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 <packet.h>
00040 #include <ip.h>
00041 #include <random.h>
00042
00043 #include <cmu-trace.h>
00044 #include <imep/imep.h>
00045
00046 #define CURRENT_TIME Scheduler::instance().clock()
00047
00048 static const int verbose = 0;
00049 static const int imep_use_mac_callback = 1;
00050
00051
00052
00053
00054
00055 int hdr_imep::offset_;
00056 static class IMEPHeaderClass : public PacketHeaderClass {
00057 public:
00058 IMEPHeaderClass() : PacketHeaderClass("PacketHeader/IMEP",
00059 IMEP_HDR_LEN) {
00060 bind_offset(&hdr_imep::offset_);
00061 }
00062 } class_imep_hdr;
00063
00064 static class agentIMEPclass : public TclClass {
00065 public:
00066 agentIMEPclass() : TclClass("Agent/IMEP") {}
00067 TclObject* create(int argc, const char*const* argv) {
00068 assert(argc == 5);
00069 return (new imepAgent((nsaddr_t) atoi(argv[4])));
00070 }
00071 } class_imepAgent;
00072
00073
00074
00075
00076
00077
00078 static void
00079 imep_failed_callback(Packet *p, void *arg)
00080 {
00081 if(imep_use_mac_callback)
00082 ((imepAgent*) arg)->imepPacketUndeliverable(p);
00083 else {
00084 Packet::free(p);
00085
00086 }
00087 }
00088
00089 imepAgent::imepAgent(nsaddr_t index) :
00090 Agent(PT_TORA),
00091 beaconTimer(this, BEACON_TIMER),
00092 controlTimer(this, CONTROL_TIMER),
00093 rexmitTimer(this, REXMIT_TIMER),
00094 incomingTimer(this, INCOMING_TIMER),
00095 ipaddr(index),
00096 incomingQ(this, index)
00097 {
00098 controlSequence = 0;
00099 recvtarget_ = sendtarget_ = 0;
00100 logtarget_ = 0;
00101 rtagent_ = 0;
00102 LIST_INIT(&imepLinkHead);
00103 bzero(&stats, sizeof(stats));
00104 }
00105
00106 int
00107 imepAgent::command(int argc, const char*const* argv)
00108 {
00109 if(argc == 2) {
00110 if(strcmp(argv[1], "start") == 0) {
00111 beaconTimer.start(BEACON_PERIOD);
00112 return TCL_OK;
00113 }
00114 else if(strcmp(argv[1], "reset") == 0) {
00115 Terminate();
00116 return TCL_OK;
00117 }
00118 } else if (argc == 3) {
00119 if (strcmp(argv[1], "recvtarget") == 0) {
00120 recvtarget_ = (NsObject*) TclObject::lookup(argv[2]);
00121 assert(recvtarget_);
00122 return (TCL_OK);
00123 }
00124 else if (strcmp(argv[1], "sendtarget") == 0) {
00125 sendtarget_ = (NsObject*) TclObject::lookup(argv[2]);
00126 assert(sendtarget_);
00127 return (TCL_OK);
00128 }
00129 else if (strcmp(argv[1], "rtagent") == 0) {
00130 rtagent_ = (rtAgent*) TclObject::lookup(argv[2]);
00131 assert(rtagent_);
00132 return (TCL_OK);
00133 }
00134 else if(strcmp(argv[1], "log-target") == 0) {
00135 logtarget_ = (Trace*) TclObject::lookup(argv[2]);
00136 assert(logtarget_);
00137 return (TCL_OK);
00138 }
00139 }
00140 return Agent::command(argc, argv);
00141 }
00142
00143
00144 imepLink*
00145 imepAgent::findLink(nsaddr_t index)
00146 {
00147 imepLink *l;
00148
00149 for(l = imepLinkHead.lh_first; l; l = l->link.le_next) {
00150 if(l->index() == index)
00151 return l;
00152 }
00153 return 0;
00154 }
00155
00156 Packet*
00157 imepAgent::findObjectSequence(u_int8_t seqno)
00158 {
00159 Packet *p;
00160 ReXmitQIter iter = rexmitq.iter();
00161 struct imep_object_block *ob;
00162
00163 while ((p = iter.next())) {
00164 ob = findObjectBlock(p);
00165
00166 if(ob == 0) continue;
00167
00168
00169 if(ob->ob_sequence != seqno) continue;
00170
00171
00172 if(ob->ob_num_responses <=0) {
00173 fprintf(stderr,
00174 "imepAgent::findObjectSequence: "
00175 "Object Block without response list\n");
00176 abort();
00177 }
00178
00179 return p;
00180 }
00181
00182
00183
00184
00185
00186 return NULL;
00187 }
00188
00189
00190 void
00191 imepAgent::removeObjectResponse(Packet *p, nsaddr_t index)
00192 {
00193 struct imep_object_block *ob = findObjectBlock(p);
00194 struct imep_response *r = findResponseList(p);
00195 struct imep_response *r0;
00196 struct hdr_cmn *ch = HDR_CMN(p);
00197 int i;
00198
00199 assert(ob && r);
00200
00201 for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) {
00202 if(INT32_T(r0->resp_ipaddr) == index)
00203 break;
00204 }
00205
00206 if(INT32_T(r0->resp_ipaddr) != index) {
00207 if (verbose)
00208 trace("T %.9f _%d_ dup ack(?) from %d", CURRENT_TIME, ipaddr, index);
00209 return;
00210 }
00211
00212 if(ob->ob_num_responses == 1) {
00213 if (verbose)
00214 trace("T %.9f _%d_ remove from reXq pkt %d",
00215 CURRENT_TIME, ipaddr, ch->uid());
00216 rexmitq.remove(p);
00217 Packet::free(p);
00218 stats.num_rexmitable_fully_acked++;
00219 } else {
00220
00221 r += (ob->ob_num_responses - 1);
00222
00223 if(r != r0) {
00224 INT32_T(r0->resp_ipaddr) = INT32_T(r->resp_ipaddr);
00225 }
00226
00227 ob->ob_num_responses -= 1;
00228
00229 if (verbose)
00230 trace("T %.9f _%d_ remove %d from resp list %d (%d left) RL %s",
00231 CURRENT_TIME, ipaddr, index, ch->uid(), ob->ob_num_responses,
00232 dumpResponseList(p));
00233
00234 struct hdr_imep *im = HDR_IMEP(p);
00235 ch->size() -= sizeof(struct imep_response);
00236 U_INT16_T(im->imep_length) -= sizeof(struct imep_response);
00237 }
00238 }
00239
00240
00241 void
00242 imepAgent::purgeReXmitQ(nsaddr_t index)
00243
00244 {
00245 Packet *p;
00246 ReXmitQIter iter = rexmitq.iter();
00247 struct imep_object_block *ob;
00248 struct imep_response *r,*r0;
00249 struct hdr_cmn *ch;
00250 int i;
00251
00252 if (verbose)
00253 trace("T %.9f _%d_ purge %d from reXmit Q",
00254 CURRENT_TIME, ipaddr, index);
00255
00256 while ((p = iter.next())) {
00257 ob = findObjectBlock(p);
00258 if(ob == 0) assert(0);
00259
00260 r = findResponseList(p);
00261 ch = HDR_CMN(p);
00262
00263 assert(ob && r);
00264
00265 for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) {
00266 if(INT32_T(r0->resp_ipaddr) == index)
00267 break;
00268 }
00269
00270 if(INT32_T(r0->resp_ipaddr) != index) {
00271 continue;
00272 }
00273
00274 if(ob->ob_num_responses == 1) {
00275 if (verbose)
00276 trace("T %.9f _%d_ remove from reXq pkt %d",
00277 CURRENT_TIME, ipaddr, ch->uid());
00278 rexmitq.remove(p);
00279 drop(p, DROP_RTR_QTIMEOUT);
00280 stats.num_rexmitable_fully_acked++;
00281 } else {
00282
00283 r += (ob->ob_num_responses - 1);
00284
00285 if(r != r0) {
00286 INT32_T(r0->resp_ipaddr) = INT32_T(r->resp_ipaddr);
00287 }
00288
00289 ob->ob_num_responses -= 1;
00290
00291 if (verbose)
00292 trace("T %.9f _%d_ purge %d from resp list %d (%d left) RL %s",
00293 CURRENT_TIME, ipaddr, index, ch->uid(), ob->ob_num_responses,
00294 dumpResponseList(p));
00295
00296 struct hdr_imep *im = HDR_IMEP(p);
00297 ch->size() -= sizeof(struct imep_response);
00298 U_INT16_T(im->imep_length) -= sizeof(struct imep_response);
00299 }
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308 void
00309 imepAgent::handlerTimer(imepTimerType t)
00310 {
00311 switch(t) {
00312 case BEACON_TIMER:
00313 handlerBeaconTimer();
00314 break;
00315 case CONTROL_TIMER:
00316 handlerControlTimer();
00317 break;
00318 case REXMIT_TIMER:
00319 handlerReXmitTimer();
00320 break;
00321 case INCOMING_TIMER:
00322 handlerIncomingTimer();
00323 break;
00324 default:
00325 abort();
00326 }
00327 }
00328
00329 void
00330 imepAgent::handlerBeaconTimer(void)
00331 {
00332 imepLink *l;
00333
00334
00335 purgeLink();
00336
00337 if (verbose) log_neighbor_list();
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if (controlTimer.busy() || helloQueue.length() > 0)
00348 {
00349
00350
00351 if (controlTimer.busy()) controlTimer.cancel();
00352 handlerControlTimer();
00353 }
00354 else
00355 {
00356
00357
00358 if (NULL == imepLinkHead.lh_first) sendBeacon();
00359
00360
00361
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371 int busy_before_hello_load = controlTimer.busy();
00372 for(l = imepLinkHead.lh_first; l; l = l->link.le_next)
00373 {
00374 if (l->status() & LINK_IN) sendHello(l->index());
00375 }
00376 if (!busy_before_hello_load && controlTimer.busy()) controlTimer.cancel();
00377
00378
00379 beaconTimer.start(BEACON_PERIOD);
00380 }
00381
00382
00383
00384 void
00385 imepAgent::handlerControlTimer(void)
00386 {
00387 Packet *p;
00388
00389 int num_acks = ackQueue.length();
00390 int num_hellos = helloQueue.length();
00391 int num_objects = objectQueue.length();
00392
00393 MAKE_PACKET:
00394 assert(num_acks + num_hellos + num_objects > 0);
00395
00396
00397
00398 p = Packet::alloc();
00399
00400 struct hdr_cmn *ch = HDR_CMN(p);
00401 struct hdr_ip *ih = HDR_IP(p);
00402 struct hdr_imep *im = HDR_IMEP(p);
00403
00404 ch->uid() = uidcnt_++;
00405 ch->ptype() = PT_IMEP;
00406 ch->size() = BEACON_HDR_LEN;
00407 ch->iface() = -2;
00408 ch->error() = 0;
00409 ch->addr_type() = NS_AF_NONE;
00410 ch->prev_hop_ = ipaddr;
00411
00412 ih->saddr() = ipaddr;
00413 ih->daddr() = IP_BROADCAST;
00414 ih->sport() = RT_PORT;
00415 ih->dport() = RT_PORT;
00416 ih->ttl_ = 1;
00417
00418 im->imep_version = IMEP_VERSION;
00419 im->imep_block_flags = 0x00;
00420 U_INT16_T(im->imep_length) = sizeof(struct hdr_imep);
00421
00422 aggregateAckBlock(p);
00423 aggregateHelloBlock(p);
00424 aggregateObjectBlock(p);
00425
00426 imep_output(p);
00427
00428 num_acks = ackQueue.length();
00429 num_hellos = helloQueue.length();
00430 num_objects = objectQueue.length();
00431 if (num_acks + num_hellos + num_objects > 0)
00432 {
00433 if (verbose)
00434 trace("T %.9f _%d_ imep pkt overflow %d %d %d leftover",
00435 CURRENT_TIME, ipaddr, num_acks, num_hellos, num_objects);
00436 goto MAKE_PACKET;
00437 }
00438
00439
00440
00441 }
00442
00443 void
00444 imepAgent::handlerReXmitTimer()
00445 {
00446 Packet *p;
00447 Time rexat;
00448 int num_xmits_left;
00449
00450 rexmitq.peekHead(&rexat, &p, &num_xmits_left);
00451
00452 if (NULL == p) return;
00453 struct hdr_cmn *ch = HDR_CMN(p);
00454
00455 if (0 == num_xmits_left)
00456 {
00457 if (verbose)
00458 {
00459 trace("T %.9f _%d_ rexmit timed out %d RL:%s",
00460 CURRENT_TIME, ipaddr, ch->uid(), dumpResponseList(p));
00461 }
00462
00463 struct imep_object_block *ob = findObjectBlock(p);
00464 struct imep_response *r = findResponseList(p);
00465 int i;
00466
00467 for(i = 0; i < ob->ob_num_responses; i++, r++)
00468 {
00469 if (verbose) trace("T %.9f _%d_ punting neighbor %d",
00470 CURRENT_TIME, ipaddr, INT32_T(r->resp_ipaddr));
00471 imepSetLinkDownStatus(INT32_T(r->resp_ipaddr));
00472 }
00473
00474 stats.num_rexmitable_retired++;
00475 stats.sum_rexmitable_retired_response_sz += ob->ob_num_responses;
00476
00477
00478
00479
00480
00481
00482
00483 }
00484 else if (rexat <= CURRENT_TIME)
00485 {
00486 if (verbose)
00487 trace("T %.9f _%d_ rexmit %d as %d",
00488 CURRENT_TIME, ipaddr, ch->uid(), uidcnt_);
00489 ch->uid() = uidcnt_++;
00490 imep_output(p->copy());
00491
00492 num_xmits_left--;
00493 rexmitq.removeHead();
00494 rexmitq.insert(CURRENT_TIME + RETRANS_PERIOD, p, num_xmits_left);
00495
00496 stats.num_rexmits++;
00497 }
00498
00499
00500 rexmitq.peekHead(&rexat, &p, &num_xmits_left);
00501 if (NULL == p) return;
00502 if (verbose) trace("T %.9f _%d_ rexmit trigger again for %d at %.9f (in %.9f)",
00503 CURRENT_TIME, ipaddr, ch->uid(), rexat, rexat - CURRENT_TIME );
00504 rexmitTimer.start(rexat - CURRENT_TIME);
00505 }
00506
00507
00508 void
00509 imepAgent::handlerIncomingTimer()
00510 {
00511 Packet *p;
00512 u_int32_t s;
00513 double expire;
00514 int index;
00515
00516 if (verbose) trace("T %.9f _%d_ inorder - timer expired",
00517 CURRENT_TIME, ipaddr);
00518
00519 incomingQ.dumpAll();
00520
00521 while((p = incomingQ.getNextPacket(s))) {
00522 stats.num_holes_retired++;
00523
00524 index = HDR_IP(p)->saddr();
00525 imepLink *l = findLink(index);
00526 assert(l);
00527
00528
00529 if(verbose)
00530 trace("T %.9f _%d_ inorder - src %d hole retired seq %d -> %d",
00531 CURRENT_TIME, ipaddr, index, l->lastSeq(), s);
00532
00533
00534
00535
00536
00537
00538
00539 rtagent_->rtNotifyLinkDN(index);
00540 stats.delete_neighbor3++;
00541 rtagent_->rtNotifyLinkUP(index);
00542 stats.new_neighbor++;
00543
00544 if (verbose)
00545 trace("T %.9f _%d_ inorder - src %d seq %d (timer delivery)",
00546 CURRENT_TIME, ipaddr, index, s);
00547
00548 l->lastSeq() = s;
00549
00550 stats.num_recvd_from_queue++;
00551 imep_object_process(p);
00552 Packet::free(p);
00553
00554
00555 Packet *p0;
00556 while((p0 = incomingQ.getPacket(index, l->lastSeq() + 1)))
00557 {
00558 if (verbose)
00559 trace("T %.9f _%d_ inorder - src %d seq %d (chain"
00560 " timer delivery)", CURRENT_TIME, ipaddr,
00561 HDR_IP(p0)->saddr(), l->lastSeq() + 1);
00562 l->lastSeq() += 1;
00563 stats.num_recvd_from_queue++;
00564 imep_object_process(p0);
00565 Packet::free(p0);
00566 }
00567 }
00568
00569 if((expire = incomingQ.getNextExpire()) != 0.0) {
00570 assert(expire > CURRENT_TIME);
00571 if (verbose)
00572 trace("T %.9f _%d_ inorder - timer started (delay %.9f)",
00573 CURRENT_TIME, ipaddr, expire - CURRENT_TIME);
00574 incomingTimer.start(expire - CURRENT_TIME);
00575 }
00576 }
00577
00578
00580
00581 void
00582 imepAgent::scheduleReXmit(Packet *p)
00583 {
00584 rexmitq.insert(CURRENT_TIME + RETRANS_PERIOD, p, MAX_REXMITS);
00585
00586
00587 if (!rexmitTimer.busy()) rexmitTimer.start(RETRANS_PERIOD);
00588 }
00589
00590 void
00591 imepAgent::scheduleIncoming(Packet *p, u_int32_t s)
00592 {
00593 struct hdr_ip *ip = HDR_IP(p);
00594
00595 incomingQ.addEntry(ip->saddr(), CURRENT_TIME + MAX_RETRANS_TIME, s, p);
00596
00597
00598 if (!incomingTimer.busy()) {
00599 if (verbose)
00600 trace("T %.9f _%d_ inorder - timer started",
00601 CURRENT_TIME, ipaddr);
00602 incomingTimer.start(MAX_RETRANS_TIME);
00603 }
00604 }
00605
00606
00607
00608
00609
00610 void
00611 imepAgent::recv(Packet *p, Handler *)
00612 {
00613
00614 struct hdr_cmn *ch = HDR_CMN(p);
00615
00616 assert(initialized());
00617
00618 if(ch->prev_hop_ == ipaddr) {
00619
00620
00621
00622
00623
00624 recv_outgoing(p);
00625 } else {
00626 recv_incoming(p);
00627 }
00628 }
00629
00630 void
00631 imepAgent::recv_outgoing(Packet *p)
00632 {
00633 struct hdr_cmn *ch = HDR_CMN(p);
00634 struct hdr_ip *ip = HDR_IP(p);
00635
00636 if(DATA_PACKET(ch->ptype())) {
00637 imep_output(p);
00638 return;
00639 }
00640
00641 if(ip->daddr() != (nsaddr_t) IP_BROADCAST) {
00642 fprintf(stderr, "IP dst is unicast - not encapsulating\n");
00643 imep_output(p);
00644 return;
00645 }
00646
00647 assert(ch->ptype() == PT_TORA);
00648
00649
00650 objectQueue.enque(p);
00651
00652
00653
00654
00655
00656
00657 double send_delay = MIN_TRANSMIT_WAIT_TIME_HIGHP
00658 + ((MAX_TRANSMIT_WAIT_TIME_HIGHP - MIN_TRANSMIT_WAIT_TIME_HIGHP)
00659 * Random::uniform());
00660 if (controlTimer.busy() == 0)
00661 {
00662 controlTimer.start(send_delay);
00663 }
00664 else if (controlTimer.timeLeft() > send_delay)
00665 {
00666 controlTimer.cancel();
00667 controlTimer.start(send_delay);
00668 }
00669 }
00670
00671 void
00672 imepAgent::recv_incoming(Packet *p)
00673 {
00674 struct hdr_cmn *ch = HDR_CMN(p);
00675 struct hdr_ip *ih = HDR_IP(p);
00676 struct hdr_imep *im = HDR_IMEP(p);
00677
00678 if(DATA_PACKET(ch->ptype())) {
00679 imep_input(p);
00680 return;
00681 }
00682
00683
00684
00685
00686
00687 imepSetLinkInStatus(ih->saddr());
00688
00689
00690
00691
00692
00693 assert(ch->ptype() == PT_IMEP);
00694 assert(im->imep_version == IMEP_VERSION);
00695
00696 if(im->imep_block_flags == 0) {
00697 imep_beacon_input(p);
00698 Packet::free(p);
00699 return;
00700 }
00701
00702 if(im->imep_block_flags & BLOCK_FLAG_ACK)
00703 imep_ack_input(p);
00704
00705 if(im->imep_block_flags & BLOCK_FLAG_HELLO)
00706 imep_hello_input(p);
00707
00708 if(im->imep_block_flags & BLOCK_FLAG_OBJECT) {
00709 imep_object_input(p);
00710
00711
00712
00713
00714 }
00715
00716 Packet::free(p);
00717 }
00718
00719 void
00720 imepAgent::imep_beacon_input(Packet *p)
00721 {
00722 struct hdr_ip *ip = HDR_IP(p);
00723
00724 sendHello(ip->saddr());
00725 }
00726
00727
00728
00729
00730
00731 void
00732 imepAgent::imep_ack_input(Packet *p)
00733 {
00734 struct hdr_ip *ih = HDR_IP(p);
00735 struct imep_ack_block *ab = findAckBlock(p);
00736 struct imep_ack *ack;
00737
00738 assert(ab);
00739 ack = (struct imep_ack*) (ab + 1);
00740
00741
00742
00743
00744 for(int i = 0; i < ab->ab_num_acks; i++, ack++) {
00745 if(INT32_T(ack->ack_ipaddr) == ipaddr) {
00746
00747 Packet *p0 = findObjectSequence(ack->ack_seqno);
00748 if (NULL == p0)
00749 {
00750 if(verbose)
00751 trace("T %.9f _%d_ %d acks seq %d : no obj"
00752 " block", CURRENT_TIME, ipaddr,
00753 ih->saddr(), ack->ack_seqno);
00754 stats.num_unexpected_acks++;
00755 continue;
00756 }
00757
00758 removeObjectResponse(p0, ih->saddr());
00759
00760 imepSetLinkBiStatus(ih->saddr());
00761 }
00762 }
00763 }
00764
00765 void
00766 imepAgent::imep_hello_input(Packet *p)
00767 {
00768 struct hdr_ip *ip = HDR_IP(p);
00769 struct imep_hello_block *hb = findHelloBlock(p);
00770 struct imep_hello *hello;
00771
00772 assert(hb);
00773 hello = (struct imep_hello*) (hb + 1);
00774
00775 for(int i = 0; i < hb->hb_num_hellos; i++, hello++) {
00776 if(INT32_T(hello->hello_ipaddr) == ipaddr) {
00777
00778 imepSetLinkBiStatus(ip->saddr());
00779
00780 break;
00781 }
00782 }
00783 }
00784
00785 void
00786 imepAgent::imep_object_input(Packet *p)
00787 {
00788 struct imep_object_block *ob;
00789
00790
00791 imep_ack_object(p);
00792
00793
00794 ob = findObjectBlock(p);
00795 assert(ob);
00796
00797 struct hdr_ip *iph = HDR_IP(p);
00798 imepLink *l = findLink(iph->saddr());
00799 assert(l);
00800
00801 if (!l->lastSeqValid())
00802 {
00803 l->lastSeqValid() = 1;
00804 l->lastSeq() = ob->ob_sequence - 1;
00805 if (verbose)
00806 trace("T %.9f _d_ first object from neighbor %d seq %d",
00807 CURRENT_TIME, ipaddr, iph->saddr(), ob->ob_sequence);
00808 }
00809
00810
00811
00812
00813 int8_t reg = (int8_t) ob->ob_sequence - (int8_t) l->lastSeq();
00814
00815 if(reg <= 0)
00816 {
00817
00818 if (verbose)
00819 trace("T %.9f _%d_ from %d ignored seq %d (already heard)",
00820 CURRENT_TIME, ipaddr, iph->saddr(), ob->ob_sequence);
00821 stats.num_out_of_window_objs++;
00822 return;
00823 }
00824
00825 if (verbose && reg > 1)
00826 {
00827 trace("T %.9f _%d_ inorder - src %d seq %d out of order (%d expected)",
00828 CURRENT_TIME, ipaddr, iph->saddr(),
00829 ob->ob_sequence, l->lastSeq()+1);
00830 }
00831
00832 if (1 == reg)
00833 {
00834
00835
00836 if (verbose)
00837 trace("T %.9f _%d_ inorder - fastpath src %d seq %d (delivering)",
00838 CURRENT_TIME, ipaddr, HDR_IP(p)->saddr(), ob->ob_sequence);
00839 stats.num_in_order_objs++;
00840
00841 imep_object_process(p);
00842 assert((u_int8_t)(l->lastSeq() + 1) == ob->ob_sequence);
00843 l->lastSeq() = ob->ob_sequence;
00844 }
00845 else
00846 {
00847
00848 scheduleIncoming(p->copy(), ob->ob_sequence);
00849 stats.num_out_of_order_objs++;
00850 }
00851
00852
00853 Packet *p0;
00854 while((p0 = incomingQ.getPacket(iph->saddr(), l->lastSeq() + 1)))
00855 {
00856 stats.num_recvd_from_queue++;
00857 if (verbose)
00858 trace("T %.9f _%d_ inorder - src %d seq %d (delivering)",
00859 CURRENT_TIME, ipaddr, HDR_IP(p0)->saddr(), l->lastSeq() + 1);
00860 l->lastSeq() += 1;
00861 imep_object_process(p0);
00862 Packet::free(p0);
00863 }
00864 }
00865
00866 void
00867 imepAgent::imep_object_process(Packet *p)
00868
00869 {
00870 struct imep_object_block *ob;
00871 struct imep_object *object;
00872 int i;
00873
00874 stats.num_object_pkts_recvd++;
00875
00876 ob = findObjectBlock(p);
00877 assert(ob);
00878 assert(ob->ob_protocol_type == PROTO_TORA);
00879
00880 object = (struct imep_object*) (ob + 1);
00881
00882 for(i = 0; i < ob->ob_num_objects; i++)
00883 {
00884 Packet *p0 = p->copy();
00885
00886 assert(object->o_length > 0);
00887
00888 toraCreateHeader(p0,
00889 ((char*) object) + sizeof(struct imep_object),
00890 object->o_length);
00891
00892 imep_input(p0);
00893
00894 object = (struct imep_object*) ((char*) object +
00895 sizeof(struct imep_object) + object->o_length);
00896 }
00897 }
00898
00899
00900 void
00901 imepAgent::imep_ack_object(Packet *p)
00902
00903 {
00904 struct hdr_ip *iph = HDR_IP(p);
00905 struct imep_object_block *ob;
00906 struct imep_object *object;
00907 int i;
00908
00909 ob = findObjectBlock(p);
00910 if (!ob) return;
00911
00912 if (0 == ob->ob_num_responses)
00913 return;
00914
00915 if (31 == ob->ob_num_responses)
00916 {
00917 sendAck(iph->saddr(), ob->ob_sequence);
00918 return;
00919 }
00920
00921 object = (struct imep_object*) (ob + 1);
00922
00923
00924 for(i = 0; i < ob->ob_num_objects; i++)
00925 {
00926 object = (struct imep_object*) ((char*) object +
00927 sizeof(struct imep_object) + object->o_length);
00928 }
00929
00930 struct imep_response *r = (struct imep_response*) object;
00931 for (i = 0; i < ob->ob_num_responses; i++)
00932 {
00933 if (INT32_T(r->resp_ipaddr) == ipaddr)
00934 {
00935 sendAck(iph->saddr(), ob->ob_sequence);
00936 break;
00937 }
00938 r = r + 1;
00939 }
00940 }
00941
00942
00943
00944
00945
00946 void
00947 imepAgent::imep_input(Packet *p)
00948 {
00949 recvtarget_->recv(p, (Handler*) 0);
00950 }
00951
00952 void
00953 imepAgent::imep_output(Packet *p)
00954 {
00955 struct hdr_cmn *ch = HDR_CMN(p);
00956
00957 if(imep_use_mac_callback) {
00958 ch->xmit_failure_ = imep_failed_callback;
00959 ch->xmit_failure_data_ = (void*) this;
00960 } else {
00961 ch->xmit_failure_ = 0;
00962 ch->xmit_failure_data_ = 0;
00963 }
00964 ch->xmit_reason_ = 0;
00965
00966 sendtarget_->recv(p, (Handler*) 0);
00967 }
00968
00969
00970
00971
00972
00973 void
00974 imepAgent::imep_dump_header(Packet *p)
00975 {
00976 struct hdr_imep *im = HDR_IMEP(p);
00977
00978 fprintf(stderr,
00979 "imep_version: 0x%x\n", im->imep_version);
00980 fprintf(stderr,
00981 "imep_block_flags: 0x%x\n", im->imep_block_flags);
00982 fprintf(stderr,
00983 "imep_length: 0x%04x\n", U_INT16_T(im->imep_length));
00984
00985 Packet::dump_header(p, hdr_imep::offset_, 64);
00986 }
00987
00988 void
00989 imepAgent::log_neighbor_list()
00990 {
00991 imepLink *l;
00992 int offset = 0;
00993
00994 if(! verbose ) return;
00995
00996 sprintf(logtarget_->pt_->buffer(),
00997 "T %.9f _%d_ neighbors: ", CURRENT_TIME, ipaddr);
00998
00999 for(l = imepLinkHead.lh_first; l; l = l->link.le_next) {
01000 offset = strlen(logtarget_->pt_->buffer());
01001 sprintf(logtarget_->pt_->buffer() + offset,
01002 "%d%c ", l->index(),
01003 l->status() == LINK_BI ? '+' :
01004 (l->status() == LINK_IN ? '-' :
01005 (l->status() == LINK_OUT ? '|' : 'X')));
01006 }
01007 logtarget_->pt_->dump();
01008 }
01009
01010 void
01011 imepAgent::trace(char* fmt, ...)
01012 {
01013 va_list ap;
01014
01015 if (!logtarget_) return;
01016
01017 va_start(ap, fmt);
01018 vsprintf(logtarget_->pt_->buffer(), fmt, ap);
01019 logtarget_->pt_->dump();
01020 va_end(ap);
01021 }
01022
01023
01024 char *
01025 imepAgent::dumpResponseList(Packet *p)
01026 {
01027 static char buf[512];
01028 char *ptr = buf;
01029 struct imep_object_block *ob = findObjectBlock(p);
01030 struct imep_response *r = findResponseList(p);
01031 struct imep_response *r0;
01032 int i;
01033
01034 for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++)
01035 {
01036 ptr += (int)sprintf(ptr,"%d ", INT32_T(r0->resp_ipaddr));
01037 }
01038 return buf;
01039 }
01040
01041
01042 void
01043 imepAgent::Terminate()
01044 {
01045 trace("IL %.9f _%d_ Add-Adj: %d New-Neigh: %d Del-Neigh1: %d Del-Neigh2: %d Del-Neigh3: %d",
01046 CURRENT_TIME, ipaddr,
01047 stats.new_in_adjacency,
01048 stats.new_neighbor ,
01049 stats.delete_neighbor1 ,
01050 stats.delete_neighbor2,
01051 stats.delete_neighbor3);
01052
01053 trace("IL %.9f _%d_ Created QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr,
01054 stats.qry_objs_created ,
01055 stats.upd_objs_created ,
01056 stats.clr_objs_created);
01057
01058 trace("IL %.9f _%d_ Received QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr,
01059 stats.qry_objs_recvd ,
01060 stats.upd_objs_recvd ,
01061 stats.clr_objs_recvd);
01062
01063 trace("IL %.9f _%d_ Total-Obj-Created: %d Obj-Pkt-Created: %d Obj-Pkt-Recvd: %d",
01064 CURRENT_TIME, ipaddr,
01065 stats.num_objects_created ,
01066 stats.num_object_pkts_created ,
01067 stats.num_object_pkts_recvd);
01068
01069 trace("IL %.9f _%d_ Rexmit Pkts: %d Acked: %d Retired: %d Rexmits: %d",
01070 CURRENT_TIME, ipaddr,
01071 stats.num_rexmitable_pkts ,
01072 stats.num_rexmitable_fully_acked ,
01073 stats.num_rexmitable_retired ,
01074 stats.num_rexmits);
01075
01076
01077 trace("IL %.9f _%d_ Sum-Response-List-Size Created: %d Retired: %d",
01078 CURRENT_TIME, ipaddr,
01079 stats.sum_response_list_sz ,
01080 stats.sum_rexmitable_retired_response_sz);
01081
01082 trace("IL %.9f _%d_ Holes Created: %d Retired: %d ReSeqQ-Drops: %d ReSeqQ-Recvd: %d",
01083 CURRENT_TIME, ipaddr,
01084 stats.num_holes_created ,
01085 stats.num_holes_retired ,
01086 stats.num_reseqq_drops,
01087 stats.num_recvd_from_queue);
01088
01089 trace("IL %.9f _%d_ Unexpected-Acks: %d Out-Win-Obj: %d Out-Order-Obj: %d In-Order-Obj: %d", CURRENT_TIME, ipaddr,
01090 stats.num_unexpected_acks ,
01091 stats.num_out_of_window_objs ,
01092 stats.num_out_of_order_objs ,
01093 stats.num_in_order_objs);
01094 }