Linux Wireless之WIFI监管域处理流程

1. 概述

Linux无线监管域(Regulatory Domain)是cfg80211无线子系统中的核心组件,负责管理无线设备的频段、功率、信道使用规则等参数。

前面有简单介绍了Linux下的WIFI无线监管域:

今天来看看整个监管域处理流程(基于内核v7.1.0-rc6)。


2. 机制演进

Linux无线监管域机制经历了三个主要阶段演进:

  1. CRDA用户空间方案 (早期)
    • 内核通过udev事件通知用户空间需要监管域
    • CRDA守护进程响应请求,通过nl80211发送监管规则
    • 需要udev规则:KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
  2. 内置数据库方案 (中期)
    • 引入 regulatory.db 固件文件,编译时可链接到内核
    • 通过 request_firmware_nowait() 异步加载
    • 支持签名验证(load_builtin_regdb_keys()
    • 保留CRDA作为后备方案(CONFIG_CFG80211_CRDA_SUPPORT
  3. 自监管设备方案 (现代)
    • 引入 REGULATORY_WIPHY_SELF_MANAGED 标志
    • 设备固件/驱动自行管理监管域,忽略外部提示
    • 通过 regulatory_set_wiphy_regd() 接口设置
    • 不共享监管信息,独立于系统其他设备

3. 整体架构图

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           Linux无线监管域架构                                    │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐    ┌──────────────┐  │
│  │   用户空间    │    │   CRDA/      │    │   regulatory │    │   内置数据库  │  │
│  │   iw/ip      │    │   regdb      │    │   .db文件    │    │              │  │
│  └──────┬───────┘    └──────┬───────┘    └──────┬───────┘    └──────┬───────┘  │
│         │                   │                   │                   │          │
│         ▼                   ▼                   ▼                   ▼          │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                          nl80211 接口层                                  │   │
│  │  NL80211_CMD_SET_REG / NL80211_CMD_REQ_SET_REG / NL80211_CMD_GET_REG   │   │
│  └────────────────────────────────┬────────────────────────────────────────┘   │
│                                   │                                            │
│                                   ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                        监管域核心 (reg.c)                               │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │   │
│  │  │ 请求队列    │  │ 提示处理    │  │ 域交集算法  │  │ 数据库查询  │   │   │
│  │  │ reg_requests│  │ reg_process │  │ intersect   │  │ query_regdb │   │   │
│  │  │ _list       │  │ _hint       │  │             │  │             │   │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘   │   │
│  └────────────────────────────────┬────────────────────────────────────────┘   │
│                                   │                                            │
│                                   ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                       监管域应用层                                       │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │   │
│  │  │ wiphy更新   │  │ 信道处理    │  │ 规则应用    │  │ 通知机制    │   │   │
│  │  │ update_all  │  │ handle_     │  │ map_regdom  │  │ nl80211_    │   │   │
│  │  │ _wiphy      │  │ channel     │  │ _flags      │  │ send_event  │   │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘   │   │
│  └────────────────────────────────┬────────────────────────────────────────┘   │
│                                   │                                            │
│                                   ▼                                            │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │                       无线驱动层                                        │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │   │
│  │  │ 驱动提示    │  │ 自监管设备  │  │ 信标发现    │  │ DFS处理     │   │   │
│  │  │ regulatory  │  │ wiphy_self  │  │ found_      │  │ radar_      │   │   │
│  │  │ _hint       │  │ _managed    │  │ beacon      │  │ detected    │   │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘  └─────────────┘   │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

4. 监管域初始化流程

4.1 初始化流程图

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           监管域初始化流程                                       │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    cfg80211_init()                                                              │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────┐                                                       │
│    │ regulatory_init()  │ reg.c:4328                                            │
│    └─────────┬──────────┘                                                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 1. 创建虚拟设备 reg_fdev                           │                       │
│    │    faux_device_create("regulatory", NULL, NULL)    │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 2. 设置初始世界监管域                               │                       │
│    │    rcu_assign_pointer(cfg80211_regdomain,          │                       │
│    │                       cfg80211_world_regdom)       │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 3. 初始化用户alpha2为 '97' (未配置)                │                       │
│    │    user_alpha2[0] = '9'; user_alpha2[1] = '7'     │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4. regulatory_init_db()                            │                       │
│    │    late_initcall (内核模块) 或直接调用 (可加载模块) │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4.1 load_builtin_regdb_keys()                      │                       │
│    │      加载内置签名密钥                               │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4.2 regulatory_hint_core("00")                     │                       │
│    │      发送核心监管提示 (世界监管域)                  │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4.3 检查模块参数 ieee80211_regdom                  │                       │
│    │      如果非"00",调用 regulatory_hint_user()       │                       │
│    └────────────────────────────────────────────────────┘                       │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

4.2 世界监管域定义

// reg.c:233
static const struct ieee80211_regdomain world_regdom = {
    .n_reg_rules = 8,
    .alpha2 = "00",
    .reg_rules = {
        /* 2.4GHz: 信道 1-11 */
        REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
        /* 2.4GHz: 信道 12-13 */
        REG_RULE(2467-10, 2472+10, 20, 6, 20, NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW),
        /* 2.4GHz: 信道 14 (仅日本) */
        REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM),
        /* 5GHz: 信道 36-48 */
        REG_RULE(5180-10, 5240+10, 80, 6, 20, NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW),
        /* 5GHz: 信道 52-64 (DFS) */
        REG_RULE(5260-10, 5320+10, 80, 6, 20, NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW | NL80211_RRF_DFS),
        /* 5GHz: 信道 100-144 (DFS) */
        REG_RULE(5500-10, 5720+10, 160, 6, 20, NL80211_RRF_NO_IR | NL80211_RRF_DFS),
        /* 5GHz: 信道 149-165 */
        REG_RULE(5745-10, 5825+10, 80, 6, 20, NL80211_RRF_NO_IR),
        /* 60GHz: 信道 1-3 */
        REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
    }
};

5. 监管域请求处理流程

5.1 请求来源与处理流程图

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           监管请求处理流程                                       │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│   │   用户空间   │  │   驱动      │  │   AP国家IE  │  │   核心      │          │
│   │   iw set    │  │   regulatory│  │   country   │  │   regulatory│          │
│   │   reg       │  │   _hint()   │  │   _ie       │  │   _hint_    │          │
│   │   country   │  │             │  │             │  │   core()    │          │
│   └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘          │
│          │                │                │                │                  │
│          ▼                ▼                ▼                ▼                  │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    regulatory_hint_*() 函数族                         │     │
│   │  - regulatory_hint_user()      reg.c:3244                            │     │
│   │  - regulatory_hint()           reg.c:3316                            │     │
│   │  - regulatory_hint_country_ie() reg.c:3344                           │     │
│   │  - regulatory_hint_core()      reg.c:3225                            │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    queue_regulatory_request()   reg.c:3209           │     │
│   │  1. 转换alpha2为大写                                                 │     │
│   │  2. 加入 reg_requests_list 链表                                      │     │
│   │  3. 调度 reg_work 工作队列                                           │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    reg_todo() 工作队列处理    reg.c:3200              │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │              reg_process_pending_hints()   reg.c:3084                 │     │
│   │  1. 检查 last_request->processed 状态                               │     │
│   │  2. 从 reg_requests_list 取出第一个请求                              │     │
│   │  3. 调用 reg_process_hint() 处理                                     │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    reg_process_hint()   reg.c:3013                    │     │
│   │                                                                      │     │
│   │   switch(initiator) {                                                │     │
│   │   ┌─────────────────────────────────────────────────────────────┐   │     │
│   │   │ BY_CORE ──► reg_process_hint_core()     reg.c:2675         │   │     │
│   │   │ BY_USER ──► reg_process_hint_user()     reg.c:2734         │   │     │
│   │   │ BY_DRIVER ► reg_process_hint_driver()   reg.c:2790         │   │     │
│   │   │ BY_COUNTRY ►reg_process_hint_country_ie() reg.c:2894       │   │     │
│   │   └─────────────────────────────────────────────────────────────┘   │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    reg_query_database()   reg.c:1111                  │     │
│   │  1. query_regdb_file() - 查询内置数据库                               │     │
│   │  2. call_crda() - 调用CRDA用户空间守护进程                           │     │
│   └────────────────────────────────────┬─────────────────────────────────┘     │
│                                        │                                       │
│                                        ▼                                       │
│   ┌──────────────────────────────────────────────────────────────────────┐     │
│   │                    set_regdom()   reg.c:3942                          │     │
│   │  设置监管域并应用到所有wiphy                                          │     │
│   └──────────────────────────────────────────────────────────────────────┘     │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

5.2 请求处理结果枚举

// reg.c:73
enum reg_request_treatment {
    REG_REQ_OK,           // 继续处理请求
    REG_REQ_IGNORE,       // 忽略请求
    REG_REQ_INTERSECT,    // 需要与当前域交集
    REG_REQ_ALREADY_SET,  // 已设置相同域,无需处理
};

6. 监管域设置流程

6.1 set_regdom() 主流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           set_regdom() 流程   reg.c:3942                         │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    set_regdom(rd, regd_src)                                                     │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 1. 验证请求有效性                                   │                       │
│    │    - IS_ERR_OR_NULL(rd)                            │                       │
│    │    - reg_is_valid_request(rd->alpha2)              │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 2. 重置CRDA超时 (如果是CRDA来源)                   │                       │
│    │    if (regd_src == REGD_SOURCE_CRDA)               │                       │
│    │        reset_crda_timeouts()                       │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 3. 根据发起者类型调用对应设置函数                                       │  │
│    │                                                                        │  │
│    │    switch(lr->initiator) {                                             │  │
│    │    ┌──────────────────────────────────────────────────────────────┐    │  │
│    │    │ BY_CORE ──────────► reg_set_rd_core()      reg.c:3802       │    │  │
│    │    │ BY_USER ──────────► reg_set_rd_user()      reg.c:3810       │    │  │
│    │    │ BY_DRIVER ────────► reg_set_rd_driver()    reg.c:3841       │    │  │
│    │    │ BY_COUNTRY_IE ────► reg_set_rd_country_ie() reg.c:3904      │    │  │
│    │    └──────────────────────────────────────────────────────────────┘    │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4. 处理错误                                        │                       │
│    │    -EALREADY: 标记请求已处理                        │                       │
│    │    其他错误: restore_regulatory_settings() 恢复    │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 5. 更新所有wiphy                                   │                       │
│    │    update_all_wiphy_regulatory(lr->initiator)      │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 6. 后续处理                                        │                       │
│    │    - print_regdomain() 打印监管域信息               │                       │
│    │    - nl80211_send_reg_change_event() 发送事件      │                       │
│    │    - reg_set_request_processed() 标记已处理        │                       │
│    └────────────────────────────────────────────────────┘                       │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

6.2 各类型设置函数对比

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         各类型设置函数对比                                       │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_set_rd_core()   reg.c:3802                                          │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │  条件: 必须是世界监管域 (alpha2 == "00")                                │   │
│  │  操作: update_world_regdomain(rd)                                       │   │
│  │  结果: 更新世界监管域指针                                               │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_set_rd_user()   reg.c:3810                                          │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │  条件: 监管域必须有效                                                   │   │
│  │  操作:                                                                  │   │
│  │    if (user_request->intersect) {                                       │   │
│  │        intersected_rd = regdom_intersect(rd, get_cfg80211_regdom())     │   │
│  │        reset_regdomains(false, intersected_rd)                          │   │
│  │    } else {                                                             │   │
│  │        reset_regdomains(false, rd)                                      │   │
│  │    }                                                                    │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_set_rd_driver()   reg.c:3841                                        │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │  条件: 不能是世界监管域,监管域必须有效                                 │   │
│  │  操作:                                                                  │   │
│  │    if (!driver_request->intersect) {                                    │   │
│  │        // 直接设置到wiphy和全局                                         │   │
│  │        rcu_assign_pointer(request_wiphy->regd, regd)                    │   │
│  │        reset_regdomains(false, rd)                                      │   │
│  │    } else {                                                             │   │
│  │        // 交集处理                                                      │   │
│  │        intersected_rd = regdom_intersect(rd, get_cfg80211_regdom())     │   │
│  │        rcu_assign_pointer(request_wiphy->regd, rd)  // 保存原始域      │   │
│  │        reset_regdomains(false, intersected_rd)                          │   │
│  │    }                                                                    │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_set_rd_country_ie()   reg.c:3904                                    │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │  条件: alpha2有效,监管域有效,不支持交集                               │   │
│  │  操作: reset_regdomains(false, rd)                                      │   │
│  │  结果: 直接设置监管域                                                   │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

7. 监管域应用流程

7.1 应用到wiphy的流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         监管域应用流程                                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    update_all_wiphy_regulatory(initiator)   reg.c:2515                          │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │  遍历所有注册的wiphy                                                    │  │
│    │  for_each_rdev(rdev) {                                                 │  │
│    │      wiphy = &rdev->wiphy;                                             │  │
│    │      wiphy_update_regulatory(wiphy, initiator);                        │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │  wiphy_update_regulatory()   reg.c:2485                                │  │
│    │                                                                        │  │
│    │  1. ignore_reg_update() 检查是否需要忽略                               │  │
│    │  2. 遍历所有频段: for (band = 0; band < NUM_NL80211_BANDS; band++)    │  │
│    │  3. handle_band(wiphy, initiator, wiphy->bands[band])                  │  │
│    │  4. reg_process_beacons() 处理信标提示                                 │  │
│    │  5. reg_process_ht_flags() 处理HT标志                                  │  │
│    │  6. reg_call_notifier() 调用驱动通知函数                               │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │  handle_band()   reg.c:2018                                            │  │
│    │                                                                        │  │
│    │  for (i = 0; i < sband->n_channels; i++)                              │  │
│    │      handle_channel(wiphy, initiator, &sband->channels[i]);            │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │  handle_channel()   reg.c:1934                                         │  │
│    │                                                                        │  │
│    │  1. 获取信道频率 orig_chan_freq = ieee80211_channel_to_khz(chan)       │  │
│    │  2. 查询规则: rrule = freq_reg_info(wiphy, orig_chan_freq)            │  │
│    │                                                                        │  │
│    │  if (IS_ERR(rrule)) {                                                  │  │
│    │      // 检查相邻规则 (±20MHz)                                          │  │
│    │      rrule1 = freq_reg_info(wiphy, orig_chan_freq - 20MHz)            │  │
│    │      rrule2 = freq_reg_info(wiphy, orig_chan_freq + 20MHz)            │  │
│    │      if (找到相邻规则)                                                 │  │
│    │          handle_channel_adjacent_rules()                               │  │
│    │      else                                                              │  │
│    │          禁用信道                                                      │  │
│    │  } else {                                                              │  │
│    │      handle_channel_single_rule()                                      │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

7.2 信道处理详细流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                       handle_channel_single_rule() 流程                          │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    handle_channel_single_rule(wiphy, initiator, chan, flags,                     │
│                               lr, request_wiphy, reg_rule)                      │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 1. 计算带宽标志                                     │                       │
│    │    bw_flags = reg_rule_to_chan_bw_flags(regd,      │                       │
│    │                                         reg_rule,  │                       │
│    │                                         chan)       │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 2. 判断是否为严格监管设备 (REGULATORY_STRICT_REG)                      │  │
│    │                                                                        │  │
│    │  if (lr->initiator == BY_DRIVER &&                                     │  │
│    │      request_wiphy == wiphy &&                                         │  │
│    │      request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {        │  │
│    │      // 设置原始值 (不会被后续请求覆盖)                                │  │
│    │      chan->orig_flags = map_regdom_flags(reg_rule->flags) | bw_flags   │  │
│    │      chan->orig_mag = MBI_TO_DBI(power_rule->max_antenna_gain)         │  │
│    │      chan->orig_mpwr = MBM_TO_DBM(power_rule->max_eirp)               │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 3. 设置信道属性                                                        │  │
│    │                                                                        │  │
│    │  chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags)   │  │
│    │  chan->max_antenna_gain = min(chan->orig_mag,                          │  │
│    │                              MBI_TO_DBI(power_rule->max_antenna_gain))│  │
│    │  chan->max_reg_power = MBM_TO_DBM(power_rule->max_eirp)               │  │
│    │                                                                        │  │
│    │  // 设置最大功率                                                      │  │
│    │  if (chan->orig_mpwr)                                                 │  │
│    │      chan->max_power = min(chan->orig_mpwr, chan->max_reg_power)      │  │
│    │  else                                                                  │  │
│    │      chan->max_power = chan->max_reg_power                             │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 4. DFS处理                                                             │  │
│    │                                                                        │  │
│    │  if (chan->flags & IEEE80211_CHAN_RADAR) {                             │  │
│    │      chan->dfs_cac_ms = reg_rule->dfs_cac_ms ?                         │  │
│    │                         reg_rule->dfs_cac_ms :                         │  │
│    │                         IEEE80211_DFS_MIN_CAC_TIME_MS                  │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

7.3 监管规则查询流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         freq_reg_info() 查询流程                                 │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    freq_reg_info(wiphy, center_freq)   reg.c:1656                               │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 1. 确定最小带宽                                     │                       │
│    │    min_bw = (center_freq < 1GHz) ? 1kHz : 20kHz    │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 2. 调用 __freq_reg_info()                          │                       │
│    │    reg.c:1638                                       │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 3. 获取监管域                                       │                       │
│    │    regd = reg_get_regdomain(wiphy)                 │                       │
│    │                                                    │                       │
│    │    // 优先级:                                      │                       │
│    │    // 1. 国家IE或用户请求 -> 全局监管域            │                       │
│    │    // 2. 其他 -> wiphy->regd (驱动设置)            │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 4. 尝试不同带宽                                     │                       │
│    │    static const u32 bws[] = {0,1,2,4,5,8,10,16,20} │                       │
│    │                                                    │                       │
│    │    for (i = 8; i >= 0; i--) {                      │                       │
│    │        bw = MHZ_TO_KHZ(bws[i])                    │                       │
│    │        if (bw < min_bw) break                      │                       │
│    │        reg_rule = freq_reg_info_regd(center_freq,  │                       │
│    │                                      regd, bw)     │                       │
│    │        if (!IS_ERR(reg_rule)) return reg_rule      │                       │
│    │    }                                                │                       │
│    └─────────┬──────────────────────────────────────────┘                       │
│              │                                                                  │
│              ▼                                                                  │
│    ┌────────────────────────────────────────────────────┐                       │
│    │ 5. freq_reg_info_regd() 匹配逻辑                   │                       │
│    │    reg.c:1600                                       │                       │
│    │                                                    │                       │
│    │    for (i = 0; i < regd->n_reg_rules; i++) {      │                       │
│    │        rr = &regd->reg_rules[i]                    │                       │
│    │        fr = &rr->freq_range                        │                       │
│    │        if (freq_in_rule_band(fr, center_freq) &&   │                       │
│    │            cfg80211_does_bw_fit_range(fr, center,   │                       │
│    │                                       bw))         │                       │
│    │            return rr                                │                       │
│    │    }                                                │                       │
│    └────────────────────────────────────────────────────┘                       │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

8. 监管域交集算法

监管域交集(Regulatory Domain Intersection) 是一个极其核心的安全机制。用一句话概括:当系统同时收到多个不同来源的监管域规则时,最终生效的规则是这些规则中“最严格”的那一个。 这在逻辑上等同于取所有允许发射的信道、功率和带宽的数学交集

8.1 交集计算流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         监管域交集算法                                            │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    regdom_intersect(rd1, rd2)   reg.c:1487                                      │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 1. 计算交集规则数量                                                     │  │
│    │                                                                        │  │
│    │  for (x = 0; x < rd1->n_reg_rules; x++) {                             │  │
│    │      for (y = 0; y < rd2->n_reg_rules; y++) {                         │  │
│    │          if (!reg_rules_intersect(rd1, rd2, rule1, rule2, &tmp))       │  │
│    │              num_rules++                                               │  │
│    │      }                                                                 │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 2. 分配结果监管域                                                       │  │
│    │    rd = kzalloc_flex(*rd, reg_rules, num_rules)                        │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 3. 计算并添加交集规则                                                   │  │
│    │                                                                        │  │
│    │  for (x = 0; x < rd1->n_reg_rules; x++) {                             │  │
│    │      for (y = 0; y < rd2->n_reg_rules; y++) {                         │  │
│    │          r = reg_rules_intersect(rd1, rd2, rule1, rule2, &tmp)        │  │
│    │          if (!r)                                                       │  │
│    │              add_rule(&tmp, rd->reg_rules, &rd->n_reg_rules)          │  │
│    │      }                                                                 │  │
│    │  }                                                                     │  │
│    └────────────────────────────────────┬───────────────────────────────────┘  │
│                                         │                                      │
│                                         ▼                                      │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 4. 设置结果属性                                                         │  │
│    │    rd->alpha2 = "98"  // 交集标识                                      │  │
│    │    rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,          │  │
│    │                                              rd2->dfs_region)          │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

8.2 规则交集计算

┌─────────────────────────────────────────────────────────────────────────────────┐
│                       reg_rules_intersect() 计算逻辑                             │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│    reg_rules_intersect(rd1, rd2, rule1, rule2, intersected_rule)                │
│         │                                                                       │
│         ▼                                                                       │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 频率范围交集                                                            │  │
│    │ ─────────────────────────────────────────────────────────────────────  │  │
│    │ intersected_rule->freq_range.start_freq_khz =                          │  │
│    │     max(rule1->freq_range.start_freq_khz,                              │  │
│    │         rule2->freq_range.start_freq_khz)                              │  │
│    │                                                                        │  │
│    │ intersected_rule->freq_range.end_freq_khz =                            │  │
│    │     min(rule1->freq_range.end_freq_khz,                                │  │
│    │         rule2->freq_range.end_freq_khz)                                │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 带宽限制                                                                │  │
│    │ ─────────────────────────────────────────────────────────────────────  │  │
│    │ // 如果有AUTO_BW标志,计算最大带宽                                     │  │
│    │ if (rule1->flags & NL80211_RRF_AUTO_BW)                               │  │
│    │     max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1)                │  │
│    │                                                                        │  │
│    │ intersected_rule->freq_range.max_bandwidth_khz =                       │  │
│    │     min(max_bandwidth1, max_bandwidth2)                                │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 标志位处理                                                              │  │
│    │ ─────────────────────────────────────────────────────────────────────  │  │
│    │ // 取并集                                                              │  │
│    │ intersected_rule->flags = rule1->flags | rule2->flags                 │  │
│    │                                                                        │  │
│    │ // AUTO_BW特殊处理                                                    │  │
│    │ if (both have AUTO_BW)                                                │  │
│    │     keep AUTO_BW                                                      │  │
│    │ else                                                                   │  │
│    │     remove AUTO_BW                                                    │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ 功率规则                                                                │  │
│    │ ─────────────────────────────────────────────────────────────────────  │  │
│    │ // 取较小值 (更严格)                                                   │  │
│    │ intersected_rule->power_rule.max_eirp =                                │  │
│    │     min(rule1->power_rule.max_eirp, rule2->power_rule.max_eirp)       │  │
│    │                                                                        │  │
│    │ intersected_rule->power_rule.max_antenna_gain =                        │  │
│    │     min(rule1->power_rule.max_antenna_gain,                            │  │
│    │         rule2->power_rule.max_antenna_gain)                            │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│    ┌────────────────────────────────────────────────────────────────────────┐  │
│    │ DFS CAC时间                                                             │  │
│    │ ─────────────────────────────────────────────────────────────────────  │  │
│    │ // 取较大值 (更保守)                                                   │  │
│    │ intersected_rule->dfs_cac_ms =                                         │  │
│    │     max(rule1->dfs_cac_ms, rule2->dfs_cac_ms)                         │  │
│    └────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

9. 用户空间接口

9.1 nl80211命令接口

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         nl80211 监管域相关命令                                    │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ NL80211_CMD_GET_REG                                                      │   │
│  │ 处理函数: nl80211_get_reg_do / nl80211_get_reg_dump                      │   │
│  │ 功能: 获取当前监管域信息                                                 │   │
│  │ 权限: 普通用户可访问                                                     │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ NL80211_CMD_SET_REG (需要 CONFIG_CFG80211_CRDA_SUPPORT)                 │   │
│  │ 处理函数: nl80211_set_reg()   nl80211.c:10452                            │   │
│  │ 功能: CRDA设置监管域                                                     │   │
│  │ 权限: GENL_ADMIN_PERM (需要CAP_NET_ADMIN)                               │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 流程:                                                                    │   │
│  │  1. 解析 NL80211_ATTR_REG_ALPHA2 (国家代码)                             │   │
│  │  2. 解析 NL80211_ATTR_REG_RULES (监管规则)                              │   │
│  │  3. 可选: 解析 NL80211_ATTR_DFS_REGION (DFS区域)                        │   │
│  │  4. 构建 ieee80211_regdomain 结构                                       │   │
│  │  5. 调用 set_regdom(rd, REGD_SOURCE_CRDA)                               │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ NL80211_CMD_REQ_SET_REG                                                  │   │
│  │ 处理函数: nl80211_req_set_reg()   nl80211.c:9725                         │   │
│  │ 功能: 用户请求设置监管域                                                 │   │
│  │ 权限: GENL_ADMIN_PERM (需要CAP_NET_ADMIN)                               │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 支持的提示类型:                                                          │   │
│  │  ┌───────────────────────────────────────────────────────────────────┐ │   │
│  │  │ NL80211_USER_REG_HINT_USER                                        │ │   │
│  │  │   - 需要 NL80211_ATTR_REG_ALPHA2 属性                             │ │   │
│  │  │   - 调用 regulatory_hint_user(alpha2, HINT_USER)                  │ │   │
│  │  ├───────────────────────────────────────────────────────────────────┤ │   │
│  │  │ NL80211_USER_REG_HINT_CELL_BASE                                   │ │   │
│  │  │   - 需要 NL80211_ATTR_REG_ALPHA2 属性                             │ │   │
│  │  │   - 调用 regulatory_hint_user(alpha2, HINT_CELL_BASE)             │ │   │
│  │  ├───────────────────────────────────────────────────────────────────┤ │   │
│  │  │ NL80211_USER_REG_HINT_INDOOR                                      │ │   │
│  │  │   - 可选 NL80211_ATTR_REG_INDOOR 属性                             │ │   │
│  │  │   - 可选 NL80211_ATTR_SOCKET_OWNER 属性                           │ │   │
│  │  │   - 调用 regulatory_hint_indoor(is_indoor, portid)                │ │   │
│  │  └───────────────────────────────────────────────────────────────────┘ │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ NL80211_CMD_RELOAD_REGDB                                                 │   │
│  │ 处理函数: nl80211_reload_regdb()   nl80211.c:9769                        │   │
│  │ 功能: 重新加载监管数据库                                                 │   │
│  │ 权限: GENL_ADMIN_PERM (需要CAP_NET_ADMIN)                               │   │
│  │ 调用: reg_reload_regdb()   reg.c:1059                                    │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

9.2 用户空间工具使用示例

# 1. 获取当前监管域
iw reg get

# 2. 设置国家代码 (用户提示)
iw reg set US

# 3. 设置室内环境
iw reg set indoor

# 4. 查看监管规则
iw reg get | grep -A 5 "country"

# 5. 使用CRDA (传统方式)
crda

10. 工作队列机制

10.1 工作队列架构

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           工作队列机制                                            │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 主工作队列: reg_work                                                     │   │
│  │ 声明: static DECLARE_WORK(reg_work, reg_todo);  reg.c:230               │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 处理函数: reg_todo()   reg.c:3200                                        │   │
│  │                                                                        │   │
│  │ static void reg_todo(struct work_struct *work)                          │   │
│  │ {                                                                       │   │
│  │     rtnl_lock();                                                        │   │
│  │     reg_process_pending_hints();      // 处理待处理提示                 │   │
│  │     reg_process_pending_beacon_hints(); // 处理待处理信标               │   │
│  │     reg_process_self_managed_hints(); // 处理自监管提示                 │   │
│  │     rtnl_unlock();                                                      │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 通道检查工作: reg_check_chans                                            │   │
│  │ 声明: static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);│  │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 处理函数: reg_check_chans_work()   reg.c:2461                            │   │
│  │                                                                        │   │
│  │ // 验证活动接口是否在合法信道上                                          │   │
│  │ static void reg_check_chans_work(struct work_struct *work)              │   │
│  │ {                                                                       │   │
│  │     rtnl_lock();                                                        │   │
│  │     for_each_rdev(rdev)                                                 │   │
│  │         reg_leave_invalid_chans(&rdev->wiphy);                          │   │
│  │     rtnl_unlock();                                                      │   │
│  │ }                                                                       │   │
│  │                                                                        │   │
│  │ // 调度延迟 (60秒宽限期)                                                │   │
│  │ void reg_check_channels(void)                                           │   │
│  │ {                                                                       │   │
│  │     mod_delayed_work(system_power_efficient_wq, &reg_check_chans,      │   │
│  │                      msecs_to_jiffies(REG_ENFORCE_GRACE_MS));           │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 数据库应用工作: reg_regdb_work                                           │   │
│  │ 声明: static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);  reg.c:495  │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 处理函数: reg_regdb_apply()   reg.c:474                                  │   │
│  │                                                                        │   │
│  │ // 从队列中取出监管域并应用                                              │   │
│  │ static void reg_regdb_apply(struct work_struct *work)                   │   │
│  │ {                                                                       │   │
│  │     rtnl_lock();                                                        │   │
│  │     while (!list_empty(&reg_regdb_apply_list)) {                        │   │
│  │         request = list_first_entry(...);                                 │   │
│  │         list_del(&request->list);                                       │   │
│  │         set_regdom(request->regdom, REGD_SOURCE_INTERNAL_DB);           │   │
│  │         kfree(request);                                                  │   │
│  │     }                                                                    │   │
│  │     rtnl_unlock();                                                      │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ CRDA超时工作: crda_timeout (需要 CONFIG_CFG80211_CRDA_SUPPORT)           │   │
│  │ 声明: static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work);     │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ 处理函数: crda_timeout_work()   reg.c:526                                │   │
│  │                                                                        │   │
│  │ // CRDA响应超时处理                                                      │   │
│  │ static void crda_timeout_work(struct work_struct *work)                 │   │
│  │ {                                                                       │   │
│  │     rtnl_lock();                                                        │   │
│  │     reg_crda_timeouts++;                                                │   │
│  │     restore_regulatory_settings(true, false);                           │   │
│  │     rtnl_unlock();                                                      │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

11. 自监管设备支持

普通无线设备的射频合规由 Linux 内核“中央集权”管理,而自监管设备则自带“法务部”,由硬件或固件自己管理射频合规,Linux 内核放弃干预,只负责被动记录。

11.1 自监管设备流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                       自监管设备 (WIPHY_SELF_MANAGED) 流程                        │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 特点:                                                                    │   │
│  │  - 忽略所有非本设备的监管提示                                            │   │
│  │  - 不使用信标提示和国家IE                                                │   │
│  │  - 不与其他设备共享监管信息                                              │   │
│  │  - 自动设置 REGULATORY_DISABLE_BEACON_HINTS | REGULATORY_COUNTRY_IE_IGNORE │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 设置接口: regulatory_set_wiphy_regd()   reg.c:4050                       │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ int regulatory_set_wiphy_regd(struct wiphy *wiphy,                       │   │
│  │                               struct ieee80211_regdomain *rd)            │   │
│  │ {                                                                       │   │
│  │     // 1. 验证自监管标志                                                 │   │
│  │     if (!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED))     │   │
│  │         return -EPERM;                                                   │   │
│  │                                                                         │   │
│  │     // 2. 验证监管域有效性                                               │   │
│  │     if (!is_valid_rd(rd)) return -EINVAL;                               │   │
│  │                                                                         │   │
│  │     // 3. 复制监管域                                                     │   │
│  │     regd = reg_copy_regd(rd);                                           │   │
│  │                                                                         │   │
│  │     // 4. 保存到rdev->requested_regd                                    │   │
│  │     spin_lock(&reg_requests_lock);                                      │   │
│  │     prev_regd = rdev->requested_regd;                                   │   │
│  │     rdev->requested_regd = regd;                                        │   │
│  │     spin_unlock(&reg_requests_lock);                                    │   │
│  │                                                                         │   │
│  │     // 5. 调度处理                                                       │   │
│  │     schedule_work(&reg_work);                                           │   │
│  │     return 0;                                                            │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 同步设置接口: regulatory_set_wiphy_regd_sync()   reg.c:4063              │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ int regulatory_set_wiphy_regd_sync(struct wiphy *wiphy,                  │   │
│  │                                    struct ieee80211_regdomain *rd)       │   │
│  │ {                                                                       │   │
│  │     ASSERT_RTNL();                                                      │   │
│  │                                                                         │   │
│  │     // 1. 保存请求                                                       │   │
│  │     ret = __regulatory_set_wiphy_regd(wiphy, rd);                       │   │
│  │                                                                         │   │
│  │     // 2. 立即处理 (不通过工作队列)                                      │   │
│  │     reg_process_self_managed_hint(wiphy);                               │   │
│  │     reg_check_channels();                                                │   │
│  │     return 0;                                                            │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 处理函数: reg_process_self_managed_hint()   reg.c:3146                   │   │
│  ├─────────────────────────────────────────────────────────────────────────┤   │
│  │ static void reg_process_self_managed_hint(struct wiphy *wiphy)           │   │
│  │ {                                                                       │   │
│  │     // 1. 获取请求的监管域                                               │   │
│  │     spin_lock(&reg_requests_lock);                                      │   │
│  │     regd = rdev->requested_regd;                                        │   │
│  │     rdev->requested_regd = NULL;                                        │   │
│  │     spin_unlock(&reg_requests_lock);                                    │   │
│  │                                                                         │   │
│  │     if (!regd) return;                                                   │   │
│  │                                                                         │   │
│  │     // 2. 设置到wiphy->regd                                             │   │
│  │     tmp = get_wiphy_regdom(wiphy);                                      │   │
│  │     rcu_assign_pointer(wiphy->regd, regd);                              │   │
│  │     rcu_free_regdom(tmp);                                                │   │
│  │                                                                         │   │
│  │     // 3. 应用到所有频段                                                 │   │
│  │     for (band = 0; band < NUM_NL80211_BANDS; band++)                    │   │
│  │         handle_band_custom(wiphy, wiphy->bands[band], regd);            │   │
│  │                                                                         │   │
│  │     // 4. 处理HT标志                                                     │   │
│  │     reg_process_ht_flags(wiphy);                                        │   │
│  │                                                                         │   │
│  │     // 5. 发送通知                                                       │   │
│  │     nl80211_send_wiphy_reg_change_event(&request);                      │   │
│  │ }                                                                       │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

12. DFS区域处理

12.1 DFS状态传播流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         DFS状态传播流程                                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  regulatory_propagate_dfs_state(wiphy, chandef, dfs_state, event)               │
│  reg.c:4243                                                                     │
│         │                                                                       │
│         ▼                                                                       │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 1. 验证chandef有效性                                                     │  │
│  │    if (WARN_ON(!cfg80211_chandef_valid(chandef)))                        │  │
│  │        return;                                                           │  │
│  └────────────────────────────────────┬─────────────────────────────────────┘  │
│                                       │                                        │
│                                       ▼                                        │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 2. 遍历所有wiphy                                                         │  │
│  │                                                                          │  │
│  │  for_each_rdev(rdev) {                                                   │  │
│  │      if (wiphy == &rdev->wiphy) continue;  // 跳过源wiphy                │  │
│  │                                                                          │  │
│  │      // 检查DFS区域是否相同                                              │  │
│  │      if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))                      │  │
│  │          continue;                                                        │  │
│  │                                                                          │  │
│  │      // 检查目标wiphy是否有相同频率的信道                                │  │
│  │      if (!ieee80211_get_channel(&rdev->wiphy,                            │  │
│  │                                 chandef->chan->center_freq))              │  │
│  │          continue;                                                        │  │
│  │                                                                          │  │
│  │      // ... 处理                                                         │  │
│  │  }                                                                        │  │
│  └────────────────────────────────────┬─────────────────────────────────────┘  │
│                                       │                                        │
│                                       ▼                                        │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 3. 更新DFS状态                                                           │  │
│  │    cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state)              │  │
│  └────────────────────────────────────┬─────────────────────────────────────┘  │
│                                       │                                        │
│                                       ▼                                        │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 4. 根据事件类型处理                                                       │  │
│  │                                                                          │  │
│  │  if (event == NL80211_RADAR_DETECTED ||                                  │  │
│  │      event == NL80211_RADAR_CAC_FINISHED) {                              │  │
│  │      // 调度DFS通道更新                                                   │  │
│  │      cfg80211_sched_dfs_chan_update(rdev);                               │  │
│  │      // 结束相关CAC                                                       │  │
│  │      cfg80211_check_and_end_cac(rdev);                                   │  │
│  │  }                                                                        │  │
│  │                                                                          │  │
│  │  // 发送radar通知                                                         │  │
│  │  nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);           │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

13. 监管数据库

13.1 数据库加载流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         监管数据库加载流程                                        │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  query_regdb_file(alpha2)   reg.c:1037                                          │
│         │                                                                       │
│         ▼                                                                       │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 1. 检查数据库是否已加载                                                   │  │
│  │    if (regdb)                                                            │  │
│  │        return query_regdb(alpha2);  // 直接查询                          │  │
│  └────────────────────────────────────┬─────────────────────────────────────┘  │
│                                       │                                        │
│                                       ▼                                        │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 2. 异步加载数据库                                                         │  │
│  │    request_firmware_nowait(THIS_MODULE, true, "regulatory.db",           │  │
│  │                            &reg_fdev->dev, GFP_KERNEL,                   │  │
│  │                            (void *)alpha2, regdb_fw_cb)                  │  │
│  └────────────────────────────────────┬─────────────────────────────────────┘  │
│                                       │                                        │
│                                       ▼                                        │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 3. 回调函数: regdb_fw_cb()   reg.c:991                                   │  │
│  │                                                                          │  │
│  │  static void regdb_fw_cb(const struct firmware *fw, void *context)       │  │
│  │  {                                                                        │  │
│  │      // 验证数据库                                                        │  │
│  │      if (!fw) {                                                           │  │
│  │          pr_info("failed to load regulatory.db\n");                      │  │
│  │          set_error = -ENODATA;                                            │  │
│  │      } else if (!valid_regdb(fw->data, fw->size)) {                      │  │
│  │          pr_info("loaded regulatory.db is malformed...");                │  │
│  │          set_error = -EINVAL;                                             │  │
│  │      }                                                                     │  │
│  │                                                                           │  │
│  │      rtnl_lock();                                                         │  │
│  │      if (set_error) {                                                      │  │
│  │          regdb = ERR_PTR(set_error);                                      │  │
│  │      } else if (fw) {                                                      │  │
│  │          // 复制到内核内存                                                 │  │
│  │          db = kmemdup(fw->data, fw->size, GFP_KERNEL);                   │  │
│  │          if (db) {                                                         │  │
│  │              regdb = db;                                                   │  │
│  │              // 查询并应用                                                 │  │
│  │              restore = context && query_regdb(context);                   │  │
│  │          }                                                                 │  │
│  │      }                                                                     │  │
│  │                                                                           │  │
│  │      if (restore)                                                          │  │
│  │          restore_regulatory_settings(true, false);                        │  │
│  │      rtnl_unlock();                                                        │  │
│  │  }                                                                        │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

13.2 数据库格式

┌─────────────────────────────────────────────────────────────────────────────────┐
│                         regulatory.db 文件格式                                    │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 文件头 (fwdb_header)                                                     │  │
│  │ ┌─────────────────────────────────────────────────────────────────────┐ │  │
│  │ │ magic: 0x52474442 ("RGDB")                                          │ │  │
│  │ │ version: 20                                                          │ │  │
│  │ └─────────────────────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 国家列表 (fwdb_country[])                                                │  │
│  │ ┌─────────────────────────────────────────────────────────────────────┐ │  │
│  │ │ alpha2: "US"                                                        │ │  │
│  │ │ coll_ptr: 指向集合的指针                                             │ │  │
│  │ ├─────────────────────────────────────────────────────────────────────┤ │  │
│  │ │ alpha2: "JP"                                                        │ │  │
│  │ │ coll_ptr: 指向集合的指针                                             │ │  │
│  │ ├─────────────────────────────────────────────────────────────────────┤ │  │
│  │ │ ...                                                                  │ │  │
│  │ └─────────────────────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 集合 (fwdb_collection)                                                   │  │
│  │ ┌─────────────────────────────────────────────────────────────────────┐ │  │
│  │ │ len: 结构长度                                                        │ │  │
│  │ │ n_rules: 规则数量                                                    │ │  │
│  │ │ dfs_region: DFS区域 (FCC/ETSI/JP)                                   │ │  │
│  │ │ rules_ptr[]: 规则指针数组                                            │ │  │
│  │ └─────────────────────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
│  ┌──────────────────────────────────────────────────────────────────────────┐  │
│  │ 规则 (fwdb_rule)                                                         │  │
│  │ ┌─────────────────────────────────────────────────────────────────────┐ │  │
│  │ │ len: 结构长度                                                        │ │  │
│  │ │ flags: 标志位 (NO_OFDM, NO_OUTDOOR, DFS, NO_IR, AUTO_BW)           │ │  │
│  │ │ max_eirp: 最大EIRP (dBm)                                           │ │  │
│  │ │ start: 起始频率 (kHz)                                                │ │  │
│  │ │ end: 结束频率 (kHz)                                                  │ │  │
│  │ │ max_bw: 最大带宽 (kHz)                                               │ │  │
│  │ │ [可选] cac_timeout: CAC超时 (秒)                                     │ │  │
│  │ │ [可选] wmm_ptr: WMM规则指针                                          │ │  │
│  │ └─────────────────────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────────────────────┘  │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

14. 完整流程总结

14.1 从用户空间到驱动的完整流程

┌─────────────────────────────────────────────────────────────────────────────────┐
│                    监管域处理完整流程 (从用户空间到驱动)                            │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  用户空间                                                                       │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ iw reg set US                                                           │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │ Netlink                                │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ nl80211_req_set_reg()                                                    │   │
│  │ regulatory_hint_user("US", NL80211_USER_REG_HINT_USER)                  │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │                                        │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ queue_regulatory_request()                                               │   │
│  │ 加入 reg_requests_list 链表                                              │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │ schedule_work                           │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_todo() 工作队列                                                      │   │
│  │ reg_process_pending_hints()                                              │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │                                        │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ reg_process_hint_user()                                                  │   │
│  │ reg_query_database() ──► query_regdb_file("US")                         │   │
│  │                    ──► call_crda("US")                                  │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │                                        │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ set_regdom(us_regdom, REGD_SOURCE_INTERNAL_DB)                           │   │
│  │ reg_set_rd_user() ──► reset_regdomains(false, rd)                        │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │                                        │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ update_all_wiphy_regulatory(NL80211_REGDOM_SET_BY_USER)                  │   │
│  │ ┌─────────────────────────────────────────────────────────────────────┐ │   │
│  │ │ for_each_rdev(rdev) {                                               │ │   │
│  │ │     wiphy_update_regulatory(wiphy, BY_USER)                         │ │   │
│  │ │         handle_band(wiphy, BY_USER, sband)                          │ │   │
│  │ │             handle_channel(wiphy, BY_USER, chan)                     │ │   │
│  │ │                 freq_reg_info(wiphy, freq) ──► 查找匹配规则         │ │   │
│  │ │                 handle_channel_single_rule() ──► 应用规则到信道     │ │   │
│  │ │     reg_call_notifier(wiphy, lr) ──► 通知驱动                       │ │   │
│  │ │ }                                                                    │ │   │
│  │ └─────────────────────────────────────────────────────────────────────┘ │   │
│  └────────────────────────────────────┬────────────────────────────────────┘   │
│                                       │                                        │
│                                       ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────────┐   │
│  │ 驱动层                                                                   │   │
│  │ wiphy->reg_notifier(wiphy, request) ──► 驱动回调函数                    │   │
│  │ 信道属性已更新:                                                          │   │
│  │   chan->flags, chan->max_power, chan->dfs_state 等                      │   │
│  └─────────────────────────────────────────────────────────────────────────┘   │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

15. 总结

Linux无线监管域处理流程是一个复杂但设计良好的系统,具有以下特点:

  1. 多层架构: 核心层、驱动层、用户空间层协同工作
  2. 优先级管理: 不同来源的提示有不同的处理优先级
  3. 交集算法: 确保遵守最严格的监管限制
  4. 异步处理: 通过工作队列实现非阻塞处理
  5. RCU保护: 高效的读取并发支持
  6. 灵活接口: 支持多种设备类型和使用场景

该系统确保了无线设备在不同国家和地区都能遵守当地的无线电监管要求,同时提供了足够的灵活性供驱动和用户空间进行定制。