RFC: ieee802154 radio api


Johann Fischer
 

Dear developers,

during the implementation of the MCR20A driver I missed some functions
of the ieee802154 radio API, which I known by linux kernel and RIOT-OS.

I do not know if a todo already exist, I have not found any, so I try to
summarize it:

The transceivers can have different capabilities (csma, autoack ...).
During the initialization of the driver, the appropriate flags should be
set by the driver. During the initializing of the subsystem, the flags
must be checked and enabled according to the desired behavior.

For example, if the hardware can automatically perform CCA before the TX
sequence (IEEE802154_HW_LBT is set), the linklayer does not have to call
the API function int (*cca)(struct device *dev);

The Flags for the Hardware Capabilities:
(The same identifiers as in Linux kernel)
- IEEE802154_HW_TX_OMIT_CKSUM
- IEEE802154_HW_LBT (listen before transmit or CCA before TX)
- IEEE802154_HW_CSMA_PARAMS
- IEEE802154_HW_FRAME_RETRIES
- IEEE802154_HW_AFILT
- IEEE802154_HW_PROMISCUOUS
- IEEE802154_HW_RX_OMIT_CKSUM
- IEEE802154_HW_RX_DROP_BAD_CKSUM

In addition, I would insert following flags:
- IEEE802154_HW_TX_AUTOACK (can transmit ACK frame after RX)
- IEEE802154_HW_RX_ACKREQ (RX ACK frame is expected after TX)
- IEEE802154_RF_TESTMODE (disabled by default, Modes: RX, CW, PRBS9 ...)
- bit field for supported channels ?
Other suggestions and comments are welcome.

What would be the appropriate place for the flags variable, Network
Interface structure?

Then the ieee802154_radio_api could then be extended by the following
operations:
...
int (*set_lbt)(struct device *dev, bool on),

int (*set_csma_params)(struct device *dev, ...),

int (*set_cca_mode)(struct device *dev, ...),

int (*set_cca_threshold)(struct device *dev, int32_t level),

int (*set_promiscuous_mode)(struct device *dev, bool on),

int (*set_frame_retries)(struct device *dev, bool on),

int (*set_hw_addr_filt)(struct device *dev, ...),

int (*set_auto_ack)(struct device *dev, ...),

int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
...

Is it ok to use the same identifiers as Linux kernel?

--
Best Regards,
Johann Fischer


Tomasz Bursztyka
 

Hi Johann,

The transceivers can have different capabilities (csma, autoack ...).
During the initialization of the driver, the appropriate flags should
be set by the driver. During the initializing of the subsystem, the
flags must be checked and enabled according to the desired behavior.
L2 behavior can avoid using any flags, at least for now (see below).
There is no reason to copy the way it's done elsewhere.
Moreover from Linux which really does not have the same constraints as
Zephyr.
Not to say about the design obviously.

That said, current L2 does lack of some features below.


For example, if the hardware can automatically perform CCA before the
TX sequence (IEEE802154_HW_LBT is set), the linklayer does not have to
call the API function int (*cca)(struct device *dev);
No. L2 has to call that, unless hw can perform part or all of the radio
strategy (usually, CSMA).
Doing cca before tx on hw side is just to ensure that it won't generate
noise uselessly. (and fails its transmission as well as
creating jitters on the network). That has to be enabled all the time,
it's cost-less.


The Flags for the Hardware Capabilities:
(The same identifiers as in Linux kernel)
- IEEE802154_HW_TX_OMIT_CKSUM
Is there any hw which is unable to do the chksum?
I made a patch on my local tree, to support software chksum on tx, and
rx. But as long as
there is no hw supporting it: I won't post it.

- IEEE802154_HW_LBT (listen before transmit or CCA before TX)
Always enable it if the hw supports it, at built time.

- IEEE802154_HW_CSMA_PARAMS
That's when the hw support csma strategy on its own. Afaik, we don't
have any yet.

- IEEE802154_HW_FRAME_RETRIES
Up to the driver to handle it. L2 does not have to care about it.

- IEEE802154_HW_AFILT
About hw filtering I guess?

- IEEE802154_HW_PROMISCUOUS
See below, at the end of this mail.

- IEEE802154_HW_RX_OMIT_CKSUM
- IEEE802154_HW_RX_DROP_BAD_CKSUM
Same as above about chksum on tx.
Is there any hw that cannot do cksum by itself and thus drop relevant
frames?
If not, then we can forget about it.


In addition, I would insert following flags:
- IEEE802154_HW_TX_AUTOACK (can transmit ACK frame after RX)
Always enable it if the hw supports it.

That said, if the hw does not support it, one will want the L2 to handle it.
It is handled currently, enabled at built time. But it does not mix at
all if we have 2 15.4 devices:
one supporting autoack, not the other.
But then again: is there any hw around that is unable to do such thing?
(At least for 15.4 >= 2012, I guess not many can do. But we are not
there yet)

- IEEE802154_HW_RX_ACKREQ (RX ACK frame is expected after TX)
Already handled. That's part of the radio strategy.

- IEEE802154_RF_TESTMODE (disabled by default, Modes: RX, CW, PRBS9 ...)
- bit field for supported channels ?
For now the hardware are only 2.4Ghz. That will come when other band
will be supported.

Other suggestions and comments are welcome.

What would be the appropriate place for the flags variable, Network
Interface structure?

Then the ieee802154_radio_api could then be extended by the following
operations:
...
int (*set_lbt)(struct device *dev, bool on),
No. If the device can do it, just enable it all the time.
I don't see any point in being able, at runtime, to play with it.


int (*set_csma_params)(struct device *dev, ...),
As long as there is no hw supporting it, no need to add that yet.


int (*set_cca_mode)(struct device *dev, ...),

int (*set_cca_threshold)(struct device *dev, int32_t level),
Not convinced to expose these 2.


int (*set_promiscuous_mode)(struct device *dev, bool on),
Ok on that one. But it should be built time set feature.


int (*set_frame_retries)(struct device *dev, bool on),
driver/hw side, at built time. No need to play with it at runtime.


int (*set_hw_addr_filt)(struct device *dev, ...),
That one we are missing yes. So it could be used once neighbors are
detected etc...
But it means improving nbr management also. It's really not the biggest
feature missing
right now.


int (*set_auto_ack)(struct device *dev, ...),
No, that's set at built time. And imo, there is no point in playing with it.
For now it should be always enabled.
(will see when newer spec will have to be implemented)


int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
What's the use case for it?

...

Is it ok to use the same identifiers as Linux kernel?
As long as it's semantically relevant, and we don't export any code from
linux. Sure.



For now I don't see much point for exposing capabilities, besides maybe
the autoack one but I want
a real hw example that does not support it first. (pushing awai the
newer specs for now).

Point is, all drivers are exposing the same API. For instance, if it
does not support promiscuous mode, then
it sets the relevant api function pointer to NULL. If the user asks "set
promiscuous" (let's say through the 15.4 shell),
l2 verify that and return -ENOTSUPP accordingly. No need of any flag here.
Same for hw filtering etc etc... There is no need of checking any flag
at anytime.

Br,

Tomasz


Johann Fischer
 

Hi Tomasz,

For example, if the hardware can automatically perform CCA before the
TX sequence (IEEE802154_HW_LBT is set), the linklayer does not have to
call the API function int (*cca)(struct device *dev);
No. L2 has to call that, unless hw can perform part or all of the radio
strategy (usually, CSMA).
Doing cca before tx on hw side is just to ensure that it won't generate
noise uselessly. (and fails its transmission as well as
creating jitters on the network). That has to be enabled all the time,
it's cost-less.
Ok, then I will implement the cca function, which then execute a
standalone CCA.


The Flags for the Hardware Capabilities:
(The same identifiers as in Linux kernel)
- IEEE802154_HW_TX_OMIT_CKSUM
Is there any hw which is unable to do the chksum?
I made a patch on my local tree, to support software chksum on tx, and
rx. But as long as
there is no hw supporting it: I won't post it.
ok I agree. What bothers me is the IEEE802154_MTU of 127, the frame
length is 127 octets (including FCS field), should it not be 125?


- IEEE802154_HW_LBT (listen before transmit or CCA before TX)
Always enable it if the hw supports it, at built time.
> ...

ok



int (*set_cca_mode)(struct device *dev, ...),

int (*set_cca_threshold)(struct device *dev, int32_t level),
Not convinced to expose these 2.
It makes a difference what CCA mode the HW uses. It should be prescribed
somewhere or the L2 sets it to runtime.
For the threshold, the default value of the PHY may be ok.


int (*set_promiscuous_mode)(struct device *dev, bool on),
Ok on that one. But it should be built time set feature.
You mean the timestamps should be inserted by the driver?


int (*set_hw_addr_filt)(struct device *dev, ...),
That one we are missing yes. So it could be used once neighbors are
detected etc...
But it means improving nbr management also. It's really not the biggest
feature missing
right now.
ok


int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
What's the use case for it?
It would be turned off by default (return -ENOTSUPP). It is useful for
commissioning the hardware and is required for the test during the CE or
FCC certification. Of course, there are tools from the manufacturers for
it, but they are usually not so nice and they are almost always bound to
an OS, which I do not want to use. Natively implemented, it is also
useful in driver development, e.g. to check whether PLL was set
correctly after the channel was switched or to test CCA :-). Mostly only
four modes are useful: Idle, continues RX, carrier wave, PRBS9. It must
be clearly marked that it is only for testing.


For now I don't see much point for exposing capabilities, besides maybe
the autoack one but I want
a real hw example that does not support it first. (pushing awai the
newer specs for now).

Point is, all drivers are exposing the same API. For instance, if it
does not support promiscuous mode, then
it sets the relevant api function pointer to NULL. If the user asks "set
promiscuous" (let's say through the 15.4 shell),
l2 verify that and return -ENOTSUPP accordingly. No need of any flag here.
Same for hw filtering etc etc... There is no need of checking any flag
at anytime.
ok, got it :-)

Br,

Tomasz
--
Best Regards,
Johann Fischer


Tomasz Bursztyka
 

Hi Johann,


The Flags for the Hardware Capabilities:
(The same identifiers as in Linux kernel)
- IEEE802154_HW_TX_OMIT_CKSUM
Is there any hw which is unable to do the chksum?
I made a patch on my local tree, to support software chksum on tx, and
rx. But as long as
there is no hw supporting it: I won't post it.
ok I agree. What bothers me is the IEEE802154_MTU of 127, the frame
length is 127 octets (including FCS field), should it not be 125?
It's a left-over. Just keep it that way. Drivers are setting the MTU to
125 mostly due to net buf. (it's possible to reserve header part, not
tail part, and that was generating issuse)
Up to the driver to not write the fcs into buffer's data. (L2 does not
care about it anyway).
And anyway driver don't push bigger frames than what they are supposed
to, so the check in frame is really superfluous.




int (*set_cca_mode)(struct device *dev, ...),

int (*set_cca_threshold)(struct device *dev, int32_t level),
Not convinced to expose these 2.
It makes a difference what CCA mode the HW uses. It should be
prescribed somewhere or the L2 sets it to runtime.
For the threshold, the default value of the PHY may be ok.


int (*set_promiscuous_mode)(struct device *dev, bool on),
Ok on that one. But it should be built time set feature.
You mean the timestamps should be inserted by the driver?
No I mean the promiscuous feature should be Kconfig set, and disabled by
default.


int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
What's the use case for it?
It would be turned off by default (return -ENOTSUPP). It is useful for
commissioning the hardware and is required for the test during the CE
or FCC certification. Of course, there are tools from the
manufacturers for it, but they are usually not so nice and they are
almost always bound to an OS, which I do not want to use. Natively
implemented, it is also useful in driver development, e.g. to check
whether PLL was set correctly after the channel was switched or to
test CCA :-). Mostly only four modes are useful: Idle, continues RX,
carrier wave, PRBS9. It must be clearly marked that it is only for
testing.
Isn't this kind of test made out of any 15.4 network? (i.e.: does it
require L2? I don't think so).


Br,

Tomasz


Oliver Hahm <oliver.hahm@...>
 

Hi Tomasz!

On Wed, Jan 18, 2017 at 09:57:15AM +0100, Tomasz Bursztyka wrote:
For example, if the hardware can automatically perform CCA before the TX
sequence (IEEE802154_HW_LBT is set), the linklayer does not have to call
the API function int (*cca)(struct device *dev);
No. L2 has to call that, unless hw can perform part or all of the radio
strategy (usually, CSMA).
Doing cca before tx on hw side is just to ensure that it won't generate
noise uselessly. (and fails its transmission as well as
creating jitters on the network). That has to be enabled all the time, it's
cost-less.
<snip>
- IEEE802154_HW_LBT (listen before transmit or CCA before TX)
Always enable it if the hw supports it, at built time.
Not sure, I understand you correctly here, but some transceivers (e.g. the
at86rf2xx) does not allow you to perform manual CCA if automatic CCA is
enabled.

- IEEE802154_HW_FRAME_RETRIES
Up to the driver to handle it. L2 does not have to care about it.
What if the MAC needs full control over L2 retransmissions (e.g. in a TDMA
MAC).

In addition, I would insert following flags:
- IEEE802154_HW_TX_AUTOACK (can transmit ACK frame after RX)
Always enable it if the hw supports it.
Same as above. For some MAC protocols (e.g. IEEE 802.15.4 TSCH mode) this is
not a viable solution.

Or is your point only about setting these capabilities at runtime? Is it still
possible to disable these flags at compile time?

Cheers,
Oleg


Tomasz Bursztyka
 

Hi Oliver,

On Wed, Jan 18, 2017 at 09:57:15AM +0100, Tomasz Bursztyka wrote:
For example, if the hardware can automatically perform CCA before the TX
sequence (IEEE802154_HW_LBT is set), the linklayer does not have to call
the API function int (*cca)(struct device *dev);
No. L2 has to call that, unless hw can perform part or all of the radio
strategy (usually, CSMA).
Doing cca before tx on hw side is just to ensure that it won't generate
noise uselessly. (and fails its transmission as well as
creating jitters on the network). That has to be enabled all the time, it's
cost-less.
<snip>
- IEEE802154_HW_LBT (listen before transmit or CCA before TX)
Always enable it if the hw supports it, at built time.
Not sure, I understand you correctly here, but some transceivers (e.g. the
at86rf2xx) does not allow you to perform manual CCA if automatic CCA is
enabled.
Good to know. Does it behave like that because it can do some/all of the
CSMA job directly?
For now I'd say disable auto-CCA in driver by default, then.

Basically manual CCA is meant for the fully soft-CSMA radio strategy,
as it is right now.
If only auto-cca does not mess up with the manual one, then keep it enabled.

But soon, we'll have to figure out a way to hand-over CSMA parts to
relevant hw that can
do it.


- IEEE802154_HW_FRAME_RETRIES
Up to the driver to handle it. L2 does not have to care about it.
What if the MAC needs full control over L2 retransmissions (e.g. in a TDMA
MAC).
Hum, MAC and L2 in our case is the same. What I call L2 here is
ieee802.15.4 soft-MAC L2 stack.
See subsys/net/ip/l2/ieee802154/

Anyway, TDMA is not part of IEEE 802.15.4 <= 2011, so we can put it aside.


In addition, I would insert following flags:
- IEEE802154_HW_TX_AUTOACK (can transmit ACK frame after RX)
Always enable it if the hw supports it.
Same as above. For some MAC protocols (e.g. IEEE 802.15.4 TSCH mode) this is
not a viable solution.
TSCH is for IEEE 802.15.4 >= 2012. So at this point we can put it aside.

Or is your point only about setting these capabilities at runtime? Is it still
possible to disable these flags at compile time?
We had autoack, and crc and all being disabled at compile time for a
while. But at this stage
it was just useless, so it got removed.


Br,

Tomasz


Johann Fischer
 

Hi Tomasz,

int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
What's the use case for it?
It would be turned off by default (return -ENOTSUPP). It is useful for
commissioning the hardware and is required for the test during the CE
or FCC certification. Of course, there are tools from the
manufacturers for it, but they are usually not so nice and they are
almost always bound to an OS, which I do not want to use. Natively
implemented, it is also useful in driver development, e.g. to check
whether PLL was set correctly after the channel was switched or to
test CCA :-). Mostly only four modes are useful: Idle, continues RX,
carrier wave, PRBS9. It must be clearly marked that it is only for
testing.
Isn't this kind of test made out of any 15.4 network? (i.e.: does it
require L2? I don't think so).
No, it just for the PHY (RF Testing, simular to BT DTM, e.g.
DTM_PKT_PRBS9 or CARRIER_TEST ...). It would also needs a shell command.

--
Best Regards,
Johann Fischer


Tomasz Bursztyka
 

Hi Johann,


int (*set_rf_test_mode)(struct device *dev, uint32_t mode),
What's the use case for it?
It would be turned off by default (return -ENOTSUPP). It is useful for
commissioning the hardware and is required for the test during the CE
or FCC certification. Of course, there are tools from the
manufacturers for it, but they are usually not so nice and they are
almost always bound to an OS, which I do not want to use. Natively
implemented, it is also useful in driver development, e.g. to check
whether PLL was set correctly after the channel was switched or to
test CCA :-). Mostly only four modes are useful: Idle, continues RX,
carrier wave, PRBS9. It must be clearly marked that it is only for
testing.
Isn't this kind of test made out of any 15.4 network? (i.e.: does it
require L2? I don't think so).
No, it just for the PHY (RF Testing, simular to BT DTM, e.g.
DTM_PKT_PRBS9 or CARRIER_TEST ...). It would also needs a shell command.
Ok sound like it could use the actual RAW use of the driver.

So you would need 2 function:

- one returning the supported modes

- one running the test with requested mode as you proposed.

this would be exposed only on Kconfig option condition.


Br

Tomasz