3. 無線感知網路模擬模組之實作
3.2. 無線感知網路模組之實作
3.2.3. 實作
承接 3.2.1 所描述的通訊協定堆疊,在本次的實作中僅需針對 MAC80211 與 Wphy 這兩個模組進行更改。但為了使得一般的使用者與使用無線感知網路的使用者能夠並存,
因此勢必需要產生新的模組。因此,在最一開始即複製整個 MAC80211 與 Wphy 模組,
16
並在其後加入_CR 之字串以示區隔。而完成後的類別名稱則為 mac802_11dcf_CR 與 wphy_CR。而整個的修改架構則如圖 5 的簡化後之類別圖所示:
mac802_11dcf_CR - Log File Pointers: FILE*
- Related counter:Integer - Contention Window Size: Integer - Related Timers: timerObj*
- Related Packet Buffer: ePacket_*
- nav: 64-bit Unsigned Integer [0..MAX_USABLE_CHANNEL]
- mhSense: timerObj*
- mhWait: timerObj*
- mhRTI: timerObj*
- mhSIFS_CR: timerObj*
- epktTxBuf: TxQueue*
- epktRTS_CR: ePacket_*
- epktCTRL_CR: ePacket_*
- txOP_CR: Integer
- channel_ctrl: CRChannel_Ctrl*
- action_state: enum ActionState + init()
+ send() + recv() + log()
+ SwitchChannel()
- check_pktCTRL_CR(): Integer - check_pktRTS_CR(): Integer - senseChHandler(Event_ *): Integer - waitHandler(Event_ *): Integer - RTIHandler(Event_ *): Integer - sensePUHandler(Event_ *): Integer - sendRTS_CR(u_char*): Void - sendCTS_CR(u_char*): Void - sendRTI(u_char*): Void - retransmitRTS_CR(): Void - recvRTS_CR(ePacket_*): Void - recvCTS_CR(ePacket_*): Void - recvRTI(ePacket_*): Void - start_sensetimer(u_int32_t): Void - start_waittimer(u_int32_t): Void - start_RTItimer(u_int32_t): Void - start_SIFS_CRtimer(u_int32_t): Void - start_fastSensetimer(u_int32_t): Void
CRChannel_Ctrl - mac_module_: mac802_11dcf_CR*
- wphy_module_: wphy_CR*
- current_channel_: Integer - control_channel_: Integer - initial_channel_: Integer - inc_per_hop_: Integer
- nav: Unsigned 64-bit Integer[0..MAX_USABLE_CHANNEL]
+ GetCurrentChannel(): Integer + GetInitialChannel(): Integer + GetIncPerHop(): Integer + SetControlChannel(Integer): Void + SwitchToTheNextChannel(): Integer + BackToTheControlChannel(): Void + SetChannelInf(Integer, Integer): Void + GenerateChannelInf(Integer&, Integer&): Void + UpdateChannelStatus(Packet*): Void + IsCurrentChannelIdle(): Boolean
1 1
- Log File Pointers: FILE*
- Physical Attributes: double - channel_: Integer
- channel_ctrl: CR_ChannelCtrl * + init(): Integer
+ recv(): Integer + send(): Integer
+ command(int, char*[]): Integer + log(): Integer
+ BitError(double): Integer
+ Link Flag Related Functions(): Void + SwitchChannel(int): Void
+ getCurrentChannel(): Integer
+ InitChannelCtrlPtr(CR_ChannelCtrl*): Void Wphy_CR
1
1
- epktTxBuf: std::list<ePacket_*>
- max_size: Integer + Enqueue(ePacket_*): Void + Dequeue(): ePacket_*
+ GetCurrentQueueLen(): Integer + IsEmpty(): Boolean
+ IsFull(): Boolean
+ SetSize(unsigned int): Void + Clear(): Void
TxQueue
1 1
圖 5、本次實作之類別圖。
其中為了簡單呈現,因此在類別成員與類別方法僅詳細列出本次所新增的部份,其 餘部份則予以簡化。從中可以看到在修改後,主要是以 mac802_11dcf_CR 做為
17
MAC80211CR 模組之實作類別,而 Wphy_CR 則為 WphyCR 模組之實作類別。至於其 他尚有 CRChannel_Ctrl 與 TxQueue 這兩個類別,第一個類別主要是用來進行頻段操作 之相關動作;而第二個類別 TxQueue 則是用來做為連續資料封包的緩衝區維護之類別。
這兩個類別將分別在 3.2.3.2 與 3.2.3.3 中詳加描述。
3.2.3.1. 控制封包的新增與行為狀態之維護
控制封包的新增
在這次的實作中一共有三個控制封包需要新增,分別為 RTSCR、CTSCR、RTI。針對 前二者之封包,可利用原先之 RTS、CTS 封包進行更改。其中,由於 CTSCR僅用為回應 傳送端,使傳送端了解接收端已同意這次的傳輸,因此整個表頭的設計與原本的 CTS 一樣之外,RTSCR則配合了該無線感知網路的機制而做些許修改,其表頭結構如下:
Frame
Control Receiver Address Transmitter Address Initial
Channel Inc Per Hop Frame
Duration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
FCS
21 22 23 24
圖 6、RTSCR之表頭結構。
Frame
Control Frame Receiver Address FCS last
Duration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
圖 7、RTI 之表頭結構。
修改後的結構仍與 RTS 相似,不同之處在於 RTSCR需要帶的兩個參數則置於最後 面。而除了 RTSCR與 CTSCR之外,尚有 RTI 之控制封包。這個封包的部份以 ACK 之控 制封包來進行實作,並加上通知接收端是否還有封包要傳送的資訊。
18
在決定完控制封包的資料結構後,僅需要參考之前處理 RTS、CTS、ACK 的設計,
即可將此部份的產生控制封包、傳送控制封包的行為處理完成。對應先前的設計,為了 產生與填寫控制封包,在此需要實作 sendRTS_CR、sendCTS_CR 與 sendRTI 這三個填 寫表頭欄位之相關的函式,其中 sendRTS_CR 負責產生 RTSCR;sendCTS_CR 則是用以 產生 CTSCR之封包;最後 sendRTI 則是產生 RTI 而使用的。在實作完成後,需將此三個 函式填入對應的地方,以使其能在正確的時間點被執行。其中 sendRTS_CR 主要是在當 有封包抵達此模組時第一個進入的函式 send 進行呼叫;而 sendCTS_CR 則是在收到 RTSCR時對應的處理函式 recvRTS_CR 進行呼叫;最後在接收到 ACK 時的處理函式 recvACK 則是檢查是否還有其他封包要傳送與呼叫 sendRTI 函式。
除了填寫表頭欄位之相關函式外,由於這些封包仍需要送出至其他節點,因此需要 進行封包傳輸函式之實作。實作的內容包括了:check_pktRTS_CR、check_pktCTRL_CR 這兩個函式,前者主要用來處理 RTSCR之封包,而後者則是負責傳送 CTSCR與 RTI 這兩 種封包。而這兩個函式需要放在 deferHandler 與 backoffHandler 這兩個計時器逾時處理 函式進行呼叫。
最後還需要增加 recvRTS_CR、recvCTS_CR、recvRTI 這三個接收 RTSCR、CTSCR
與 RTI 封包的對應處理函式,這些函式會透過送來的控制封包的內容來更新其狀態與頻 段使用決策的相關參數。而被呼叫的位置則是在封包接收的處理函式 recvHandler 內。
行為狀態的維護
但單純加入產生封包、送出封包的處理函式是不夠的,這樣的實作很有可能發生狀 態錯亂的狀況,原因是在 3.2.3 介紹的部份曾提到 MAC80211CR 並沒有與頻段相關的概 念。此外,在先前的設計中,傳送端與接收端的定義主要是由封包類型的傳送優先順序 來維護的。在這樣的狀態下,很有可能造成當傳送端與接收端進入資料傳輸頻段時,在 頻段感測完成並進入 RTS-CTS 握手機制的狀況下,此時接收端有封包需要進行傳輸,
19
Produce a CTSCR Frame
CTSCR Send Timeout / Start mhSense Timer
Sense channel busy / None
Sense channel busy / None
mhSense Timeout / start mhWait timer
mhWait Timeout / Switch to the next
channel And start mhSense
timer
mhSense Timeout / Switch to the next
channel And start mhSense
timer
Finish sending CTS / None
Receive a DATA /
Produce an ACK frame Finish sending an ACK / Start mhRTI timer and update has_more_data
flag
Receive a RTI / Cancel mhRTI timer and start mnSIFSCR
Timer mhSIFSCR Timeout and
txop <= TxOPCR and has_more_data is true /
None
mhSIFSCR Timeout and (txop > TxOPCR or has_more_data is false)
/ None Sense channel busy /
None
mhSIFSCR Timeout / None Receive a RTS Frame /
Produce a CTS frame
圖 8、發送端之行為狀態循環圖。
〈註:未標示之輸入者表示維持原本狀態,並且無任何輸出。〉
20
Receive a CTSCR / Switch to the data
channel And start mhSense
timer
Sense channel busy / None
Sense channel busy / None
mhSense Timeout / Produce a RTS Frame And start mhWait timer
mhWait Timeout / Switch to the next
channel And start mhSense
timer
mhSense Timeout / Switch to the next
channel And start mhSense
timer
Finish sending RTS /
None Receive a CTS Frame /
cancel mhWait timer
Finish sending DATA / None
Receive an ACK / Produce a RTI Frame
Finish sending RTI / start mnSIFSCR Timer mhSIFSCR Timeout and
txop <= TxOPCR and epktTx != NULL / None
mhSIFSCR Timeout and (txop > TxOPCR or epktTx == NULL) / None Sense channel busy /
None
在頻段的切換中,由於切換的決定權在 MAC80211CR 模組中,但目前使用之頻段 資訊則是由 WphyCR 模組所維護,MAC80211 模組本身對於頻段是沒有概念的。因此在 此處,本實作提出了在 MAC80211CR 模組中增加一個稱作 Cognitive Radio Channel Control 的類別 CRChannel_Ctrl,這個類別主要是在 MAC80211CR 模組中產生,負責與
21
頻段相關的處理事件。但是只有這樣的模組是不夠的,若需要更動目前所使用頻段還需 要 WphyCR 模組之支援。故在此增加設定與取得目前相關頻段的函式,使得該類別之物 件能直接呼叫相關函式 SwitchChannel 以協助 MAC80211CR 模組進行切換頻段之動作;
此外在切換的過程中,為了避免切換頻段後仍在接收前一頻段資料之狀況,因此,在 MAC80211CR 內也另外實作一個函式 SwitchChannel 以處理這些動作。整體設計如圖 5 的 Wphy_CR 與 CRChannel_Ctrl 之類型描述區塊所示。
但在頻段的感測中,目前 NCTUns 對於本部份的實作主要是透過實體層模組來判斷 這個封包是否與自己所屬之頻段符合,符合者則將此封包往上層送,如此 MAC 模組即 能知道此時存在某些使用者正在使用該頻段;若不符合即直接將該封包丟棄。這樣的狀 況在原本的使用情境──即該無線網路使用設備僅在某一特定頻段使用是沒有問題的 設計方法,但應用在無線感知網路的情境中卻會導致極大的問題。
而這個問題的解釋主要在於模擬封包接收的方法上,承接上一段的敘述,若接收的封包 與自己所在的頻帶吻合,則在 MAC 模組收到後,其流程主要為:
1. 由 MAC 模組的 recv 函式將此封包儲存在接收的緩衝區 epktRx 內,並且利用其封 包大小與實體層相關參數來計算其接收時間,並利用此接收時間來啟動接收時所用 的計時器 mhRecv。
2. 當 mhRecv 之計時器計時完畢時,此時該封包會透過 recvHandler 這個函式來判斷該 封包是否為自己的,是的話即呼叫對應的處理函式;不是的話則在設定完 NAV (Network Allocation Vector) 後丟棄。
在這樣的處理下,由 mhRecv 是否正在倒數計時以及 MAC 的接收狀態即可判斷此 時是否能夠感應得到資料的進入,但若考慮圖 10 之情境,這一套設計可能就無法正常 運作。
22
圖 10、不適用於原先 NCTUns 感測頻段忙碌流程之實例。
在圖 10 中,一開始無線感知網路的使用者正在控制封包傳輸頻段中進行封包的傳 輸,而在同時,第一個資料傳輸頻段也有一個主要使用者正在傳送資料。假設此情境下,
這三位使用者皆能完整接收到其它使用者所傳輸之封包,則在該時間點,無線感知網路 之使用者均會收到由第一個資料傳輸頻段傳送來的封包,但是在實體層卻會因為它不是 屬於目前使用之頻段的封包為理由而將其丟棄。之後,兩位無線感知網路之使用者切換 至第一個資料傳輸頻段,在他們進行頻段感測時卻無法知道目前有一位主要使用者正在 使用該頻段,因為該位使用者傳來的封包已被丟棄。
為了解決這樣的問題,最簡單的方式是改寫 WphyCR 模組,讓其完全不用判斷所用 頻段,直接將其往上層送,但是這樣即不符合 MAC 的行為定義。因此在此處的設計主 要是透過 CRChannel_Ctrl 來實作一個稱作 UpdateChannelStatus 的函式,任何進入
WphyCR 模組的封包都會被交由該函式處理,而該函式主要會計算出若要接收這個封包,
則至少要到哪個時間點才能被接收完畢,並將該時間點儲存於該類別中負責儲存對應頻 段的陣列中。此時若 MAC80211CR 模組需要檢查現在頻段是否為閒置狀態,則可直接 透過 CRChannel_Ctrl 這個類別的物件來進行查詢,若現在時間比所記錄的時間小,則代
23
表此時仍有封包在傳輸。因此,此機制搭配原先儲存在 MAC80211CR 的 NAV 的機制在 多重頻段上的改寫,即可正確判斷出目前頻段是否為忙碌狀態。
頻段感測時間區間之實作
在頻段由控制封包傳輸頻段切換至資料傳輸頻段後,根據[10]所提的機制,無線感 測網路之傳送端與接收端雙方均要進行頻段感測之動作。若此時頻段為忙碌,則接下來
在頻段由控制封包傳輸頻段切換至資料傳輸頻段後,根據[10]所提的機制,無線感 測網路之傳送端與接收端雙方均要進行頻段感測之動作。若此時頻段為忙碌,則接下來