00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
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
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;
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
00170
00171
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
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
00256
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 }