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 */
트러블슈팅 체크리스트
# 인터페이스 및 드라이버 확인
iw dev
iw phy
ethtool -i wlan0
# 규제 도메인 및 채널 상태
iw reg get
iw list | grep -A4 Frequencies
# 연결/인증 이벤트 추적
sudo journalctl -u wpa_supplicant -f
sudo dmesg | grep -i -E "cfg80211|mac80211|wlan|radar|dfs"
커널 설정
| 옵션 | 설명 | 권장 |
|---|---|---|
CONFIG_CFG80211 | 무선 규제/관리 코어 | y |
CONFIG_MAC80211 | Soft-MAC 공통 스택 | y |
CONFIG_NL80211_TESTMODE | 드라이버 테스트 경로 | 필요 시 y |
CONFIG_ATH11K | Qualcomm 802.11ax 드라이버 | m |
CONFIG_IWLWIFI | Intel 무선 드라이버 | m |