Linux Wireless (802.11/Wi-Fi) 서브시스템 심화
리눅스 커널의 무선 네트워킹 서브시스템은 cfg80211, nl80211, mac80211 세 계층으로 구성됩니다. IEEE 802.11 PHY/MAC 프레임 구조부터 드라이버 구현 패턴(iwlwifi, ath9k/ath10k/ath11k, mt76, rtw88/rtw89), Station/AP 모드, WPA2/WPA3 보안, 802.11n/ac/ax/be 세대별 기술, Mesh 네트워킹, 전원 관리, regulatory domain, Rate Control 알고리즘, TX aggregation, 디버깅까지 전 영역을 상세히 다룹니다.
IEEE 802.11 프로토콜 스택 개요
802.11 프로토콜 계층 구조
IEEE 802.11 표준은 OSI 모델의 물리 계층(PHY)과 데이터 링크 계층(MAC)을 정의합니다. 유선 이더넷(802.3)과 달리 무선 매체의 특수성을 반영하여 MAC 하위 계층(MAC sublayer)과 PHY 계층 사이에 PLCP(Physical Layer Convergence Procedure)와 PMD(Physical Medium Dependent) 서브 레이어가 존재합니다.
| 계층 | 서브 레이어 | 역할 | 리눅스 커널 매핑 |
|---|---|---|---|
| 데이터 링크 계층 (L2) | LLC (Logical Link Control) | SNAP 헤더, 상위 프로토콜 다중화 | 커널 네트워크 스택 (net/llc/) |
| MAC (Medium Access Control) | CSMA/CA, RTS/CTS, 프레임 형식, 인증/연관 | mac80211 (net/mac80211/) | |
| MAC Management | 스캔, 연결, 로밍, 전원 관리 | cfg80211 + wpa_supplicant | |
| 물리 계층 (L1) | PLCP | 프레임 경계, 동기화, 프리앰블 | 하드웨어/펌웨어 |
| PMD | 변조/복조 (OFDM, DSSS 등) | 하드웨어/펌웨어 | |
| RF Front-end | 안테나, PA, LNA, 주파수 합성 | 하드웨어 |
802.11 표준 세대별 비교
| 표준 | 명칭 | 주파수(GHz) | 최대 속도 | 채널 폭 | 변조 | MIMO | 핵심 기술 |
|---|---|---|---|---|---|---|---|
| 802.11a | - | 5 | 54 Mbps | 20 MHz | OFDM | SISO | 52 서브캐리어 |
| 802.11b | - | 2.4 | 11 Mbps | 22 MHz | DSSS/CCK | SISO | - |
| 802.11g | - | 2.4 | 54 Mbps | 20 MHz | OFDM | SISO | ERP (Extended Rate Physical) |
| 802.11n | Wi-Fi 4 (HT) | 2.4/5 | 600 Mbps | 20/40 MHz | OFDM | 4x4 | MIMO, 블록 ACK, 프레임 집합 |
| 802.11ac | Wi-Fi 5 (VHT) | 5 | 6.93 Gbps | 20/40/80/160 MHz | OFDM | 8x8 MU-MIMO | 256-QAM, DL MU-MIMO |
| 802.11ax | Wi-Fi 6/6E (HE) | 2.4/5/6 | 9.6 Gbps | 20/40/80/160 MHz | OFDMA | 8x8 MU-MIMO | 1024-QAM, UL/DL OFDMA, TWT, BSS Coloring |
| 802.11be | Wi-Fi 7 (EHT) | 2.4/5/6 | 46 Gbps | 최대 320 MHz | OFDMA | 16x16 MU-MIMO | 4096-QAM, MLO, Multi-RU, Preamble Puncturing |
802.11 MAC 프레임 일반 형식
802.11 MAC 프레임은 유선 이더넷 프레임과 구조가 다릅니다. 최대 4개의 주소 필드를 가질 수 있으며, Frame Control 필드에 프레임 유형(Management, Control, Data)과 서브타입이 인코딩됩니다.
| 필드 | 크기(바이트) | 설명 |
|---|---|---|
| Frame Control | 2 | 프로토콜 버전, Type, Subtype, To DS, From DS, More Frag, Retry, PM, More Data, Protected, Order |
| Duration/ID | 2 | NAV(Network Allocation Vector) 또는 PS-Poll에서의 AID |
| Address 1 | 6 | 수신자 (RA, Receiver Address) |
| Address 2 | 6 | 송신자 (TA, Transmitter Address) |
| Address 3 | 6 | BSSID 또는 SA/DA (To DS/From DS 비트에 따라 달라짐) |
| Sequence Control | 2 | 시퀀스 번호(12비트) + 프래그먼트 번호(4비트) |
| Address 4 | 0 또는 6 | WDS(Wireless Distribution System) 프레임에서만 사용 |
| QoS Control | 0 또는 2 | QoS 데이터 프레임에서 TID, EOSP, Ack Policy |
| HT Control | 0 또는 4 | HT/VHT/HE 제어 정보 (Link Adaptation, CSI 등) |
| Frame Body | 0~7951 | MSDU (MAC Service Data Unit), AMSDU 시 최대 7935 |
| FCS | 4 | CRC-32 프레임 체크 시퀀스 |
- 00: IBSS(Ad-hoc) — Addr1=DA, Addr2=SA, Addr3=BSSID
- 01: STA → AP (To DS=1) — Addr1=BSSID, Addr2=SA, Addr3=DA
- 10: AP → STA (From DS=1) — Addr1=DA, Addr2=BSSID, Addr3=SA
- 11: WDS/4-addr — Addr1=RA, Addr2=TA, Addr3=DA, Addr4=SA
Frame Control 필드 비트 레이아웃
비트: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+--+--+--+--+--+--+--+--+--+--+---+---+---+---+---+---+
|Protocol |Type | Subtype |ToDS|FrDS|MF |Rt |PM |MD |PF|Ord|
| Version | | | | | | | | | | |
+--+--+--+--+--+--+--+--+--+--+---+---+---+---+---+---+
Type 값:
00 = Management (Beacon, Probe Req/Resp, Auth, Deauth, Assoc, Disassoc)
01 = Control (RTS, CTS, ACK, BAR, BA, PS-Poll)
10 = Data (Data, Null, QoS Data, QoS Null)
11 = Extension
관리 프레임 주요 서브타입
| 서브타입 | 이름 | 방향 | 용도 |
|---|---|---|---|
| 0000 | Association Request | STA → AP | AP에 연관 요청 |
| 0001 | Association Response | AP → STA | 연관 응답 (AID 할당) |
| 0010 | Reassociation Request | STA → AP | 로밍 시 재연관 |
| 0011 | Reassociation Response | AP → STA | 재연관 응답 |
| 0100 | Probe Request | STA → broadcast | 능동 스캔 |
| 0101 | Probe Response | AP → STA | 스캔 응답 |
| 1000 | Beacon | AP → broadcast | 주기적 AP 알림 (보통 100ms 간격) |
| 1010 | Disassociation | 양방향 | 연관 해제 |
| 1011 | Authentication | 양방향 | Open System / SAE 인증 |
| 1100 | Deauthentication | 양방향 | 인증 해제 |
| 1101 | Action | 양방향 | 블록 ACK, 스펙트럼 관리, BSS 전환 등 |
802.11 프레임 유형별 커널 처리 경로
리눅스 커널에서 802.11 프레임은 유형에 따라 다른 처리 경로를 따릅니다.
관리 프레임(Management Frame)은 mac80211의 ieee80211_rx_handlers()에서 처리되며,
데이터 프레임은 변환 후 상위 네트워크 스택으로 전달됩니다.
/* 802.11 프레임 유형 정의 (include/linux/ieee80211.h) */
#define IEEE80211_FTYPE_MGMT 0x0000
#define IEEE80211_FTYPE_CTL 0x0004
#define IEEE80211_FTYPE_DATA 0x0008
#define IEEE80211_FTYPE_EXT 0x000c
/* 관리 프레임 서브타입 */
#define IEEE80211_STYPE_ASSOC_REQ 0x0000
#define IEEE80211_STYPE_ASSOC_RESP 0x0010
#define IEEE80211_STYPE_BEACON 0x0080
#define IEEE80211_STYPE_AUTH 0x00B0
#define IEEE80211_STYPE_DEAUTH 0x00C0
#define IEEE80211_STYPE_ACTION 0x00D0
/* ieee80211_hdr: 802.11 MAC 헤더 구조체 */
struct ieee80211_hdr {
__le16 frame_control; /* FC 필드 */
__le16 duration_id; /* Duration/ID */
u8 addr1[ETH_ALEN]; /* RA (수신자) */
u8 addr2[ETH_ALEN]; /* TA (송신자) */
u8 addr3[ETH_ALEN]; /* BSSID 또는 SA/DA */
__le16 seq_ctrl; /* 시퀀스 제어 */
u8 addr4[ETH_ALEN]; /* WDS에서만 사용 */
} __packed __aligned(2);
/* 프레임 유형 추출 도우미 매크로 */
static inline bool ieee80211_is_mgmt(__le16 fc) {
return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
cpu_to_le16(IEEE80211_FTYPE_MGMT);
}
static inline bool ieee80211_is_data(__le16 fc) {
return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
cpu_to_le16(IEEE80211_FTYPE_DATA);
}
static inline bool ieee80211_is_beacon(__le16 fc) {
return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
}
코드 설명
- 1~6행 Frame Control 필드의 Type 비트(bit 2~3)에 대응하는 상수입니다. Management(00), Control(01), Data(10), Extension(11).
- 8~13행 관리 프레임의 Subtype 비트(bit 4~7) 정의. Beacon은 0x0080(subtype=1000b), Authentication은 0x00B0(subtype=1011b)입니다.
-
16~23행
ieee80211_hdr구조체는 802.11 MAC 헤더를 표현합니다. Address 4는 WDS 모드에서만 사용되므로, 일반적인 경우ieee80211_hdr_3addr변형이 사용됩니다. -
26~37행
인라인 도우미 함수들로 Frame Control의 Type/Subtype 비트를 마스킹하여 프레임 유형을 판별합니다. Little-endian 바이트 순서 처리를 위해
cpu_to_le16()을 사용합니다.
802.11 vs 이더넷(802.3) 변환
무선 데이터 프레임이 상위 네트워크 스택으로 전달될 때, mac80211은 802.11 헤더를 이더넷 헤더로 변환합니다.
이 과정은 ieee80211_deliver_skb() 내에서 수행되며, __ieee80211_data_to_8023() 함수가 핵심 변환 로직을 담당합니다.
| 항목 | 802.11 프레임 | 이더넷(802.3) 프레임 |
|---|---|---|
| 헤더 크기 | 24~36 바이트 (주소 개수에 따라) | 14 바이트 (고정) |
| 주소 필드 | 최대 4개 (RA, TA, DA, SA) | 2개 (Destination, Source) |
| FCS | 4 바이트 CRC-32 | 4 바이트 CRC-32 |
| LLC/SNAP | 포함 (8 바이트) | EtherType 직접 사용 (2 바이트) |
| 최대 MSDU | 2304 바이트 | 1500 바이트 (일반 MTU) |
cfg80211 / nl80211 프레임워크
cfg80211 개요
cfg80211은 리눅스 무선 서브시스템의 구성(configuration) 계층입니다.
커널 소스 net/wireless/ 디렉터리에 위치하며, 모든 무선 드라이버(Soft-MAC, Full-MAC 모두)가
사용자 공간과 통신하기 위해 이 프레임워크에 등록해야 합니다.
cfg80211의 핵심 역할
| 기능 | 설명 | 관련 구조체/함수 |
|---|---|---|
| wiphy 등록 | 무선 PHY 디바이스를 커널에 등록, 지원 대역/채널/속도 정보 제공 | wiphy_new(), wiphy_register() |
| 인터페이스 관리 | STA, AP, Monitor, P2P, IBSS, Mesh, NAN 등 가상 인터페이스 생성/삭제 | cfg80211_ops.add_virtual_intf() |
| 스캔 | 능동/수동 스캔 요청, 스캔 결과 BSS 목록 관리 | cfg80211_scan_request, cfg80211_scan_done() |
| 연결 관리 | connect/disconnect API, SME(Station Management Entity) 제공 | cfg80211_ops.connect(), cfg80211_connect_result() |
| Regulatory | 국가별 주파수 규제 정보 관리, CRDA 연동 | regulatory_hint(), wiphy_apply_custom_regulatory() |
| 키 관리 | 암호화 키 설정/삭제 (WEP, TKIP, CCMP, GCMP, BIP) | cfg80211_ops.add_key(), cfg80211_ops.set_default_key() |
| 이벤트 알림 | 드라이버 → cfg80211 → nl80211 → 사용자 공간 이벤트 전달 | cfg80211_disconnected(), cfg80211_roamed() |
wiphy 구조체 핵심 필드
/* include/net/cfg80211.h (주요 필드만 발췌) */
struct wiphy {
/* 기본 식별 */
char perm_addr[ETH_ALEN]; /* 영구 MAC */
char addr_mask[ETH_ALEN]; /* 가상 MAC 마스크 */
u32 flags; /* WIPHY_FLAG_* */
u32 features; /* NL80211_FEATURE_* */
/* 지원 대역 정보 */
struct ieee80211_supported_band *bands[NUM_NL80211_BANDS];
/* 인터페이스 모드 조합 */
const struct ieee80211_iface_combination *iface_combinations;
int n_iface_combinations;
/* 지원 암호 스위트 */
const u32 *cipher_suites;
int n_cipher_suites;
/* regulatory 정보 */
const struct ieee80211_regdomain *regd;
enum nl80211_dfs_regions dfs_region;
/* 프레임 등록 (관리 프레임 수신) */
struct list_head mgmt_registrations;
spinlock_t mgmt_registrations_lock;
/* 드라이버 private 데이터 (wiphy_priv() 로 접근) */
char priv[] __aligned(NETDEV_ALIGN);
};
코드 설명
-
4~7행
디바이스 식별 정보.
flags에는WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL,WIPHY_FLAG_SUPPORTS_TDLS등이 설정됩니다. -
10행
bands[]배열은 2.4GHz, 5GHz, 6GHz 각 대역의 지원 채널, 속도, HT/VHT/HE 능력을 담고 있습니다. - 13~14행 동시에 활성화할 수 있는 인터페이스 조합을 정의합니다. 예: STA+P2P, AP+AP+STA 등.
- 17~18행 지원되는 암호 스위트 목록. CCMP(AES-128), GCMP(AES-256), BIP(관리 프레임 보호) 등.
- 21~22행 현재 적용된 regulatory domain과 DFS 지역 정보입니다.
-
28행
가변 길이 배열로 드라이버가 자신만의 private 데이터를 wiphy 뒤에 할당합니다.
wiphy_priv(wiphy)로 접근합니다.
nl80211 — Generic Netlink 인터페이스
nl80211은 사용자 공간과 cfg80211 사이의 통신 채널입니다.
Generic Netlink 프로토콜 위에 구축되어 있으며, iw 도구와 wpa_supplicant가
이 인터페이스를 통해 커널과 상호작용합니다.
nl80211 주요 명령과 이벤트
| 명령 (NL80211_CMD_*) | 방향 | 설명 | 대응 cfg80211_ops |
|---|---|---|---|
| GET_WIPHY | 요청/응답 | PHY 장치 정보 조회 | - |
| SET_INTERFACE | 요청 | 인터페이스 모드 변경 (STA/AP/Monitor 등) | change_virtual_intf() |
| NEW_INTERFACE | 요청 | 가상 인터페이스 생성 | add_virtual_intf() |
| TRIGGER_SCAN | 요청 | 스캔 시작 | scan() |
| NEW_SCAN_RESULTS | 이벤트 | 스캔 완료 알림 | cfg80211_scan_done() |
| CONNECT | 요청 | AP 연결 요청 | connect() |
| DISCONNECT | 요청/이벤트 | 연결 해제 | disconnect() |
| AUTHENTICATE | 요청 | 인증 프레임 전송 (SME in driver 모드) | auth() |
| ASSOCIATE | 요청 | 연관 프레임 전송 (SME in driver 모드) | assoc() |
| NEW_KEY / DEL_KEY | 요청 | 암호화 키 추가/삭제 | add_key() / del_key() |
| SET_BSS | 요청 | BSS 파라미터 설정 (AP 모드) | change_bss() |
| START_AP / STOP_AP | 요청 | AP 모드 시작/중지 | start_ap() / stop_ap() |
| NEW_STATION | 이벤트 | 새 STA 연결 알림 (AP 모드) | cfg80211_new_sta() |
| FRAME | 요청/이벤트 | 관리 프레임 송수신 (Action 프레임 등) | mgmt_tx() |
| REMAIN_ON_CHANNEL | 요청 | 특정 채널에서 대기 (P2P 디스커버리) | remain_on_channel() |
| SET_REKEY_OFFLOAD | 요청 | GTK Rekeying 오프로드 (절전 중 키 갱신) | set_rekey_data() |
cfg80211_ops 콜백 구조체
/* include/net/cfg80211.h (주요 콜백만 발췌) */
struct cfg80211_ops {
/* 인터페이스 관리 */
struct wireless_dev *(*add_virtual_intf)(struct wiphy *wiphy,
const char *name,
unsigned char name_assign_type,
enum nl80211_iftype type,
struct vif_params *params);
int (*del_virtual_intf)(struct wiphy *wiphy,
struct wireless_dev *wdev);
/* 스캔 */
int (*scan)(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
void (*abort_scan)(struct wiphy *wiphy,
struct wireless_dev *wdev);
/* 연결 관리 */
int (*connect)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_connect_params *sme);
int (*disconnect)(struct wiphy *wiphy,
struct net_device *dev,
u16 reason_code);
/* AP 모드 */
int (*start_ap)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_ap_settings *settings);
int (*stop_ap)(struct wiphy *wiphy,
struct net_device *dev,
unsigned int link_id);
/* 키 관리 */
int (*add_key)(struct wiphy *wiphy,
struct net_device *dev,
int link_id, u8 key_index, bool pairwise,
const u8 *mac_addr,
struct key_params *params);
/* 전원 관리 */
int (*set_power_mgmt)(struct wiphy *wiphy,
struct net_device *dev,
bool enabled, int timeout);
/* 채널/주파수 */
int (*set_channel)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef);
/* ... 50개 이상의 콜백이 존재 */
};
wiphy 등록 흐름 예제
/* 드라이버 초기화 시 wiphy 등록 전체 흐름 */
static int mydrv_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct wiphy *wiphy;
struct mydrv_priv *priv;
struct ieee80211_supported_band *band;
/* 1. wiphy 할당 (private 크기 포함) */
wiphy = wiphy_new(&mydrv_cfg80211_ops,
sizeof(struct mydrv_priv));
if (!wiphy)
return -ENOMEM;
priv = wiphy_priv(wiphy);
priv->pdev = pdev;
/* 2. 지원 대역 설정 */
band = &priv->band_2ghz;
band->channels = mydrv_2ghz_channels;
band->n_channels = ARRAY_SIZE(mydrv_2ghz_channels);
band->bitrates = mydrv_2ghz_rates;
band->n_bitrates = ARRAY_SIZE(mydrv_2ghz_rates);
band->ht_cap.ht_supported = true;
wiphy->bands[NL80211_BAND_2GHZ] = band;
/* 3. wiphy 속성 설정 */
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_MONITOR);
wiphy->max_scan_ssids = 4;
wiphy->max_scan_ie_len = 2048;
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->cipher_suites = mydrv_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(mydrv_cipher_suites);
SET_IEEE80211_DEV(wiphy, &pdev->dev);
/* 4. wiphy 등록 */
int ret = wiphy_register(wiphy);
if (ret) {
wiphy_free(wiphy);
return ret;
}
/* 5. 네트워크 인터페이스 생성 */
/* ... wdev / netdev 생성 코드 ... */
return 0;
}
ieee80211_alloc_hw()가 내부적으로 wiphy_new()를 호출합니다.
Full-MAC 드라이버(예: brcmfmac)는 mac80211 없이 cfg80211에 직접 등록합니다.
mac80211 서브시스템 심화
mac80211 개요
mac80211은 Soft-MAC 무선 드라이버를 위한 프레임워크로, 커널 소스
net/mac80211/ 디렉터리에 위치합니다.
드라이버가 하드웨어 제어만 담당하고, 나머지 MAC 레벨 기능(프레임 처리, 암호화, 집합, 전원 관리 등)을
mac80211이 제공합니다. 이를 통해 드라이버 코드가 크게 단순화되고, 공통 기능의 중복 구현을 방지합니다.
ieee80211_hw 구조체
ieee80211_hw는 mac80211과 드라이버 사이의 핵심 인터페이스입니다.
드라이버가 ieee80211_alloc_hw()로 할당하고, 하드웨어 능력과 제한사항을 이 구조체에 설정합니다.
/* include/net/mac80211.h (주요 필드만 발췌) */
struct ieee80211_hw {
struct ieee80211_conf conf; /* 현재 설정 */
struct wiphy *wiphy; /* cfg80211 wiphy */
const char *rate_control_algorithm; /* RC 알고리즘 이름 */
void *priv; /* 드라이버 private */
/* 하드웨어 플래그 (IEEE80211_HW_*) */
u32 flags;
/* 하드웨어 능력 */
unsigned int extra_tx_headroom; /* TX 헤더 여유 공간 */
unsigned int extra_beacon_tailroom; /* 비콘 꼬리 여유 */
int vif_data_size; /* per-vif private 크기 */
int sta_data_size; /* per-sta private 크기 */
int chanctx_data_size;
/* 큐 관련 */
u16 queues; /* TX 하드웨어 큐 수 */
u16 max_listen_interval;
s8 max_signal; /* 최대 RSSI 값 (dBm) */
/* AMPDU 제한 */
u8 max_rx_aggregation_subframes;
u8 max_tx_aggregation_subframes;
/* 오프로드 능력 */
netdev_features_t netdev_features;
/* Weight(가중치): 멀티큐 FQ(fq_codel) 양자 */
u32 weight_multiplier;
};
ieee80211_hw 주요 플래그 (IEEE80211_HW_*)
| 플래그 | 의미 | 드라이버 예 |
|---|---|---|
| HAS_RATE_CONTROL | 하드웨어/펌웨어에 자체 RC 알고리즘 내장 | iwlwifi (mvm) |
| RX_INCLUDES_FCS | 수신 프레임에 FCS 포함 | 일부 Full-MAC |
| SIGNAL_DBM | RSSI를 dBm 단위로 보고 | 대부분 |
| SPECTRUM_MGMT | 스펙트럼 관리 지원 (DFS) | ath9k, ath10k |
| AMPDU_AGGREGATION | TX AMPDU 집합 지원 | 대부분 |
| SUPPORTS_PS | 전원 관리(Power Save) 지원 | 대부분 |
| SUPPORTS_DYNAMIC_PS | 동적 PS 타이머 지원 | ath9k |
| MFP_CAPABLE | Management Frame Protection 지원 | iwlwifi, ath10k |
| SUPPORTS_MULTI_BSSID | 다중 BSSID 지원 | ath11k |
| CHANCTX_STA_CSA | STA 모드에서 CSA 지원 | iwlwifi |
| WANT_MONITOR_VIF | 모니터 인터페이스를 vif로 수신 원함 | ath9k |
| MLO_MCAST_MULTI_LINK_TX | MLO 멀티캐스트 지원 (Wi-Fi 7) | ath12k |
ieee80211_ops — mac80211 드라이버 콜백
/* include/net/mac80211.h (핵심 콜백만 발췌) */
struct ieee80211_ops {
/* === 기본 생명주기 === */
int (*start)(struct ieee80211_hw *hw);
void (*stop)(struct ieee80211_hw *hw);
/* === 인터페이스(vif) 관리 === */
int (*add_interface)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void (*remove_interface)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
/* === 설정 변경 === */
int (*config)(struct ieee80211_hw *hw, u32 changed);
void (*bss_info_changed)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u64 changed);
/* === TX/RX 경로 === */
void (*tx)(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb);
void (*wake_tx_queue)(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
/* === AMPDU 집합 === */
int (*ampdu_action)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params);
/* === 스테이션 관리 === */
int (*sta_state)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ieee80211_sta_state old_state,
enum ieee80211_sta_state new_state);
/* === 하드웨어 설정 === */
void (*configure_filter)(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
u64 multicast);
int (*set_key)(struct ieee80211_hw *hw,
enum set_key_cmd cmd,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key);
/* === 채널 컨텍스트 === */
int (*add_chanctx)(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx);
void (*change_chanctx)(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx,
u32 changed);
/* ... 80개 이상의 콜백이 존재 */
};
코드 설명
-
4~5행
start()는 첫 인터페이스 활성화 시 호출되어 하드웨어를 초기화합니다.stop()은 마지막 인터페이스 비활성화 시 호출됩니다. - 8~11행 가상 인터페이스(vif) 추가/삭제 콜백. 하나의 PHY에서 STA+AP+Monitor 등 다중 vif를 운영할 수 있습니다.
-
14~18행
config()는 채널, TX 파워 등 전역 설정 변경 시 호출됩니다.bss_info_changed()는 BSS 연관 파라미터(BSSID, 비콘 간격, CTS 보호 등) 변경 시 호출됩니다. -
21~24행
tx()는 프레임 전송 콜백입니다. 최근 커널에서는wake_tx_queue()를 통한 pull 기반 TX가 선호됩니다. mac80211의 fq(fair queue) 스케줄러가 TXQ를 관리합니다. -
27~29행
AMPDU 세션 시작/중지/TX 동작 제어 콜백.
IEEE80211_AMPDU_TX_START,IEEE80211_AMPDU_TX_STOP_*,IEEE80211_AMPDU_RX_START등의 액션을 처리합니다. - 32~36행 스테이션 상태 전이 콜백. NOTEXIST → NONE → AUTH → ASSOC → AUTHORIZED 순서로 전이됩니다.
mac80211 드라이버 등록 전체 흐름
/* mac80211 드라이버 초기화 패턴 */
static const struct ieee80211_ops mydrv_mac80211_ops = {
.start = mydrv_start,
.stop = mydrv_stop,
.tx = mydrv_tx,
.wake_tx_queue = ieee80211_handle_wake_tx_queue,
.add_interface = mydrv_add_interface,
.remove_interface = mydrv_remove_interface,
.config = mydrv_config,
.bss_info_changed = mydrv_bss_info_changed,
.configure_filter = mydrv_configure_filter,
.set_key = mydrv_set_key,
.sta_state = mydrv_sta_state,
.ampdu_action = mydrv_ampdu_action,
.sw_scan_start = mydrv_sw_scan_start,
.sw_scan_complete = mydrv_sw_scan_complete,
};
static int mydrv_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct ieee80211_hw *hw;
struct mydrv_priv *priv;
/* 1. ieee80211_hw 할당 */
hw = ieee80211_alloc_hw(sizeof(*priv), &mydrv_mac80211_ops);
if (!hw)
return -ENOMEM;
priv = hw->priv;
priv->hw = hw;
SET_IEEE80211_DEV(hw, &pdev->dev);
/* 2. 하드웨어 능력 설정 */
ieee80211_hw_set(hw, SIGNAL_DBM);
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
ieee80211_hw_set(hw, MFP_CAPABLE);
ieee80211_hw_set(hw, SUPPORTS_PS);
hw->queues = 4; /* AC_BK, AC_BE, AC_VI, AC_VO */
hw->extra_tx_headroom = 32;
hw->max_rx_aggregation_subframes = 64;
hw->max_tx_aggregation_subframes = 64;
/* 3. 대역 설정 (wiphy에) */
mydrv_setup_bands(hw);
/* 4. mac80211 등록 */
int ret = ieee80211_register_hw(hw);
if (ret) {
ieee80211_free_hw(hw);
return ret;
}
pci_set_drvdata(pdev, hw);
return 0;
}
mac80211 스테이션(STA) 상태 머신
mac80211은 각 연결 스테이션에 대해 명확한 상태 전이를 관리합니다.
드라이버의 sta_state() 콜백이 각 전이 시점에 호출되어
하드웨어 수준의 스테이션 테이블을 갱신할 수 있습니다.
| 상태 | 설명 | 전이 조건 |
|---|---|---|
| NOTEXIST | 스테이션 미존재 | → NONE: sta_info_alloc() |
| NONE | 스테이션 엔트리 생성됨 | → AUTH: 인증 완료 |
| AUTH | 인증 완료 | → ASSOC: 연관 완료 |
| ASSOC | 연관 완료 | → AUTHORIZED: 4-way handshake 완료 |
| AUTHORIZED | 데이터 전송 허용 | → ASSOC: 키 만료/재인증 |
ops->tx()가 push 방식으로 프레임을 드라이버에 전달했지만,
현재 권장되는 방식은 ops->wake_tx_queue() 기반의 pull 모델입니다.
mac80211 내부의 fq_codel 스케줄러가 TXQ를 관리하며, 드라이버가
ieee80211_tx_dequeue()로 프레임을 가져갑니다.
이를 통해 공정한 큐잉(per-flow fair queueing)과 bufferbloat 방지가 가능합니다.
무선 드라이버 구현
주요 리눅스 무선 드라이버 비교
| 드라이버 | 칩셋 제조사 | MAC 유형 | 최대 세대 | 커널 소스 경로 | 특징 |
|---|---|---|---|---|---|
| iwlwifi | Intel | Soft-MAC (mac80211) | Wi-Fi 7 (BE200/201) | drivers/net/wireless/intel/iwlwifi/ | MVM/FW 아키텍처, 펌웨어 의존성 높음, 최적화된 RC |
| ath9k | Qualcomm/Atheros | Soft-MAC | Wi-Fi 4 (AR9xxx) | drivers/net/wireless/ath/ath9k/ | 완전 오픈소스, HAL 없음, 펌웨어 불필요, 참조 구현 |
| ath10k | Qualcomm/Atheros | Soft-MAC | Wi-Fi 5 (QCA9xxx) | drivers/net/wireless/ath/ath10k/ | 펌웨어 기반 데이터 경로, CT(Candela Technologies) 펌웨어 |
| ath11k | Qualcomm | Soft-MAC | Wi-Fi 6/6E (QCN9xxx, WCN685x) | drivers/net/wireless/ath/ath11k/ | AHB/PCIe 이중 버스, HAL 추상화 계층 |
| ath12k | Qualcomm | Soft-MAC | Wi-Fi 7 (WCN7850, QCN9274) | drivers/net/wireless/ath/ath12k/ | MLO(Multi-Link Operation) 지원, EHT |
| mt76 | MediaTek | Soft-MAC | Wi-Fi 7 (MT7996) | drivers/net/wireless/mediatek/mt76/ | 통합 드라이버 프레임워크, USB/PCIe/MMIO |
| rtw88 | Realtek | Soft-MAC | Wi-Fi 5 (RTL8822x) | drivers/net/wireless/realtek/rtw88/ | 현대적 mac80211 드라이버 |
| rtw89 | Realtek | Soft-MAC | Wi-Fi 6/6E (RTL8852x) | drivers/net/wireless/realtek/rtw89/ | rtw88 후속, HE 지원 |
| brcmfmac | Broadcom | Full-MAC | Wi-Fi 6 (BCM43xx) | drivers/net/wireless/broadcom/brcm80211/brcmfmac/ | Full-MAC: MAC 기능이 펌웨어에, cfg80211 직접 사용 |
| wl18xx | Texas Instruments | Soft-MAC | Wi-Fi 4 (WL18xx) | drivers/net/wireless/ti/wlcore/ | SPI/SDIO 버스, 임베디드 플랫폼 |
iwlwifi 아키텍처 상세
Intel iwlwifi는 가장 복잡한 구조를 가진 무선 드라이버 중 하나입니다. 드라이버는 크게 트랜스포트 계층(PCIe/platform), opmode(MVM/DVM), 펌웨어 인터페이스로 나뉩니다.
/* iwlwifi MVM(Modern Virtual MAC) 아키텍처 핵심 구조체 */
struct iwl_mvm {
struct iwl_trans *trans; /* PCIe 트랜스포트 */
struct iwl_fw *fw; /* 펌웨어 이미지 */
struct ieee80211_hw *hw; /* mac80211 hw */
struct iwl_mvm_vif *vifs[NUM_MAC_INDEX_DRIVER];
struct iwl_mvm_sta *sta_data[IWL_MVM_STATION_COUNT];
/* 펌웨어 커맨드 큐 */
struct iwl_host_cmd cmd;
u32 fw_error;
bool firmware_running;
/* TX 큐 매핑 */
u8 queue_to_mac80211[IWL_MAX_TVQM_QUEUES];
/* 스캔 관련 */
unsigned int scan_status;
struct iwl_mvm_scan_params last_scan_params;
/* 온도/전력 제어 (Thermal Throttling) */
struct iwl_mvm_tt_mgmt thermal_throttle;
};
/* iwlwifi TX 흐름:
mac80211 → iwl_mvm_mac_tx() → iwl_mvm_tx_skb()
→ iwl_trans_tx() → PCIe TFD ring → 펌웨어 → 무선 전송 */
ath9k — 참조 Soft-MAC 드라이버
ath9k은 펌웨어 없이 HAL(Hardware Abstraction Layer)을 직접 구현한 완전 오픈소스 드라이버입니다. mac80211의 모든 기능을 활용하는 참조 구현으로, 무선 드라이버 학습에 가장 적합합니다.
/* ath9k 핵심 구조 (drivers/net/wireless/ath/ath9k/) */
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
struct ath_hw *sc_ah; /* 하드웨어 추상화 */
struct ath_common common;
/* TX 큐 */
struct ath_txq tx_queue[ATH9K_NUM_TX_QUEUES];
/* RX 처리 */
struct ath_rx rx;
struct tasklet_struct rx_tasklet; /* bottom half */
struct tasklet_struct tx_tasklet;
/* 인터럽트 */
u32 imask; /* 인터럽트 마스크 */
u32 intr_status;
/* 안테나 다양성 */
struct ath_ant_comb ant_comb;
/* 스펙트럼 분석 */
struct ath_spec_scan spec_scan;
};
/* ath9k 인터럽트 핸들러 */
static irqreturn_t ath_isr(int irq, void *dev_id)
{
struct ath_softc *sc = dev_id;
struct ath_hw *ah = sc->sc_ah;
u32 status;
/* 하드웨어 인터럽트 상태 읽기 */
status = ath9k_hw_getisr(ah, &ah->intr_status);
if (!status)
return IRQ_NONE;
/* RX 인터럽트: tasklet으로 지연 처리 */
if (status & ATH9K_INT_RX)
tasklet_schedule(&sc->rx_tasklet);
/* TX 완료 인터럽트 */
if (status & ATH9K_INT_TX)
tasklet_schedule(&sc->tx_tasklet);
return IRQ_HANDLED;
}
mt76 — MediaTek 통합 프레임워크
mt76은 MediaTek의 다양한 Wi-Fi 칩셋(MT7603, MT7615, MT7915, MT7921, MT7996)을 하나의 통합 프레임워크로 지원하는 드라이버입니다. USB, PCIe, 플랫폼(MMIO) 버스를 공통 추상화합니다.
/* mt76 공통 디바이스 구조체 */
struct mt76_dev {
struct mt76_phy phy; /* 주 PHY */
struct mt76_phy *phys[__MT_MAX_BAND];
struct ieee80211_hw *hw;
const struct mt76_bus_ops *bus; /* USB/PCIe/MMIO */
const struct mt76_driver_ops *drv;
/* DMA 엔진 */
struct mt76_queue q_tx[__MT_TXQ_MAX];
struct mt76_queue q_rx[__MT_RXQ_MAX];
/* MCU(Microcontroller Unit) 통신 */
struct mt76_mcu mcu;
struct sk_buff_head mcu_res_queue;
/* WCID(Wireless Client ID) 테이블 */
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
};
/* 칩별 드라이버는 mt76_dev를 포함하는 확장 구조체를 사용 */
/* 예: struct mt7915_dev { struct mt76_dev mt76; ... }; */
Station 모드 (STA)
STA 모드 연결 절차 개요
Station 모드는 무선 클라이언트가 AP(Access Point)에 접속하는 가장 일반적인 동작 모드입니다. 연결 과정은 스캔 → 인증 → 연관 → 4-way handshake → 데이터 전송의 단계를 거칩니다.
커널 내부 연결 관리 흐름
/* wpa_supplicant가 NL80211_CMD_CONNECT 호출 시 커널 경로 */
/* 1. nl80211 → cfg80211 */
nl80211_connect()
→ cfg80211_connect()
→ rdev_connect(rdev, dev, connect)
/* 2. mac80211 SME (Station Management Entity) */
/* cfg80211 connect API를 mac80211이 auth+assoc으로 분해 */
ieee80211_mgd_auth()
→ ieee80211_prep_auth(sdata, req)
→ ieee80211_send_auth(sdata, ...) /* Auth 프레임 전송 */
ieee80211_mgd_assoc()
→ ieee80211_send_assoc(sdata) /* Assoc Request 전송 */
/* 3. RX에서 응답 수신 */
ieee80211_rx_mgmt_auth()
→ ieee80211_auth_completed()
ieee80211_rx_mgmt_assoc_resp()
→ ieee80211_assoc_success()
→ cfg80211_rx_assoc_resp() /* cfg80211에 연관 완료 알림 */
/* 4. 4-way handshake (wpa_supplicant가 EAPOL 처리) */
/* mac80211 → netdev → wpa_supplicant EAPOL 교환 */
/* 키 설치: NL80211_CMD_NEW_KEY → cfg80211_ops.add_key() */
/* 5. 포트 인가 */
cfg80211_port_authorized(dev, bssid, pmk, pmk_len, GFP_KERNEL);
/* → STA 상태가 AUTHORIZED로 전이, 데이터 프레임 전송 허용 */
로밍(Roaming) 메커니즘
로밍은 STA가 현재 연결된 AP에서 더 신호가 강한 AP로 전환하는 과정입니다. 리눅스에서는 크게 세 가지 로밍 방식을 지원합니다:
| 방식 | 제어 주체 | 설명 | 커널 API |
|---|---|---|---|
| 사용자 공간 로밍 | wpa_supplicant | RSSI 모니터링 후 disconnect → connect (느림) | NL80211_CMD_DISCONNECT + CONNECT |
| 드라이버/FW 로밍 | 드라이버/펌웨어 | 하드웨어가 자체 로밍 결정 후 알림 | cfg80211_roamed() |
| 802.11r (FT) | mac80211 + 드라이버 | Fast BSS Transition: 로밍 시간 최소화 | NL80211_CMD_UPDATE_FT_IES |
NL80211_CMD_UPDATE_FT_IES와 cfg80211_ft_event()로 지원됩니다.
AP 모드 (hostapd)
AP 모드 개요
리눅스에서 AP(Access Point) 모드는 hostapd 데몬이 cfg80211/nl80211을 통해
커널의 mac80211 서브시스템을 제어하여 구현됩니다. 드라이버는 비콘(Beacon) 전송,
클라이언트 인증/연관 처리, DFS(Dynamic Frequency Selection), CSA(Channel Switch Announcement) 등을 지원합니다.
hostapd와 커널의 상호작용
| 동작 | hostapd 측 | nl80211 명령 | mac80211 처리 |
|---|---|---|---|
| AP 시작 | hostapd.conf 로드 | NL80211_CMD_START_AP | ieee80211_start_ap() → 비콘 설정, BSS 활성화 |
| 비콘 전송 | 비콘 IE 생성 | NL80211_CMD_SET_BEACON | ieee80211_beacon_get() → 주기적 비콘 DMA |
| STA 인증 | 인증 결정 | NL80211_CMD_FRAME (mgmt_tx) | Auth Response 전송 |
| STA 연관 | AID 할당, RSN 검증 | NL80211_CMD_NEW_STATION | sta_info 추가, 상태 전이 |
| 키 설치 | PTK/GTK 도출 | NL80211_CMD_NEW_KEY | ieee80211_set_key() → HW 키 프로그래밍 |
| 채널 전환 | CSA 트리거 | NL80211_CMD_CHANNEL_SWITCH | ieee80211_channel_switch() → CSA 비콘 삽입 |
| STA 킥 | deauth 결정 | NL80211_CMD_DEL_STATION | Deauthentication 전송, sta_info 제거 |
비콘 프레임 구조
/* 비콘 프레임에 포함되는 주요 Information Elements (IEs) */
struct ieee80211_mgmt {
struct ieee80211_hdr hdr; /* FC, Duration, Addr1~3, SeqCtrl */
union {
struct {
__le64 timestamp; /* TSF 타임스탬프 */
__le16 beacon_int; /* 비콘 간격 (TU, 보통 100) */
__le16 capab_info; /* Capability Information */
/* 이후 가변 길이 IEs:
SSID (ID=0)
Supported Rates (ID=1)
DS Parameter Set (ID=3)
TIM - Traffic Indication Map (ID=5)
Country (ID=7)
HT Capabilities (ID=45)
RSN (ID=48) - WPA2 보안 정보
HT Operation (ID=61)
VHT Capabilities (ID=191)
VHT Operation (ID=192)
HE Capabilities (ID=255, ext=35)
HE Operation (ID=255, ext=36)
EHT Capabilities (ID=255, ext=108) - Wi-Fi 7
*/
u8 variable[];
} __packed beacon;
} u;
} __packed __aligned(2);
/* mac80211이 비콘을 생성하는 핵심 함수 */
struct sk_buff *ieee80211_beacon_get_tim(
struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 *tim_offset, u16 *tim_length,
unsigned int link_id);
CSA (Channel Switch Announcement)
CSA는 AP가 운영 채널을 변경할 때 연결된 STA들에게 사전 알림하는 메커니즘입니다.
DFS 레이더 감지 시 필수적이며, hostapd가 NL80211_CMD_CHANNEL_SWITCH를 통해 트리거합니다.
/* CSA IE (Information Element) 구조 */
/* Element ID = 37, Length = 3 */
struct ieee80211_csa_ie {
u8 mode; /* 0: 전송 허용, 1: 전송 중지 */
u8 new_ch_num; /* 전환할 새 채널 번호 */
u8 count; /* 남은 비콘 수 (0이면 즉시 전환) */
} __packed;
/* Extended CSA IE (5GHz → 6GHz 등 대역 간 전환) */
struct ieee80211_ext_csa_ie {
u8 mode;
u8 new_operating_class; /* 새 Operating Class */
u8 new_ch_num;
u8 count;
} __packed;
/* mac80211에서 CSA 처리 */
int ieee80211_channel_switch(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_csa_settings *params);
/* → 비콘에 CSA IE 삽입
→ count 비콘 후 실제 채널 전환
→ 드라이버에 channel_switch 콜백 호출 */
Wi-Fi 보안
무선 보안 프로토콜 진화
| 프로토콜 | 도입 | 암호화 | 키 관리 | 취약점/상태 |
|---|---|---|---|---|
| WEP | 1997 | RC4 (40/104비트) | 정적 키 | 심각한 결함, 사용 금지 |
| WPA (TKIP) | 2003 | RC4-TKIP (MIC) | PSK 또는 802.1X | TKIP 폐기 예정, 호환성 모드 |
| WPA2 (RSN) | 2004 | AES-CCMP (128비트) | PSK 또는 802.1X | KRACK 취약점(패치됨), 현재 표준 |
| WPA3-Personal | 2018 | AES-CCMP/GCMP | SAE (Dragonfly) | 오프라인 사전 공격 방지 |
| WPA3-Enterprise | 2018 | AES-GCMP-256 | 802.1X (EAP-TLS) | 192비트 보안 스위트, CNSA 준수 |
| OWE | 2018 | AES-CCMP/GCMP | ECDH 키 교환 | 개방 네트워크의 암호화 (Enhanced Open) |
4-Way Handshake 상세
4-Way Handshake는 WPA2/WPA3에서 PTK(Pairwise Transient Key)와 GTK(Group Temporal Key)를 도출하고 설치하는 핵심 절차입니다. EAPOL-Key 프레임을 사용합니다.
/* 키 계층 구조 */
/* PSK (Pre-Shared Key) 또는 PMK (Pairwise Master Key)
- WPA2-Personal: PMK = PSK = PBKDF2(passphrase, SSID, 4096, 256)
- WPA3-SAE: PMK = SAE 핸드셰이크에서 도출 */
/* PTK (Pairwise Transient Key) 도출:
PTK = PRF-X(PMK, "Pairwise key expansion",
Min(AA,SPA) || Max(AA,SPA) ||
Min(ANonce,SNonce) || Max(ANonce,SNonce))
PTK 분해:
- KCK (Key Confirmation Key) : EAPOL MIC 계산 (16/24/32 바이트)
- KEK (Key Encryption Key) : GTK 암호화 전송 (16/24/32 바이트)
- TK (Temporal Key) : 데이터 암호화 (16/32 바이트)
*/
/* 리눅스 커널의 키 설치 */
struct ieee80211_key_conf {
u32 cipher; /* WLAN_CIPHER_SUITE_CCMP 등 */
u8 icv_len; /* ICV 길이 */
u8 iv_len; /* IV 길이 */
u8 hw_key_idx; /* HW 키 인덱스 */
u8 keyidx; /* 키 인덱스 (0~3) */
u16 keylen; /* 키 길이 */
u32 flags; /* IEEE80211_KEY_FLAG_* */
u8 key[]; /* 실제 키 데이터 */
};
/* 지원되는 암호 스위트 */
#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01
#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 /* AES-128 */
#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A /* AES-256 */
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 /* GCMP-128 */
#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 /* GCMP-256 */
#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
SAE (Simultaneous Authentication of Equals) — WPA3
SAE는 WPA3-Personal의 핵심 인증 프로토콜로, Dragonfly 키 교환 알고리즘을 기반으로 합니다. 패스워드 기반이지만 오프라인 사전 공격에 내성이 있습니다.
| 단계 | 메시지 | 내용 | 커널 처리 |
|---|---|---|---|
| 1. Commit | STA → AP | 스칼라 + Element (ECC 포인트) | Authentication 프레임 (auth_alg=SAE, seq=1) |
| 2. Commit | AP → STA | 스칼라 + Element | Authentication 프레임 (seq=1) |
| 3. Confirm | STA → AP | confirm 값 (KCK로 서명) | Authentication 프레임 (seq=2) |
| 4. Confirm | AP → STA | confirm 값 | Authentication 프레임 (seq=2) → PMK 도출 |
IEEE80211_HW_MFP_CAPABLE 플래그가
설정된 드라이버에서 관리 프레임(Deauth, Disassoc, Action)에 BIP(Broadcast Integrity Protocol)
또는 CCMP 보호를 적용합니다. 이를 통해 Deauth 플러딩 공격을 방지합니다.
802.1X (Enterprise) 인증 흐름
STA AP (NAS) RADIUS 서버
| | |
| EAPOL-Start | |
|─────────────────>| |
| | RADIUS-Access-Req |
| |───────────────────>|
| EAP-Request | |
|<─────────────────|<───────────────────|
| (Identity) | |
| | |
| EAP-Response | RADIUS-Access-Req |
|─────────────────>|───────────────────>|
| (Identity) | |
| | |
| EAP-TLS/PEAP/TTLS 교환 (다수 라운드) |
|<────────────────>|<──────────────────>|
| | |
| | RADIUS-Accept |
| |<───────────────────|
| EAP-Success | (MSK 전달) |
|<─────────────────| |
| | |
| 4-Way Handshake (PMK = MSK 앞 32바이트)
|<────────────────>| |
802.11n/ac/ax/be — 세대별 핵심 기술
802.11n (Wi-Fi 4, HT)
802.11n은 MIMO(Multiple Input Multiple Output)를 최초로 도입하여 최대 600 Mbps를 달성합니다. 채널 폭 40 MHz, 블록 ACK, 프레임 집합(A-MSDU, A-MPDU)이 핵심 기술입니다.
/* HT Capabilities 구조체 (include/linux/ieee80211.h) */
struct ieee80211_ht_cap {
__le16 cap_info; /* HT 능력 비트맵 */
u8 ampdu_params_info; /* A-MPDU 파라미터 */
struct ieee80211_mcs_info mcs; /* MCS(Modulation Coding Scheme) */
__le16 extended_ht_cap_info;
__le32 tx_BF_cap_info; /* 빔포밍 능력 */
u8 antenna_selection_info;
} __packed;
/* HT cap_info 비트 필드 */
#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
#define IEEE80211_HT_CAP_SM_PS 0x000C
#define IEEE80211_HT_CAP_GRN_FLD 0x0010 /* Green Field */
#define IEEE80211_HT_CAP_SGI_20 0x0020 /* Short GI 20MHz */
#define IEEE80211_HT_CAP_SGI_40 0x0040 /* Short GI 40MHz */
#define IEEE80211_HT_CAP_TX_STBC 0x0080
#define IEEE80211_HT_CAP_RX_STBC 0x0300
#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 /* 7935 vs 3839 */
802.11ac (Wi-Fi 5, VHT)
802.11ac은 5GHz 전용으로 최대 6.93 Gbps를 달성합니다. 핵심 기술은 80/160 MHz 채널 폭, 256-QAM, 다운링크 MU-MIMO(최대 8x8)입니다.
/* VHT Capabilities (include/linux/ieee80211.h) */
struct ieee80211_vht_cap {
__le32 vht_cap_info; /* VHT 능력 비트맵 */
struct ieee80211_vht_mcs_info supp_mcs; /* MCS 지원 정보 */
} __packed;
/* VHT cap_info 주요 비트 */
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
/* 채널 폭별 최대 속도 (MCS 9, 8SS) */
/* 80 MHz: 3.47 Gbps
160 MHz: 6.93 Gbps */
802.11ax (Wi-Fi 6/6E, HE)
802.11ax는 고밀도 환경 최적화에 초점을 맞춘 세대입니다. OFDMA(Orthogonal Frequency Division Multiple Access)로 여러 사용자가 동시에 서브채널을 공유하며, TWT(Target Wake Time)로 전력 효율을 높입니다.
802.11ax HE 관련 커널 구조체
/* HE (High Efficiency) Capabilities (include/linux/ieee80211.h) */
struct ieee80211_he_cap_elem {
u8 mac_cap_info[6]; /* HE MAC 능력 */
u8 phy_cap_info[11]; /* HE PHY 능력 */
} __packed;
/* HE MAC 능력 비트 (일부) */
#define IEEE80211_HE_MAC_CAP0_HTC_HE 0x01
#define IEEE80211_HE_MAC_CAP0_TWT_REQ 0x02
#define IEEE80211_HE_MAC_CAP0_TWT_RES 0x04
#define IEEE80211_HE_MAC_CAP3_OFDMA_RA 0x01
#define IEEE80211_HE_MAC_CAP4_BQR 0x40 /* BSS Color */
/* HE PHY 능력 비트 (일부) */
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G 0x08
/* mac80211에서 HE 지원 대역 설정 */
struct ieee80211_sband_iftype_data {
u16 types_mask; /* NL80211_IFTYPE 비트맵 */
struct ieee80211_sta_he_cap he_cap;
struct ieee80211_he_6ghz_capa he_6ghz_capa;
struct ieee80211_sta_eht_cap eht_cap; /* Wi-Fi 7 */
};
802.11be (Wi-Fi 7, EHT) — 최신 세대
802.11be는 MLO(Multi-Link Operation), 320 MHz 채널 폭, 4096-QAM, Multi-RU(여러 RU를 하나의 STA에 할당), Preamble Puncturing을 도입합니다. 리눅스 커널에서는 6.2+ 버전부터 MLO 지원이 진행되고 있습니다.
| 기술 | 설명 | 리눅스 커널 지원 |
|---|---|---|
| MLO (Multi-Link) | 여러 대역(2.4+5+6GHz)에 동시 연결, 집합 처리량 또는 지연 최소화 | ieee80211_vif.link[], cfg80211 multi-link API (6.2+) |
| 320 MHz 채널 | 6GHz에서 320 MHz 연속 대역폭 | NL80211_CHAN_WIDTH_320, cfg80211_chan_def |
| 4096-QAM | MCS 12/13, 비트 당 12비트 → 20% 처리량 향상 | EHT MCS map |
| Multi-RU | 비연속 RU를 하나의 STA에 할당 | EHT PPDU format |
| Preamble Puncturing | 간섭 서브채널을 제외하고 나머지 사용 | cfg80211_chan_def.punctured |
/* MLO (Multi-Link Operation) 관련 구조체 */
struct ieee80211_vif {
/* ... */
bool valid_links; /* MLO 활성 여부 */
u16 active_links; /* 활성 링크 비트맵 */
u16 dormant_links; /* 휴면 링크 비트맵 */
struct {
struct ieee80211_bss_conf *conf; /* 링크별 BSS 설정 */
u8 addr[ETH_ALEN]; /* 링크별 MAC 주소 */
} link[IEEE80211_MLD_MAX_NUM_LINKS];
/* MLD (Multi-Link Device) 주소 */
u8 addr[ETH_ALEN]; /* MLD MAC 주소 */
};
/* MLO 링크별 채널 설정 */
struct cfg80211_chan_def {
struct ieee80211_channel *chan; /* 주 채널 */
enum nl80211_chan_width width; /* 채널 폭 */
u32 center_freq1; /* 중심 주파수 1 */
u32 center_freq2; /* 160+160 시 사용 */
u16 punctured; /* 펑처링 비트맵 (Wi-Fi 7) */
};
Mesh 네트워킹 (802.11s)
Mesh 네트워크 개요
IEEE 802.11s는 AP 없이 무선 노드들이 자율적으로 메시 토폴로지를 형성하는 표준입니다.
각 노드가 패킷을 릴레이(forwarding)하여 넓은 영역을 커버합니다.
리눅스 커널은 mac80211에 mesh 기능을 내장하고 있으며, iw 도구로 설정합니다.
Mesh 핵심 개념
| 용어 | 설명 | 커널 구조체 |
|---|---|---|
| Mesh Point (MP) | 메시 네트워크에 참여하는 노드 | ieee80211_if_mesh |
| Mesh BSS | 동일 Mesh ID, 프로파일을 가진 노드 집합 | ieee80211_mesh_cfg |
| MBSS (Mesh BSS) | 메시 기본 서비스 셋 | - |
| Mesh Gate | 외부 네트워크(유선)로의 게이트웨이 역할 | NL80211_MESHCONF_GATE_ANNOUNCE |
| HWMP | Hybrid Wireless Mesh Protocol (기본 경로 프로토콜) | mesh_path |
| Mesh Peering | 이웃 노드와의 연결 수립/관리 | sta_plink_state |
| Mesh Path | 목적지까지의 경로 정보 | struct mesh_path |
HWMP (Hybrid Wireless Mesh Protocol) 경로 프로토콜
/* mesh_path 구조체 (net/mac80211/mesh.h) */
struct mesh_path {
u8 dst[ETH_ALEN]; /* 목적지 MAC */
struct sta_info __rcu *next_hop; /* 다음 홉 STA */
struct timer_list timer; /* 경로 만료 타이머 */
u32 sn; /* 시퀀스 번호 */
u32 metric; /* 경로 메트릭 (ALM) */
u8 hop_count; /* 홉 수 */
unsigned long exp_time; /* 만료 시각 */
enum mesh_path_flags flags; /* ACTIVE, RESOLVING 등 */
spinlock_t state_lock;
struct sk_buff_head frame_queue; /* 경로 해석 대기 큐 */
struct rcu_head rcu;
};
/* HWMP 경로 요청/응답 */
/* PREQ (Path Request): 브로드캐스트, 목적지 경로 탐색 */
/* PREP (Path Reply): 유니캐스트, 경로 응답 */
/* PERR (Path Error): 경로 단절 알림 */
/* RANN (Root Announcement): 루트 노드 공지 */
Mesh 설정 예시
# 메시 인터페이스 생성
iw dev wlan0 interface add mesh0 type mesh
# 메시 네트워크 참가
iw dev mesh0 mesh join "my-mesh-network" freq 5180
# 메시 상태 확인
iw dev mesh0 station dump # 피어 목록
iw dev mesh0 mpath dump # 경로 테이블
iw dev mesh0 mesh param dump # 메시 파라미터
# 메시 게이트 활성화 (외부 네트워크 연결)
iw dev mesh0 set mesh_param mesh_gate_announcements=1
# 주요 메시 파라미터
iw dev mesh0 set mesh_param mesh_hwmp_rootmode=4 # proactive RANN
iw dev mesh0 set mesh_param mesh_fwding=1 # 포워딩 활성화
전원 관리 (Power Save)
802.11 전원 관리 메커니즘
무선 디바이스의 전력 소비를 줄이기 위해 802.11 표준은 다양한 절전 메커니즘을 정의합니다. STA는 AP에 절전 모드 진입을 알리고, AP는 해당 STA를 위한 프레임을 버퍼링합니다.
| 메커니즘 | 표준 | 동작 방식 | 지연 특성 | 커널 지원 |
|---|---|---|---|---|
| Legacy PS (PS-Poll) | 802.11 | STA가 비콘의 TIM 확인 → PS-Poll로 버퍼 프레임 요청 | 비콘 간격(100ms) 단위 지연 | mac80211 기본 |
| Dynamic PS | - | 유휴 시간 타이머 후 자동 절전 모드 진입 | 타이머 값 의존 (보통 100~500ms) | IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
| U-APSD | 802.11e | STA가 트리거 프레임 전송 → AP가 버퍼 프레임 전달 | STA 주도적 (VoIP 최적화) | IEEE80211_HW_SUPPORTS_UAPSD |
| TWT (Target Wake Time) | 802.11ax | AP와 STA가 정확한 깨어남 스케줄 합의 | 예측 가능, 스케줄 기반 | NL80211_CMD_SET_TWT (6.x+) |
mac80211 전원 관리 구현
/* mac80211 Power Save 설정 흐름 */
/* 1. 사용자 공간에서 PS 활성화 */
/* iw dev wlan0 set power_save on */
/* → NL80211_CMD_SET_POWER_SAVE → cfg80211_ops.set_power_mgmt() */
/* 2. mac80211 PS 상태 관리 */
struct ieee80211_conf {
u32 flags; /* IEEE80211_CONF_PS 비트 */
int dynamic_ps_timeout; /* Dynamic PS 타이머 (ms) */
int max_sleep_period; /* 최대 절전 기간 (비콘 수) */
/* ... */
};
/* 3. PS-Poll 프레임 전송 */
/* 비콘 수신 → TIM 확인 → 버퍼 데이터 존재 시 PS-Poll 전송 */
static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len,
struct ieee80211_rx_status *rx_status)
{
/* ... 비콘 처리 ... */
/* TIM에서 현재 STA의 AID 비트 확인 */
if (ieee80211_check_tim(tim_ie, tim_len, sdata->vif.cfg.aid)) {
/* AP에 버퍼된 프레임 존재 → PS-Poll 또는 QoS Null 전송 */
if (sdata->vif.cfg.ps) {
ieee80211_send_pspoll(sdata);
/* 또는 U-APSD 모드라면 트리거 프레임 전송 */
}
}
}
/* 4. Dynamic PS 타이머 */
/* 데이터 전송 후 timeout ms 동안 유휴 → PS 모드 진입 */
static void ieee80211_dynamic_ps_timer(struct timer_list *t)
{
struct ieee80211_local *local = from_timer(local, t, dynamic_ps_timer);
ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
}
TWT (Target Wake Time) — 802.11ax
TWT는 AP와 STA가 정확한 깨어남 시점을 사전 합의하여 전력 소모를 극적으로 줄입니다. 특히 IoT 디바이스에서 배터리 수명을 수 배 연장할 수 있습니다.
| TWT 유형 | 설명 | 사용 사례 |
|---|---|---|
| Individual TWT | 개별 STA-AP 간 1:1 합의 | IoT 센서, 저전력 디바이스 |
| Broadcast TWT | AP가 다수 STA에게 동일 TWT 스케줄 공지 | 다중 IoT 디바이스 동시 관리 |
| Restricted TWT | 802.11be에서 도입, 더 엄격한 스케줄 보장 | 실시간 애플리케이션 |
cfg80211 Regulatory Domain
무선 규제 개요
모든 무선 디바이스는 운용 국가의 주파수 규제를 준수해야 합니다.
리눅스 커널의 cfg80211은 규제 정보를 관리하여 허용되지 않은 채널/전력을 차단합니다.
wireless-regdb와 CRDA(Central Regulatory Domain Agent) 또는
내장 규제 데이터베이스를 통해 규제 정보를 로드합니다.
Regulatory 설정 소스
| 소스 | 우선순위 | 설명 | 커널 설정 |
|---|---|---|---|
| 드라이버/EEPROM | 최고 | 하드웨어에 내장된 규제 정보 | wiphy_apply_custom_regulatory() |
| 사용자 공간 (CRDA/iw) | 높음 | CRDA 데몬 또는 iw reg set | regulatory_hint_user() |
| 커널 내장 regdb | 중간 | 커널 컴파일 시 내장된 regulatory.db | CONFIG_CFG80211_REQUIRE_SIGNED_REGDB |
| Country IE (11d) | 낮음 | AP 비콘의 Country IE에서 추출 | cfg80211_rx_mlme_mgmt() |
규제 관련 커널 구조체
/* 규제 도메인 구조체 (include/net/regulatory.h) */
struct ieee80211_regdomain {
struct rcu_head rcu_head;
u32 n_reg_rules; /* 규칙 수 */
char alpha2[3]; /* 국가 코드 (예: "KR") */
enum nl80211_dfs_regions dfs_region; /* FCC/ETSI/JP */
struct ieee80211_reg_rule reg_rules[];
};
/* 개별 규제 규칙 */
struct ieee80211_reg_rule {
struct ieee80211_freq_range freq_range;
struct ieee80211_power_rule power_rule;
u32 flags; /* NL80211_RRF_NO_OUTDOOR, _DFS, _NO_IR 등 */
u32 dfs_cac_ms; /* DFS CAC 시간 (ms) */
};
struct ieee80211_freq_range {
u32 start_freq_khz; /* 시작 주파수 */
u32 end_freq_khz; /* 종료 주파수 */
u32 max_bandwidth_khz; /* 최대 채널 폭 */
};
struct ieee80211_power_rule {
u32 max_antenna_gain; /* 최대 안테나 이득 (mBi) */
u32 max_eirp; /* 최대 EIRP (mBm) */
};
/* 규제 힌트 제공 */
int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
/* 사용자 공간에서 규제 설정 */
/* iw reg set KR → NL80211_CMD_REQ_SET_REG → regulatory_hint_user() */
규제 설정 명령
# 현재 규제 도메인 확인
iw reg get
# 출력 예:
# country KR: DFS-JP
# (2402 - 2482 @ 40), (N/A, 23 dBm)
# (5170 - 5250 @ 80), (N/A, 20 dBm), NO-OUTDOOR, AUTO-BW
# (5250 - 5330 @ 80), (N/A, 20 dBm), NO-OUTDOOR, DFS, AUTO-BW
# (5490 - 5730 @ 160), (N/A, 30 dBm), DFS
# (5735 - 5835 @ 80), (N/A, 30 dBm)
# (5945 - 7125 @ 160), (N/A, 24 dBm), NO-OUTDOOR
# 규제 도메인 설정
iw reg set KR
# wireless-regdb 업데이트 (firmware 경로)
# /lib/firmware/regulatory.db
# /lib/firmware/regulatory.db.p7s (서명 파일)
채널 / 주파수 / 대역 관리
Wi-Fi 주파수 대역
| 대역 | 주파수 범위 | 채널 수 (20MHz) | 특징 | 커널 enum |
|---|---|---|---|---|
| 2.4 GHz | 2.412~2.484 GHz | 14 (국가별 다름) | 넓은 커버리지, 간섭 많음 | NL80211_BAND_2GHZ |
| 5 GHz | 5.170~5.835 GHz | 25 (U-NII 1~4) | DFS 채널 포함, 중간 대역폭 | NL80211_BAND_5GHZ |
| 6 GHz | 5.925~7.125 GHz | 59 (20MHz 기준) | Wi-Fi 6E/7 전용, 깨끗한 스펙트럼 | NL80211_BAND_6GHZ |
| 60 GHz | 57~71 GHz | - | 802.11ad/ay, WiGig | NL80211_BAND_60GHZ |
DFS (Dynamic Frequency Selection)
5GHz 대역의 일부 채널(DFS 채널)은 기상/군사 레이더와 공유됩니다. DFS는 레이더를 감지하면 즉시 채널을 전환하는 메커니즘입니다.
DFS 관련 커널 API
/* DFS 이벤트 알림 (드라이버 → cfg80211) */
void cfg80211_radar_event(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef,
gfp_t gfp);
/* → cfg80211이 NL80211_CMD_RADAR_DETECT 이벤트를 사용자 공간에 알림
→ hostapd가 CSA로 새 채널로 전환 */
/* CAC 시작 요청 */
int cfg80211_start_background_radar_detection(
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef);
/* CAC 완료 알림 */
void cfg80211_cac_event(struct net_device *netdev,
const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event,
gfp_t gfp);
/* 채널 플래그 */
#define IEEE80211_CHAN_DISABLED 0x0001
#define IEEE80211_CHAN_NO_IR 0x0002 /* 능동 전송 금지 */
#define IEEE80211_CHAN_RADAR 0x0008 /* DFS 필수 */
#define IEEE80211_CHAN_NO_HT40PLUS 0x0010
#define IEEE80211_CHAN_NO_HT40MINUS 0x0020
#define IEEE80211_CHAN_NO_80MHZ 0x0040
#define IEEE80211_CHAN_NO_160MHZ 0x0080
#define IEEE80211_CHAN_NO_320MHZ 0x0100 /* Wi-Fi 7 */
Rate Control 알고리즘 (Minstrel / Minstrel-HT)
Rate Control 개요
Rate Control(RC)은 무선 전송 속도를 동적으로 선택하는 알고리즘으로, 무선 성능의 핵심 요소입니다.
채널 상태가 변화하는 무선 환경에서 최적의 MCS(Modulation and Coding Scheme)를 실시간으로 결정해야 합니다.
mac80211은 Rate Control API를 제공하며, 드라이버가 자체 RC를 내장하지 않는 한(IEEE80211_HW_HAS_RATE_CONTROL)
소프트웨어 RC 알고리즘이 사용됩니다.
mac80211 Rate Control 알고리즘 비교
| 알고리즘 | 커널 소스 | 특징 | 적용 세대 | 상태 |
|---|---|---|---|---|
| Minstrel | net/mac80211/rc80211_minstrel.c | 통계 기반, 랜덤 샘플링으로 최적 rate 탐색 | 802.11a/b/g (Legacy) | 유지보수 (레거시) |
| Minstrel-HT | net/mac80211/rc80211_minstrel_ht.c | Minstrel 확장, HT/VHT/HE MCS 지원, 그룹 기반 샘플링 | 802.11n/ac/ax | 기본 알고리즘 |
Minstrel-HT 알고리즘 동작 원리
Minstrel-HT는 통계 기반 Rate Control 알고리즘으로, 각 MCS에 대한 전송 성공/실패 통계를 수집하여 예상 처리량(expected throughput)을 계산합니다. 주기적으로 랜덤 MCS를 시도(sampling)하여 채널 상태 변화에 적응합니다.
Minstrel-HT 핵심 구조체와 API
/* Minstrel-HT Rate 통계 (net/mac80211/rc80211_minstrel_ht.h) */
struct minstrel_rate_stats {
u16 attempts; /* 전송 시도 횟수 */
u16 success; /* 전송 성공 횟수 */
u16 last_attempts; /* 이전 기간 시도 */
u16 last_success; /* 이전 기간 성공 */
/* 확률 (EWMA) — 0~MINSTREL_FRAC(1,1) 범위 */
u16 prob_avg; /* 평균 성공 확률 (EWMA) */
u16 prob_avg_1; /* 이전 기간 확률 */
u8 sample_skipped; /* 샘플 건너뛴 횟수 */
bool retry_updated;
};
/* MCS 그룹별 Rate 정보 */
struct minstrel_mcs_group_data {
u8 index; /* 그룹 인덱스 */
u8 column; /* 현재 열 (스트림 수) */
struct minstrel_rate_stats rates[MCS_GROUP_RATES];
};
/* STA별 Minstrel-HT 상태 */
struct minstrel_ht_sta {
/* 현재 선택된 Rate 인덱스 */
u16 max_tp_rate[2]; /* 최대 처리량 rate [0]=최고, [1]=차순 */
u16 max_prob_rate; /* 최대 성공 확률 rate */
/* 그룹별 통계 */
struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB];
/* 샘플링 제어 */
u8 sample_group; /* 다음 샘플 그룹 */
u8 sample_count; /* 남은 샘플 수 */
u8 sample_slow; /* 느린 rate 샘플 카운터 */
/* EWMA 윈도우 */
unsigned long last_stats_update; /* 마지막 통계 갱신 jiffies */
unsigned int avg_ampdu_len; /* 평균 AMPDU 길이 */
};
/* Rate Control API — mac80211이 제공하는 콜백 구조 */
struct rate_control_ops {
const char *name;
void *(*alloc)(struct ieee80211_hw *hw);
void (*free)(void *priv);
void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp);
void (*free_sta)(void *priv, struct ieee80211_sta *sta, void *sta_priv);
void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
void *sta_priv, struct sk_buff *skb);
void (*get_rate)(void *priv, struct ieee80211_sta *sta,
void *sta_priv, struct ieee80211_tx_rate_control *txrc);
void (*rate_update)(void *priv, struct ieee80211_supported_band *sband,
struct cfg80211_chan_def *chandef,
struct ieee80211_sta *sta, void *sta_priv,
u32 changed);
};
코드 설명
-
2~11행
minstrel_rate_stats는 각 MCS에 대한 전송 성공/실패 통계입니다.prob_avg는 EWMA(지수 가중 이동 평균)로 계산된 성공 확률로, 0에서 MINSTREL_FRAC(1,1) 사이의 값입니다. -
20~23행
max_tp_rate[0]은 예상 처리량이 가장 높은 MCS,max_tp_rate[1]은 차순위입니다.max_prob_rate은 성공 확률이 가장 높은 MCS로, 재시도 체인에서 폴백으로 사용됩니다. -
36~46행
rate_control_ops는 mac80211의 RC 플러그인 인터페이스입니다.get_rate()가 TX 시 호출되어 rate를 선택하고,tx_status()가 TX 완료 후 통계를 갱신합니다.
Minstrel-HT MCS 그룹 구조
Minstrel-HT는 MCS를 "그룹"으로 분류합니다. 각 그룹은 동일한 스트림 수, GI(Guard Interval), 채널 폭의 조합입니다. 그룹 내에서 MCS 0~9(VHT) 또는 MCS 0~7(HT)을 독립적으로 추적합니다.
| 그룹 유형 | 조합 요소 | 그룹 수 (예시) | MCS/그룹 |
|---|---|---|---|
| HT (802.11n) | 스트림(1~4) × GI(Long/Short) × BW(20/40MHz) | 4 × 2 × 2 = 16 | 8 (MCS 0~7) |
| VHT (802.11ac) | 스트림(1~8) × GI(Long/Short) × BW(20/40/80/160MHz) | 8 × 2 × 4 = 64 | 10 (MCS 0~9) |
| HE (802.11ax) | 스트림(1~8) × GI(0.8/1.6/3.2μs) × BW(20/40/80/160MHz) | 8 × 3 × 4 = 96 | 12 (MCS 0~11) |
Minstrel-HT Rate 선택 로직 (재시도 체인)
/* TX 시 Rate 선택 — 4단계 재시도 체인 */
/* 1단계: max_tp_rate[0] — 최대 처리량 rate */
/* 예: MCS 7, 40MHz, Short GI → 300 Mbps (1SS) */
/* 재시도 횟수: 보통 2~4회 */
/* 2단계: max_tp_rate[1] — 차순위 처리량 rate */
/* 예: MCS 6, 40MHz, Short GI → 270 Mbps */
/* 재시도 횟수: 보통 2회 */
/* 3단계: max_prob_rate — 최대 확률 rate */
/* 예: MCS 4, 40MHz, Long GI → 120 Mbps */
/* 재시도 횟수: 보통 2회 */
/* 4단계: 최저 기본 rate (폴백) */
/* 예: MCS 0, 20MHz, Long GI → 6.5 Mbps */
/* 재시도 횟수: 나머지 전부 */
/* debugfs에서 Rate 통계 확인 */
/* cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/<MAC>/rc_stats */
/* 출력 예:
best ____________rate__________ ____statistics___ _____last____ ______sum-of________
mode guard # rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#retry | #suc | #att]
HT20 LGI 0 T TP MCS0 0 1648 6.5 6.5 100.0 1 0 0 12 10 12
HT20 LGI 1 tp MCS1 1 824 13.0 12.7 97.6 2 0 0 34 33 34
...
HT40 SGI 7 S P MCS7 15 100 300.0 285.3 95.1 4 0 0 456 434 456
*/
하드웨어 Rate Control (iwlwifi 예)
IEEE80211_HW_HAS_RATE_CONTROL 플래그가 설정된 드라이버(예: iwlwifi MVM)는
펌웨어 내장 RC를 사용합니다. 이 경우 mac80211의 Minstrel은 비활성화되고,
펌웨어가 자체 통계에 기반하여 Rate를 결정합니다.
/* iwlwifi MVM Rate Control 인터페이스 */
/* 펌웨어가 Rate를 결정하므로 mac80211 RC를 사용하지 않음 */
/* 드라이버 초기화 시 */
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
/* TX 시: mac80211이 rate 선택을 건너뛰고 드라이버에 위임 */
/* iwl_mvm_tx_skb() → iwl_mvm_set_tx_params()에서 rate 설정 */
/* 펌웨어 Rate Scale 알림 콜백 */
static void iwl_mvm_rs_rate_init(
struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
enum nl80211_band band)
{
/* 펌웨어에 초기 Rate Scale 테이블 전송 */
struct iwl_lq_cmd lq_cmd = {};
lq_cmd.sta_id = mvmsta->sta_id;
lq_cmd.reduced_tpc = 0;
/* 초기 rate: 현재 연결된 rate에서 시작 */
rs_get_initial_rate(mvm, sta, band, &lq_cmd);
/* Rate Scale 테이블을 펌웨어에 전송 */
iwl_mvm_send_lq_cmd(mvm, &lq_cmd, false);
}
debugfs를 통해 각 STA의 Rate 통계를 실시간으로 확인할 수 있습니다.
/sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/<MAC>/rc_stats
파일에서 각 MCS의 처리량, 성공 확률, 재시도 횟수를 볼 수 있습니다.
RC 알고리즘은 /sys/kernel/debug/ieee80211/phy0/rc_algorithm에서 확인합니다.
AMPDU / AMSDU 프레임 집합 (Aggregation)
프레임 집합 개요
802.11n 이후 프레임 집합(Aggregation)은 무선 효율을 크게 높이는 핵심 기술입니다. 무선 매체는 프레임 간 IFS(Inter-Frame Space), 프리앰블, ACK 등의 오버헤드가 크기 때문에, 여러 프레임을 하나로 묶어 전송하면 오버헤드를 줄이고 처리량을 극대화할 수 있습니다.
A-MSDU vs A-MPDU 비교
| 항목 | A-MSDU (Aggregate MSDU) | A-MPDU (Aggregate MPDU) |
|---|---|---|
| 집합 계층 | MAC 서브레이어 (LLC/SNAP 위) | MAC 레이어 (MPDU 단위) |
| 헤더 구조 | 공통 MAC 헤더 1개 + 서브프레임 헤더 | 각 MPDU에 독립 MAC 헤더 |
| 최대 크기 | 3839/7935 바이트 (HT cap에 따라) | 64K (HT), 1M (VHT/HE) |
| FCS | 집합 전체에 FCS 1개 | 각 MPDU에 FCS |
| 오류 복구 | 하나 손상 → 전체 재전송 | 손상된 MPDU만 개별 재전송 (Block ACK) |
| 암호화 | 집합 전체를 하나의 MPDU로 암호화 | 각 MPDU 독립 암호화 (더 안전) |
| 오버헤드 | 낮음 (헤더 공유) | 높음 (각 MPDU에 헤더+FCS) |
| 채널 오류 내성 | 약함 | 강함 (개별 재전송) |
| 실무 사용 | 소규모 프레임 묶기 | 대규모 데이터 전송의 핵심 |
mac80211 AMPDU 세션 관리
/* AMPDU 세션 관리 — mac80211 ampdu_action 콜백 */
/* AMPDU 액션 열거형 */
enum ieee80211_ampdu_mlme_action {
IEEE80211_AMPDU_RX_START, /* RX AMPDU 세션 시작 */
IEEE80211_AMPDU_RX_STOP, /* RX AMPDU 세션 중지 */
IEEE80211_AMPDU_TX_START, /* TX AMPDU 세션 시작 요청 */
IEEE80211_AMPDU_TX_OPERATIONAL, /* TX AMPDU 세션 운영 시작 */
IEEE80211_AMPDU_TX_STOP_CONT, /* TX 중지 (계속 전송 허용) */
IEEE80211_AMPDU_TX_STOP_FLUSH, /* TX 중지 (큐 비우기) */
IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, /* TX 중지 + 비움 + 계속 */
};
/* AMPDU 파라미터 */
struct ieee80211_ampdu_params {
struct ieee80211_sta *sta; /* 대상 STA */
u16 tid; /* Traffic ID (0~7) */
u16 ssn; /* Starting Sequence Number */
u16 buf_size; /* AMPDU 버퍼 크기 */
bool amsdu; /* A-MSDU in A-MPDU 허용 */
enum ieee80211_ampdu_mlme_action action;
};
/* TX AMPDU 세션 시작 흐름 */
/* 1. mac80211 → drv_ampdu_action(IEEE80211_AMPDU_TX_START)
2. 드라이버가 HW 큐 준비 → ieee80211_start_tx_ba_cb_irqsafe()
3. mac80211 → ADDBA Request 전송
4. 상대방 ADDBA Response 수신
5. mac80211 → drv_ampdu_action(IEEE80211_AMPDU_TX_OPERATIONAL)
6. 이제 해당 TID에 대해 A-MPDU 전송 가능 */
/* Block ACK 비트맵 구조 */
struct ieee80211_bar {
__le16 frame_control;
__le16 duration;
u8 ra[ETH_ALEN]; /* 수신자 */
u8 ta[ETH_ALEN]; /* 송신자 */
__le16 control; /* BAR Control */
__le16 start_seq_num; /* SSN (시작 시퀀스) */
} __packed;
/* Block ACK 비트맵: 각 비트가 하나의 MPDU 수신 상태 */
/* 1 = 수신 성공, 0 = 수신 실패 (재전송 필요) */
/* 비트맵 크기: 64비트 (normal) 또는 256비트 (compressed) */
A-MSDU in A-MPDU 설정
/* mac80211에서 A-MSDU in A-MPDU 지원 설정 */
/* 드라이버가 지원 선언 */
hw->max_tx_aggregation_subframes = 64; /* 최대 MPDU 수 */
hw->max_tx_fragments = 1; /* A-MSDU 비활성화 시 1 */
/* ieee80211_sta의 AMPDU 능력 확인 */
if (sta->deflink.ht_cap.ht_supported) {
/* A-MPDU 파라미터: 최대 길이, 최소 시작 간격 */
u8 ampdu_factor = sta->deflink.ht_cap.ampdu_factor;
/* 최대 A-MPDU 길이 = 2^(13 + ampdu_factor) - 1
factor=0: 8191, factor=1: 16383, factor=2: 32767, factor=3: 65535 */
u8 ampdu_density = sta->deflink.ht_cap.ampdu_density;
/* 0=제한없음, 1=0.25μs, 2=0.5μs, ... 7=16μs */
}
/* VHT에서 확장된 A-MPDU 길이 */
/* VHT max_ampdu_length_exp: 0~7 → 2^(13+factor) - 1
최대 1,048,575 바이트 (약 1MB) */
dmesg | grep -i ampdu로 세션 상태를 확인하고,
iw dev wlan0 station dump에서 rx ht-mcs-map과
tx ht-mcs-map으로 AMPDU 지원 여부를 확인하세요.
일부 드라이버에서는 modprobe 파라미터로 AMPDU를 비활성화할 수 있습니다
(예: iwlwifi 11n_disable=8).
빔포밍 (Beamforming)
빔포밍 개요
빔포밍(Beamforming)은 다중 안테나 시스템에서 전자기파의 위상과 진폭을 조절하여 특정 방향으로 신호를 집중시키는 기술입니다. 이를 통해 SNR(Signal-to-Noise Ratio)을 개선하고, 커버리지를 확장하며, 간섭을 줄입니다.
빔포밍 유형 비교
| 유형 | 표준 | 동작 방식 | 리눅스 지원 |
|---|---|---|---|
| Implicit Beamforming | 802.11n | 수신 채널 추정으로 TX 빔 결정 (채널 상호성 가정) | 제한적 (드라이버 의존) |
| Explicit Beamforming (SU) | 802.11ac/ax | Sounding 프레임 → 피드백 → 스티어링 매트릭스 계산 | VHT_CAP_SU_BEAMFORMER/BEAMFORMEE |
| MU-MIMO Beamforming | 802.11ac Wave2/ax | 여러 STA에 동시에 다른 빔 방사 (DL MU-MIMO) | VHT_CAP_MU_BEAMFORMER_CAPABLE |
| UL MU-MIMO | 802.11ax | 여러 STA가 동시에 AP에 전송, AP가 공간 분리 | HE PHY capabilities |
빔포밍 관련 커널 구조체
/* VHT Beamforming 능력 비트 */
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
/* Beamformee STS (Space-Time Streams) */
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK (0x7 << 13)
/* 값: 0~7 → STS = 값+1 (1~8 스트림) */
/* Sounding Dimensions (Beamformer가 지원하는 안테나 열 수) */
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16
#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK (0x7 << 16)
/* HE (802.11ax) Beamforming */
/* HE PHY에서 SU/MU/Trigger-based BF 지원 여부 확인 */
#define IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER 0x80
#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01
#define IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER 0x02
/* 드라이버에서 BF 능력 설정 예 */
vht_cap->cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
vht_cap->cap |= (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); /* 4 STS */
QoS / WMM (802.11e)
802.11e QoS 개요
802.11e 표준은 무선 LAN에 QoS(Quality of Service)를 도입합니다. WMM(Wi-Fi Multimedia)은 802.11e의 상용 구현으로, 트래픽을 4개의 액세스 카테고리(AC)로 분류하여 음성/영상 트래픽에 우선권을 부여합니다. 리눅스 커널의 mac80211은 4개의 TX 큐를 기본 제공합니다.
WMM 액세스 카테고리
| 액세스 카테고리 | 우선순위 | 매핑 UP(User Priority) | CWmin | CWmax | AIFSN | TXOP Limit | 사용 사례 |
|---|---|---|---|---|---|---|---|
| AC_VO (Voice) | 최고 | 6, 7 | 3 | 7 | 2 | 1.504ms | VoIP, 화상회의 |
| AC_VI (Video) | 높음 | 4, 5 | 7 | 15 | 2 | 3.008ms | 스트리밍, IPTV |
| AC_BE (Best Effort) | 보통 | 0, 3 | 15 | 1023 | 3 | 0 | 웹 브라우징, 이메일 |
| AC_BK (Background) | 최저 | 1, 2 | 15 | 1023 | 7 | 0 | 백업, 대량 다운로드 |
EDCA (Enhanced Distributed Channel Access) 동작
/* EDCA 파라미터 구조체 (mac80211) */
struct ieee80211_tx_queue_params {
u16 txop; /* TXOP 제한 (단위: 32μs) */
u16 cw_min; /* 최소 경쟁 윈도우 */
u16 cw_max; /* 최대 경쟁 윈도우 */
u8 aifs; /* AIFSN (Arbitration IFS Number) */
bool acm; /* Admission Control Mandatory */
bool uapsd; /* U-APSD 활성화 */
};
/* mac80211 TX 큐 매핑 */
/* ieee80211_ac_numbers 열거형 */
enum ieee80211_ac_numbers {
IEEE80211_AC_VO = 0, /* Voice */
IEEE80211_AC_VI = 1, /* Video */
IEEE80211_AC_BE = 2, /* Best Effort */
IEEE80211_AC_BK = 3, /* Background */
IEEE80211_NUM_ACS
};
/* 802.1D 우선순위 → AC 매핑 */
static const int ieee802_1d_to_ac[8] = {
IEEE80211_AC_BE, /* UP 0: Best Effort */
IEEE80211_AC_BK, /* UP 1: Background */
IEEE80211_AC_BK, /* UP 2: Background */
IEEE80211_AC_BE, /* UP 3: Best Effort */
IEEE80211_AC_VI, /* UP 4: Video */
IEEE80211_AC_VI, /* UP 5: Video */
IEEE80211_AC_VO, /* UP 6: Voice */
IEEE80211_AC_VO, /* UP 7: Voice */
};
/* AP가 비콘에 포함하는 EDCA Parameter Set IE */
/* WMM Information Element (vendor-specific, OUI: 00:50:F2, type: 2) */
/* STA는 연관 시 이 파라미터를 수신하여 자신의 TX 큐에 적용 */
/* bss_info_changed 콜백에서 EDCA 파라미터 업데이트 */
if (changed & BSS_CHANGED_QOS) {
for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
struct ieee80211_tx_queue_params *p = &sdata->tx_conf[ac];
/* 드라이버에 EDCA 파라미터 전달 */
drv_conf_tx(local, sdata, ac, p);
}
}
mac80211 fq_codel (Fair Queuing with CoDel)
mac80211은 각 TXQ에 fq_codel 스케줄러를 적용하여 공정한 큐잉과 bufferbloat 방지를 구현합니다. fq_codel은 플로우별 큐잉(per-flow fair queue)과 CoDel(Controlled Delay) AQM을 결합합니다.
| 구성 요소 | 역할 | 설정 |
|---|---|---|
| Fair Queue (FQ) | 플로우(5-tuple) 해시로 분류, 라운드 로빈 디큐 | fq_flows_cnt (기본 4096) |
| CoDel AQM | 큐잉 지연이 임계값(target) 이상이면 드롭 | target=5ms, interval=100ms |
| Airtime Fairness | 에어타임 기반 공정 스케줄링 (느린 STA 보호) | IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU |
Wi-Fi Direct / P2P
Wi-Fi Direct 개요
Wi-Fi Direct(P2P)는 AP 없이 디바이스 간 직접 연결을 허용하는 기술입니다.
리눅스에서는 wpa_supplicant가 P2P 기능을 제공하며,
커널의 cfg80211/mac80211은 P2P 인터페이스 유형과 관련 프레임 처리를 지원합니다.
P2P 핵심 개념
| 용어 | 설명 | 커널 매핑 |
|---|---|---|
| P2P Device | P2P 디스커버리 및 협상용 가상 인터페이스 | NL80211_IFTYPE_P2P_DEVICE |
| P2P GO (Group Owner) | 그룹의 AP 역할을 하는 디바이스 | NL80211_IFTYPE_P2P_GO |
| P2P Client | GO에 연결하는 클라이언트 | NL80211_IFTYPE_P2P_CLIENT |
| GO Negotiation | 누가 GO/Client가 될지 결정하는 3-way 핸드셰이크 | NL80211_CMD_FRAME (Action) |
| P2P Invitation | 기존 그룹에 새 피어 초대 | P2P Invitation Req/Resp Action |
| Service Discovery | 연결 전 서비스 검색 (Bonjour, UPnP) | GAS (Generic Advertisement Service) |
P2P 연결 시퀀스
디바이스 A 디바이스 B
| |
| 1. Device Discovery (Probe Req/Resp + P2P IE)
|<─────────────────────────────────────>|
| |
| 2. GO Negotiation Request |
|─────────────────────────────────────>|
| (Intent 값, 채널 목록) |
| |
| 3. GO Negotiation Response |
|<─────────────────────────────────────|
| (Intent 값, 채널 결정) |
| |
| 4. GO Negotiation Confirm |
|─────────────────────────────────────>|
| |
| [Intent가 높은 쪽이 GO, 같으면 타이브레이크 비트]
| |
| 5. Provisioning (WPS PBC/PIN) |
|<────────────────────────────────────>|
| |
| 6. GO: AP 모드 활성화 |
| 7. Client: WPA2 연결 + 4-Way HS |
|<────────────────────────────────────>|
| |
| 8. DHCP → 데이터 전송 |
|<════════════════════════════════════>|
커널 P2P 인터페이스 관련 코드
/* P2P 인터페이스 유형 (include/uapi/linux/nl80211.h) */
enum nl80211_iftype {
/* ... */
NL80211_IFTYPE_P2P_CLIENT, /* P2P 클라이언트 */
NL80211_IFTYPE_P2P_GO, /* P2P Group Owner */
NL80211_IFTYPE_P2P_DEVICE, /* P2P 디스커버리 전용 */
NL80211_IFTYPE_NAN, /* Neighbor Awareness Networking */
/* ... */
};
/* P2P 디바이스는 실제 netdev 없이 wdev만 가짐 */
/* Remain-on-Channel(ROC)로 특정 채널에서 대기하며 Action 프레임 교환 */
/* P2P GO 시작 = AP 모드 시작과 유사 */
/* NL80211_CMD_START_AP + P2P IE 포함 */
/* 동시 인터페이스 조합 예 */
static const struct ieee80211_iface_combination mydrv_iface_comb[] = {
{
.limits = (struct ieee80211_iface_limit[]) {
{ .max = 1, .types = BIT(NL80211_IFTYPE_STATION) },
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT) },
},
.n_limits = 2,
.max_interfaces = 2,
.num_different_channels = 2, /* MCC: 다중 채널 동시 */
},
};
Monitor 모드 / 패킷 캡처
Monitor 모드 개요
Monitor 모드는 무선 인터페이스가 모든 802.11 프레임을 수동적으로 캡처하는 모드입니다. 연결 상태 없이 주변의 모든 관리 프레임, 제어 프레임, 데이터 프레임을 수신할 수 있어 디버깅, 네트워크 분석, 보안 감사에 필수적입니다.
Monitor 모드 설정과 활용
# Monitor 인터페이스 생성 (기존 인터페이스 유지)
iw dev wlan0 interface add mon0 type monitor
# 또는 기존 인터페이스를 Monitor로 전환
ip link set wlan0 down
iw dev wlan0 set type monitor
ip link set wlan0 up
# 특정 채널 설정
iw dev mon0 set channel 36 HT40+
iw dev mon0 set freq 5180 80 5210 # 80MHz, center 5210
# Monitor 모드 플래그 설정
iw dev mon0 set monitor fcsfail control otherbss
# fcsfail: FCS 오류 프레임도 캡처
# control: 제어 프레임(ACK, RTS/CTS) 캡처
# otherbss: 다른 BSS의 프레임도 캡처
# tcpdump로 802.11 프레임 캡처
tcpdump -i mon0 -w capture.pcap -e
# -e: 링크 레이어 헤더 출력
# 특정 유형만 필터
tcpdump -i mon0 'type mgt' # 관리 프레임만
tcpdump -i mon0 'type mgt subtype beacon' # 비콘만
tcpdump -i mon0 'type data' # 데이터 프레임만
tcpdump -i mon0 'type ctl subtype ack' # ACK만
# tshark (Wireshark CLI)로 상세 분석
tshark -i mon0 -Y "wlan.fc.type_subtype == 0x08" # Beacon
tshark -i mon0 -Y "eapol" # EAPOL/4-way HS
tshark -i mon0 -Y "wlan.sa == aa:bb:cc:dd:ee:ff" # 특정 MAC
Radiotap 헤더
Monitor 모드에서 캡처된 프레임에는 Radiotap 헤더가 앞에 붙습니다. Radiotap은 드라이버가 PHY 레벨 정보(RSSI, Rate, 채널, 안테나 등)를 사용자 공간에 전달하는 표준 메타데이터 형식입니다.
/* Radiotap 헤더 (include/net/ieee80211_radiotap.h) */
struct ieee80211_radiotap_header {
u8 it_version; /* 항상 0 */
u8 it_pad;
__le16 it_len; /* 전체 Radiotap 길이 */
__le32 it_present; /* 포함된 필드 비트맵 */
} __packed;
/* Radiotap 필드 비트맵 */
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0, /* μs 타임스탬프 */
IEEE80211_RADIOTAP_FLAGS = 1, /* CFP, Short Preamble, WEP 등 */
IEEE80211_RADIOTAP_RATE = 2, /* 전송 속도 (500kbps 단위) */
IEEE80211_RADIOTAP_CHANNEL = 3, /* 주파수 + 채널 플래그 */
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, /* RSSI (dBm) */
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, /* 잡음 레벨 (dBm) */
IEEE80211_RADIOTAP_ANTENNA = 11, /* 안테나 인덱스 */
IEEE80211_RADIOTAP_MCS = 19, /* HT MCS 정보 */
IEEE80211_RADIOTAP_VHT = 21, /* VHT 정보 */
IEEE80211_RADIOTAP_HE = 23, /* HE (11ax) 정보 */
};
/* mac80211이 RX 프레임에 Radiotap 추가 */
/* ieee80211_add_rx_radiotap_header()에서 ieee80211_rx_status의
정보를 Radiotap 형식으로 변환하여 skb 앞에 삽입 */
패킷 주입 (Packet Injection)
Monitor 인터페이스를 통해 임의의 802.11 프레임을 전송(주입)할 수도 있습니다.
드라이버가 NL80211_FEATURE_TX_POWER_INSERTION을 지원하거나,
mac80211의 주입 경로를 통해 가능합니다. 인가된 보안 테스트에만 사용해야 합니다.
# 주입 가능 여부 확인
iw phy phy0 info | grep -i monitor
# 커널 설정 확인
# CONFIG_MAC80211_RC_MINSTREL=y 등이 필요
# mac80211 주입 경로:
# 사용자가 mon0 인터페이스로 raw 프레임 write
# → ieee80211_monitor_start_xmit()
# → Radiotap 헤더 파싱 (rate, channel 등 추출)
# → 802.11 프레임을 드라이버의 tx() 콜백으로 전달
WoWLAN (Wake on Wireless LAN)
WoWLAN 개요
WoWLAN은 시스템이 절전(suspend) 상태에 있을 때 특정 무선 이벤트가 발생하면 시스템을 깨우는 기능입니다. 유선 WoL(Wake on LAN)의 무선 확장이며, cfg80211과 드라이버가 협력하여 구현합니다.
WoWLAN 트리거 유형
| 트리거 | 설명 | nl80211 상수 |
|---|---|---|
| Disconnect | AP 연결 끊김 시 시스템 웨이크 | NL80211_WOWLAN_TRIG_DISCONNECT |
| Magic Packet | WoL 매직 패킷 수신 시 웨이크 | NL80211_WOWLAN_TRIG_MAGIC_PKT |
| 패턴 매칭 | 지정된 바이트 패턴과 일치하는 패킷 수신 시 | NL80211_WOWLAN_TRIG_PKT_PATTERN |
| GTK Rekey 실패 | GTK 키 갱신 실패 시 (보안 문제) | NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE |
| EAP Identity Request | 802.1X EAP 재인증 요청 수신 시 | NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST |
| 4-Way HS 요청 | 4-Way Handshake 재요청 수신 시 | NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE |
| TCP 연결 | 지정된 TCP 연결 유지 및 응답 패턴 감시 | NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNECTION |
| Net Detect | 절전 중 특정 SSID 스캔 발견 시 | NL80211_WOWLAN_TRIG_NET_DETECT |
WoWLAN 커널 구조체와 설정
/* WoWLAN 지원 선언 (드라이버) */
static const struct wiphy_wowlan_support mydrv_wowlan = {
.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_GTK_REKEY_FAILURE |
WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
WIPHY_WOWLAN_4WAY_HANDSHAKE |
WIPHY_WOWLAN_NET_DETECT,
.n_patterns = 20, /* 최대 패턴 수 */
.pattern_max_len = 256, /* 패턴 최대 길이 */
.pattern_min_len = 1, /* 패턴 최소 길이 */
.max_nd_match_sets = 11, /* Net Detect SSID 수 */
};
/* wiphy에 등록 */
wiphy->wowlan = &mydrv_wowlan;
/* cfg80211_ops WoWLAN 콜백 */
struct cfg80211_ops {
/* ... */
int (*suspend)(struct wiphy *wiphy,
struct cfg80211_wowlan *wow);
int (*resume)(struct wiphy *wiphy);
void (*set_wakeup)(struct wiphy *wiphy, bool enabled);
};
WoWLAN 사용자 공간 설정
# WoWLAN 지원 확인
iw phy phy0 wowlan show
# WoWLAN 트리거 설정
iw phy phy0 wowlan enable magic-packet disconnect
# 패턴 기반 웨이크 (예: 특정 포트의 TCP SYN)
iw phy phy0 wowlan enable patterns "offset 0+xx:xx:xx:xx:xx:xx"
# Net Detect (절전 중 SSID 스캔)
iw phy phy0 wowlan enable net-detect interval 5000 freqs 2412 2437 2462 \
matches ssid "my-network"
# 현재 WoWLAN 설정 확인
iw phy phy0 wowlan show
# WoWLAN 비활성화
iw phy phy0 wowlan disable
debugfs 무선 디버깅 인터페이스
debugfs 개요
리눅스 무선 서브시스템은 debugfs를 통해 풍부한 런타임 디버깅 정보를 제공합니다.
mac80211, cfg80211, 각 드라이버 모두 자체 debugfs 엔트리를 생성합니다.
/sys/kernel/debug/ieee80211/ 아래에서 접근할 수 있으며,
디버깅, 성능 분석, 문제 진단에 필수적입니다.
debugfs 디렉터리 구조
# debugfs 마운트 (보통 자동)
mount -t debugfs debugfs /sys/kernel/debug
# ieee80211 debugfs 트리 구조
/sys/kernel/debug/ieee80211/phy0/
├── airtime_flags # Airtime fairness 플래그
├── aqm # Active Queue Management 통계
├── force_tx_status # TX 상태 보고 강제
├── hwflags # IEEE80211_HW_* 플래그 목록
├── misc # 기타 정보
├── queues # TX 큐 상태
├── rc_algorithm # 현재 Rate Control 알고리즘 이름
├── total_ps_buffered # PS 버퍼된 총 프레임 수
├── wep_iv # WEP IV 카운터
│
├── netdev:wlan0/ # 인터페이스별
│ ├── flags # 인터페이스 플래그
│ ├── state # 인터페이스 상태
│ ├── tsf # TSF 타이머 값
│ ├── aqm # 인터페이스별 AQM
│ └── stations/ # 연결된 STA 목록
│ └── aa:bb:cc:dd:ee:ff/
│ ├── agg_status # AMPDU 세션 상태
│ ├── airtime # Airtime 사용량
│ ├── aqm # STA별 AQM 통계
│ ├── flags # STA 플래그
│ ├── last_signal # 마지막 수신 RSSI
│ ├── num_ps_buf_frames # PS 버퍼 프레임 수
│ ├── rc_stats # Rate Control 통계 (Minstrel)
│ ├── rc_stats_csv # RC 통계 CSV 형식
│ └── rx_stats # RX 통계
│
└── ath9k/ # 드라이버별 debugfs (예: ath9k)
├── ani # Adaptive Noise Immunity
├── dma # DMA 엔진 상태
├── interrupt # 인터럽트 카운터
├── recv # RX 통계
├── reset # 리셋 카운터
├── spectral_count # 스펙트럼 분석
├── spectral_scan_ctl # 스펙트럼 스캔 제어
├── xmit # TX 통계
└── queues # HW 큐 상태
주요 debugfs 활용 명령
# 현재 Rate Control 알고리즘 확인
cat /sys/kernel/debug/ieee80211/phy0/rc_algorithm
# 출력: minstrel_ht
# 하드웨어 플래그 확인
cat /sys/kernel/debug/ieee80211/phy0/hwflags
# 출력: HAS_RATE_CONTROL, SIGNAL_DBM, AMPDU_AGGREGATION, ...
# STA별 Rate Control 통계 (Minstrel-HT)
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/aa:bb:cc:dd:ee:ff/rc_stats
# AMPDU 세션 상태
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/aa:bb:cc:dd:ee:ff/agg_status
# 출력: 각 TID의 TX/RX AMPDU 세션 상태
# Airtime 사용량 확인
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/aa:bb:cc:dd:ee:ff/airtime
# TX 큐 상태 (AQM 통계)
cat /sys/kernel/debug/ieee80211/phy0/aqm
# TSF (Timing Synchronization Function) 타이머
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/tsf
# ath9k 인터럽트 통계
cat /sys/kernel/debug/ieee80211/phy0/ath9k/interrupt
# ath9k 스펙트럼 분석 활성화
echo 1 > /sys/kernel/debug/ieee80211/phy0/ath9k/spectral_scan_ctl
# iwlwifi 펌웨어 디버그 정보
cat /sys/kernel/debug/iwlwifi/*/iwlmvm/fw_rx_stats
cat /sys/kernel/debug/iwlwifi/*/iwlmvm/stations
트러블슈팅 체크리스트
기본 진단
# 1. 인터페이스 및 드라이버 확인
iw dev # 무선 인터페이스 목록
iw phy # PHY 장치 능력
ethtool -i wlan0 # 드라이버 이름/버전
lspci -k | grep -A3 -i wireless # PCI 디바이스 확인
lsusb | grep -i wireless # USB 디바이스 확인
# 2. 펌웨어 로드 확인
dmesg | grep -i firmware
dmesg | grep -i -E "iwlwifi|ath|mt76|rtw"
ls -la /lib/firmware/iwlwifi-* # Intel 펌웨어
ls -la /lib/firmware/ath* # Atheros 펌웨어
# 3. 규제 도메인 및 채널 상태
iw reg get
iw list | grep -A20 Frequencies
iw dev wlan0 survey dump # 채널별 사용/잡음 통계
# 4. 연결 상태 확인
iw dev wlan0 link # 현재 연결 정보
iw dev wlan0 station dump # STA 통계 (RSSI, TX/RX rate 등)
iw dev wlan0 info # 인터페이스 상세 정보
연결 문제 진단
# 5. 이벤트 실시간 추적
iw event -f -t # nl80211 이벤트 실시간 (-t: 타임스탬프)
sudo journalctl -u wpa_supplicant -f # wpa_supplicant 로그
sudo journalctl -u NetworkManager -f # NM 로그
# 6. 커널 로그 필터링
sudo dmesg | grep -i -E "cfg80211|mac80211|wlan|wireless"
sudo dmesg | grep -i -E "radar|dfs|cac" # DFS 관련
sudo dmesg | grep -i -E "auth|assoc|deauth" # 인증/연관
# 7. wpa_supplicant 상세 디버그
wpa_cli -i wlan0 status # 연결 상태
wpa_cli -i wlan0 scan # 스캔 시작
wpa_cli -i wlan0 scan_results # 스캔 결과
wpa_cli -i wlan0 log_level DEBUG # 디버그 레벨 변경
wpa_cli -i wlan0 signal_poll # 신호 레벨 조회
# 8. Dynamic debug 활성화 (상세 커널 로그)
echo 'module cfg80211 +p' > /sys/kernel/debug/dynamic_debug/control
echo 'module mac80211 +p' > /sys/kernel/debug/dynamic_debug/control
echo 'module iwlwifi +p' > /sys/kernel/debug/dynamic_debug/control
성능 문제 진단
# 9. 처리량 측정
iperf3 -c 192.168.1.1 -t 30 -P 4 # TCP 병렬 4스트림
iperf3 -c 192.168.1.1 -u -b 500M # UDP 500Mbps 목표
# 10. Rate Control 상태 확인
cat /sys/kernel/debug/ieee80211/phy0/rc_algorithm
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/*/rc_stats
# 11. 채널 혼잡도 확인
iw dev wlan0 survey dump | grep -A5 "in use"
# channel active time: 총 채널 사용 시간
# channel busy time: 채널 사용 중인 시간 (높으면 혼잡)
# channel receive time: 수신 시간
# channel transmit time: 송신 시간
# 12. AMPDU 상태 확인
cat /sys/kernel/debug/ieee80211/phy0/netdev:wlan0/stations/*/agg_status
# 13. 간섭 소스 확인 (ath9k 스펙트럼 분석)
echo chanscan > /sys/kernel/debug/ieee80211/phy0/ath9k/spectral_scan_ctl
cat /sys/kernel/debug/ieee80211/phy0/ath9k/spectral_scan0
흔한 문제와 해결책
| 증상 | 가능한 원인 | 진단 방법 | 해결책 |
|---|---|---|---|
| 인터페이스 미표시 | 드라이버/펌웨어 미로드 | dmesg | grep firmware |
펌웨어 패키지 설치, 드라이버 모듈 로드 |
| 스캔 결과 없음 | 규제 도메인 미설정, rfkill | rfkill list, iw reg get |
rfkill unblock wifi, iw reg set KR |
| 인증 실패 | 잘못된 PSK, SAE 미지원 | wpa_cli status, dmesg |
비밀번호 확인, WPA3 지원 드라이버 확인 |
| 연결 후 즉시 끊김 | 4-Way HS 실패, PMF 불일치 | EAPOL 캡처, iw event |
PMF 설정 확인, wpa_supplicant.conf 점검 |
| 느린 속도 | MCS 다운, 채널 혼잡, AMPDU 미사용 | rc_stats, survey dump | 채널 변경, AMPDU 확인, 안테나 확인 |
| 간헐적 끊김 | 로밍 실패, DFS 채널 전환 | iw event, dmesg radar |
DFS 채널 회피, 로밍 설정 조정 |
| AP 시작 실패 | DFS CAC 미완료, 채널 미지원 | iw list, dmesg | grep dfs |
비DFS 채널 사용, CAC 대기 |
| 높은 지연 | bufferbloat, PS 모드 | AQM 통계, iw dev wlan0 set power_save off |
Power Save 비활성화, fq_codel 확인 |
rfkill list로 소프트/하드 블록 상태를 확인하세요.
노트북의 물리 스위치(하드 블록)가 꺼져 있으면 소프트웨어로 해제할 수 없습니다.
소프트 블록은 rfkill unblock wifi로 해제합니다.
커널 설정
무선 서브시스템 핵심 옵션
| 옵션 | 설명 | 의존성 | 권장 |
|---|---|---|---|
CONFIG_WIRELESS | 무선 서브시스템 최상위 스위치 | - | y |
CONFIG_CFG80211 | 무선 규제/관리 코어 | WIRELESS | y |
CONFIG_CFG80211_WEXT | WEXT 호환 레이어 (구식 iwconfig 지원) | CFG80211 | y (호환성) |
CONFIG_CFG80211_DEBUGFS | cfg80211 debugfs 엔트리 | CFG80211, DEBUG_FS | y (디버깅) |
CONFIG_CFG80211_REQUIRE_SIGNED_REGDB | 서명된 regulatory.db만 허용 | CFG80211 | y (보안) |
CONFIG_MAC80211 | Soft-MAC 공통 스택 | CFG80211 | y |
CONFIG_MAC80211_DEBUGFS | mac80211 debugfs 엔트리 | MAC80211, DEBUG_FS | y (디버깅) |
CONFIG_MAC80211_MESH | 802.11s Mesh 네트워킹 지원 | MAC80211 | y (필요 시) |
CONFIG_MAC80211_LEDS | 무선 LED 트리거 지원 | MAC80211, NEW_LEDS | y |
CONFIG_MAC80211_RC_MINSTREL | Minstrel Rate Control | MAC80211 | y (기본) |
CONFIG_NL80211_TESTMODE | 드라이버 테스트 모드 경로 | CFG80211 | 필요 시 y |
CONFIG_RFKILL | RF 킬 스위치 지원 | - | y |
주요 드라이버 옵션
| 옵션 | 칩셋/드라이버 | 버스 | 권장 |
|---|---|---|---|
CONFIG_IWLWIFI | Intel Wi-Fi 4/5/6/7 | PCIe | m |
CONFIG_IWLMVM | Intel Modern Virtual MAC | - | m (IWLWIFI 의존) |
CONFIG_ATH9K | Qualcomm AR9xxx (Wi-Fi 4) | PCIe/AHB | m |
CONFIG_ATH10K | Qualcomm QCA9xxx (Wi-Fi 5) | PCIe/USB/SDIO | m |
CONFIG_ATH11K | Qualcomm QCN9xxx (Wi-Fi 6/6E) | PCIe/AHB | m |
CONFIG_ATH12K | Qualcomm WCN7850 (Wi-Fi 7) | PCIe | m |
CONFIG_MT76 | MediaTek 통합 프레임워크 | PCIe/USB/MMIO | m |
CONFIG_MT7915E | MediaTek MT7915 (Wi-Fi 6) | PCIe | m |
CONFIG_MT7996E | MediaTek MT7996 (Wi-Fi 7) | PCIe | m |
CONFIG_RTW88 | Realtek RTL8822x (Wi-Fi 5) | PCIe/USB | m |
CONFIG_RTW89 | Realtek RTL8852x (Wi-Fi 6) | PCIe/USB | m |
CONFIG_BRCMFMAC | Broadcom BCM43xx (Full-MAC) | SDIO/PCIe/USB | m |
디버깅 관련 커널 옵션
# 무선 디버깅에 유용한 커널 옵션
CONFIG_MAC80211_MESSAGE_TRACING=y # mac80211 메시지 트레이싱
CONFIG_MAC80211_DEBUG_MENU=y # mac80211 디버그 메뉴
CONFIG_MAC80211_VERBOSE_DEBUG=y # 상세 디버그 출력
CONFIG_CFG80211_DEVELOPER_WARNINGS=y # 개발자 경고
CONFIG_CFG80211_CERTIFICATION_ONUS=y # 인증 관련 검사 완화
CONFIG_DYNAMIC_DEBUG=y # 런타임 디버그 메시지 제어
CONFIG_DEBUG_FS=y # debugfs 지원
# 드라이버별 디버그 옵션
CONFIG_IWLWIFI_DEBUGFS=y # Intel 디버그
CONFIG_ATH9K_DEBUGFS=y # ath9k 디버그
CONFIG_ATH10K_DEBUGFS=y # ath10k 디버그
CONFIG_ATH11K_DEBUGFS=y # ath11k 디버그
참고자료
커널 공식 문서
- 커널 문서: mac80211 패킷 주입
- 커널 문서: cfg80211
- 커널 문서: 802.11 드라이버 API
- 커널 문서: mac80211 서브시스템
- 커널 문서: Regulatory 프레임워크
커뮤니티 및 위키
- Linux Wireless Wiki — 리눅스 무선 공식 위키
- mac80211 개발자 문서
- 무선 드라이버 목록 및 상태
- Regulatory 개발자 가이드
IEEE 표준
- IEEE 802.11-2020 — 802.11 통합 표준 (무료 공개)
- IEEE 802.11ax-2021 — Wi-Fi 6 (HE) 표준
- IEEE 802.11be (Draft) — Wi-Fi 7 (EHT) 표준 (개발 중)
- IEEE 802.11s-2011 — Mesh 네트워킹 표준
- IEEE 802.11w-2009 — Protected Management Frames
- IEEE 802.11r-2008 — Fast BSS Transition (FT)
도구
- wpa_supplicant — WPA/WPA2/WPA3 supplicant
- hostapd — AP/WPA authenticator
- iw — nl80211 기반 무선 설정 도구
- wireless-regdb — 무선 규제 데이터베이스
커널 소스 핵심 경로
| 경로 | 설명 |
|---|---|
net/wireless/ | cfg80211 코어 (regulatory, scan, connect, nl80211) |
net/mac80211/ | mac80211 (TX/RX, RC, PS, aggregation, mesh) |
include/net/cfg80211.h | cfg80211 API 헤더 |
include/net/mac80211.h | mac80211 API 헤더 (ieee80211_hw, ieee80211_ops) |
include/linux/ieee80211.h | 802.11 프레임/IE 구조체 정의 |
include/uapi/linux/nl80211.h | nl80211 사용자 공간 API (명령, 속성, 이벤트) |
drivers/net/wireless/ | 무선 드라이버 (ath, intel, mediatek, realtek 등) |