📄 aodv.cc
字号:
switch (rq->rq_flags){ case RREQ_NO_FLAG: recvMRQ_NOFLAG(p); return; case RREQ_J: recvMRQ_J(p); return; case RREQ_R: recvMRQ_R(p); return; case RREQ_JR: recvMRQ_JR(p); return; default: Packet::free(p); return; } }#endif rt = rtable.rt_lookup(rq->rq_dst); // First check if I am the destination .. if(rq->rq_dst == index) {#ifdef DEBUG fprintf(stderr, "%d - %s: destination sending reply\n", index, __FUNCTION__);#endif // DEBUG // Just to be safe, I use the max. Somebody may have // incremented the dst seqno. seqno = max(seqno, rq->rq_dst_seqno)+1; if (seqno%2) seqno++;#ifdef MULTICAST sendReply(rq->rq_src, // IP Destination rq->rq_flags, 0, // Hop Count index, // Dest IP Address seqno, // Dest Sequence Num MY_ROUTE_TIMEOUT, // Lifetime rq->rq_timestamp); // timestamp#else sendReply(rq->rq_src, // IP Destination 0, 1, // Hop Count index, // Dest IP Address seqno, // Dest Sequence Num MY_ROUTE_TIMEOUT, // Lifetime rq->rq_timestamp); // timestamp#endif /******************************/ Packet::free(p); } // I am not the destination, but I may have a fresh enough route. else if (rt && (rt->rt_hops != INFINITY2) && (rt->rt_seqno >= rq->rq_dst_seqno) ) { //assert (rt->rt_flags == RTF_UP); assert(rq->rq_dst == rt->rt_dst); //assert ((rt->rt_seqno%2) == 0); // is the seqno even?#ifdef MULTICAST sendReply(rq->rq_src, rq->rq_flags, rt->rt_hops, rq->rq_dst, rt->rt_seqno, (u_int32_t) (rt->rt_expire - CURRENT_TIME), // rt->rt_expire - CURRENT_TIME, rq->rq_timestamp); // timestamp#else sendReply(rq->rq_src, 0, rt->rt_hops + 1, rq->rq_dst, rt->rt_seqno, (u_int32_t) (rt->rt_expire - CURRENT_TIME), // rt->rt_expire - CURRENT_TIME, rq->rq_timestamp);#endif // Insert nexthops to RREQ source and RREQ destination in the // precursor lists of destination and source respectively rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source rt0->pc_insert(rt->rt_nexthop); // nexthop to RREQ destination#ifdef RREQ_GRAT_RREP sendReply(rq->rq_dst, rq->rq_flags, rq->rq_hop_count, rq->rq_src, rq->rq_src_seqno, (u_int32_t) (rt->rt_expire - CURRENT_TIME), // rt->rt_expire - CURRENT_TIME, rq->rq_timestamp); // timestamp#endif // TODO: send grat RREP to dst if G flag set in RREQ using rq->rq_src_seqno, rq->rq_hop_counT // DONE: Included gratuitous replies to be sent as per IETF aodv draft specification. As of now, G flag has not been dynamically used and is always set or reset in aodv-packet.h --- Anant Utgikar, 09/16/02. Packet::free(p); } /* * Can't reply. So forward the Route Request */ else { ih->saddr() = index; ih->daddr() = IP_BROADCAST; rq->rq_hop_count += 1;#ifdef PREDICTION if (rt && rt->rt_flags == RTF_P_LINK) { struct hdr_aodv_request_link *rq1 = HDR_AODV_REQUEST_LINK(p); struct hdr_cmn *ch = HDR_CMN(p); ch->size() = IP_HDR_LEN + rq1->size(); rq1->rq_type = AODVTYPE_LINK_RREQ; rq1->from = index; rq1->to = rt->rt_nexthop; }#endif // Maximum sequence number seen en route if (rt) rq->rq_dst_seqno = max(rt->rt_seqno, rq->rq_dst_seqno); forward((aodv_rt_entry*) 0, p, DELAY); }}voidAODV::recvReply(Packet *p) {//struct hdr_cmn *ch = HDR_CMN(p);struct hdr_ip *ih = HDR_IP(p);struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);aodv_rt_entry *rt;char suppress_reply = 0;double delay = 0.0; #ifdef DEBUG fprintf(stderr, "%d - %s: received a REPLY\n", index, __FUNCTION__);#endif // DEBUG /* * Got a reply. So reset the "soft state" maintained for * route requests in the request table. We don't really have * have a separate request table. It is just a part of the * routing table itself. */ // Note that rp_dst is the dest of the data packets, not the // the dest of the reply, which is the src of the data packets.#ifdef MULTICAST if (rp->rp_dst >= IP_MULTICAST){ if (rp->rp_flags != RREP_NO_FLAG && (CURRENT_TIME - rp->rp_timestamp) > 2*RREP_WAIT_TIME) {Packet::free(p); return;} switch (rp->rp_flags){ case RREP_NO_FLAG: break; case RREP_J: recvMRP_J(p); return; case RREP_R: recvMRP_R(p); return; case RREP_JR: recvMRP_JR(p); return; default: Packet::free(p); return; } } rp->rp_hop_count++;#endif rt = rtable.rt_lookup(rp->rp_dst); /* * If I don't have a rt entry to this host... adding */ if(rt == 0) { rt = rtable.rt_add(rp->rp_dst); }#ifdef PREDICTION struct hdr_cmn *ch = HDR_CMN(p); if ((rt->rt_flags == RTF_P_LINK) && rt->rt_nexthop == ch->prev_hop_){ Packet::free(p); return; }#endif /* * Add a forward route table entry... here I am following * Perkins-Royer AODV paper almost literally - SRD 5/99 */ if ( (rt->rt_seqno < rp->rp_dst_seqno) || // newer route ((rt->rt_seqno == rp->rp_dst_seqno) && (rt->rt_hops > rp->rp_hop_count)) ) { // shorter or better route // Update the rt entry rt_update(rt, rp->rp_dst_seqno, rp->rp_hop_count, rp->rp_src, CURRENT_TIME + rp->rp_lifetime); // reset the soft state rt->rt_req_cnt = 0; rt->rt_req_timeout = 0.0; rt->rt_req_last_ttl = rp->rp_hop_count; if (ih->daddr() == index) { // If I am the original source // Update the route discovery latency statistics // rp->rp_timestamp is the time of request origination rt->rt_disc_latency[rt->hist_indx] = (CURRENT_TIME - rp->rp_timestamp) / (double) rp->rp_hop_count; // increment indx for next time rt->hist_indx = (rt->hist_indx + 1) % MAX_HISTORY; } /* * Send all packets queued in the sendbuffer destined for * this destination. * XXX - observe the "second" use of p. */ Packet *buf_pkt; while((buf_pkt = rqueue.deque(rt->rt_dst))) { if(rt->rt_hops != INFINITY2) { assert (rt->rt_flags == RTF_UP); // Delay them a little to help ARP. Otherwise ARP // may drop packets. -SRD 5/23/99 forward(rt, buf_pkt, delay); delay += ARP_DELAY; } } } else { suppress_reply = 1; } /* * If reply is for me, discard it. */if(ih->daddr() == index || suppress_reply) { Packet::free(p); } /* * Otherwise, forward the Route Reply. */ else { // Find the rt entryaodv_rt_entry *rt0 = rtable.rt_lookup(ih->daddr()); // If the rt is up, forward if(rt0 && (rt0->rt_hops != INFINITY2)) { assert (rt0->rt_flags == RTF_UP);#ifndef MULTICAST rp->rp_hop_count += 1;#endif rp->rp_src = index; forward(rt0, p, NO_DELAY); // Insert the nexthop towards the RREQ source to // the precursor list of the RREQ destination rt->pc_insert(rt0->rt_nexthop); // nexthop to RREQ source } else { // I don't know how to forward .. drop the reply. #ifdef DEBUG fprintf(stderr, "%s: dropping Route Reply\n", __FUNCTION__);#endif // DEBUG drop(p, DROP_RTR_NO_ROUTE); } }}voidAODV::recvError(Packet *p) {struct hdr_ip *ih = HDR_IP(p);struct hdr_aodv_error *re = HDR_AODV_ERROR(p);aodv_rt_entry *rt;u_int8_t i;Packet *rerr = Packet::alloc();struct hdr_aodv_error *nre = HDR_AODV_ERROR(rerr); nre->DestCount = 0; for (i=0; i<re->DestCount; i++) { // For each unreachable destination rt = rtable.rt_lookup(re->unreachable_dst[i]); if ( rt && (rt->rt_hops != INFINITY2) && (rt->rt_nexthop == ih->saddr()) && (rt->rt_seqno <= re->unreachable_dst_seqno[i]) ) {#ifdef PREDICTION assert(rt->rt_flags == RTF_UP || rt->rt_flags == RTF_P_LINK || rt->rt_flags == RTF_PREDICTION); #else assert(rt->rt_flags == RTF_UP);#endif assert((rt->rt_seqno%2) == 0); // is the seqno even?#ifdef DEBUG fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\t(%d\t%u\t%d)\n", __FUNCTION__,CURRENT_TIME, index, rt->rt_dst, rt->rt_seqno, rt->rt_nexthop, re->unreachable_dst[i],re->unreachable_dst_seqno[i], ih->saddr());#endif // DEBUG rt->rt_seqno = re->unreachable_dst_seqno[i]; rt_down(rt); // Not sure whether this is the right thing to do Packet *pkt; while((pkt = ifqueue->filter(ih->saddr()))) { drop(pkt, DROP_RTR_MAC_CALLBACK); } // if precursor list non-empty add to RERR and delete the precursor list if (!rt->pc_empty()) { nre->unreachable_dst[nre->DestCount] = rt->rt_dst; nre->unreachable_dst_seqno[nre->DestCount] = rt->rt_seqno; nre->DestCount += 1; rt->pc_delete(); } } } if (nre->DestCount > 0) {#ifdef DEBUG fprintf(stderr, "%s(%f): %d\t sending RERR...\n", __FUNCTION__, CURRENT_TIME, index);#endif // DEBUG sendError(rerr); } else { Packet::free(rerr); } Packet::free(p);}/* Packet Transmission Routines*/voidAODV::forward(aodv_rt_entry *rt, Packet *p, double delay) {struct hdr_cmn *ch = HDR_CMN(p);struct hdr_ip *ih = HDR_IP(p); if(ih->ttl_ == 0) {#ifdef DEBUG fprintf(stderr, "%s: calling drop()\n", __PRETTY_FUNCTION__);#endif // DEBUG drop(p, DROP_RTR_TTL); return; } /*** added for multicast ***/ ch->prev_hop_ = index; /**************************/ if (rt) {#ifdef PREDICTION assert(rt->rt_flags == RTF_UP || rt->rt_flags == RTF_P_LINK || rt->rt_flags == RTF_PREDICTION); if (rt->rt_flags == RTF_UP) rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;#else assert(rt->rt_flags == RTF_UP); rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;#endif ch->next_hop_ = rt->rt_nexthop; ch->addr_type() = NS_AF_INET; ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction } else { // if it is a broadcast packet // assert(ch->ptype() == PT_AODV); // maybe a diff pkt type like gaf assert(ih->daddr() == (nsaddr_t) IP_BROADCAST); ch->addr_type() = NS_AF_NONE; ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction }if (ih->daddr() == (nsaddr_t) IP_BROADCAST) { // If it is a broadcast packet assert(rt == 0); /* * Jitter the sending of broadcast packets by 10ms */#ifdef MULTICAST controlNextHello();#endif Scheduler::instance().schedule(target_, p, 0.01 * Random::uniform()); } else { // Not a broadcast packet if(delay > 0.0) { Scheduler::instance().schedule(target_, p, delay); } else { // Not a broadcast packet, no delay, send immediately Scheduler::instance().schedule(target_, p, 0.); } }}voidAODV::sendRequest(nsaddr_t dst) {// Allocate a RREQ packet Packet *p = Packet::alloc();struct hdr_cmn *ch = HDR_CMN(p);struct hdr_ip *ih = HDR_IP(p);struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);aodv_rt_entry *rt = rtable.rt_lookup(dst); assert(rt); /* * Rate limit sending of Route Requests. We are very conservative * about sending out route requests. */ if (rt->rt_flags == RTF_UP) { assert(rt->rt_hops != INFINITY2); Packet::free((Packet *)p); return; } if (rt->rt_req_timeout > CURRENT_TIME) { Packet::free((Packet *)p); return; } // rt_req_cnt is the no. of times we did network-wide broadcast // RREQ_RETRIES is the maximum number we will allow before // going to a long timeout. if (rt->rt_req_cnt > RREQ_RETRIES) { rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT; rt->rt_req_cnt = 0;#ifdef MULTICAST rt->rt_req_times = 0;#endif Packet *buf_pkt; while ((buf_pkt = rqueue.deque(rt->rt_dst))) { drop(buf_pkt, DROP_RTR_NO_ROUTE); } Packet::free((Packet *)p); return; }#ifdef DEBUG fprintf(stderr, "%2d sending Route Request, dst: %d\n", index, rt->rt_dst);#endif // DEBUG // Determine the TTL to be used this time. // Dynamic TTL evaluation - SRD rt->rt_req_last_ttl = max(rt->rt_req_last_ttl,rt->rt_last_hop_count);#ifdef MULTICAST rt->rt_req_times ++;#endif if (0 == rt->rt_req_last_ttl) { // first time query broadcast ih->ttl_ = TTL_START; } else { // Expanding ring search. if (rt->rt_req_last_ttl < TTL_THRESHOLD) ih->ttl_ = rt->rt_req_last_ttl + TTL_INCREMENT; else { // network-wide broadcast ih->ttl_ = NETWORK_DIAMETER; rt->rt_req_cnt += 1; } } // remember the TTL used for the next time rt->rt_req_last_ttl = ih->ttl_; // PerHopTime is the roundtrip time per hop for route requests.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -