dsdv.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:34k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * Ported from CMU/Monarch's code, nov'98 -Padma.
  35.  *
  36.  * $Header: /cvsroot/nsnam/ns-2/dsdv/dsdv.cc,v 1.26 2006/02/21 15:20:18 mahrenho Exp $
  37.  */
  38. extern "C" {
  39. #include <stdarg.h>
  40. #include <float.h>
  41. }
  42. #include "dsdv.h"
  43. #include "priqueue.h"
  44. #include <random.h>
  45. #include <cmu-trace.h>
  46. #include <address.h>
  47. #include <mobilenode.h>
  48. #define DSDV_STARTUP_JITTER 2.0 // secs to jitter start of periodic activity from
  49. // when start-dsr msg sent to agent
  50. #define DSDV_ALMOST_NOW     0.1 // jitter used for events that should be effectively
  51. // instantaneous but are jittered to prevent
  52. // synchronization
  53. #define DSDV_BROADCAST_JITTER 0.01 // jitter for all broadcast packets
  54. #define DSDV_MIN_TUP_PERIOD 1.0 // minimum time between triggered updates
  55. #define IP_DEF_TTL   32 // default TTTL
  56. #undef TRIGGER_UPDATE_ON_FRESH_SEQNUM
  57. //#define TRIGGER_UPDATE_ON_FRESH_SEQNUM
  58. /* should the receipt of a fresh (newer) sequence number cause us
  59.    to send a triggered update?  If undef'd, we'll only trigger on
  60.    routing metric changes */
  61. // Returns a random number between 0 and max
  62. static inline double 
  63. jitter (double max, int be_random_)
  64. {
  65.   return (be_random_ ? Random::uniform(max) : 0);
  66. }
  67. void DSDV_Agent::
  68. trace (char *fmt,...)
  69. {
  70.   va_list ap;
  71.   if (!tracetarget)
  72.     return;
  73.   va_start (ap, fmt);
  74.   vsprintf (tracetarget->pt_->buffer (), fmt, ap);
  75.   tracetarget->pt_->dump ();
  76.   va_end (ap);
  77. }
  78. void 
  79. DSDV_Agent::tracepkt (Packet * p, double now, int me, const char *type)
  80. {
  81.   char buf[1024];
  82.   unsigned char *walk = p->accessdata ();
  83.   int ct = *(walk++);
  84.   int seq, dst, met;
  85.   snprintf (buf, 1024, "V%s %.5f _%d_ [%d]:", type, now, me, ct);
  86.   while (ct--)
  87.     {
  88.       dst = *(walk++);
  89.       dst = dst << 8 | *(walk++);
  90.       dst = dst << 8 | *(walk++);
  91.       dst = dst << 8 | *(walk++);
  92.       met = *(walk++);
  93.       seq = *(walk++);
  94.       seq = seq << 8 | *(walk++);
  95.       seq = seq << 8 | *(walk++);
  96.       seq = seq << 8 | *(walk++);
  97.       snprintf (buf, 1024, "%s (%d,%d,%d)", buf, dst, met, seq);
  98.     }
  99.   // Now do trigger handling.
  100.   //trace("VTU %.5f %d", now, me);
  101.   if (verbose_)
  102.     trace ("%s", buf);
  103. }
  104. // Prints out an rtable element.
  105. void
  106. DSDV_Agent::output_rte(const char *prefix, rtable_ent * prte, DSDV_Agent * a)
  107. {
  108.   a->trace("DFU: deimplemented");
  109.   printf("DFU: deimplemented");
  110.   prte = 0;
  111.   prefix = 0;
  112. #if 0
  113.   printf ("%s%d %d %d %d %f %f %f %f 0x%08xn",
  114.   prefix, prte->dst, prte->hop, prte->metric, prte->seqnum,
  115.   prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,
  116.   (unsigned int) prte->timeout_event);
  117.   a->trace ("VTE %.5f %d %d %d %d %f %f %f %f 0x%08x",
  118.           Scheduler::instance ().clock (), prte->dst, prte->hop, prte->metric,
  119.   prte->seqnum, prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,
  120.     prte->timeout_event);
  121. #endif
  122. }
  123. class DSDVTriggerHandler : public Handler {
  124.   public:
  125.     DSDVTriggerHandler(DSDV_Agent *a_) { a = a_; }
  126.     virtual void handle(Event *e);
  127.   private:
  128.     DSDV_Agent *a;
  129. };
  130. void
  131. DSDVTriggerHandler::handle(Event *e)
  132.  // send a triggered update (or a full update if one's needed)
  133. {
  134. //DEBUG
  135. //printf("(%d)-->triggered update with e=%xn", a->myaddr_,e); 
  136.   Scheduler & s = Scheduler::instance ();
  137.   Time now = s.clock ();
  138.   rtable_ent *prte;
  139.   int update_type;  // we want periodic (=1) or triggered (=0) update?
  140.   Time next_possible = a->lasttup_ + DSDV_MIN_TUP_PERIOD;
  141.   for (a->table_->InitLoop(); (prte = a->table_->NextLoop());)
  142.   if (prte->trigger_event == e) break;
  143.   assert(prte && prte->trigger_event == e);
  144.   if (now < next_possible)
  145.     {
  146.     //DEBUG
  147.     //printf("(%d)..Re-scheduling triggered updaten",a->myaddr_);
  148.       s.schedule(a->trigger_handler, e, next_possible - now);
  149.       a->cancelTriggersBefore(next_possible);
  150.       return;
  151.     }
  152.   update_type = 0;
  153.   Packet * p = a->makeUpdate(/*in-out*/update_type);
  154.       
  155.   if (p != NULL) 
  156.     {   
  157.       if (update_type == 1)
  158. { // we got a periodic update, though we only asked for triggered
  159.   // cancel and reschedule periodic update
  160.   s.cancel(a->periodic_callback_);
  161.   //DEBUG
  162.   //printf("we got a periodic update, though asked for triggn");
  163.   s.schedule (a->helper_, a->periodic_callback_, 
  164.       a->perup_ * (0.75 + jitter (0.25, a->be_random_)));
  165.   if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "PU");   
  166. }
  167.       else
  168. {
  169.   if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "TU");   
  170. }
  171.       assert (!HDR_CMN (p)->xmit_failure_); // DEBUG 0x2   
  172.       s.schedule (a->target_, p, jitter(DSDV_BROADCAST_JITTER, a->be_random_));
  173.       
  174.       a->lasttup_ = now; // even if we got a full update, it still counts
  175.       // for our last triggered update time
  176.     }
  177.   
  178.   // free this event
  179.   for (a->table_->InitLoop (); (prte = a->table_->NextLoop ());)
  180.     if (prte->trigger_event && prte->trigger_event == e)
  181.       {
  182. prte->trigger_event = 0;
  183. delete e;
  184.       }
  185. }
  186. void
  187. DSDV_Agent::cancelTriggersBefore(Time t)
  188.   // Cancel any triggered events scheduled to take place *before* time
  189.   // t (exclusive)
  190. {
  191.   rtable_ent *prte;
  192.   Scheduler & s = Scheduler::instance ();
  193.   for (table_->InitLoop (); (prte = table_->NextLoop ());)
  194.     if (prte->trigger_event && prte->trigger_event->time_ < t)
  195.       {
  196.       //DEBUG
  197.       //printf("(%d) cancel event %xn",myaddr_,prte->trigger_event);
  198. s.cancel(prte->trigger_event);
  199. delete prte->trigger_event;
  200. prte->trigger_event = 0;
  201.       }
  202. }
  203. void
  204. DSDV_Agent::needTriggeredUpdate(rtable_ent *prte, Time t)
  205.   // if no triggered update already pending, make one so
  206. {
  207.   Scheduler & s = Scheduler::instance();
  208.   Time now = Scheduler::instance().clock();
  209.   assert(t >= now);
  210.   if (prte->trigger_event) 
  211.     s.cancel(prte->trigger_event);
  212.   else
  213.     prte->trigger_event = new Event;
  214.   //DEBUG
  215.   //printf("(%d)..scheduling trigger-update with event %xn",myaddr_,prte->trigger_event);
  216.   s.schedule(trigger_handler, prte->trigger_event, t - now);
  217. }
  218. void
  219. DSDV_Agent::helper_callback (Event * e)
  220. {
  221.   Scheduler & s = Scheduler::instance ();
  222.   double now = s.clock ();
  223.   rtable_ent *prte;
  224.   rtable_ent *pr2;
  225.   int update_type;  // we want periodic (=1) or triggered (=0) update?
  226.   //DEBUG
  227.   //printf("Triggered handler on 0x%08xn", e);
  228.   // Check for periodic callback
  229.   if (periodic_callback_ && e == periodic_callback_)
  230.     {
  231.       update_type = 1;
  232.       Packet *p = makeUpdate(/*in-out*/update_type);
  233.       if (verbose_)
  234. {
  235.   trace ("VPC %.5f _%d_", now, myaddr_);
  236.   tracepkt (p, now, myaddr_, "PU");
  237. }
  238.       
  239.       if (p) {
  240.       assert (!HDR_CMN (p)->xmit_failure_); // DEBUG 0x2
  241.       // send out update packet jitter to avoid sync
  242.       //DEBUG
  243.       //printf("(%d)..sendout update pkt (periodic=%d)n",myaddr_,update_type);
  244.       s.schedule (target_, p, jitter(DSDV_BROADCAST_JITTER, be_random_));
  245.       }
  246.       
  247.       // put the periodic update sending callback back onto the 
  248.       // the scheduler queue for next time....
  249.       s.schedule (helper_, periodic_callback_, 
  250.   perup_ * (0.75 + jitter (0.25, be_random_)));
  251.       // this will take the place of any planned triggered updates
  252.       lasttup_ = now;
  253.       return;
  254.     }
  255.   // Check for timeout
  256.   // If it was a timeout, fix the routing table.
  257.   for (table_->InitLoop (); (prte = table_->NextLoop ());)
  258.     if (prte->timeout_event && (prte->timeout_event == e))
  259.       break;
  260.   // If it was a timeout, prte will be non-NULL
  261.   // Note that in the if we don't touch the changed_at time, so that when
  262.   // wst is computed, it doesn't consider the infinte metric the best
  263.   // one at that sequence number.
  264.   if (prte)
  265.   {
  266.       if (verbose_)
  267. {
  268.   trace ("VTO %.5f _%d_ %d->%d", now, myaddr_, myaddr_, prte->dst);
  269.   /*   trace ("VTO %.5f _%d_ trg_sch %x on sched %x time %f", now, myaddr_, 
  270.  trigupd_scheduled, 
  271.  trigupd_scheduled ? s.lookup(trigupd_scheduled->uid_) : 0,
  272.  trigupd_scheduled ? trigupd_scheduled->time_ : 0); */
  273. }
  274.       
  275.       for (table_->InitLoop (); (pr2 = table_->NextLoop ()); )
  276. {
  277.   if (pr2->hop == prte->dst && pr2->metric != BIG)
  278.     {
  279.       if (verbose_)
  280. trace ("VTO %.5f _%d_ marking %d", now, myaddr_, pr2->dst);
  281.       pr2->metric = BIG;
  282.       pr2->advertise_ok_at = now;
  283.       pr2->advert_metric = true;
  284.       pr2->advert_seqnum = true;
  285.       pr2->seqnum++;
  286.       // And we have routing info to propogate.
  287.       //DEBUG
  288.       //printf("(%d)..we have routing info to propagate..trigger update for dst %dn",myaddr_,pr2->dst);
  289.       needTriggeredUpdate(pr2, now);
  290.     }
  291. }
  292.       // OK the timeout expired, so we'll free it. No dangling pointers.
  293.       prte->timeout_event = 0;    
  294.     }
  295.   else 
  296.     { // unknown event on  queue
  297.       fprintf(stderr,"DFU: unknown queue eventn");
  298.      abort();
  299.     }
  300.   if (e)
  301.     delete e;
  302. }
  303. void
  304. DSDV_Agent::lost_link (Packet *p)
  305. {
  306.   hdr_cmn *hdrc = HDR_CMN (p);
  307.   rtable_ent *prte = table_->GetEntry (hdrc->next_hop_);
  308.   if(use_mac_ == 0) {
  309.           drop(p, DROP_RTR_MAC_CALLBACK);
  310.           return;
  311.   }
  312.   //DEBUG
  313.   //printf("(%d)..Lost link..n",myaddr_);
  314.   if (verbose_ && hdrc->addr_type_ == NS_AF_INET)
  315.     trace("VLL %.8f %d->%d lost at %d",
  316.     Scheduler::instance().clock(),
  317.    hdr_ip::access(p)->saddr(), hdr_ip::access(p)->daddr(),
  318.    myaddr_);
  319.   if (!use_mac_ || !prte || hdrc->addr_type_ != NS_AF_INET)
  320.     return;
  321.   if (verbose_)
  322.     trace ("VLP %.5f %d:%d->%d:%d lost at %d [hop %d]",
  323.   Scheduler::instance ().clock (),
  324.    hdr_ip::access (p)->saddr(),
  325.    hdr_ip::access (p)->sport(),
  326.    hdr_ip::access (p)->daddr(),
  327.    hdr_ip::access (p)->dport(),
  328.    myaddr_, prte->dst);
  329.   if (prte->timeout_event)
  330.     {
  331.       Scheduler::instance ().cancel (prte->timeout_event);
  332.       helper_callback (prte->timeout_event);
  333.     }
  334.   else if (prte->metric != BIG)
  335.     {
  336.       assert(prte->timeout_event == 0);
  337.       prte->timeout_event = new Event ();
  338.       helper_callback (prte->timeout_event);
  339.     }
  340.   // Queue these packets up...
  341.   recv(p, 0);
  342. #if 0
  343.   while (p2 = ((PriQueue *) target_)->filter (prte->dst))
  344.     {
  345.       if (verbose_)
  346.       trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),
  347.        hdr_ip::access (p2)->saddr(),
  348.        hdr_ip::access (p2)->sport(),
  349.        hdr_ip::access (p2)->daddr(),
  350.        hdr_ip::access (p2)->dport(), myaddr_);
  351.       recv(p2, 0);
  352.     }
  353.   while (p2 = ll_queue->filter (prte->dst))
  354.     {
  355.       if (verbose_)
  356.       trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),
  357.        hdr_ip::access (p2)->saddr(),
  358.        hdr_ip::access (p2)->sport(),
  359.        hdr_ip::access (p2)->daddr(),
  360.        hdr_ip::access (p2)->dport(), myaddr_);
  361.       recv (p2, 0);
  362.     }
  363. #endif
  364. }
  365. static void 
  366. mac_callback (Packet * p, void *arg)
  367. {
  368.   ((DSDV_Agent *) arg)->lost_link (p);
  369. }
  370. Packet *
  371. DSDV_Agent::makeUpdate(int& periodic)
  372.     // return a packet advertising the state in the routing table
  373.     // makes a full ``periodic'' update if requested, or a ``triggered''
  374.     // partial update if there are only a few changes and full update otherwise
  375.     // returns with periodic = 1 if full update returned, or = 0 if partial
  376.   //   update returned
  377. {
  378. //DEBUG
  379. //printf("(%d)-->Making update pktn",myaddr_);
  380.   Packet *p = allocpkt ();
  381.   hdr_ip *iph = hdr_ip::access(p);
  382.   hdr_cmn *hdrc = HDR_CMN (p);
  383.   double now = Scheduler::instance ().clock ();
  384.   rtable_ent *prte;
  385.   unsigned char *walk;
  386.   int change_count;             // count of entries to go in this update
  387.   int rtbl_sz; // counts total entries in rt table
  388.   int unadvertiseable; // number of routes we can't advertise yet
  389.   //printf("Update packet from %d [per=%d]n", myaddr_, periodic);
  390.   // The packet we send wants to be broadcast
  391.   hdrc->next_hop_ = IP_BROADCAST;
  392.   hdrc->addr_type_ = NS_AF_INET;
  393.   iph->daddr() = IP_BROADCAST << Address::instance().nodeshift();
  394.   iph->dport() = ROUTER_PORT;
  395.   change_count = 0;
  396.   rtbl_sz = 0;
  397.   unadvertiseable = 0;
  398.   for (table_->InitLoop (); 
  399.        (prte = table_->NextLoop ()); )
  400.     {
  401.       rtbl_sz++;
  402.       if ((prte->advert_seqnum || prte->advert_metric) 
  403.   && prte->advertise_ok_at <= now) 
  404. change_count++;
  405.       if (prte->advertise_ok_at > now) unadvertiseable++;
  406.     }
  407.   //printf("change_count = %dn",change_count);
  408.   if (change_count * 3 > rtbl_sz && change_count > 3)
  409.     { // much of the table has changed, just do a periodic update now
  410.       periodic = 1;
  411.     }
  412.   // Periodic update... increment the sequence number...
  413.   if (periodic)
  414.     {
  415.       change_count = rtbl_sz - unadvertiseable;
  416.       //printf("rtbsize-%d, unadvert-%dn",rtbl_sz,unadvertiseable);
  417.       rtable_ent rte;
  418.       bzero(&rte, sizeof(rte));
  419.       /* inc sequence number on any periodic update, even if we started
  420.  off wanting to do a triggered update, b/c we're doing a real
  421.  live periodic update now that'll take the place of our next
  422.  periodic update */
  423.       seqno_ += 2;
  424.       rte.dst = myaddr_;
  425.       //rte.hop = iph->src();
  426.       rte.hop = Address::instance().get_nodeaddr(iph->saddr());
  427.       rte.metric = 0;
  428.       rte.seqnum = seqno_;
  429.       rte.advertise_ok_at = 0.0; // can always advert ourselves
  430.       rte.advert_seqnum = true;  // always include ourselves in Triggered Upds
  431.       rte.changed_at = now;
  432.       rte.new_seqnum_at = now;
  433.       rte.wst = 0;
  434.       rte.timeout_event = 0; // Don't time out our localhost :)
  435.       rte.q = 0; // Don't buffer pkts for self!
  436.       table_->AddEntry (rte);
  437.     }
  438.   if (change_count == 0) 
  439.     {
  440.       Packet::free(p); // allocated by us, no drop needed
  441.       return NULL; // nothing to advertise
  442.     }
  443.   /* ****** make the update packet.... ***********
  444.      with less than 100+ nodes, an update for all nodes is less than the
  445.      MTU, so don't bother worrying about splitting the update over
  446.      multiple packets -dam 4/26/98 */
  447.   //assert(rtbl_sz <= (1500 / 12)); ---how about 100++ node topologies
  448.   p->allocdata((change_count * 9) + 1);
  449.   walk = p->accessdata ();
  450.   *(walk++) = change_count;
  451.   // hdrc->size_ = change_count * 12 + 20; // DSDV + IP
  452.   hdrc->size_ = change_count * 12 + IP_HDR_LEN; // DSDV + IP
  453.   for (table_->InitLoop (); (prte = table_->NextLoop ());)
  454.     {
  455.       if (periodic && prte->advertise_ok_at > now)
  456. { // don't send out routes that shouldn't be advertised
  457.   // even in periodic updates
  458.   continue;
  459. }
  460.       if (periodic || 
  461.   ((prte->advert_seqnum || prte->advert_metric) 
  462.    && prte->advertise_ok_at <= now))
  463. { // include this rte in the advert
  464.   if (!periodic && verbose_)
  465.     trace ("VCT %.5f _%d_ %d", now, myaddr_, prte->dst);
  466.   //assert (prte->dst < 256 && prte->metric < 256);
  467.   //*(walk++) = prte->dst;
  468.   *(walk++) = prte->dst >> 24;
  469.     *(walk++) = (prte->dst >> 16) & 0xFF;
  470.     *(walk++) = (prte->dst >> 8) & 0xFF;
  471.     *(walk++) = (prte->dst >> 0) & 0xFF;
  472.   *(walk++) = prte->metric;
  473.   *(walk++) = (prte->seqnum) >> 24;
  474.   *(walk++) = ((prte->seqnum) >> 16) & 0xFF;
  475.   *(walk++) = ((prte->seqnum) >> 8) & 0xFF;
  476.   *(walk++) = (prte->seqnum) & 0xFF;
  477.   prte->last_advertised_metric = prte->metric;
  478.   // seqnum's only need to be advertised once after they change
  479.   prte->advert_seqnum = false; // don't need to advert seqnum again
  480.   if (periodic) 
  481.     { // a full advert means we don't have to re-advert either 
  482.       // metrics or seqnums again until they change
  483.       prte->advert_seqnum = false;
  484.       prte->advert_metric = false;
  485.     }
  486.   change_count--;
  487. }
  488.     }  
  489.   assert(change_count == 0);
  490.   return p;
  491. }
  492. void
  493. DSDV_Agent::updateRoute(rtable_ent *old_rte, rtable_ent *new_rte)
  494. {
  495.   int negvalue = -1;
  496.   assert(new_rte);
  497.   Time now = Scheduler::instance().clock();
  498.   char buf[1024];
  499.   //  snprintf (buf, 1024, "%c %.5f _%d_ (%d,%d->%d,%d->%d,%d->%d,%lf)",
  500.   snprintf (buf, 1024, "%c %.5f _%d_ (%d,%d->%d,%d->%d,%d->%d,%f)",
  501.     (new_rte->metric != BIG 
  502.      && (!old_rte || old_rte->metric != BIG)) ? 'D' : 'U', 
  503.     now, myaddr_, new_rte->dst, 
  504.     old_rte ? old_rte->metric : negvalue, new_rte->metric, 
  505.     old_rte ? old_rte->seqnum : negvalue,  new_rte->seqnum,
  506.     old_rte ? old_rte->hop : -1,  new_rte->hop, 
  507.     new_rte->advertise_ok_at);
  508.   table_->AddEntry (*new_rte);
  509.   //printf("(%d),Route table updated..n",myaddr_);
  510.   if (trace_wst_)
  511.     trace ("VWST %.12lf frm %d to %d wst %.12lf nxthp %d [of %d]",
  512.    now, myaddr_, new_rte->dst, new_rte->wst, new_rte->hop, 
  513.    new_rte->metric);
  514.   if (verbose_)
  515.     trace ("VS%s", buf);
  516. }
  517. void
  518. DSDV_Agent::processUpdate (Packet * p)
  519. {
  520.   hdr_ip *iph = HDR_IP(p);
  521.   Scheduler & s = Scheduler::instance ();
  522.   double now = s.clock ();
  523.   
  524.   // it's a dsdv packet
  525.   int i;
  526.   unsigned char *d = p->accessdata ();
  527.   unsigned char *w = d + 1;
  528.   rtable_ent rte; // new rte learned from update being processed
  529.   rtable_ent *prte; // ptr to entry *in* routing tbl
  530.   //DEBUG
  531.   //int src, dst;
  532.   //src = Address::instance().get_nodeaddr(iph->src());
  533.   //dst = Address::instance().get_nodeaddr(iph->dst());
  534.   //printf("Received DSDV packet from %d(%d) to %d(%d) [%d)]n", src, iph->sport(), dst, iph->dport(), myaddr_);
  535.   for (i = *d; i > 0; i--)
  536.     {
  537.       bool trigger_update = false;  // do we need to do a triggered update?
  538.       nsaddr_t dst;
  539.       prte = NULL;
  540.       dst = *(w++);
  541.       dst = dst << 8 | *(w++);
  542.       dst = dst << 8 | *(w++);
  543.       dst = dst << 8 | *(w++);
  544.       if ((prte = table_->GetEntry (dst)))
  545. {
  546.   bcopy(prte, &rte, sizeof(rte));
  547. }
  548.       else
  549. {
  550.   bzero(&rte, sizeof(rte));
  551. }
  552.       rte.dst = dst;
  553.       //rte.hop = iph->src();
  554.       rte.hop = Address::instance().get_nodeaddr(iph->saddr());
  555.       rte.metric = *(w++);
  556.       rte.seqnum = *(w++);
  557.       rte.seqnum = rte.seqnum << 8 | *(w++);
  558.       rte.seqnum = rte.seqnum << 8 | *(w++);
  559.       rte.seqnum = rte.seqnum << 8 | *(w++);
  560.       rte.changed_at = now;
  561.       if (rte.metric != BIG) rte.metric += 1;
  562.       if (rte.dst == myaddr_)
  563. {
  564.   if (rte.metric == BIG && periodic_callback_)
  565.     {
  566.       // You have the last word on yourself...
  567.       // Tell the world right now that I'm still here....
  568.       // This is a CMU Monarch optimiziation to fix the 
  569.       // the problem of other nodes telling you and your neighbors
  570.       // that you don't exist described in the paper.
  571.       s.cancel (periodic_callback_);
  572.       s.schedule (helper_, periodic_callback_, 0);
  573.     }
  574.   continue; // don't corrupt your own routing table.
  575. }
  576.       /**********  fill in meta data for new route ***********/
  577.       // If it's in the table, make it the same timeout and queue.
  578.       if (prte)
  579. { // we already have a route to this dst
  580.   if (prte->seqnum == rte.seqnum)
  581.     { // we've got an update with out a new squenece number
  582.       // this update must have come along a different path
  583.       // than the previous one, and is just the kind of thing
  584.       // the weighted settling time is supposed to track.
  585.       // this code is now a no-op left here for clarity -dam XXX
  586.       rte.wst = prte->wst;
  587.       rte.new_seqnum_at = prte->new_seqnum_at;
  588.     }
  589.   else 
  590.     { // we've got a new seq number, end the measurement period
  591.       // for wst over the course of the old sequence number
  592.       // and update wst with the difference between the last
  593.       // time we changed the route (which would be when the 
  594.       // best route metric arrives) and the first time we heard
  595.       // the sequence number that started the measurement period
  596.       // do we care if we've missed a sequence number, such
  597.       // that we have a wst measurement period that streches over
  598.       // more than a single sequence number??? XXX -dam 4/20/98
  599.       rte.wst = alpha_ * prte->wst + 
  600. (1.0 - alpha_) * (prte->changed_at - prte->new_seqnum_at);
  601.       rte.new_seqnum_at = now;
  602.     }
  603. }
  604.       else
  605. { // inititallize the wst for the new route
  606.   rte.wst = wst0_;
  607.   rte.new_seqnum_at = now;
  608. }
  609.   
  610.       // Now that we know the wst_, we know when to update...
  611.       if (rte.metric != BIG && (!prte || prte->metric != BIG))
  612. rte.advertise_ok_at = now + (rte.wst * 2);
  613.       else
  614. rte.advertise_ok_at = now;
  615.       /*********** decide whether to update our routing table *********/
  616.       if (!prte)
  617. { // we've heard from a brand new destination
  618.   if (rte.metric < BIG) 
  619.     {
  620.       rte.advert_metric = true;
  621.       trigger_update = true;
  622.     }
  623.   updateRoute(prte,&rte);
  624. }
  625.       else if ( prte->seqnum == rte.seqnum )
  626. { // stnd dist vector case
  627.   if (rte.metric < prte->metric) 
  628.     { // a shorter route!
  629.       if (rte.metric == prte->last_advertised_metric)
  630. { // we've just gone back to a metric we've already advertised
  631.   rte.advert_metric = false;
  632.   trigger_update = false;
  633. }
  634.       else
  635. { // we're changing away from the last metric we announced
  636.   rte.advert_metric = true;
  637.   trigger_update = true;
  638. }
  639.       updateRoute(prte,&rte);
  640.     }
  641.   else
  642.     { // ignore the longer route
  643.     }
  644. }
  645.       else if ( prte->seqnum < rte.seqnum )
  646. { // we've heard a fresher sequence number
  647.   // we *must* believe its rt metric
  648.   rte.advert_seqnum = true; // we've got a new seqnum to advert
  649.   if (rte.metric == prte->last_advertised_metric)
  650.     { // we've just gone back to our old metric
  651.       rte.advert_metric = false;
  652.     }
  653.   else
  654.     { // we're using a metric different from our last advert
  655.       rte.advert_metric = true;
  656.     }
  657.   updateRoute(prte,&rte);
  658. #ifdef TRIGGER_UPDATE_ON_FRESH_SEQNUM
  659.   trigger_update = true;
  660. #else
  661.   trigger_update = false;
  662. #endif
  663. }
  664.       else if ( prte->seqnum > rte.seqnum )
  665. { // our neighbor has older sequnum info than we do
  666.   if (rte.metric == BIG && prte->metric != BIG)
  667.     { // we must go forth and educate this ignorant fellow
  668.       // about our more glorious and happy metric
  669.       prte->advertise_ok_at = now;
  670.       prte->advert_metric = true;
  671.       // directly schedule a triggered update now for 
  672.       // prte, since the other logic only works with rte.*
  673.       needTriggeredUpdate(prte,now);
  674.     }
  675.   else
  676.     { // we don't care about their stale info
  677.     }
  678. }
  679.       else
  680. {
  681.   fprintf(stderr,
  682.   "%s DFU: unhandled adding a route entry?n", __FILE__);
  683.   abort();
  684. }
  685.       
  686.       if (trigger_update)
  687. {
  688.   prte = table_->GetEntry (rte.dst);
  689.   assert(prte != NULL && prte->advertise_ok_at == rte.advertise_ok_at);
  690.   needTriggeredUpdate(prte, prte->advertise_ok_at);
  691. }
  692.       // see if we can send off any packets we've got queued
  693.       if (rte.q && rte.metric != BIG)
  694. {
  695.   Packet *queued_p;
  696.   while ((queued_p = rte.q->deque()))
  697.   // XXX possible loop here  
  698.   // while ((queued_p = rte.q->deque()))
  699.   // Only retry once to avoid looping
  700.   // for (int jj = 0; jj < rte.q->length(); jj++){
  701.   //  queued_p = rte.q->deque();
  702.     recv(queued_p, 0); // give the packets to ourselves to forward
  703.   // }
  704.   delete rte.q;
  705.   rte.q = 0;
  706.   table_->AddEntry(rte); // record the now zero'd queue
  707. }
  708.     } // end of all destination mentioned in routing update packet
  709.   // Reschedule the timeout for this neighbor
  710.   prte = table_->GetEntry(Address::instance().get_nodeaddr(iph->saddr()));
  711.   if (prte)
  712.     {
  713.       if (prte->timeout_event)
  714. s.cancel (prte->timeout_event);
  715.       else
  716. {
  717.   prte->timeout_event = new Event ();
  718. }
  719.       
  720.       s.schedule (helper_, prte->timeout_event, min_update_periods_ * perup_);
  721.     }
  722.   else
  723.     { // If the first thing we hear from a node is a triggered update
  724.       // that doesn't list the node sending the update as the first
  725.       // thing in the packet (which is disrecommended by the paper)
  726.       // we won't have a route to that node already.  In order to timeout
  727.       // the routes we just learned, we need a harmless route to keep the
  728.       // timeout metadata straight.
  729.       
  730.       // Hi there, nice to meet you. I'll make a fake advertisement
  731.       bzero(&rte, sizeof(rte));
  732.       rte.dst = Address::instance().get_nodeaddr(iph->saddr());
  733.       rte.hop = Address::instance().get_nodeaddr(iph->saddr());
  734.       rte.metric = 1;
  735.       rte.seqnum = 0;
  736.       rte.advertise_ok_at = now + 604800; // check back next week... :)
  737.       
  738.       rte.changed_at = now;
  739.       rte.new_seqnum_at = now;
  740.       rte.wst = wst0_;
  741.       rte.timeout_event = new Event ();
  742.       rte.q = 0;
  743.       
  744.       updateRoute(NULL, &rte);
  745.       s.schedule(helper_, rte.timeout_event, min_update_periods_ * perup_);
  746.     }
  747.   
  748.   /*
  749.    * Freeing a routing layer packet --> don't need to
  750.    * call drop here.
  751.    */
  752.   Packet::free (p);
  753. }
  754. int 
  755. DSDV_Agent::diff_subnet(int dst) 
  756. {
  757. char* dstnet = Address::instance().get_subnetaddr(dst);
  758. if (subnet_ != NULL) {
  759. if (dstnet != NULL) {
  760. if (strcmp(dstnet, subnet_) != 0) {
  761. delete [] dstnet;
  762. return 1;
  763. }
  764. delete [] dstnet;
  765. }
  766. }
  767. //assert(dstnet == NULL);
  768. return 0;
  769. }
  770. void
  771. DSDV_Agent::forwardPacket (Packet * p)
  772. {
  773.   hdr_ip *iph = HDR_IP(p);
  774.   Scheduler & s = Scheduler::instance ();
  775.   double now = s.clock ();
  776.   hdr_cmn *hdrc = HDR_CMN (p);
  777.   int dst;
  778.   rtable_ent *prte;
  779.   
  780.   // We should route it.
  781.   //printf("(%d)-->forwardig pktn",myaddr_);
  782.   // set direction of pkt to -1 , i.e downward
  783.   hdrc->direction() = hdr_cmn::DOWN;
  784.   // if the destination is outside mobilenode's domain
  785.   // forward it to base_stn node
  786.   // Note: pkt is not buffered if route to base_stn is unknown
  787.   dst = Address::instance().get_nodeaddr(iph->daddr());  
  788.   if (diff_subnet(iph->daddr())) {
  789.    prte = table_->GetEntry (dst);
  790.   if (prte && prte->metric != BIG) 
  791.   goto send;
  792.   
  793.   //int dst = (node_->base_stn())->address();
  794.   dst = node_->base_stn();
  795.   prte = table_->GetEntry (dst);
  796.   if (prte && prte->metric != BIG) 
  797.   goto send;
  798.   
  799.   else {
  800.   //drop pkt with warning
  801.   fprintf(stderr, "warning: Route to base_stn not known: dropping pktn");
  802.   Packet::free(p);
  803.   return;
  804.   }
  805.   }
  806.   
  807.   prte = table_->GetEntry (dst);
  808.   
  809.   //  trace("VDEBUG-RX %d %d->%d %d %d 0x%08x 0x%08x %d %d", 
  810.   //  myaddr_, iph->src(), iph->dst(), hdrc->next_hop_, hdrc->addr_type_,
  811.   //  hdrc->xmit_failure_, hdrc->xmit_failure_data_,
  812.   //  hdrc->num_forwards_, hdrc->opt_num_forwards);
  813.   if (prte && prte->metric != BIG)
  814.     {
  815.        //printf("(%d)-have route for dstn",myaddr_);
  816.        goto send;
  817.     }
  818.   else if (prte)
  819.     { /* must queue the packet */
  820.     //printf("(%d)-no route, queue pktn",myaddr_);
  821.       if (!prte->q)
  822. {
  823.   prte->q = new PacketQueue ();
  824. }
  825.       prte->q->enque(p);
  826.       if (verbose_)
  827. trace ("VBP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_, iph->saddr(),
  828.        iph->sport(), iph->daddr(), iph->dport());
  829.       while (prte->q->length () > MAX_QUEUE_LENGTH)
  830.       drop (prte->q->deque (), DROP_RTR_QFULL);
  831.       return;
  832.     }
  833.   else
  834.     { // Brand new destination
  835.       rtable_ent rte;
  836.       double now = s.clock();
  837.       
  838.       bzero(&rte, sizeof(rte));
  839.       rte.dst = dst;
  840.       rte.hop = dst;
  841.       rte.metric = BIG;
  842.       rte.seqnum = 0;
  843.       rte.advertise_ok_at = now + 604800; // check back next week... :)
  844.       rte.changed_at = now;
  845.       rte.new_seqnum_at = now; // was now + wst0_, why??? XXX -dam
  846.       rte.wst = wst0_;
  847.       rte.timeout_event = 0;
  848.       rte.q = new PacketQueue();
  849.       rte.q->enque(p);
  850.   
  851.       assert (rte.q->length() == 1 && 1 <= MAX_QUEUE_LENGTH);
  852.       table_->AddEntry(rte);
  853.       
  854.       if (verbose_)
  855.       trace ("VBP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_,
  856.      iph->saddr(), iph->sport(), iph->daddr(), iph->dport());
  857.       return;
  858.     }
  859.  send:
  860.   hdrc->addr_type_ = NS_AF_INET;
  861.   hdrc->xmit_failure_ = mac_callback;
  862.   hdrc->xmit_failure_data_ = this;
  863.   if (prte->metric > 1)
  864.   hdrc->next_hop_ = prte->hop;
  865.   else
  866.   hdrc->next_hop_ = dst;
  867.   if (verbose_)
  868.   trace ("Routing pkts outside domain: 
  869. VFP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_, iph->saddr(),
  870.  iph->sport(), iph->daddr(), iph->dport());  
  871.   assert (!HDR_CMN (p)->xmit_failure_ ||
  872.   HDR_CMN (p)->xmit_failure_ == mac_callback);
  873.   target_->recv(p, (Handler *)0);
  874.   return;
  875.   
  876. }
  877. void 
  878. DSDV_Agent::sendOutBCastPkt(Packet *p)
  879. {
  880.   Scheduler & s = Scheduler::instance ();
  881.   // send out bcast pkt with jitter to avoid sync
  882.   s.schedule (target_, p, jitter(DSDV_BROADCAST_JITTER, be_random_));
  883. }
  884. void
  885. DSDV_Agent::recv (Packet * p, Handler *)
  886. {
  887.   hdr_ip *iph = HDR_IP(p);
  888.   hdr_cmn *cmh = HDR_CMN(p);
  889.   int src = Address::instance().get_nodeaddr(iph->saddr());
  890.   /*
  891.    *  Must be a packet I'm originating...
  892.    */
  893.   if(src == myaddr_ && cmh->num_forwards() == 0) {
  894.     /*
  895.      * Add the IP Header
  896.      */
  897.     cmh->size() += IP_HDR_LEN;    
  898.     iph->ttl_ = IP_DEF_TTL;
  899.   }
  900.   /*
  901.    *  I received a packet that I sent.  Probably
  902.    *  a routing loop.
  903.    */
  904.   else if(src == myaddr_) {
  905.     drop(p, DROP_RTR_ROUTE_LOOP);
  906.     return;
  907.   }
  908.   /*
  909.    *  Packet I'm forwarding...
  910.    */
  911.   else {
  912.     /*
  913.      *  Check the TTL.  If it is zero, then discard.
  914.      */
  915.     if(--iph->ttl_ == 0) {
  916.       drop(p, DROP_RTR_TTL);
  917.       return;
  918.     }
  919.   }
  920.   
  921.   if ((src != myaddr_) && (iph->dport() == ROUTER_PORT))
  922.     {
  923.     // XXX disable this feature for mobileIP where
  924.     // the MH and FA (belonging to diff domains)
  925.     // communicate with each other.
  926.     // Drop pkt if rtg update from some other domain:
  927.     // if (diff_subnet(iph->src())) 
  928.     // drop(p, DROP_OUTSIDE_SUBNET);
  929.     //else    
  930.     processUpdate(p);
  931.     }
  932.   else if (iph->daddr() == ((int)IP_BROADCAST) &&
  933.    (iph->dport() != ROUTER_PORT)) 
  934.   {
  935.      if (src == myaddr_) {
  936.      // handle brdcast pkt
  937.      sendOutBCastPkt(p);
  938.      }
  939.      else {
  940.      // hand it over to the port-demux
  941.     port_dmux_->recv(p, (Handler*)0);
  942.      }
  943.   }
  944.   else 
  945.     {
  946.     forwardPacket(p);
  947.     }
  948. }
  949. static class DSDVClass:public TclClass
  950. {
  951.   public:
  952.   DSDVClass ():TclClass ("Agent/DSDV")
  953.   {
  954.   }
  955.   TclObject *create (int, const char *const *)
  956.   {
  957.     return (new DSDV_Agent ());
  958.   }
  959. } class_dsdv;
  960. DSDV_Agent::DSDV_Agent (): Agent (PT_MESSAGE), ll_queue (0), seqno_ (0), 
  961.   myaddr_ (0), subnet_ (0), node_ (0), port_dmux_(0),
  962.   periodic_callback_ (0), be_random_ (1), 
  963.   use_mac_ (0), verbose_ (1), trace_wst_ (0), lasttup_ (-10), 
  964.   alpha_ (0.875),  wst0_ (6), perup_ (15), 
  965.   min_update_periods_ (3) // constants
  966.  {
  967.   table_ = new RoutingTable ();
  968.   helper_ = new DSDV_Helper (this);
  969.   trigger_handler = new DSDVTriggerHandler(this);
  970.   bind_time ("wst0_", &wst0_);
  971.   bind_time ("perup_", &perup_);
  972.   bind ("use_mac_", &use_mac_);
  973.   bind ("be_random_", &be_random_);
  974.   bind ("alpha_", &alpha_);
  975.   bind ("min_update_periods_", &min_update_periods_);
  976.   bind ("verbose_", &verbose_);
  977.   bind ("trace_wst_", &trace_wst_);
  978.   //DEBUG
  979.   address = 0;
  980.  
  981. }
  982. void
  983. DSDV_Agent::startUp()
  984. {
  985.  Time now = Scheduler::instance().clock();
  986.   subnet_ = Address::instance().get_subnetaddr(myaddr_);
  987.   //DEBUG
  988.   address = Address::instance().print_nodeaddr(myaddr_);
  989.   //printf("myaddress: %d -> %sn",myaddr_,address);
  990.   
  991.   rtable_ent rte;
  992.   bzero(&rte, sizeof(rte));
  993.   rte.dst = myaddr_;
  994.   rte.hop = myaddr_;
  995.   rte.metric = 0;
  996.   rte.seqnum = seqno_;
  997.   seqno_ += 2;
  998.   rte.advertise_ok_at = 0.0; // can always advert ourselves
  999.   rte.advert_seqnum = true;
  1000.   rte.advert_metric = true;
  1001.   rte.changed_at = now;
  1002.   rte.new_seqnum_at = now;
  1003.   rte.wst = 0;
  1004.   rte.timeout_event = 0; // Don't time out our localhost :)
  1005.   
  1006.   rte.q = 0; // Don't buffer pkts for self!
  1007.   
  1008.   table_->AddEntry (rte);
  1009.   // kick off periodic advertisments
  1010.   periodic_callback_ = new Event ();
  1011.   Scheduler::instance ().schedule (helper_, 
  1012.    periodic_callback_,
  1013.    jitter (DSDV_STARTUP_JITTER, be_random_));
  1014. }
  1015. int 
  1016. DSDV_Agent::command (int argc, const char *const *argv)
  1017. {
  1018.   if (argc == 2)
  1019.     {
  1020.       if (strcmp (argv[1], "start-dsdv") == 0)
  1021. {
  1022.   startUp();
  1023.   return (TCL_OK);
  1024. }
  1025.       else if (strcmp (argv[1], "dumprtab") == 0)
  1026. {
  1027.   Packet *p2 = allocpkt ();
  1028.   hdr_ip *iph2 = HDR_IP(p2);
  1029.   rtable_ent *prte;
  1030.   printf ("Table Dump %d[%d]n----------------------------------n",
  1031.   iph2->saddr(), iph2->sport());
  1032. trace ("VTD %.5f %d:%dn", Scheduler::instance ().clock (),
  1033.  iph2->saddr(), iph2->sport());
  1034.   /*
  1035.    * Freeing a routing layer packet --> don't need to
  1036.    * call drop here.
  1037.    */
  1038. Packet::free (p2);
  1039.   for (table_->InitLoop (); (prte = table_->NextLoop ());)
  1040.     output_rte ("t", prte, this);
  1041.   printf ("n");
  1042.   return (TCL_OK);
  1043. }
  1044.       else if (strcasecmp (argv[1], "ll-queue") == 0)
  1045. {
  1046. if (!(ll_queue = (PriQueue *) TclObject::lookup (argv[2])))
  1047.     {
  1048.       fprintf (stderr, "DSDV_Agent: ll-queue lookup of %s failedn", argv[2]);
  1049.       return TCL_ERROR;
  1050.     }
  1051.   return TCL_OK;
  1052. }
  1053.     }
  1054.   else if (argc == 3)
  1055.     {
  1056.       if (strcasecmp (argv[1], "addr") == 0) {
  1057.  int temp;
  1058.  temp = Address::instance().str2addr(argv[2]);
  1059.  myaddr_ = temp;
  1060.  return TCL_OK;
  1061.       }
  1062.       TclObject *obj;
  1063.       if ((obj = TclObject::lookup (argv[2])) == 0)
  1064. {
  1065.   fprintf (stderr, "%s: %s lookup of %s failedn", __FILE__, argv[1],
  1066.    argv[2]);
  1067.   return TCL_ERROR;
  1068. }
  1069.       if (strcasecmp (argv[1], "tracetarget") == 0)
  1070. {
  1071.   
  1072.   tracetarget = (Trace *) obj;
  1073.   return TCL_OK;
  1074. }
  1075.       else if (strcasecmp (argv[1], "node") == 0) {
  1076.       node_ = (MobileNode*) obj;
  1077.       return TCL_OK;
  1078.       }
  1079.       else if (strcasecmp (argv[1], "port-dmux") == 0) {
  1080.       port_dmux_ = (NsObject *) obj;
  1081.       return TCL_OK;
  1082.       }
  1083.     }
  1084.   
  1085.   return (Agent::command (argc, argv));
  1086. }