1. 程式人生 > >aodv協議尋路流程

aodv協議尋路流程

當協議接收到一個分組,即recv(Packet*,Handler*)函式被呼叫,函式根據分組型別呼叫不同的處理函式進行處理。

 

void
AODV::recv(Packet *p, Handler*) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);


 assert(initialized());


 //如果分組型別是AODV型別,則交給recvAodv函式
 if(ch->ptype() == PT_AODV) {
   ih->ttl_ -= 1;
   recvAODV(p);
   
return; } /**/ }

 

1、如果是協議分組,則將分組的ttl值減1,並呼叫recvAODV(Packet*)函式進行處理。recvAODV函式再根據分組的不同型別來呼叫不同的函式進行處理。

 

void
AODV::recvAODV(Packet *p) {
 struct hdr_aodv *ah = HDR_AODV(p);


 assert(HDR_IP (p)->sport() == RT_PORT);
 assert(HDR_IP (p)->dport() == RT_PORT);


 
/* * Incoming Packets.傳入的資料包。 */ switch(ah->ah_type) {//根據包型別呼叫不同函式 case AODVTYPE_RREQ: recvRequest(p); break; case AODVTYPE_RREP: recvReply(p); break; case AODVTYPE_RERR: recvError(p); break; case AODVTYPE_HELLO: recvHello(p); break;
default: fprintf(stderr, "Invalid AODV type (%x)\n", ah->ah_type); exit(1); } }
View Code


(1)如果接收到的是路由請求分組,則呼叫recvRequest(Packet*)函式進行處理。

 

 1 void
 2 AODV::recvRequest(Packet *p) {
 3 struct hdr_ip *ih = HDR_IP(p);
 4 struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
 5 aodv_rt_entry *rt;
 6     /*1,看該分組是否有自己產生*/
 7   if(rq->rq_src == index) {  
 8     Packet::free(p);
 9     return;
10   }
11   
12   /*2,如果已經收到了源地址和請求序列號相等的請求報文,丟棄*/
13  if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {
14    Packet::free(p);
15    return;
16  }
17  
18       /*3,如果沒有收到過該分組,將收到的廣播分組存入broadcast中*/
19  /*快取此路由請求*/
20  id_insert(rq->rq_src, rq->rq_bcast_id);
21       /*4,建立反向路徑*/
22  aodv_rt_entry *rt0; // rt0 is the reverse route rt0是反向路由
23    //查詢是否存在反向路由
24    rt0 = rtable.rt_lookup(rq->rq_src);
25    
26    if(rt0 == 0) { 
27        //如果不存在反向路由項,新建立反向路由
28      rt0 = rtable.rt_add(rq->rq_src);
29    }
30   //更新此路由條目的生存時間
31    rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));
32    // 如存在反向路由,判斷反向路由是否需要更新
33    if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||//如果請求序列號大於路由序列號或者
34     ((rq->rq_src_seqno == rt0->rt_seqno) && //兩者序列號相等但是跳數比源路由跳數小,則更新
35            (rq->rq_hop_count < rt0->rt_hops)) ) {
36     /*
37      * 此處略
38      */
39    }
40    // End for putting reverse route in rt table  在rt表中設定反向路由
41 
42 
43    /*5,轉發或處理該包*/
44 
45    /*在這種情況下我們有兩種選擇,一種是將RREQ繼續傳播下去,另一種是產生RREP.在這之前我們需要確定,
46    反向路由已經在路由表中存在。如果存在反向路由,在考慮是否應該向源節點發送RREP*/
47  rt = rtable.rt_lookup(rq->rq_dst);    // 判斷節點本身是否是路由請求分組的目的地址
48 
49 
50  if(rq->rq_dst == index) {  //如果節點本身是目的節點地址,向源節點發送路由請求應答分組並且回收請求分組
51 
52    seqno = max(seqno, rq->rq_dst_seqno)+1;
53    if (seqno%2) seqno++;// 如果目的節點序列號是奇數就將其變成偶數,保證目的節點序列號是偶數
54 
55 
56    sendReply(rq->rq_src,           // IP Destination
57              1,                    // Hop Count
58              index,                // Dest IP Address
59              seqno,                // Dest Sequence Num
60              MY_ROUTE_TIMEOUT,     // Lifetime
61              rq->rq_timestamp);    // timestamp
62 
63    Packet::free(p);//釋放RREQ ,產生RREP
64  }
65 //如果不是目的節點,但是有到目的節點的路徑,也傳送路由應答報文
66  else if (rt && (rt->rt_hops != INFINITY2) &&(rt->rt_seqno >= rq->rq_dst_seqno) ) {//保證夠新(目的節點序列號)
67 
68    assert(rq->rq_dst == rt->rt_dst);
69  
70    //向源節點發送路由應答分組
71    sendReply(rq->rq_src,
72              rt->rt_hops + 1, // 若是目的節點設成 1,這裡不是目的節點就在RREQ中的跳數加1
73              rq->rq_dst,  //如果是目的節點這一項就是目的節點的IP地址(這個節點本身的地址)這裡是RREQ中的目的節點的IP地址
74              rt->rt_seqno,
75     (u_int32_t) (rt->rt_expire - CURRENT_TIME),
76     
77              rq->rq_timestamp);
78           // Insert nexthops to RREQ source and RREQ destination in the   將nexthops插入到RREQ源和RREQ目的地
79           // precursor lists of destination and source respectively        分別位於的目的地和源的前體列表中
80 
81 
82    //更新正向路由和反向路由的前區列表
83    rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source  加入字首列表
84    rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination 加入字首列表
85 
86 
87 Packet::free(p);
88  }
89 //如果沒有到達目的節點足夠新的路由,繼續轉發路由請求分組
90  else {
91    ih->saddr() = index;
92    ih->daddr() = IP_BROADCAST;
93    rq->rq_hop_count += 1;
94    // Maximum sequence number seen en route  看到的最大的序列號
95    if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno);
96    forward((aodv_rt_entry*) 0, p, DELAY);
97  }
98 }
View Code2

 

2、forward

 1 void
 2 AODV::forward(aodv_rt_entry *rt, Packet *p, double delay) {
 3 struct hdr_cmn *ch = HDR_CMN(p);
 4 struct hdr_ip *ih = HDR_IP(p);
 5 /*如果跳數為零,直接丟棄*/
 6  if(ih->ttl_ == 0) { //超時
 7      drop(p, DROP_RTR_TTL);
 8      return;
 9  }
10  /*如果不是AODV型別資料包並且鏈路方向是上行並且是廣播包或者此節點就是目的地址*/
11  if ((( ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP ) &&
12 ((u_int32_t)ih->daddr() == IP_BROADCAST))
13 || (ih->daddr() == here_.addr_)) {
14 dmux_->recv(p,0);//交給分類器
15 return;
16  }
17 
18 /*判斷是否有去忘目的地的路由,沒有那說明這是廣播*/
19  if (rt) {    //更新一些引數
20    assert(rt->rt_flags == RTF_UP);
21    rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
22    ch->next_hop_ = rt->rt_nexthop;
23    ch->addr_type() = NS_AF_INET; //代表分組需要經過單播路由到達目的地,需要呼叫arp;
24    ch->direction() = hdr_cmn::DOWN;       //important: change the packet's direction
25  }
26  else {
27   
28    assert(ih->daddr() == (nsaddr_t) IP_BROADCAST);
29    ch->addr_type() = NS_AF_NONE;//代表廣播報文 , NS_AF_ILINK代表不需要呼叫arp
30    ch->direction() = hdr_cmn::DOWN;  // 鏈路方向下行     important: change the packet's direction
31  }
32  //如果該資料包是廣播包
33 if (ih->daddr() == (nsaddr_t) IP_BROADCAST) {//廣播報文
34  // If it is a broadcast packet
35    assert(rt == 0);
36    if (ch->ptype() == PT_AODV) {
37      /*
38       *  Jitter the sending of AODV broadcast packets by 10ms
39  *  Jitter傳送AODV廣播資料包10ms
40       */
41      Scheduler::instance().schedule(target_, p,
42         0.01 * Random::uniform());//加入定時器
43    } else { //如果不是AODV型別
44      Scheduler::instance().schedule(target_, p, 0.);  // No jitter
45    }
46  }
47  else { // Not a broadcast packet  非廣播報文
48    if(delay > 0.0) {
49      Scheduler::instance().schedule(target_, p, delay);
50    }
51    else {
52    // Not a broadcast packet, no delay, send immediately 立即傳送
53      Scheduler::instance().schedule(target_, p, 0.);
54    }
55  }
56 
57 
58 }
View Code3