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 const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/common/ivs.cc,v 1.16 2000/09/01 03:04:05 haoboy Exp $ (LBL)";
00038 #endif
00039
00040 #include <stdlib.h>
00041 #include <math.h>
00042 #include "message.h"
00043 #include "trace.h"
00044 #include "agent.h"
00045
00046
00047 struct hdr_ivs {
00048 double ts_;
00049 u_int8_t S_;
00050 u_int8_t R_;
00051 u_int8_t state_;
00052 u_int8_t rshft_;
00053 u_int8_t kshft_;
00054 u_int16_t key_;
00055 double maxrtt_;
00056 int seqno_;
00057
00058 static int offset_;
00059 inline static int& offset() { return offset_; }
00060 inline static hdr_ivs* access(Packet* p) {
00061 return (hdr_ivs*) p->access(offset_);
00062 }
00063
00064
00065 double& ts() { return (ts_); }
00066 u_int8_t& S() { return (S_); }
00067 u_int8_t& R() { return (R_); }
00068 u_int8_t& state() { return (state_); }
00069 u_int8_t& rshft() { return (rshft_); }
00070 u_int8_t& kshft() { return (kshft_); }
00071 u_int16_t& key() { return (key_); }
00072 double& maxrtt() { return (maxrtt_); }
00073 int& seqno() { return (seqno_); }
00074 };
00075
00076 int hdr_ivs::offset_;
00077
00078 static class IvsHeaderClass : public PacketHeaderClass {
00079 public:
00080 IvsHeaderClass() : PacketHeaderClass("PacketHeader/IVS",
00081 sizeof(hdr_ivs)) {
00082 bind_offset(&hdr_ivs::offset_);
00083 }
00084 } class_ivshdr;
00085
00086 class IvsSource : public Agent {
00087 public:
00088 IvsSource();
00089 protected:
00090 void reset();
00091 void recv(Packet *pkt, Handler*);
00092 void sendpkt();
00093
00094 int S_;
00095 int R_;
00096 int state_;
00097 #define ST_U 0
00098 #define ST_L 1
00099 #define ST_C 2
00100 int rttShift_;
00101 int keyShift_;
00102 int key_;
00103 double maxrtt_;
00104 };
00105
00106 struct Mc_Hole {
00107 int start;
00108 int end;
00109 double time;
00110 Mc_Hole* next;
00111 };
00112
00113 class IvsReceiver : public Agent {
00114 public:
00115 IvsReceiver();
00116 int command(int argc, const char*const* argv);
00117 protected:
00118 void recv(Packet *pkt, Handler*);
00119 void update_ipg(double now);
00120 int lossMeter(double timeDiff, u_int32_t seq, double maxrtt);
00121 void upcall_respond(double ts, int matchS);
00122 void upcall_rtt_solicit(double ts, int rshift);
00123
00124 int state_;
00125 u_int32_t nextSeq_;
00126
00127 double timeMean_;
00128 double timeVar_;
00129 double ipg_;
00130 Mc_Hole* head_;
00131 Mc_Hole* tail_;
00132 double lastPktTime_;
00133 int ignoreR_;
00134 double lastTime_;
00135 int key_;
00136 };
00137
00138 static class IvsSourceClass : public TclClass {
00139 public:
00140 IvsSourceClass() : TclClass("Agent/IVS/Source") {}
00141 TclObject* create(int, const char*const*) {
00142 return (new IvsSource());
00143 }
00144 } class_ivs_source;
00145
00146 static class IvsReceiverClass : public TclClass {
00147 public:
00148 IvsReceiverClass() : TclClass("Agent/IVS/Receiver") {}
00149 TclObject* create(int, const char*const*) {
00150 return (new IvsReceiver());
00151 }
00152 } class_ivs_receiver;
00153
00154 IvsSource::IvsSource() : Agent(PT_MESSAGE), S_(0), R_(0), state_(ST_U),
00155 rttShift_(0), keyShift_(0), key_(0), maxrtt_(0)
00156 {
00157 bind("S_", &S_);
00158 bind("R_", &R_);
00159 bind("state_", &state_);
00160 bind("rttShift_", &rttShift_);
00161 bind("keyShift_", &keyShift_);
00162 bind("key_", &key_);
00163 bind("maxrtt_", &maxrtt_);
00164 }
00165
00166 void IvsSource::reset()
00167 {
00168 }
00169
00170
00171
00172
00173
00174 void IvsSource::recv(Packet* pkt, Handler*)
00175 {
00176 char wrk[128];
00177 Tcl& tcl = Tcl::instance();
00178 hdr_msg *q = hdr_msg::access(pkt);
00179 sprintf(wrk, "%s handle {%s}", name(), q->msg());
00180 tcl.eval(wrk);
00181 Packet::free(pkt);
00182 }
00183
00184 #ifdef notdef
00185 void IvsSource::probe_timeout()
00186 {
00187 rndStart_ = now;
00188
00189 if (keyShift_ == 15) {
00190 if (key_ == 0) {
00191 if (solicitedResponses_ == 0)
00192 estReceivers_ = 0;
00193
00194
00195
00196
00197 if (state_ == ST_U)
00198 increase();
00199
00200
00201 S_ = 1;
00202 state_ = ST_U;
00203
00204
00205 setRttSolicit(mcstate);
00206
00207 solicitedResponses_ = 0;
00208 keyShift_ = startShift_;
00209
00210 setkey();
00211
00212 } else { mcstate->hdr.key = 0; }
00213 } else {
00214 if (probeTimeout_ > 0)
00215 ++keyShift_;
00216 }
00217 sched(pktTime + 2 * maxrtt_, IVS_TIMER_PROBE);
00218 }
00219 #endif
00220
00221 void IvsSource::sendpkt()
00222 {
00223 Packet* pkt = allocpkt();
00224 hdr_ivs *p = hdr_ivs::access(pkt);
00225
00226 p->ts() = Scheduler::instance().clock();
00227 p->S() = S_;
00228 p->R() = R_;
00229 p->state() = state_;
00230 p->rshft() = rttShift_;
00231 p->kshft() = keyShift_;
00232 p->key() = key_;
00233 p->maxrtt() = maxrtt_;
00234
00235 target_->recv(pkt, (Handler *)0);
00236 }
00237
00238 IvsReceiver::IvsReceiver() : Agent(PT_MESSAGE), state_(ST_U),
00239 nextSeq_(0),
00240 timeMean_(0.), timeVar_(0.),
00241 ipg_(0.),
00242 head_(0),
00243 tail_(0),
00244 lastPktTime_(0.),
00245 ignoreR_(0),
00246 lastTime_(0.),
00247 key_(0)
00248 {
00249 bind("ignoreR_", &ignoreR_);
00250 bind("key_", &key_);
00251 bind("state_", &state_);
00252 bind("packetSize_", &size_);
00253 }
00254
00255 inline void IvsReceiver::update_ipg(double v)
00256 {
00257
00258 ipg_ = (15 * ipg_ + v) / 16;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 int IvsReceiver::lossMeter(double timeDiff, u_int32_t seq, double maxrtt)
00272 {
00273
00274
00275
00276
00277
00278
00279
00280
00281 double now = Scheduler::instance().clock();
00282 if (nextSeq_ == 0)
00283 nextSeq_ = seq + 1;
00284 else if (seq == nextSeq_)
00285 nextSeq_++;
00286 else if (seq > nextSeq_) {
00287 #ifdef notdef
00288 if (trace_ != 0) {
00289 sprintf(trace_->buffer(), "d %g %d",
00290 lastPktTime_, seq - nextSeq_);
00291 trace_->dump();
00292 }
00293 #endif
00294
00295
00296 Mc_Hole* hole = new Mc_Hole;
00297 hole->time = now;
00298 hole->start = nextSeq_;
00299 hole->end = seq - 1;
00300 hole->next = 0;
00301
00302 if (head_ == NULL) {
00303 head_ = hole;
00304 tail_ = hole;
00305 } else {
00306 tail_->next = hole;
00307 tail_ = hole;
00308 }
00309 nextSeq_ = seq + 1;
00310 } else {
00311
00312 fprintf(stderr, "ns: ivs rcvr: seq number went backward\n");
00313 abort();
00314 }
00315
00316
00317
00318 if (timeMean_ == 0)
00319 timeMean_ = timeDiff;
00320 else
00321 timeMean_ = (7 * timeMean_ + timeDiff) / 8;
00322
00323 timeDiff -= timeMean_;
00324 if (timeDiff < 0)
00325 timeDiff = -timeDiff;
00326
00327 timeVar_ = (7 * timeVar_ + timeDiff) / 8;
00328
00329 int lostPkts = 0;
00330
00331
00332
00333
00334
00335 if (head_ == 0)
00336 return (ST_U);
00337
00338 Mc_Hole *cur = head_, *prev = NULL;
00339
00340 double validEnd = now - 2 * timeVar_;
00341 double validStart = validEnd - maxrtt;
00342
00343
00344
00345
00346
00347 while (cur != NULL) {
00348 if (cur->time < validStart) {
00349 if (prev == NULL)
00350 head_ = cur->next;
00351 else
00352 prev->next = cur->next;
00353 delete cur;
00354 if (prev == NULL)
00355 cur = head_;
00356 else
00357 cur = prev->next;
00358 } else {
00359 if (cur->time < validEnd)
00360 lostPkts += cur->end - cur->start + 1;
00361 prev = cur;
00362 cur = cur->next;
00363 }
00364 }
00365
00366
00367
00368
00369
00370
00371 double pps = (ipg_ != 0) ? maxrtt / ipg_ : 0.;
00372
00373
00374 #ifdef notdef
00375 if (trace_ != 0) {
00376 double now = Scheduler::instance().clock();
00377 sprintf(trace_->buffer(), "%.17g %g", now,
00378 (double)lostPkts / pps);
00379 trace_->dump();
00380 }
00381 #endif
00382
00383
00384 #define LOSSCONGTH 15
00385 #define LOSSLOADTH 5
00386
00387 if ((pps * LOSSCONGTH) / 100 < 2)
00388 pps = 200 / LOSSCONGTH;
00389
00390 if (lostPkts <= (LOSSLOADTH * pps) / 100)
00391 return (ST_U);
00392 else if (lostPkts <= (LOSSCONGTH * pps) / 100)
00393 return (ST_L);
00394 else
00395 return (ST_C);
00396 }
00397
00398 void IvsReceiver::recv(Packet* pkt, Handler*)
00399 {
00400 hdr_ivs *p = hdr_ivs::access(pkt);
00401 double now = Scheduler::instance().clock();
00402
00403 if (lastPktTime_ == 0.) {
00404 lastPktTime_ = now;
00405 Packet::free(pkt);
00406 return;
00407 }
00408 update_ipg(now - lastPktTime_);
00409 double ts = p->ts();
00410 int prevState = state_;
00411 state_ = lossMeter(now - ts, p->seqno(), p->maxrtt());
00412
00413 lastPktTime_ = now;
00414
00415
00416 if (p->R() && !ignoreR_)
00417
00418 upcall_rtt_solicit(ts, p->rshft());
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 if (now - lastTime_ < p->maxrtt() && state_ <= prevState) {
00429 Packet::free(pkt);
00430 return;
00431 }
00432
00433 int shift = p->kshft();
00434 int match;
00435 if (p->key() == 0)
00436 match = 1;
00437 else
00438 match = (key_ >> shift) == (p->key() >> shift);
00439
00440 int matchS = match ? p->S() : 0;
00441
00442 if (state_ == ST_C || matchS || (match && state_ == ST_L)) {
00443 upcall_respond(ts, matchS);
00444 lastTime_ = now;
00445 }
00446
00447 Packet::free(pkt);
00448 }
00449
00450 void IvsReceiver::upcall_respond(double ts, int matchS)
00451 {
00452 Tcl::instance().evalf("%s respond %.17g %d", name(), ts, matchS);
00453 }
00454
00455 void IvsReceiver::upcall_rtt_solicit(double ts, int rshift)
00456 {
00457 Tcl::instance().evalf("%s solicit-rtt %.17g %d", name(), ts, rshift);
00458 }
00459
00460 int IvsReceiver::command(int argc, const char*const* argv)
00461 {
00462 Tcl& tcl = Tcl::instance();
00463 if (argc == 3) {
00464 if (strcmp(argv[1], "send") == 0) {
00465 Packet* pkt = allocpkt();
00466 hdr_msg* p = hdr_msg::access(pkt);
00467 const char* s = argv[2];
00468 int n = strlen(s);
00469 if (n >= p->maxmsg()) {
00470 tcl.result("message too big");
00471 Packet::free(pkt);
00472 return (TCL_ERROR);
00473 }
00474 strcpy(p->msg(), s);
00475 target_->recv(pkt, (Handler*)0);
00476 return (TCL_OK);
00477 }
00478 }
00479 return (Agent::command(argc, argv));
00480 }