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 #include <agent.h>
00040 #include <random.h>
00041 #include <trace.h>
00042
00043 #include <ll.h>
00044 #include <priqueue.h>
00045 #include <tora/tora_packet.h>
00046 #include <tora/tora.h>
00047
00048 #define LOG(s) \
00049 fprintf(stdout, "%s --- %s (index: %d, time: %f)\n", \
00050 __PRETTY_FUNCTION__, (s), index, Scheduler::instance().clock())
00051
00052
00053 #define CURRENT_TIME Scheduler::instance().clock()
00054
00055
00056
00057
00058 #define ARP_SEPARATION_DELAY 0.030
00059
00060
00061
00062
00063
00064 int hdr_tora::offset_;
00065 static class TORAHeaderClass : public PacketHeaderClass {
00066 public:
00067 TORAHeaderClass() : PacketHeaderClass("PacketHeader/TORA",
00068 TORA_HDR_LEN) {
00069 bind_offset(&hdr_tora::offset_);
00070 }
00071 } class_toraAgent_hdr;
00072
00073 static class toraAgentclass : public TclClass {
00074 public:
00075 toraAgentclass() : TclClass("Agent/TORA") {}
00076 TclObject* create(int argc, const char*const* argv) {
00077 assert(argc == 5);
00078 return (new toraAgent((nsaddr_t) atoi(argv[4])));
00079 }
00080 } class_toraAgent;
00081
00082
00083
00084
00085
00086 toraAgent::toraAgent(nsaddr_t id) :
00087 rtAgent(id, PT_TORA),
00088 rqueue()
00089 {
00090 LIST_INIT(&dstlist);
00091 imepagent = 0;
00092 logtarget = 0;
00093 ifqueue = 0;
00094 }
00095
00096 void
00097 toraAgent::reset()
00098 {
00099 Packet *p;
00100 while((p = rqueue.deque())) {
00101 drop(p,DROP_END_OF_SIMULATION);
00102 }
00103 }
00104
00105 int
00106 toraAgent::command(int argc, const char*const* argv)
00107 {
00108 if(argc == 2) {
00109 Tcl& tcl = Tcl::instance();
00110
00111 if(strncasecmp(argv[1], "id", 2) == 0) {
00112 tcl.resultf("%d", index);
00113 return TCL_OK;
00114 }
00115 }
00116 else if(argc == 3) {
00117
00118 if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0 ) {
00119 logtarget = (Trace*) TclObject::lookup(argv[2]);
00120 if(logtarget == 0)
00121 return TCL_ERROR;
00122 return TCL_OK;
00123 }
00124 else if(strcmp(argv[1], "drop-target") == 0) {
00125 int stat = rqueue.command(argc,argv);
00126 if (stat != TCL_OK) return stat;
00127 return Agent::command(argc, argv);
00128 }
00129 else if(strcmp(argv[1], "if-queue") == 0) {
00130 ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
00131 if(ifqueue == 0)
00132 return TCL_ERROR;
00133 return TCL_OK;
00134 }
00135 else if(strcmp(argv[1], "imep-agent") == 0) {
00136 imepagent = (imepAgent*) TclObject::lookup(argv[2]);
00137 if(imepagent == 0)
00138 return TCL_ERROR;
00139 imepagent->imepRegister((rtAgent*) this);
00140 return TCL_OK;
00141 }
00142 }
00143 return Agent::command(argc, argv);
00144 }
00145
00146
00147
00148
00149
00150 TORADest*
00151 toraAgent::dst_find(nsaddr_t id)
00152 {
00153 TORADest* td = dstlist.lh_first;
00154 for( ; td; td = td->link.le_next) {
00155 if(td->index == id)
00156 return td;
00157 }
00158 return 0;
00159 }
00160
00161 TORADest*
00162 toraAgent::dst_add(nsaddr_t id)
00163 {
00164 TORADest *td = new TORADest(id, this);
00165 assert(td);
00166
00167 LIST_INSERT_HEAD(&dstlist, td, link);
00168
00169 int *nblist = 0, nbcnt = 0;
00170 imepagent->imepGetBiLinks(nblist, nbcnt);
00171
00172 for(int i = 0; i < nbcnt; i++)
00173 (void) td->nb_add(nblist[i]);
00174
00175 if(nblist) delete[] nblist;
00176
00177 return td;
00178 }
00179
00180 void
00181 toraAgent::dst_dump()
00182 {
00183 TORADest *td = dstlist.lh_first;
00184
00185 for( ; td; td = td->link.le_next)
00186 td->dump();
00187 }
00188
00189
00190
00191
00192
00193 void
00194 toraAgent::forward(Packet *p, nsaddr_t nexthop, Time delay)
00195 {
00196 struct hdr_cmn *ch = HDR_CMN(p);
00197
00198 #ifdef TORA_DISALLOW_ROUTE_LOOP
00199 if(nexthop == ch->prev_hop_) {
00200 log_route_loop(ch->prev_hop_, nexthop);
00201 drop(p, DROP_RTR_ROUTE_LOOP);
00202 return;
00203 }
00204 #endif
00205 ch->next_hop() = nexthop;
00206 ch->prev_hop_ = ipaddr();
00207 ch->addr_type() = NS_AF_INET;
00208
00209
00210 ch->direction() = hdr_cmn::DOWN;
00211
00212 if (0.0 == delay) {
00213 tora_output(p);
00214 } else {
00215 Scheduler::instance().schedule(target_, p, delay);
00216 }
00217 }
00218
00219
00220 void
00221 toraAgent::rt_resolve(Packet *p)
00222 {
00223 struct hdr_ip *ih = HDR_IP(p);
00224 TORADest *td;
00225 TORANeighbor *tn;
00226
00227 td = dst_find(ih->daddr());
00228 if(td == 0) {
00229 td = dst_add(ih->daddr());
00230 }
00231
00232 tn = td->nb_find_next_hop();
00233 if(tn == 0) {
00234 rqueue.enque(p);
00235
00236 trace("T %.9f _%d_ tora enq %d->%d",
00237 Scheduler::instance().clock(), ipaddr(),
00238 ih->saddr(), ih->daddr());
00239
00240 if(!td->rt_req)
00241 {
00242 sendQRY(ih->daddr());
00243 td->time_tx_qry = CURRENT_TIME;
00244 td->rt_req = 1;
00245 }
00246 }
00247 else {
00248 forward(p, tn->index);
00249 }
00250 }
00251
00252
00253
00254
00255
00256 void
00257 toraAgent::recv(Packet *p, Handler *)
00258 {
00259 struct hdr_cmn *ch = HDR_CMN(p);
00260 struct hdr_ip *ih = HDR_IP(p);
00261
00262 assert(initialized());
00263
00264 if(ch->ptype() == PT_TORA) {
00265 recvTORA(p);
00266 return;
00267 }
00268
00269
00270
00271
00272 if(ih->saddr() == ipaddr() && ch->num_forwards() == 0) {
00273
00274
00275
00276 ch->size() += IP_HDR_LEN;
00277
00278 ih->ttl_ = IP_DEF_TTL;
00279 }
00280
00281 #ifdef TORA_DISALLOW_ROUTE_LOOP
00282
00283
00284
00285
00286 else if(ih->saddr() == ipaddr()) {
00287 drop(p, DROP_RTR_ROUTE_LOOP);
00288 return;
00289 }
00290 #endif
00291
00292
00293
00294 else {
00295
00296
00297
00298 if(--ih->ttl_ == 0) {
00299 drop(p, DROP_RTR_TTL);
00300 return;
00301 }
00302 }
00303
00304 rt_resolve(p);
00305 }
00306
00307 void
00308 toraAgent::recvTORA(Packet *p)
00309 {
00310 struct hdr_tora *th = HDR_TORA(p);
00311 TORADest *td;
00312 TORANeighbor *tn;
00313
00314
00315
00316
00317 assert(HDR_IP (p)->sport() == RT_PORT);
00318 assert(HDR_IP (p)->dport() == RT_PORT);
00319
00320
00321
00322
00323 switch(th->th_type) {
00324 case TORATYPE_QRY:
00325 recvQRY(p);
00326 Packet::free(p);
00327 return;
00328
00329 case TORATYPE_UPD:
00330 log_recv_upd(p);
00331 recvUPD(p);
00332 break;
00333
00334 case TORATYPE_CLR:
00335 log_recv_clr(p);
00336 recvCLR(p);
00337 break;
00338
00339 default:
00340 fprintf(stderr,
00341 "%s: Invalid TORA type (%x)\n",
00342 __PRETTY_FUNCTION__, th->th_type);
00343 exit(1);
00344 }
00345
00346 if((td = dst_find(th->th_dst)) == 0) {
00347 Packet::free(p);
00348 return;
00349 }
00350
00351 logNextHopChange(td);
00352
00353 if((tn = td->nb_find_next_hop())) {
00354 Packet *p0;
00355 Time delay = 0.0;
00356
00357 while((p0 = rqueue.deque(td->index))) {
00358 forward(p0, tn->index, delay);
00359 delay += ARP_SEPARATION_DELAY;
00360 }
00361 }
00362 Packet::free(p);
00363 }
00364
00365
00366
00367
00368
00369
00370 void
00371 toraAgent::recvQRY(Packet *p)
00372 {
00373 struct hdr_ip *ih = HDR_IP(p);
00374 struct hdr_tora_qry *qh = HDR_TORA_QRY(p);
00375 TORADest *td;
00376 TORANeighbor *tn;
00377
00378 if(qh->tq_dst == ipaddr()) {
00379 #ifdef DEBUG
00380 fprintf(stderr, "node %d received `QRY` for itself.\n", index);
00381 #endif
00382 return;
00383 }
00384
00385 td = dst_find(qh->tq_dst);
00386 if(td == 0)
00387 td = dst_add(qh->tq_dst);
00388
00389 if(td->rt_req) {
00390 return;
00391 }
00392
00393 if(td->height.r == 0) {
00394 tn = td->nb_find(ih->saddr());
00395
00396 if(tn && tn->time_act > td->time_upd) {
00397 td->time_upd = Scheduler::instance().clock();
00398 sendUPD(td->index);
00399 }
00400 else {
00401 }
00402 }
00403 else {
00404 tn = td->nb_find_min_height(0);
00405
00406 if(tn) {
00407 td->update_height(tn->height.tau,
00408 tn->height.oid,
00409 tn->height.r,
00410 tn->height.delta + 1,
00411 ipaddr());
00412
00413 td->time_upd = Scheduler::instance().clock();
00414
00415 sendUPD(td->index);
00416 }
00417 else {
00418 td->rt_req = 1;
00419 td->time_rt_req = CURRENT_TIME;
00420
00421 if(td->num_active > 1) {
00422 sendQRY(td->index);
00423 }
00424 else {
00425
00426 }
00427 }
00428 }
00429 }
00430
00431
00432
00433
00434
00435 void
00436 toraAgent::recvUPD(Packet *p)
00437 {
00438 struct hdr_ip *ih = HDR_IP(p);
00439 struct hdr_tora_upd *uh = HDR_TORA_UPD(p);
00440 TORADest *td;
00441 TORANeighbor *tn;
00442
00443 if(uh->tu_dst == ipaddr()) {
00444 return;
00445 }
00446
00447 td = dst_find(uh->tu_dst);
00448 if(td == 0)
00449 td = dst_add(uh->tu_dst);
00450
00451 tn = td->nb_find(ih->saddr());
00452 if(tn == 0) {
00453
00454
00455
00456
00457
00458
00459
00460 trace("T %.9f _%d_ received `UPD` from non-neighbor %d",
00461 CURRENT_TIME, ipaddr(), ih->saddr());
00462 #ifdef DEBUG
00463 fprintf(stderr,
00464 "node %d received `UPD` from non-neighbor %d\n",
00465 index, ih->src_);
00466 #endif
00467 return;
00468 }
00469
00470
00471
00472
00473 td->update_height_nb(tn, uh);
00474
00475 if(td->rt_req && tn->height.r == 0) {
00476
00477 td->update_height(tn->height.tau,
00478 tn->height.oid,
00479 tn->height.r,
00480 tn->height.delta + 1,
00481 ipaddr());
00482
00483 td->rt_req = 0;
00484
00485 td->time_upd = Scheduler::instance().clock();
00486
00487 sendUPD(td->index);
00488 }
00489 else if(td->num_down == 0) {
00490 if(td->num_up == 0) {
00491 if(td->height.isNull())
00492 return;
00493 else {
00494 td->height.Null();
00495
00496 td->time_upd = Scheduler::instance().clock();
00497
00498 sendUPD(td->index);
00499 }
00500 }
00501 else {
00502 if(td->nb_check_same_ref()) {
00503 TORANeighbor *tn;
00504
00505 if( (tn = td->nb_find_min_height(0)) ) {
00506 td->update_height(tn->height.tau,
00507 tn->height.oid,
00508 1,
00509 0,
00510 ipaddr());
00511 td->time_upd = Scheduler::instance().clock();
00512
00513 sendUPD(td->index);
00514 }
00515 else {
00516 if(td->height.oid == ipaddr()) {
00517 double temp_tau = td->height.tau;
00518 nsaddr_t temp_oid = td->height.oid;
00519
00520 td->height.Null();
00521 td->num_down = 0;
00522 td->num_up = 0;
00523
00524
00525
00526
00527
00528
00529
00530 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00531 if(tn->index == td->index) {
00532 tn->height.Zero();
00533 tn->lnk_stat = LINK_DN;
00534
00535 }
00536 else {
00537 tn->height.Null();
00538 tn->lnk_stat = LINK_UN;
00539 }
00540 }
00541
00542 sendCLR(td->index, temp_tau, temp_oid);
00543 }
00544 else {
00545 td->update_height(Scheduler::instance().clock(),
00546 ipaddr(),
00547 0,
00548 0,
00549 ipaddr());
00550 td->rt_req = 0;
00551 td->time_upd = Scheduler::instance().clock();
00552
00553 #ifdef DEBUG
00554
00555
00556
00557
00558 if (logtarget)
00559 {
00560 sprintf(logtarget->pt_->buffer(), "T %.9f _%d_ rule IIA2a(ii)x fires %d",
00561 Scheduler::instance().clock(), ipaddr(), td->index);
00562 logtarget->pt_->dump();
00563 }
00564 #endif
00565 sendUPD(td->index);
00566 }
00567 }
00568
00569 }
00570 else {
00571 TORANeighbor *n = td->nb_find_max_height();
00572 assert(n);
00573 TORANeighbor *m = td->nb_find_min_nonnull_height(&n->height);
00574 assert(m);
00575
00576 td->update_height(m->height.tau,
00577 m->height.oid,
00578 m->height.r,
00579 m->height.delta - 1,
00580 ipaddr());
00581
00582 td->time_upd = Scheduler::instance().clock();
00583
00584 sendUPD(td->index);
00585 }
00586 }
00587 }
00588 else {
00589
00590 }
00591 }
00592
00593
00594
00595
00596
00597 void
00598 toraAgent::recvCLR(Packet *p)
00599 {
00600 struct hdr_ip *ih = HDR_IP(p);
00601 struct hdr_tora_clr *th = HDR_TORA_CLR(p);
00602 TORADest *td;
00603 TORANeighbor *tn;
00604
00605 if(th->tc_dst == ipaddr()) {
00606 return;
00607 }
00608
00609 td = dst_find(th->tc_dst);
00610 if(td == 0)
00611 td = dst_add(th->tc_dst);
00612 assert(td);
00613
00614 if(td->height.tau == th->tc_tau &&
00615 td->height.oid == th->tc_oid &&
00616 td->height.r == 1) {
00617 double temp_tau = td->height.tau;
00618 nsaddr_t temp_oid = td->height.oid;
00619
00620 td->height.Null();
00621 td->num_up = 0;
00622 td->num_down = 0;
00623
00624 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00625 if(tn->index == td->index) {
00626 tn->height.Zero();
00627 tn->lnk_stat = LINK_DN;
00628 }
00629 else {
00630 tn->height.Null();
00631 tn->lnk_stat = LINK_UN;
00632 }
00633 }
00634 if(td->num_active > 1) {
00635 sendCLR(td->index, temp_tau, temp_oid);
00636 }
00637 else {
00638 }
00639 }
00640 else {
00641 tn = td->nb_find(ih->saddr());
00642 if(tn == 0) {
00643
00644
00645
00646 trace("T %.9f _%d_ received `CLR` from non-neighbor %d",
00647 CURRENT_TIME, index, ih->saddr());
00648 #ifdef DEBUG
00649 fprintf(stderr,
00650 "node %d received `CLR` from non-neighbor %d\n",
00651 index, ih->src_);
00652 #endif
00653 return;
00654 }
00655
00656 tn->height.Null();
00657 tn->lnk_stat = LINK_UN;
00658
00659 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00660 if(tn->height.tau == th->tc_tau &&
00661 tn->height.oid == th->tc_oid &&
00662 tn->height.r == 1) {
00663 tn->height.Null();
00664 tn->lnk_stat = LINK_UN;
00665 }
00666 }
00667 if(td->num_down == 0) {
00668 if(td->num_up == 0) {
00669 if(td->height.isNull()) {
00670 }
00671 else {
00672 td->height.Null();
00673 td->time_upd = Scheduler::instance().clock();
00674 sendUPD(td->index);
00675 }
00676 }
00677 else {
00678 td->update_height(Scheduler::instance().clock(),
00679 ipaddr(),
00680 0,
00681 0,
00682 ipaddr());
00683 td->rt_req = 0;
00684 td->time_upd = Scheduler::instance().clock();
00685 sendUPD(td->index);
00686 }
00687 }
00688 else {
00689
00690 }
00691 }
00692 }
00693
00694 void
00695 toraAgent::trace(char* fmt, ...)
00696 {
00697 va_list ap;
00698
00699 if (!logtarget) return;
00700
00701 va_start(ap, fmt);
00702 vsprintf(logtarget->pt_->buffer(), fmt, ap);
00703 logtarget->pt_->dump();
00704 va_end(ap);
00705 }
00706
00707