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.26 2005/09/18 23:33:35 tomh 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 sprintf(wrk_, "%8.3f %d %d %d %d %d %d "
00169 STRTOI64_FMTSTR" "STRTOI64_FMTSTR" %d %d "
00170 STRTOI64_FMTSTR" "STRTOI64_FMTSTR" %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 f->epdrops(),
00181 f->ebdrops(),
00182 parrivals(),
00183 barrivals(),
00184 epdrops(),
00185 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 %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 %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 f->qs_pkts(),
00404 f->qs_bytes(),
00405 f->qs_drops()
00406 );
00407 };
00408
00409 void
00410 FlowMon::dumpflow(Tcl_Channel tc, Flow* f)
00411 {
00412 fformat(f);
00413 if (tc != 0) {
00414 int n = strlen(wrk_);
00415 wrk_[n++] = '\n';
00416 wrk_[n] = '\0';
00417 (void)Tcl_Write(tc, wrk_, n);
00418 wrk_[n-1] = '\0';
00419 }
00420 }
00421
00422 int
00423 FlowMon::command(int argc, const char*const* argv)
00424 {
00425 Tcl& tcl = Tcl::instance();
00426 if (argc == 2) {
00427 if (strcmp(argv[1], "classifier") == 0) {
00428 if (classifier_)
00429 tcl.resultf("%s", classifier_->name());
00430 else
00431 tcl.resultf("");
00432 return (TCL_OK);
00433 }
00434 if (strcmp(argv[1], "dump") == 0) {
00435 dumpflows();
00436 return (TCL_OK);
00437 }
00438 if (strcmp(argv[1], "flows") == 0) {
00439
00440 tcl.result(flow_list());
00441 return (TCL_OK);
00442 }
00443 } else if (argc == 3) {
00444 if (strcmp(argv[1], "classifier") == 0) {
00445 classifier_ = (Classifier*)
00446 TclObject::lookup(argv[2]);
00447 if (classifier_ == NULL)
00448 return (TCL_ERROR);
00449 return (TCL_OK);
00450 }
00451 if (strcmp(argv[1], "attach") == 0) {
00452 int mode;
00453 const char* id = argv[2];
00454 channel_ = Tcl_GetChannel(tcl.interp(),
00455 (char*) id, &mode);
00456 if (channel_ == NULL) {
00457 tcl.resultf("FlowMon (%s): can't attach %s for writing",
00458 name(), id);
00459 return (TCL_ERROR);
00460 }
00461 return (TCL_OK);
00462 }
00463 }
00464 return (EDQueueMonitor::command(argc, argv));
00465 }
00466
00467
00468
00469
00470
00471 static class FlowMonitorClass : public TclClass {
00472 public:
00473 FlowMonitorClass() : TclClass("QueueMonitor/ED/Flowmon") {}
00474 TclObject* create(int, const char*const*) {
00475 return (new FlowMon);
00476 }
00477 } flow_monitor_class;
00478
00479 static class FlowClass : public TclClass {
00480 public:
00481 FlowClass() : TclClass("QueueMonitor/ED/Flow") {}
00482 TclObject* create(int, const char*const*) {
00483 return (new Flow);
00484 }
00485 } flow_class;
00486
00487
00488 static class TaggerTBFlowClass : public TclClass {
00489 public:
00490 TaggerTBFlowClass() : TclClass("QueueMonitor/ED/Flow/TB") {}
00491 TclObject* create(int, const char*const*) {
00492 return (new TaggerTBFlow);
00493 }
00494 } flow_tb_class;
00495
00496
00497 static class TaggerTSWFlowClass : public TclClass {
00498 public:
00499 TaggerTSWFlowClass() : TclClass("QueueMonitor/ED/Flow/TSW") {}
00500 TclObject* create(int, const char*const*) {
00501 return (new TaggerTSWFlow);
00502 }
00503 } flow_tsw_class;
00504
00505
00506 static class TaggerClass : public TclClass {
00507 public:
00508 TaggerClass() : TclClass("QueueMonitor/ED/Tagger") {}
00509 TclObject* create(int, const char*const*) {
00510 return (new Tagger);
00511 }
00512 } tagger_class;
00513