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/tools/flowmon.cc,v 1.23 2002/03/10 04:43:31 sfloyd Exp $ (LBL)";
00038 #endif
00039
00040
00041
00042
00043
00044
00045
00046 #include "flowmon.h"
00047
00048 void TaggerTSWFlow::tagging(Packet *pkt)
00049 {
00050 double now = Scheduler::instance().clock();;
00051 double p, prob, u;
00052 int count1;
00053 int retVal;
00054
00055 run_rate_estimator(pkt, now);
00056
00057 if (avg_rate_ <= target_rate_) {
00058 prob = 0;
00059 retVal = 0;
00060 }
00061 else {
00062 prob = (avg_rate_ - target_rate_) / avg_rate_;
00063 p = prob;
00064 count1 = count;
00065
00066 if ( p < 0.5) {
00067 if (wait_) {
00068 if (count1 * p < 1)
00069 p = 0;
00070 else if (count1 * p < 2)
00071 p /= (2 - count1 *p);
00072 else
00073 p = 1;
00074 }
00075 else if (!wait_) {
00076 if (count1 * p < 1)
00077 p /= (1 - count1 * p);
00078 else
00079 p = 1;
00080 }
00081 }
00082
00083 u = Random::uniform();
00084 if (u < p) {
00085 retVal = 1;
00086 }
00087 else
00088 retVal = 0;
00089
00090
00091
00092
00093
00094
00095 }
00096
00097 if (retVal == 0) {
00098 hdr_flags::access(pkt)->pri_=1;
00099 total_in = total_in + 1;
00100 ++count;
00101 }
00102 else {
00103 total_out = total_out + 1;
00104 count = 0;
00105 }
00106 };
00107
00108
00109
00110
00111
00112 void
00113 Tagger::in(Packet *p)
00114 {
00115 Flow* desc;
00116 EDQueueMonitor::in(p);
00117 if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
00118 desc->setfields(p);
00119 desc->tagging(p);
00120 desc->in(p);
00121 }
00122 }
00123
00124 void
00125 Tagger::dumpflows()
00126 {
00127 register int i, j = classifier_->maxslot();
00128 Flow* f;
00129
00130 for (i = 0; i <= j; i++) {
00131 if ((f = (Flow*)classifier_->slot(i)) != NULL)
00132 dumpflow(channel_, f);
00133 }
00134 }
00135
00136 char*
00137 Tagger::flow_list()
00138 {
00139 register const char* z;
00140 register int i, j = classifier_->maxslot();
00141 Flow* f;
00142 register char* p = wrk_;
00143 register char* q;
00144 q = p + sizeof(wrk_) - 2;
00145 *p = '\0';
00146 for (i = 0; i <= j; i++) {
00147 if ((f = (Flow*)classifier_->slot(i)) != NULL) {
00148 z = f->name();
00149 while (*z && p < q)
00150 *p++ = *z++;
00151 *p++ = ' ';
00152 }
00153 if (p >= q) {
00154 fprintf(stderr, "Tagger:: flow list exceeded working buffer\n");
00155 fprintf(stderr, "\t recompile ns with larger Tagger::wrk_[] array\n");
00156 exit (1);
00157 }
00158 }
00159 if (p != wrk_)
00160 *--p = '\0';
00161 return (wrk_);
00162 }
00163
00164 void
00165 Tagger::fformat(Flow* f)
00166 {
00167 double now = Scheduler::instance().clock();
00168
00169
00170 sprintf(wrk_, "%8.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
00171 now,
00172 f->flowid(),
00173 0,
00174 f->ptype(),
00175 f->flowid(),
00176 f->src(),
00177 f->dst(),
00178 f->parrivals(),
00179 f->barrivals(),
00180 int(f->epdrops()),
00181 int(f->ebdrops()),
00182 parrivals(),
00183 barrivals(),
00184 int(epdrops()),
00185 int(ebdrops()),
00186 pdrops(),
00187 bdrops(),
00188 f->pdrops(),
00189 f->bdrops(),
00190 pmarks()
00191 );
00192 }
00193
00194 void
00195 Tagger::dumpflow(Tcl_Channel tc, Flow* f)
00196 {
00197 fformat(f);
00198 if (tc != 0) {
00199 int n = strlen(wrk_);
00200 wrk_[n++] = '\n';
00201 wrk_[n] = '\0';
00202 (void)Tcl_Write(tc, wrk_, n);
00203 wrk_[n-1] = '\0';
00204 }
00205 }
00206
00207 int
00208 Tagger::command(int argc, const char*const* argv)
00209 {
00210 Tcl& tcl = Tcl::instance();
00211 if (argc == 2) {
00212 if (strcmp(argv[1], "classifier") == 0) {
00213 if (classifier_)
00214 tcl.resultf("%s", classifier_->name());
00215 else
00216 tcl.resultf("");
00217 return (TCL_OK);
00218 }
00219 if (strcmp(argv[1], "dump") == 0) {
00220 dumpflows();
00221 return (TCL_OK);
00222 }
00223 if (strcmp(argv[1], "flows") == 0) {
00224 tcl.result(flow_list());
00225 return (TCL_OK);
00226 }
00227 } else if (argc == 3) {
00228 if (strcmp(argv[1], "classifier") == 0) {
00229 classifier_ = (Classifier*)
00230 TclObject::lookup(argv[2]);
00231 if (classifier_ == NULL)
00232 return (TCL_ERROR);
00233 return (TCL_OK);
00234 }
00235 if (strcmp(argv[1], "attach") == 0) {
00236 int mode;
00237 const char* id = argv[2];
00238 channel_ = Tcl_GetChannel(tcl.interp(),
00239 (char*) id, &mode);
00240 if (channel_ == NULL) {
00241 tcl.resultf("Tagger (%s): can't attach %s for writing",
00242 name(), id);
00243 return (TCL_ERROR);
00244 }
00245 return (TCL_OK);
00246 }
00247 }
00248 return (EDQueueMonitor::command(argc, argv));
00249 }
00250
00251
00252
00253
00254
00255
00256 FlowMon::FlowMon() : classifier_(NULL), channel_(NULL),
00257 enable_in_(1), enable_out_(1), enable_drop_(1), enable_edrop_(1), enable_mon_edrop_(1)
00258 {
00259 bind_bool("enable_in_", &enable_in_);
00260 bind_bool("enable_out_", &enable_out_);
00261 bind_bool("enable_drop_", &enable_drop_);
00262 bind_bool("enable_edrop_", &enable_edrop_);
00263 }
00264
00265 void
00266 FlowMon::in(Packet *p)
00267 {
00268 Flow* desc;
00269
00270 EDQueueMonitor::in(p);
00271 if (!enable_in_)
00272 return;
00273 if ((desc = ((Flow *)classifier_->find(p))) != NULL) {
00274 desc->setfields(p);
00275 desc->in(p);
00276 }
00277 }
00278
00279 void
00280 FlowMon::out(Packet *p)
00281 {
00282 Flow* desc;
00283 EDQueueMonitor::out(p);
00284 if (!enable_out_)
00285 return;
00286 if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
00287 desc->setfields(p);
00288 desc->out(p);
00289 }
00290 }
00291
00292 void
00293 FlowMon::drop(Packet *p)
00294 {
00295 Flow* desc;
00296 EDQueueMonitor::drop(p);
00297 if (!enable_drop_)
00298 return;
00299 if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
00300 desc->setfields(p);
00301 desc->drop(p);
00302 }
00303 }
00304
00305 void
00306 FlowMon::edrop(Packet *p)
00307 {
00308 Flow* desc;
00309 EDQueueMonitor::edrop(p);
00310 if (!enable_edrop_)
00311 return;
00312 if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
00313 desc->setfields(p);
00314 desc->edrop(p);
00315 }
00316 }
00317
00318
00319 void
00320 FlowMon::mon_edrop(Packet *p)
00321 {
00322 Flow* desc;
00323 EDQueueMonitor::mon_edrop(p);
00324 if (!enable_mon_edrop_)
00325 return;
00326 if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
00327 desc->setfields(p);
00328 desc->mon_edrop(p);
00329 }
00330 }
00331
00332 void
00333 FlowMon::dumpflows()
00334 {
00335 register int i, j = classifier_->maxslot();
00336 Flow* f;
00337
00338 for (i = 0; i <= j; i++) {
00339 if ((f = (Flow*)classifier_->slot(i)) != NULL)
00340 dumpflow(channel_, f);
00341 }
00342 }
00343
00344 char*
00345 FlowMon::flow_list()
00346 {
00347 register const char* z;
00348 register int i, j = classifier_->maxslot();
00349 Flow* f;
00350 register char* p = wrk_;
00351 register char* q;
00352 q = p + sizeof(wrk_) - 2;
00353 *p = '\0';
00354
00355 for (i = 0; i <= j; i++) {
00356 if ((f = (Flow*)classifier_->slot(i)) != NULL) {
00357
00358 z = f->name();
00359 while (*z && p < q) {
00360 *p++ = *z++;
00361 }
00362 *p++ = ' ';
00363 }
00364 if (p >= q) {
00365 fprintf(stderr, "FlowMon:: flow list exceeded working buffer\n");
00366 fprintf(stderr, "\t recompile ns with larger FlowMon::wrk_[] array\n");
00367 exit (1);
00368 }
00369 }
00370 if (p != wrk_)
00371 *--p = '\0';
00372 return (wrk_);
00373 }
00374
00375 void
00376 FlowMon::fformat(Flow* f)
00377 {
00378 double now = Scheduler::instance().clock();
00379 #if defined(HAVE_INT64)
00380 sprintf(wrk_, "%8.3f %d %d %d %d %d %d " STRTOI64_FMTSTR " " STRTOI64_FMTSTR " %d %d " STRTOI64_FMTSTR " " STRTOI64_FMTSTR " %d %d %d %d %d %d",
00381 #else
00382 sprintf(wrk_, "%8.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
00383 #endif
00384 now,
00385 f->flowid(),
00386 0,
00387 f->ptype(),
00388 f->flowid(),
00389 f->src(),
00390 f->dst(),
00391 f->parrivals(),
00392 f->barrivals(),
00393 f->epdrops(),
00394 f->ebdrops(),
00395 parrivals(),
00396 barrivals(),
00397 epdrops(),
00398 ebdrops(),
00399 pdrops(),
00400 bdrops(),
00401 f->pdrops(),
00402 f->bdrops()
00403 );
00404 };
00405
00406 void
00407 FlowMon::dumpflow(Tcl_Channel tc, Flow* f)
00408 {
00409 fformat(f);
00410 if (tc != 0) {
00411 int n = strlen(wrk_);
00412 wrk_[n++] = '\n';
00413 wrk_[n] = '\0';
00414 (void)Tcl_Write(tc, wrk_, n);
00415 wrk_[n-1] = '\0';
00416 }
00417 }
00418
00419 int
00420 FlowMon::command(int argc, const char*const* argv)
00421 {
00422 Tcl& tcl = Tcl::instance();
00423 if (argc == 2) {
00424 if (strcmp(argv[1], "classifier") == 0) {
00425 if (classifier_)
00426 tcl.resultf("%s", classifier_->name());
00427 else
00428 tcl.resultf("");
00429 return (TCL_OK);
00430 }
00431 if (strcmp(argv[1], "dump") == 0) {
00432 dumpflows();
00433 return (TCL_OK);
00434 }
00435 if (strcmp(argv[1], "flows") == 0) {
00436
00437 tcl.result(flow_list());
00438 return (TCL_OK);
00439 }
00440 } else if (argc == 3) {
00441 if (strcmp(argv[1], "classifier") == 0) {
00442 classifier_ = (Classifier*)
00443 TclObject::lookup(argv[2]);
00444 if (classifier_ == NULL)
00445 return (TCL_ERROR);
00446 return (TCL_OK);
00447 }
00448 if (strcmp(argv[1], "attach") == 0) {
00449 int mode;
00450 const char* id = argv[2];
00451 channel_ = Tcl_GetChannel(tcl.interp(),
00452 (char*) id, &mode);
00453 if (channel_ == NULL) {
00454 tcl.resultf("FlowMon (%s): can't attach %s for writing",
00455 name(), id);
00456 return (TCL_ERROR);
00457 }
00458 return (TCL_OK);
00459 }
00460 }
00461 return (EDQueueMonitor::command(argc, argv));
00462 }
00463
00464
00465
00466
00467
00468 static class FlowMonitorClass : public TclClass {
00469 public:
00470 FlowMonitorClass() : TclClass("QueueMonitor/ED/Flowmon") {}
00471 TclObject* create(int, const char*const*) {
00472 return (new FlowMon);
00473 }
00474 } flow_monitor_class;
00475
00476 static class FlowClass : public TclClass {
00477 public:
00478 FlowClass() : TclClass("QueueMonitor/ED/Flow") {}
00479 TclObject* create(int, const char*const*) {
00480 return (new Flow);
00481 }
00482 } flow_class;
00483
00484
00485 static class TaggerTBFlowClass : public TclClass {
00486 public:
00487 TaggerTBFlowClass() : TclClass("QueueMonitor/ED/Flow/TB") {}
00488 TclObject* create(int, const char*const*) {
00489 return (new TaggerTBFlow);
00490 }
00491 } flow_tb_class;
00492
00493
00494 static class TaggerTSWFlowClass : public TclClass {
00495 public:
00496 TaggerTSWFlowClass() : TclClass("QueueMonitor/ED/Flow/TSW") {}
00497 TclObject* create(int, const char*const*) {
00498 return (new TaggerTSWFlow);
00499 }
00500 } flow_tsw_class;
00501
00502
00503 static class TaggerClass : public TclClass {
00504 public:
00505 TaggerClass() : TclClass("QueueMonitor/ED/Tagger") {}
00506 TclObject* create(int, const char*const*) {
00507 return (new Tagger);
00508 }
00509 } tagger_class;
00510