> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/man9/ieee80211.9.md).

# ieee80211(9)

`IEEE80211` — 802.11 网络层

## 名称

`IEEE80211`

## 概要

```c
#include <net80211/ieee80211_var.h>
```

```c
void
ieee80211_ifattach(struct ieee80211com *ic)
void
ieee80211_ifdetach(struct ieee80211com *ic)
int
ieee80211_mhz2ieee(u_int freq, u_int flags)
int
ieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c)
u_int
ieee80211_ieee2mhz(u_int chan, u_int flags)
int
ieee80211_media_change(struct ifnet *ifp)
void
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
int
ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode)
enum ieee80211_phymode
ieee80211_chan2mode(const struct ieee80211_channel *chan)
int
ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode)
int
ieee80211_media2rate(int mword)
```

## 描述

IEEE 802.11 设备驱动程序编写为使用 `IEEE80211` 软件层提供的基础设施。该软件为驱动程序提供支持框架，包括 ifnet 克隆、状态管理以及应用程序通过其与 802.11 设备交互的用户管理 API。大多数驱动程序依赖 `IEEE80211` 层提供协议服务，但卸载功能的设备可绕过该层直接连接到设备。

`IEEE80211` 设备驱动程序实现虚拟无线电 API，通过从底层设备克隆的网络接口（又称 vap）导出给用户。这些接口具有操作模式（station、adhoc、hostap、wds、monitor 等），在接口生命周期内固定。可支持多个并发接口的设备允许克隆多个 vap。这支持构建有趣的应用程序，如一个 AP vap 和一个或多个 WDS vap，或多个 AP vap，每个具有不同的安全模型。`IEEE80211` 层虚拟化大多数 802.11 状态并协调 vap 状态更改，包括调度多个 vap。未虚拟化的状态包括当前信道和 WME/WMM 参数。协议处理通常完全在 `IEEE80211` 层处理，驱动程序仅负责在主机和设备之间移动数据。同样，`IEEE80211` 处理大多数 ioctl(2) 请求而不进入驱动程序；驱动程序仅在需要其参与的状态更改时被通知。

`IEEE80211` 层定义的虚拟无线电接口意味着驱动程序必须结构化以遵循特定规则。任何时候仅支持单个接口的驱动程序也必须遵循这些规则。

这些函数中的大多数要求在调用之前已附加到协议栈。

`ieee80211_ifattach` 函数将无线网络接口 `ic` 附加到 802.11 网络协议栈层。在使用任何需要跨调用存储驱动程序状态的 `IEEE80211` 函数之前，必须调用此函数。

`ieee80211_ifdetach` 函数释放与驱动程序关联的任何 `IEEE80211` 结构，并代表调用者执行 Ethernet 和 BPF 分离。

`ieee80211_mhz2ieee` 实用程序函数将频率 `freq`（以 MHz 为单位指定）转换为 IEEE 802.11 信道号。`flags` 参数是一个提示，指定频率是在 2GHz ISM 频段（`IEEE80211_CHAN_2GHZ`）还是 5GHz 频段（`IEEE80211_CHAN_5GHZ`）；然后执行结果的适当截断。

`ieee80211_chan2ieee` 函数将为驱动程序 `ic` 将 `*c` 中指定的信道转换为 IEEE 信道号。如果转换无效，将向系统控制台打印错误消息。此函数要求驱动程序已连接到 `IEEE80211` 子系统。

`ieee80211_ieee2mhz` 实用程序函数将 IEEE 信道号 `chan` 转换为频率（以 MHz 为单位）。`flags` 参数是一个提示，指定频率是在 2GHz ISM 频段（`IEEE80211_CHAN_2GHZ`）还是 5GHz 频段（`IEEE80211_CHAN_5GHZ`）；然后执行结果的适当截断。

`ieee80211_media_status` 和 `ieee80211_media_change` 函数是 `ifmedia` 命令的设备无关处理程序，不打算直接调用。

`ieee80211_setmode` 函数从 802.11 协议栈内部调用以更改驱动程序 PHY 的模式；不打算直接调用。

`ieee80211_chan2mode` 函数返回使用信道 `chan` 所需的 PHY 模式。这通常用于选择要在信标中通告的速率集等。

`ieee80211_rate2media` 函数将比特率 `rate`（以 0.5Mbps 为单位测量）转换为在 PHY 模式 `mode` 下运行的设备 `ic` 的 `ifmedia` 子类型。`ieee80211_media2rate` 执行此转换的反向操作，返回对应于 `ifmedia` 子类型的比特率（以 0.5Mbps 为单位）。

## 数据结构

虚拟无线电架构将状态拆分为单个每设备 `ieee80211com` 结构和一个或多个 `ieee80211vap` 结构。驱动程序应在设备附加和 vap 创建期间在这些结构中设置各种共享状态，但除此之外应将其视为只读。`ieee80211com` 结构由 `IEEE80211` 层作为设备 `ifnet` 的附属数据分配；通过 `if_l2com` 结构成员访问。`ieee80211vap` 结构由驱动程序在“vap create”方法中分配，并应使用任何驱动程序私有状态扩展。这种让驱动程序控制分配数据结构的技术用于其他 `IEEE80211` 数据结构，应利用它将驱动程序私有状态与公共 `IEEE80211` 状态一起维护。

其他主要数据结构是跟踪本地 BSS 中对等点的站点（或节点）表，以及定义当前可用无线电信道集合的信道表。两个表都绑定到 `ieee80211com` 结构并由所有 vap 共享。对节点的长期引用被计数以防止过早回收。特别是每个发送/接收的数据包都持有节点引用（发送时显式或接收时隐式）。

`ieee80211com` 和 `ieee80211vap` 结构还包含驱动程序填写和/或覆盖以控制某些操作的方法指针集合。这些方法是驱动程序绑定到 `IEEE80211` 层的主要方式，描述如下。

## 驱动程序附加/分离

驱动程序使用 `ieee80211_ifattach` 函数附加到 `IEEE80211` 层。驱动程序应在传递控制之前分配和设置任何设备私有数据结构。`ieee80211com` 结构必须预初始化为设置 `IEEE80211` 层所需的状态：

**`ic_ifp`** 指向物理设备 ifnet 的反向指针。

**`ic_caps`** 设备/驱动程序能力；完整描述请参见下文。

**`ic_channels`** 设备可操作的信道表。这最初由驱动程序提供，但可能通过更改监管状态的调用而更改。

**`ic_nchan`** `ic_channels` 中的条目数。

从 `ieee80211_ifattach` 返回时，驱动程序应覆盖 `ieee80211com` 结构中的默认回调函数以注册其私有例程。标有“\*”的方法必须由驱动程序提供。

**`ic_vap_create*`** 创建指定类型（操作模式）的 vap 实例。提供任何固定的 BSSID 和/或 MAC 地址。支持多 bssid 操作的驱动程序可接受请求的 BSSID 或分配自己的。

**`ic_vap_delete*`** 销毁由 `ic_vap_create` 创建的 vap 实例。

**`ic_getradiocaps`** 返回无线电的校准信道列表。默认方法返回当前信道列表（空间允许的情况下）。

**`ic_setregdomain`** 处理更改监管状态的请求。该例程可拒绝请求或限制更改（例如降低发射功率上限）。默认方法接受所有建议的更改。

**`ic_send_mgmt`** 发送 802.11 管理帧。默认方法使用 `IEEE80211` 状态构造帧并通过 `ic_raw_xmit` 方法将其传递给驱动程序。

**`ic_raw_xmit`** 发送原始 802.11 帧。默认方法丢弃帧并在控制台上生成消息。

**`ic_updateslot`** 在 802.11 IFS 时隙时间更改后更新硬件状态。无默认方法；指针可为 NULL，在这种情况下不会使用。

**`ic_update_mcast`** 为多播数据包过滤器的更改更新硬件。默认方法打印控制台消息。

**`ic_update_promisc`** 为混杂模式设置的更改更新硬件。默认方法打印控制台消息。

**`ic_newassoc`** 为关联到新 AP（在 station 模式下）或当新站点关联时（例如在 AP 模式下）更新驱动程序/设备状态。无默认方法；指针可为 NULL，在这种情况下不会使用。

**`ic_node_alloc`** 分配并初始化 `ieee80211_node` 结构。此方法不能休眠。默认方法使用 [malloc(9)](/man9/malloc.9.md) 分配清零内存。驱动程序应覆盖此方法以分配满足自身需求的扩展存储。驱动程序分配的内存必须用 `M_80211_NODE` 标记以平衡内存分配统计。

**`ic_node_free`** 回收由 `ic_node_alloc` 分配的节点存储。驱动程序应 *介入* 自身方法以清理私有状态，但必须通过此方法调用以允许 `IEEE80211` 回收其私有状态。

**`ic_node_cleanup`** 清理由 `ic_node_alloc` 创建的 `ieee80211_node` 中的状态。此操作与 `ic_node_free` 区别在于它可能在节点实际被回收之前很久被调用以清理附属状态。例如，当节点由于发送队列中的数据包持有引用而无法回收时。驱动程序通常介入 `ic_node_cleanup` 而非 `ic_node_free`。

**`ic_node_age`** 老化并可能回收与节点关联的资源。默认方法老化省电队列上的帧（在 AP 模式下）和接收重排序队列中的挂起帧（对于使用 A-MPDU 的站点）。

**`ic_node_drain`** 回收与节点关联的所有可选资源。此调用用于在资源短缺时释放资源。

**`ic_node_getrssi`** 返回指定节点的接收信号强度指示 (RSSI)，以 .5 dBm 为单位。此接口返回 `ic_node_getsignal` 返回信息的子集。默认方法计算传入 [ieee80211\_input(9)](/man9/ieee80211_input.9.md) 或 ieee80211\_input\_all(9) 的最后十个样本的过滤平均值。

**`ic_node_getsignal`** 返回站点的 RSSI 和噪声底（以 .5 dBm 为单位）。默认方法如上所述计算 RSSI；返回的噪声底是提供给 [ieee80211\_input(9)](/man9/ieee80211_input.9.md) 或 ieee80211\_input\_all(9) 的最后一个值。

**`ic_node_getmimoinfo`** 返回站点的 MIMO 无线电状态以支持 `IEEE80211_IOC_STA_INFO` ioctl 请求。默认方法不返回任何内容。

**`ic_scan_start*`** 为扫描准备驱动程序/硬件状态。此回调在可休眠上下文中完成。

**`ic_scan_end*`** 在扫描完成后恢复驱动程序/硬件状态。此回调在可休眠上下文中完成。

**`ic_set_channel*`** 使用 `ic_curchan` 设置当前无线电信道。此回调在可休眠上下文中完成。

**`ic_scan_curchan`** 开始在信道上扫描。此方法在每次信道更改后立即调用，必须启动扫描信道的工作并调度定时器以推进到扫描列表中的下一个信道。此回调在可休眠上下文中完成。默认方法处理主动扫描工作（例如发送 ProbeRequest 帧），并根据信道的最大驻留时间调度对 ieee80211\_scan\_next(9) 的调用。将扫描工作卸载到固件的驱动程序通常使用此方法触发每信道扫描活动。

**`ic_scan_mindwell`** 处理扫描时在信道上达到最小驻留时间。当一个或多个站点在信道上被发现且已达到最小驻留时间时触发此事件。此回调在可休眠上下文中完成。默认方法通知扫描机制尽快推进到下一个信道。驱动程序可使用此方法抢先工作（例如如果扫描由固件处理）或忽略请求以强制信道上的最大驻留时间。

**`ic_recv_action`** 处理接收到的 Action 帧。默认方法指向 ieee80211\_recv\_action(9)，它提供了为每个 Action 帧类设置处理程序的机制。

**`ic_send_action`** 发送 Action 帧。默认方法指向 ieee80211\_send\_action(9)，它提供了为每个 Action 帧类设置处理程序的机制。

**`ic_ampdu_enable`** 检查是否应为指定站点和 AC 启用发送 A-MPDU。默认方法根据每 vap 阈值检查每 AC 流量速率以决定是否应启用 A-MPDU。此方法还对 ADDBA 请求进行速率限制，以便在接收方资源有限时不会过于频繁地发出请求。

**`ic_addba_request`** 请求 A-MPDU 发送聚合。默认方法设置本地状态并发出 ADDBA Request Action 帧。如果驱动程序需要设置用于处理发送 A-MPDU 的私有状态，可介入此方法。

**`ic_addb_response`** 处理接收到的 ADDBA Response Action 帧，并根据需要设置资源以执行发送 A-MPDU。

**`ic_addb_stop`** 为指定站点和 AC 关闭 A-MPDU 发送流。默认方法在发送 DelBA Action 帧后回收本地状态。

**`ic_bar_response`** 处理对发送的 BAR 控制帧的响应。

**`ic_ampdu_rx_start`** 准备从指定站点接收 TID 的 A-MPDU 数据。

**`ic_ampdu_rx_stop`** 终止从指定站点接收 TID 的 A-MPDU 数据。

一旦 `IEEE80211` 层附加到驱动程序，通常还需完成两个步骤以完成工作：

* 为捕获通过设备的原始 802.11 数据包设置“radiotap 支持”。这通过调用 ieee80211\_radiotap\_attach(9) 完成。
* 执行任何最终设备设置，如启用中断。

状态通过调用 `ieee80211_ifdetach` 拆除和回收。注意此调用可能导致多次回调到驱动程序，因此应在任何关键驱动程序状态回收之前完成。从 `ieee80211_ifdetach` 返回时，所有关联的 vap 和 ifnet 结构已被回收或对用户应用程序不可访问，因此可以安全地拆除驱动程序状态而无需担心被重入。驱动程序负责在其为物理设备分配的 ifnet 上调用 if\_free(9)。

## 驱动程序能力

驱动程序/设备能力使用 `ieee80211com` 结构中的几组标志指定。一般能力由 `ic_caps` 指定。硬件加密能力由 `ic_cryptocaps` 指定。软件加密能力由 `ic_sw_cryptocaps` 指定。802.11n 能力（如果有）由 `ic_htcaps` 指定。`IEEE80211` 层通过等效字段将这些能力的子集传播到每个 vap：`iv_caps`、`iv_cryptocaps` 和 `iv_htcaps`。定义了以下一般能力：

**`IEEE80211_C_STA`** 设备能够在 station（又称 Infrastructure）模式下操作。

**`IEEE80211_C_8023ENCAP`** 设备要求为发送传递 802.3 封装的帧。默认情况下，`IEEE80211` 将所有出站帧封装为 802.11 帧（无 PLCP 头）。

**`IEEE80211_C_FF`** 设备支持 Atheros Fast-Frames。

**`IEEE80211_C_TURBOP`** 设备支持 Atheros Dynamic Turbo 模式。

**`IEEE80211_C_IBSS`** 设备能够在 adhoc/IBSS 模式下操作。

**`IEEE80211_C_PMGT`** 设备在 station 模式下支持动态电源管理（又称省电）。

**`IEEE80211_C_HOSTAP`** 设备能够在 Infrastructure 模式下作为接入点操作。

**`IEEE80211_C_AHDEMO`** 设备能够在 Adhoc Demo 模式下操作。在此模式下，设备仅用于发送/接收原始 802.11 帧。

**`IEEE80211_C_SWRETRY`** 设备支持发送帧的软件重试。

**`IEEE80211_C_TXPMGT`** 设备支持发送帧的动态发射功率更改；又称发射功率控制 (TPC)。

**`IEEE80211_C_SHSLOT`** 设备支持短时隙时间操作（用于 802.11g）。

**`IEEE80211_C_SHPREAMBLE`** 设备支持短前导码操作（用于 802.11g）。

**`IEEE80211_C_MONITOR`** 设备能够在监视器模式下操作。

**`IEEE80211_C_DFS`** 设备支持雷达检测和/或 DFS。DFS 协议支持可由 `IEEE80211` 处理，但设备必须能够检测雷达事件。

**`IEEE80211_C_MBSS`** 设备能够在 MeshBSS (MBSS) 模式下操作（如 802.11s Draft 3.0 所定义）。

**`IEEE80211_C_WPA1`** 设备支持 WPA1 操作。

**`IEEE80211_C_WPA2`** 设备支持 WPA2/802.11i 操作。

**`IEEE80211_C_BURST`** 设备支持帧突发。

**`IEEE80211_C_WME`** 设备支持 WME/WMM 操作（目前这主要是对使用 EDCF 发送和接收 QoS 帧的支持）。

**`IEEE80211_C_WDS`** 设备支持 4 地址帧的发送/接收。

**`IEEE80211_C_BGSCAN`** 设备支持后台扫描。

**`IEEE80211_C_TXFRAG`** 设备支持分片 802.11 帧的发送。

**`IEEE80211_C_TDMA`** 设备能够在 TDMA 模式下操作。

定义了以下一般加密能力。通常当设备不能硬件加速某个密码时，`IEEE80211` 会回退到软件支持。这可基于每密钥进行。`IEEE80211` 还可处理软件 `Michael` 计算与硬件 `AES` 加速的组合。

**`IEEE80211_CRYPTO_WEP`** 设备支持硬件 WEP 密码。

**`IEEE80211_CRYPTO_TKIP`** 设备支持硬件 TKIP 密码。

**`IEEE80211_CRYPTO_AES_OCB`** 设备支持硬件 AES-OCB 密码。

**`IEEE80211_CRYPTO_AES_CCM`** 设备支持硬件 AES-CCM 密码。

**`IEEE80211_CRYPTO_TKIPMIC`** 设备支持用于 TKIP 的硬件 Michael。

**`IEEE80211_CRYPTO_CKIP`** 设备支持硬件 CKIP 密码。

定义了以下一般 802.11n 能力。第一组能力完全按照 802.11n 规范中的定义。以 IEEE80211\_HTC\_AMPDU 开头的能力仅由 `IEEE80211` 层使用。

**`IEEE80211_HTCAP_CHWIDTH40`** 设备支持 20/40 信道宽度操作。

**`IEEE80211_HTCAP_SMPS_DYNAMIC`** 设备支持动态 SM 省电操作。

**`IEEE80211_HTCAP_SMPS_ENA`** 设备支持静态 SM 省电操作。

**`IEEE80211_HTCAP_GREENFIELD`** 设备支持 Greenfield 前导码。

**`IEEE80211_HTCAP_SHORTGI20`** 设备支持 20MHz 信道上的短保护间隔。

**`IEEE80211_HTCAP_SHORTGI40`** 设备支持 40MHz 信道上的短保护间隔。

**`IEEE80211_HTCAP_TXSTBC`** 设备支持发送的空时块卷积 (STBC)。

**`IEEE80211_HTCAP_RXSTBC_1STREAM`** 设备支持 STBC 接收的 1 个空间流。

**`IEEE80211_HTCAP_RXSTBC_2STREAM`** 设备支持 STBC 接收的 1-2 个空间流。

**`IEEE80211_HTCAP_RXSTBC_3STREAM`** 设备支持 STBC 接收的 1-3 个空间流。

**`IEEE80211_HTCAP_MAXAMSDU_7935`** 设备支持高达 7935 个八位字节的 A-MSDU 帧。

**`IEEE80211_HTCAP_MAXAMSDU_3839`** 设备支持高达 3839 个八位字节的 A-MSDU 帧。

**`IEEE80211_HTCAP_DSSSCCK40`** 设备支持在 40MHz 信道上使用 DSSS/CCK。

**`IEEE80211_HTCAP_PSMP`** 设备支持 PSMP。

**`IEEE80211_HTCAP_40INTOLERANT`** 设备不容忍 40MHz 宽信道使用。

**`IEEE80211_HTCAP_LSIGTXOPPROT`** 设备支持 L-SIG TXOP 保护。

**`IEEE80211_HTC_AMPDU`** 设备支持 A-MPDU 聚合。注意任何 802.11n 兼容设备必须支持 A-MPDU 接收，因此这隐含意味着支持 A-MPDU 帧的 *发送*。

**`IEEE80211_HTC_AMSDU`** 设备支持 A-MSDU 聚合。注意任何 802.11n 兼容设备必须支持 A-MSDU 接收，因此这隐含意味着支持 A-MSDU 帧的 *发送*。

**`IEEE80211_HTC_HT`** 设备支持高吞吐量 (HT) 操作。必须设置此能力才能在 `IEEE80211` 中启用 802.11n 功能。

**`IEEE80211_HTC_SMPS`** 设备支持 MIMO 省电操作。

**`IEEE80211_HTC_RIFS`** 设备支持减少帧间间隔 (RIFS)。

## 参见

`ioctl(2)`, [ieee80211\_amrr(9)](/man9/ieee80211_amrr.9.md), [ieee80211\_beacon(9)](/man9/ieee80211_beacon.9.md), [ieee80211\_bmiss(9)](/man9/ieee80211_bmiss.9.md), [ieee80211\_crypto(9)](/man9/ieee80211_crypto.9.md), [ieee80211\_ddb(9)](/man9/ieee80211_ddb.9.md), [ieee80211\_input(9)](/man9/ieee80211_input.9.md), [ieee80211\_node(9)](/man9/ieee80211_node.9.md), [ieee80211\_output(9)](/man9/ieee80211_output.9.md), [ieee80211\_proto(9)](/man9/ieee80211_proto.9.md), [ieee80211\_radiotap(9)](/man9/ieee80211_radiotap.9.md), [ieee80211\_regdomain(9)](/man9/ieee80211_regdomain.9.md), [ieee80211\_scan(9)](/man9/ieee80211_scan.9.md), [ieee80211\_vap(9)](/man9/ieee80211_vap.9.md), [ifnet(9)](/man9/ifnet.9.md), [malloc(9)](/man9/malloc.9.md)

## 历史

`IEEE80211` 系列函数首次出现于 NetBSD 1.5，后来移植到 FreeBSD 4.6。此手册页使用 NetBSD `IEEE80211` 手册页的信息更新。

## 作者

原始 NetBSD `IEEE80211` 手册页由 Bruce M. Simpson <bms@FreeBSD.org> 和 Darron Broad <darron@kewl.org> 编写。
