Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

dest_queue.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Computer Systems
00017  *      Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 /* Ported from CMU/Monarch's code*/
00035 
00036 /* 
00037    dest_queue.cc
00038    $Id: dest_queue.cc,v 1.2 1999/08/12 21:17:11 yaxu Exp $
00039    
00040    implement a group of resequencing queues.  one for each source of packets.
00041    the name destination queue is a misnomer.
00042    */
00043 
00044 #include <imep/dest_queue.h>
00045 #ifdef TEST_ONLY
00046 #include <stdio.h>
00047 #else
00048 #include <imep/imep.h>
00049 #endif
00050 #ifndef TEST_ONLY
00051 #define CURRENT_TIME Scheduler::instance().clock()
00052 #else
00053 extern double CURRENT_TIME;
00054 #endif
00055 
00056 
00057 static const int verbose = 0;
00058 
00060 // Transmission Queue Entry
00061 txent::txent(double e, u_int32_t s, Packet *p)
00062 {
00063         expire_ = e;
00064         seqno_ = s;
00065         pkt_ = p;
00066 }
00067 
00069 // Destination Queue Entry
00070 dstent::dstent(nsaddr_t index)
00071 {
00072         LIST_INIT(&txentHead);
00073         ipaddr_ = index;
00074         seqno_ = ILLEGAL_SEQ;
00075 }
00076 
00077 static int
00078 SEQ_GT(u_int8_t a, u_int8_t b)
00079 {
00080   int8_t reg = (int8_t)a - (int8_t) b;
00081   return reg > 0;
00082 }
00083         
00084 void
00085 dstent::addEntry(double e, u_int32_t s, Packet *p)
00086 {
00087         txent *t, *u, *v = 0;
00088 
00089         if((t = findEntry(s)) == 0) {
00090                 t = new txent(e, s, p);
00091                 assert(t);
00092 
00093                 for(u = txentHead.lh_first; u; u = u->link.le_next) {
00094                         if(SEQ_GT(u->seqno(), s))
00095                           break;
00096                         v = u;
00097                 }
00098 
00099                 if(u == 0 && v == 0) {
00100                         LIST_INSERT_HEAD(&txentHead, t, link);
00101                 } else if(u) {
00102                         LIST_INSERT_BEFORE(u, t, link);
00103                 } else {
00104                         assert(v);
00105                         LIST_INSERT_AFTER(v, t, link);
00106                 }
00107 
00108         } else {
00109                 Packet::free(p);
00110                 // already have a copy of this packet
00111         }
00112 
00113 #ifdef  DEBUG
00114         // verify that I did not fuck up...
00115         u_int32_t max = 0;
00116         for(t = txentHead.lh_first; t; t = t->link.le_next) {
00117                 if(max == 0)
00118                         max = t->seqno();
00119                 else {
00120                         assert(t->seqno() > max);
00121                         max = t->seqno();
00122                 }
00123         } 
00124 #endif
00125 }                        
00126 
00127 void
00128 dstent::delEntry(txent *t)
00129 {
00130         LIST_REMOVE(t, link);
00131         delete t;
00132 }
00133 
00134 txent*
00135 dstent::findEntry(u_int32_t s)
00136 {
00137         txent *t;
00138 
00139         for(t = txentHead.lh_first; t; t = t->link.le_next) {
00140                 if(t->seqno() == s)
00141                         return t;
00142         }
00143         return 0;
00144 }
00145 
00146 txent*
00147 dstent::findFirstEntry(void)
00148 {
00149         return txentHead.lh_first;
00150         // this gives the minimum sequence number for the destination
00151 }
00152 
00154 // Destination Queue
00155 dstQueue::dstQueue(imepAgent *a, nsaddr_t index) : agent_(a), ipaddr_(index)
00156 {
00157         LIST_INIT(&dstentHead);
00158 }
00159 
00160 void
00161 dstQueue::addEntry(nsaddr_t dst, double e, u_int32_t s, Packet *p)
00162 {
00163         dstent *t;
00164 
00165         if((t = findEntry(dst)) == 0) {
00166                 t = new dstent(dst);
00167                 assert(t);
00168                 LIST_INSERT_HEAD(&dstentHead, t, link);
00169         }
00170 
00171         if (NULL == t->txentHead.lh_first) agent_->stats.num_holes_created++;
00172         t->addEntry(e, s, p);
00173 }
00174 
00175         
00176 dstent*
00177 dstQueue::findEntry(nsaddr_t dst)
00178 {
00179         dstent *t;
00180 
00181         for(t = dstentHead.lh_first; t; t = t->link.le_next) {
00182                 if(t->ipaddr() == dst)
00183                         return t;
00184         }
00185         return 0;
00186 }
00187 
00190 
00191 Packet*
00192 dstQueue::getPacket(nsaddr_t dst, u_int32_t seqno)
00193 {
00194         dstent *d;
00195         txent *t;
00196 
00197         for(d = dstentHead.lh_first; d; d = d->link.le_next) {
00198                 if(d->ipaddr() == dst)
00199                         break;
00200         }
00201 
00202         if(d && (t = d->findEntry(seqno))) {
00203                 Packet *p = t->pkt();
00204                 d->delEntry(t);
00205 
00206                 // make sure packets come out in increasing order only
00207                 //      int8_t reg = (int8_t) seqno - (int8_t) d->seqno();
00208                 //assert(reg > 0); // SEQ_GT(seqno, d->seqno())
00209                 //d->seqno() = seqno; 
00210 
00211                 return p;
00212         }
00213         return 0;
00214 }
00215 
00216 double
00217 dstQueue::getNextExpire()
00218 {
00219         dstent *t;
00220         Time min = 0.0;
00221 
00222         for(t = dstentHead.lh_first; t; t = t->link.le_next) {
00223                 Time texp = t->expire(); // computed by traversing a list
00224                 if(min == 0.0 || (texp && texp < min))
00225                         min = texp;
00226         }
00227         if (verbose)
00228           agent_->trace("T %.9f _%d_ dest_queue -  getNextExpire is %.9f",
00229                         CURRENT_TIME, ipaddr_, min);
00230 
00231         return min;
00232 }
00233 
00234 Packet*
00235 dstQueue::getNextPacket(u_int32_t& s)
00236 {
00237         dstent *d;
00238 
00239         for(d = dstentHead.lh_first; d; d = d->link.le_next) {
00240           txent *t = d->findFirstEntry();
00241 
00242           if (t == 0) 
00243             {
00244               d->seqno() = ILLEGAL_SEQ;
00245               continue; // no packets here
00246             }
00247 
00248           Time texp = d->expire();
00249           assert(texp);
00250 #ifdef TEST_ONLY
00251           fprintf(stderr,
00252                   "IN:\td->expire: %f, d->seqno: %d, t->expire: %f, t->seqno: %d\n",
00253                   d->expire(), d->seqno(), t->expire(), t->seqno());
00254 #endif
00255           if (texp > CURRENT_TIME && d->seqno() == ILLEGAL_SEQ) continue;
00256 
00257           if (t->expire() <= CURRENT_TIME)
00258             { // remember this seq as starting a chain we can pull off
00259               d->seqno() = t->seqno();
00260             }
00261           else if (d->seqno() != ILLEGAL_SEQ && t->seqno() != (u_int8_t) (d->seqno() + 1))
00262             { // the next pkt isn't part of the chain we were pulling off
00263               // stop pulling off packets
00264               d->seqno() = ILLEGAL_SEQ;
00265               continue;         
00266             }
00267 
00268             Packet *p = t->pkt();
00269             assert(p);
00270 
00271             s = t->seqno();
00272 
00273 #ifdef TEST_ONLY
00274             fprintf(stderr, "\t%s: returning seqno: %d\n",
00275                     __FUNCTION__, s);
00276 #endif
00277             if (d->seqno() != ILLEGAL_SEQ) 
00278               { // advance d->seqno() along the chain
00279                 d->seqno() = t->seqno();
00280               }
00281             
00282             d->delEntry(t);
00283 #ifdef TEST_ONLY
00284           fprintf(stderr,
00285                   "OUT:\td->expire: %f, d->seqno: %d, t->expire: %f, t->seqno: %d\n",
00286                   d->expire(), d->seqno(), t->expire(), t->seqno());
00287 #endif
00288             return p;
00289         }
00290         return 0;
00291 }
00292 
00293 void 
00294 dstQueue::deleteDst(nsaddr_t dst)
00295 {
00296   dstent *d;
00297   txent *t;
00298   
00299   if (verbose)
00300     agent_->trace("T %.9f _%d_ purge dstQ id %d",
00301                   CURRENT_TIME, ipaddr_, dst);
00302 
00303   for(d = dstentHead.lh_first; d; d = d->link.le_next) 
00304     {
00305       if(d->ipaddr() == dst)
00306         break;
00307     }
00308   if (!d) return;
00309 
00310   while ((t = d->findFirstEntry()))
00311     {
00312       Packet *p = t->pkt();
00313       if (verbose)
00314         agent_->trace("T %.9f _%d_ dstQ id %d delete seq %d",
00315                       CURRENT_TIME, ipaddr_, dst, t->seqno());
00316       Packet::free(p);
00317       d->delEntry(t); 
00318       agent_->stats.num_reseqq_drops++;
00319     }
00320 
00321   LIST_REMOVE(d,link);
00322   delete d;
00323 }
00324 
00325 void
00326 dstQueue::dumpAll()
00327 {
00328         dstent *t;
00329 
00330         for(t = dstentHead.lh_first; t; t = t->link.le_next) {
00331           if (verbose)
00332                 agent_->trace("T %.9f _%d_ dest_queue - src %d expire %.9f seqno %d",
00333                               CURRENT_TIME, ipaddr_, t->ipaddr(), t->expire(), t->seqno());
00334 
00335                 txent *u = t->findFirstEntry();
00336                 for(;u; u = u->link.le_next) {
00337                   if(verbose)
00338                     agent_->trace("T %.9f _%d_ dest_queue - src %d seq %d expire %.9f",
00339                                   CURRENT_TIME, ipaddr_, t->ipaddr(),
00340                                   u->seqno(), u->expire());
00341                 }
00342         }
00343 }

Generated on Tue Apr 20 12:14:13 2004 for NS2.26SourcesOriginal by doxygen 1.3.3