Skip to content

RFC: Move PHY/MAC layer out of drivers #11483

@jia200x

Description

@jia200x

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_t so common operations (TX, RX, CCA, Energy Detection) are transceiver agnostic.
  • Define a minimal rf_ops interface between netdev_ieee802154_t and 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_t interface 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

Metadata

Metadata

Labels

Area: networkArea: NetworkingDiscussion: RFCThe issue/PR is used as a discussion starting point about the item of the issue/PRProcess: API changeIntegration Process: PR contains or issue proposes an API change. Should be handled with care.State: staleState: The issue / PR has no activity for >185 daysType: enhancementThe issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions