執行人: horseface1110, dingsen-Greenhorn
Dingsen-Greenhorn 解說影片(可調整的 MCS)
horseface1110 解說影片(模擬延遲)
charliechiou部分敘述會有全形半形的差異,如 : MCS 及 MCS 圖片的使用上可以去除原先來源的Figure 1 等 caption 並附上來源,建議可做修改。
Response by 'dingsen-Greenhorn'
感謝建議,修改標題全形 MCS 統一半形。
salmoniscute僅有在解說影片說明使用 Long GI 與 Short GI 的分別考量,建議可以整理在筆記 擴展 USER 手動調整 MCS 的範圍並且同時可以調整 GI(Guard Interval) 此 section 的開頭。
Response by 'dingsen-Greenhorn'
感謝建議,在開頭寫出。
liangchingyun是 bit rate 還是 bitrate? 須整篇統一。
Response by 'dingsen-Greenhorn'
感謝建議,已更正。
horseface1110用簡單的方式,依照訊號強度區間來動態自動選擇 MCS
請問這之後的程式碼中,-50、-70、-90的區段劃分是有什麼理論的依據或是白皮書的指示嗎?還是單純就想這樣設定
另外,commit連結無法看到了
Response by 'dingsen-Greenhorn'
IEEE 802.11 標準文件不會明確指出「RSSI 到某值時應用哪個 MCS」,因為這涉及裝置廠商對 RF 硬體、通道狀況預測、錯誤率容忍度、使用情境等多種因素的調整。因此,此部分通常是個廠商演算法與競爭力核心,不會有公開文件。
你所提出的理想情況下理論依據是有的 optimal solution 是 Water-Filling Algorithm,但這裡為了實現將功能簡化,未來可以考慮。(邏輯上粗淺推論,通道增益是與功率相乘,當通道增益過小,功率必須極大,不划算)
commit 800ad32 / Support Linux v6.11
ctx = false to maintain behavior of legacy APIcommit c502eb8 "virtio: Introduce struct virtqueue_info and find_vqs_info() config op"
kernel version : v6.11-rc1 ~
date : Jul 17, 2024
Using separate arrays for names, callbacks, and contexts when setting up virtqueues is error-prone and not extensible.
To simplify and consolidate queue configuration, a new struct virtqueue_info was introduced.
This structure bundles name, callback, and ctx together into a single unit.
commit 6c85d6b/Support Linux 6.15
kernel version : v6.11-rc1 ~
Jul 17, 2024
Since the original virtio_find_vqs() is no longer present, rename
virtio_find_vqs_info() back to virtio_find_vqs().
commit a50af43/Support Linux 6.15
commit 908a1d7 "hrtimer: Introduce hrtimer_setup() to replace hrtimer_init()"
kernel version : v6.13-rc1 ~
date : Nov 7, 2024
The legacy hrtimer_init() was replaced by hrtimer_setup() to provide a safer, clearer API.
The new interface requires the callback function to be explicitly passed during initialization, avoiding assignment errors.
commit 9779489"hrtimers: Delete hrtimer_init()"
kernel version : v6.15-rc1 ~
date : Apr 5, 2025
hrtimer_init() is now unused. Delete it.
commit75f36f5/Support Linux v6.1.84
commit 9b13df3f "timers: Rename del_timer_sync() to timer_delete_sync()"
kernel version: v6.1.84 ~
date: Nov 24, 2022
del_timer_sync() was renamed to timer_delete_sync() for naming consistency.
The old name remains as a wrapper but is discouraged in new code.
commit f82e7df/ Support Linux v6.14
commit 7a53af8"wifi: cfg80211: send MLO links tx power info in GET_INTERFACE"
kernel version: v6.14-rc1 ~
date: Dec 4, 2024
To support Multi-Link Operation (MLO), the get_tx_power callback now includes a link_id parameter.
TX power can be reported per link via NL80211_ATTR_MLO_LINKS in GET_INTERFACE.
For non-MLO interfaces, behavior remains unchanged.
傳輸延遲應能根據目前的 bitrate 動態調整,以模擬不同傳輸速率下的封包傳輸行為。
該 TODO: 傳輸延遲應與目前 bitrate 成反比,自動或手動調整
由於原始的 vwifi 驅動將傳輸速率(bitrate)寫死為固定值(MCS 31,260 Mbps),這導致在測試環境中無法模擬不同 bitrate 對網路行為(如延遲)的影響。因此,我的目標是:
iw dev set bitrates 指令,讓使用者能透過 CLI 設定速率。station dump 顯示與實際傳輸行為中。為了找出一個實作 set_bitrate_mask 的標準範例,我閱讀了多個已有驅動的實作邏輯,包括:
ath9k_htc_set_bitrate_mask(有實作)ieee80211_set_bitrate_mask(有實作)drv_set_bitrate_maskrdev_set_bitrate_mask其中我選擇主要參考 mac80211 子系統下的 ieee80211_set_bitrate_mask(),原因如下:
vwifi 虛擬設備所在層級相同,需要的參數也相同,更適合作為設計參考。ieee80211_sdata_running)HAS_RATE_CONTROL)我將這些核心邏輯濃縮後,實現在 vwifi_set_bitrate_mask() 中,並以 bitmask 判斷使用者是否設定了合理的速率範圍(以 vwifi_supported_rates[] 為依據定義 2.4GHz / 5GHz 的合法範圍)。
為了讓 bitrate_mask 的設定不只是一個瞬時指令,而是能影響整體傳輸與查詢行為,我在 vwifi 的結構中新增儲存欄位:
這段實作有兩個目的:
vwifi_vif 中預留空間保存設定值,避免設定後在後續流程中失效。get_station() 與封包傳輸)能夠引用相同設定,確保查詢與行為一致。get_station 中我從 vif->bitrate_mask 推算出應顯示的傳輸速率;而在傳輸封包時,則根據這個速率計算應延遲的時間,並使用 udelay() 模擬出來。不過在實作延遲模擬的過程中,我發現無法在 __vwifi_ndo_start_xmit() 中直接呼叫 vwifi_get_station(),查明後發現vwifi_get_station 是專為 cfg80211 框架設計的接口函數,他複雜的參數結構和錯誤處理機制使其不適合作為內部函數直接呼叫
在實作延遲模擬(於 __vwifi_ndo_start_xmit() 函式中)時,我遇到一個問題是「如何從 bitrate_mask 中取出正確的傳輸速率」。最初我考慮是否需要進行單位換算,但後來深入閱讀了 iw 的原始碼與 Linux 的 nl80211.h 定義,發現:
NL80211_RATE_INFO_BITRATE的單位為 100 kbps,而vwifi_supported_rates[].bitrate的單位亦相同。
這讓我確認可以直接使用 vwifi_supported_rates[i].bitrate(不需再乘上 10 或 1000),並應用於延遲計算公式:
此公式的邏輯為:將資料長度轉為 bit,再除以 kbps 速率,得出理論延遲(單位為 microseconds),透過 udelay() 注入延遲模擬。
這樣的設計讓系統可以根據設定的 bitrate 自動對應不同的延遲行為,並在 station dump 中正確顯示對應速率。
為驗證我的 bitrate_mask 實作是否實際影響傳輸延遲,我設計了一組系統性實驗,模擬多組不同速率設定下的實際傳輸表現。具體流程如下:
sudo ip netns exec ns0 iw dev vw0 set bitrates legacy-2.4 <bitrate_list> 指令設定 bitmask。bitrate_list 的內容依據 vwifi_supported_rates[] 所定義的速率順序進行選擇。1 2 11),驅動會從 bitmask 中選取最低的速率作為該連線實際使用的 txrate / rxrate。for (int i = 0; i < 32; i++),會從 bitmask 的最低有效位元開始找第一個被設定的速率。根據這些測試,我繪製出下方圖表,可明顯看出 bitrate 越低,平均延遲越高
如圖所示,bitrate 數值越低時,平均延遲明顯上升;當 bitrate 提升至一定程度後,延遲曲線趨於平緩,呈現合理的反比趨勢,驗證模擬行為符合預期。
而這是沒有依照bitrate調整延遲的情況:
此時的vwifi沒有實作延遲模擬,這些延遲是來自於系統的實際處理時間
為支援動態環境下的 MCS 選擇邏輯,需實作 MCS 查表功能以便快速對應 MCS index 至實際資料速率與 GI 組合。此查表亦用於 station_dump 與傳輸時間模擬中,並支援 iw dev set bitrates 指令後的即時速率查詢與驗證,故將 MCS 表建置為全域結構以提升查詢效率與可維護性。
為支援 HT 模式(802.11n)在 2.4 GHz 頻段下的傳輸速率計算與模擬,新增靜態 ht_mcs_table,涵蓋 MCS index 0–31,對應 20 MHz 頻寬下 0.8 µs 及 0.4 µs GI(Guard Interval)所對應的 bitrate(Kbps)。
該表格作為全域結構,支援快速查詢速率,便於未來支援:
iw dev set bitrates ht-mcs-2.4 指令執行後之速率驗證另提供 get_ht_bitrate_kbps() 輔助函式,可依據 vwifi_vif 中當前的 MCS index 與 GI 設定,查詢實際資料速率(單位:Kbps):
目前整體流程已可完成:
TODO: 提交延遲測試和分析的自動化腳本
TODO: 針對應用場景去提供延遲模擬
調變與編碼組合 (Modulation and Coding Scheme, MCS) 應允許程式化控制與調整,以符合各種測試場景中對於 PHY 層吞吐量模擬的需求。
在 IEEE 802.11 無線網路架構中,MCS 決定了所使用的調變方式(如 BPSK、QPSK、16-QAM 等)以及 FEC 編碼率 (如 1/2、3/4),因此對 bitrate 與傳輸延遲具直接影響。現代無線網路裝置通常支援根據訊號品質進行動態 MCS 調整 (即 rate adaptation),而在虛擬裝置中,若能以使用者空間介面(例如 netlink 或 debugfs)手動調整 MCS,將有助於研究 WiFi stack 在不同傳輸品質下的行為。
由於前一版本 vwifi driver,是無法調整調變與編碼(MCS fixed 31, lgi, 260 Mpbs),進而調整其傳輸速率,這對於許多設備,像是邊緣裝置而言,會有許多的資源浪費。舉手機為例,通常的使用習慣是少數時間下載與看影片時,有大量傳輸的需求,其他大多數時間,只需要少數傳輸需求。然而固定 64-QAM 的調變會大幅增加功率消耗,對於邊緣裝置而言,是非常致命的,會大幅降低裝置使用時間。
以下,大略粗估 QPSK (MCS 1) 與 64-QAM (MCS 31) 在相同錯誤率下所需的功率比較。(不考慮多天線與編碼)
錯誤率估計相關文獻
從以上這張圖可以看到,在 Rayleigh fading 通道下(無線中裝置在典型的城市中通道)錯誤率與功率比較。
可以看到在固定(uncoded)錯誤率 10^-4 下,QPSK 與 64-QAM 功率差距超過 26dB。(功率差距超過 398 倍)(圖中黑線)
這裡只單純考慮傳送功率,現實環境中 High-QAM 還會進一步增加耗能元件功率,使用者之間的干擾,裝置發熱所造成的效能降低等等…。
因此,現代無線通訊裝置,通常會動態調整 MCS,來大幅降低功率消耗,這也是我實作的最初動機。
commit 0c6c24b
這個 commit 主要依照以下模擬的通道訊號強度來決定所使用的 MCS。
用簡單的方式,依照訊號強度區間來動態自動選擇 MCS
commit 0c6c24b
此想法主要來自我的 reviewer @jychen0611 他提出一個有趣的想法,就是使用者可以根據自身需求來調整 MCS 。
實現的方法架構為:
依照上述架構實現出可以手動調整的 MCS
實作 cfg80211_ops 中的 set_bitrate_mask 回呼函式以支援手動 MCS 設定
功能說明
本次實作在 Linux 無線網路架構中的 cfg80211_ops 結構體中,加入 set_bitrate_mask 回呼函式,用於支援使用者透過 iw 工具手動設定 Modulation and Coding Scheme(MCS) 指數。這項功能允許開發者或進階使用者在測試環境中精確控制 Wi-Fi 傳輸的調變與編碼方式。
入口點:使用者設定
透過 iw dev <dev> set bitrates ht-mcs-2.4 <mcs>,由 cfg80211 呼叫驅動提供的 set_bitrate_mask()。
驅動在 vwifi_cfg_ops 中註冊了此 callback:
MCS 解析與驗證
驅動從 mask->control[NL80211_BAND_2GHZ].ht_mcs[i] 提取 MCS bitmask。
搜尋前 32 個 MCS index(4 個 byte × 8 bit)並取第一個有效的 index。
僅允許 index 為 {7, 15, 23, 31},否則拒絕設定。
儲存使用者設定
將選定的 MCS index 存入 vwifi_vif 結構:
若無法取得合法 MCS 或介面未連線(SME_CONNECTED),則記錄錯誤並返回 -EINVAL。
跨模組共享使用者設定,未來當 vwifi_get_station() 被呼叫查詢速率資訊時,若 manual_mcs_set為 true,即回傳 manual_mcs 對應速率。
否則落回自動 MCS 選擇策略(如 RSSI-based selection),也就是 commit 0c6c24b 實現的功能。
儲存欄位擴充說明
在 vwifi_vif 結構中新增欄位,以保存完整的 bitrate 設定,支援未來查詢或封包模擬:
struct cfg80211_bitrate_mask bitrate_mask;
並於 callback 函式中保存使用者設定:
Test commands format
result
commit a9b4edd
為什麼現代無線通訊系統要用多天線 (spatial stream) 呢?有什麼好處?
由於基地台會同時服務多個用戶,也因此需要多個 RF-Chain 來分別傳輸不同資料流,當有 N 個用戶時,RF-Chain 必須至少 N 個才能滿足不同用戶同時傳輸。
並且就算在一個用戶的情形下,多天線也有極大好處。
由 Shannon's Channel Capacity theorem 相關文獻 。我們可以用數學非常清楚證明出的通道中的 Upper bond 的極限 Capacity,也就是可以傳輸的最大速率。
如以下圖片:
此數學式為:
從上圖中可以看到,當我增加我的傳輸功率(可以粗略的想成增加 QAM )
我所得到的傳輸速率會在我逐漸增加功率時,被一個緩慢遞增的 log2 函數限制,也就是說當增加功率時,所能得到的 Capacity(頻譜使用效率)越來越少。
當然從這個公式中的 B 可以突破限制,使得 Capacity 線性成長。然而,現實中,
頻譜是一個非常寶貴的資源,需要與政府購買。甚至像是 Wi-Fi 使用的是 ISM band 為免費資源。有此可知增加頻段很難實現。
那解決的方法就是 MIMO 多天線系統,他會使得上面數學式變成以下情況。
M 就是我的天線數量,當我增加天線時,也可以線性增加 Capacity,避免了 log2 的速率成長,也同時避免增加昂貴的頻譜資源。
因此,在通訊的技術發展上,增加天線數,成為關鍵技術,也是現代無線通訊裝置的必要技術之一。
由上可以知道,我們可以進一步將多天線考慮進 vwifi driver 實現的方向。
原始 vwifi 驅動程式中,手動 MCS 僅支援部分固定 index(如 7、15、23、31),對於 4 spatial streams 對應的 MCS 24–31 並未完整支援。
本次開發的目標為:
擴展 vwifi_set_bitrate_mask() 的驗證邏輯以允許 MCS 24–31。
在 vwifi_get_station() 中增加對 MCS 24–31 對應的 modulation 和 coding scheme(例如 BPSK、QPSK、16-QAM、64-QAM)。
| MCS | Modulation | Coding Rate | Spatial Streams |
|---|---|---|---|
| 24 | BPSK | 1/2 | 4 |
| 25 | QPSK | 1/2 | 4 |
| 26 | QPSK | 3/4 | 4 |
| 27 | 16-QAM | 1/2 | 4 |
| 28 | 16-QAM | 3/4 | 4 |
| 29 | 64-QAM | 2/3 | 4 |
| 30 | 64-QAM | 3/4 | 4 |
| 31 | 64-QAM | 5/6 | 4 |
並考慮編碼與資訊流(也就是 最少 4 個 RF-Chain ,與最少 4 隻天線)
以下為 commit code 參考。
commit 9f8dfc2
commit fc181b9
擴展手動調整功能並考量同時可調整 GI (guard Interval)
先說結論,城市中適合 long GI ,鄉村適合 short GI。
GI(Guard Interval,保護間隔)是現代 OFDM(正交分頻多工)系統中的一項關鍵技術,特別在 Wi-Fi(如 802.11n/ac/ax)或 LTE/5G 中扮演抑制干擾與增進系統穩定性的角色。以下我們詳細說明它所解決的三大問題與其相關背景:
ISI 是當前一個符號還未完全接收完畢時,下一個符號已經開始進入接收器所造成的干擾。在多路徑傳播環境中,前一個符號的尾端會以延遲形式(multipath delay)重疊到下一個符號的開頭,導致接收錯誤。
GI 的解決方法:
為了防止多路徑延遲干擾下一個符號,GI 被插入於每個 OFDM 符號之間,其長度 至少與最大多徑延遲相當,這樣即使有延遲,重疊的訊號也只會落在 GI 範圍中,而不會影響下一個有效符號。
成效:
減少 BER(Bit Error Rate)
增強穩定性與通訊可靠性
OFDM 利用「正交」子載波傳送不同數據。然而,由於多路徑或頻率偏移(如 Doppler shift),這些子載波可能不再完全正交,導致頻率重疊與干擾,也就是 ICI。
GI 的解決方法:
雖然 GI 本身不是直接為 ICI 設計,但搭配「循環前綴」(cyclic prefix)可以使子載波保持正交性,進一步降低 ICI。
成效:
保持子載波正交性,減少頻域間干擾
穩定 FFT 解調過程,維持頻率解析度
在離散傅立葉轉換(DFT)領域,卷積對應到頻域乘法。但若接收器採用 FFT(有限長度 DFT),則「線性卷積」會產生邊界效應。
GI 作為 Cyclic Prefix:
GI 的內容是 將 OFDM 符號尾端的一段資料複製到開頭,這稱為「循環前綴」。這麼做的好處是:
能夠將通道效應視為「循環卷積」
FFT 解調後可直接使用頻域等化(例如單一子載波頻率上的簡單除法)
好處與優點:
減少通道估計與等化的複雜度
提升解調準確率
與 ISI/ICI 抑制聯合作用
實現講解
gi_mode 模組參數支援
你加入了新的模組參數 gi_mode,可讓使用者透過 modprobe 或 echo 寫入來切換 Long GI(0.8 µs)與 Short GI(0.4 µs),取代原本寫死的:
在 vwifi_set_bitrate_mask() 函數中,根據 bitrate_mask.control[].gi 值解析 GI 模式,並記錄 log:
這樣在實驗時能透過 GI 選擇參數靈活調整傳輸效率與抗干擾能力。
你透過 bitrate_mask.control[].ht_mcs[] 的 bitmask 判斷啟用的 MCS 指數,新增 loop 遍歷並找出最高有效的 MCS:
此段確保使用者在啟用多個 MCS 時,優先採用最高者,兼顧性能與測試效率。若沒設定,預設回退為 MCS 0。
3. 調變與編碼率解析
你加入 MCS 對應到 modulation 與 coding rate 的 mapping 表,在如 vwifi_get_station()報告時印出對應資訊:
這對 debug 及測試時了解每個傳輸模式的實際調變與編碼非常重要,並符合 802.11n 規格。
4. GI 標記反饋至 get_station
在 vwifi_get_station() 中新增回報 txrate.flags:
讓 iw dev link 可正確反映使用的是 Short GI 或 Long GI,達成用戶層觀察傳輸行為的能力。
詳細參考此 commit 部分
commit acc1bd1
commit 75fc59c
Verify.sh為了自動化測試所有實作的 MCS table 與不同 GI (guard interval)
寫出 Verify.sh
詳細參考此 commit script 部分
commit 75fc59c
Result:(part of the log)