| .. _l2_and_drivers: | 
 |  | 
 | L2 Stack and Drivers | 
 | #################### | 
 |  | 
 | The L2 stack is designed to hide the whole networking link-layer part | 
 | and the related device drivers from the higher IP stack. This is made | 
 | through a unique object known as the "network interface object": | 
 | :c:type:`struct net_if` declared in :file:`include/net/net_if.h`. | 
 |  | 
 | The IP layer is unaware of implementation details beyond the net_if | 
 | object and the generic API provided by the L2 layer in | 
 | :file:`include/net/net_l2.h` as :c:type:`struct net_l2`. | 
 |  | 
 | Only the L2 layer can talk to the device driver, linked to the net_if | 
 | object. The L2 layer dictates the API provided by the device driver, | 
 | specific for that device, and optimized for working together. | 
 |  | 
 | Currently, there are L2 layers for Ethernet, IEEE 802.15.4 Soft-MAC, | 
 | Bluetooth IPSP, and a dummy one, which is a generic layer example that | 
 | can be used as a template for writing a new one. | 
 |  | 
 | L2 layer API | 
 | ************ | 
 |  | 
 | In order to create an L2 layer, or even a driver for a specific L2 | 
 | layer, one needs to understand how the IP layer interacts with it and | 
 | how the L2 layer is supposed to behave. The generic L2 API has 3 | 
 | functions: | 
 |  | 
 | - recv: All device drivers, once they receive a packet which they put | 
 |   into a :c:type:`struct net_pkt`, will push this buffer to the IP | 
 |   core stack via :c:func:`net_recv_data()`. At this point, the IP core | 
 |   stack does not know what to do with it. Instead, it passes the | 
 |   buffer along to the L2 stack's recv() function for handling. The L2 | 
 |   stack does what it needs to do with the packet, for example, parsing | 
 |   the link layer header, or handling link-layer only packets. The | 
 |   recv() function will return NET_DROP in case of an erroneous packet, | 
 |   NET_OK if the packet was fully consumed by the L2, or NET_CONTINUE | 
 |   if the IP stack should then handle it as an IP packet. | 
 |  | 
 | - reserve: Prior to creating any network buffer content, the Zephyr | 
 |   core stack needs to know how much dedicated buffer space is needed | 
 |   for the L2 layer (for example, space for the link layer header). This | 
 |   reserve function returns the number of bytes needed. | 
 |  | 
 | - send: Similar to recv, the IP core stack will call this function to | 
 |   actually send a packet. All relevant link-layer content will be | 
 |   generated and added by this function.  As for recv, send returns a | 
 |   verdict and can decide to drop the packet via NET_DROP if something | 
 |   wrong happened, or will return NET_OK. | 
 |  | 
 | Network Device drivers | 
 | ********************** | 
 |  | 
 | Network device drivers fully follows Zephyr device driver model as a | 
 | basis. Please refer to :ref:`device_drivers`. | 
 |  | 
 | There are, however, two differences: | 
 |  | 
 | - the driver_api pointer must point to a valid :c:type:`struct | 
 |   net_if_api` pointer. | 
 |  | 
 | - The network device driver must use ``NET_DEVICE_INIT_INSTANCE()``. This | 
 |   macro will call the DEVICE_AND_API_INIT() macro, and also | 
 |   instantiate a unique :c:type:`struct net_if` related to the created | 
 |   device driver instance. | 
 |  | 
 | Implementing a network device driver depends on the L2 stack it | 
 | belongs to: Ethernet, IEEE 802.15.4, etc. In the next section, we will | 
 | describe how a device driver should behave when receiving or sending a | 
 | packet. The rest is really hardware dependent and thus does not need | 
 | to be detailed here. | 
 |  | 
 | Ethernet device driver | 
 | ====================== | 
 |  | 
 | On reception, it is up to the device driver to fill-in the buffer with | 
 | as many data fragments as required. The buffer itself is a | 
 | :c:type:`struct net_pkt` and should be allocated through | 
 | :c:func:`net_pkt_get_reserve_rx(0)`. Then all fragments will be | 
 | allocated through :c:func:`net_pkt_get_reserve_data(0)`. Of course | 
 | the amount of required fragments depends on the size of the received | 
 | packet and on the size of a fragment, which is given by | 
 | :option:`CONFIG_NET_BUF_DATA_SIZE`. | 
 |  | 
 | Note that it is not up to the device driver to decide on the | 
 | link-layer space to be reserved in the buffer. Hence the 0 given as | 
 | parameter here. The Ethernet L2 layer will update such information | 
 | once the packet's Ethernet header has been successfully parsed. | 
 |  | 
 | In case :c:func:`net_recv_data()` call fails, it will be up to the | 
 | device driver to unreference the buffer via | 
 | :c:func:`net_pkt_unref()`. | 
 |  | 
 | On sending, it is up to the device driver to send the buffer all at | 
 | once, with all the fragments. | 
 |  | 
 | In case of a fully successful packet transmission only, the device | 
 | driver must unreference the buffer via :c:func:`net_pkt_unref()`. | 
 |  | 
 | Each Ethernet device driver will need, in the end, to call | 
 | ``NET_DEVICE_INIT_INSTANCE()`` like this: | 
 |  | 
 | .. code-block:: c | 
 |  | 
 |    NET_DEVICE_INIT_INSTANCE(..., | 
 |                             CONFIG_ETH_INIT_PRIORITY | 
 | 			    &the_valid_net_if_api_instance, | 
 | 			    ETHERNET_L2, | 
 | 			    NET_L2_GET_CTX_TYPE(ETHERNET_L2), 1500); | 
 |  | 
 | IEEE 802.15.4 device driver | 
 | =========================== | 
 |  | 
 | Device drivers for IEEE 802.15.4 L2 work basically the same as for | 
 | Ethernet.  What has been described above, especially for recv, applies | 
 | here as well.  There are two specific differences however: | 
 |  | 
 | - It requires a dedicated device driver API: :c:type:`struct | 
 |   ieee802154_radio_api`, which overloads :c:type:`struct | 
 |   net_if_api`. This is because 802.15.4 L2 needs more from the device | 
 |   driver than just send and recv functions.  This dedicated API is | 
 |   declared in :file:`include/net/ieee802154_radio.h`. Each and every IEEE | 
 |   802.15.4 device driver must provide a valid pointer on such | 
 |   relevantly filled-in API structure. | 
 |  | 
 | - Sending a packet is slightly particular. IEEE 802.15.4 sends | 
 |   relatively small frames, 127 bytes all inclusive: frame header, | 
 |   payload and frame checksum.  Buffer fragments are meant to fit such | 
 |   frame size limitation.  But a buffer containing an IPv6/UDP packet | 
 |   might have more than one fragment. In the Ethernet device driver, it | 
 |   is up to the driver to handle all fragments. IEEE 802.15.4 drivers | 
 |   handle only one fragment at a time.  This is why the :c:type:`struct | 
 |   ieee802154_radio_api` requires a tx function pointer which differs | 
 |   from the :c:type:`struct net_if_api` send function pointer. | 
 |   Instead, the IEEE 802.15.4 L2, provides a generic | 
 |   :c:func:`ieee802154_radio_send()` meant to be given as | 
 |   :c:type:`struct net_if` send function. It turn, the implementation | 
 |   of :c:func:`ieee802154_radio_send()` will ensure the same behavior: | 
 |   sending one fragment at a time through :c:type:`struct | 
 |   ieee802154_radio_api` tx function, and unreferencing the buffer | 
 |   only when all the transmission were successful. | 
 |  | 
 | Each IEEE 802.15.4 device driver, in the end, will need to call | 
 | ``NET_DEVICE_INIT_INSTANCE()`` that way: | 
 |  | 
 | .. code-block:: c | 
 |  | 
 |    NET_DEVICE_INIT_INSTANCE(..., | 
 |                             the_device_init_prio, | 
 | 			    &the_valid_ieee802154_radio_api_instance, | 
 | 			    IEEE802154_L2, | 
 | 			    NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125); |