Try   HackMD

Linux 核心專題: 虛擬無線網路裝置驅動程式

執行人: jychen0611
專題解說錄影
投影片

Reviewed by marsh-fish

是否可以提供 Ad-hoc (IBSS) mode 的實作程式碼?

有關 Ad-hoc (IBSS) mode 相關程式碼的更新可見 Support ad hoc network #70
jychen0611

Reviewed by dcciou

請問是否知道封包的傳遞錯誤率

據我所知,目前 iw 相關命令無法提供 BER (bit error rate) 的相關底層傳輸資訊,但能透過 iw dev vw_i link 得知封包傳遞接收的數量及 byte 數統計。若想用模擬的方式推得 BER ,則須考量SNR (signal-to-noise ratio)、編碼模式、距離、阻擋等因素。可見 What is the relation between Bit Error Rate (BER), distance d and SNR(dB)?
jychen0611

任務簡介

vwifi 是個程式碼約~三千行,具體而微的 WiFi 裝置驅動程式,採用 cfg80211 框架。目前 vwifi 支援 scan, connect, disconnect 等 cfg80211 的介面操作,並得以正確處理 Tx/Rx 封包。

TODO: 支援 Linux v6.8+

commit 35ca058 / Align with recent cfg80211 header (#63)

  • The scan_width field is no longer present in the cfg80211_inform_bss structure.

commit 5add321 "wifi: cfg80211: remove scan_width support"

kernel version : v6.9-rc6 ~ v6.7-rc1
date : Sep 13, 2023

There really isn't any support for scanning at different channel widths than 20 MHz since there's no way to set it.
Remove this support for now, if somebody wants to maintain this whole thing later we can revisit how it should work.

- bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
  • The parameters in the change_beacon function have been updated to cfg80211_ap_update.

beacon [bee-kuhn]

a guiding or warning signal, as a light or fire, especially one in an elevated position.

在此指用來傳遞 BSS (Basic Service Set) 的相關訊息的 management frame,使其他無線裝置能得知該 BSS 的存在。

A beacon frame is a type of management frame in IEEE 802.11 WLANs. It contains information about the network. Beacon frames are transmitted periodically; they serve to announce the presence of a wireless LAN and to provide a timing signal to synchronise communications with the devices using the network (the members of a service set).

  • In an infrastructure basic service set (BSS), beacon frames are transmitted by the access point (AP).

  • In ad hoc (IBSS) networks, beacon generation is distributed among the stations.

commit bb55441 "wifi: cfg80211: split struct cfg80211_ap_settings"

kernel version : v6.9-rc6 ~ v6.7-rc1
date : Sep 25, 2023

Using the full struct cfg80211_ap_settings for an update is misleading, since most settings cannot be updated. Split the update case off into a new struct cfg80211_ap_update.


/**
 * struct cfg80211_ap_update - AP configuration update
 *
 * Subset of &struct cfg80211_ap_settings, for updating a running AP.
 *
 * @beacon: beacon data
 * @fils_discovery: FILS discovery transmission parameters
 * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
 */
+struct cfg80211_ap_update {
+	struct cfg80211_beacon_data beacon;
+	struct cfg80211_fils_discovery fils_discovery;
+	struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
+};

	int	(*change_beacon)(struct wiphy *wiphy, struct net_device *dev,
-				 struct cfg80211_ap_settings *info);
+				 struct cfg80211_ap_update *info);
    

commit 66f85d5 "wifi: cfg80211: modify prototype for change_beacon"

kernel version : v6.9-rc6 ~ v6.7-rc1
date : Sep 13, 2023

Modify the prototype for change_beacon() in struct cfg80211_op to accept cfg80211_ap_settings instead of cfg80211_beacon_data so that it can process data in addition to beacons.
Modify the prototypes of ieee80211_change_beacon() and driver specific functions accordingly.


	int	(*change_beacon)(struct wiphy *wiphy, struct net_device *dev,
-				 struct cfg80211_beacon_data *info);
+				 struct cfg80211_ap_settings *info);

Simply put, the change_beacon function now includes two additional parameters, fils_discovery and unsol_bcast_probe_resp, which are part of the cfg80211_ap_update structure.

  • fils_discovery : FILS discovery transmission parameters
  • unsol_bcast_probe_resp : Unsolicited broadcast probe response parameters

TODO: 建立背景知識

閱讀《802.11 Wireless Networks: The Definitive Guide, 2/e》建立基礎概念

筆記

Lightweight and Fast WiFi Access in Virtual Machines〉, Open Source Summit Europe 2023

TODO: Emulate rate and mcs

commit a8bdf8a / Support data rate and MCS (#67)

ref :
WI-FI 7 MCS TABLE
MCS Table

  • QPSK (4-QAM)
    • 利用
      0,90,180,270
      四個相位表示00 01 10 11,因此可表達 2 bits
  • QAM
    • 2n
      QAM 表一個 symbol 可表達 n bits

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

採用 802.11n (HT) 做為 PHY,設置如下 :

Modulation : 64-QAM
Data Bandwidth : 20MHz
Number of Spatial Streams : 4

參照 802.11n (HT) 調變對照表可得

Number of Data Subcarriers : 52
Number of Coded Bits per Subcarrier per Stream : 6
Coding : 5/6
OFDM Symbol Duration : 3.2 us
Guard Interval Duration : 0.8 us


NSD=52
NBPSCS=6

R=56

NSS=4

TDFT=3.2 us

TGI=0.8 µs

經公式推算後可得 data rate = 260 Mbps 與顯示結果相符

sinfo->filled = BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |
                ...
+               BIT_ULL(NL80211_STA_INFO_RX_BITRATE)|
+               BIT_ULL(NL80211_STA_INFO_TX_BITRATE);

/* Support 64-QAM modulation with 20MHz data bandwidth*/
+    sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
+    sinfo->rxrate.mcs = 31;
+    sinfo->rxrate.bw = RATE_INFO_BW_20;
+    sinfo->rxrate.n_bonded_ch = 1;

+    sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+    sinfo->txrate.mcs = 31;
+    sinfo->txrate.bw = RATE_INFO_BW_20;
+    sinfo->txrate.n_bonded_ch = 1;
tx bitrate:	260.0 MBit/s MCS 31
rx bitrate:	260.0 MBit/s MCS 31

TODO: 實作 vwifi_{set,get}_tx_power

commit f63872b / Support transmit power (#68)

在結構體 vwifi_vif 上新增 tx_power 以描述裝置的傳輸功率。

struct vwifi_vif {
    
+    /* Transmission power */
+    s32 tx_power;
};

cfg80211_ops 的架構上新增 vwifi_set_tx_powervwifi_get_tx_power 用以設定和取得裝置的功率。

static struct cfg80211_ops vwifi_cfg_ops = {
    
+    .set_tx_power = vwifi_set_tx_power,
+    .get_tx_power = vwifi_get_tx_power,
};

使用者可透過 iwconfig [interface] txpower [transmit power (dBm)] 設定裝置傳輸功率。
以下命令將 vw0 的傳輸功率設為 11 dBm

$ sudo iwconfig vw0 txpower 11
$ iw dev

phy#10
	Interface vw0
		ifindex 12
		wdev 0xa00000001
		addr 00:76:77:30:00:00
		type managed
		txpower 11.00 dBm

為了維持命令一致性,必須支援 iw 命令設置 transmit power。

由於使用 iw 命令會導致 set_tx_power 的輸入參數 wdev 為 NULL,詳見
cfg80211: allow per interface TX power setting

The TX power setting is currently per wiphy (hardware
device) but with multi-channel capabilities that doesn't
make much sense any more.

Allow drivers (and mac80211) to advertise support for
per-interface TX power configuration. When the TX power is configured for the wiphy, the wdev will be NULL and the driver can still handle that, but when a wdev is given the TX power can be set only for that wdev now.
Signed-off-by: Johannes Berg johannes.berg@intel.com

因此新增函式 wiphy_get_vwifi_vif 以利用參數 wiphy 取得裝置的 virtual interface。

此外,亦利用參數 type 以區別命令為 auto/limit/fixed。

  • auto : 使用預設傳輸功率
  • limit : 限制功率上下限於特定值
  • fixed : 可隨意設置功率

使用者可使用 iw dev [interface] set txpower [auto/limit/fixed] [transmit power (mBm)] 來設定。

  • 注意這邊的功率單位為 mBm (1dBm = 100mBm)

以下命令將 vw0 的傳輸功率設為 1100 mBm (即 11 dBm)

$ sudo iw dev vw0 set txpower fixed 1100
$ iw dev

phy#45
	Interface vw0
		ifindex 48
		wdev 0x2d00000001
		addr 00:76:77:30:00:00
		type managed
		txpower 11.00 dBm

TODO: 實作 Ad-hoc (IBSS) mode

commit a5fc5f0 / Support ad hoc network (#70)

ibss

新增 AD-HOC interface type

wiphy 上新增 NL80211_IFTYPE_ADHOC interface type,使其能透過 vwifi_change_iface 的 operation 切換成 Ad-hoc (IBSS) 模式。

static int vwifi_change_iface(...)
{
    switch (type) {
    ...
+    case NL80211_IFTYPE_ADHOC:
+        ndev->ieee80211_ptr->iftype = type;
+        break;
    ...
}

wiphy->interface_modes =
        BIT(NL80211_IFTYPE_STATION) | 
        BIT(NL80211_IFTYPE_AP) | 
+       BIT(NL80211_IFTYPE_ADHOC);

使用者可透過命令 iw dev [interface] set type ibss 將裝置切換成 IBSS 模式。

$ sudo iw dev vw3 set type ibss
$ iw dev vw3 info

Interface vw3
	ifindex 61
	wdev 0x3a00000001
	addr 00:76:77:33:00:00
	type IBSS
	wiphy 58
	txpower 0.00 dBm

實作 IBSS join 與 leave 機制

cfg80211_ops 的架構上新增 vwifi_join_ibssvwifi_leave_ibss 使 IBSS 裝置能加入特定 IBSS cell 及頻段。

static struct cfg80211_ops vwifi_cfg_ops = {
    ...
+    .join_ibss = vwifi_join_ibss,
+    .leave_ibss = vwifi_leave_ibss,
};

使用者可透過命令 iw dev [interface] ibss join [SSID] [freq in MHz] [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [fixed-freq] [<fixed bssid>] [beacon-interval <TU>] [basic-rates <rate in Mbps,rate2,>] [mcast-rate <rate in Mbps>] [key d:0:abcde] 加入特定 IBSS cell 並同時建置其它設定。若此 IBSS cell 原先不存在則創建之。

以下命令使 vw3 加入 SSID 為 ibss1 的 IBSS cell,且指定頻段為 2412 MHz。

$ sudo iw dev vw3 ibss join ibss1 2412 NOHT fixed-freq 02:11:22:33:44:55 beacon-interval 100 basic-rates 6,12 mcast-rate 6 key d:0:abcde
$ iw dev vw3 info

Interface vw3
	ifindex 51
	wdev 0x3000000001
	addr 00:76:77:33:00:00
	ssid ibss1
	type IBSS
	wiphy 48
	txpower 14.00 dBm

若要離開目前的 IBSS cell,則可使用 iw dev [interface] ibss leave

$ sudo iw dev vw3 ibss leave
$ iw dev vw3 info

Interface vw3
	ifindex 51
	wdev 0x3000000001
	addr 00:76:77:33:00:00
	type IBSS
	wiphy 48
	txpower 14.00 dBm

vwifi_join_ibss 中應紀錄 AD-HOC 之相關設定。
紀錄 AD-HOC 相關資訊的結構體定義在 virtual interface 中。

/* Structure for AD-HOC mode */
struct {
    /* List node for storing ibss (vwifi->ibss_list is the head),
     * this field is for interface in AD-HOC mode.
     */
    struct list_head ibss_list;
    struct cfg80211_chan_def ah_chandef;
    u16 ah_beacon_int;
    u32 ah_basic_rates;
    bool ah_channel_fixed;
    bool ah_privacy;
    bool ah_control_port;
    bool ah_control_port_over_nl80211;
    bool ah_userspace_handles_dfs;
    int ah_mcast_rate[NUM_NL80211_BANDS];
    struct ieee80211_ht_cap ah_ht_capa;
    struct ieee80211_ht_cap ah_ht_capa_mask;
    struct key_params *ah_wep_keys;
    int ah_wep_tx_key;
};

在全域結構體 vwifi_context 中新增 ibss_list 以便尋找 ibss 裝置,當裝置 join 後便會被加入 ibss_list,若裝置 leave 則會被移出。

 INIT_LIST_HEAD(&vwifi->vif_list);
 INIT_LIST_HEAD(&vwifi->ap_list);
+INIT_LIST_HEAD(&vwifi->ibss_list);
/* Context for the whole program, so there's only single vwifi_context
 * regardless of the number of virtual interfaces. Fields in the structure
 * are interface-independent.
 */
struct vwifi_context {
    /* We may not need this lock because vif_list would not change during
     * the whole lifetime.
     */
    struct mutex lock;
    enum vwifi_state state;    /**< indicate the program state */
    struct list_head vif_list; /**< maintaining all interfaces */
    struct list_head ap_list;  /**< maintaining multiple AP */
+   struct list_head ibss_list;/**< maintaining all ibss devices */
    char *denylist;            /**< maintaining the denylist */
};

實作 AD-HOC 封包傳遞機制

在轉送前要確認 source 和 destination 是否處於相同 IBSS cell,以及確認是否在該 IBSS cell 的同個 BSS 中。

/* TX by interface of IBSS(ad-hoc) mode */
else if (vif->wdev.iftype == NL80211_IFTYPE_ADHOC) {
    /* Check if the packet is broadcasting */
    if (is_broadcast_ether_addr(eth_hdr->h_dest)) {
        list_for_each_entry (dest_vif, &vwifi->ibss_list, ibss_list) {
            /* Don't send broadcast packet back to the source interface.
             */
            if (ether_addr_equal(eth_hdr->h_source,
                                 dest_vif->ndev->dev_addr))
                continue;
            /* Don't send packet from dest_vif's denylist */
            if (denylist_check(dest_vif->ndev->name, vif->ndev->name))
                continue;
            /* Don't send packet to device with different SSID. */
            if (strcmp(vif->ssid, dest_vif->ssid))
                continue;
            /* Don't send packet to device with different BSSID. */
            if (!ether_addr_equal(vif->bssid, dest_vif->bssid))
                continue;
            if (__vwifi_ndo_start_xmit(vif, dest_vif, skb))
                count++;
        }
    }
    /* The packet is unicasting */
    else {
        list_for_each_entry (dest_vif, &vwifi->ibss_list, ibss_list) {
            if (ether_addr_equal(eth_hdr->h_dest,
                                 dest_vif->ndev->dev_addr)) {
                /* Don't send packet from dest_vif's denylist */
                if (denylist_check(dest_vif->ndev->name, vif->ndev->name))
                    continue;
                /* Don't send packet to device with different SSID. */
                if (strcmp(vif->ssid, dest_vif->ssid))
                    continue;
                /* Don't send packet to device with different BSSID. */
                if (!ether_addr_equal(vif->bssid, dest_vif->bssid))
                    continue;
                if (__vwifi_ndo_start_xmit(vif, dest_vif, skb))
                    count++;
            }
        }
    }
}

Ping Test

測試一 : 同 IBSS cell 中 ping 特定裝置

vw3, vw4, vw5 皆在同 IBSS cell 中,讓 vw3 ping vw4,可發現封包正常傳遞。

$ sudo ip netns exec ns3 ip addr add 10.0.0.4/24 dev vw3
$ sudo ip netns exec ns4 ip addr add 10.0.0.5/24 dev vw4
$ sudo ip netns exec ns5 ip addr add 10.0.0.6/24 dev vw5
$ sudo ip netns exec ns3 ping -c 1 10.0.0.5    
================================================================================
Ping Test: IBSS vw3 (10.0.0.4) (in ibss1) <--> IBSS vw4 (10.0.0.5) (in ibss1)

(should success)
(be patient, it will take some time to route...)
================================================================================
PING 10.0.0.5 (10.0.0.5) 56(84) bytes of data.
64 bytes from 10.0.0.5: icmp_seq=1 ttl=64 time=0.098 ms

--- 10.0.0.5 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.098/0.098/0.098/0.000 ms

觀察核心訊息可發現在 vw3 的 ARP cache 中原先無 10.0.0.5 對應的 mac address。
因此流程如下:

  1. vw3 會先發送 ARP Request 封包 (broadcast) 請求 10.0.0.5 對應的 mac address。
  2. vw4 會回傳 ARP Reply (內含 vw4 的 mac address),vw5 則無視之。
  3. vw3 收到 vw4 回傳的 ARP Reply 後,再進行 ICMP 封包傳遞 (Ping Request)。
  4. vw4 收到 vw3 的 Ping Request 後,回傳 Ping Reply
Created with Raphaël 2.2.0vw3vw3vw4vw4vw5vw5ARP RequestARP RequestARP ReplyPing RequestPing Reply
[  717.657196] broadcasting
[  717.657204] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[  717.657208] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  717.657212] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw5 (ff:ff:ff:ff:ff:ff)
[  717.657214] vwifi: IBSS vw5 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  717.657236] unicasting
[  717.657237] vwifi: IBSS vw4 (00:76:77:34:00:00) send packet to IBSS vw3 (00:76:77:33:00:00)
[  717.657238] vwifi: IBSS vw3 (00:76:77:33:00:00) receive packet from IBSS vw4 (00:76:77:34:00:00)
[  717.657247] unicasting
[  717.657248] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (00:76:77:34:00:00)
[  717.657249] vwifi: IBSS vw4 (00:76:77:34:00:00) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  717.657263] unicasting
[  717.657264] vwifi: IBSS vw4 (00:76:77:34:00:00) send packet to IBSS vw3 (00:76:77:33:00:00)
[  717.657265] vwifi: IBSS vw3 (00:76:77:33:00:00) receive packet from IBSS vw4 (00:76:77:34:00:00)

測試二 : ping 處於不同 IBSS cell 的裝置

vw3vw5 處於不同 IBSS cell,讓 vw3 ping vw5,如預期般失敗,原因在於兩者處於不同 IBSS,無法通訊。

$ sudo ip netns exec ns3 ip addr add 10.0.0.4/24 dev vw3
$ sudo ip netns exec ns4 ip addr add 10.0.0.5/24 dev vw4
$ sudo ip netns exec ns5 ip addr add 10.0.0.6/24 dev vw5
$ sudo ip netns exec ns3 ping -c 1 10.0.0.6
================================================================================
Ping Test: IBSS vw3 (10.0.0.4) (in ibss1) <--> IBSS vw5 (10.0.0.6) (in ibss2)

(should fail)
(be patient, it will take some time to route...)
================================================================================
PING 10.0.0.6 (10.0.0.6) 56(84) bytes of data.
From 10.0.0.4 icmp_seq=1 Destination Host Unreachable

--- 10.0.0.6 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

觀察核心訊息可發現, vw3 三度嘗試用 ARP Request 請求 mac address,但沒有裝置回應。

[ 3272.467235] broadcasting
[ 3272.467244] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 3272.467249] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[ 3273.492554] broadcasting
[ 3273.492598] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 3273.492613] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[ 3274.518330] broadcasting
[ 3274.518372] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 3274.518385] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)

測試三 : ping 處於 STA mode 的裝置

vw3 為 IBSS mode, vw2 則為 STA mode,讓 vw3 ping vw2,如預期般失敗。

$ sudo ip netns exec ns2 ip addr add 10.0.0.3/24 dev vw2
$ sudo ip netns exec ns3 ip addr add 10.0.0.4/24 dev vw3
$ sudo ip netns exec ns4 ip addr add 10.0.0.5/24 dev vw4
$ sudo ip netns exec ns3 ping -c 1 10.0.0.3
================================================================================
Ping Test: IBSS vw3 (10.0.0.4) (in ibss1) <--> STA vw2 (10.0.0.3)

(should fail)
(be patient, it will take some time to route...)
================================================================================
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
From 10.0.0.4 icmp_seq=1 Destination Host Unreachable

--- 10.0.0.3 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

如同測試二,vw3 三度嘗試用 ARP Request 請求 mac address,但沒有裝置回應。

[ 4208.333391] broadcasting
[ 4208.333399] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 4208.333403] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[ 4209.349666] broadcasting
[ 4209.349709] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 4209.349748] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[ 4210.375102] broadcasting
[ 4210.375162] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[ 4210.375190] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)

使 IBSS 支援掃描

/* inform with dummy BSS */
    inform_bss(vif);
+   ah_inform_bss(vif);

執行 scan 可發現該 bss 資訊

BSS 00:76:77:30:00:00(on vw1)
	TSF: 4320753904 usec (0d, 01:12:00)
	freq: 2437
	beacon interval: 100 TUs
	capability: ESS Privacy (0x0011)
	signal: -43.00 dBm
	last seen: 0 ms ago
	SSID: test
	Supported rates: 1.0* 2.0* 5.5 11.0 
	DS Parameter set: channel 6
	RSN:	 * Version: 1
		 * Group cipher: CCMP
		 * Pairwise ciphers: CCMP
		 * Authentication suites: PSK
		 * Capabilities: 1-PTKSA-RC 1-GTKSA-RC (0x0000)
	Extended capabilities:
		 * SSID List
BSS 00:76:77:33:00:00(on vw1)
	TSF: 4320753917 usec (0d, 01:12:00)
	freq: 2412
	beacon interval: 300 TUs
	capability: IBSS (0x0002)
	signal: -45.00 dBm
	last seen: 0 ms ago
BSS 00:76:77:35:00:00(on vw1)
	TSF: 4320753921 usec (0d, 01:12:00)
	freq: 2412
	beacon interval: 200 TUs
	capability: IBSS (0x0002)
	signal: -45.00 dBm
	last seen: 0 ms ago


[ 4320.753585] vwifi: vw1 performs scan, found vw0 (SSID: test, BSSID: 00:76:77:30:00:00)
[ 4320.753594] cap = 17, beacon_ie_len = 43
[ 4320.753601] vwifi: vw1 performs scan, found vw3 (SSID: ibss1, BSSID: 00:76:77:33:00:00)
[ 4320.753604] cap = 2, beacon_ie_len = 0
[ 4320.753607] vwifi: vw1 performs scan, found vw4 (SSID: ibss1, BSSID: 00:76:77:33:00:00)
[ 4320.753609] cap = 2, beacon_ie_len = 0
[ 4320.753611] vwifi: vw1 performs scan, found vw5 (SSID: ibss2, BSSID: 00:76:77:35:00:00)
[ 4320.753612] cap = 2, beacon_ie_len = 0


WPA support in IBSS mode

建立設定檔 wpa_supplicant_ibss.conf

network={
    ssid="ibss1"
    mode=1
    frequency=2412
    key_mgmt=WPA-PSK
    proto=RSN
    pairwise=CCMP
    group=CCMP
    psk="12345678"
}

測試情境 1

使用命令 wpa_supplicant 設定 vw3vw4 加入 ibss1

$ wpa_supplicant -i vw3 -B -c scripts/wpa_supplicant_ibss.conf    

Successfully initialized wpa_supplicant

$ wpa_supplicant -i vw4 -B -c scripts/wpa_supplicant_ibss.conf    

Successfully initialized wpa_supplicant

觀察 interface 資訊可發現兩者皆成功加入 ibss1

Interface vw3
	ifindex 12
	wdev 0x900000001
	addr 00:76:77:33:00:00
	ssid ibss1
	type IBSS
	wiphy 9
	txpower 14.00 dBm
Interface vw4
	ifindex 13
	wdev 0xa00000001
	addr 00:76:77:34:00:00
	ssid ibss1
	type IBSS
	wiphy 10
	txpower 15.00 dBm

仔細觀察核心訊息可發現一開始 ibss1 不存在,於是 vw3 創建之。而 vw4 透過掃描得知 ibss1 的存在,並加入之。

[  205.578356] vwifi : vw3 start acting in IBSS mode.
[  205.578720] vwifi : vw3 join ibss1.
[  205.639498] vwifi: vw4 performs scan, found vw3 (SSID: ibss1, BSSID: 00:00:00:00:00:00)
[  205.639506] cap = 18, beacon_ie_len = 35
[  205.640141] vwifi : vw4 start acting in IBSS mode.
[  205.640475] vwifi : vw4 join ibss1.

值得注意的一點是,使用 WPA 創建 ibss 網路,其 BSSID 應由系統自動生成 (這樣可確保了每個 IBSS 網路的唯一性),因此並不會出現在 join 函式的輸入參數中。
因此當 join 參數的 BSSID 為 NULL 時,應比對當前存在的 ibss 網路。若有符合其 WPA 設定則沿用 BSSID ,否則以當前裝置的 MAC address 作為新網路的 BSSID。

/* When the BSSID is automatically generated by the system, it will not be
 * passed as a parameter to the join function. */
if (params->bssid)
    memcpy(vif->bssid, params->bssid, ETH_ALEN);
else {
    /* Search for IBSS networks with WPA settings in the IBSS list. If a
     * matching network exists, join it. Otherwise, create one. */
    memcpy(vif->bssid, ndev->dev_addr, ETH_ALEN);
    struct vwifi_vif *ibss_vif = NULL;
    list_for_each_entry (ibss_vif, &vwifi->ibss_list, ibss_list) {
        if (ibss_vif->ssid_len == vif->ssid_len &&
            !memcmp(ibss_vif->ssid, vif->ssid, vif->ssid_len) &&
            ibss_vif->ibss_chandef.center_freq1 ==
                vif->ibss_chandef.center_freq1) {
            memcpy(vif->bssid, ibss_vif->bssid, ETH_ALEN);
            break;
        }
    }
}

嘗試讓 vw3 ping vw4 ,封包傳遞成功。

$ sudo ip netns exec ns3 ping -c 1 10.0.0.5
================================================================================
Ping Test: IBSS vw3 (10.0.0.4) (in ibss1) <--> IBSS vw4 (10.0.0.5) (in ibss1)

(should success)
(be patient, it will take some time to route...)
================================================================================
PING 10.0.0.5 (10.0.0.5) 56(84) bytes of data.
64 bytes from 10.0.0.5: icmp_seq=1 ttl=64 time=1031 ms

--- 10.0.0.5 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1031.052/1031.052/1031.052/0.000 ms
[  206.559641] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[  206.559650] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  206.559699] vwifi: IBSS vw4 (00:76:77:34:00:00) send packet to IBSS vw3 (00:76:77:33:00:00)
[  206.559701] vwifi: IBSS vw3 (00:76:77:33:00:00) receive packet from IBSS vw4 (00:76:77:34:00:00)
[  206.559706] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (00:76:77:34:00:00)
[  206.559708] vwifi: IBSS vw4 (00:76:77:34:00:00) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  206.559727] vwifi: IBSS vw4 (00:76:77:34:00:00) send packet to IBSS vw3 (00:76:77:33:00:00)
[  206.559728] vwifi: IBSS vw3 (00:76:77:33:00:00) receive packet from IBSS vw4 (00:76:77:34:00:00)

測試情境 2

vw5 以手動方式創建並加入 ibss2vw3vw4 則以 WPA 設定加入 ibss1

$ sudo ip netns exec ns5 iw dev vw5 set type ibss
$ sudo ip netns exec ns5 iw dev vw5 ibss join ibss2 2412 NOHT fixed-freq 00:76:77:35:00:00 beacon-interval 300 

$ sudo ip netns exec ns3 ip addr add 10.0.0.4/24 dev vw3
$ sudo ip netns exec ns4 ip addr add 10.0.0.5/24 dev vw4
$ sudo ip netns exec ns5 ip addr add 10.0.0.6/24 dev vw5
    
$ sudo ip netns exec ns3 wpa_supplicant -i vw3 -B -c scripts/wpa_supplicant_ibss.conf
$ sudo ip netns exec ns4 wpa_supplicant -i vw4 -B -c scripts/wpa_supplicant_ibss.conf

觀察核心訊息可發現,由於 vw5 先創建 ibss2 ,所以 vw3 一開始設定時會掃描到 ibss2 ,然而這並不符合 vw3 的 WPA 設定。於是 vw3 會自己創建一個 ibss1 。隨後 vw4 也會進行掃描,並同時發現 ibss1ibss2 ,選擇 ibss1 加入之。

[  961.600176] vwifi : vw5 start acting in IBSS mode.
[  961.613599] vwifi : vw5 join ibss2.
[  962.020891] vwifi: vw3 performs scan, found vw5 (SSID: ibss2, BSSID: 00:76:77:35:00:00)
[  962.020897] cap = 2, beacon_ie_len = 0
[  962.021099] vwifi : vw3 start acting in IBSS mode.
[  962.021256] vwifi : vw3 join ibss1.
[  962.159989] vwifi: vw4 performs scan, found vw5 (SSID: ibss2, BSSID: 00:76:77:35:00:00)
[  962.159998] cap = 2, beacon_ie_len = 0
[  962.160004] vwifi: vw4 performs scan, found vw3 (SSID: ibss1, BSSID: 00:00:00:00:00:00)
[  962.160006] cap = 18, beacon_ie_len = 35
[  962.160645] vwifi : vw4 start acting in IBSS mode.

vw3 ping vw5 ,很明顯無法傳遞封包。

$ sudo ip netns exec ns3 ping -c 1 10.0.0.6
================================================================================
Ping Test: IBSS vw3 (10.0.0.4) (in ibss1) <--> IBSS vw5 (10.0.0.6) (in ibss2)

(should fail)
(be patient, it will take some time to route...)
================================================================================
PING 10.0.0.6 (10.0.0.6) 56(84) bytes of data.
From 10.0.0.4 icmp_seq=1 Destination Host Unreachable

--- 10.0.0.6 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

[  963.141034] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[  963.141039] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  964.156816] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[  964.156873] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)
[  965.193847] vwifi: IBSS vw3 (00:76:77:33:00:00) send packet to IBSS vw4 (ff:ff:ff:ff:ff:ff)
[  965.193908] vwifi: IBSS vw4 (ff:ff:ff:ff:ff:ff) receive packet from IBSS vw3 (00:76:77:33:00:00)

Demo video

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Reference

2022q1 vwifi
Linux 核心專題: vwifi
Lightweight and Fast WiFi Access in Virtual Machines
802.11 Wireless Networks: The Definitive Guide, 2/e
LKMPG
cfg80211_ops
WI-FI 7 MCS TABLE
MCS Table
iw commands