Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

at86rf2xx: fix option setting #5227

Merged
merged 2 commits into from
Apr 20, 2016
Merged

Conversation

miri64
Copy link
Member

@miri64 miri64 commented Apr 1, 2016

@miri64 miri64 added Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Apr 1, 2016
@miri64 miri64 added this to the Release 2016.04 milestone Apr 1, 2016
@haukepetersen
Copy link
Contributor

seems to me like you broke the code: if an option is set successfully, the res var is still set to -ENOTSUP...

@miri64
Copy link
Member Author

miri64 commented Apr 1, 2016

@miri64
Copy link
Member Author

miri64 commented Apr 1, 2016

Ah wait, for some instances you are right.

@miri64
Copy link
Member Author

miri64 commented Apr 1, 2016

Okay, now I replaced the instances where the values are just invalid for the scope of the device with -EINVAL to prevent jumping into the netdev2_ieee802154_set() function. It seems to me the more correct error code anyway.

@haukepetersen
Copy link
Contributor

looks better :-)

@miri64
Copy link
Member Author

miri64 commented Apr 1, 2016

Rebased to current master.

@@ -433,7 +433,7 @@ static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len)
uint8_t chan = ((uint8_t *)val)[0];
if (chan < AT86RF2XX_MIN_CHANNEL ||
chan > AT86RF2XX_MAX_CHANNEL) {
res = -ENOTSUP;
res = -EINVAL;
break;
}
at86rf2xx_set_chan(dev, chan);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe I am confused, but something still seems off: initially, res is set to -ENOTSUP. If the given channel is invalid, we set it to -EINVAL, so far so good. But if the channel is valid, we do not change res, so when we get to the break below, res is still set to -ENOTSUP. This will trigger the call to netdev2_ieee802154_set(...) at the end of the function. Is this intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know GitHub is blending it out, but it is commented on in the line below. This PR does not change this behavior since the chan field in the netdev2_ieee802154_t struct still needs to be set.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think res should be getting set here on a valid channel change, since netdev2_ieee802154_set() doesn't handle NETOPT_CHANNEL...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@aeneby
Copy link
Member

aeneby commented Apr 1, 2016

Could I also suggest that, for this PR, we remove the existing code in the at86rf2xx driver that should be getting done in netdev2_ieee802154_set()? I'm referring to lines like

dev->netdev.long_addr[i] = (uint8_t)(addr >> (i * 8));
but there's probably more.

@miri64
Copy link
Member Author

miri64 commented Apr 1, 2016

Could I also suggest that, for this PR, we remove the existing code in the at86rf2xx driver that should be getting done in netdev2_ieee802154_set()?

I'm all for it, but this is touching legacy code by @haukepetersen, that was intended to keep the driver independent from netdev. Are you alright with this change, @haukepetersen?

@aeneby
Copy link
Member

aeneby commented Apr 9, 2016

Also, I thinkNETOPT_AUTOACK is being handled incorrectly by netdev2_ieee802154_{g,s}et(). It's getting/setting the NETDEV2_IEEE802154_ACK_REQ flag, which as I understand it is not the same thing as AUTOACK.

@aeneby
Copy link
Member

aeneby commented Apr 9, 2016

The documentation here needs updating too, given the previous commits:

* The setting of netdev2_ieee802154_t::chan is omitted since the legality of

@aeneby
Copy link
Member

aeneby commented Apr 10, 2016

Also, I think NETOPT_AUTOACK is being handled incorrectly by netdev2_ieee802154_{g,s}et().

#5287

@aeneby
Copy link
Member

aeneby commented Apr 12, 2016

@haukepetersen what do you think about the PR in its current state?

case NETOPT_CHANNEL:
/* validity needs to be checked by device, since sub-GHz and 2.4 GHz
* band radios have different legal values */
if (len > sizeof(dev->chan)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use assert here instead...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the file doesn't use assert either yet. Let's do this in a seperate follow-up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #5327

@haukepetersen
Copy link
Contributor

in general I am ok with this, though I think there is still a bug in the behavior: the the set function, netdev2_ieee802154_set() should always be called, even if the option was already addressed. If this is not the case, we will change e.g. the address in the device, but we will not update the netdev2_ieee802154 state struct accordingly...

@aeneby
Copy link
Member

aeneby commented Apr 13, 2016

But there are some options for which calling netdev2_ieee802154_set() would be redundant, since they can only be handled by the driver itself. NETOPT_STATE, for example, which is presumably why this option is not included as a case. Calling netdev2_ieee802154_set() with NETOPT_STATE will return -ENOTSUP all the way back up the call chain.

@haukepetersen
Copy link
Contributor

exactly, and that is the problem of the current code. Just have a look at my WIP PR for the CC2420 driver https://github.com/RIOT-OS/RIOT/pull/5314/files#diff-9557a9fbe33e77bb84867da9d97c67c9R808. This way both are called, but the -ENOTSUP is only returned if none them know what to do with the data..

@aeneby
Copy link
Member

aeneby commented Apr 14, 2016

But that approach also has problems - what if an application tries to set an invalid channel, for example? Since only the driver can know if the requested channel is valid, it will be set to an invalid value in the netdev2_ieee802154 struct by netdev2_ieee802154_set(), and then cc2420_set_chan() will presumably return an error code, leaving things in an inconsistent state.

Since some options cannot be dealt with at all by netdev2_ieee802154_set() (NETOPT_STATE, NETOPT_AUTOACK, etc), why do you feel that "the set function, netdev2_ieee802154_set() should always be called, even if the option was already addressed"?

@aeneby
Copy link
Member

aeneby commented Apr 14, 2016

If I can be selfish for a second :) I'm really only interested in the changes to netdev2_ieee802154.c here since I can't test #5291 properly without the NETOPT_CHANNEL support. @authmillenon, how would you feel about separating this code out into a new PR while the at86rf2xx-specific stuff is discussed? The changes are orthogonal, and it would also keep this PR specific to the at86rf2xx driver.

@haukepetersen
Copy link
Contributor

Ok, I see your needs. I didn't really want to go into the deeper architectural discussion here (as the hole concept is currently flawed as is). So for now, I would be fine with taking this PR as is, if we fix it, so that certain params (as address, pan id) are also passed to the netdev2_ieee.. layer

@aeneby
Copy link
Member

aeneby commented Apr 15, 2016

if we fix it, so that certain params (as address, pan id) are also passed to the netdev2_ieee.. layer

They already are...

@miri64
Copy link
Member Author

miri64 commented Apr 17, 2016

@authmillenon, how would you feel about separating this code out into a new PR while the at86rf2xx-specific stuff is discussed?

Since at86rf2xx is using the netdev2_ieee802154, not changing the at86rf2xx code untouched in this PR would leave it faulty in master. So I'm not feeling very positive about this idea.

@haukepetersen
Copy link
Contributor

ok, never mind, the issue I was referring to does not exist, so I am ok with this PR.

@haukepetersen
Copy link
Contributor

something is off when setting a channel:

2016-04-20 16:05:20,451 - INFO # > ifconfig 7 set chan 22
2016-04-20 16:05:20,452 - INFO # error: unable to set channel

@haukepetersen
Copy link
Contributor

but the channel is actually set, so the return value is off?

@miri64
Copy link
Member Author

miri64 commented Apr 20, 2016

Fixed. Please retest.

@miri64 miri64 added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Apr 20, 2016
@haukepetersen
Copy link
Contributor

that did the job. Looks good now -> ACK once squashed and Murock gives a green

@miri64
Copy link
Member Author

miri64 commented Apr 20, 2016

Done

@miri64 miri64 added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Apr 20, 2016
@miri64 miri64 merged commit cedf7d8 into RIOT-OS:master Apr 20, 2016
@miri64 miri64 deleted the at86rf2xx/fix/set branch April 20, 2016 15:33
@aeneby
Copy link
Member

aeneby commented Apr 20, 2016

@authmillenon @haukepetersen there is no way this has been tested properly. You declare chan as uint16_t and then immediately assert "chan <= UINT8_MAX" when setting the channel.

@miri64
Copy link
Member Author

miri64 commented Apr 20, 2016

Yes, we tested it properly: netopt expects channel of type uint16_t while the channel field in IEEE 802.15.4 is uint8_t. That's why the assert is there.

@miri64
Copy link
Member Author

miri64 commented Apr 20, 2016

The driver has to make sure the channel is in the correct range, as the comment states.

@aeneby
Copy link
Member

aeneby commented Apr 20, 2016

But then if netdev2_ieee802154_set is called with NETOPT_CHANNEL and an 8-bit value, the cast to uint16_t will read in garbage and the assertion will likely fail. Why aren't we checking len in that case?

@aeneby
Copy link
Member

aeneby commented Apr 20, 2016

Or just declaring chan as uint8_t?

@miri64
Copy link
Member Author

miri64 commented Apr 20, 2016

But then if netdev2_ieee802154_set is called with NETOPT_CHANNEL and an 8-bit value, the cast to uint16_t will read in garbage and the assertion will likely fail. Why aren't we checking len in that case?

Under the given test conditions NETOPT_CHANNEL is not given as an 8-bit value (since it is documented that it should be a 16-bit value). True, the check should probably better be != but I fixed that in #5327 already.

Or just declaring chan as uint8_t?

IEEE 802.15.4 isn't the only radio standard we support and apparently (pure conjecture, given that I did not define the type for that NETOPT) there are radio standards with channel value > 255.

@aeneby
Copy link
Member

aeneby commented Apr 20, 2016

OK - I understand. It just seemed weird to require a 16-bit value, only to throw 8 bits of it away, especially on memory-constrained devices. Perhaps we could check if NETOPT_CHANNEL really does need to be 16-bit.

@miri64
Copy link
Member Author

miri64 commented Apr 21, 2016

Since this 16-bit value is typically allocated on the stack I would argue that keeping the variety of types in NETOPT at a small level (i. e. trying to use the most common one) might even be beneficial for memory constraints, since you only have to allocate a small number of variables to handle multiple options (since you can reuse them then).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants