当协议接收到一个分组,即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); } }
(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 }
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 }