lms-receiver.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * lms-receiver.cc
00004  * Copyright (C) 2001 by the University of Southern California
00005  * $Id: lms-receiver.cc,v 1.3 2005/08/25 18:58:07 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  * Light-Weight Multicast Services (LMS), Reliable Multicast
00049  *
00050  * lms-receiver.cc
00051  *
00052  * This implements the Receiving LMS agent, "Agent/LMS/Receiver".
00053  *
00054  * Christos Papadopoulos. 
00055  * christos@isi.edu
00056  */
00057 
00058 #include <math.h>
00059 #include "agent.h"
00060 #include "tclcl.h"
00061 #include "packet.h"
00062 #include "ip.h"
00063 #include "rtp.h"
00064 #include "lms.h"
00065 #include "rcvbuf.h"
00066 
00067 #define LMS_NAK_TIMEOUT 0
00068 #define LMS_RDL_TIMEOUT 1
00069 #define LMS_RFR_TIMEOUT 2
00070 
00071 #define LMS_RQL_MAX 10  // requests to remember
00072 #define LMS_RDL_MAX 10  // rdata to remember
00073 
00074 #define LMS_LOSS_SMPL_IVL   0   // sample loss every LMS_LOSS_SMPL_IVL packets
00075                                 // a value of 0 disables adaptive repliers
00076 #define LMS_COST_THR        1   // change in packet loss required to trigger LMS_REFRESH
00077 
00078 static int rcv_uid_ = 0;
00079 
00080 
00081 class LmsReceiver;
00082 class LmsNak;
00083 
00084 //
00085 // Lms Nak Timer
00086 // When this timer expires, the Nak is sent again
00087 //
00088 class LmsNakTimer : public TimerHandler {
00089 public:
00090         LmsNakTimer(LmsNak *a) : TimerHandler() { a_ = a; }
00091         void expire(Event *e);
00092 protected:
00093         LmsNak *a_;
00094 };
00095 
00096 //
00097 // LMS RECEIVER
00098 //
00099 class LmsReceiver: public Agent {
00100  public:
00101     LmsReceiver();
00102     LmsReceiver* next_;
00103     int command (int argc, const char*const* argv);
00104     void recv (Packet* pkt, Handler*);
00105     virtual void timeout (int type, int lo, int hi);
00106 
00107  protected:
00108     void handle_lms_pkt (Packet* pkt);
00109     void send_refresh ();
00110     void send_dmcast (hdr_lms* lh, int seqno, int fid);
00111     int  add_req (Packet *rq);
00112     void send_nak (int sqn, int lo, int hi);
00113     void create_nak (int lo, int hi);
00114     void delete_nak (LmsNak *n);
00115     LmsNak* find_nak (int i);
00116     void add_rdl (int rseq, double clock);
00117     int  exists_rdl (int rseq);
00118     void print_stats ();
00119     void print_all_stats (int drops);
00120 
00121     char        uname_[8];  // unique name in the form r#
00122     RcvBuffer*  rcvbuf_;    // the receive buffer: see rcvbuf.{h,cc}
00123     int     dataSize_;  // data packet size
00124     double      rtt_;       // RTT to source
00125     nsaddr_t    lms_src_;   // address of sender
00126     nsaddr_t    lms_group_; // group address
00127 
00128     // LMS related params
00129     nsaddr_t    upstream_lms_;  // address of upstream LMS element
00130     int     lms_cost_;  // our current replier cost
00131     Packet*     rql_;       // request list - used to detect duplicate requests
00132     int     rql_sz_;    // current request list size
00133     struct lms_rdl* rdl_;       // rdata list - used to avoid re-retransmission
00134     int     rdl_sz_;    // current rdata list size
00135     LmsNak*     nak_;       // list of currently outstanding naks
00136 
00137     // Loss Sampling
00138     int     ls_last_rq_;    // # of requests at last loss sampling
00139     int     ls_last_seq_;   // data seq num at last loss sampling
00140     int     ls_smpl_ivl_;   // loss sampling interval (in packets)
00141     int     ls_cntdown_;    // how many packets until next loss sample
00142 
00143     // Receiver Stats
00144     int     req_sent_;  // number of unique requests sent
00145     int     req_rcvd_;  // number of requests received
00146     int     dup_reqs_;  // number of duplicate requests received
00147  static int             max_dup_naks_;  // max num of duplicate naks accros RXs
00148     
00149     // Header offsets
00150     // int      off_rtp_;
00151     // int      off_lms_;
00152     // int      off_ip_;
00153 };
00154 
00155 //
00156 // A NAK
00157 //
00158 class LmsNak {
00159  public:
00160     LmsNak (LmsReceiver *a, int lo, int hi);
00161     LmsNak  *next_;
00162     void    timeout (int type) {
00163             a_->timeout (type, lo_, hi_); }
00164     LmsNakTimer nak_timer_;
00165     int     lo_;
00166     int     hi_;
00167     int     seqn_;
00168     double      nak_timeout_;
00169  private:
00170     LmsReceiver *a_;
00171     int     fid_;
00172 };
00173 
00174 LmsNak::LmsNak(LmsReceiver *a, int lo, int hi): nak_timer_(this), lo_(lo), hi_(hi), a_(a)
00175 {
00176     seqn_ = 0;
00177 }
00178 
00179 void LmsNakTimer::expire(Event *e) {
00180         a_->timeout(LMS_NAK_TIMEOUT);
00181 }
00182 
00183 LmsReceiver *all_lms_receivers = 0;
00184 
00185 static class LmsReceiverClass : public TclClass {
00186 public:
00187     LmsReceiverClass() : TclClass("Agent/LMS/Receiver") {}
00188     TclObject* create(int, const char*const*) {
00189         return (new LmsReceiver());
00190     }
00191 } class_lms_receiver;
00192 
00193 
00194 
00195 // Obligatory definition of the class static
00196 int LmsReceiver::max_dup_naks_ = 0;
00197 
00198 LmsReceiver::LmsReceiver(): Agent(PT_LMS)
00199 {
00200     sprintf (uname_, "rcv%d", rcv_uid_++);
00201     lms_cost_ = 0;
00202     lms_src_ = lms_group_ = LMS_NOADDR;
00203     rtt_ = 0.0;
00204     rcvbuf_ = new RcvBuffer;
00205     req_sent_ = req_rcvd_ = dup_reqs_ = max_dup_naks_ = 0;
00206     upstream_lms_ =  LMS_NOADDR;
00207     dataSize_ = 0;
00208     ls_smpl_ivl_ = LMS_LOSS_SMPL_IVL;
00209     ls_cntdown_ = ls_smpl_ivl_;
00210     ls_last_rq_ = ls_last_seq_ = 0;
00211     nak_ = NULL;
00212     rql_ = NULL;
00213     rdl_ = NULL;
00214     rdl_sz_ = 0;
00215 
00216     this->next_ = all_lms_receivers;
00217     all_lms_receivers = this;
00218 
00219     bind("lmsPacketSize_", &size_);
00220 
00221     // bind("off_rtp_", &off_rtp_);
00222     // bind("off_ip_", &off_ip_);
00223     // bind("off_lms_", &off_lms_);
00224 }
00225 
00226 //
00227 // Send request upstream
00228 //
00229 void LmsReceiver::send_nak (int sqn, int lo, int hi)
00230 {
00231     Packet* p = allocpkt(sizeof (struct lms_nak));
00232     struct lms_nak  *n = (struct lms_nak*)p->accessdata ();
00233 
00234     hdr_ip* iph = HDR_IP(p);
00235     hdr_cmn* ch = HDR_CMN(p);  
00236 
00237     ch->size_ = sizeof(struct lms_nak) + sizeof(hdr_lms); 
00238     iph->daddr() = upstream_lms_;
00239     iph->flowid() = 8;
00240 #ifdef LMS_DEBUG
00241 printf("at %f %s send nak to upstream lms %d, size is %d\n\n",
00242   now,uname_, upstream_lms_, (HDR_CMN(p))->size_);
00243 #endif
00244     hdr_lms* lh = HDR_LMS(p);
00245     lh->type_   = LMS_REQ;
00246     lh->from_   = addr();
00247     lh->src_    = lms_src_;
00248     lh->group_  = lms_group_;
00249 
00250     lh->tp_addr_ = LMS_NOADDR;
00251     lh->tp_port_ = -1;
00252     lh->tp_iface_ = LMS_NOIFACE;
00253     lh->lo_ = n->nak_lo_ = lo;
00254     lh->hi_ = n->nak_hi_ = hi;
00255     n->nak_seqn_ = sqn;
00256         n->dup_cnt_ = 0;
00257         
00258     target_->recv(p);
00259 }
00260 
00261 //
00262 // Send a replier refresh upstream.
00263 //
00264 void LmsReceiver::send_refresh ()
00265 {
00266     Packet* p = allocpkt (sizeof (struct lms_ctl));
00267     struct lms_ctl  *ctl = (struct lms_ctl*)p->accessdata ();
00268 
00269     hdr_ip* iph = HDR_IP(p);
00270     hdr_cmn *ch = HDR_CMN(p);  
00271 
00272     ch->size_ = sizeof(struct lms_ctl) + sizeof(hdr_lms); 
00273     iph->daddr() = upstream_lms_;
00274     iph->flowid() = 7;      // mark refresh packets black for nam
00275 #ifdef LMS_DEBUG
00276 printf("%s send refresh packet, size is %d\n\n",
00277   uname_, (HDR_CMN(p))->size_);
00278 #endif
00279     hdr_lms* lh = HDR_LMS(p);
00280     lh->type_   = LMS_REFRESH;
00281     lh->from_   = addr();
00282     lh->src_    = lms_src_;
00283     lh->group_  = lms_group_;
00284 
00285     ctl->cost_ = lms_cost_;
00286     ctl->hop_cnt_ = 0;
00287         ctl->downstream_lms_.addr_ = addr();
00288         ctl->downstream_lms_.port_ = port();
00289         
00290     target_->recv(p);
00291 }
00292 
00293 //
00294 // Receive a packet
00295 //
00296 void LmsReceiver::recv (Packet* pkt, Handler*)
00297 {
00298     hdr_cmn* h = HDR_CMN(pkt);
00299 
00300     // handle LMS packet
00301     if (h->ptype_ == PT_LMS)
00302         {
00303         handle_lms_pkt (pkt);
00304         return;
00305         }
00306 
00307     // DATA packet
00308     double      clock = Scheduler::instance().clock();
00309     hdr_rtp*    rh = HDR_RTP(pkt);
00310     int     rseq = rh->seqno();
00311 
00312     dataSize_ = h->size_;  
00313 
00314 #ifdef LMS_DEBUG
00315 printf ("%s got data pkt %d\n", uname_, rseq);
00316 #endif
00317     // GAP: send retransmission request
00318     if (rcvbuf_->nextpkt_ <  rseq)
00319         {
00320         int lo = rcvbuf_->nextpkt_;
00321         int hi = rseq - 1;
00322         req_sent_++;
00323 #ifdef LMS_DEBUG
00324 printf ("%s Sending REQ, lo %d, hi %d\n", uname_, lo, hi);
00325 #endif
00326         create_nak (lo, hi);
00327         send_nak (0, lo, hi);
00328         }
00329     // RETRANSMISSION
00330     else if (rcvbuf_->nextpkt_ >  rseq &&
00331          !rcvbuf_->exists_pkt (rseq))
00332         {
00333         add_rdl (rseq, clock);  // remember rdata
00334 
00335         LmsNak *nak = find_nak (rseq);
00336         if (nak->lo_ !=  nak->hi_)
00337             {
00338             if (rseq == nak->lo_)
00339                 create_nak (rseq+1, nak->hi_);
00340             else if (rseq == nak->hi_)
00341                 create_nak (nak->lo_, rseq-1);
00342             else    {
00343                 create_nak (nak->lo_, rseq-1);
00344                 create_nak (rseq+1, nak->hi_);
00345                 }
00346             }
00347         delete_nak (nak);
00348         }
00349 
00350     rcvbuf_->add_pkt (rseq, clock);
00351 
00352     // The LMS replier cost is sampled and refreshed every
00353     // LMS_LOSS_SMPL_IVL packets - data or retransmnissions.
00354     // New cost is the number of lost packets during LMS_LOSS_SMPL_IVL.
00355     // We update cost only if loss >= LMS_COST_THR.
00356     // The previous value is forgotten, making cost refresh very responsive.
00357     //
00358     // (XXX: We need a better algorithm here.
00359     if (ls_smpl_ivl_ && --ls_cntdown_ == 0)
00360         {
00361         int newcost = req_sent_ - ls_last_rq_;
00362         assert (newcost >= 0);
00363         if (abs (newcost - lms_cost_) >= LMS_COST_THR)
00364             {
00365             lms_cost_ = newcost;
00366             if (newcost > 0)
00367                 ls_last_rq_ = req_sent_;
00368 #ifdef LMS_DEBUG
00369 printf ("%s NEW LMS_COST %d\n", uname_, lms_cost_);
00370 #endif
00371             }
00372         send_refresh ();
00373         ls_cntdown_ = ls_smpl_ivl_;
00374         }
00375 
00376     Packet::free(pkt);
00377 }
00378 
00379 /*
00380  * Handle LMS packets
00381  */
00382 void LmsReceiver::handle_lms_pkt (Packet* pkt)
00383 {
00384     hdr_lms* lh = HDR_LMS(pkt);
00385     hdr_ip* iph = HDR_IP(pkt);
00386     int st = 0;
00387 #ifdef LMS_DEBUG
00388 int a1, a2;
00389 #endif
00390     switch (lh->type())
00391     {
00392         case LMS_REQ:
00393         {
00394             struct lms_nak *n = (struct lms_nak *)pkt->accessdata ();
00395             req_rcvd_++;
00396 #ifdef LMS_DEBUG
00397 a1 = lh->from(); a2 = lh->src();
00398 printf ("%s got LMS_REQ from %d:%d src %d:%d group 0x%x ",
00399   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group());
00400 printf ("TP: (%d:%d, %d)\n\n", lh->tp_addr_>>8, lh->tp_addr_&0xff, lh->tp_iface_);
00401 #endif
00402             if ((st = add_req (pkt)) != 0)
00403                 {
00404                     for (int i = lh->lo_; i <= lh->hi_; i++)
00405                         if (!(n->nak_seqn_ == 0 && exists_rdl (i)) &&
00406                             (rcvbuf_->exists_pkt (i)))
00407                             send_dmcast (lh, i, 3);
00408                 }
00409             else    dup_reqs_++;
00410 
00411             break;
00412         }
00413         case LMS_SETUP:
00414                         {
00415             lms_src_ = iph->saddr();
00416             lms_group_ = iph->daddr();
00417             rtt_ = 2.0*(Scheduler::instance().clock() - lh->ts_);
00418             upstream_lms_ = lh->from_;
00419             dataSize_ = lh->cost_;      // XXX
00420 
00421             Tcl& tcl = Tcl::instance();
00422             char wrk[64];
00423             sprintf (wrk, "set_max_rtt %f", rtt_);
00424             tcl.eval (wrk); 
00425 
00426 #ifdef LMS_DEBUG
00427 a1 = lh->from(); a2 = lh->src();
00428 //printf("%d %d, %ld %ld\n\n ", a1, a2, iph->saddr(), iph->daddr());
00429 printf("%s the upstream_lms is %d\n\n", uname_, upstream_lms_);
00430 printf ("%s LMS_SETUP from %d:%d src %d:%d group 0x%x RTT %f dataSize %d\n\n",
00431   uname_, a1>>8, a1&0xff, a2>>8, a2&0xff, lh->group(), rtt_, dataSize_);
00432 #endif
00433                         send_refresh ();
00434             break;
00435             }
00436         case LMS_SPM:
00437             {
00438             struct lms_spm *spm = (struct lms_spm *)pkt->accessdata ();
00439 #ifdef LMS_DEBUG    
00440 printf ("%s LMS_SPM seqno %d, upstream %d:%d\n\n",
00441   uname_, spm->spm_seqno_, adr>>8, adr&0xff);
00442 #endif
00443             if (upstream_lms_ != spm->spm_path_)
00444                 upstream_lms_ = spm->spm_path_;
00445             }
00446             break;
00447         case LMS_LINKS:
00448         case LMS_SRC_REFRESH:
00449             break;
00450         default:
00451             printf ("ERROR: %s Unexpected LMS packet type: %d\n\n", uname_, lh->type());
00452             abort ();
00453         }
00454     if (!st)
00455         Packet::free(pkt);
00456 }
00457 
00458 int LmsReceiver::command(int argc, const char*const* argv)
00459 {
00460     if (argc == 2) {
00461         if (strcmp(argv[1], "clear") == 0) {
00462             return (TCL_OK);
00463         }
00464                 if (strcmp(argv[1], "print-stats") == 0) {
00465                         print_stats ();
00466                         return (TCL_OK);
00467                 }
00468     }
00469     if (argc == 3)
00470         {
00471                 if (strcmp(argv[1], "print-all-stats") == 0) {
00472                         print_all_stats (atoi (argv[2]));
00473                         return (TCL_OK);
00474                 }
00475         if (strcmp(argv[1], "set-replier-cost") == 0)
00476             {
00477             lms_cost_  = atoi (argv[2]);
00478                         send_refresh ();
00479             return (TCL_OK);
00480             }
00481         if (strcmp(argv[1], "loss-smpl-ivl") == 0)
00482             {
00483             ls_cntdown_ = ls_smpl_ivl_ = atoi (argv[2]);
00484             return (TCL_OK);
00485             }
00486         }
00487     return (Agent::command(argc, argv));
00488 }
00489 
00490 /*
00491  * Send a LMS_DMCAST in response to LMS_REQ packet
00492  */
00493 void LmsReceiver::send_dmcast (hdr_lms* lh, int seqno, int fid)
00494 {
00495     Packet  *p = allocpkt();
00496     hdr_cmn *ch = HDR_CMN(p);
00497     hdr_rtp *rh = HDR_RTP(p);
00498     hdr_ip  *piph = HDR_IP(p);
00499 #ifdef LMS_DEBUG
00500 printf ("%s Sending DMCAST %d to %d:%d, size is %d\n",
00501   uname_, seqno, lh->tp_addr_>>8, lh->tp_addr_&0xff, ch->size_);
00502 #endif
00503 
00504     hdr_lms *plh = HDR_LMS(p);
00505     ch->ptype_ = PT_CBR;
00506     ch->size() = dataSize_; 
00507 
00508     rh->seqno() = seqno;
00509 
00510     piph->daddr() = lh->tp_addr_;
00511     piph->dport() = lh->tp_port_;
00512     piph->flowid() = fid;       // to color packets in NAM
00513 
00514     plh->type_ = LMS_DMCAST;
00515     plh->from_ = addr();
00516     plh->src_ = lms_src_;
00517     plh->group_ = lms_group_;
00518     plh->tp_addr_ = lh->tp_addr_;
00519     plh->tp_port_ = lh->tp_port_;
00520     plh->tp_iface_ = lh->tp_iface_;
00521 
00522     target_->recv(p);
00523 }
00524 
00525 // Add a new request to rql_
00526 // Return 1 if the request was added,
00527 // 0 if this was a duplicate request and was not added.
00528 // Requests are added to the head of the list
00529 // and the list size is limited to LMS_RQL_MAX
00530 // (XXX: should have timer to expire old entries)
00531 //
00532 int LmsReceiver::add_req (Packet *rq)
00533 {
00534     hdr_lms *lh = HDR_LMS(rq);
00535         Packet  *p = rql_;
00536         int     i = 0;
00537 
00538         if (!p)
00539         {
00540             rql_ = rq;
00541             rq->next_ = 0;
00542             rql_sz_ = 1;
00543             return 1;
00544         }
00545 
00546 #ifdef LMS_DEBUG
00547 printf("%s REQ: \tlo=%d \thi=%d \ttp_addr=%d \ttp_if=%d\n",
00548   uname_, lh->lo_, lh->hi_, lh->tp_addr_, lh->tp_iface_);
00549 #endif
00550 
00551       while (p)
00552         {
00553             if (++i > LMS_RQL_MAX)
00554                 break;
00555             
00556             hdr_lms *plh = HDR_LMS(p);
00557 
00558 #ifdef LMS_DEBUG
00559 printf("%s DB: \tlo=%d \thi=%d \ttp_addr=%d \ttp_if=%d\n",
00560   uname_, plh->lo_, plh->hi_, plh->tp_addr_, plh->tp_iface_);
00561 #endif            
00562             
00563 
00564             if ((plh->lo_ == lh->lo_) &&
00565                 (plh->hi_ == lh->hi_) &&
00566                 (plh->tp_addr_ == lh->tp_addr_) &&
00567                 (plh->tp_iface_ == lh->tp_iface_)) 
00568             {
00569                 struct lms_nak *nh = (struct lms_nak *)p->accessdata();
00570                 // increments the dup_cnt_ for this NAK, and updates
00571                 // max_dup_naks_ if appropriate
00572                 ++nh->dup_cnt_;
00573 
00574 #ifdef LMS_DEBUG
00575    printf ("%s got %d dup reqs, max is %d\n", uname_, nh->dup_cnt_, max_dup_naks_);
00576 #endif                
00577                 
00578                 if( nh->dup_cnt_ > max_dup_naks_)
00579                     max_dup_naks_ = nh->dup_cnt_;
00580                                 
00581                 return 0;
00582             }
00583             
00584             p = p->next_;
00585         }
00586         
00587         if (i > LMS_RQL_MAX && p && p->next_)
00588         {
00589             Packet::free (p->next_);
00590             p->next_ = 0;
00591             rql_sz_--;
00592         }
00593 
00594         rq->next_ = rql_;
00595         rql_ = rq;
00596         rql_sz_++;
00597         return 1;
00598 }
00599 
00600 void LmsReceiver::print_all_stats (int drops)
00601 {
00602     LmsReceiver *r = all_lms_receivers;
00603     int     nrcvs = 0; 
00604     int     cnt1 = 0; 
00605     int     cnt2 = 0; 
00606     int     dup_replies = 0;
00607     double          avg_norm_latency = 0.0;
00608     double      min = 1000000.0, max = 0.0;
00609         float           aveTotalDupReqs = 0.0;
00610         
00611     while (r)
00612         {
00613             ++nrcvs;
00614 
00615             // first, we'll add up all dupReqs, and after the loop we'll
00616             // div. by nrcvrs
00617             aveTotalDupReqs += float(r->dup_reqs_);
00618 
00619             if (r->rcvbuf_->duplicates_)
00620             {
00621                 cnt1++;
00622                 dup_replies += r->rcvbuf_->duplicates_;
00623             }
00624             if (r->rcvbuf_->pkts_recovered_)
00625             {
00626                 cnt2++;
00627                 double avl = r->rcvbuf_->delay_sum_/(double)r->rcvbuf_->pkts_recovered_;
00628                 avg_norm_latency += avl / r->rtt_;
00629                 
00630                 double m = r->rcvbuf_->min_delay_/r->rtt_;
00631                 double x = r->rcvbuf_->max_delay_/r->rtt_;
00632                 if (m < min)
00633                     min = m;
00634                 if (x > max)
00635                     max = x;
00636             }
00637             r = r->next_;
00638         }
00639         if(drops) 
00640             aveTotalDupReqs = (float(aveTotalDupReqs) / float(nrcvs)) / float(drops);
00641         else 
00642             aveTotalDupReqs = 0.0;
00643         
00644     //
00645     // Print stats in the form: <avg duplicate replies> <avg recovery latency> <min> <max>
00646     //
00647     if (drops)
00648         {
00649                     printf ("\t%.5lf\t  %d\t%.4lf", aveTotalDupReqs, max_dup_naks_,
00650                                  ((double)dup_replies/(double)(nrcvs*drops)) );
00651         }
00652     else    {
00653         printf ("\t0.0\t  0\t0.0");
00654         }
00655 
00656     //printf ("\t%d/%d/%.2lf", nrcvs, cnt1, (cnt1)?((double)dup_replies/(double)cnt1):0.0);
00657     if (cnt2) 
00658         {
00659         printf ("\t%.2lf\t%.2lf\t%.2lf\n", avg_norm_latency/(double)cnt2, min, max);
00660         }
00661     else
00662         {
00663         printf ("\t0.0\t0.0\t0.0\n");
00664         }
00665     printf ("\n");
00666 
00667     //printf ("Avg duplicates: %lf\n", (double)dup_replies / (double) cnt1);
00668     //printf ("Avg norm latency: %lf\n", avg_norm_latency / (double) cnt2);
00669 }
00670 
00671 void LmsReceiver::print_stats ()
00672 {
00673         printf ("%s:\n", uname_);
00674         printf ("\tLast packet:\t\t%d\n", rcvbuf_->nextpkt_-1);
00675         printf ("\tMax packet:\t\t%d\n", rcvbuf_->maxpkt_);
00676         printf ("\tRequests sent:\t\t%d\n", req_sent_);
00677         printf ("\tRequests received:\t%d\n", req_rcvd_);
00678         if (rcvbuf_->pkts_recovered_)
00679                 {
00680                 printf ("\tPackets recovered:\t%d\n", rcvbuf_->pkts_recovered_);
00681                 printf ("\tNormalized latency (min, max, avg):\t%lf, %lf, %lf\n",
00682                         rcvbuf_->min_delay_/rtt_, rcvbuf_->max_delay_/rtt_,
00683                         (rcvbuf_->delay_sum_/(double)rcvbuf_->pkts_recovered_)/rtt_);
00684                 }
00685         printf ("\tDuplicate Replies:\t%d\n", rcvbuf_->duplicates_);
00686         printf ("\tDuplicate Requests:\t%d\n", dup_reqs_);
00687         printf ("\tRtt:\t\t\t%lf\n", rtt_);
00688         printf ("\n");
00689 }
00690 
00691 void LmsReceiver::timeout (int type, int lo, int hi)
00692 {
00693     if (type == LMS_NAK_TIMEOUT)
00694         {
00695 #ifdef LMS_DEBUG
00696 double now= Scheduler::instance().clock();
00697 printf ("at %f %s LMS_NAK_TIMEOUT for %d, %d\n", now, uname_, lo, hi);
00698 #endif
00699         LmsNak *nak = find_nak (lo);
00700         send_nak (++nak->seqn_, lo, hi);
00701         nak->nak_timeout_ *= 2.0;           // exponential back-off
00702         nak->nak_timer_.resched (nak->nak_timeout_);
00703         }
00704 }
00705 
00706 void LmsReceiver::create_nak (int lo, int hi)
00707 {
00708 #ifdef LMS_DEBUG
00709 printf ("%s Creating NAK %d, %d\n", uname_, lo, hi);
00710 #endif
00711     LmsNak *nak = new LmsNak (this, lo, hi);
00712     nak->nak_timeout_ = rtt_ * 2.0;     // set initial timeout to twice rtt
00713     nak->nak_timer_.resched (nak->nak_timeout_);
00714     nak->next_ = nak_;
00715     nak_ = nak;
00716 }
00717 
00718 LmsNak *LmsReceiver::find_nak (int i)
00719 {
00720     for (LmsNak *n = nak_; n; n = n->next_)
00721         if (n->lo_ <= i && i <= n->hi_)
00722             return n;
00723     // NOT REACHED
00724     printf("ERROR: %s nak %d not found\n", uname_, i);
00725     abort ();
00726     return 0;
00727 }
00728 
00729 void LmsReceiver::delete_nak (LmsNak *n)
00730 {
00731     if (n == nak_)
00732         nak_ = nak_->next_;
00733     else    {
00734         LmsNak *cur, *prev = nak_;
00735         cur = nak_->next_;
00736         while (cur)
00737             {
00738             if (cur == n)
00739                 {
00740                 prev->next_ = cur->next_;
00741                 break;
00742                 }
00743             prev = cur;
00744             cur = cur->next_;
00745             }
00746         }
00747     n->nak_timer_.cancel();
00748 #ifdef LMS_DEBUG
00749 printf ("%s Deleting NAK %d, %d\n", uname_, n->lo_, n->hi_);
00750 #endif
00751     delete n;
00752 }
00753 
00754 //
00755 // Remember retransmissions. Uses a linked list
00756 // whose size is limited to LMS_RDL_MAX.
00757 // (Perhaps better to use an array and a timer to expire entries)
00758 //
00759 void LmsReceiver::add_rdl (int rseq, double clock)
00760 {
00761     struct lms_rdl *r = new (struct lms_rdl);
00762     r->seqn_ = rseq;
00763     r->ts_ = clock;
00764     r->next_ = rdl_;
00765     rdl_ = r;
00766 
00767     if (++rdl_sz_ > LMS_RDL_MAX)
00768         {
00769         struct lms_rdl *r = rdl_;
00770         for (int i = 0; i < LMS_RDL_MAX; i++)
00771             r = r->next_;
00772         delete r->next_;
00773         r->next_ = NULL;
00774         --rdl_sz_;
00775         }
00776 }
00777 
00778 int LmsReceiver::exists_rdl (int rseq)
00779 {
00780     struct lms_rdl *r = rdl_;
00781     for (; r; r = r->next_)
00782         if (r->seqn_ == rseq)
00783             return 1;
00784     return 0;
00785 }

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