📄 aodv.cc
字号:
/* aodv.cc *//* The AODV code developed by the CMU/MONARCH group was optimized * and tuned by Samir Das and Mahesh Marina, University of Cincinnati. The * work was partially done in Sun Microsystems. * * The original CMU copyright is below. *//*Copyright (c) 1997, 1998 Carnegie Mellon University. All RightsReserved. Permission to use, copy, modify, and distribute thissoftware and its documentation is hereby granted (including forcommercial or for-profit use), provided that both the copyright noticeand this permission notice appear in all copies of the software,derivative works, or modified versions, and any portions thereof, andthat both notices appear in supporting documentation, and that creditis given to Carnegie Mellon University in all publications reportingon direct or indirect use of this code or its derivatives.ALL CODE, SOFTWARE, PROTOCOLS, AND ARCHITECTURES DEVELOPED BY THE CMUMONARCH PROJECT ARE EXPERIMENTAL AND ARE KNOWN TO HAVE BUGS, SOME OFWHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THISSOFTWARE OR OTHER INTELLECTUAL PROPERTY IN ITS ``AS IS'' CONDITION,AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITYBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ORBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCEOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE ORINTELLECTUAL PROPERTY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCHDAMAGE.Carnegie Mellon encourages (but does not require) users of thissoftware or intellectual property to return any improvements orextensions that they make, and to grant Carnegie Mellon the rights toredistribute these changes without encumbrance.*///#include <ip.h>//#include <cmu/cmu-trace.h>//#include <cmu/aodv/aodv.h>#include <cmu/aodv/aodv_packet.h>#include <random.h>#define min(a,b) a < b ? a : b#define max(a,b) a > b ? a : b#define CURRENT_TIME Scheduler::instance().clock()// #define DEBUG#ifdef DEBUGstatic int extra_route_reply = 0;static int limit_route_request = 0;static int route_request = 0;#endif/* TCL Hooks*/static class AODVHeaderClass : public PacketHeaderClass {public: AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV", AODV_HDR_LEN) { } } class_rtProtoAODV_hdr;static class AODVclass : public TclClass {public: AODVclass() : TclClass("Agent/rtProto/AODV") {} TclObject* create(int argc, const char*const* argv) { assert(argc == 5); return (new AODV((nsaddr_t) atoi(argv[4]))); }} class_rtProtoAODV;static voidaodv_rt_failed_callback(Packet *p, void *arg) { ((AODV*) arg)->rt_ll_failed(p);}intAODV::command(int argc, const char*const* argv) { if(argc == 2) { Tcl& tcl = Tcl::instance(); if(strncasecmp(argv[1], "id", 2) == 0) { tcl.resultf("%d", index); return TCL_OK; } if(strncasecmp(argv[1], "start", 2) == 0) { btimer.handle((Event*) 0); rqueue.limit_ = send_buffer_size_; rqueue.timeout_ = send_buffer_timeout_;#ifdef DEBUG fprintf(stderr, "%s: limit(%d)\ttimeout(%f)\n", __FUNCTION__, rqueue.limit_, rqueue.timeout_); fprintf(stderr, "%s(%d): %d\n", __FUNCTION__, index, aomdv_max_paths_); fprintf(stderr, "%s(%d): %d\n", __FUNCTION__, index, aomdv_prim_alt_path_len_diff_);#endif // DEBUG /*#ifndef AODV_LINK_LAYER_DETECTION htimer.handle((Event*) 0); ntimer.handle((Event*) 0);#endif // LINK LAYER DETECTION */#ifdef AODV_HELLO htimer.handle((Event*) 0); ntimer.handle((Event*) 0);#endif // AODV HELLO rtimer.handle((Event*) 0); return TCL_OK; } } else if(argc == 3) { if(strcmp(argv[1], "index") == 0) { index = atoi(argv[2]); return TCL_OK; } else if(strcmp(argv[1], "log-target") == 0) { logtarget = (Trace*) TclObject::lookup(argv[2]); if(logtarget == 0) return TCL_ERROR; return TCL_OK; } else if(strcmp(argv[1], "drop-target") == 0) { int stat = rqueue.command(argc,argv); if (stat != TCL_OK) return stat; return Agent::command(argc, argv); } else if(strcmp(argv[1], "if-queue") == 0) { ifqueue = (PriQueue*) TclObject::lookup(argv[2]); if(ifqueue == 0) return TCL_ERROR; return TCL_OK; }} return Agent::command(argc, argv);}/* Constructor*/AODV::AODV(nsaddr_t id) : Agent(PT_AODV), btimer(this), htimer(this), ntimer(this), rtimer(this), lrtimer(this), rqueue() { bind("off_AODV_", &off_AODV_); send_buffer_size_ = AODV_RTQ_MAX_LEN; bind("send_buffer_size_", &send_buffer_size_); send_buffer_timeout_ = AODV_RTQ_TIMEOUT; bind("send_buffer_timeout_", &send_buffer_timeout_);#ifdef AOMDV aomdv_max_paths_ = 0; bind("aomdv_max_paths_", &aomdv_max_paths_); aomdv_prim_alt_path_len_diff_ = 0; bind("aomdv_prim_alt_path_len_diff_", &aomdv_prim_alt_path_len_diff_);#endif AOMDV index = id; seqno = 2; bid = 1; LIST_INIT(&nbhead); LIST_INIT(&bihead); logtarget = 0; ifqueue = 0;}voidAODV::recv(Packet *p, Handler*) {struct hdr_cmn *ch = HDR_CMN(p);struct hdr_ip *ih = HDR_IP(p); assert(initialized()); assert(p->incoming == 0); if(ch->ptype() == PT_AODV) { ih->ttl_ -= 1; recvAODV(p); return; } /* * Must be a packet I'm originating... */ if((ih->src_ == index) && (ch->num_forwards() == 0)) { assert(DATA_PACKET(ch->ptype())); /* * Add the IP Header */ ch->size() += IP_HDR_LEN;#ifdef AOMDV ch->aomdv_salvage_count_ = 0;#endif // AOMDV ih->ttl_ = NETWORK_DIAMETER; } /* * I received a packet that I sent. Probably * a routing loop. */ else if(ih->src_ == index) { drop(p, DROP_RTR_ROUTE_LOOP); return; } /* * Packet I'm forwarding... */ else { /* * Check the TTL. If it is zero, then discard. */ if(--ih->ttl_ == 0) { drop(p, DROP_RTR_TTL); return; } } rt_resolve(p);}voidAODV::recvAODV(Packet *p) {struct hdr_aodv *ah = HDR_AODV(p);struct hdr_ip *ih = HDR_IP(p); assert(ih->sport_ == RT_PORT); assert(ih->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); }}/* * Data packet forwarding */voidAODV::rt_resolve(Packet *p) {struct hdr_cmn *ch = HDR_CMN(p);struct hdr_ip *ih = HDR_IP(p);aodv_rt_entry *rt; /* * Set the transmit failure callback. That * won't change. */ ch->xmit_failure_ = aodv_rt_failed_callback; ch->xmit_failure_data_ = (void*) this; rt = rtable.rt_lookup(ih->dst_); if(rt == 0) { rt = rtable.rt_add(ih->dst_); } /* * If the route is up, forward the packet */ if(rt->rt_flags == RTF_UP) { forward(rt, p, NO_DELAY); } /* * if I am the source of the packet, then do a Route Request. */ else if(ih->src_ == index) { rqueue.enque(p); sendRequest(rt->rt_dst); } /* * A local repair is in progress. Buffer the packet. */ else if (rt->rt_flags == RTF_IN_REPAIR) { rqueue.enque(p); } /* * I am trying to forward a packet for someone else to which * I don't have a route. * Drop the packet and send a route error upstream */ else { Packet *rerr = Packet::alloc(); struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr); #ifdef DEBUG fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__);#endif // DEBUG assert (rt->rt_flags == RTF_DOWN); re->DestCount = 0; re->unreachable_dst[re->DestCount] = rt->rt_dst; re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno; re->DestCount += 1; sendError(rerr, false); drop(p, DROP_RTR_NO_ROUTE); }}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; } if (rt) { assert(rt->rt_flags == RTF_UP); ch->addr_type() = AF_INET;#ifndef AOMDV ch->next_hop_ = rt->rt_nexthop; rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; // CHANGE if ((ih->src_ != index) && DATA_PACKET(ch->ptype())) rt->rt_error = true; // CHANGE #else AOMDVAODV_Path *path = rt->path_find(); ch->next_hop_ = path->nexthop; path->expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT; // CHANGE if ((ih->src_ != index) && DATA_PACKET(ch->ptype())) rt->rt_error = true; // CHANGE #endif AOMDV } else { // if it is a broadcast packet assert(ch->ptype() == PT_AODV); assert(ih->dst_ == (nsaddr_t) IP_BROADCAST); ch->addr_type() = AF_NONE; } if (ih->dst_ == (nsaddr_t) IP_BROADCAST) { // If it is a broadcast packet assert(rt == 0); /* * Jitter the sending of broadcast packets by 10ms */ Scheduler::instance().schedule(target_, p, 0.01 * Random::uniform()); } else { // Not a broadcast packet // CHANGE ch->xmit_failure_ = aodv_rt_failed_callback; ch->xmit_failure_data_ = (void*) this; // CHANGE 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.); } }}/* * Route discovery */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); if (rt->rt_flags == RTF_UP) { 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 if (rt->rt_req_cnt > RREQ_RETRIES) { rt->rt_req_timeout = 0.0; rt->rt_req_last_ttl = 0; rt->rt_req_cnt = 0; Packet *buf_pkt; while ((buf_pkt = rqueue.deque(rt->rt_dst))) { drop(buf_pkt, DROP_RTR_QTIMEOUT); } Packet::free((Packet *)p); return; } rt->rt_expire = 0; // expanding ring search: dynamic ttl evaluation int new_ttl = 0; if (rt->rt_req_last_ttl == 0) { // we are about to start a new route discovery if (rt->rt_last_hop_count == 0) new_ttl = TTL_START; else new_ttl = rt->rt_last_hop_count + TTL_INCREMENT; } else { // we are already in the midst of a route discovery assert (rt->rt_req_last_ttl > rt->rt_last_hop_count); if (rt->rt_req_last_ttl < TTL_THRESHOLD) new_ttl = rt->rt_req_last_ttl + TTL_INCREMENT; else new_ttl = NETWORK_DIAMETER; } if (new_ttl >= NETWORK_DIAMETER) { // network-wide broadcast new_ttl = NETWORK_DIAMETER; rt->rt_req_cnt += 1; } ih->ttl_ = new_ttl; rt->rt_req_last_ttl = new_ttl; rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt); // PerHopTime is the roundtrip time per hop for route requests. // The factor 2.0 is just to be safe .. SRD 5/22/99 if (rt->rt_req_cnt > 0) rt->rt_req_timeout *= rt->rt_req_cnt; // Also note that we are making timeouts to be larger if we have // done network wide broadcast before. rt->rt_req_timeout += CURRENT_TIME; // Fill out the RREQ packet // ch->uid() = 0; ch->ptype() = PT_AODV; ch->size() = IP_HDR_LEN + rq->size(); ch->iface() = -2; ch->error() = 0; ch->addr_type() = AF_NONE; ih->src_ = index; ih->dst_ = IP_BROADCAST; ih->sport_ = RT_PORT; ih->dport_ = RT_PORT; // Fill up some more fields. rq->rq_type = AODVTYPE_RREQ; rq->rq_bcast_id = bid++; rq->rq_hop_count = 0; rq->rq_dst = dst; rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0); rq->rq_src = index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -