本文主要是介绍NS2下AODV协议aodv.cc注释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原文地址:http://blog.csdn.net/ise_gaoyue1990/article/details/7610522
- //#include <ip.h>
- #include <aodv/aodv.h>
- #include <aodv/aodv_packet.h>
- #include <random.h>
- #include <cmu-trace.h>
- //#include <energy-model.h>
- #define max(a,b) ( (a) > (b) ? (a) : (b) )
- #define CURRENT_TIME Scheduler::instance().clock()
- //#define DEBUG
- //#define ERROR
- #ifdef DEBUG
- static int extra_route_reply = 0;
- static int limit_route_request = 0;
- static int route_request = 0;
- #endif
- /*
- TCL Hooks
- */
- int hdr_aodv::offset_;
- static class AODVHeaderClass : public PacketHeaderClass {
- public:
- AODVHeaderClass() : PacketHeaderClass("PacketHeader/AODV",
- sizeof(hdr_all_aodv)) {
- bind_offset(&hdr_aodv::offset_);
- }
- } class_rtProtoAODV_hdr;
- /*AODVclass 只有两个函数,构造函数和creat函数*/
- static class AODVclass : public TclClass {
- public:
- AODVclass() : TclClass("Agent/AODV") {}
- TclObject* create(int argc, const char*const* argv) {
- assert(argc == 5);
- //return (new AODV((nsaddr_t) atoi(argv[4])));
- return (new AODV((nsaddr_t) Address::instance().str2addr(argv[4])));
- }
- } class_rtProtoAODV;
- /*command函数实现了命令的分发*/
- int
- AODV::command(int argc, const char*const* argv) {
- if(argc == 2) {//命令的参数个数是2
- Tcl& tcl = Tcl::instance();
- if(strncasecmp(argv[1], "id", 2) == 0) {//命令所要求的操作为id
- tcl.resultf("%d", index);
- return TCL_OK;
- }
- if(strncasecmp(argv[1], "start", 2) == 0) {//命令所要求的操作为start
- btimer.handle((Event*) 0);
- #ifndef AODV_LINK_LAYER_DETECTION
- htimer.handle((Event*) 0);
- ntimer.handle((Event*) 0);
- #endif // LINK LAYER DETECTION
- rtimer.handle((Event*) 0);
- return TCL_OK;
- }
- }
- else if(argc == 3) {//命令参数个数等于3
- if(strcmp(argv[1], "index") == 0) {//命令所要求的操作为index
- index = atoi(argv[2]);
- return TCL_OK;
- }
- //命令所要求的操作为log-target或者tracetarget
- else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {
- logtarget = (Trace*) TclObject::lookup(argv[2]);
- if(logtarget == 0)
- return TCL_ERROR;
- return TCL_OK;
- }
- else if(strcmp(argv[1], "drop-target") == 0)
- {
- //命令所要求的操作为drop-target
- int stat = rqueue.command(argc,argv);
- if (stat != TCL_OK) return stat;
- return Agent::command(argc, argv);
- }
- //命令所要求的操作if-queue
- else if(strcmp(argv[1], "if-queue") == 0) {
- ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
- if(ifqueue == 0)
- return TCL_ERROR;
- return TCL_OK;
- }
- //命令所要求的操作为port-dmux
- else if (strcmp(argv[1], "port-dmux") == 0) {
- dmux_ = (PortClassifier *)TclObject::lookup(argv[2]);
- if (dmux_ == 0) {
- fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__,
- argv[1], argv[2]);
- 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() {
- index = id;
- seqno = 2;
- bid = 1;
- LIST_INIT(&nbhead);
- LIST_INIT(&bihead);
- logtarget = 0;
- ifqueue = 0;
- }
- /*
- Timers
- */
- //广播定时器
- void
- BroadcastTimer::handle(Event*) {
- agent->id_purge();
- Scheduler::instance().schedule(this, &intr, BCAST_ID_SAVE);
- }
- //hello报文定时器
- void
- HelloTimer::handle(Event*) {
- agent->sendHello();
- double interval = MinHelloInterval +
- ((MaxHelloInterval - MinHelloInterval) * Random::uniform());
- assert(interval >= 0);
- Scheduler::instance().schedule(this, &intr, interval);
- }
- //邻居定时器
- void
- NeighborTimer::handle(Event*) {
- agent->nb_purge();
- Scheduler::instance().schedule(this, &intr, HELLO_INTERVAL);
- }
- 路由缓存定时器
- void
- RouteCacheTimer::handle(Event*) {
- agent->rt_purge();
- #define FREQUENCY 0.5 // sec
- Scheduler::instance().schedule(this, &intr, FREQUENCY);
- }
- //路由缓存定时器
- void
- LocalRepairTimer::handle(Event* p) { // SRD: 5/4/99
- aodv_rt_entry *rt;
- struct hdr_ip *ih = HDR_IP( (Packet *)p);
- /* you get here after the timeout in a local repair attempt */
- /* fprintf(stderr, "%s\n", __FUNCTION__); */
- rt = agent->rtable.rt_lookup(ih->daddr());
- if (rt && rt->rt_flags != RTF_UP) {
- // route is yet to be repaired
- // I will be conservative and bring down the route
- // and send route errors upstream.
- /* The following assert fails, not sure why */
- /* assert (rt->rt_flags == RTF_IN_REPAIR); */
- //rt->rt_seqno++;
- agent->rt_down(rt);
- // send RERR
- #ifdef DEBUG
- fprintf(stderr,"Node %d: Dst - %d, failed local repair\n",index, rt->rt_dst);
- #endif
- }
- Packet::free((Packet *)p);
- }
- /*
- Broadcast ID Management Functions
- */
- void
- AODV::id_insert(nsaddr_t id, u_int32_t bid) {
- BroadcastID *b = new BroadcastID(id, bid);
- assert(b);
- b->expire = CURRENT_TIME + BCAST_ID_SAVE;
- LIST_INSERT_HEAD(&bihead, b, link);
- }
- /* SRD */
- bool
- AODV::id_lookup(nsaddr_t id, u_int32_t bid) {
- BroadcastID *b = bihead.lh_first;
- // Search the list for a match of source and bid
- for( ; b; b = b->link.le_next) {
- if ((b->src == id) && (b->id == bid))
- return true;
- }
- return false;
- }
- void
- AODV::id_purge() {
- BroadcastID *b = bihead.lh_first;
- BroadcastID *bn;
- double now = CURRENT_TIME;
- for(; b; b = bn) {
- bn = b->link.le_next;
- if(b->expire <= now) {
- LIST_REMOVE(b,link);
- delete b;
- }
- }
- }
- /*
- Helper Functions
- */
- double
- AODV::PerHopTime(aodv_rt_entry *rt) {
- int num_non_zero = 0, i;
- double total_latency = 0.0;
- if (!rt)
- return ((double) NODE_TRAVERSAL_TIME );
- for (i=0; i < MAX_HISTORY; i++) {
- if (rt->rt_disc_latency[i] > 0.0) {
- num_non_zero++;
- total_latency += rt->rt_disc_latency[i];
- }
- }
- if (num_non_zero > 0)
- return(total_latency / (double) num_non_zero);
- else
- return((double) NODE_TRAVERSAL_TIME);
- }
- /*
- Link Failure Management Functions
- */
- static void
- aodv_rt_failed_callback(Packet *p, void *arg) {
- ((AODV*) arg)->rt_ll_failed(p);
- }
- /*
- * This routine is invoked when the link-layer reports a route failed.
- */
- /*邻居链路down掉,处理*/
- void
- AODV::rt_ll_failed(Packet *p) {
- struct hdr_cmn *ch = HDR_CMN(p);
- struct hdr_ip *ih = HDR_IP(p);
- aodv_rt_entry *rt;
- nsaddr_t broken_nbr = ch->next_hop_;//记录下一跳邻居的地址
- #ifndef AODV_LINK_LAYER_DETECTION
- drop(p, DROP_RTR_MAC_CALLBACK);
- #else
- /*
- * Non-data packets and Broadcast Packets can be dropped.
- */
- //如果是非数据或者广播报文,则可以直接丢弃
- if(! DATA_PACKET(ch->ptype()) ||
- (u_int32_t) ih->daddr() == IP_BROADCAST) {
- drop(p, DROP_RTR_MAC_CALLBACK);
- return;
- }
- log_link_broke(p);
- //如果不存在到达目的节点的路径,丢弃报文
- if((rt = rtable.rt_lookup(ih->daddr())) == 0) {
- drop(p, DROP_RTR_MAC_CALLBACK);
- return;
- }
- log_link_del(ch->next_hop_);
- #ifdef AODV_LOCAL_REPAIR
- /* if the broken link is closer to the dest than source,
- attempt a local repair. Otherwise, bring down the route. */
- //如果转发的跳数大于到达目的节点的跳数,则进行路由修复;否则丢弃通过此邻居的
- //数据并且删除此邻居
- if (ch->num_forwards() > rt->rt_hops) {
- local_rt_repair(rt, p); // local repair
- // retrieve all the packets in the ifq using this link,
- // queue the packets for which local repair is done,
- return;
- }
- else
- #endif // LOCAL REPAIR
- {
- drop(p, DROP_RTR_MAC_CALLBACK);
- // Do the same thing for other packets in the interface queue using the
- // broken link -Mahesh
- while((p = ifqueue->filter(broken_nbr))) {
- drop(p, DROP_RTR_MAC_CALLBACK);
- }
- nb_delete(broken_nbr);
- }
- #endif // LINK LAYER DETECTION
- }
- /*当发现邻居失效的时候,就会调用此函数*/
- void
- AODV::handle_link_failure(nsaddr_t id) {
- aodv_rt_entry *rt, *rtn;
- Packet *rerr = Packet::alloc();
- struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
- re->DestCount = 0;
- //查找通过此邻居节点到达目的的路由,
- for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
- rtn = rt->rt_link.le_next;
- //如果跳数不是无限大并且下一跳就是失效的邻居
- if ((rt->rt_hops != INFINITY2) && (rt->rt_nexthop == id) ) {
- assert (rt->rt_flags == RTF_UP);
- assert((rt->rt_seqno%2) == 0);
- rt->rt_seqno++;
- re->unreachable_dst[re->DestCount] = rt->rt_dst;
- re->unreachable_dst_seqno[re->DestCount] = rt->rt_seqno;
- #ifdef DEBUG
- fprintf(stderr, "%s(%f): %d\t(%d\t%u\t%d)\n", __FUNCTION__, CURRENT_TIME,
- index, re->unreachable_dst[re->DestCount],
- re->unreachable_dst_seqno[re->DestCount], rt->rt_nexthop);
- #endif // DEBUG
- re->DestCount += 1;
- rt_down(rt);//将此路由down掉
- }
- // remove the lost neighbor from all the precursor lists
- rt->pc_delete(id);//删除此路由的前缀列表
- }
- /*如果存在通过此邻居到达目的节点的路由,则发送错误报文*/
- if (re->DestCount > 0) {
- #ifdef DEBUG
- fprintf(stderr, "%s(%f): %d\tsending RERR...\n", __FUNCTION__, CURRENT_TIME, index);
- #endif // DEBUG
- sendError(rerr, false);
- }
- else {
- Packet::free(rerr);
- }
- }
- void
- AODV::local_rt_repair(aodv_rt_entry *rt, Packet *p) {
- #ifdef DEBUG
- fprintf(stderr,"%s: Dst - %d\n", __FUNCTION__, rt->rt_dst);
- #endif
- // Buffer the packet
- rqueue.enque(p);
- // mark the route as under repair
- rt->rt_flags = RTF_IN_REPAIR;
- sendRequest(rt->rt_dst);
- // set up a timer interrupt
- Scheduler::instance().schedule(&lrtimer, p->copy(), rt->rt_req_timeout);
- }
- /*更新路由条目*/
- void
- AODV::rt_update(aodv_rt_entry *rt, u_int32_t seqnum, u_int16_t metric,
- nsaddr_t nexthop, double expire_time) {
- rt->rt_seqno = seqnum;
- rt->rt_hops = metric;
- rt->rt_flags = RTF_UP;
- rt->rt_nexthop = nexthop;
- rt->rt_expire = expire_time;
- }
- /*将此路由条目down掉*/
- void
- AODV::rt_down(aodv_rt_entry *rt) {
- /*
- * Make sure that you don't "down" a route more than once.
- */
- if(rt->rt_flags == RTF_DOWN) {
- return;
- }
- // assert (rt->rt_seqno%2); // is the seqno odd?
- rt->rt_last_hop_count = rt->rt_hops;
- rt->rt_hops = INFINITY2;
- rt->rt_flags = RTF_DOWN;
- rt->rt_nexthop = 0;
- rt->rt_expire = 0;
- } /* rt_down function */
- /*
- Route Handling Functions
- */
- void
- AODV::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->daddr());
- if(rt == 0) {
- rt = rtable.rt_add(ih->daddr());
- }
- /*
- * If the route is up, forward the packet
- */
- //如果存在路由,则转发
- if(rt->rt_flags == RTF_UP) {
- assert(rt->rt_hops != INFINITY2);
- forward(rt, p, NO_DELAY);
- }
- /*
- * if I am the source of the packet, then do a Route Request.
- */
- else if(ih->saddr() == 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.
- */
- //否则发送错误报文
- else {
- Packet *rerr = Packet::alloc();
- struct hdr_aodv_error *re = HDR_AODV_ERROR(rerr);
- /*
- * For now, drop the packet and send error upstream.
- * Now the route errors are broadcast to upstream
- * neighbors - Mahesh 09/11/99
- */
- 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;
- #ifdef DEBUG
- fprintf(stderr, "%s: sending RERR...\n", __FUNCTION__);
- #endif
- sendError(rerr, false);
- drop(p, DROP_RTR_NO_ROUTE);
- }
- }
- /*定时查看路由缓存条目*/
- void
- AODV::rt_purge() {
- aodv_rt_entry *rt, *rtn;
- double now = CURRENT_TIME;
- double delay = 0.0;
- Packet *p;
- for(rt = rtable.head(); rt; rt = rtn) { // for each rt entry
- rtn = rt->rt_link.le_next;
- //如果此路由条目标注为有效,但是生存时间为0
- //丢弃前往目的分组,并且将此路由条目down掉
- if ((rt->rt_flags == RTF_UP) && (rt->rt_expire < now)) {
- // if a valid route has expired, purge all packets from
- // send buffer and invalidate the route.
- assert(rt->rt_hops != INFINITY2);
- while((p = rqueue.deque(rt->rt_dst))) {
- #ifdef DEBUG
- fprintf(stderr, "%s: calling drop()\n",
- __FUNCTION__);
- #endif // DEBUG
- drop(p, DROP_RTR_NO_ROUTE);
- }
- rt->rt_seqno++;
- assert (rt->rt_seqno%2);
- rt_down(rt);
- }
- //如果此路由条目并没有过期,则可以发送分组
- else if (rt->rt_flags == RTF_UP) {
- // If the route is not expired,
- // and there are packets in the sendbuffer waiting,
- // forward them. This should not be needed, but this extra
- // check does no harm.
- assert(rt->rt_hops != INFINITY2);
- while((p = rqueue.deque(rt->rt_dst))) {
- forward (rt, p, delay);
- delay += ARP_DELAY;
- }
- }
- //如果此路由条目已经down掉,但是有前往目的的分组,则发送路由请求
- else if (rqueue.find(rt->rt_dst))
- // If the route is down and
- // if there is a packet for this destination waiting in
- // the sendbuffer, then send out route request. sendRequest
- // will check whether it is time to really send out request
- // or not.
- // This may not be crucial to do it here, as each generated
- // packet will do a sendRequest anyway.
- sendRequest(rt->rt_dst);
- }
- }
- /*
- Packet Reception Routines
- */
- void
- AODV::recv(Packet *p, Handler*) {
- struct hdr_cmn *ch = HDR_CMN(p);
- struct hdr_ip *ih = HDR_IP(p);
- assert(initialized());
- //assert(p->incoming == 0);
- // XXXXX NOTE: use of incoming flag has been depracated; In order to track direction of pkt flow, direction_ in hdr_cmn is used instead. see packet.h for details.
- //如果分组类型是AODV类型,则交给recvAodv函数
- if(ch->ptype() == PT_AODV) {
- ih->ttl_ -= 1;
- recvAODV(p);
- return;
- }
- /*
- * Must be a packet I'm originating...
- */
- //如果是我发送的报文,加上包头,ch->num_forward()是转发的跳数
- if((ih->saddr() == index) && (ch->num_forwards() == 0)) {
- /*
- * Add the IP Header
- */
- ch->size() += IP_HDR_LEN;
- // Added by Parag Dadhania && John Novatnack to handle broadcasting
- if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
- ih->ttl_ = NETWORK_DIAMETER;
- }
- /*
- * I received a packet that I sent. Probably
- * a routing loop.
- */
- //出现路由环路,丢弃
- else if(ih->saddr() == index) {
- drop(p, DROP_RTR_ROUTE_LOOP);
- return;
- }
- /*
- * Packet I'm forwarding...
- */
- else {
- /*
- * Check the TTL. If it is zero, then discard.
- */
- //如果ttl值为零,丢弃
- if(--ih->ttl_ == 0) {
- drop(p, DROP_RTR_TTL);
- return;
- }
- }
- // Added by Parag Dadhania && John Novatnack to handle broadcasting
- //如果不是广播报文,交给re_resolve函数处理;如果是广播报文,则转发
- if ( (u_int32_t)ih->daddr() != IP_BROADCAST)
- rt_resolve(p);
- else
- forward((aodv_rt_entry*) 0, p, NO_DELAY);
- }
- void
- AODV::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);
- }
- }
- void
- AODV::recvRequest(Packet *p) {
- struct hdr_ip *ih = HDR_IP(p);
- struct hdr_aodv_request *rq = HDR_AODV_REQUEST(p);
- aodv_rt_entry *rt;
- /*
- * Drop if:
- * - I'm the source
- * - I recently heard this request.
- */
- /*如果此节点就是源节点,出现环路,丢弃路由请求报文*/
- if(rq->rq_src == index) {
- #ifdef DEBUG
- fprintf(stderr, "%s: got my own REQUEST\n", __FUNCTION__);
- #endif // DEBUG
- Packet::free(p);
- return;
- }
- /*如果已经收到了源地址和请求序列号相等的请求报文,丢弃*/
- if (id_lookup(rq->rq_src, rq->rq_bcast_id)) {
- #ifdef DEBUG
- fprintf(stderr, "%s: discarding request\n", __FUNCTION__);
- #endif // DEBUG
- Packet::free(p);
- return;
- }
- /*
- * Cache the broadcast ID
- */
- /*缓存此路由请求*/
- id_insert(rq->rq_src, rq->rq_bcast_id);
- /*
- * We are either going to forward the REQUEST or generate a
- * REPLY. Before we do anything, we make sure that the REVERSE
- * route is in the route table.
- */
- //建立反向路径
- aodv_rt_entry *rt0; // rt0 is the reverse route
- rt0 = rtable.rt_lookup(rq->rq_src);
- if(rt0 == 0) { /* if not in the route table */
- // create an entry for the reverse route.
- rt0 = rtable.rt_add(rq->rq_src);
- }
- //更新此路由条目的生存时间
- rt0->rt_expire = max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE));
- /*如果请求序列号大于路由序列号或者两者序列号相等但是跳数
- 比源路由跳数小,则更新*/
- if ( (rq->rq_src_seqno > rt0->rt_seqno ) ||
- ((rq->rq_src_seqno == rt0->rt_seqno) &&
- (rq->rq_hop_count < rt0->rt_hops)) ) {
- // If we have a fresher seq no. or lesser #hops for the
- // same seq no., update the rt entry. Else don't bother.
- rt_update(rt0, rq->rq_src_seqno, rq->rq_hop_count, ih->saddr(),
- max(rt0->rt_expire, (CURRENT_TIME + REV_ROUTE_LIFE)) );
- /*如果此前请求过该路由条目,则更新信息*/
- if (rt0->rt_req_timeout > 0.0) {
- // Reset the soft state and
- // Set expiry time to CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT
- // This is because route is used in the forward direction,
- // but only sources get benefited by this change
- rt0->rt_req_cnt = 0;
- rt0->rt_req_timeout = 0.0;
- rt0->rt_req_last_ttl = rq->rq_hop_count;
- rt0->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
- }
- /* Find out whether any buffered packet can benefit from the
- * reverse route.
- * May need some change in the following code - Mahesh 09/11/99
- */
- /*如果有到反向路径的分组报文,则发送*/
- assert (rt0->rt_flags == RTF_UP);
- Packet *buffered_pkt;
- while ((buffered_pkt = rqueue.deque(rt0->rt_dst))) {
- if (rt0 && (rt0->rt_flags == RTF_UP)) {
- assert(rt0->rt_hops != INFINITY2);
- forward(rt0, buffered_pkt, NO_DELAY);
- }
- }
- }
- // End for putting reverse route in rt table
- /*
- * We have taken care of the reverse route stuff.
- * Now see whether we can send a route reply.
- */
- //寻找到目的节点的路由
- 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++;
- sendReply(rq->rq_src, // IP Destination
- 1, // Hop Count
- index, // Dest IP Address
- seqno, // Dest Sequence Num
- MY_ROUTE_TIMEOUT, // Lifetime
- rq->rq_timestamp); // timestamp
- 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?
- sendReply(rq->rq_src,
- 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);
- // Insert nexthops to RREQ source and RREQ destination in the
- // precursor lists of destination and source respectively
- rt->pc_insert(rt0->rt_nexthop); // 加入前缀列表
- rt0->pc_insert(rt->rt_nexthop); // 加入前缀列表
- #ifdef RREQ_GRAT_RREP
- sendReply(rq->rq_dst,
- 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);
- #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;
- // 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);
- }
- }
- void
- AODV::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.
- 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);
- }
- /*
- * 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 entry
- aodv_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);
- rp->rp_hop_count += 1;
- 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);
- }
- }
- }
- /*从邻居那里收到错误分组,检查自己路由表是否有通过此邻居到达目的地的
- 路由条目,如果有,则将此路由删除,并继续向邻居广播错误分组*/
- void
- AODV::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]) ) {
- assert(rt->rt_flags == RTF_UP);
- assert((rt->rt_seqno%2) == 0); // 奇数代表无穷大,无效的意思
- #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);//将此路由down掉
- // Not sure whether this is the right thing to do
- /*查看队列中是否有下一跳是此邻居的分组
- 若有的话,直接丢包;具体请看queue/priqueue.cc的filter函数*/
- 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
- */
- void
- AODV::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;
- }
- /*如果不是AODV数据包并且链路方向是上行并且是广播包或者此节点就是目的地址*/
- if (ch->ptype() != PT_AODV && ch->direction() == hdr_cmn::UP &&
- ((u_int32_t)ih->daddr() == IP_BROADCAST)
- || ((u_int32_t)ih->daddr() == here_.addr_)) {
- dmux_->recv(p,0);//交给分类器
- return;
- }
- if (rt) {//如果存在去往目的的路由,设置一系列参数
- assert(rt->rt_flags == RTF_UP);
- rt->rt_expire = CURRENT_TIME + ACTIVE_ROUTE_TIMEOUT;
- 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
- */
- Scheduler::instance().schedule(target_, p,
- 0.01 * Random::uniform());//加入定时器
- }
- else { // 非广播报文
- 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.);
- }
- }
- }
- void
- AODV::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;
- 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) - %2d sending Route Request, dst: %d\n",
- ++route_request, 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);
- //路由请求的环搜索
- //第一次广播请求,选择初始跳数;随后逐渐扩大
- 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.
- // The factor 2.0 is just to be safe .. SRD 5/22/99
- // Also note that we are making timeouts to be larger if we have
- // done network wide broadcast before.
- rt->rt_req_timeout = 2.0 * (double) ih->ttl_ * PerHopTime(rt);
- if (rt->rt_req_cnt > 0)
- rt->rt_req_timeout *= rt->rt_req_cnt;
- rt->rt_req_timeout += CURRENT_TIME;
- // Don't let the timeout to be too large, however .. SRD 6/8/99
- if (rt->rt_req_timeout > CURRENT_TIME + MAX_RREQ_TIMEOUT)
- rt->rt_req_timeout = CURRENT_TIME + MAX_RREQ_TIMEOUT;
- rt->rt_expire = 0;
- #ifdef DEBUG
- fprintf(stderr, "(%2d) - %2d sending Route Request, dst: %d, tout %f ms\n",
- ++route_request,
- index, rt->rt_dst,
- rt->rt_req_timeout - CURRENT_TIME);
- #endif // DEBUG
- // 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() = NS_AF_NONE;
- ch->prev_hop_ = index; // AODV hack
- ih->saddr() = index;
- ih->daddr() = IP_BROADCAST;
- ih->sport() = RT_PORT;
- ih->dport() = RT_PORT;
- // Fill up some more fields.
- rq->rq_type = AODVTYPE_RREQ;
- rq->rq_hop_count = 1;
- rq->rq_bcast_id = bid++;
- rq->rq_dst = dst;
- rq->rq_dst_seqno = (rt ? rt->rt_seqno : 0);
- rq->rq_src = index;
- seqno += 2;
- assert ((seqno%2) == 0);
- rq->rq_src_seqno = seqno;
- rq->rq_timestamp = CURRENT_TIME;
- Scheduler::instance().schedule(target_, p, 0.);
- }
- void
- AODV::sendReply(nsaddr_t ipdst, u_int32_t hop_count, nsaddr_t rpdst,
- u_int32_t rpseq, u_int32_t lifetime, double timestamp) {
- Packet *p = Packet::alloc();
- 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 = rtable.rt_lookup(ipdst);
- #ifdef DEBUG
- fprintf(stderr, "sending Reply from %d at %.2f\n", index, Scheduler::instance().clock());
- #endif // DEBUG
- assert(rt);
- rp->rp_type = AODVTYPE_RREP;
- //rp->rp_flags = 0x00;
- rp->rp_hop_count = hop_count;
- rp->rp_dst = rpdst;
- rp->rp_dst_seqno = rpseq;
- rp->rp_src = index;
- rp->rp_lifetime = lifetime;
- rp->rp_timestamp = timestamp;
- // ch->uid() = 0;
- ch->ptype() = PT_AODV;
- ch->size() = IP_HDR_LEN + rp->size();
- ch->iface() = -2;
- ch->error() = 0;
- ch->addr_type() = NS_AF_INET;
- ch->next_hop_ = rt->rt_nexthop;
- ch->prev_hop_ = index; // AODV hack
- ch->direction() = hdr_cmn::DOWN;
- ih->saddr() = index;
- ih->daddr() = ipdst;
- ih->sport() = RT_PORT;
- ih->dport() = RT_PORT;
- ih->ttl_ = NETWORK_DIAMETER;
- Scheduler::instance().schedule(target_, p, 0.);
- }
- void
- AODV::sendError(Packet *p, bool jitter) {
- struct hdr_cmn *ch = HDR_CMN(p);
- struct hdr_ip *ih = HDR_IP(p);
- struct hdr_aodv_error *re = HDR_AODV_ERROR(p);
- #ifdef ERROR
- fprintf(stderr, "sending Error from %d at %.2f\n", index, Scheduler::instance().clock());
- #endif // DEBUG
- re->re_type = AODVTYPE_RERR;
- //re->reserved[0] = 0x00; re->reserved[1] = 0x00;
- // DestCount and list of unreachable destinations are already filled
- // ch->uid() = 0;
- ch->ptype() = PT_AODV;
- ch->size() = IP_HDR_LEN + re->size();
- ch->iface() = -2;
- ch->error() = 0;
- ch->addr_type() = NS_AF_NONE;
- ch->next_hop_ = 0;
- ch->prev_hop_ = index; // AODV hack
- ch->direction() = hdr_cmn::DOWN; //important: change the packet's direction
- ih->saddr() = index;
- ih->daddr() = IP_BROADCAST;
- ih->sport() = RT_PORT;
- ih->dport() = RT_PORT;
- ih->ttl_ = 1;
- // Do we need any jitter? Yes
- if (jitter)
- Scheduler::instance().schedule(target_, p, 0.01*Random::uniform());
- else
- Scheduler::instance().schedule(target_, p, 0.0);
- }
- /*
- Neighbor Management Functions
- */
- void
- AODV::sendHello() {
- Packet *p = Packet::alloc();
- struct hdr_cmn *ch = HDR_CMN(p);
- struct hdr_ip *ih = HDR_IP(p);
- struct hdr_aodv_reply *rh = HDR_AODV_REPLY(p);
- #ifdef DEBUG
- fprintf(stderr, "sending Hello from %d at %.2f\n", index, Scheduler::instance().clock());
- #endif // DEBUG
- rh->rp_type = AODVTYPE_HELLO;
- //rh->rp_flags = 0x00;
- rh->rp_hop_count = 1;
- rh->rp_dst = index;
- rh->rp_dst_seqno = seqno;
- rh->rp_lifetime = (1 + ALLOWED_HELLO_LOSS) * HELLO_INTERVAL;
- // ch->uid() = 0;
- ch->ptype() = PT_AODV;
- ch->size() = IP_HDR_LEN + rh->size();
- ch->iface() = -2;
- ch->error() = 0;
- ch->addr_type() = NS_AF_NONE;
- ch->prev_hop_ = index; // AODV hack
- ih->saddr() = index;
- ih->daddr() = IP_BROADCAST;
- ih->sport() = RT_PORT;
- ih->dport() = RT_PORT;
- ih->ttl_ = 1;
- Scheduler::instance().schedule(target_, p, 0.0);
- }
- void
- AODV::recvHello(Packet *p) {
- //struct hdr_ip *ih = HDR_IP(p);
- struct hdr_aodv_reply *rp = HDR_AODV_REPLY(p);
- AODV_Neighbor *nb;
- nb = nb_lookup(rp->rp_dst);
- if(nb == 0) {
- nb_insert(rp->rp_dst);
- }
- else {
- nb->nb_expire = CURRENT_TIME +
- (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
- }
- Packet::free(p);
- }
- void
- AODV::nb_insert(nsaddr_t id) {
- AODV_Neighbor *nb = new AODV_Neighbor(id);
- assert(nb);
- nb->nb_expire = CURRENT_TIME +
- (1.5 * ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
- LIST_INSERT_HEAD(&nbhead, nb, nb_link);
- seqno += 2; // set of neighbors changed
- assert ((seqno%2) == 0);
- }
- AODV_Neighbor*
- AODV::nb_lookup(nsaddr_t id) {
- AODV_Neighbor *nb = nbhead.lh_first;
- for(; nb; nb = nb->nb_link.le_next) {
- if(nb->nb_addr == id) break;
- }
- return nb;
- }
- /*
- * Called when we receive *explicit* notification that a Neighbor
- * is no longer reachable.
- */
- void
- AODV::nb_delete(nsaddr_t id) {
- AODV_Neighbor *nb = nbhead.lh_first;
- log_link_del(id);
- seqno += 2; // Set of neighbors changed
- assert ((seqno%2) == 0);
- for(; nb; nb = nb->nb_link.le_next) {
- if(nb->nb_addr == id) {
- LIST_REMOVE(nb,nb_link);
- delete nb;
- break;
- }
- }
- handle_link_failure(id);
- }
- /*
- * Purges all timed-out Neighbor Entries - runs every
- * HELLO_INTERVAL * 1.5 seconds.
- */
- void
- AODV::nb_purge() {
- AODV_Neighbor *nb = nbhead.lh_first;
- AODV_Neighbor *nbn;
- double now = CURRENT_TIME;
- for(; nb; nb = nbn) {
- nbn = nb->nb_link.le_next;
- if(nb->nb_expire <= now) {
- nb_delete(nb->nb_addr);
- }
- }
- }
这篇关于NS2下AODV协议aodv.cc注释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!