文章目录
在
hostapd 中,
radio 和
interface 的概念在代码结构、数据处理和逻辑控制上有明确的体现,其设计反映了无线硬件的物理特性和软件管理的灵活性。以下是它们的体现、处理方式以及数据结构设计的区别和联系:
1. 概念定义
- Radio: 代表一个物理无线设备(通常是 WiFi 芯片/适配器)。它是一个物理实体,具有以下关键属性:
- 工作在特定的频段(2.4GHz, 5GHz, 6GHz)。
- 一次只能在一个主信道(中心频率)上工作。
- 具有特定的硬件能力(支持的带宽、MIMO 流数、支持的调制编码方案等)。
- 是创建虚拟接口(VAPs)的基础。
- Interface: 代表一个逻辑上的无线接入点或站点。它是一个虚拟实体,运行在某个
radio之上。关键属性:- 有自己的 MAC 地址(BSSID)。
- 有自己的配置(SSID、认证加密方式、VLAN、ACL 等)。
- 独立处理关联/认证客户端、发送信标/探测响应、数据帧转发等。
- 一个
radio可以承载多个interface(多个 BSSID/VAP)。
2. 在代码中的体现与处理
核心数据结构
-
struct hostapd_data(通常缩写为hapd):- 代表: 一个 Interface (BSS)。
- 作用: 这是
hostapd内部最核心的结构体,包含了管理一个独立接入点(BSS)所需的所有状态和配置信息。 - 关键成员:
struct hostapd_config *iconf: 指向该接口的静态配置(从配置文件解析而来)。struct hostapd_bss_config *conf: 指向该接口的运行时配置(包含更动态的或与特定 BSS 相关的设置)。struct hostapd_iface *iface: 指向其所属的hostapd_iface结构体,这是体现interface从属于radio的关键链接。struct wpa_driver_ops *driver: 指向驱动程序操作函数表的结构体指针。struct sta_info *sta_list: 与该接口关联的客户端(STA)列表。struct ap_list *ap_list: (在 Mesh 模式下或其他场景可能有不同含义)。- 大量的状态变量:如信标间隔计数器、DTIM 计数器、各种定时器、HT/VHT/HE 操作信息等。
- 处理:
hostapd为配置文件中定义的每一个 BSS/interface 块创建一个hostapd_data实例。所有针对该特定接口的操作(如处理客户端关联请求、发送信标、处理数据帧)都通过这个结构体的上下文进行。
-
struct hostapd_iface(通常缩写为iface):- 代表: 一个 Radio 及其承载的所有 Interfaces (BSSs)。
- 作用: 管理一个物理无线设备 (
radio) 以及运行在其上的所有虚拟接口 (hostapd_data实例)。它负责radio层面的协调和共享资源管理。 - 关键成员:
struct hostapd_data **bss: 一个指向指针数组的指针。这个数组包含了运行在此iface(radio) 上的所有hostapd_data(BSS/interface) 实例。这是体现radio承载多个interface的关键数据结构。int num_bss:bss数组中的元素个数(即该 radio 上运行的 VAP 数量)。struct hostapd_config *conf: 指向包含此 radio 上所有 BSS 配置的全局配置结构。它内部包含一个struct hostapd_bss_config **bss数组,对应每个接口的配置。struct wpa_driver_ops *driver: 指向驱动程序操作函数表的结构体指针(通常与hostapd_data->driver指向同一个表)。void *drv_priv: 驱动程序为这个iface(radio) 分配的私有数据指针。- 物理层参数:
struct hostapd_hw_modes *hw_features: 支持的硬件模式列表(包含信道、频段、能力信息)。 int freq: 当前工作的主信道频率。int chan_width,int sec_chan_offset: 当前信道带宽和辅助信道偏移。enum hostapd_iface_state { ... } state:radio的状态(未初始化、初始化、扫描、配置、运行、错误等)。struct hostapd_channel_data *current_mode: 指向当前工作模式(如 802.11a/b/g/n/ac/ax)的信道数据。- 大量的状态变量和回调函数:如信道切换状态机、DFS 状态机、定时器等。
- 处理:
hostapd在初始化时,会根据配置文件或命令行参数,为每个需要管理的物理无线设备 (phyX) 创建一个hostapd_iface实例。这个实例负责初始化硬件驱动、扫描信道、设置中心频率/带宽等radio级操作,并管理其上的所有 VAP (hostapd_data)。
-
struct hostapd_config:- 代表: 一个包含一个 radio (
hostapd_iface) 及其上所有 interfaces (hostapd_data) 的完整静态配置。通常从配置文件(如hostapd.conf)解析构建。 - 关键成员:
struct hostapd_bss_config **bss: 一个指向指针数组的指针。这个数组包含了该 radio 上所有 BSS/interface 的配置 (struct hostapd_bss_config)。数组大小由num_bss指定。int num_bss:bss数组中的元素个数(即该配置对应的 radio 上定义的 VAP 数量)。char *iface: 物理接口名 (e.g.,wlan0,对应hostapd_iface)。int channel: 主信道号(配置值)。int hw_mode: 基础模式 (a/b/g)。int ieee80211n,int ieee80211ac,int ieee80211ax: HT/VHT/HE 支持开关。int vht_oper_chwidth,int he_oper_chwidth: 配置的 VHT/HE 信道带宽。- 其他 radio 级别的配置参数(如国家代码
country_code、beacon间隔beacon_int等)。
- 处理: 在启动时解析配置文件构建。
hostapd_iface实例持有指向此结构体的指针 (iface->conf)。每个hostapd_data实例通过hapd->iconf访问此全局配置,并通过hapd->conf访问其自身特定的hostapd_bss_config(该配置通常也包含在hostapd_config->bss[]数组中)。
- 代表: 一个包含一个 radio (
-
struct hostapd_bss_config:- 代表: 一个 Interface (BSS) 的特定配置。
- 关键成员:
char *iface: 虚拟接口名 (e.g.,wlan0,wlan0_0,wlan0.1或wlan0vap0,对应hostapd_data)。char *bssid: 该 BSS 的 MAC 地址 (BSSID)。char *ssid.ssid,int ssid.ssid_len: SSID 及其长度。int wpa,enum wpa_alg wpa_pairwise,enum wpa_alg wpa_group,char *wpa_passphrase: WPA 相关配置。int ieee802_1x: 802.1X 认证开关。struct hostapd_eap_user *eap_user: EAP 用户列表。char *bridge: 桥接接口名。int vlan_id: VLAN ID。- 大量其他接口特定的配置(如 MAC ACL、WPS 设置、RSN 设置、Mesh 设置等)。
- 处理: 是
hostapd_config->bss[]数组的元素。在创建hostapd_data实例时,会将其指向对应的hostapd_bss_config(hapd->conf)。
关键关系图
+-------------------------+
| hostapd_config | (全局配置,对应一个 radio 配置块及其所有 BSS 块)
|-------------------------|
| *iface = "phy0/wlan0" | --> 对应 hostapd_iface 的物理设备名
| *bss[0] | ----------+
| *bss[1] | ----------|----+
| ... | | |
| num_bss = N | | |
| channel = X | | |
| hw_mode = ... | | |
+-------------------------+ | |
| |
+-------------------------+ | |
| hostapd_bss_config [0] | <----------+ | (接口0配置)
|-------------------------| |
| *iface = "wlan0_0" | |
| *bssid = "AA:BB:..." | |
| ssid = "MyNetwork1" | |
| wpa = ... | |
| ... | |
+-------------------------+ |
|
+-------------------------+ |
| hostapd_bss_config [1] | <--------------+ (接口1配置)
|-------------------------|
| *iface = "wlan0_1" |
| *bssid = "AA:BB:..." |
| ssid = "MyNetwork2" |
| ... |
+-------------------------+
+-------------------------+
| hostapd_iface (iface) | (代表物理 radio)
|-------------------------|
| **bss | --> 指向 hostapd_data 指针数组
| num_bss = N | |
| *conf |------+ (指向上面的 hostapd_config)
| *driver | |
| *drv_priv (radio ctx) | |
| freq = ... (current) | |
| state = ... | |
| ... (radio state) | |
+-------------------------+ |
|
|
+---------------------------+---------------------+
| | |
+-----------------+ +-----------------+ +-----------------+
| hostapd_data | | hostapd_data | | hostapd_data | (代表接口/VAP)
| (hapd for BSS0) | | (hapd for BSS1) | ... | (hapd for BSSN) |
|-----------------| |-----------------| |-----------------|
| *iface |---------| (指向所属的 hostapd_iface)
| *iconf |---------| (指向所属的 hostapd_config)
| *conf |-------------+ (指向对应的 hostapd_bss_config [0])
| *driver |-------------| (通常指向与 iface->driver 相同的表)
| *drv_priv (bss ctx)| (每个接口的私有驱动上下文)
| sta_list (STA0, ...) |
| ... (BSS state) |
+-----------------+ +-----------------+ +-----------------+
关键操作流程示例
-
初始化 (
hostapd_main.c: main() -> hostapd_global_init() -> interfaces_init() -> ...):- 解析配置文件,构建
hostapd_config结构(包含所有 radio 和 interface 配置)。 - 遍历配置,为每个物理接口(
hostapd_config->iface)创建一个hostapd_iface实例 (iface)。 - 将
iface->conf指向对应的hostapd_config。 - 为
hostapd_config中定义的每个 BSS 配置 (hostapd_config->bss[i]),创建一个hostapd_data实例 (hapd)。 - 设置
hapd->iface = iface(将接口链接到其所属的 radio)。 - 设置
hapd->iconf = iface->conf(指向全局配置)。 - 设置
hapd->conf = iface->conf->bss[i](指向该接口的特定配置)。 - 将
hapd的指针添加到iface->bss数组中。 - 调用
hostapd_setup_interface(iface)初始化整个 radio 和其上的所有接口。这包括:- 打开驱动程序 (
driver->init),获取iface->drv_priv(radio 上下文)。 - 设置硬件模式、信道、带宽等
radio参数(基于iface->conf)。 - 遍历
iface->bss数组,调用hostapd_setup_bss(hapd, i == 0)初始化每个接口。i == 0表示是主接口(通常负责 beaconing 等核心管理帧)。这包括:- 设置接口的 BSSID (
driver->set_bssid)。 - 设置接口的 SSID、安全参数、WPA/RSN IE 等 (
driver->set_ssid,wpa_init等)。 - 为接口申请驱动私有上下文 (
hapd->drv_priv)。 - 注册接收帧处理回调 (
driver->set_receive_handler)。
- 设置接口的 BSSID (
- 打开驱动程序 (
- 解析配置文件,构建
-
处理接收帧 (
driver层回调 ->hostapd.c: handle_data() / hostapd_mgmt_rx()):- 驱动收到帧,通过注册的回调函数(如
handle_data,hostapd_mgmt_rx)上报给hostapd。 - 回调函数通常以
hapd(hostapd_data) 作为第一个参数,表明该帧是发给哪个接口的。 - 帧处理逻辑完全在
hostapd_data的上下文中进行(检查 BSSID、处理关联请求、处理数据帧等)。hapd提供了处理该帧所需的所有接口状态和配置。
- 驱动收到帧,通过注册的回调函数(如
-
发送帧 (
hostapd_send_*系列函数):- 调用发生在
hostapd_data(hapd) 的上下文中,指明是哪个接口要发送帧。 - 最终通过
hapd->driver->send_frame或hapd->driver->send_mgmt_frame发送,驱动程序使用hapd->drv_priv来区分不同的接口。
- 调用发生在
-
Radio 级操作 (信道切换、DFS、扫描):
- 这些操作由
hostapd_iface(iface) 结构协调管理。 - 例如,触发信道切换 (
hostapd_switch_channel): 操作对象是iface。iface会通过驱动接口 (iface->driver->set_channel) 设置整个radio的新信道。然后可能需要通知或协调其上的所有hostapd_data实例(接口)关于信道变更(例如更新信标中的 HT/VHT/HE 操作元素)。
- 这些操作由
3. 数据结构设计上的区别与联系
区别 (Differentiation)
| 特征 | Radio (hostapd_iface) | Interface (hostapd_data) |
|---|---|---|
| 代表实体 | 物理设备 (WiFi 芯片/适配器) | 逻辑实体 (虚拟接入点 BSS / VAP) |
| 核心结构体 | struct hostapd_iface | struct hostapd_data |
| 配置关联 | 持有 hostapd_config* (包含所有接口配置和 radio 配置) | 持有 hostapd_bss_config* (自身特定配置) 和 hostapd_config* (全局配置) |
| 状态管理 | 物理层状态 (信道、带宽、模式、DFS状态、radio状态机) | BSS层状态 (关联的 STA 列表、信标计数器、安全关联状态) |
| 硬件操作 | 驱动初始化/去初始化、设置信道/带宽/模式、扫描 | 设置 BSSID/SSID、处理帧收发、管理 STA 关联/认证 |
| 数量关系 | 一个物理设备对应一个 | 一个物理设备可以对应多个 |
| 关键数据结构 | **bss (指向 hostapd_data* 数组), num_bss | *iface (指向所属的 hostapd_iface), sta_list |
| 驱动上下文 | drv_priv (Radio 级别的驱动私有数据) | drv_priv (BSS/Interface 级别的驱动私有数据) |
联系 (Integration)
- 层级关系:
hostapd_data(Interface) 从属于hostapd_iface(Radio)。这是通过hostapd_data->iface指针实现的。 - 配置绑定:
hostapd_config结构同时包含了 Radio 级别的配置和其上所有 Interfaces 的配置 (hostapd_bss_config数组)。hostapd_iface->conf指向这个全局配置,hostapd_data->iconf也指向它(访问全局和 radio 设置),而hostapd_data->conf则指向其自身在数组中的特定配置项。 - 聚合关系:
hostapd_iface通过bss指针数组聚合了其管理的所有hostapd_data实例。这使得 Radio 能协调其上的所有接口(如在信道切换时通知所有接口)。 - 共享硬件: 所有运行在同一
hostapd_iface上的hostapd_data实例共享同一个物理radio硬件资源(相同的信道、带宽、硬件能力)。hostapd_iface负责仲裁和管理对这些共享资源的访问。 - 驱动交互: 虽然
hostapd_data包含driver指针(通常与hostapd_iface->driver相同),但 Radio 级操作(set_channel)通过hostapd_iface的驱动上下文 (drv_priv) 进行,而 Interface 级操作(set_bssid,send_frame)则通过hostapd_data的驱动上下文 (drv_priv) 进行。驱动需要区分这两种上下文。 - 状态协同: Radio 的状态(如信道)直接影响其上所有接口的操作。接口的状态(如关联的客户端)是独立的。当 Radio 状态变化(如信道切换完成)时,可能需要更新所有接口的状态(如信标内容)。
总结
hostapd 通过 hostapd_iface 和 hostapd_data 这两个核心结构体清晰地分离了 Radio (物理设备) 和 Interface (逻辑服务集/VAP) 的概念:
hostapd_iface管理物理硬件的状态、共享资源(信道)以及与驱动进行 Radio 级别的交互。它像一个容器,管理一组相关的hostapd_data。hostapd_data管理一个独立无线接入点(BSS)的逻辑状态、配置、关联的客户端以及与驱动进行该特定 BSS 的帧交互。
数据结构 hostapd_config 和 hostapd_bss_config 进一步将配置分层,分别对应 Radio+All-BSSes 和单个 BSS。hostapd_iface->bss 数组和 hostapd_data->iface 指针是维系两者层级和聚合关系的关键纽带。这种设计有效地实现了在一个物理 Radio 上运行多个逻辑接口的功能,同时保证了必要的资源协调。
3855

被折叠的 条评论
为什么被折叠?



