rcvbuf.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * rcvbuf.cc
00004  * Copyright (C) 2001 by the University of Southern California
00005  * $Id: rcvbuf.cc,v 1.2 2005/08/25 18:58:08 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /*
00048  * Pragmatic General Multicast (PGM), Reliable Multicast
00049  * Light-Weight Multicast Services (LMS), Reliable Multicast
00050  *
00051  * rcvbuf.cc
00052  *
00053  * Utility class used by receivers to provide for packet loss detection,
00054  * and to compute latency statistics for recovered packets.
00055  *
00056  * Christos Papadopoulos
00057  */
00058 
00059 #include "config.h"
00060 
00061 #include <stdio.h>
00062 #include "rcvbuf.h"
00063 
00064 RcvBuffer::RcvBuffer ()
00065 {
00066     nextpkt_ = 0;
00067     maxpkt_ = -1;
00068     duplicates_ = 0;
00069     delay_sum_ = 0.0;
00070     max_delay_ = 0.0;
00071     min_delay_ = 1e6;
00072     pkts_recovered_ = 0;
00073     tail_ = gap_ = 0;
00074 }
00075 
00076 //
00077 // add pkt to buffer with seqno i, received at time tnow
00078 //
00079 void RcvBuffer::add_pkt (int i, double tnow)
00080 {
00081     Gap *g, *pg;
00082 
00083     if (exists_pkt (i))
00084         {
00085         duplicates_++;
00086         return;
00087         }
00088     // common case first: got what we expected
00089     if (i == nextpkt_)
00090         {
00091         nextpkt_++;
00092         if (i == maxpkt_ + 1)
00093             maxpkt_++;
00094         return;
00095         }
00096     // new gap
00097     if (i > nextpkt_)
00098         {
00099         g = new Gap;
00100         g->start_ = nextpkt_;
00101         g->end_ = i-1;
00102         g->time_ = tnow;
00103         g->next_ = 0;
00104 
00105         if (!gap_)
00106             gap_ = tail_ = g;
00107         else    {
00108             tail_->next_ = g;
00109             tail_ = g;
00110             }
00111         nextpkt_ = i+1;
00112         return;
00113         }
00114 
00115     // i < nextpkt_ (a retransmission)
00116 
00117     pkts_recovered_++;
00118 
00119     // is packet part of the first gap?
00120     if (gap_->start_ <= i && i <= gap_->end_)
00121         {
00122         double  d = tnow - gap_->time_;
00123 
00124         if (d > max_delay_)
00125             max_delay_ = d;
00126         if (d < min_delay_)
00127             min_delay_ = d;
00128         delay_sum_ += d;
00129         if (i == maxpkt_ + 1)
00130             {
00131             maxpkt_++;
00132             if (++gap_->start_ > gap_->end_)
00133                 {
00134                 g = gap_;
00135                 gap_ = gap_->next_;
00136                 if (gap_)
00137                     maxpkt_ = gap_->start_ - 1;
00138                 else    {
00139                     maxpkt_ = nextpkt_ - 1;
00140                     tail_ = 0;
00141                     }
00142                 delete g;
00143                 }
00144             return;
00145             }
00146         g = gap_;
00147         }
00148     else    {
00149         double  d;
00150 
00151         // locate gap this packet belongs to
00152         pg = gap_;
00153         g = gap_->next_;
00154         while (!(i >= g->start_ && i <= g->end_))
00155             {
00156             pg = g;
00157             g = g->next_;
00158             }
00159         d = tnow - g->time_;
00160         delay_sum_ += d;
00161         if (d > max_delay_) max_delay_ = d;
00162         if (d < min_delay_) min_delay_ = d;
00163 
00164         // first packet in gap
00165         if (g->start_ == i)
00166             {
00167             if (++g->start_ > g->end_)
00168                 {
00169                 pg->next_ = g->next_;
00170                 if (tail_ == g)
00171                     tail_ = pg;
00172                 delete g;
00173                 }
00174             return;
00175             }
00176         }
00177     // last packet in gap
00178     if (g->end_ == i)
00179         {
00180         g->end_--;
00181         return;
00182         }
00183     // a packet in the middle of gap
00184     pg = new Gap;
00185     pg->start_ = i+1;
00186     pg->end_   = g->end_;
00187     pg->time_  = g->time_;
00188     pg->next_  = g->next_;
00189 
00190     g->next_ = pg;
00191     g->end_  = i-1;
00192     if (tail_ == g)
00193         tail_ = pg;
00194 }
00195 
00196 //
00197 // Return 0 if packet does not exist in the
00198 // buffer, 1 if it does
00199 //
00200 int RcvBuffer::exists_pkt (int i)
00201 {
00202     if (i <= maxpkt_)  return 1;
00203     if (i >= nextpkt_) return 0;
00204 
00205     Gap *g;
00206     for (g = gap_; g; g = g->next_)
00207         if (g->start_ <= i && i <= g->end_)
00208             return 0;
00209     return 1;
00210 }
00211 
00212 void RcvBuffer::print ()
00213 {
00214     Gap *g;
00215 
00216     printf ("maxpkt: %d ", maxpkt_);
00217 
00218     for (g = gap_; g; g = g->next_)
00219         printf ("(%d, %d) ", g->start_, g->end_);
00220 
00221     printf ("nextpkt: %d\n", nextpkt_);
00222 }
00223 

Generated on Tue Mar 6 16:47:49 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6