00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 extern "C" {
00040 #include <stdarg.h>
00041 #include <float.h>
00042 };
00043
00044 #include "dsdv.h"
00045 #include "priqueue.h"
00046
00047 #include <random.h>
00048
00049 #include <cmu-trace.h>
00050 #include <address.h>
00051 #include <mobilenode.h>
00052
00053
00054 #define DSDV_STARTUP_JITTER 2.0 // secs to jitter start of periodic activity from
00055
00056 #define DSDV_ALMOST_NOW 0.1 // jitter used for events that should be effectively
00057
00058
00059 #define DSDV_BROADCAST_JITTER 0.01 // jitter for all broadcast packets
00060 #define DSDV_MIN_TUP_PERIOD 1.0 // minimum time between triggered updates
00061 #define IP_DEF_TTL 32 // default TTTL
00062
00063 #undef TRIGGER_UPDATE_ON_FRESH_SEQNUM
00064
00065
00066
00067
00068
00069
00070 static inline double
00071 jitter (double max, int be_random_)
00072 {
00073 return (be_random_ ? Random::uniform(max) : 0);
00074 }
00075
00076 void DSDV_Agent::
00077 trace (char *fmt,...)
00078 {
00079 va_list ap;
00080
00081 if (!tracetarget)
00082 return;
00083
00084 va_start (ap, fmt);
00085 vsprintf (tracetarget->pt_->buffer (), fmt, ap);
00086 tracetarget->pt_->dump ();
00087 va_end (ap);
00088 }
00089
00090 void
00091 DSDV_Agent::tracepkt (Packet * p, double now, int me, const char *type)
00092 {
00093 char buf[1024];
00094
00095 unsigned char *walk = p->accessdata ();
00096
00097 int ct = *(walk++);
00098 int seq, dst, met;
00099
00100 snprintf (buf, 1024, "V%s %.5f _%d_ [%d]:", type, now, me, ct);
00101 while (ct--)
00102 {
00103 dst = *(walk++);
00104 dst = dst << 8 | *(walk++);
00105 dst = dst << 8 | *(walk++);
00106 dst = dst << 8 | *(walk++);
00107 met = *(walk++);
00108 seq = *(walk++);
00109 seq = seq << 8 | *(walk++);
00110 seq = seq << 8 | *(walk++);
00111 seq = seq << 8 | *(walk++);
00112 snprintf (buf, 1024, "%s (%d,%d,%d)", buf, dst, met, seq);
00113 }
00114
00115
00116 if (verbose_)
00117 trace ("%s", buf);
00118 }
00119
00120
00121 void
00122 DSDV_Agent::output_rte(const char *prefix, rtable_ent * prte, DSDV_Agent * a)
00123 {
00124 a->trace("DFU: deimplemented");
00125 printf("DFU: deimplemented");
00126
00127 prte = 0;
00128 prefix = 0;
00129 #if 0
00130 printf ("%s%d %d %d %d %f %f %f %f 0x%08x\n",
00131 prefix, prte->dst, prte->hop, prte->metric, prte->seqnum,
00132 prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,
00133 (unsigned int) prte->timeout_event);
00134 a->trace ("VTE %.5f %d %d %d %d %f %f %f %f 0x%08x",
00135 Scheduler::instance ().clock (), prte->dst, prte->hop, prte->metric,
00136 prte->seqnum, prte->udtime, prte->new_seqnum_at, prte->wst, prte->changed_at,
00137 prte->timeout_event);
00138 #endif
00139 }
00140
00141 class DSDVTriggerHandler : public Handler {
00142 public:
00143 DSDVTriggerHandler(DSDV_Agent *a_) { a = a_; }
00144 virtual void handle(Event *e);
00145 private:
00146 DSDV_Agent *a;
00147 };
00148
00149
00150 void
00151 DSDVTriggerHandler::handle(Event *e)
00152
00153 {
00154
00155
00156
00157 Scheduler & s = Scheduler::instance ();
00158 Time now = s.clock ();
00159 rtable_ent *prte;
00160 int update_type;
00161 Time next_possible = a->lasttup_ + DSDV_MIN_TUP_PERIOD;
00162
00163 for (a->table_->InitLoop(); (prte = a->table_->NextLoop());)
00164 if (prte->trigger_event == e) break;
00165
00166 assert(prte && prte->trigger_event == e);
00167
00168 if (now < next_possible)
00169 {
00170
00171
00172 s.schedule(a->trigger_handler, e, next_possible - now);
00173 a->cancelTriggersBefore(next_possible);
00174 return;
00175 }
00176
00177 update_type = 0;
00178 Packet * p = a->makeUpdate(update_type);
00179
00180 if (p != NULL)
00181 {
00182 if (update_type == 1)
00183 {
00184
00185 s.cancel(a->periodic_callback_);
00186
00187
00188 s.schedule (a->helper_, a->periodic_callback_,
00189 a->perup_ * (0.75 + jitter (0.25, a->be_random_)));
00190 if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "PU");
00191 }
00192 else
00193 {
00194 if (a->verbose_) a->tracepkt (p, now, a->myaddr_, "TU");
00195 }
00196 assert (!HDR_CMN (p)->xmit_failure_);
00197 s.schedule (a->target_, p, jitter(DSDV_BROADCAST_JITTER, a->be_random_));
00198
00199 a->lasttup_ = now;
00200
00201 }
00202
00203
00204 for (a->table_->InitLoop (); (prte = a->table_->NextLoop ());)
00205 if (prte->trigger_event && prte->trigger_event == e)
00206 {
00207 prte->trigger_event = 0;
00208 delete e;
00209 }
00210 }
00211
00212 void
00213 DSDV_Agent::cancelTriggersBefore(Time t)
00214
00215
00216 {
00217 rtable_ent *prte;
00218 Scheduler & s = Scheduler::instance ();
00219
00220 for (table_->InitLoop (); (prte = table_->NextLoop ());)
00221 if (prte->trigger_event && prte->trigger_event->time_ < t)
00222 {
00223
00224
00225 s.cancel(prte->trigger_event);
00226 delete prte->trigger_event;
00227 prte->trigger_event = 0;
00228 }
00229 }
00230
00231 void
00232 DSDV_Agent::needTriggeredUpdate(rtable_ent *prte, Time t)
00233
00234 {
00235 Scheduler & s = Scheduler::instance();
00236 Time now = Scheduler::instance().clock();
00237
00238 assert(t >= now);
00239
00240 if (prte->trigger_event)
00241 s.cancel(prte->trigger_event);
00242 else
00243 prte->trigger_event = new Event;
00244
00245
00246 s.schedule(trigger_handler, prte->trigger_event, t - now);
00247 }
00248
00249 void
00250 DSDV_Agent::helper_callback (Event * e)
00251 {
00252 Scheduler & s = Scheduler::instance ();
00253 double now = s.clock ();
00254 rtable_ent *prte;
00255 rtable_ent *pr2;
00256 int update_type;
00257
00258
00259
00260
00261 if (periodic_callback_ && e == periodic_callback_)
00262 {
00263 update_type = 1;
00264 Packet *p = makeUpdate(update_type);
00265 if (verbose_)
00266 {
00267 trace ("VPC %.5f _%d_", now, myaddr_);
00268 tracepkt (p, now, myaddr_, "PU");
00269 }
00270
00271
00272 if (p) {
00273 assert (!HDR_CMN (p)->xmit_failure_);
00274
00275
00276
00277 s.schedule (target_, p, jitter(DSDV_BROADCAST_JITTER, be_random_));
00278 }
00279
00280
00281
00282 s.schedule (helper_, periodic_callback_,
00283 perup_ * (0.75 + jitter (0.25, be_random_)));
00284
00285
00286 lasttup_ = now;
00287 return;
00288 }
00289
00290
00291
00292 for (table_->InitLoop (); (prte = table_->NextLoop ());)
00293 if (prte->timeout_event && (prte->timeout_event == e))
00294 break;
00295
00296
00297
00298
00299
00300 if (prte)
00301 {
00302 if (verbose_)
00303 {
00304 trace ("VTO %.5f _%d_ %d->%d", now, myaddr_, myaddr_, prte->dst);
00305
00306
00307
00308
00309 }
00310
00311 for (table_->InitLoop (); (pr2 = table_->NextLoop ()); )
00312 {
00313 if (pr2->hop == prte->dst && pr2->metric != BIG)
00314 {
00315 if (verbose_)
00316 trace ("VTO %.5f _%d_ marking %d", now, myaddr_, pr2->dst);
00317 pr2->metric = BIG;
00318 pr2->advertise_ok_at = now;
00319 pr2->advert_metric = true;
00320 pr2->advert_seqnum = true;
00321 pr2->seqnum++;
00322
00323
00324
00325 needTriggeredUpdate(pr2, now);
00326 }
00327 }
00328
00329
00330 prte->timeout_event = 0;
00331 }
00332 else
00333 {
00334 fprintf(stderr,"DFU: unknown queue event\n");
00335 abort();
00336 }
00337
00338 if (e)
00339 delete e;
00340 }
00341
00342 void
00343 DSDV_Agent::lost_link (Packet *p)
00344 {
00345 hdr_cmn *hdrc = HDR_CMN (p);
00346 rtable_ent *prte = table_->GetEntry (hdrc->next_hop_);
00347
00348 if(use_mac_ == 0) {
00349 drop(p, DROP_RTR_MAC_CALLBACK);
00350 return;
00351 }
00352
00353
00354
00355 if (verbose_ && hdrc->addr_type_ == NS_AF_INET)
00356 trace("VLL %.8f %d->%d lost at %d",
00357 Scheduler::instance().clock(),
00358 hdr_ip::access(p)->saddr(), hdr_ip::access(p)->daddr(),
00359 myaddr_);
00360
00361 if (!use_mac_ || !prte || hdrc->addr_type_ != NS_AF_INET)
00362 return;
00363
00364 if (verbose_)
00365 trace ("VLP %.5f %d:%d->%d:%d lost at %d [hop %d]",
00366 Scheduler::instance ().clock (),
00367 hdr_ip::access (p)->saddr(),
00368 hdr_ip::access (p)->sport(),
00369 hdr_ip::access (p)->daddr(),
00370 hdr_ip::access (p)->dport(),
00371 myaddr_, prte->dst);
00372
00373 if (prte->timeout_event)
00374 {
00375 Scheduler::instance ().cancel (prte->timeout_event);
00376 helper_callback (prte->timeout_event);
00377 }
00378 else if (prte->metric != BIG)
00379 {
00380 assert(prte->timeout_event == 0);
00381 prte->timeout_event = new Event ();
00382 helper_callback (prte->timeout_event);
00383 }
00384
00385
00386 recv(p, 0);
00387
00388 #if 0
00389 while (p2 = ((PriQueue *) target_)->filter (prte->dst))
00390 {
00391 if (verbose_)
00392 trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),
00393 hdr_ip::access (p2)->saddr(),
00394 hdr_ip::access (p2)->sport(),
00395 hdr_ip::access (p2)->daddr(),
00396 hdr_ip::access (p2)->dport(), myaddr_);
00397
00398 recv(p2, 0);
00399 }
00400
00401 while (p2 = ll_queue->filter (prte->dst))
00402 {
00403 if (verbose_)
00404 trace ("VRS %.5f %d:%d->%d:%d lost at %d", Scheduler::instance ().clock (),
00405 hdr_ip::access (p2)->saddr(),
00406 hdr_ip::access (p2)->sport(),
00407 hdr_ip::access (p2)->daddr(),
00408 hdr_ip::access (p2)->dport(), myaddr_);
00409
00410 recv (p2, 0);
00411 }
00412 #endif
00413 }
00414
00415 static void
00416 mac_callback (Packet * p, void *arg)
00417 {
00418 ((DSDV_Agent *) arg)->lost_link (p);
00419 }
00420
00421 Packet *
00422 DSDV_Agent::makeUpdate(int& periodic)
00423
00424
00425
00426
00427
00428
00429 {
00430
00431
00432
00433 Packet *p = allocpkt ();
00434 hdr_ip *iph = hdr_ip::access(p);
00435 hdr_cmn *hdrc = HDR_CMN (p);
00436 double now = Scheduler::instance ().clock ();
00437 rtable_ent *prte;
00438 unsigned char *walk;
00439
00440 int change_count;
00441 int rtbl_sz;
00442 int unadvertiseable;
00443
00444
00445
00446
00447 hdrc->next_hop_ = IP_BROADCAST;
00448 hdrc->addr_type_ = NS_AF_INET;
00449 iph->daddr() = IP_BROADCAST << Address::instance().nodeshift();
00450 iph->dport() = ROUTER_PORT;
00451
00452 change_count = 0;
00453 rtbl_sz = 0;
00454 unadvertiseable = 0;
00455 for (table_->InitLoop ();
00456 (prte = table_->NextLoop ()); )
00457 {
00458 rtbl_sz++;
00459 if ((prte->advert_seqnum || prte->advert_metric)
00460 && prte->advertise_ok_at <= now)
00461 change_count++;
00462
00463 if (prte->advertise_ok_at > now) unadvertiseable++;
00464 }
00465
00466 if (change_count * 3 > rtbl_sz && change_count > 3)
00467 {
00468 periodic = 1;
00469 }
00470
00471
00472 if (periodic)
00473 {
00474 change_count = rtbl_sz - unadvertiseable;
00475
00476 rtable_ent rte;
00477 bzero(&rte, sizeof(rte));
00478
00479
00480
00481
00482
00483 seqno_ += 2;
00484
00485 rte.dst = myaddr_;
00486
00487 rte.hop = Address::instance().get_nodeaddr(iph->saddr());
00488 rte.metric = 0;
00489 rte.seqnum = seqno_;
00490
00491 rte.advertise_ok_at = 0.0;
00492 rte.advert_seqnum = true;
00493 rte.changed_at = now;
00494 rte.new_seqnum_at = now;
00495 rte.wst = 0;
00496 rte.timeout_event = 0;
00497
00498 rte.q = 0;
00499
00500 table_->AddEntry (rte);
00501 }
00502
00503 if (change_count == 0)
00504 {
00505 Packet::free(p);
00506
00507 return NULL;
00508 }
00509
00510
00511
00512
00513
00514 assert(rtbl_sz <= (1500 / 12));
00515
00516 p->allocdata((change_count * 9) + 1);
00517 walk = p->accessdata ();
00518 *(walk++) = change_count;
00519
00520
00521 hdrc->size_ = change_count * 12 + IP_HDR_LEN;
00522
00523 for (table_->InitLoop (); (prte = table_->NextLoop ());)
00524 {
00525
00526 if (periodic && prte->advertise_ok_at > now)
00527 {
00528
00529 continue;
00530 }
00531
00532 if (periodic ||
00533 ((prte->advert_seqnum || prte->advert_metric)
00534 && prte->advertise_ok_at <= now))
00535 {
00536 if (!periodic && verbose_)
00537 trace ("VCT %.5f _%d_ %d", now, myaddr_, prte->dst);
00538
00539
00540
00541 *(walk++) = prte->dst >> 24;
00542 *(walk++) = (prte->dst >> 16) & 0xFF;
00543 *(walk++) = (prte->dst >> 8) & 0xFF;
00544 *(walk++) = (prte->dst >> 0) & 0xFF;
00545 *(walk++) = prte->metric;
00546 *(walk++) = (prte->seqnum) >> 24;
00547 *(walk++) = ((prte->seqnum) >> 16) & 0xFF;
00548 *(walk++) = ((prte->seqnum) >> 8) & 0xFF;
00549 *(walk++) = (prte->seqnum) & 0xFF;
00550
00551 prte->last_advertised_metric = prte->metric;
00552
00553
00554 prte->advert_seqnum = false;
00555
00556 if (periodic)
00557 {
00558
00559 prte->advert_seqnum = false;
00560 prte->advert_metric = false;
00561 }
00562 change_count--;
00563 }
00564 }
00565 assert(change_count == 0);
00566 return p;
00567 }
00568
00569 void
00570 DSDV_Agent::updateRoute(rtable_ent *old_rte, rtable_ent *new_rte)
00571 {
00572 int negvalue = -1;
00573 assert(new_rte);
00574
00575 Time now = Scheduler::instance().clock();
00576
00577 char buf[1024];
00578
00579 snprintf (buf, 1024, "%c %.5f _%d_ (%d,%d->%d,%d->%d,%d->%d,%f)",
00580 (new_rte->metric != BIG
00581 && (!old_rte || old_rte->metric != BIG)) ? 'D' : 'U',
00582 now, myaddr_, new_rte->dst,
00583 old_rte ? old_rte->metric : negvalue, new_rte->metric,
00584 old_rte ? old_rte->seqnum : negvalue, new_rte->seqnum,
00585 old_rte ? old_rte->hop : -1, new_rte->hop,
00586 new_rte->advertise_ok_at);
00587
00588 table_->AddEntry (*new_rte);
00589
00590 if (trace_wst_)
00591 trace ("VWST %.12lf frm %d to %d wst %.12lf nxthp %d [of %d]",
00592 now, myaddr_, new_rte->dst, new_rte->wst, new_rte->hop,
00593 new_rte->metric);
00594 if (verbose_)
00595 trace ("VS%s", buf);
00596 }
00597
00598 void
00599 DSDV_Agent::processUpdate (Packet * p)
00600 {
00601 hdr_ip *iph = HDR_IP(p);
00602 Scheduler & s = Scheduler::instance ();
00603 double now = s.clock ();
00604
00605
00606 int i;
00607 unsigned char *d = p->accessdata ();
00608 unsigned char *w = d + 1;
00609 rtable_ent rte;
00610 rtable_ent *prte;
00611
00612
00613
00614
00615
00616
00617
00618 for (i = *d; i > 0; i--)
00619 {
00620 bool trigger_update = false;
00621 nsaddr_t dst;
00622 prte = NULL;
00623
00624 dst = *(w++);
00625 dst = dst << 8 | *(w++);
00626 dst = dst << 8 | *(w++);
00627 dst = dst << 8 | *(w++);
00628
00629 if ((prte = table_->GetEntry (dst)))
00630 {
00631 bcopy(prte, &rte, sizeof(rte));
00632 }
00633 else
00634 {
00635 bzero(&rte, sizeof(rte));
00636 }
00637
00638 rte.dst = dst;
00639
00640 rte.hop = Address::instance().get_nodeaddr(iph->saddr());
00641 rte.metric = *(w++);
00642 rte.seqnum = *(w++);
00643 rte.seqnum = rte.seqnum << 8 | *(w++);
00644 rte.seqnum = rte.seqnum << 8 | *(w++);
00645 rte.seqnum = rte.seqnum << 8 | *(w++);
00646 rte.changed_at = now;
00647 if (rte.metric != BIG) rte.metric += 1;
00648
00649 if (rte.dst == myaddr_)
00650 {
00651 if (rte.metric == BIG && periodic_callback_)
00652 {
00653
00654
00655
00656
00657
00658 s.cancel (periodic_callback_);
00659 s.schedule (helper_, periodic_callback_, 0);
00660 }
00661 continue;
00662
00663 }
00664
00665
00666
00667 if (prte)
00668 {
00669 if (prte->seqnum == rte.seqnum)
00670 {
00671
00672
00673
00674
00675
00676 rte.wst = prte->wst;
00677 rte.new_seqnum_at = prte->new_seqnum_at;
00678 }
00679 else
00680 {
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 rte.wst = alpha_ * prte->wst +
00691 (1.0 - alpha_) * (prte->changed_at - prte->new_seqnum_at);
00692 rte.new_seqnum_at = now;
00693 }
00694 }
00695 else
00696 {
00697 rte.wst = wst0_;
00698 rte.new_seqnum_at = now;
00699 }
00700
00701
00702 if (rte.metric != BIG && (!prte || prte->metric != BIG))
00703 rte.advertise_ok_at = now + (rte.wst * 2);
00704 else
00705 rte.advertise_ok_at = now;
00706
00707
00708 if (!prte)
00709 {
00710 if (rte.metric < BIG)
00711 {
00712 rte.advert_metric = true;
00713 trigger_update = true;
00714 }
00715 updateRoute(prte,&rte);
00716 }
00717 else if ( prte->seqnum == rte.seqnum )
00718 {
00719 if (rte.metric < prte->metric)
00720 {
00721 if (rte.metric == prte->last_advertised_metric)
00722 {
00723 rte.advert_metric = false;
00724 trigger_update = false;
00725 }
00726 else
00727 {
00728 rte.advert_metric = true;
00729 trigger_update = true;
00730 }
00731 updateRoute(prte,&rte);
00732 }
00733 else
00734 {
00735 }
00736 }
00737 else if ( prte->seqnum < rte.seqnum )
00738 {
00739
00740 rte.advert_seqnum = true;
00741 if (rte.metric == prte->last_advertised_metric)
00742 {
00743 rte.advert_metric = false;
00744 }
00745 else
00746 {
00747 rte.advert_metric = true;
00748 }
00749
00750 updateRoute(prte,&rte);
00751
00752 #ifdef TRIGGER_UPDATE_ON_FRESH_SEQNUM
00753 trigger_update = true;
00754 #else
00755 trigger_update = false;
00756 #endif
00757 }
00758 else if ( prte->seqnum > rte.seqnum )
00759 {
00760 if (rte.metric == BIG && prte->metric != BIG)
00761 {
00762
00763 prte->advertise_ok_at = now;
00764 prte->advert_metric = true;
00765
00766
00767 needTriggeredUpdate(prte,now);
00768 }
00769 else
00770 {
00771 }
00772 }
00773 else
00774 {
00775 fprintf(stderr,
00776 "%s DFU: unhandled adding a route entry?\n", __FILE__);
00777 abort();
00778 }
00779
00780 if (trigger_update)
00781 {
00782 prte = table_->GetEntry (rte.dst);
00783 assert(prte != NULL && prte->advertise_ok_at == rte.advertise_ok_at);
00784 needTriggeredUpdate(prte, prte->advertise_ok_at);
00785 }
00786
00787
00788 if (rte.q && rte.metric != BIG)
00789 {
00790 Packet *queued_p;
00791 while ((queued_p = rte.q->deque()))
00792
00793
00794
00795
00796
00797 recv(queued_p, 0);
00798
00799 delete rte.q;
00800 rte.q = 0;
00801 table_->AddEntry(rte);
00802 }
00803 }
00804
00805
00806 prte = table_->GetEntry(Address::instance().get_nodeaddr(iph->saddr()));
00807 if (prte)
00808 {
00809 if (prte->timeout_event)
00810 s.cancel (prte->timeout_event);
00811 else
00812 {
00813 prte->timeout_event = new Event ();
00814 }
00815
00816 s.schedule (helper_, prte->timeout_event, min_update_periods_ * perup_);
00817 }
00818 else
00819 {
00820
00821
00822
00823
00824
00825
00826
00827 bzero(&rte, sizeof(rte));
00828 rte.dst = Address::instance().get_nodeaddr(iph->saddr());
00829 rte.hop = Address::instance().get_nodeaddr(iph->saddr());
00830 rte.metric = 1;
00831 rte.seqnum = 0;
00832 rte.advertise_ok_at = now + 604800;
00833
00834 rte.changed_at = now;
00835 rte.new_seqnum_at = now;
00836 rte.wst = wst0_;
00837 rte.timeout_event = new Event ();
00838 rte.q = 0;
00839
00840 updateRoute(NULL, &rte);
00841 s.schedule(helper_, rte.timeout_event, min_update_periods_ * perup_);
00842 }
00843
00844
00845
00846
00847
00848 Packet::free (p);
00849
00850 }
00851
00852 int
00853 DSDV_Agent::diff_subnet(int dst)
00854 {
00855 char* dstnet = Address::instance().get_subnetaddr(dst);
00856 if (subnet_ != NULL) {
00857 if (dstnet != NULL) {
00858 if (strcmp(dstnet, subnet_) != 0) {
00859 delete [] dstnet;
00860 return 1;
00861 }
00862 delete [] dstnet;
00863 }
00864 }
00865
00866 return 0;
00867 }
00868
00869
00870
00871 void
00872 DSDV_Agent::forwardPacket (Packet * p)
00873 {
00874 hdr_ip *iph = HDR_IP(p);
00875 Scheduler & s = Scheduler::instance ();
00876 double now = s.clock ();
00877 hdr_cmn *hdrc = HDR_CMN (p);
00878 int dst;
00879 rtable_ent *prte;
00880
00881
00882
00883
00884 hdrc->direction() = hdr_cmn::DOWN;
00885
00886
00887
00888
00889
00890 dst = Address::instance().get_nodeaddr(iph->daddr());
00891 if (diff_subnet(iph->daddr())) {
00892 prte = table_->GetEntry (dst);
00893 if (prte && prte->metric != BIG)
00894 goto send;
00895
00896
00897 dst = node_->base_stn();
00898 prte = table_->GetEntry (dst);
00899 if (prte && prte->metric != BIG)
00900 goto send;
00901
00902 else {
00903
00904 fprintf(stderr, "warning: Route to base_stn not known: dropping pkt\n");
00905 Packet::free(p);
00906 return;
00907 }
00908 }
00909
00910 prte = table_->GetEntry (dst);
00911
00912
00913
00914
00915
00916
00917 if (prte && prte->metric != BIG)
00918 {
00919
00920 goto send;
00921 }
00922 else if (prte)
00923 {
00924
00925 if (!prte->q)
00926 {
00927 prte->q = new PacketQueue ();
00928 }
00929
00930 prte->q->enque(p);
00931
00932 if (verbose_)
00933 trace ("VBP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_, iph->saddr(),
00934 iph->sport(), iph->daddr(), iph->dport());
00935
00936 while (prte->q->length () > MAX_QUEUE_LENGTH)
00937 drop (prte->q->deque (), DROP_RTR_QFULL);
00938 return;
00939 }
00940 else
00941 {
00942 rtable_ent rte;
00943 double now = s.clock();
00944
00945 bzero(&rte, sizeof(rte));
00946 rte.dst = dst;
00947 rte.hop = dst;
00948 rte.metric = BIG;
00949 rte.seqnum = 0;
00950
00951 rte.advertise_ok_at = now + 604800;
00952 rte.changed_at = now;
00953 rte.new_seqnum_at = now;
00954 rte.wst = wst0_;
00955 rte.timeout_event = 0;
00956
00957 rte.q = new PacketQueue();
00958 rte.q->enque(p);
00959
00960 assert (rte.q->length() == 1 && 1 <= MAX_QUEUE_LENGTH);
00961 table_->AddEntry(rte);
00962
00963 if (verbose_)
00964 trace ("VBP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_,
00965 iph->saddr(), iph->sport(), iph->daddr(), iph->dport());
00966 return;
00967 }
00968
00969
00970 send:
00971 hdrc->addr_type_ = NS_AF_INET;
00972 hdrc->xmit_failure_ = mac_callback;
00973 hdrc->xmit_failure_data_ = this;
00974 if (prte->metric > 1)
00975 hdrc->next_hop_ = prte->hop;
00976 else
00977 hdrc->next_hop_ = dst;
00978 if (verbose_)
00979 trace ("Routing pkts outside domain: \
00980 VFP %.5f _%d_ %d:%d -> %d:%d", now, myaddr_, iph->saddr(),
00981 iph->sport(), iph->daddr(), iph->dport());
00982
00983 assert (!HDR_CMN (p)->xmit_failure_ ||
00984 HDR_CMN (p)->xmit_failure_ == mac_callback);
00985 target_->recv(p, (Handler *)0);
00986 return;
00987
00988 }
00989
00990 void
00991 DSDV_Agent::sendOutBCastPkt(Packet *p)
00992 {
00993 Scheduler & s = Scheduler::instance ();
00994
00995 s.schedule (target_, p, jitter(DSDV_BROADCAST_JITTER, be_random_));
00996 }
00997
00998
00999 void
01000 DSDV_Agent::recv (Packet * p, Handler *)
01001 {
01002 hdr_ip *iph = HDR_IP(p);
01003 hdr_cmn *cmh = HDR_CMN(p);
01004 int src = Address::instance().get_nodeaddr(iph->saddr());
01005 int dst = cmh->next_hop();
01006
01007
01008
01009 if(src == myaddr_ && cmh->num_forwards() == 0) {
01010
01011
01012
01013 cmh->size() += IP_HDR_LEN;
01014 iph->ttl_ = IP_DEF_TTL;
01015 }
01016
01017
01018
01019
01020 else if(src == myaddr_) {
01021 drop(p, DROP_RTR_ROUTE_LOOP);
01022 return;
01023 }
01024
01025
01026
01027 else {
01028
01029
01030
01031 if(--iph->ttl_ == 0) {
01032 drop(p, DROP_RTR_TTL);
01033 return;
01034 }
01035 }
01036
01037 if ((src != myaddr_) && (iph->dport() == ROUTER_PORT))
01038 {
01039
01040
01041
01042
01043
01044
01045
01046
01047 processUpdate(p);
01048 }
01049 else if ((u_int32_t) dst == IP_BROADCAST &&
01050 (iph->dport() != ROUTER_PORT))
01051 {
01052 if (src == myaddr_) {
01053
01054 sendOutBCastPkt(p);
01055 }
01056 else {
01057
01058
01059 port_dmux_->recv(p, (Handler*)0);
01060 }
01061 }
01062 else
01063 {
01064 forwardPacket(p);
01065 }
01066 }
01067
01068 static class DSDVClass:public TclClass
01069 {
01070 public:
01071 DSDVClass ():TclClass ("Agent/DSDV")
01072 {
01073 }
01074 TclObject *create (int, const char *const *)
01075 {
01076 return (new DSDV_Agent ());
01077 }
01078 } class_dsdv;
01079
01080 DSDV_Agent::DSDV_Agent (): Agent (PT_MESSAGE), ll_queue (0), seqno_ (0),
01081 myaddr_ (0), subnet_ (0), node_ (0), port_dmux_(0),
01082 periodic_callback_ (0), be_random_ (1),
01083 use_mac_ (0), verbose_ (1), trace_wst_ (0), lasttup_ (-10),
01084 alpha_ (0.875), wst0_ (6), perup_ (15),
01085 min_update_periods_ (3)
01086 {
01087 table_ = new RoutingTable ();
01088 helper_ = new DSDV_Helper (this);
01089 trigger_handler = new DSDVTriggerHandler(this);
01090
01091 bind_time ("wst0_", &wst0_);
01092 bind_time ("perup_", &perup_);
01093
01094 bind ("use_mac_", &use_mac_);
01095 bind ("be_random_", &be_random_);
01096 bind ("alpha_", &alpha_);
01097 bind ("min_update_periods_", &min_update_periods_);
01098 bind ("verbose_", &verbose_);
01099 bind ("trace_wst_", &trace_wst_);
01100
01101 address = 0;
01102
01103 }
01104
01105 void
01106 DSDV_Agent::startUp()
01107 {
01108 Time now = Scheduler::instance().clock();
01109
01110 subnet_ = Address::instance().get_subnetaddr(myaddr_);
01111
01112 address = Address::instance().print_nodeaddr(myaddr_);
01113
01114
01115 rtable_ent rte;
01116 bzero(&rte, sizeof(rte));
01117
01118 rte.dst = myaddr_;
01119 rte.hop = myaddr_;
01120 rte.metric = 0;
01121 rte.seqnum = seqno_;
01122 seqno_ += 2;
01123
01124 rte.advertise_ok_at = 0.0;
01125 rte.advert_seqnum = true;
01126 rte.advert_metric = true;
01127 rte.changed_at = now;
01128 rte.new_seqnum_at = now;
01129 rte.wst = 0;
01130 rte.timeout_event = 0;
01131
01132 rte.q = 0;
01133
01134 table_->AddEntry (rte);
01135
01136
01137 periodic_callback_ = new Event ();
01138 Scheduler::instance ().schedule (helper_,
01139 periodic_callback_,
01140 jitter (DSDV_STARTUP_JITTER, be_random_));
01141 }
01142
01143 int
01144 DSDV_Agent::command (int argc, const char *const *argv)
01145 {
01146 if (argc == 2)
01147 {
01148 if (strcmp (argv[1], "start-dsdv") == 0)
01149 {
01150 startUp();
01151 return (TCL_OK);
01152 }
01153 else if (strcmp (argv[1], "dumprtab") == 0)
01154 {
01155 Packet *p2 = allocpkt ();
01156 hdr_ip *iph2 = HDR_IP(p2);
01157 rtable_ent *prte;
01158
01159 printf ("Table Dump %d[%d]\n----------------------------------\n",
01160 iph2->saddr(), iph2->sport());
01161 trace ("VTD %.5f %d:%d\n", Scheduler::instance ().clock (),
01162 iph2->saddr(), iph2->sport());
01163
01164
01165
01166
01167
01168 Packet::free (p2);
01169
01170 for (table_->InitLoop (); (prte = table_->NextLoop ());)
01171 output_rte ("\t", prte, this);
01172
01173 printf ("\n");
01174
01175 return (TCL_OK);
01176 }
01177 else if (strcasecmp (argv[1], "ll-queue") == 0)
01178 {
01179 if (!(ll_queue = (PriQueue *) TclObject::lookup (argv[2])))
01180 {
01181 fprintf (stderr, "DSDV_Agent: ll-queue lookup of %s failed\n", argv[2]);
01182 return TCL_ERROR;
01183 }
01184
01185 return TCL_OK;
01186 }
01187
01188 }
01189 else if (argc == 3)
01190 {
01191 if (strcasecmp (argv[1], "addr") == 0) {
01192 int temp;
01193 temp = Address::instance().str2addr(argv[2]);
01194 myaddr_ = temp;
01195 return TCL_OK;
01196 }
01197 TclObject *obj;
01198 if ((obj = TclObject::lookup (argv[2])) == 0)
01199 {
01200 fprintf (stderr, "%s: %s lookup of %s failed\n", __FILE__, argv[1],
01201 argv[2]);
01202 return TCL_ERROR;
01203 }
01204 if (strcasecmp (argv[1], "tracetarget") == 0)
01205 {
01206
01207 tracetarget = (Trace *) obj;
01208 return TCL_OK;
01209 }
01210 else if (strcasecmp (argv[1], "node") == 0) {
01211 node_ = (MobileNode*) obj;
01212 return TCL_OK;
01213 }
01214 else if (strcasecmp (argv[1], "port-dmux") == 0) {
01215 port_dmux_ = (NsObject *) obj;
01216 return TCL_OK;
01217 }
01218 }
01219
01220 return (Agent::command (argc, argv));
01221 }
01222
01223
01224
01225