1.. _net_l2_interface: 2 3L2 Layer Management 4################### 5 6.. contents:: 7 :local: 8 :depth: 2 9 10Overview 11******** 12 13The L2 stack is designed to hide the whole networking link-layer part 14and the related device drivers from the upper network stack. This is made 15through a :c:struct:`net_if` declared in 16:zephyr_file:`include/zephyr/net/net_if.h`. 17 18The upper layers are unaware of implementation details beyond the net_if 19object and the generic API provided by the L2 layer in 20:zephyr_file:`include/zephyr/net/net_l2.h` as :c:struct:`net_l2`. 21 22Only the L2 layer can talk to the device driver, linked to the net_if 23object. The L2 layer dictates the API provided by the device driver, 24specific for that device, and optimized for working together. 25 26Currently, there are L2 layers for :ref:`Ethernet <ethernet_interface>`, 27:ref:`IEEE 802.15.4 Soft-MAC <ieee802154_interface>`, :ref:`CANBUS <can_api>`, 28:ref:`OpenThread <thread_protocol_interface>`, Wi-Fi, and a dummy layer example 29that can be used as a template for writing a new one. 30 31L2 layer API 32************ 33 34In order to create an L2 layer, or a driver for a specific L2 layer, 35one needs to understand how the L3 layer interacts with it and 36how the L2 layer is supposed to behave. 37See also :ref:`network stack architecture <network_stack_architecture>` for 38more details. The generic L2 API has these functions: 39 40- ``recv()``: All device drivers, once they receive a packet which they put 41 into a :c:struct:`net_pkt`, will push this buffer to the network 42 stack via :c:func:`net_recv_data`. At this point, the network 43 stack does not know what to do with it. Instead, it passes the 44 buffer along to the L2 stack's ``recv()`` function for handling. 45 The L2 stack does what it needs to do with the packet, for example, parsing 46 the link layer header, or handling link-layer only packets. The ``recv()`` 47 function will return ``NET_DROP`` in case of an erroneous packet, 48 ``NET_OK`` if the packet was fully consumed by the L2, or ``NET_CONTINUE`` 49 if the network stack should then handle it. 50 51- ``send()``: Similar to receive function, the network stack will call this 52 function to actually send a network packet. All relevant link-layer content 53 will be generated and added by this function. 54 The ``send()`` function returns the number of bytes sent, or a negative 55 error code if there was a failure sending the network packet. 56 57- ``enable()``: This function is used to enable/disable traffic over a network 58 interface. The function returns ``<0`` if error and ``>=0`` if no error. 59 60- ``get_flags()``: This function will return the capabilities of an L2 driver, 61 for example whether the L2 supports multicast or promiscuous mode. 62 63Network Device drivers 64********************** 65 66Network device drivers fully follows Zephyr device driver model as a 67basis. Please refer to :ref:`device_model_api`. 68 69There are, however, two differences: 70 71- The driver_api pointer must point to a valid :c:struct:`net_if_api` 72 pointer. 73 74- The network device driver must use :c:macro:`NET_DEVICE_INIT_INSTANCE()` 75 or :c:macro:`ETH_NET_DEVICE_INIT()` for Ethernet devices. These 76 macros will call the :c:macro:`DEVICE_DEFINE()` macro, and also 77 instantiate a unique :c:struct:`net_if` related to the created 78 device driver instance. 79 80Implementing a network device driver depends on the L2 stack it 81belongs to: :ref:`Ethernet <ethernet_interface>`, 82:ref:`IEEE 802.15.4 <ieee802154_interface>`, etc. 83In the next section, we will describe how a device driver should behave when 84receiving or sending a network packet. The rest is hardware dependent 85and is not detailed here. 86 87Ethernet device driver 88====================== 89 90On reception, it is up to the device driver to fill-in the network packet with 91as many data buffers as required. The network packet itself is a 92:c:struct:`net_pkt` and should be allocated through 93:c:func:`net_pkt_rx_alloc_with_buffer`. Then all data buffers will be 94automatically allocated and filled by :c:func:`net_pkt_write`. 95 96After all the network data has been received, the device driver needs to 97call :c:func:`net_recv_data`. If that call fails, it will be up to the 98device driver to unreference the buffer via :c:func:`net_pkt_unref`. 99 100On sending, the device driver send function will be called, and it is up to 101the device driver to send the network packet all at once, with all the buffers. 102 103Each Ethernet device driver will need, in the end, to call 104``ETH_NET_DEVICE_INIT()`` like this: 105 106.. code-block:: c 107 108 ETH_NET_DEVICE_INIT(..., CONFIG_ETH_INIT_PRIORITY, 109 &the_valid_net_if_api_instance, 1500); 110 111IEEE 802.15.4 device driver 112=========================== 113 114Device drivers for IEEE 802.15.4 L2 work basically the same as for 115Ethernet. What has been described above, especially for ``recv()``, applies 116here as well. There are two specific differences however: 117 118- It requires a dedicated device driver API: :c:struct:`ieee802154_radio_api`, 119 which overloads :c:struct:`net_if_api`. This is because 802.15.4 L2 needs more from the device 120 driver than just ``send()`` and ``recv()`` functions. This dedicated API is 121 declared in :zephyr_file:`include/zephyr/net/ieee802154_radio.h`. Each and every 122 IEEE 802.15.4 device driver must provide a valid pointer on such 123 relevantly filled-in API structure. 124 125- Sending a packet is slightly different than in Ethernet. Most IEEE 802.15.4 126 PHYs support relatively small frames only, 127 bytes all inclusive: frame 127 header, payload and frame checksum. Buffers to be sent over the radio will 128 often not fit this frame size limitation, e.g. a buffer containing an IPv6 129 packet will often have to be split into several fragments and IP6 packet headers 130 and fragments need to be compressed using a protocol like 6LoWPAN before being 131 passed on to the radio driver. Additionally the IEEE 802.15.4 standard defines 132 medium access (e.g. CSMA/CA), frame retransmission, encryption and other pre-processing 133 procedures (e.g. addition of information elements) that individual 134 radio drivers should not have to care about. This is why the 135 :c:struct:`ieee802154_radio_api` requires a tx function pointer which differs 136 from the :c:struct:`net_if_api` send function pointer. Zephyr's native 137 IEEE 802.15.4 L2 implementation provides a generic :c:func:`ieee802154_send` 138 instead, meant to be given as :c:type:`net_if` send function. The implementation 139 of :c:func:`ieee802154_send` takes care of IEEE 802.15.4 standard packet 140 preparation procedures, splitting the packet into possibly compressed, 141 encrypted and otherwise pre-processed fragment buffers, sending one buffer 142 at a time through :c:struct:`ieee802154_radio_api` tx function and unreferencing 143 the network packet only when the transmission as a whole was either successful 144 or failed. 145 146Interaction between IEEE 802.15.4 radio device drivers and L2 is bidirectional: 147 148- L2 -> L1: Methods as :c:func:`ieee802154_send` and several IEEE 802.15.4 net 149 management calls will call into the driver, e.g. to send a packet over the 150 radio link or re-configure the driver at runtime. These incoming calls will 151 all be handled by the methods in the :c:struct:`ieee802154_radio_api`. 152 153- L1 -> L2: There are several situations in which the driver needs to initiate 154 calls into the L2/MAC layer. Zephyr's IEEE 802.15.4 L1 -> L2 adaptation API 155 employs an "inversion-of-control" pattern in such cases avoids duplication of 156 complex logic across independent driver implementations and ensures 157 implementation agnostic loose coupling and clean separation of concerns between 158 MAC (L2) and PHY (L1) whenever reverse information transfer or close co-operation 159 between hardware and L2 is required. During driver initialization, for example, 160 the driver calls :c:func:`ieee802154_init` to pass the interface's MAC address 161 as well as other hardware-related configuration to L2. Similarly, drivers may 162 indicate performance or timing critical radio events to L2 that require close 163 integration with the hardware (e.g. :c:func:`ieee802154_handle_ack`). Calls 164 from L1 into L2 are not implemented as methods in :c:struct:`ieee802154_radio_api` 165 but are standalone functions declared and documented as such in 166 :zephyr_file:`include/zephyr/net/ieee802154_radio.h`. The API documentation will 167 clearly state which functions must be implemented by all L2 stacks as part 168 of the L1 -> L2 "inversion-of-control" adaptation API. 169 170Note: Standalone functions in :zephyr_file:`include/zephyr/net/ieee802154_radio.h` 171that are not explicitly documented as callbacks are considered to be helper functions 172within the PHY (L1) layer implemented independently of any specific L2 stack, see for 173example :c:func:`ieee802154_is_ar_flag_set`. 174 175As all net interfaces, IEEE 802.15.4 device driver implementations will have to call 176``NET_DEVICE_INIT_INSTANCE()`` in the end: 177 178.. code-block:: c 179 180 NET_DEVICE_INIT_INSTANCE(..., 181 the_device_init_prio, 182 &the_valid_ieee802154_radio_api_instance, 183 IEEE802154_L2, 184 NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125); 185 186API Reference 187************* 188 189.. doxygengroup:: net_l2 190