⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsdv.cc

📁 在Linux下做的QuadTree的程序
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* dsdv.cc   $Id: dsdv.cc,v 1.1.1.1 2000/08/28 18:40:12 jinyang Exp $   */extern "C" {#include <stdarg.h>#include <float.h>};#include "dsdv.h"#include "priqueue.h"#include <random.h>#include <cmu/cmu-trace.h>#define DSDV_STARTUP_JITTER 2.0	// secs to jitter start of periodic activity from				// when start-dsr msg sent to agent#define DSDV_ALMOST_NOW     0.1 // jitter used for events that should be effectively				// instantaneous but are jittered to prevent				// synchronization#define DSDV_BROADCAST_JITTER 0.01 // jitter for all broadcast packets#define DSDV_MIN_TUP_PERIOD 1.0 // minimum time between triggered updates#define IP_DEF_TTL   32 // default TTTL#define TRIGGER_UPDATE_ON_FRESH_SEQNUM/* should the receipt of a fresh (newer) sequence number cause us   to send a triggered update?  If undef'd, we'll only trigger on   routing metric changes */// Returns a random number between 0 and maxstatic inline double jitter (double max, int be_random_){  return (be_random_ ? Random::uniform(max) : 0);}void DSDV_Agent::trace (char *fmt,...){  va_list ap;  if (!tracetarget)    return;  va_start (ap, fmt);  vsprintf (tracetarget->buffer (), fmt, ap);  tracetarget->dump ();  va_end (ap);}void DSDV_Agent::tracepkt (Packet * p, double now, int me, const char *type){  char buf[1024];  unsigned char *walk = p->accessdata ();  int ct = *(walk++);  int seq, dst, met;  snprintf (buf, 1024, "V%s %.5f _%d_ [%d]:", type, now, me, ct);  while (ct--)    {      dst = *(walk++);      met = *(walk++);      seq = *(walk++);      seq = seq << 8 | *(walk++);      seq = seq << 8 | *(walk++);      seq = seq << 8 | *(walk++);      snprintf (buf, 1024, "%s (%d,%d,%d)", buf, dst, met, seq);    }  // Now do trigger handling.  //trace("VTU %.5f %d", now, me);  if (verbose_)    trace ("%s", buf);}// Prints out an rtable element.voidDSDV_Agent::output_rte(const char *prefix, rtable_ent * prte, DSDV_Agent * a){  a->trace("DFU: deimplemented");  printf("DFU: deimplemented");  prte = 0;  prefix = 0;#if 0  printf ("%s%d %d %d %d %f %f %f %f 0x%08x\n",	  prefix, prte->dst, prte->hop, prte->metric, prte->seqnum,	  prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,	  (unsigned int) prte->timeout_event);  a->trace ("VTE %.5f %d %d %d %d %f %f %f %f 0x%08x",          Scheduler::instance ().clock (), prte->dst, prte->hop, prte->metric,	  prte->seqnum, prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,	    prte->timeout_event);#endif}class DSDVTriggerHandler : public Handler {  public:    DSDVTriggerHandler(DSDV_Agent *a_) { a = a_; }    virtual void handle(Event *e);  private:    DSDV_Agent *a;};voidDSDVTriggerHandler::handle(Event *e) // send a triggered update (or a full update if one's needed){  Scheduler & s = Scheduler::instance ();  Time now = s.clock ();  rtable_ent *prte;  int update_type;	 // we want periodic (=1) or triggered (=0) update?  Time next_possible = a->lasttup_ + DSDV_MIN_TUP_PERIOD;  for (a->table_->InitLoop(); (prte = a->table_->NextLoop()); )    if (prte->trigger_event == e) break;  assert(prte && prte->trigger_event == e);  if (now < next_possible)    {      s.schedule(a->trigger_handler, e, next_possible - now);      a->cancelTriggersBefore(next_possible);      return;    }  update_type = 0;  Packet * p = a->makeUpdate(/*in-out*/update_type);        if (p != NULL)     {	        if (update_type == 1)	{ // we got a periodic update, though we only asked for triggered	  // cancel and reschedule periodic update	  s.cancel(a->periodic_callback_);	  s.schedule (a->helper_, a->periodic_callback_, 		      a->perup_ * (0.75 + jitter (0.25, a->be_random_)));	  if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "PU");	  	}      else	{	  if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "TU");	  	}      assert (!HDR_CMN (p)->xmit_failure_);	// DEBUG 0x2	        s.schedule (a->target_, p, jitter(DSDV_BROADCAST_JITTER, a->be_random_));            a->lasttup_ = now; // even if we got a full update, it still counts      // for our last triggered update time    }    // free this event  for (a->table_->InitLoop (); (prte = a->table_->NextLoop ());)    if (prte->trigger_event && prte->trigger_event == e)      {	prte->trigger_event = 0;	delete e;      }}voidDSDV_Agent::cancelTriggersBefore(Time t)  // Cancel any triggered events scheduled to take place *before* time  // t (exclusive){  struct rtable_ent *prte;  Scheduler & s = Scheduler::instance ();  for (table_->InitLoop (); (prte = table_->NextLoop ());)    if (prte->trigger_event && prte->trigger_event->time_ < t)      {	s.cancel(prte->trigger_event);	delete prte->trigger_event;	prte->trigger_event = 0;      }}voidDSDV_Agent::needTriggeredUpdate(rtable_ent *prte, Time t)  // if no triggered update already pending, make one so{  Scheduler & s = Scheduler::instance();  Time now = Scheduler::instance().clock();  assert(t >= now);  if (prte->trigger_event)     s.cancel(prte->trigger_event);  else    prte->trigger_event = new Event;  s.schedule(trigger_handler, prte->trigger_event, t - now);}voidDSDV_Agent::helper_callback (Event * e){  Scheduler & s = Scheduler::instance ();  double now = s.clock ();  rtable_ent *prte;  rtable_ent *pr2;  int update_type;	 // we want periodic (=1) or triggered (=0) update?  //printf("Triggered handler on 0x%08x\n", e);  // Check for periodic callback  if (periodic_callback_ && e == periodic_callback_)    {      update_type = 1;      Packet *p = makeUpdate(/*in-out*/update_type);      if (verbose_)	{	  trace ("VPC %.5f _%d_", now, myaddr_);	  tracepkt (p, now, myaddr_, "PU");	}      assert (!HDR_CMN (p)->xmit_failure_);	// DEBUG 0x2      // send out update packet jitter to avoid sync      s.schedule (target_, p, jitter(DSDV_BROADCAST_JITTER, be_random_));      // put the periodic update sending callback back onto the       // the scheduler queue for next time....      s.schedule (helper_, periodic_callback_, 		  perup_ * (0.75 + jitter (0.25, be_random_)));      // this will take the place of any planned triggered updates      lasttup_ = now;      return;    }  // Check for timeout  // If it was a timeout, fix the routing table.  for (table_->InitLoop (); (prte = table_->NextLoop ());)    if (prte->timeout_event && (prte->timeout_event == e))      break;  // If it was a timeout, prte will be non-NULL  // Note that in the if we don't touch the changed_at time, so that when  // wst is computed, it doesn't consider the infinte metric the best  // one at that sequence number.  if (prte)    {      if (verbose_)	{	  trace ("VTO %.5f _%d_ %d->%d", now, myaddr_, myaddr_, prte->dst);	  /*	  trace ("VTO %.5f _%d_ trg_sch %x on sched %x time %f", now, myaddr_, 		 trigupd_scheduled, 		 trigupd_scheduled ? s.lookup(trigupd_scheduled->uid_) : 0,		 trigupd_scheduled ? trigupd_scheduled->time_ : 0); */	}            for (table_->InitLoop (); (pr2 = table_->NextLoop ()); )	{	  if (pr2->hop == prte->dst && pr2->metric != BIG)	    {	      if (verbose_)		trace ("VTO %.5f _%d_ marking %d", now, myaddr_, pr2->dst);	      pr2->metric = BIG;	      pr2->advertise_ok_at = now;	      pr2->advert_metric = true;	      pr2->advert_seqnum = true;	      pr2->seqnum++;	      // And we have routing info to propogate.	      needTriggeredUpdate(pr2, now);	    }	}      // OK the timeout expired, so we'll free it. No dangling pointers.      prte->timeout_event = 0;        }  else     { // unknown event on  queue      fprintf(stderr,"DFU: unknown queue event\n");     abort();    }  if (e)    delete e;}voidDSDV_Agent::lost_link (Packet *p){  hdr_cmn *hdrc = HDR_CMN (p);  rtable_ent *prte = table_->GetEntry (hdrc->next_hop_);  if(use_mac_ == 0) {          drop(p, DROP_RTR_MAC_CALLBACK);          return;  }  if (verbose_ && hdrc->addr_type_ == AF_INET)    trace ("VLL %.8f %d->%d lost at %d",	   Scheduler::instance ().clock (),	   ((hdr_ip *) p->access (off_ip_))->src_,	   ((hdr_ip *) p->access (off_ip_))->dst_,	   myaddr_);  if (!use_mac_ || !prte || hdrc->addr_type_ != AF_INET)    return;  if (verbose_)    trace ("VLP %.5f %d:%d->%d:%d lost at %d [hop %d]",  Scheduler::instance ().clock (),	   ((hdr_ip *) p->access (off_ip_))->src_,	   ((hdr_ip *) p->access (off_ip_))->sport_,	   ((hdr_ip *) p->access (off_ip_))->dst_,	   ((hdr_ip *) p->access (off_ip_))->dport_,	   myaddr_, prte->dst);  if (prte->timeout_event)    {      Scheduler::instance ().cancel (prte->timeout_event);      helper_callback (prte->timeout_event);    }  else if (prte->metric != BIG)    {      assert(prte->timeout_event == 0);      prte->timeout_event = new Event ();      helper_callback (prte->timeout_event);    }  // Queue these packets up...  recv(p, 0);#if 0  while (p2 = ((PriQueue *) target_)->filter (prte->dst))    {      if (verbose_)      trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),	       ((hdr_ip *) p2->access (off_ip_))->src_,	       ((hdr_ip *) p2->access (off_ip_))->sport_,	       ((hdr_ip *) p2->access (off_ip_))->dst_,	       ((hdr_ip *) p2->access (off_ip_))->dport_, myaddr_);      recv(p2, 0);    }  while (p2 = ll_queue->filter (prte->dst))    {      if (verbose_)      trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),	       ((hdr_ip *) p2->access (off_ip_))->src_,	       ((hdr_ip *) p2->access (off_ip_))->sport_,	       ((hdr_ip *) p2->access (off_ip_))->dst_,	       ((hdr_ip *) p2->access (off_ip_))->dport_, myaddr_);      recv (p2, 0);    }#endif}static void mac_callback (Packet * p, void *arg){  ((DSDV_Agent *) arg)->lost_link (p);}Packet *DSDV_Agent::makeUpdate(int& periodic)    // return a packet advertising the state in the routing table    // makes a full ``periodic'' update if requested, or a ``triggered''    // partial update if there are only a few changes and full update otherwise    // returns with periodic = 1 if full update returned, or = 0 if partial  //   update returned{  Packet *p = allocpkt ();  hdr_ip *iph = (hdr_ip *) p->access (off_ip_);  hdr_cmn *hdrc = HDR_CMN (p);  double now = Scheduler::instance ().clock ();  rtable_ent *prte;  unsigned char *walk;  int change_count;             // count of entries to go in this update  int rtbl_sz;			// counts total entries in rt table  int unadvertiseable;		// number of routes we can't advertise yet  //printf("Update packet from %d [per=%d]\n", myaddr_, periodic);  // The packet we send wants to be broadcast  hdrc->next_hop_ = IP_BROADCAST;  hdrc->addr_type_ = AF_INET;  iph->dst_ = IP_BROADCAST;  iph->dport_ = ROUTER_PORT;  change_count = 0;  rtbl_sz = 0;  unadvertiseable = 0;  for (table_->InitLoop ();        (prte = table_->NextLoop ()); )    {      rtbl_sz++;      if ((prte->advert_seqnum || prte->advert_metric) 	  && prte->advertise_ok_at <= now) 	change_count++;      if (prte->advertise_ok_at > now) unadvertiseable++;    }  if (change_count * 3 > rtbl_sz && change_count > 3)    { // much of the table has changed, just do a periodic update now      periodic = 1;    }  // Periodic update... increment the sequence number...  if (periodic)    {      change_count = rtbl_sz - unadvertiseable;      assert(change_count >= 1);       /* should always be an advertiseable route for ourselves in the 	 table */#if 0      trace("DAM %.5f _%d_ sz %d cc %d unat %d", 	    now, myaddr_, rtbl_sz, change_count, unadvertiseable);#endif       rtable_ent rte;      bzero(&rte, sizeof(rte));      /* inc sequence number on any periodic update, even if we started	 off wanting to do a triggered update, b/c we're doing a real	 live periodic update now that'll take the place of our next	 periodic update */      seqno_ += 2;      rte.dst = myaddr_;      rte.hop = iph->src_;      rte.metric = 0;      rte.seqnum = seqno_;      rte.advertise_ok_at = 0.0; // can always advert ourselves      rte.advert_seqnum = true;  // always include ourselves in Triggered Upds      rte.changed_at = now;      rte.new_seqnum_at = now;      rte.wst = 0;      rte.timeout_event = 0;		// Don't time out our localhost :)      rte.q = 0;		// Don't buffer pkts for self!      /* this add isn't going to increase the size of the table, since	 a route for ourselves was inserted at startup, but serves	 to refresh all the variables in the table to values set above */      table_->AddEntry (rte);    }  if (change_count == 0)     {      Packet::free(p); // allocated by us, no drop needed      return NULL; // nothing to advertise    }  /* ****** make the update packet.... ***********     with less than 100+ nodes, an update for all nodes is less than the     MTU, so don't bother worrying about splitting the update over     multiple packets -dam 4/26/98 */  assert(rtbl_sz <= (1500 / 12));  p->allocdata ((change_count * 6) + 1);  walk = p->accessdata ();  *(walk++) = change_count;  hdrc->size_ = change_count * 12 + IP_HDR_LEN;	// DSDV + IP#if 0   int jjj = 0;#endif   for (table_->InitLoop (); (prte = table_->NextLoop ());)    {#if 0      jjj++;      trace("DAM %.5f _%d_ jjj %d cc %d -dst %d ok at %f", 	    now, myaddr_, jjj, change_count, prte->dst, 	    prte->advertise_ok_at );#endif      if (periodic && prte->advertise_ok_at > now)	{ // don't send out routes that shouldn't be advertised	  // even in periodic updates	  continue;	}      if (periodic || 	  ((prte->advert_seqnum || prte->advert_metric) 	   && prte->advertise_ok_at <= now))	{ // include this rte in the advert	  if (!periodic && verbose_)	    trace ("VCT %.5f _%d_ %d", now, myaddr_, prte->dst);	  assert (prte->dst < 256 && prte->metric < 256);	  *(walk++) = prte->dst;	  *(walk++) = prte->metric;	  *(walk++) = (prte->seqnum) >> 24;	  *(walk++) = ((prte->seqnum) >> 16) & 0xFF;	  *(walk++) = ((prte->seqnum) >> 8) & 0xFF;	  *(walk++) = (prte->seqnum) & 0xFF;	  prte->last_advertised_metric = prte->metric;	  // seqnum's only need to be advertised once after they change	  prte->advert_seqnum = false; // don't need to advert seqnum again	  if (periodic) 	    { // a full advert means we don't have to re-advert either 	      // metrics or seqnums again until they change	      prte->advert_seqnum = false;	      prte->advert_metric = false;	    }	  change_count--;	}    }    assert(change_count == 0);  return p;}voidDSDV_Agent::updateRoute(struct rtable_ent *old_rte, 			struct rtable_ent *new_rte){  assert(new_rte);  Time now = Scheduler::instance().clock();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -