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

rlm.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) 1994-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 
00035 #ifndef lint
00036 static char rcsid[] =
00037     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/mcast/rlm.cc,v 1.8 2001/12/20 19:27:44 haldar Exp $ (LBL)";
00038 #endif
00039 
00040 #include "agent.h"
00041 #include "node.h"
00042 
00043 struct srcpkt {
00044         double off;
00045         int level;
00046         int size;
00047         srcpkt* next;
00048 };
00049 
00050 
00051 class RLM_Sender : public Agent {
00052  public:
00053         RLM_Sender();
00054         ~RLM_Sender();
00055         int command(int argc, const char*const* argv);
00056  protected:
00057         virtual void timeout(int);
00058         void start();
00059         void stop();
00060         void sched_next();
00061         void sendpkt(int size, int level);
00062         void addpkt(double off, int size, int level);
00063         int running_;
00064         double interval_;
00065         srcpkt* pkt_;
00066         srcpkt* allpkt_;
00067         /*XXX make size dynamic*/
00068 #define MAXLEVEL 32
00069         int seqno_[MAXLEVEL];
00070         int blkno_;
00071 };
00072 
00073 static class RLMMatcher : public Matcher {
00074 public:
00075         RLMMatcher() : Matcher("agent") {}
00076         TclObject* match(const char* id) {
00077                 if (strcmp(id, "rlm-sender") == 0)
00078                         return (new RLM_Sender());
00079                 return (0);
00080         }
00081 } matcher_rlm;
00082 
00083 RLM_Sender::RLM_Sender() : Agent(PT_CBR), pkt_(0), allpkt_(0)
00084 {
00085         Tcl& tcl = Tcl::instance();
00086         link_time("ns_rlm", "interval", &interval_, 0);
00087         link_int("ns_rlm", "packet-size", &size_, 0);
00088         running_ = 0;
00089         memset(seqno_, 0, sizeof(seqno_));
00090         blkno_ = 0;
00091 }
00092 
00093 RLM_Sender::~RLM_Sender()
00094 {
00095         /*XXX free allpkt_ */
00096 }
00097 
00098 void RLM_Sender::start()
00099 {
00100         if (allpkt_ != 0) {
00101                 running_ = 1;
00102                 pkt_ = allpkt_;
00103                 sched(pkt_->off, 0);
00104         }
00105 }
00106 
00107 void RLM_Sender::stop()
00108 {
00109         running_ = 0;
00110 }
00111 
00112 void RLM_Sender::sched_next()
00113 {
00114         srcpkt* p = pkt_;
00115         srcpkt* n = p->next;
00116         double t;
00117         if (n == 0) {
00118                 t = interval_;
00119                 n = allpkt_;
00120                 ++blkno_;
00121                 blkitem_ = 0;
00122         } else
00123                 t = 0.;
00124         t += n->off - p->off;
00125         pkt_ = n;
00126         sched(t, 0);
00127 }
00128 
00129 void RLM_Sender::timeout(int)
00130 {
00131         if (running_) {
00132                 sendpkt(pkt_->size, pkt_->level);
00133                 sched_next();
00134         }
00135 }
00136 
00137 void RLM_Sender::sendpkt(int size, int level)
00138 {
00139         Packet* p = allocpkt(seqno_[level]++);
00140         IPHeader *iph = IPHeader::access(p->bits());
00141         RLMHeader *rh = RLMHeader::access(p->bits());
00142         rh->blkno() = blkno_;
00143         rh->blkitem() = blkitem_++;
00144         iph->size() = size;
00145         iph->daddr() += level;
00146 #ifdef notdef
00147         iph->class() += level;/*XXX*/
00148 #endif
00149         node_->transmit(p);
00150 }
00151 
00152 extern double time_atof(const char*);
00153 
00154 void RLM_Sender::addpkt(double off, int size, int level)
00155 {
00156         srcpkt* sp = new srcpkt;
00157         sp->next = 0;
00158         sp->off = off;
00159         sp->size = size;
00160         sp->level = level;
00161         srcpkt** p;
00162         for (p = &allpkt_; *p != 0; p = &(*p)->next)
00163                 if (sp->off < (*p)->off)
00164                         break;
00165         *p = sp;
00166 }
00167 
00168 /*
00169  * $obj start
00170  * $obj stop
00171  * $obj packet $off $size $level
00172  */
00173 int RLM_Sender::command(int argc, const char*const* argv)
00174 {
00175         if (argc == 2) {
00176                 if (strcmp(argv[1], "start") == 0) {
00177                         start();
00178                         return (TCL_OK);
00179                 }
00180                 if (strcmp(argv[1], "stop") == 0) {
00181                         stop();
00182                         return (TCL_OK);
00183                 }
00184         }
00185         if (argc == 5) {
00186                 if (strcmp(argv[1], "packet") == 0) {
00187                         double off = time_atof(argv[2]);
00188                         int size = atoi(argv[3]);
00189                         int level = atoi(argv[4]);
00190                         addpkt(off, size, level);
00191                         return (TCL_OK);
00192                 }
00193         }
00194         return (Agent::command(argc, argv));
00195 }
00196 
00197 class RLM_Receiver : public Agent {
00198  public:
00199         RLM_Receiver();
00200         int command(int argc, const char*const* argv);
00201         void recv(Packet* pkt);
00202 protected:
00203         char* proc_;
00204         int loss_;
00205         int expected_;
00206         int bytes_;
00207 
00208         int pblk_;
00209         int pseq_[MAXLEVEL];
00210 };
00211 
00212 static class RLM_ReceiverMatcher : public Matcher {
00213 public:
00214         RLM_ReceiverMatcher() : Matcher("agent") {}
00215         TclObject* match(const char* id) {
00216                 if (strcmp(id, "rlm-receiver") == 0)
00217                         return (new RLM_Receiver());
00218                 return (0);
00219         }
00220 } matcher_cbr;
00221 
00222 RLM_Receiver::RLM_Receiver() : Agent(-1), proc_(0), expected_(-1)
00223 {
00224         bytes_ = 0;
00225         loss_ = 0;
00226         link_int(0, "loss", &loss_, 1);
00227         link_int(0, "bytes", &bytes_, 1);
00228 }
00229 
00230 void RLM_Receiver::recv(Packet* pkt)
00231 {
00232         IPHeader *iph = IPHeader::access(pkt->bits());
00233         SequenceHeader *sh = SequenceHeader::access(pkt->bits());
00234         bytes_ += iph->size();
00235         int seqno = sh->seqno();
00236         int blkno = seqno >> 16;
00237         seqno &= 0xffff;
00238         
00239         /*
00240          * Check for lost packets
00241          */
00242         if (expected_ >= 0) {
00243                 int loss = sh->seqno() - expected_;
00244                 if (loss > 0) {
00245                         loss_ += loss;
00246                         if (proc_ != 0)
00247                                 Tcl::instance().eval(proc_);
00248                 }
00249         }
00250         expected_ = sh->seqno() + 1;
00251         Packet::free(pkt);
00252 }
00253 
00254 /*
00255  * $proc interval $interval
00256  * $proc size $size
00257  */
00258 int RLM_Receiver::command(int argc, const char*const* argv)
00259 {
00260         if (argc == 2) {
00261                 if (strcmp(argv[1], "clear") == 0) {
00262                         expected_ = -1;
00263                         return (TCL_OK);
00264                 }
00265         } else if (argc == 3) {
00266                 if (strcmp(argv[1], "proc") == 0) {
00267                         const char* proc = argv[2];
00268                         int n = strlen(proc) + 1;
00269                         delete proc_;
00270                         proc_ = new char[n];
00271                         strcpy(proc_, proc);
00272                         return (TCL_OK);
00273                 }
00274         }
00275         return (Agent::command(argc, argv));
00276 }

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