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

通讯编程

开发平台:

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.    dest_queue.cc
  37.    $Id: dest_queue.cc,v 1.2 1999/08/12 21:17:11 yaxu Exp $
  38.    
  39.    implement a group of resequencing queues.  one for each source of packets.
  40.    the name destination queue is a misnomer.
  41.    */
  42. #include <imep/dest_queue.h>
  43. #ifdef TEST_ONLY
  44. #include <stdio.h>
  45. #else
  46. #include <imep/imep.h>
  47. #endif
  48. #ifndef TEST_ONLY
  49. #define CURRENT_TIME Scheduler::instance().clock()
  50. #else
  51. extern double CURRENT_TIME;
  52. #endif
  53. static const int verbose = 0;
  54. //////////////////////////////////////////////////////////////////////
  55. // Transmission Queue Entry
  56. txent::txent(double e, u_int32_t s, Packet *p)
  57. {
  58. expire_ = e;
  59. seqno_ = s;
  60. pkt_ = p;
  61. }
  62. //////////////////////////////////////////////////////////////////////
  63. // Destination Queue Entry
  64. dstent::dstent(nsaddr_t index)
  65. {
  66. LIST_INIT(&txentHead);
  67. ipaddr_ = index;
  68. seqno_ = ILLEGAL_SEQ;
  69. }
  70. static int
  71. SEQ_GT(u_int8_t a, u_int8_t b)
  72. {
  73.   int8_t reg = (int8_t)a - (int8_t) b;
  74.   return reg > 0;
  75. }
  76. void
  77. dstent::addEntry(double e, u_int32_t s, Packet *p)
  78. {
  79. txent *t, *u, *v = 0;
  80. if((t = findEntry(s)) == 0) {
  81. t = new txent(e, s, p);
  82. assert(t);
  83. for(u = txentHead.lh_first; u; u = u->link.le_next) {
  84. if(SEQ_GT(u->seqno(), s))
  85.   break;
  86. v = u;
  87. }
  88. if(u == 0 && v == 0) {
  89. LIST_INSERT_HEAD(&txentHead, t, link);
  90. } else if(u) {
  91. LIST_INSERT_BEFORE(u, t, link);
  92. } else {
  93. assert(v);
  94. LIST_INSERT_AFTER(v, t, link);
  95. }
  96. } else {
  97. Packet::free(p);
  98. // already have a copy of this packet
  99. }
  100. #ifdef  DEBUG
  101. // verify that I did not fuck up...
  102. u_int32_t max = 0;
  103. for(t = txentHead.lh_first; t; t = t->link.le_next) {
  104. if(max == 0)
  105. max = t->seqno();
  106. else {
  107. assert(t->seqno() > max);
  108. max = t->seqno();
  109. }
  110. #endif
  111. }  
  112. void
  113. dstent::delEntry(txent *t)
  114. {
  115. LIST_REMOVE(t, link);
  116. delete t;
  117. }
  118. txent*
  119. dstent::findEntry(u_int32_t s)
  120. {
  121. txent *t;
  122. for(t = txentHead.lh_first; t; t = t->link.le_next) {
  123. if(t->seqno() == s)
  124. return t;
  125. }
  126. return 0;
  127. }
  128. txent*
  129. dstent::findFirstEntry(void)
  130. {
  131. return txentHead.lh_first;
  132. // this gives the minimum sequence number for the destination
  133. }
  134. //////////////////////////////////////////////////////////////////////
  135. // Destination Queue
  136. dstQueue::dstQueue(imepAgent *a, nsaddr_t index) : agent_(a), ipaddr_(index)
  137. {
  138. LIST_INIT(&dstentHead);
  139. }
  140. void
  141. dstQueue::addEntry(nsaddr_t dst, double e, u_int32_t s, Packet *p)
  142. {
  143. dstent *t;
  144. if((t = findEntry(dst)) == 0) {
  145. t = new dstent(dst);
  146. assert(t);
  147. LIST_INSERT_HEAD(&dstentHead, t, link);
  148. }
  149. if (NULL == t->txentHead.lh_first) agent_->stats.num_holes_created++;
  150. t->addEntry(e, s, p);
  151. }
  152. dstent*
  153. dstQueue::findEntry(nsaddr_t dst)
  154. {
  155. dstent *t;
  156. for(t = dstentHead.lh_first; t; t = t->link.le_next) {
  157. if(t->ipaddr() == dst)
  158. return t;
  159. }
  160. return 0;
  161. }
  162. //////////////////////////////////////////////////////////////////////
  163. //////////////////////////////////////////////////////////////////////
  164. Packet*
  165. dstQueue::getPacket(nsaddr_t dst, u_int32_t seqno)
  166. {
  167. dstent *d;
  168. txent *t;
  169. for(d = dstentHead.lh_first; d; d = d->link.le_next) {
  170. if(d->ipaddr() == dst)
  171. break;
  172. }
  173. if(d && (t = d->findEntry(seqno))) {
  174. Packet *p = t->pkt();
  175. d->delEntry(t);
  176. // make sure packets come out in increasing order only
  177. // int8_t reg = (int8_t) seqno - (int8_t) d->seqno();
  178. //assert(reg > 0); // SEQ_GT(seqno, d->seqno())
  179. //d->seqno() = seqno; 
  180. return p;
  181. }
  182. return 0;
  183. }
  184. double
  185. dstQueue::getNextExpire()
  186. {
  187. dstent *t;
  188. Time min = 0.0;
  189. for(t = dstentHead.lh_first; t; t = t->link.le_next) {
  190. Time texp = t->expire(); // computed by traversing a list
  191. if(min == 0.0 || (texp && texp < min))
  192. min = texp;
  193. }
  194. if (verbose)
  195.   agent_->trace("T %.9f _%d_ dest_queue -  getNextExpire is %.9f",
  196. CURRENT_TIME, ipaddr_, min);
  197. return min;
  198. }
  199. Packet*
  200. dstQueue::getNextPacket(u_int32_t& s)
  201. {
  202. dstent *d;
  203. for(d = dstentHead.lh_first; d; d = d->link.le_next) {
  204.   txent *t = d->findFirstEntry();
  205.   if (t == 0) 
  206.     {
  207.       d->seqno() = ILLEGAL_SEQ;
  208.       continue; // no packets here
  209.     }
  210.   Time texp = d->expire();
  211.   assert(texp);
  212. #ifdef TEST_ONLY
  213.   fprintf(stderr,
  214.   "IN:td->expire: %f, d->seqno: %d, t->expire: %f, t->seqno: %dn",
  215.   d->expire(), d->seqno(), t->expire(), t->seqno());
  216. #endif
  217.   if (texp > CURRENT_TIME && d->seqno() == ILLEGAL_SEQ) continue;
  218.   if (t->expire() <= CURRENT_TIME)
  219.     { // remember this seq as starting a chain we can pull off
  220.       d->seqno() = t->seqno();
  221.     }
  222.   else if (d->seqno() != ILLEGAL_SEQ && t->seqno() != (u_int8_t) (d->seqno() + 1))
  223.     { // the next pkt isn't part of the chain we were pulling off
  224.       // stop pulling off packets
  225.       d->seqno() = ILLEGAL_SEQ;
  226.       continue;
  227.     }
  228.       Packet *p = t->pkt();
  229.     assert(p);
  230.     s = t->seqno();
  231. #ifdef TEST_ONLY
  232.     fprintf(stderr, "t%s: returning seqno: %dn",
  233.     __FUNCTION__, s);
  234. #endif
  235.     if (d->seqno() != ILLEGAL_SEQ) 
  236.       { // advance d->seqno() along the chain
  237. d->seqno() = t->seqno();
  238.       }
  239.     
  240.     d->delEntry(t);
  241. #ifdef TEST_ONLY
  242.   fprintf(stderr,
  243.   "OUT:td->expire: %f, d->seqno: %d, t->expire: %f, t->seqno: %dn",
  244.   d->expire(), d->seqno(), t->expire(), t->seqno());
  245. #endif
  246.     return p;
  247. }
  248. return 0;
  249. }
  250. void 
  251. dstQueue::deleteDst(nsaddr_t dst)
  252. {
  253.   dstent *d;
  254.   txent *t;
  255.   
  256.   if (verbose)
  257.     agent_->trace("T %.9f _%d_ purge dstQ id %d",
  258.   CURRENT_TIME, ipaddr_, dst);
  259.   for(d = dstentHead.lh_first; d; d = d->link.le_next) 
  260.     {
  261.       if(d->ipaddr() == dst)
  262. break;
  263.     }
  264.   if (!d) return;
  265.   while ((t = d->findFirstEntry()))
  266.     {
  267.       Packet *p = t->pkt();
  268.       if (verbose)
  269. agent_->trace("T %.9f _%d_ dstQ id %d delete seq %d",
  270.       CURRENT_TIME, ipaddr_, dst, t->seqno());
  271.       Packet::free(p);
  272.       d->delEntry(t); 
  273.       agent_->stats.num_reseqq_drops++;
  274.     }
  275.   LIST_REMOVE(d,link);
  276.   delete d;
  277. }
  278. void
  279. dstQueue::dumpAll()
  280. {
  281. dstent *t;
  282. for(t = dstentHead.lh_first; t; t = t->link.le_next) {
  283.   if (verbose)
  284. agent_->trace("T %.9f _%d_ dest_queue - src %d expire %.9f seqno %d",
  285.       CURRENT_TIME, ipaddr_, t->ipaddr(), t->expire(), t->seqno());
  286. txent *u = t->findFirstEntry();
  287. for(;u; u = u->link.le_next) {
  288.   if(verbose)
  289.     agent_->trace("T %.9f _%d_ dest_queue - src %d seq %d expire %.9f",
  290.   CURRENT_TIME, ipaddr_, t->ipaddr(),
  291.   u->seqno(), u->expire());
  292. }
  293. }
  294. }