imep.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:29k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *      This product includes software developed by the Computer Systems
  17.  *      Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * Ported from CMU/Monarch's code 
  35.  *
  36.  * $Header: /cvsroot/nsnam/ns-2/imep/imep.cc,v 1.12 2006/02/21 15:20:18 mahrenho Exp $
  37.  */
  38. #include <packet.h>
  39. #include <ip.h>
  40. #include <random.h>
  41. #include <cmu-trace.h>
  42. #include <imep/imep.h>
  43. #define CURRENT_TIME Scheduler::instance().clock()
  44. static const int verbose = 0;
  45. static const int imep_use_mac_callback = 1;
  46. // ======================================================================
  47. //   TCL Hooks
  48. // ======================================================================
  49. int hdr_imep::offset_;
  50. static class IMEPHeaderClass : public PacketHeaderClass {
  51. public:
  52.         IMEPHeaderClass() : PacketHeaderClass("PacketHeader/IMEP",
  53.       IMEP_HDR_LEN) { 
  54. bind_offset(&hdr_imep::offset_);
  55. } class_imep_hdr;
  56. static class agentIMEPclass : public TclClass {
  57. public:
  58. agentIMEPclass() : TclClass("Agent/IMEP") {}
  59. TclObject* create(int argc, const char*const* argv) {
  60. assert(argc == 5);
  61. return (new imepAgent((nsaddr_t) atoi(argv[4])));
  62. }
  63. } class_imepAgent;
  64. // ======================================================================
  65. // ======================================================================
  66. // MAC layer callback
  67. static void
  68. imep_failed_callback(Packet *p, void *arg)
  69. {
  70. if(imep_use_mac_callback)
  71. ((imepAgent*) arg)->imepPacketUndeliverable(p);
  72. else {
  73. Packet::free(p);
  74. // XXX: Should probably call a "drop" agent here
  75. }
  76. }
  77. imepAgent::imepAgent(nsaddr_t index) :
  78. Agent(PT_TORA),
  79. beaconTimer(this, BEACON_TIMER),
  80. controlTimer(this, CONTROL_TIMER),
  81. rexmitTimer(this, REXMIT_TIMER),
  82. incomingTimer(this, INCOMING_TIMER),
  83. ipaddr(index),
  84. incomingQ(this, index)
  85. {
  86. controlSequence = 0;
  87. recvtarget_ = sendtarget_ = 0;
  88. logtarget_ = 0;
  89. rtagent_ = 0;
  90. LIST_INIT(&imepLinkHead);
  91. bzero(&stats, sizeof(stats));
  92. }
  93. int
  94. imepAgent::command(int argc, const char*const* argv)
  95. {
  96. if(argc == 2) {
  97. if(strcmp(argv[1], "start") == 0) {
  98. beaconTimer.start(BEACON_PERIOD);
  99. return TCL_OK;
  100. else if(strcmp(argv[1], "reset") == 0) {
  101.         Terminate();
  102. return TCL_OK;
  103. }
  104. } else if (argc == 3) {
  105. if (strcmp(argv[1], "recvtarget") == 0) {
  106. recvtarget_ = (NsObject*) TclObject::lookup(argv[2]);
  107.                         assert(recvtarget_);
  108. return (TCL_OK);
  109. }
  110. else if (strcmp(argv[1], "sendtarget") == 0) {
  111. sendtarget_ = (NsObject*) TclObject::lookup(argv[2]);
  112.                         assert(sendtarget_);
  113. return (TCL_OK);
  114. }
  115. else if (strcmp(argv[1], "rtagent") == 0) {
  116. rtagent_ = (rtAgent*) TclObject::lookup(argv[2]);
  117. assert(rtagent_);
  118. return (TCL_OK);
  119. }
  120. else if(strcmp(argv[1], "log-target") == 0) {
  121. logtarget_ = (Trace*) TclObject::lookup(argv[2]);
  122. assert(logtarget_);
  123. return (TCL_OK);
  124. }
  125. }
  126. return Agent::command(argc, argv);
  127. }
  128. imepLink*
  129. imepAgent::findLink(nsaddr_t index)
  130. {
  131. imepLink *l;
  132. for(l = imepLinkHead.lh_first; l; l = l->link.le_next) {
  133. if(l->index() == index)
  134. return l;
  135. }
  136. return 0;
  137. }
  138. Packet*
  139. imepAgent::findObjectSequence(u_int8_t seqno)
  140. {
  141.         Packet *p;
  142. ReXmitQIter iter = rexmitq.iter();
  143. struct imep_object_block *ob;
  144. while ((p = iter.next())) {
  145. ob = findObjectBlock(p);
  146. if(ob == 0) continue;
  147. // no OBJECT block
  148. if(ob->ob_sequence != seqno) continue;
  149. // wrong SEQUENCE number
  150. if(ob->ob_num_responses <=0) {
  151. fprintf(stderr,
  152. "imepAgent::findObjectSequence: "
  153. "Object Block without response listn");
  154. abort();
  155. }
  156. return p;
  157. }
  158. /* abort();
  159. this isn't an abort condition.  consider an ack arriving 
  160. for a pkt after it's timed out from the rexmit q -dam */
  161. return NULL;
  162. }
  163. void
  164. imepAgent::removeObjectResponse(Packet *p, nsaddr_t index)
  165. {
  166. struct imep_object_block *ob = findObjectBlock(p);
  167. struct imep_response *r = findResponseList(p);
  168. struct imep_response *r0;
  169. struct hdr_cmn *ch = HDR_CMN(p);
  170. int i;
  171. assert(ob && r);
  172. for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) {
  173. if(INT32_T(r0->resp_ipaddr) == index)
  174. break;
  175. }
  176. if(INT32_T(r0->resp_ipaddr) != index) {
  177.   if (verbose) 
  178.     trace("T %.9f _%d_ dup ack(?) from %d", CURRENT_TIME, ipaddr, index);
  179.   return;
  180. }
  181. if(ob->ob_num_responses == 1) {
  182.         if (verbose) 
  183.            trace("T %.9f _%d_ remove from reXq pkt %d", 
  184.          CURRENT_TIME, ipaddr, ch->uid());
  185.         rexmitq.remove(p);
  186.         Packet::free(p);
  187. stats.num_rexmitable_fully_acked++;
  188. } else {
  189. // find the last "response"
  190.            r += (ob->ob_num_responses - 1);
  191. if(r != r0) {
  192. INT32_T(r0->resp_ipaddr) = INT32_T(r->resp_ipaddr);
  193. }
  194. ob->ob_num_responses -= 1;
  195.         if (verbose) 
  196.            trace("T %.9f _%d_ remove %d from resp list %d (%d left) RL %s", 
  197.          CURRENT_TIME, ipaddr, index, ch->uid(), ob->ob_num_responses, 
  198.  dumpResponseList(p));
  199. struct hdr_imep *im = HDR_IMEP(p);
  200. ch->size() -= sizeof(struct imep_response);
  201. U_INT16_T(im->imep_length) -= sizeof(struct imep_response);
  202. }
  203. }
  204. void 
  205. imepAgent::purgeReXmitQ(nsaddr_t index)
  206.   // remove index from any response lists in the rexmit q
  207. {
  208.   Packet *p;
  209.   ReXmitQIter iter = rexmitq.iter();
  210.   struct imep_object_block *ob;
  211.   struct imep_response *r,*r0;
  212.   struct hdr_cmn *ch;
  213.   int i;
  214.   if (verbose)
  215.     trace("T %.9f _%d_ purge %d from reXmit Q", 
  216.   CURRENT_TIME, ipaddr, index);
  217.   while ((p = iter.next())) {
  218.     ob = findObjectBlock(p);
  219.     if(ob == 0) assert(0); // should always be an object block
  220.     r = findResponseList(p);
  221.     ch = HDR_CMN(p);
  222.     assert(ob && r);
  223.     for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) {
  224.       if(INT32_T(r0->resp_ipaddr) == index)
  225. break;
  226.     }
  227.     if(INT32_T(r0->resp_ipaddr) != index) {
  228.       continue; // index not in this response list
  229.     }
  230.     if(ob->ob_num_responses == 1) {
  231.       if (verbose) 
  232. trace("T %.9f _%d_ remove from reXq pkt %d",
  233.       CURRENT_TIME, ipaddr, ch->uid());
  234.       rexmitq.remove(p);
  235.       drop(p, DROP_RTR_QTIMEOUT);
  236.       stats.num_rexmitable_fully_acked++;
  237.     } else {
  238.       // find the last "response"
  239.       r += (ob->ob_num_responses - 1);
  240.       if(r != r0) {
  241. INT32_T(r0->resp_ipaddr) = INT32_T(r->resp_ipaddr);
  242.       }
  243.       ob->ob_num_responses -= 1;
  244.       if (verbose) 
  245. trace("T %.9f _%d_ purge %d from resp list %d (%d left) RL %s", 
  246.       CURRENT_TIME, ipaddr, index, ch->uid(), ob->ob_num_responses, 
  247.       dumpResponseList(p));
  248.       struct hdr_imep *im = HDR_IMEP(p);
  249.       ch->size() -= sizeof(struct imep_response);
  250.       U_INT16_T(im->imep_length) -= sizeof(struct imep_response);
  251.     }
  252.   }
  253. }
  254. // ======================================================================
  255. // ======================================================================
  256. // Timer Handling Functions
  257. void
  258. imepAgent::handlerTimer(imepTimerType t)
  259. {
  260. switch(t) {
  261. case BEACON_TIMER:
  262. handlerBeaconTimer();
  263. break;
  264. case CONTROL_TIMER:
  265. handlerControlTimer();
  266. break;
  267. case REXMIT_TIMER:
  268.         handlerReXmitTimer();
  269. break;
  270. case INCOMING_TIMER:
  271. handlerIncomingTimer();
  272. break;
  273. default:
  274. abort();
  275. }
  276. }
  277. void
  278. imepAgent::handlerBeaconTimer(void)
  279. {
  280.   imepLink *l;
  281.   // garbage collect old links
  282.   purgeLink();
  283.   if (verbose) log_neighbor_list();
  284.   /* aside from the debugging asserts, handleControlTimer will generate a
  285.    ``beacon'' packet if there are no objects pending, so we could
  286.    just call it.  Since we have sendBeacon() laying around, though, 
  287.    I'll call it and leave the debugging asserts in handleControlTimer()
  288.    The packet generated by handlerControlTimer is a beacon equivelent, 
  289.    so we don't need to generate a beacon. */
  290.   if (controlTimer.busy() || helloQueue.length() > 0)
  291.     { // a control timer is pending or there's left over Hello's in the queue, 
  292.       // but we're about to service all pending acks, hellos, and objects now, 
  293.       // so cancel the timer
  294.       if (controlTimer.busy()) controlTimer.cancel();
  295.       handlerControlTimer();
  296.     }
  297.   else 
  298.     { // all the Hellos we had to send out during the last BEACON_PERIOD
  299.       // went out.  Assuming there were some, they were beacon equivelent,
  300.       // and we don't need to send a beacon now.  If there were none, beacon
  301.       if (NULL == imepLinkHead.lh_first) sendBeacon();
  302.       // this is a touch conservative, since if there were hellos that went out
  303.       // but their links were down'd by purgeLink, we'll still beacon.
  304.       // But, if we *have*no* adjacencies, we should do something to get some
  305.     }
  306.   /* Send a hello to all our IN adjacencies (everyone we've heard a
  307.      packet from). This loads up the helloQueue with all the hellos that
  308.      that need to go out sometime in the next BEACON_PERIOD before the
  309.      beaconTimer goes off, but doesn't start the controlTimer.  If a
  310.      control packet is sent for some other reason, the hellos will ride out
  311.      for free, otherwise they'll go out when the beacon timer goes off.
  312.      */
  313.   int busy_before_hello_load = controlTimer.busy();
  314.   for(l = imepLinkHead.lh_first; l; l = l->link.le_next) 
  315.     {
  316.       if (l->status() & LINK_IN) sendHello(l->index());
  317.     }
  318.   if (!busy_before_hello_load && controlTimer.busy()) controlTimer.cancel();
  319.   // restart the beacon timer
  320.   beaconTimer.start(BEACON_PERIOD);
  321. }
  322. // transmit all queued ACKs, HELLOs, and OBJECTs.
  323. void
  324. imepAgent::handlerControlTimer(void)
  325. {
  326. Packet *p;
  327. int num_acks = ackQueue.length();
  328. int num_hellos = helloQueue.length();
  329. int num_objects = objectQueue.length();
  330. MAKE_PACKET:
  331. assert(num_acks + num_hellos + num_objects > 0);
  332. // now have to aggregate multiple control packets
  333. p = Packet::alloc();
  334. struct hdr_cmn *ch = HDR_CMN(p);
  335. struct hdr_ip *ih = HDR_IP(p);
  336. struct hdr_imep *im = HDR_IMEP(p);
  337. ch->uid() = uidcnt_++;
  338. ch->ptype() = PT_IMEP;
  339. ch->size() = BEACON_HDR_LEN;
  340. ch->iface() = -2;
  341. ch->error() = 0;
  342. ch->addr_type() = NS_AF_NONE;
  343.         ch->prev_hop_ = ipaddr;
  344. ih->saddr() = ipaddr;
  345. ih->daddr() = IP_BROADCAST;
  346. ih->sport() = RT_PORT;
  347. ih->dport() = RT_PORT;
  348. ih->ttl_ = 1;
  349. im->imep_version = IMEP_VERSION;
  350. im->imep_block_flags = 0x00;
  351. U_INT16_T(im->imep_length) = sizeof(struct hdr_imep);
  352. aggregateAckBlock(p);
  353. aggregateHelloBlock(p);
  354. aggregateObjectBlock(p);
  355. imep_output(p);
  356. num_acks = ackQueue.length();
  357. num_hellos = helloQueue.length();
  358. num_objects = objectQueue.length();
  359. if (num_acks + num_hellos + num_objects > 0)
  360.   { // not done yet...
  361.     if (verbose) 
  362.       trace("T %.9f _%d_ imep pkt overflow %d %d %d leftover",
  363.     CURRENT_TIME, ipaddr, num_acks, num_hellos, num_objects);
  364.     goto MAKE_PACKET;
  365.   }
  366. // don't need to restart the controlTimer because the arrival of
  367. // the next packet from an ULP will start it.
  368. }
  369. void
  370. imepAgent::handlerReXmitTimer() 
  371. {
  372.   Packet *p;
  373.   Time rexat;
  374.   int num_xmits_left;
  375.   rexmitq.peekHead(&rexat, &p, &num_xmits_left);
  376.   if (NULL == p) return;  //  no more pkts on queue
  377.   struct hdr_cmn *ch = HDR_CMN(p);
  378.   if (0 == num_xmits_left)
  379.     {
  380.       if (verbose) 
  381. {
  382.   trace("T %.9f _%d_ rexmit timed out %d RL:%s",
  383. CURRENT_TIME, ipaddr, ch->uid(), dumpResponseList(p));
  384. }
  385.         struct imep_object_block *ob = findObjectBlock(p);
  386. struct imep_response *r = findResponseList(p);
  387. int i;
  388. for(i = 0; i < ob->ob_num_responses; i++, r++) 
  389.   {
  390.     if (verbose) trace("T %.9f _%d_ punting neighbor %d",
  391.        CURRENT_TIME, ipaddr, INT32_T(r->resp_ipaddr));
  392.     imepSetLinkDownStatus(INT32_T(r->resp_ipaddr));
  393.   }
  394.       stats.num_rexmitable_retired++;
  395.       stats.sum_rexmitable_retired_response_sz += ob->ob_num_responses;
  396.       // don't need to explicitly remove p from q and drop it, since
  397.       // by downing all the links on it's response list, it'll have bee
  398.       // dropped anyway
  399.       // rexmitq.removeHead();
  400.       // drop(p, DROP_RTR_QTIMEOUT);
  401.     }
  402.   else if (rexat <= CURRENT_TIME) 
  403.     {
  404.       if (verbose) 
  405. trace("T %.9f _%d_ rexmit %d as %d",
  406.       CURRENT_TIME, ipaddr, ch->uid(), uidcnt_);
  407.       ch->uid() = uidcnt_++;
  408.       imep_output(p->copy());
  409.       num_xmits_left--;
  410.       rexmitq.removeHead(); // take it off the queue and reinsert it
  411.       rexmitq.insert(CURRENT_TIME + RETRANS_PERIOD, p, num_xmits_left);
  412.       stats.num_rexmits++;
  413.     }  
  414.   
  415.   // reschedule the timer
  416.   rexmitq.peekHead(&rexat, &p, &num_xmits_left);
  417.   if (NULL == p) return;  //  no more pkts on queue
  418.   if (verbose) trace("T %.9f _%d_ rexmit trigger again for %d at %.9f (in %.9f)",
  419.      CURRENT_TIME, ipaddr, ch->uid(), rexat, rexat - CURRENT_TIME );
  420.   rexmitTimer.start(rexat - CURRENT_TIME);
  421. }
  422. void
  423. imepAgent::handlerIncomingTimer()
  424. {
  425. Packet *p;
  426. u_int32_t s;
  427. double expire;
  428. int index;
  429. if (verbose) trace("T %.9f _%d_ inorder - timer expired",
  430.       CURRENT_TIME, ipaddr);
  431. incomingQ.dumpAll();
  432. while((p = incomingQ.getNextPacket(s))) {
  433. stats.num_holes_retired++;
  434. index = HDR_IP(p)->saddr();
  435. imepLink *l = findLink(index);
  436. assert(l);  // if there's no link entry, then the incoming
  437. // q should have been cleared, when the link entry was destroyed
  438. if(verbose) 
  439.   trace("T %.9f _%d_ inorder - src %d hole retired seq %d -> %d",
  440. CURRENT_TIME, ipaddr, index, l->lastSeq(), s);
  441. /* tell ULP that we've effectively broken our link to 
  442.    neighbor by retiring the hole and accepting the deletion.
  443.    since we don't do this till at least MAX_REXMIT_TIME after
  444.    receiving the out of seq packet, we're sure the packet's sender
  445.    must have timed us out when we didn't ack their packet.
  446.    can't call imepLinkDown b/c it'll purge the reseq q */
  447. rtagent_->rtNotifyLinkDN(index);
  448. stats.delete_neighbor3++;
  449. rtagent_->rtNotifyLinkUP(index);
  450. stats.new_neighbor++;
  451. if (verbose)
  452.   trace("T %.9f _%d_ inorder - src %d seq %d (timer delivery)",
  453. CURRENT_TIME, ipaddr, index, s);
  454. l->lastSeq() = s;  // advance sequence number for this neighbor
  455. stats.num_recvd_from_queue++;
  456. imep_object_process(p);
  457. Packet::free(p);
  458. // now deliver as many in sequence packets to ULP as possible
  459. Packet *p0;
  460. while((p0 = incomingQ.getPacket(index, l->lastSeq() + 1)))
  461.   {
  462.     if (verbose)
  463.       trace("T %.9f _%d_ inorder - src %d seq %d (chain" 
  464.     " timer delivery)", CURRENT_TIME, ipaddr, 
  465.     HDR_IP(p0)->saddr(), l->lastSeq() + 1);
  466.     l->lastSeq() += 1;
  467.     stats.num_recvd_from_queue++;
  468.     imep_object_process(p0);
  469.     Packet::free(p0);
  470.   }
  471. }
  472. if((expire = incomingQ.getNextExpire()) != 0.0) {
  473. assert(expire > CURRENT_TIME);
  474. if (verbose)
  475.   trace("T %.9f _%d_ inorder - timer started (delay %.9f)",
  476. CURRENT_TIME, ipaddr, expire - CURRENT_TIME);
  477.         incomingTimer.start(expire - CURRENT_TIME);
  478. }
  479. }
  480. //////////////////////////////////////////////////////////////////////
  481. void
  482. imepAgent::scheduleReXmit(Packet *p)
  483. {
  484.   rexmitq.insert(CURRENT_TIME + RETRANS_PERIOD, p, MAX_REXMITS);
  485.   
  486.   // start the timer
  487.   if (!rexmitTimer.busy()) rexmitTimer.start(RETRANS_PERIOD);    
  488. }
  489. void
  490. imepAgent::scheduleIncoming(Packet *p, u_int32_t s)
  491. {
  492. struct hdr_ip *ip = HDR_IP(p);
  493. incomingQ.addEntry(ip->saddr(), CURRENT_TIME + MAX_RETRANS_TIME, s, p);
  494.   
  495. // start the timer
  496. if (!incomingTimer.busy()) {
  497. if (verbose) 
  498.   trace("T %.9f _%d_ inorder - timer started",
  499. CURRENT_TIME, ipaddr);
  500. incomingTimer.start(MAX_RETRANS_TIME);
  501. }
  502. }
  503. // ======================================================================
  504. // Packet Processing Functions
  505. void
  506. imepAgent::recv(Packet *p, Handler *)
  507. {
  508. //struct hdr_ip *ih = HDR_IP(p);
  509. struct hdr_cmn *ch = HDR_CMN(p);
  510. assert(initialized());
  511. if(ch->prev_hop_ == ipaddr) {
  512.   // I hate all uses of prev_hop, but the only other way to
  513.   // do this test is by checking for a nonNULL handler (like 
  514.   // mac-801_11.cc does), which would
  515.   // require changing tora to send out pkts with a non 0 hndler
  516.   // -dam
  517. recv_outgoing(p);
  518. } else {
  519.         recv_incoming(p);
  520. }
  521. }
  522. void
  523. imepAgent::recv_outgoing(Packet *p)
  524. {
  525. struct hdr_cmn *ch = HDR_CMN(p);
  526. struct hdr_ip *ip = HDR_IP(p);
  527. if(DATA_PACKET(ch->ptype())) {
  528. imep_output(p);
  529. return;
  530. }
  531. if(ip->daddr() != (nsaddr_t) IP_BROADCAST) {
  532. fprintf(stderr, "IP dst is unicast - not encapsulatingn");
  533. imep_output(p);
  534. return;
  535. }
  536. assert(ch->ptype() == PT_TORA);
  537. // XXX: for debugging purposes - IMEP supports other object types
  538. objectQueue.enque(p);
  539. // this queue is a queue of "packets" passed down from the 
  540. // upper layer routing protocols that IMEP will buffer and try
  541. // to aggregate before transmitting.  Although these are valid
  542. // packets, they must not be transmitted before encaspulating
  543. // them in an IMEP packet to ensure reliability.
  544. double send_delay = MIN_TRANSMIT_WAIT_TIME_HIGHP
  545.   + ((MAX_TRANSMIT_WAIT_TIME_HIGHP - MIN_TRANSMIT_WAIT_TIME_HIGHP)
  546.      * Random::uniform());
  547. if (controlTimer.busy() == 0) 
  548.   {
  549.     controlTimer.start(send_delay);
  550.   } 
  551. else if (controlTimer.timeLeft() > send_delay) 
  552.   {
  553.     controlTimer.cancel();
  554.     controlTimer.start(send_delay);
  555.   }
  556. }
  557. void
  558. imepAgent::recv_incoming(Packet *p)
  559. {
  560. struct hdr_cmn *ch = HDR_CMN(p);
  561. struct hdr_ip *ih = HDR_IP(p);
  562. struct hdr_imep *im = HDR_IMEP(p);
  563. if(DATA_PACKET(ch->ptype())) {
  564. imep_input(p);
  565. return;
  566. }
  567. // if it's a data packet, the ip->src could be from far away,
  568. // so we can't use it for link indications.  If we RARPd the 
  569. // MAC source addr, we could use that...
  570. imepSetLinkInStatus(ih->saddr());
  571. // XXX: this could be done at the MAC layer.  In fact, I will 
  572. // augment the IEEE 802.11 layer so that the receipt of an
  573. // ACK confirms bidirectional status. -josh
  574. // hasn't actually be done. seems unlikely to be of help, and is
  575. // fairly hard to do. -dam 8/19/98
  576.         assert(ch->ptype() == PT_IMEP);
  577. assert(im->imep_version == IMEP_VERSION);
  578. if(im->imep_block_flags == 0) {
  579. imep_beacon_input(p);
  580. Packet::free(p);
  581. return;
  582. }
  583. if(im->imep_block_flags & BLOCK_FLAG_ACK)
  584. imep_ack_input(p);
  585. if(im->imep_block_flags & BLOCK_FLAG_HELLO)
  586. imep_hello_input(p);
  587. if(im->imep_block_flags & BLOCK_FLAG_OBJECT) {
  588. imep_object_input(p);
  589. // each upper layer object will be decapsulated and
  590. // placed into its own packet before being passed
  591. // to the upper layer.  This provides total transparency
  592. // to the upper layer.
  593. }
  594. Packet::free(p);
  595. }
  596. void
  597. imepAgent::imep_beacon_input(Packet *p)
  598. {
  599. struct hdr_ip *ip = HDR_IP(p);
  600. sendHello(ip->saddr());
  601. }
  602. // If there is an ACK for us we need to (1) removed the sender
  603. // of the ACK from the "ack list", and we need to update the
  604. // status of this neighbor to "BIDIRECTIONAL".
  605. void
  606. imepAgent::imep_ack_input(Packet *p)
  607. {
  608. struct hdr_ip *ih = HDR_IP(p);
  609. struct imep_ack_block *ab = findAckBlock(p);
  610. struct imep_ack *ack;
  611. assert(ab);
  612. ack = (struct imep_ack*) (ab + 1);
  613. // According to the IMEP specs, the ACK block (if it exists)
  614. // immediately follows the 3-byte IMEP header.
  615. for(int i = 0; i < ab->ab_num_acks; i++, ack++) {
  616. if(INT32_T(ack->ack_ipaddr) == ipaddr) {
  617. Packet *p0 = findObjectSequence(ack->ack_seqno);
  618. if (NULL == p0)
  619.   {
  620.     if(verbose) 
  621.       trace("T %.9f _%d_ %d acks seq %d : no obj"
  622.     " block", CURRENT_TIME, ipaddr, 
  623.     ih->saddr(), ack->ack_seqno);
  624.     stats.num_unexpected_acks++;
  625.     continue;
  626.   }
  627. removeObjectResponse(p0, ih->saddr());
  628. imepSetLinkBiStatus(ih->saddr());
  629. }
  630. }
  631. }
  632. void
  633. imepAgent::imep_hello_input(Packet *p)
  634. {
  635. struct hdr_ip *ip = HDR_IP(p);
  636. struct imep_hello_block *hb = findHelloBlock(p);
  637. struct imep_hello *hello;
  638. assert(hb);
  639. hello = (struct imep_hello*) (hb + 1);
  640. for(int i = 0; i < hb->hb_num_hellos; i++, hello++) {
  641. if(INT32_T(hello->hello_ipaddr) == ipaddr) {
  642. imepSetLinkBiStatus(ip->saddr());
  643. break;
  644. }
  645. }
  646. }
  647. void
  648. imepAgent::imep_object_input(Packet *p)
  649. {
  650. struct imep_object_block *ob;
  651. // First, send an ack for the object
  652. imep_ack_object(p);
  653. // now see what to do with the object
  654. ob = findObjectBlock(p);
  655. assert(ob);
  656. struct hdr_ip *iph = HDR_IP(p);
  657. imepLink *l = findLink(iph->saddr());
  658. assert(l);  // if we have an object, a link entry should already exist
  659. if (!l->lastSeqValid()) 
  660.   { // first object we've heard from this node
  661.     l->lastSeqValid() = 1;
  662.     l->lastSeq() = ob->ob_sequence - 1;
  663.     if (verbose)
  664.       trace("T %.9f _d_ first object from neighbor %d seq %d",
  665.     CURRENT_TIME, ipaddr, iph->saddr(), ob->ob_sequence);
  666.   }
  667. // This calc requires sequence number SEQ_GT() semantics
  668. // Life will be very bad if this calc isn't actually done in 
  669. // a register the size of the sequence number space
  670. int8_t reg = (int8_t) ob->ob_sequence - (int8_t) l->lastSeq();
  671. if(reg <= 0)
  672.   { // already passed this pkt up to ULP or declared it a permenant
  673.     // hole
  674.     if (verbose)
  675.       trace("T %.9f _%d_ from %d ignored seq %d (already heard)",
  676.     CURRENT_TIME, ipaddr, iph->saddr(), ob->ob_sequence);
  677.     stats.num_out_of_window_objs++;
  678.     return;
  679.   }
  680. if (verbose && reg > 1)
  681.   { // found a hole in the sequence number space...
  682.     trace("T %.9f _%d_ inorder - src %d seq %d out of order (%d expected)",
  683.   CURRENT_TIME, ipaddr, iph->saddr(),
  684.   ob->ob_sequence, l->lastSeq()+1);
  685.   }
  686. if (1 == reg)
  687.   { // ``fast path''
  688.     // got the expected next seq num
  689.     if (verbose)
  690.       trace("T %.9f _%d_ inorder - fastpath src %d seq %d (delivering)",
  691.     CURRENT_TIME, ipaddr, HDR_IP(p)->saddr(), ob->ob_sequence);
  692.     stats.num_in_order_objs++;
  693.     imep_object_process(p);
  694.     assert((u_int8_t)(l->lastSeq() + 1) == ob->ob_sequence);
  695.     l->lastSeq() = ob->ob_sequence;
  696.   }
  697. else
  698.   {
  699.     // put this packet on the resequencing queue
  700.     scheduleIncoming(p->copy(), ob->ob_sequence);
  701.     stats.num_out_of_order_objs++;
  702.   }
  703. // now deliver as many in-sequence packets to ULP as possible
  704. Packet *p0;
  705. while((p0 = incomingQ.getPacket(iph->saddr(), l->lastSeq() + 1)))
  706.   {
  707.     stats.num_recvd_from_queue++;
  708.     if (verbose)
  709.       trace("T %.9f _%d_ inorder - src %d seq %d (delivering)",
  710.     CURRENT_TIME, ipaddr, HDR_IP(p0)->saddr(), l->lastSeq() + 1);
  711.     l->lastSeq() += 1;
  712.     imep_object_process(p0);
  713.     Packet::free(p0);
  714.   }
  715. }
  716. void
  717. imepAgent::imep_object_process(Packet *p)
  718.   // hand the conents of any object in the pkt to the respective ULP
  719. {
  720.   struct imep_object_block *ob;
  721.   struct imep_object *object;
  722.   int i;
  723.   stats.num_object_pkts_recvd++;
  724.   ob = findObjectBlock(p);
  725.   assert(ob);
  726.   assert(ob->ob_protocol_type == PROTO_TORA); // XXX: more general later
  727.   object = (struct imep_object*) (ob + 1);
  728.   for(i = 0; i < ob->ob_num_objects; i++)
  729.     {
  730.       Packet *p0 = p->copy();
  731.       assert(object->o_length > 0); // sanity check
  732.       toraCreateHeader(p0,
  733.        ((char*) object) + IMEP_OBJECT_SIZE,
  734.        object->o_length);
  735.       imep_input(p0);
  736.       object = (struct imep_object*) ((char*) object + 
  737.              IMEP_OBJECT_SIZE + object->o_length);
  738.     }
  739. }
  740. void
  741. imepAgent::imep_ack_object(Packet *p)
  742.   // send an ack for the object in p, if any
  743. {
  744.   struct hdr_ip *iph = HDR_IP(p);
  745.   struct imep_object_block *ob;
  746.   struct imep_object *object;
  747.   int i;
  748.   ob = findObjectBlock(p);
  749.   if (!ob) return;
  750.   if (0 == ob->ob_num_responses) 
  751.     return;
  752.   if (31 == ob->ob_num_responses) 
  753.     { // a ``broadcast'' response list to which everyone replies
  754.       sendAck(iph->saddr(), ob->ob_sequence);
  755.       return;
  756.     }
  757.   object = (struct imep_object*) (ob + 1);
  758.   // walk the objects to find the response list
  759.   for(i = 0; i < ob->ob_num_objects; i++)
  760.     {
  761.       object = (struct imep_object*) ((char*) object + 
  762.       IMEP_OBJECT_SIZE +object->o_length);
  763.     }
  764.   struct imep_response *r = (struct imep_response*) object;
  765.   for (i = 0; i < ob->ob_num_responses; i++)
  766.     {
  767.       if (INT32_T(r->resp_ipaddr) == ipaddr)
  768. {
  769.   sendAck(iph->saddr(), ob->ob_sequence);
  770.   break;
  771. }
  772.       r = r + 1;
  773.     }
  774. }
  775. // ======================================================================
  776. // ======================================================================
  777. // Routines by which packets leave the IMEP object
  778. void
  779. imepAgent::imep_input(Packet *p)
  780. {
  781. recvtarget_->recv(p, (Handler*) 0);
  782. }
  783. void
  784. imepAgent::imep_output(Packet *p)
  785. {
  786. struct hdr_cmn *ch = HDR_CMN(p);
  787. if(imep_use_mac_callback) {
  788. ch->xmit_failure_ = imep_failed_callback;
  789. ch->xmit_failure_data_ = (void*) this;
  790. } else {
  791. ch->xmit_failure_ = 0;
  792. ch->xmit_failure_data_ = 0;
  793. }
  794. ch->xmit_reason_ = 0;
  795.   sendtarget_->recv(p, (Handler*) 0);
  796. }
  797. // ======================================================================
  798. // ======================================================================
  799. // Debugging routines
  800. void
  801. imepAgent::imep_dump_header(Packet *p)
  802. {
  803. struct hdr_imep *im = HDR_IMEP(p);
  804. fprintf(stderr,
  805. "imep_version: 0x%xn", im->imep_version);
  806. fprintf(stderr,
  807. "imep_block_flags: 0x%xn", im->imep_block_flags);
  808. fprintf(stderr,
  809. "imep_length: 0x%04xn", U_INT16_T(im->imep_length));
  810. Packet::dump_header(p, hdr_imep::offset_, 64);
  811. }
  812. void
  813. imepAgent::log_neighbor_list()
  814. {
  815. imepLink *l;
  816. int offset = 0;
  817.         if(! verbose ) return;
  818.         sprintf(logtarget_->pt_->buffer(),
  819.                 "T %.9f _%d_ neighbors: ", CURRENT_TIME, ipaddr);
  820. for(l = imepLinkHead.lh_first; l; l = l->link.le_next) {
  821.   offset = strlen(logtarget_->pt_->buffer());
  822.   sprintf(logtarget_->pt_->buffer() + offset,
  823.   "%d%c ", l->index(),
  824.   l->status() == LINK_BI ? '+' : 
  825.     (l->status() == LINK_IN ? '-' : 
  826.      (l->status() == LINK_OUT ? '|' : 'X')));
  827. }
  828.         logtarget_->pt_->dump();
  829. }
  830. void
  831. imepAgent::trace(char* fmt, ...)
  832. {
  833.   va_list ap;
  834.   
  835.   if (!logtarget_) return;
  836.   va_start(ap, fmt);
  837.   vsprintf(logtarget_->pt_->buffer(), fmt, ap);
  838.   logtarget_->pt_->dump();
  839.   va_end(ap);
  840. }
  841. char *
  842. imepAgent::dumpResponseList(Packet *p)
  843. {
  844.   static char buf[512];
  845.   char *ptr = buf;
  846.   struct imep_object_block *ob = findObjectBlock(p);
  847.   struct imep_response *r = findResponseList(p);
  848.   struct imep_response *r0;
  849.   int i;
  850.   for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) 
  851.     {
  852.       ptr += (int)sprintf(ptr,"%d ", INT32_T(r0->resp_ipaddr));
  853.     }
  854.   return buf;
  855. }
  856. void
  857. imepAgent::Terminate()
  858. {
  859.   trace("IL %.9f _%d_ Add-Adj: %d New-Neigh: %d Del-Neigh1: %d Del-Neigh2: %d Del-Neigh3: %d",
  860. CURRENT_TIME, ipaddr, 
  861. stats.new_in_adjacency,
  862. stats.new_neighbor      ,
  863. stats.delete_neighbor1      ,
  864. stats.delete_neighbor2,
  865. stats.delete_neighbor3);
  866.   trace("IL %.9f _%d_ Created QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr,
  867. stats.qry_objs_created      ,
  868. stats.upd_objs_created      ,
  869. stats.clr_objs_created);
  870.   trace("IL %.9f _%d_ Received QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr,
  871. stats.qry_objs_recvd      ,
  872. stats.upd_objs_recvd      ,
  873. stats.clr_objs_recvd);
  874.   trace("IL %.9f _%d_ Total-Obj-Created: %d Obj-Pkt-Created: %d Obj-Pkt-Recvd: %d",
  875. CURRENT_TIME, ipaddr,
  876. stats.num_objects_created      ,
  877. stats.num_object_pkts_created      ,
  878. stats.num_object_pkts_recvd);
  879.   trace("IL %.9f _%d_ Rexmit Pkts: %d Acked: %d Retired: %d Rexmits: %d",
  880. CURRENT_TIME, ipaddr,
  881. stats.num_rexmitable_pkts      ,
  882. stats.num_rexmitable_fully_acked      ,
  883. stats.num_rexmitable_retired      ,
  884. stats.num_rexmits);
  885.   trace("IL %.9f _%d_ Sum-Response-List-Size Created: %d Retired: %d",
  886. CURRENT_TIME, ipaddr,
  887. stats.sum_response_list_sz      ,
  888. stats.sum_rexmitable_retired_response_sz);
  889.   trace("IL %.9f _%d_ Holes Created: %d Retired: %d ReSeqQ-Drops: %d ReSeqQ-Recvd: %d",
  890. CURRENT_TIME, ipaddr,
  891. stats.num_holes_created      ,
  892. stats.num_holes_retired      ,
  893. stats.num_reseqq_drops,
  894. stats.num_recvd_from_queue);
  895.   trace("IL %.9f _%d_ Unexpected-Acks: %d Out-Win-Obj: %d Out-Order-Obj: %d In-Order-Obj: %d", CURRENT_TIME, ipaddr,
  896. stats.num_unexpected_acks      ,
  897. stats.num_out_of_window_objs      ,
  898. stats.num_out_of_order_objs      ,
  899. stats.num_in_order_objs);
  900. }