AODV路由協議的路由緩存隊列詳解
AODV路由協議的使用往往在一些復雜的程序當中。那么我們如何理解這些協議的使用和一些代碼函數的含義呢?下面我們就來闡述一下這方面的問題。首先了解一下在NS2.27中,AODV路由協議主要包括以下幾個組件:
1、協議實體
2、路由表
3、定時器
(1)廣播定時器
(2)周期Hello報文廣播定時器
(3)用于鄰居管理的定時器
(4)用于路由緩存的定時器
(5)用于本地修復的定時器
(6)緩存廣播ID的定時器
4、日志記錄器
5、路由緩存隊列
首先來看AODV路由協議從接收到一個分組開始的基本流程。
當協議接收到一個分組,即recv(Packet*, Handler*)函數被調用,函數根據分組類型調用不同的處理函數進行處理。
1、如果是協議分組,則將分組的ttl值減1,并調用recvAODV(Packet*)函數進行處理。recvAODV函數再根據分組的不同類型來調用不同的函數進行處理。
(1)如果接收到的是路由請求分組,則調用recvRequest(Packet*)函數進行處理。
如果該分組由節點自身產生或已經接收過的,會被節點丟棄,并結束處理。
否則,節點將緩存該分組的序列號,并將該分組發送來的路徑添加到反向路由中,轉發相應分組。然后,節點根據該分組的目的地址進行判斷并調用不同函數進行處理。
如果節點自身即為目的節點,則調用sendReply(nsaddr_t, u_int32_t, nsaddr_t, u_int32_t, u_int32_t, double)函數進行響應。如果節點不是目的節點,但知道通往目的節點的路由,則調用sendReply函數進行響應,并在源和目的前驅列表中分別插入到源和目的的下一跳節點。否則,不能直接響應該請求,將跳數加1,并調用forward(AODV_rt_entry*, Packet*, double)函數轉發該分組。
在sendReply函數中,節點首先查找到達目的節點(即發送路由請求分組的節點)的路由,創建并填充分組,然后調用Scheduler::instance().schedule()函數來發送該分組。
(2)如果接收到的是路由響應分組,則調用recvReply(Packet*)函數進行處理。
節點首先查詢前往分組目的節點的路由,如果不存在則新增一條路由項。然后,節點更新到該目的節點的路由項,并發送所有相關分組。
如果節點為目的節點則更新路由發現延遲并發送所有相關的分組。如果節點不是目的節點,但知道通往目的節點的路由,則將跳數加1,調用forward函數轉發該分組,并修改響應的前驅列表。如果節點不是目的節點,也不知道通往目的節點的路由,則丟棄該分組。
(3)如果接收到的是路由錯誤分組,AODV路由協議則調用recvError(Packet*)函數進行處理。#p#
節點首先清除所有受到影響的路由項,丟棄所有受影響的分組。然后,如果前驅節點中存在會受該路由錯誤影響的分組,則調用sendError(Packet*, bool)函數轉發該分組。
sendError函數創建并填充分組,然后調用Scheduler::instance().schedule()函數來發送該分組。
(4)如果接收到的是Hello消息分組,則調用recvHello(Packet*)函數進行處理。
節點會將該鄰居的信息添加到鄰居列表中(或更新該鄰居的信息)。
2、如果是數據分組,則節點丟棄已經發送過或者ttl為0的分組,并結束處理。如果分組是由上層協議產生的,則節點添加IP報頭。隨后,節點根據目的路由進行不同處理。
(1)如果目的節點路由未知,則調用rt_resolve(Packet*)函數進行路由解析和轉發。
如果目的節點路由在路由表中存在,則直接調用forward函數進行轉發。如果分組是由節點自身產生的,則將分組保存到緩沖隊列中,并調用 sendRequest(nsaddr_t)函數查詢目的路由。如果目的路由已知,但正在進行本地修復,則將分組保存到緩沖隊列中。否則,丟棄該分組,并調用sendError函數報錯。
(2)如果目的節點路由已知,則調用forward進行轉發。
節點丟棄ttl為0的分組,并根據分組類型決定下一步操作。
如果接收到的是數據分組,且自身為目的節點,則通過調用PortClassifier對象的recv(Packet*, Handle*)函數將分組交遞給高層協議,并結束處理。否則,節點設置分組屬性,并調用Scheduler::instance().schedule (Handler*, Event*, double)函數來發送分組。其中,Handler為基類中的屬性target_(會根據腳本中的設置指向相應的協議實體),Event為要發送的分組即可。
以上就是AODV路由協議在節點收到分組后的一個處理過程。接下來看看各個定時器所做的工作。
1、廣播定時器BroadcastTimer在到時后調用id_purge()函數刪除廣播項中已超時的項目,并通過調用Scheduler:: instance().schedule()函數來設置下次被調用的時間(Handler為this指針,Event為類屬性intr)。
2、周期Hello報文廣播定時器HelloTimer在到時后調用sendHello()函數向鄰居創建并發送Hello消息,并調用schedule()函數來設置下次被調用的時間。
3、鄰居管理定時器NeighborTimer在到時后調用nb_purge()函數來清除鄰居列表中已超時的鄰居項,并調用schedule()來設置下次被調用的時間。nb_purge會調用nt_delete(nsaddr_t)函數來清除超時的鄰居項,其又會調用 handle_link_failure(nsaddr_t)函數來處理由于鄰居節點被刪除而引起的路由變化。
4、路由緩存定時器RouteCacheTimer在到時后調用rt_purge()函數來清除路由表中已超時的路由項,并丟棄相關的分組,再調用schedule()來設置下次被調用的時間。
5、本地修復定時器LocalRepairTimer在調用后根據傳遞的分組的目的地址關閉相應的路由項。
6、緩存廣播ID定時器BroadcastID用來保存廣播分組的ID。
此外,AODV路由協議的路由表、日志記錄和隊列三個類就相對比較簡單了,都只實現了一些非常基本的功能,在此就不做介紹了