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 Mar 6 16:47:49 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6