Saturday, 26 August 2017

Overview of Linux wireless networking architecture





fig: Overview of Linux wireless networking architecture


  • There are two types of WiFi devices, depending on where IEEE802.11 MLME is implemented. If it is implemented in device hardware, the device is a full MAC device. If it is implemented in software, the device is a soft MAC device. Most devices today are soft MAC devices.
  • Linux wireless subsystem to contain two major blocks: cfg80211 and mac80211, and they help the WiFi driver to interface with rest of the kernel and user space
  • cfg80211 provides configuration management services in the kernel. It also provides management interface between kernel and user space via nl80211. Both soft MAC and full MAC devices need to work with cfg80211. Mac80211 is a driver API that supports only software MAC devices. Our focus here will be on soft MAC devices, as shown in Fig


Data Path and Management Path:


  • From Fig. 1, there are two major paths in the architecture: a data path, and a management path. The data path corresponds to the IEEE 802.11 data frames, and the management path corresponds to the IEEE 802.11 management frames. For IEEE802.11 control frames, as most of them are used for time-critical operations such as ACK, they are often handled by the hardware. An exception may be the PS-Poll frame, which can also be taken care of by mac80211. The data and management paths are split in mac80211


How is data packet transmitted?


  • Starting from user space application, often we create a socket, bind it to an interface (e.g. Ethernet or WiFi), put the content into socket buffer, and send it. In socket creation, we also specify its protocol family, which will be used by the kernel. This happens in the data application block in Fig. 1. Eventually this invokes a system call, and subsequent work happens in the kernel space.
  • The transmission first passes the socket layer, and an important structure here is struct sk_buff, or more commonly known as skb. A skb holds pointer to the data buffer and tracks the data length. It provides very good support and APIs to transfer our data among different layers in the kernel, such as header insertion/removal, and is used thoughout the packet transmission / reception process.
  • Now the transmission lands itself at the device agnostic layer, which links various hardware devices like Ethernet and WiFi to different network protocols, transparently. The device agnostic layer is characterized by an important structure: struct net_device. This is how Ethernet device drivers interface with the kernel, as shown by the Ethernet driver block in Fig. 1. The interfacing is via struct net_device_ops, which has a long list of net_device operations. Particularly for transmit:
struct net_device_ops {
â¦
netdev_tx_t(*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev);
â¦
};
To send the packet, the skb is passed to a function called dev_queue_xmit. After tracing through the call, it eventually invokes ops->ndo_start_xmit(skb, dev). This is exactly the API handler that Ethernet device drivers need to register.
For WiFi devices, however, it is usually mac80211 (instead of the device drivers) that registers with netdev_ops. See net/mac80211/iface.c:
static const struct net_device_opsieee80211_dataif_ops = { .ndo_open = ieee80211_open, .ndo_stop = ieee80211_stop, .ndo_uninit = ieee80211_uninit, .ndo_start_xmit = ieee80211_subif_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_change_mtu = ieee80211_change_mtu, .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_netdev_select_queue,};
So mac80211 also appears as a net_device, and when a packet needs to be transmitted via WiFi, the corresponding transmit handler, ieee80211_subif_start_xmit, is invoked, and we are entering the mac80211 block. Below is the call trace for ieee80211_subif_start_xmits. Subsequently it invokes:
We are now at the boundary between mac80211 and WiFi driver. The drv_tx is simply a wrapper that maps the transmission to the tx handler that WiFi device driver has registered:
static inline void drv_tx(struct ieee80211_local *local, struct ieee80211_tx_control *control, struct sk_buff *skb){ local->ops->tx(&local->hw, control, skb);}
This is the end of mac80211, and device driver will take over.


What about management path?
  • Theoretically we can transmit management frames the same way as in data path by constructing management frames in user space and send them via socket, but there are well-developed user space tools, notably wpa_supplicant and host_apd, that can do the work. Wpa_supplicant controls the wireless connection for client STAs such as scan, authentication, and association, whereas host_apd functions as AP. These user space tools uses netlink socket to communication with the kernel, and the corresponding handler in the kernel is nl80211 in cfg80211. These user space tools will invoke the send handlers in netlink library to send command (e.g. NL80211_CMD_TRIGGER_SCAN) to the kernel. In kernel space, the command is received by nl80211, which has the mapping between command (.cmd) and action (.doit) in static struct genl_ops nl80211_ops:
static const struct genl_opsnl80211_ops[] = {
â¦
{
.cmd = NL80211_CMD_TRIGGER_SCAN,
},
â¦
};
  • For the example of triggering scan, the scan request is passed from cfg80211 to mac80211 via the scan handler that mac80211 has registered with cfg80211 in struct cfg80211_ops:
const struct cfg80211_ops mac80211_config_ops = {
â¦
.scan = ieee80211_scan,
â¦
};
In mac80211, ieee80211_scan will take over the scanning process:
=>ieee80211_scan_state_send_probe
=>ieee80211_send_probe_req
=>ieee80211_tx_skb_tid_band
=>ieee80211_xmit
=>ieee80211_tx
=>ieee80211_tx_frags
=>drv_tx
How is received packet handled?
  • When a packet is captured by the WiFi hardware over the air, the hardware may generate an interrupt to the kernel (e.g. as in most PCI interfaces ), or the packet may be polled (e.g. for the case of USB interface). In the former case, the interrupt will lead to a receive interrupt handler, and for the latter, a receive callback handler is invoked
  • It turns out that in these handlers the device driver does not do much with the received packet except for some sanity check, filling up the receive descriptor for mac80211, and then passing the packet to mac80211 for further processing (either directly or more commonly putting the packet on a receive queue)
  • Entry to mac80211 is via ieee80211_rx or one of its variants, which invokes various receive handlers in mac80211 (see in ieee80211_rx_handlers for the code). This is also where the data path and management path are divided.
  • If the received frame is of type data, it is translated into 802.3 frame (by __ieee80211_data_to8023) and is delivered to the networking stack via netif_receive_skb. From then on, the network protocol block will parse and decode the protocol header
  • If the received frame is of type management, it is processed in ieee80211_sta_rx_queued_mgmt. Some management frames end in mac80211, and some are further passed up to cfg80211 and sent to user space management tools. For example authentication frames are further processed by cfg80211_rx_mlme_mgmt and sent to user space via nl80211_send_rx_auth, and association response frames are processed by cfg80211_rx_assoc_resp and sent to user space via nl80211_send_rx_assoc.


Concluding the Walk
  • The typical flow pattern of a WiFi driver contains three tasks: configuration, transmit path handling, and receive path handling. Take again the USB WiFi adapter for example, when the device is detected, the probe function is invoked. This could be where the configuration like registration of ieee80211_ops takes place
  • First, ieee80211_alloc_hw allocates a struct ieee80211_hw, which represents the WiFi device.
  • In particular, the following data structures are allocated:
  • - struct wiphy: mainly used to describe WiFi hardware parameters like MAC address, interface modes and combinations, supported bands, and other hardware capabilities.
  • - struct ieee80211_local: this is the driver visible part and is largely used by mac80211. The mapping of ieee80211_ops is linked to the struct ieee80211_local (const struct ieee80211_ops *ops of struct ieee80211_local). It can be accessed from ieee80211_hw by using container_of, or the API hw_to_local.
  • - Private struct for device driver (void *priv in struct ieee80211_hw).
  • Registration of the hardware is completed through ieee80211_register_hw, after which other mac80211 functions takes place. For example, in STA mode, wpa_supplicant will instruct the device to scan, authenticate, and associate with a BSS and subsequently data communication will occur.


mac802_11_cfg80211_nl80211:

About mac80211:



  • mac80211 is a framework which driver developers can use to write drivers for SoftMAC wireless devices.
  • mac80211 implements the cfg80211 callbacks for SoftMAC devices, mac80211 then depends on cfg80211 for both registration to the networking subsystem and for configuration. Configuration is handled by cfg80211 both through nl80211 and wireless extensions.

About cfg80211:

  • cfg80211 is the Linux 802.11 configuration

  • cfg80211 replaces Wireless-Extensions

  • nl80211 is used to configure a cfg80211 device and is used for kernel ←→ userspace communication.

  • When implementing a cfg80211 driver wireless extensions support is still provided automatically for you through cfg80211 through CONFIG_CFG80211_WEXT. Distributions no longer needing wireless extensions can remove this and are encouraged to do so. cfg80211 also provides full regulatory support, this is done through wireless-regdb and the usage of CRDA.

  • All new Linux wireless drivers should be written targeting either cfg80211 for fullmac devices or mac80211 for softmac devices

Writing cfg80211 drivers:

  • We now have a few cfg80211 drivers, a good example of a full cfg80211 drivers is the Atheros ath6kl driver. Instead of writing wext ioctls you now write cfg80211 operation callbacks and fill in the wiphy struct to indicate to cfg80211 its device capabilities.

About nl80211:

  • nl80211 is the new 802.11 netlink interface public header. Together with cfg80211 it is intended to replace Wireless-Extensions
  • nl80211 and cfg80211 are still under development.

Users of nl80211:

  • Current users of nl80211:

About iw:

  • iw is a new nl80211 based CLI configuration utility for wireless devices. It supports all new drivers that have been added to the kernel recently. The old tool iwconfig, which uses Wireless Extensions interface, is deprecated and it's strongly recommended to switch to iw and nl80211.
  • iw help
  • on your command line and it will print out the commands it supports.
  • Getting device capabilities

  • Use the following to get device capabilities for all devices, such as band information (2.4 , and 5 ), and 802.11n information:
> iw list
  • Scanning

> iw dev wlan0 scan
  • Listening to events

>  iw event
> When debugging, it can be useful to see the auth/assoc/deauth/disassoc frames, use
    iw event -f
> and sometimes timing information is also useful:
   iw event -t
  • Getting link status

>To determine if you are connected to an AP or not and if you are the last TX rate used you can use the command below.
Example output when associated to a legacy (non-802.11n) AP:
iw dev wlan0 link
Connected to 04:21:b0:e8:c8:8b (on wlan0)
       SSID: attwifi
       freq: 2437
       RX: 2272 bytes (18 packets)
       TX: 232 bytes (3 packets)
       signal: -57 dBm
       tx bitrate: 36.0 Mbit/s
  • Getting station statistics
iw dev wlan1 station dump
Station 12:34:56:78:9a:bc (on wlan0)
        inactive time:  304 ms
        rx bytes:       18816
        rx packets:     75
       tx bytes:       5386
       tx packets:     21
       signal:         -29 dBm
       tx bitrate:     54.0 MBit/s
References:
https://www.kernel.org/doc/html/latest/driver-api/80211/

No comments:

Post a Comment