歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

NS2下AODV協議aodv.cc注釋

NS2下AODV協議aodv.cc注釋

//#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);
  }
 }

}

Ubuntu 13.04 安裝NS2.35 http://www.linuxidc.com/Linux/2014-03/98266.htm

Linux平台下NS2.35安裝 http://www.linuxidc.com/Linux/2013-11/93055.htm

NS2.33在Ubuntu 12.10的完整安裝過程及相關問題 http://www.linuxidc.com/Linux/2013-05/84032.htm

NS2.33中安裝Noah協議 http://www.linuxidc.com/Linux/2012-06/63764.htm

NS2使用tcl腳本debug工具tcl-debug-2.0 http://www.linuxidc.com/Linux/2012-06/63761.htm

Copyright © Linux教程網 All Rights Reserved