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 = 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_ip *ih = HDR_IP(p);
00311 struct hdr_tora *th = HDR_TORA(p);
00312 TORADest *td;
00313 TORANeighbor *tn;
00314
00315
00316
00317
00318 assert(ih->sport() == RT_PORT);
00319 assert(ih->dport() == RT_PORT);
00320
00321
00322
00323
00324 switch(th->th_type) {
00325 case TORATYPE_QRY:
00326 recvQRY(p);
00327 Packet::free(p);
00328 return;
00329
00330 case TORATYPE_UPD:
00331 log_recv_upd(p);
00332 recvUPD(p);
00333 break;
00334
00335 case TORATYPE_CLR:
00336 log_recv_clr(p);
00337 recvCLR(p);
00338 break;
00339
00340 default:
00341 fprintf(stderr,
00342 "%s: Invalid TORA type (%x)\n",
00343 __PRETTY_FUNCTION__, th->th_type);
00344 exit(1);
00345 }
00346
00347 if((td = dst_find(th->th_dst)) == 0) {
00348 Packet::free(p);
00349 return;
00350 }
00351
00352 logNextHopChange(td);
00353
00354 if((tn = td->nb_find_next_hop())) {
00355 Packet *p0;
00356 Time delay = 0.0;
00357
00358 while((p0 = rqueue.deque(td->index))) {
00359 forward(p0, tn->index, delay);
00360 delay += ARP_SEPARATION_DELAY;
00361 }
00362 }
00363 Packet::free(p);
00364 }
00365
00366
00367
00368
00369
00370
00371 void
00372 toraAgent::recvQRY(Packet *p)
00373 {
00374 struct hdr_ip *ih = HDR_IP(p);
00375 struct hdr_tora_qry *qh = HDR_TORA_QRY(p);
00376 TORADest *td;
00377 TORANeighbor *tn;
00378
00379 if(qh->tq_dst == ipaddr()) {
00380 #ifdef DEBUG
00381 fprintf(stderr, "node %d received `QRY` for itself.\n", index);
00382 #endif
00383 return;
00384 }
00385
00386 td = dst_find(qh->tq_dst);
00387 if(td == 0)
00388 td = dst_add(qh->tq_dst);
00389
00390 if(td->rt_req) {
00391 return;
00392 }
00393
00394 if(td->height.r == 0) {
00395 tn = td->nb_find(ih->saddr());
00396
00397 if(tn && tn->time_act > td->time_upd) {
00398 td->time_upd = Scheduler::instance().clock();
00399 sendUPD(td->index);
00400 }
00401 else {
00402 }
00403 }
00404 else {
00405 tn = td->nb_find_min_height(0);
00406
00407 if(tn) {
00408 td->update_height(tn->height.tau,
00409 tn->height.oid,
00410 tn->height.r,
00411 tn->height.delta + 1,
00412 ipaddr());
00413
00414 td->time_upd = Scheduler::instance().clock();
00415
00416 sendUPD(td->index);
00417 }
00418 else {
00419 td->rt_req = 1;
00420 td->time_rt_req = CURRENT_TIME;
00421
00422 if(td->num_active > 1) {
00423 sendQRY(td->index);
00424 }
00425 else {
00426
00427 }
00428 }
00429 }
00430 }
00431
00432
00433
00434
00435
00436 void
00437 toraAgent::recvUPD(Packet *p)
00438 {
00439 struct hdr_ip *ih = HDR_IP(p);
00440 struct hdr_tora_upd *uh = HDR_TORA_UPD(p);
00441 TORADest *td;
00442 TORANeighbor *tn;
00443
00444 if(uh->tu_dst == ipaddr()) {
00445 return;
00446 }
00447
00448 td = dst_find(uh->tu_dst);
00449 if(td == 0)
00450 td = dst_add(uh->tu_dst);
00451
00452 tn = td->nb_find(ih->saddr());
00453 if(tn == 0) {
00454
00455
00456
00457
00458
00459
00460
00461 trace("T %.9f _%d_ received `UPD` from non-neighbor %d",
00462 CURRENT_TIME, ipaddr(), ih->saddr());
00463 #ifdef DEBUG
00464 fprintf(stderr,
00465 "node %d received `UPD` from non-neighbor %d\n",
00466 index, ih->src_);
00467 #endif
00468 return;
00469 }
00470
00471
00472
00473
00474 td->update_height_nb(tn, uh);
00475
00476 if(td->rt_req && tn->height.r == 0) {
00477
00478 td->update_height(tn->height.tau,
00479 tn->height.oid,
00480 tn->height.r,
00481 tn->height.delta + 1,
00482 ipaddr());
00483
00484 td->rt_req = 0;
00485
00486 td->time_upd = Scheduler::instance().clock();
00487
00488 sendUPD(td->index);
00489 }
00490 else if(td->num_down == 0) {
00491 if(td->num_up == 0) {
00492 if(td->height.isNull())
00493 return;
00494 else {
00495 td->height.Null();
00496
00497 td->time_upd = Scheduler::instance().clock();
00498
00499 sendUPD(td->index);
00500 }
00501 }
00502 else {
00503 if(td->nb_check_same_ref()) {
00504 TORANeighbor *tn;
00505
00506 if( (tn = td->nb_find_min_height(0)) ) {
00507 td->update_height(tn->height.tau,
00508 tn->height.oid,
00509 1,
00510 0,
00511 ipaddr());
00512 td->time_upd = Scheduler::instance().clock();
00513
00514 sendUPD(td->index);
00515 }
00516 else {
00517 if(td->height.oid == ipaddr()) {
00518 double temp_tau = td->height.tau;
00519 nsaddr_t temp_oid = td->height.oid;
00520
00521 td->height.Null();
00522 td->num_down = 0;
00523 td->num_up = 0;
00524
00525
00526
00527
00528
00529
00530
00531 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00532 if(tn->index == td->index) {
00533 tn->height.Zero();
00534 tn->lnk_stat = LINK_DN;
00535
00536 }
00537 else {
00538 tn->height.Null();
00539 tn->lnk_stat = LINK_UN;
00540 }
00541 }
00542
00543 sendCLR(td->index, temp_tau, temp_oid);
00544 }
00545 else {
00546 td->update_height(Scheduler::instance().clock(),
00547 ipaddr(),
00548 0,
00549 0,
00550 ipaddr());
00551 td->rt_req = 0;
00552 td->time_upd = Scheduler::instance().clock();
00553
00554 #ifdef DEBUG
00555
00556
00557
00558
00559 if (logtarget)
00560 {
00561 sprintf(logtarget->pt_->buffer(), "T %.9f _%d_ rule IIA2a(ii)x fires %d",
00562 Scheduler::instance().clock(), ipaddr(), td->index);
00563 logtarget->pt_->dump();
00564 }
00565 #endif
00566 sendUPD(td->index);
00567 }
00568 }
00569
00570 }
00571 else {
00572 TORANeighbor *n = td->nb_find_max_height();
00573 assert(n);
00574 TORANeighbor *m = td->nb_find_min_nonnull_height(&n->height);
00575 assert(m);
00576
00577 td->update_height(m->height.tau,
00578 m->height.oid,
00579 m->height.r,
00580 m->height.delta - 1,
00581 ipaddr());
00582
00583 td->time_upd = Scheduler::instance().clock();
00584
00585 sendUPD(td->index);
00586 }
00587 }
00588 }
00589 else {
00590
00591 }
00592 }
00593
00594
00595
00596
00597
00598 void
00599 toraAgent::recvCLR(Packet *p)
00600 {
00601 struct hdr_ip *ih = HDR_IP(p);
00602 struct hdr_tora_clr *th = HDR_TORA_CLR(p);
00603 TORADest *td;
00604 TORANeighbor *tn;
00605
00606 if(th->tc_dst == ipaddr()) {
00607 return;
00608 }
00609
00610 td = dst_find(th->tc_dst);
00611 if(td == 0)
00612 td = dst_add(th->tc_dst);
00613 assert(td);
00614
00615 if(td->height.tau == th->tc_tau &&
00616 td->height.oid == th->tc_oid &&
00617 td->height.r == 1) {
00618 double temp_tau = td->height.tau;
00619 nsaddr_t temp_oid = td->height.oid;
00620
00621 td->height.Null();
00622 td->num_up = 0;
00623 td->num_down = 0;
00624
00625 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00626 if(tn->index == td->index) {
00627 tn->height.Zero();
00628 tn->lnk_stat = LINK_DN;
00629 }
00630 else {
00631 tn->height.Null();
00632 tn->lnk_stat = LINK_UN;
00633 }
00634 }
00635 if(td->num_active > 1) {
00636 sendCLR(td->index, temp_tau, temp_oid);
00637 }
00638 else {
00639 }
00640 }
00641 else {
00642 tn = td->nb_find(ih->saddr());
00643 if(tn == 0) {
00644
00645
00646
00647 trace("T %.9f _%d_ received `CLR` from non-neighbor %d",
00648 CURRENT_TIME, index, ih->saddr());
00649 #ifdef DEBUG
00650 fprintf(stderr,
00651 "node %d received `CLR` from non-neighbor %d\n",
00652 index, ih->src_);
00653 #endif
00654 return;
00655 }
00656
00657 tn->height.Null();
00658 tn->lnk_stat = LINK_UN;
00659
00660 for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
00661 if(tn->height.tau == th->tc_tau &&
00662 tn->height.oid == th->tc_oid &&
00663 tn->height.r == 1) {
00664 tn->height.Null();
00665 tn->lnk_stat = LINK_UN;
00666 }
00667 }
00668 if(td->num_down == 0) {
00669 if(td->num_up == 0) {
00670 if(td->height.isNull()) {
00671 }
00672 else {
00673 td->height.Null();
00674 td->time_upd = Scheduler::instance().clock();
00675 sendUPD(td->index);
00676 }
00677 }
00678 else {
00679 td->update_height(Scheduler::instance().clock(),
00680 ipaddr(),
00681 0,
00682 0,
00683 ipaddr());
00684 td->rt_req = 0;
00685 td->time_upd = Scheduler::instance().clock();
00686 sendUPD(td->index);
00687 }
00688 }
00689 else {
00690
00691 }
00692 }
00693 }
00694
00695 void
00696 toraAgent::trace(char* fmt, ...)
00697 {
00698 va_list ap;
00699
00700 if (!logtarget) return;
00701
00702 va_start(ap, fmt);
00703 vsprintf(logtarget->pt_->buffer(), fmt, ap);
00704 logtarget->pt_->dump();
00705 va_end(ap);
00706 }
00707
00708