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.c | MLME (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 配置实现