Joshua Oreman: 802.11 wireless development

gPXE 802.11 API design notes

The below are my thoughts about a week into the coding season. They may change without warning. This is not meant to be a complete API guide; there are comments in the header files for that. Update: As of Week 5 these have been updated for accuracy, if not completeness.

802.11 drivers should “feel” like regular NIC drivers. They'll need to handle more things, because wireless networking is more complex than wired, but the programming interface should be similar. 802.11 has a lot of MAC-layer processing, though, so there needs to be a shim between the driver layer and the ll_protocol push/pull. I chose to implement this by creating a net80211_device, and having the 802.11 MAC layer set up a normal net_device to wrap it.

The operations for a net80211_device are the same as those of a net_device, with one addition: config(). The config call is used to ask the driver to update any hardware-level settings for wireless-specific issues like channel, transmission rate, association settings (what network are we connected to?), and physical-layer issues like ERP parameters. (When associating with an 802.11g network, we might get something in the association response packet that tells us how to configure our timings and such; the card needs to hear about that.)

On initialization (the driver probe() routine), each wireless driver provides some information about the capabilities and quirks of its hardware in order to register its net80211_device. This information is stored in a net80211_hw_info structure, and its contents are mostly self-explanatory. The MAC layer uses it to know what to advertise when associating with a network, how to interpret the card's status, and how to set up the wrapping net_device (proper MAC address).

Network management

When the 802.11 netdev is first open, after driver initialization is complete, an auto-association process is started that does all of the following in sequence. They can be done separately from that based on user commands.

First, it's necessary to find out what network you want to associate with. To that end, net80211_probe_start() will start scanning for networks, and process received data whenever net80211_probe_step() is called. The handler should call net80211_probe_finish_all() or net80211_probe_finish_best() to retrieve a list of all networks, or the best-signal network, that were returned by the probe and matched the SSID filter supplied, if any. The probe call will attempt a passive search (scanning for beacons), but can be configured to search actively (sending probe requests) for networks on the 2.4GHz band by setting the netX/active-scan gPXE setting. The net80211_probe_finish_* calls return net80211_wlan structures listing the detected network parameters; either a list or a single structure. The returned structure(s) need to be freed by calling net80211_free_wlan() or net80211_free_wlanlist() after they have been used for association.

The actual association is performed by passing that net80211_wlan structure in sequence to net80211_prepare_assoc(), net80211_send_auth(), net80211_send_assoc(), and crypto handshaking:

  • net80211_prepare_assoc() sets device parameters like channel and transmission rate based on the contents of the beacon packet received and recorded in the wlan structure. There is a variant, net80211_prepare_probe(), that creates a sensible default list without knowing beacon information, to be used for either passive or active scanning. (The passive default includes more channels, because it's always safe to listen on a channel but local regulations may prohibit sending on it.)
  • net80211_send_auth() sends an authentication packet, using either Open System or Shared Key authentication. It sets the NET80211_WORKING flag in dev→state and returns immediately. As further packets in the authentication sequence are received, they are responded to automatically. When authentication either succeeds or fails, the NET80211_WORKING flag is unset. On success, NET80211_AUTHENTICATED is set; on failure, the 802.11 status code is stored in the low byte of dev→state.
  • net80211_send_assoc() sends an association request packet; authentication must have previously succeeded. It operates similarly to net80211_authenticate, setting the WORKING flag until a reply is received, and setting NET80211_ASSOCIATED if the association was successful or storing the status code if it was not.
  • The crypto handshaking is only relevant for WPA-protected networks. There will be some mechanism to call out to WPA-specific code to perform the four-way EAPOL handshake. EAPOL (Extensible Authentication Protocol Over LANs) runs just above the link-layer, without IP or TCP encapsulation; it will use the gPXE net_protocol API. Not implemented yet.

To be continued…

QR Code
QR Code soc:2009:oremanj:notes:design (generated for current page)