-
Notifications
You must be signed in to change notification settings - Fork 2.1k
RFC: Move PHY/MAC layer out of drivers #11483
Description
Description
Towards adding more features of IEEE802.15.4 and variants (TSCH, etc), having a well defined MAC layer, reduce code duplication and increase maintainability, I've been working in a series of changes like #11473 and the following proposal.
Most of the PHY and MAC logic is currently implemented in the drivers (ACK management, sending packets, etc). This leads to code duplication, radios that are not easy to maintain and it's hard to integrate full MAC features on existing radios (and it's hard to add new radios)
We already have some common PHY code in netdev_xxx_t descriptors (e.g netdev_ieee802154_t), but there are a lot of stuff that can be factorized out from the drivers.
In the case of IEEE802.15.4, the proposal is:
- Implement PHY layer logic using
netdev_ieee802154_tso common operations (TX, RX, CCA, Energy Detection) are transceiver agnostic. - Define a minimal
rf_opsinterface betweennetdev_ieee802154_tand the transceiver with low level operations (prepare packet, trigger send, maybe flush fifo, etc) - Implement MAC layers on top using well known interfaces (for IEEE802.15.4, the MCPS-SAP and MLME-SAP as described in RFC: Implement IEEE802 MAC SAP interface (MLME/MCPS) #11324 )
- A
netdev_ieee802154_ops_tinterface with specific PHY ops might be needed (cca, prepare frame, transmit, etc) in order to accomplish most MAC layers features.
For transceiver implementing PHY and MAC components use radio caps (#11473) to decide whether a feature is handled by the layer or the tranceiver.
Here is a picture about how can it look like for IEEE802.15.4:
I did a quick proof of concept for the PHY layer with the AT86RF231 radio and this is how generic prepare, transmit and send functions look like:
/**
* Implementation of netdev_ieee802154_ops_t members
*/
/* PSDU: PHY Service Data Unit. Equivalent to MPDU (Mac Protocol Data Unit), a.k.a full MAC header */
int netdev_ieee802154_prepare(netdev_ieee802154_t *dev, const iolist_t *psdu)
{
dev->rf_ops->prepare(dev);
if(dev->caps & NETDEV_IEEE802154_CAPS_TX_CHECKSUM)
uint8_t psdu_len = iolist_size(psdu) + IEEE802154_FCS_LEN;
if (psdu_len > IEEE802154_FRAME_LEN_MAX) {
DEBUG("[at86rf2xx] error: packet too large (%u byte) to be send\n",
(unsigned) psdu_len);
return -EOVERFLOW;
}
/* Write PHDR */
dev->rf_ops->tx_load(dev, &psdu_len, 1);
/* load packet data into FIFO */
for (const iolist_t *iol = psdu; iol; iol = iol->iol_next) {
/* current packet data + FCS too long */
if (iol->iol_len) {
dev->rx_ops->tx_load(dev, iol->iol_base, iol->iol_len);
}
}
/* return the number of bytes that were actually loaded into the frame
* buffer/send out */
return (int)psdu_len;
}
void netdev_ieee802154_transmit(netdev_ieee802154_t *dev)
{
/* Transmit PHY Protocol Data Unit (PPDU) */
dev->rf_ops->tx_exec(dev);
}
int netdev_ieee802154_send(netdev_ieee802154_t *dev, const iolist_t *psdu)
{
if(res = netdev_ieee802154_prepare(dev, psdu)) {
netdev_ieee802154_transmit(dev);
}
return res;
}Any thoughts?
Useful links
- IPP Hurray: They used this abstraction for their IEEE802.15.4 stack using TinyOS
- Linux Kernel: Check their reasons on why they moved the PHY layer out of the drivers
