NOTE: this page is for archival only, see the note at the end of the page.

About cfg80211

cfg80211 is the new Linux wireless configuration API. cfg80211 replaces Wireless-Extensions. nl80211 is used to configure a cfg80211 device. Wext is now in maintenance mode, no new features will be added to it, we'll only fix bugs for it. cfg80211 is now feature-par complete with wireless-extensions.

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 Intel iwmc3200wifi driver. Instead of writing wext ioctls you now write cg80211 operation callbacks and fill in the wiphy struct to indicate to cfg80211 its device capabilities.

As an example here is iwmc3200wifi's cfg80211_ops:

static struct cfg80211_ops iwm_cfg80211_ops = {
        .change_virtual_intf = iwm_cfg80211_change_iface,
        .add_key = iwm_cfg80211_add_key,
        .get_key = iwm_cfg80211_get_key,
        .del_key = iwm_cfg80211_del_key,
        .set_default_key = iwm_cfg80211_set_default_key,
        .get_station = iwm_cfg80211_get_station,
        .scan = iwm_cfg80211_scan,
        .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
        .connect = iwm_cfg80211_connect,
        .disconnect = iwm_cfg80211_disconnect,
        .join_ibss = iwm_cfg80211_join_ibss,
        .leave_ibss = iwm_cfg80211_leave_ibss,
        .set_tx_power = iwm_cfg80211_set_txpower,
        .get_tx_power = iwm_cfg80211_get_txpower,
        .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
        .set_pmksa = iwm_cfg80211_set_pmksa,
        .del_pmksa = iwm_cfg80211_del_pmksa,
        .flush_pmksa = iwm_cfg80211_flush_pmksa,

Then you allocate the wiphy by specifying the cfg80211 ops and fill the wiphy. For example iwmc3200wifi does it this way:

        wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
        if (!wdev) {
                dev_err(dev, "Couldn't allocate wireless device\n");
                return ERR_PTR(-ENOMEM);

        wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
                                sizeof(struct iwm_priv) + sizeof_bus);
        if (!wdev->wiphy) {
                dev_err(dev, "Couldn't allocate wiphy device\n");
                ret = -ENOMEM;
                goto out_err_new;

        set_wiphy_dev(wdev->wiphy, dev);
        wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
        wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
        wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
        wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
        wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;

        wdev->wiphy->cipher_suites = cipher_suites;
        wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);

        ret = wiphy_register(wdev->wiphy);
        if (ret < 0) {
                dev_err(dev, "Couldn't register wiphy device\n");
                goto out_err_register;

For more details refer to cfg80211.h and as an example driver you can read iwmc3200wifi.

Regulatory support

cfg80211 has regulatory compliance built into it, each registered device obeys cfg80211's regulatory interpretations and provides an API for drivers and for mac80211 to provide hints to it as to what rules should be enforced. A device registers with cfg80211 a list of supported bands and each band has a list of supported channels. During registration cfg80211 will ensure only the allowed channels for the currently set regulatory domain will be left enabled.

Wireless core initialization

Upon the initialization of the wireless core (cfg80211) a world regulatory domain (highly restrictive) will be set as the central regulatory domain. If CRDA is present the latest dynamic world regulatory domain is queried from CRDA; if it is not then a statically defined list is used.

When a wiphy is registered to cfg80211 (possibly via mac80211) the effective set of permitted channels/maximum power is calculated for that device based on the current regulatory domain. As initially that will be the world regulatory domain, devices start out being restricted to that.

Driver settings

Each driver can hint to cfg80211 which regulatory domain to set by providing an ISO-3166 alpha2 country code; this is intended to be used as a first start-up hint based on the device's EEPROM.

Conflicts can arise when you have multiple wireless devices present on a system which claim different regulatory domains. Arbitrarily complex algorithms could be invented to resolve such conflicts; for now the regulatory domain selected by the first wireless card is chosen. It would also be reasonable to let users resolve the conflict manually.

Once an alpha2 is suggested to the wireless core it will query CRDA for a regulatory domain for that alpha2. The wireless core will then iterate overall all registered wireless devices and update the device's list of enabled channels, max power, max bandwidth and max antenna gain for each of them.

After a regulatory domain has been set the reg_notfier() for each driver (if defined) will be called. Drivers have the option to register their callback (reg_notifier()) to review the current regulatory settings and update them based on further requirements.

Drivers which have regulatory restrictions enforced in the firmware and do not have ISO / IEC 3166 alpha2 country mappings to their currently set regulatory domain may choose to opt out of the first regulatory core review upon initialization, however subsequent updates (by the user or mac80211 through 802.11d) will be obeyed.

802.11 country information

APs can provide an ISO/IEC 3166-1 country code and a channel list (with associated max tx power setting.) In practice though one can not always trust APs country information element regulatory information due to considerations for outdated data, rogue/busted APs. Therefore, the wireless code determines the regulatory permissions based on the intersection of data from the APs country information element and what CRDA provides for the given country code.

The Linux kernel wireless subsystem always enables the dot11MultiDomainCapabilityEnabled flag. Therefore, it tries to follow country information received in AP beacons.

If an AP supports sending the Country IE it will send the country IE appended on every beacon. Since we have an initial regulatory setting (set by the user, driver, or core) we don't pay attention to the country IE until we try to associate to the AP. Upon association we will parse the country IE, convert it to a cfg80211 regulatory domain structure and pass it up as a country IE regulatory hint to the wireless core. All cfg80211 drivers can use this, they must call regulatory_hint_11d(). mac80211 does this for its drivers when processing the country IEs on a beacon. regulatory_hint_11d() is optimized to ignore hints from the same AP or that match the same country IE checksum.

APs may support 2 bands (2.4 GHz and 5 GHz) or 1 band (2.4 GHz or 5 GHz). When an AP supports 1 band, as per IEEE-802.11 2007 country IE clarification request the AP may send a subset of the allowed regulatory rules and not the complete set. Because of this the cfg80211 regulatory infrastructure trusts its original regulatory requests if the AP does not send any information on a band it does not support. Since band information is purely artificial in cfg80211 we conclude an AP does not support a band if it has no channel information in its country IE that fits within 2 GHz of the tested band. We can can tune this as we see fit, in freq_in_rule_band().

If an AP has no information on a supported device band we trust the last trusted regulatory request. The last trusted regulatory request will vary depending on the device.

Manual setting of the regulatory domain

Manual setting for a regulatory domain only makes sense if you have no AP capable of broadcasting regulatory information or if your card has no EEPROM regulatory information. To help these type of devices we can allow setting of the regulatory domain to help the user comply to regulatory rules. This can happen, for example, when you travel with a wireless card. For devices with their own EEPROM regulatory information the callback routine (reg_notifier()) registered to cfg80211 for the driver can ensure the EEPROM data is respected even if a user changes the regulatory information manually.

Driver initialization

As mentioned above, after the driver has registered to cfg80211 the world regulatory domain settings will have been set by default as no beacons with country information could have been received yet. Drivers should register all supported hardware channels to the wireless core.

Drivers with EEPROM regulatory information

Drivers that have country information in their EEPROM should provide an ISO/IEC 3166-1 alpha2 code to cfg80211 as a hint about the current regulatory domain. This should be done wiphy registration.

For the special case where the EEPROM regulatory information must be observed at all times, the driver will not register any other channels.

In the special case where the EEPROM regulatory information must be observed unless 802.11 country information is received, the driver may register a regulatory notifier and restrict any information that CRDA supplied to the EEPROM information depending on the cause of the regulatory change.

Drivers without EEPROM regulatory information

Drivers with no EEPROM regulatory information can simply rely on the world regulatory domain, wait for an 802.11 country information or the user setting the regulatory domain manually.

Regulatory hints

cfg80211 provides APIs for both drivers and mac80211 to supply regulatory hints to further enhance regulatory compliance.


After registration with cfg80211 a driver can provide a regulatory_hint() with an alpha2. This alpha2 can come from a map read from the device's EEPROM.


cfg80211 supports enhancing regulatory compliance by allowing drivers and mac80211 to inform it of when a country information element has been received and should be obeyed. The Country Information Element (cf. 802.11-2007 contains the information required to allow a station to identify the regulatory domain in which the AP is located and to configure its PHY for operation in that regulatory domain. The Country IE contains, amongst other things, the list of permissions (channels and transmit power on those channels) and an ISO/IEC 3166-1 country code. regulatory_hint_11d() can be used to pass to cfg80211 an IEEE 802.11 country information element. cfg80211 will parse the information element, build a regulatory domain from it and intersect with what CRDA tells us should apply for the given alpha2. This prevents rogue/busted APs from providing incorrect information.

other documentation

cfg80211 files and kernel docs

This is a static dump of the wiki, taken after locking it in January 2015. The new wiki is at
versions of this page: last, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2, v1