Skip to content

net/mac80211 - IEEE 802.11 协议栈

1. 模块架构

1.1 功能概述

mac80211 是 Linux 的软件无线 MAC 实现,为无线设备驱动提供接口。

1.2 关键源文件

文件作用
net/mac80211/ieee80211_i.h主头文件
net/mac80211/cfg.c配置接口
net/mac80211/rx.c接收处理
net/mac80211/tx.c发送处理
net/mac80211/mlme.cMLME (MAC 子层管理)

2. 核心数据结构

2.1 struct ieee80211_local

c
// net/mac80211/ieee80211_i.h:200
struct ieee80211_local {
    struct wiphy *wiphy;

    struct ieee80211_hw *hw;
    struct ieee80211_conf conf;

    // 虚拟接口
    struct list_head interfaces;
    struct ieee80211_vif *active_ps;

    // 接收/发送
    struct sk_buff_head skb_queue;
    struct tasklet_struct tasklet;
    struct workqueue_struct *workqueue;

    // 统计
    struct mac80211_priv_stats stats;

    // 功率管理
    u8 ps_filter[ETH_ALEN];
    bool ps_enabled;
};

2.2 struct ieee80211_hw

c
// include/net/mac80211.h:100
struct ieee80211_hw {
    struct ieee80211_conf conf;
    struct wiphy *wiphy;

    const struct ieee80211_ops *ops;
    void *priv;

    u32 flags;
    u32 extra_tx_headroom;
    u32 extra_rx_headroom;

    u8 max_rx_aggregation_subframes;
    u8 max_tx_aggregation_subframes;
};

2.3 struct ieee80211_ops

c
// include/net/mac80211.h:200
struct ieee80211_ops {
    // 初始化
    int (*start)(struct ieee80211_hw *hw);
    void (*stop)(struct ieee80211_hw *hw);

    // 发送
    void (*tx)(struct ieee80211_hw *hw,
               struct ieee80211_tx_control *control,
               struct sk_buff *skb);

    // 接收
    void (*rx)(struct ieee80211_hw *hw,
               struct ieee80211_rx_status *status,
               struct sk_buff *skb);

    // 状态
    int (*add_interface)(struct ieee80211_hw *hw,
                         struct ieee80211_vif *vif);
    void (*remove_interface)(struct ieee80211_hw *hw,
                             struct ieee80211_vif *vif);

    // 配置
    int (*config)(struct ieee80211_hw *hw, u32 changed);
    void (*bss_info_changed)(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif,
                              struct ieee80211_bss_conf *info,
                              u32 changed);
};

3. 帧接收

3.1 ieee80211_rx()

c
// net/mac80211/rx.c:2000
void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
    struct ieee80211_local *local = hw->priv;
    struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
    struct ieee80211_sub_if_data *sdata;

    // 获取接收状态
    status = IEEE80211_SKB_RXCB(skb);

    // 查找对应的虚拟接口
    sdata = ieee80211_sdata_from_skb(local, skb);
    if (!sdata)
        return;

    // 处理帧
    if (status->freq)
        ieee80211_rx_monitor(local, skb, status);

    // 分发到接口
    ieee80211_deliver_skb(local, skb);
}

3.2 ieee80211_rx_h_decrypt()

c
// net/mac80211/rx.c:500
static rx_result ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
{
    struct ieee80211_key *key = rx->key;

    if (!key)
        return RX_CONTINUE;

    switch (key->conf.cipher) {
    case WLAN_CIPHER_SUITE_WEP40:
    case WLAN_CIPHER_SUITE_WEP104:
        return ieee80211_crypto_wep_decrypt(rx);
    case WLAN_CIPHER_SUITE_CCMP:
        return ieee80211_crypto_ccmp_decrypt(rx);
    case WLAN_CIPHER_SUITE_TKIP:
        return ieee80211_crypto_tkip_decrypt(rx);
    }

    return RX_CONTINUE;
}

4. 帧发送

4.1 ieee80211_subif_start_xmit()

c
// net/mac80211/tx.c:1000
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                        struct net_device *dev)
{
    struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    struct ieee80211_local *local = sdata->local;
    struct ieee80211_tx_info *info;
    struct ieee80211_key *key;

    // 获取 tx_info
    info = IEEE80211_SKB_CB(skb);

    // 查找密钥
    key = ieee80211_tx_key(sdata, skb);
    if (key)
        ieee80211_encrypt_skb(sdata, skb, key);

    // 加入队列表
    ieee80211_tx_pending(local);

    return NETDEV_TX_OK;
}

4.2 ieee80211_tx()

c
// net/mac80211/tx.c:200
static void ieee80211_tx(struct ieee80211_local *local,
                         struct sk_buff *skb, bool txpending)
{
    struct ieee80211_tx_data tx;
    struct ieee80211_sta *sta;

    // 获取站点
    sta = tx.sta;

    // 聚合处理
    if (sta && test_sta_flag(sta, WLAN_STA_AMPDU))
        ieee80211_ampdu_action(skb, sta);

    // 发送
    local->ops->tx(local->hw, &tx.control, skb);
}

5. MLME (MAC 子层管理)

5.1 扫描

c
// net/mac80211/mlme.c:2000
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
                          struct cfg80211_scan_request *req)
{
    struct ieee80211_local *local = sdata->local;

    // 发送 probe request
    ieee80211_send_probe_req(sdata, req->ssids, req->n_ssids);

    // 启动扫描定时器
    mod_timer(&local->scan.timer, jiffies + IEEE80211_SCAN_INTERVAL);
}

5.2 认证

c
// net/mac80211/mlme.c:500
static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
                                   struct ieee80211_bss *bss)
{
    struct ieee80211_local *local = sdata->local;
    struct ieee80211_mgd_auth_data *auth_data;

    // 分配 auth_data
    auth_data = kzalloc(sizeof(*auth_data), GFP_ATOMIC);

    // 发送认证请求
    ieee80211_send_auth(sdata, 1, auth_data->algorithm);

    // 设置超时
    sdata->auth_data = auth_data;
}

5.3 关联

c
// net/mac80211/mlme.c:800
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata,
                                struct ieee80211_bss *bss)
{
    struct ieee80211_mgd_assoc_data *assoc_data;

    // 发送关联请求
    ieee80211_send_assoc(sdata, bss);

    // 设置状态
    sdata->u.mgd.state = IEEE80211_STA_ASSOC;
}

6. 功率管理

6.1 PS 模式

c
// net/mac80211/pm.c:100
void ieee80211_enable_ps(struct ieee80211_local *local,
                         struct ieee80211_sub_if_data *sdata)
{
    local->ps_enabled = true;

    // 缓冲流量
    ieee80211_sta_set_tim(sdata);

    // 发送 PS-Poll 帧
    ieee80211_send_pspoll(local, sdata);
}

6.2 动态 PS

c
// 监听流量自动进入/退出 PS
// 通过 WMM 配置实现

基于 VitePress 构建