四、 實作
4.1 硬體和系統環境
為了在真的環境上面實作,查閱了相關的研究,去找尋有公開原始碼的 驅動程式(open source driver),Atheros 有公開晶片 Linux 驅動程式的原 始碼,使用 Atheros 晶片的網卡都可以使用這個驅
動程式來驅動。所以我們選擇了幾台筆記型電腦,
作業系統均為 Linux Red Hat 9.0,每台上面均裝 有 D-link DWL-AG650 的網路卡,它是使用 Atheros 的晶片,這讓我們可以修改公開的原始碼來把我們
的管理協定實作在上面。 圖 13、D-link 網路卡
圖 14、實作環境
我們利用這些筆記型電腦當成是一個個的網格點(mesh point),讓它們 形成隨建即連網路(ad-hoc network),並固定其位置模擬無線網狀網路 (mesh network),無線網狀網路和隨建即連網路有很大的共通性,差別在 於無線網狀網路有閘道可以連上網際網路(internet),且無線網狀網路沒 有行動性(mobility),我們讓這些筆記型電腦模擬一個無線網狀網路的雛 形(prototype)來當成我們要的環境。
4-2、程式架構
我 們 的 管 理 協 定 是 屬 於 OSI 七 層 網 路 模 型 的 鏈 結 層 (Data Link Layer),而在 Linux 的網路架構下是簡易的分成四層,我們所要修改的是
最底層鏈結層。
下圖 15 為 Linux 使用者空間(user space)、核心空間(kernel space) 和網路驅動程式(network driver)之間的關係,上層使用者空間的行程 (user space processes)透過系統呼叫(system call)跟核心來通溝,而核 心內行程的溝通都是使用函式呼叫(function call)的方式,在 Linux 的網 路分層架構下,每一層之間都有佇列(queue)把出境封包暫存起來,等到有 時間可以處理時,才使用函式呼叫去處理送出的動作,而外來的封包則是 使用中斷(interrupt)的方式來通知驅動程式,驅動程式需處理鏈結層的一 些必要動作,例如拿掉鍵結層的標頭(header)、過濾封包…,處理完後再 使用軟體中斷(software interrupt)通知核心處理更上層的工作。
圖 15、 Linux User Space、Kernel 和 Network Driver 之間的關係 圖 16 是我們使用的 Madwifi 驅動程式和 Linux 核心之間的架構,驅動 程式利用模組(module)方式掛載(mount)進入核心時,會跟核心註冊一些函 式。當核心需要送出資料封包時,會先將資料排入「出境佇列」(outgoing queue),然後呼叫網路介面的 hard_start_transmit()作業方法。在 Madwifi 驅動程式裡是註冊 ath_start()這個函式作為 hard_start_transmit()的函
process (IP input queue) interface
queues function call
function call to start output
software interrupt
(cause by interface layer)
hardware interrupt
(cause by network device) user space (IP input queue) interface
queues function call
function call to start output
software interrupt
(cause by interface layer)
hardware interrupt
(cause by network device) user space
kernel
driver
中斷函式,而 netif_rx()是核心給驅動程式呼叫用來通知上層處理接收到 的封包。
圖 16、Madwifi Driver 和 Linux Kernel 之間的架構
下圖 17 為對 Madwifi 程式我們所要修改新增的部分。當有封包要送出 的時候,我們必須多加鄰居佇列(per neighbor queue)來暫存封包,分類 的依據是檢查 MAC 位址,放進適當的佇列中,然後選擇一個此時該傳送的 封包傳送出去,接著再觸發傳送下一個封包。當接收到封包時,檢查是否 為時間同步或頻道排程的封包,如果是時間同步的封包則更新計時器,若 是頻道排程的封包,則更新排程資料表,若都不是則交於上層去處理。新 增切換頻道計時器,每 3 秒中斷一次,當切換頻道計時器中斷時,需去查 詢排程資料表,如果進入的是廣播時槽(broadcast slot),則切換至共同 頻道上,然後檢查頻道使用情況是否該換接收頻道,也檢查網路流量是否 需換排程,一定的週期需重設所有佇列的優先權,如果進入的是接收時槽,
最簡單,就切換到接收頻道上去等待資料就好了,如果進入的是傳送時槽,
必須依照佇列優先權和頻道排程選一個傳送端,並切換到此傳送端的接收 頻道上。
Network Layer (IP)
MAC Layer (802.11)
.
.
.
kernel
driver
Link Layer (802.3 Ethernet) ./madwifi/ath/
./madwifi/net80211/
int (*hard_start_xmit) (sk_buff*, device*)
傳送封包 function call int ath_start (sk_buff*,device*)
接收封包 interrupt ath_intr(…)
用request_irq(…)註冊中斷函式
a packet to send
check addr put in queue
select proper pkt to send
send over , trigger next send process
a packet to send
check addr put in queue
select proper pkt to send
send over , trigger next send process
1. check channel usage and necessary change receiving channel 2. check traffic pattern to
modify schedule 3. every K times, reset
priority of all queues check schedule
1. check channel usage and necessary change receiving channel 2. check traffic pattern to
modify schedule 3. every K times, reset
priority of all queues check schedule
sync timer
every 6s timeout
if this is a
every 6s timeout
if this is a time sync schedule
check pkt time sync schedule
check pkt 做置換(context switch)的動作,所以不用能 while 迴圈或 sleep 去實作,
會耗盡 CPU 的時間,其它的工作都停滯不動,其它的行程也都受到牽涉。
我們研究 Linux 核心可用的函式庫及語法,利用 timer_list 這個資料結構 來實作,向核心註冊中斷時間和中斷服務函式,時間一到,核心會自動去
裝成一個 struct sk_buff 結構,要把封包用佇列暫存,需要加上一個 sk_buff_head 把上層下來的封包串起來,便可行成一個佇列。分析封包要 傳送的位置,便可利用多個 sk_buff_head 來實作成頻道佇列(per channel queue)或鄰居佇列(per neighbor queue), 我們是以鄰居佇列為實作佇列 的方式。
困擾著我們最久的是切換頻道的問題,我們試了諸多的切換頻道的方 法,第一種,直接下 iwconfig 系統呼叫(system call)去切換頻道,是屬 於使用者空間的方法,第二種,使用 Madwifi 驅動程式被 iwconfig 下命令 著第一個呼叫的函式,並傳入相同的參鷜,第三種,在 Madwifi 驅動程式 與 IEEE 802.11 無關的程式碼裡選一個最直接切換 channel 的函式去切換,
發現一件事,切換頻道均沒有問題,但是同時兩個網格點同時換到同一個 頻道時,有時連得起來,有時連不起來,有時連的很快,有時連的很慢,
這對我們的管理協定有非常嚴重的效能折扣。第四種,我們直接去呼叫燒 在網路卡的韌體函式去切換頻道,發現沒有效果,根本不能切換頻道。正 當一切均失敗的時候,我去查閱了 IEEE 802.11 的書藉,找到 802.11 在 Ad-Hoc 模式下為了要同步的關係,需要產生信號彈(beacon),我們發現,
當一起切換到相同的頻道,當信號彈 BSSID 有合併的時候,網路才有辦法 連線,所以我們去追蹤查詢,換頻道的時候會重新產生 BSSID,就是即使隨 建即連(Ad-Hoc)網路的名稱相同,BSSID 也會不同,推測因為 BSSID 的不同,
所以封包在過濾的時候被過濾掉了,所以連線連不起來,當 BSSID 合併才 連得起來,我們查到網路卡支援一種 Ad-Hoc Demo 的模式可以把 BSSID 一 直維持在 00:00:00:00:00:00,所有封包都會收進來,如此才成功的解決問 題。
4-4、測試程式
我們的程式碼架構在驅動程式裡,為了監控驅動程式的狀態以及測試效 能,我們在使用者空間透過共享記憶體的方式去監控驅動程式的狀態,並 在上面使用 UDP 的封包進行頻寬的測試,測試畫面如下圖。
圖 18、測試監控程式
看圖 18,這是 192.168.0.2 筆記型電腦的測試監控程式的截取畫面,
此存取會對其它鄰居紀錄一些資訊,驅動程式儲的資訊放在畫面中 Network Messages 的上方,例如排程、MAC 位址、比重(Weight)、對方對我的比重 (OtherW)、目前佇列的長度(QueueLen)以及優先權(Priority),為了實作 上的方便,比重有就是 1,沒有就是 0,因為這個不是實作上的重點,所以 用最簡單的方式。畫面中 R=ch1 表示網格點的接收頻道是頻道 1,一個個藍 色小方框裡標著 B、R、F、S 是鄰居和自己網格點的排程,會有紅色的長條 顯示目前在那一個時槽,而長條中標示的 ch6 表示自已目前這個時槽是用 頻道 6,當自己在傳送時槽時而鄰居又剛好在接收時槽時,最右方會 有"Match"的紅色標示,這個傳送時槽目前傳輸的對象會在最右邊標 示"send to "的字眼,以上是驅動程式的資訊,用共享記憶體的方式讀 取出來顯示在畫面上。
在 Network Messages 的下方在網路層的監控和測試工具,在 Network Messages 可以看目前產生的封包序號或接收到的封包序號,而下方藍色大
的傳輸速度,而 Avg Speed 是過去一段時間傳輸速度的平均,因為我們有 分時槽的關係,用 Cur Speed 來看傳輸速度是不準確的,有時是 700 KBps 而有時是 0 KBps,所以要加 Avg Speed 來測試頻寬。最下方的命令列可以 用來下命令測試頻寬,例如"send UPD 192.168.0.4"可以起始一條新的 流量(最佳傳輸的方法)給 192.168.0.4 這個網格點。
4-5、測試結果
我們利用測試監控程式來測試所設計的協定,下圖 19 為我們測試的第 一個網路環境,四個網格點都在互相的干擾範圍內,A 使用最佳傳送的方式 (Best Effort)傳送 UDP 封包給 B,而 C 也使用最佳傳送的方式傳送 UDP 封 包給 D,由表 2 可看出,在相同未經修改的驅動程式下,使用不同頻道時的 效能是使用同頻道的效能的 190%而已,但是 2 個連線此時使用調頻的方式 是手動去改變頻道的方式,接著可以看到經過我們經改過的驅動程式(隨著 不同環境自動調整頻道)的效能是單一頻道的 135%的效能。
A 192.168.0.1
A 192.168.0.1
B 192.168.0.2
B 192.168.0.2
C 192.168.0.3
C 192.168.0.3
D 192.168.0.4
D 192.168.0.4
圖 19、測試環境一A-B 傳輸速度 C-D 傳輸速度 頻道使用 驅動程式
374KBps 358KBps 同頻道 未經修改的驅動程式 700KBps 698KBps 不同頻道
未經修改的驅動程式(手動調頻) 503KBps 486KBps 不同頻道 我們修改過的驅動程式
表 2、測試結果一 接著我們測試鏈狀的網路,如下圖 20。
A
五、未來展望與結論
5-1、本文研究貢獻
我們提出了一個可套用在 IEEE 802.11 MAC 層上的多重頻道管理協定,
透過不斷的切換頻道提高空間中頻道的再使用率(Spatial Reuse),只需單 張網路卡便能達成這個效果,並且容易擴充至多張網路卡,因為在同一網 格點上的每張網路卡都可使用不同的接收頻道,每張網路卡均個別使用我 們的協定就可以降低干擾,並不需要另外使用其它協定來處理。
我們的研究並不是紙上談兵,因為我們模擬真正的環境去修改網路卡的 驅動程式,把我們的管理協定實作在上面,並寫了測試程式去監控是否運 作的正常,有成功的在實機上面套用我們的協定。
5-2、未來的研究方向
在我們提出的架構之下,衍生出了很多議題,像是傳送接收時槽比例的 分配、傳送接收時槽順序的分配、傳送端的選擇,每個議題都是可以再繼 續深入研究最佳化的方法,例如傳送接收時槽比例在分配時,α、β穩定 的參數如果調整才能達到最好的效果,既穩定又能配合流量來分例。另外,
廣播時槽和其它時槽的比例和時槽的總數也是另一個研究的議題,怎麼樣 分配才不會造成時間的浪費,又不會造成廣播時槽內頻道擁塞(channel
廣播時槽和其它時槽的比例和時槽的總數也是另一個研究的議題,怎麼樣 分配才不會造成時間的浪費,又不會造成廣播時槽內頻道擁塞(channel