Padding et alignements dans mac80211

Posted by Benoit Papillault on Nov 28, 2009 in Linux |

Le matériel 802.11 ajoute du padding sur les paquets reçus et supprime le padding sur les paquets transmis. De plus, mac80211, la pile logicielle 802.11 Linux générique s’attends à un certain alignement sur les paquets reçus. Ainsi, les pilotes logiciels ont besoin de traiter ces contraintes pour éviter que des octets en trop ou en moins apparaissent.

Padding en émission

Théorie

Comme nous l’avons dis plus haut, la plupart des matériels 802.11 suppriment le padding à l’émission, cad qu’ils suppriment typiquement 2 octets entre l’entête et la charge utile d’un paquet 802.11. Une explication à cela est que si le début d’un paquet est aligné sur une frontière de 4 octets, alors la charge utile sera également aligné sur une frontière de 4 octets and cela pourrait probablement accéléré les opérations matérielles. Afin de préserver le contenu du paquet, le pilote logiciel a besoin d’ajouter 2 octets exactement au même endroit pour qu’il annule la suppression du padding fait par le matériel. En pratique, nous avons besoin de trouver à quelle position le matériel va supprimer des octets et combien d’octets. Cela pourrait ne pas être à la fin de l’entête 802.11 car chaque matériel calcule la position du padding avec sa propre formule.

Driver requirement

Once we know how the hardware operates, we need to compute the pad position and size and add the missing bytes at the proper position. This is done in the ieee80211_ops.tx handler (or some other functions called by this later) by using a source code similar to :

if (padsize > 0 && skb->len>padpos) {
  skb_push(skb, padsize);
  memmove(skb->data, skb->data+padsize, padpos);
}

When the driver is filling the hardware TX descriptor, great care must be taken not to mix :

  1. Length of the packet with padding included (skb->len). This is needed to move the correct amount of data from the host to the hardware.
  2. Length of the 802.11 original packet. This is needed by the hardware to properly computes the FCS.

Remaining question : since we modify the content of the packet (skb) and since this packet might be used elsewhere in the Linux stack (bridge or monitor), do we need to restore the content of the packet later?

Testing

Since this is a complex subject, we need an external tool that will test the software driver code as a black box. Our theory is that pad position and size only depends on the first 2 bytes of the 802.11 packet (the frame_control field). If this is the case, we can generate a varying packet size with all possible value for frame_control and send them to the driver using a monitor interface (in injection mode). Then, the packets are received on another hardware that also provided FCS field on all received packets. By checking both the FCS field and the content of the packet against the original packet, we can make sure that TX is working properly on the TX node and RX is working properly on the RX node. Remaining question : Is that really true?

RX unpadding

Theory of operation

We are now in the opposite direction, instead of transmitting a packet, we are receiving a packet. On RX, most 802.11 hardware do padding, ie they insert 2 bytes between 802.11 header and payload, likely to improve performance by 4 bytes boundary alignment. As such, the software drivers needs to remove such padding on RX.

Driver requirement

First of all, we need to compute the exact pad position and size. In most cases, this is exactly the same formula as used on TX. This makes sense since the driver is trying to obey the same alignment constraints. The hardware typically triggers an interrupt to say that an RX packet needs attention and fill in a RX descriptor containing various information about the packet (like its size, with or without the padding). The packet will be then handed to mac80211 using either ieee80211_rx() or ieee80211_rx_irqsafe(). Before doing this, a typical source code will be :

if (padsize > 0 && skb->len>=padpos+padsize) {
  memmove(skb->data + padsize, skb->data, padpos);
  skb_pull(skb, padsize);
}

Testing

Testing is done using the same mechanism used for testing TX.

RX alignment

Theory of operation

mac80211 checks the 802.11 payload is always aligned on a 4 bytes boundary. This is apparently needed to make sure that IPv4 or IPv6 will be aligned on 4 bytes boundary as well, but some people says it’s not needed. We will try to make sure that such alignment is met as well. Such alignment is checked by ieee80211_verify_alignment() and is called by ieee80211_rx() calling  __ieee80211_rx_handle_packet().

Driver requirement

Before calling ieee8021_rx() or ieee80211_rx_irqsafe(), the software drivers needs to make sure that above constraints will be met. Remaining questions : if we assume that hardware is already aligning 802.11 payload on 4 bytes boundaries, do we need more work? The answer is yes for zd1211rw driver since on RX, the hardware is not doing any padding. A typical source code will be :<TBD>

Testing

Testing is done by enabling CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT (« Enable packet alignment debugging » in make menuconfig). After recompiling the Linux kernel, you can again do the above testing and monitor syslog on the RX node. If nothing show up, then you are on the safe side.

Driver requirement

Étiquettes :

Comments are closed.

© 2024 Blog de Benoit Papillault ! Theme : Laptop Geek - Réalisation : BenoitDuWeb - Mentions légales