Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

flowmon.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) 1997 The 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 Network Research
00017  *      Group at Lawrence Berkeley National 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 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 // flow-monitor, basically a port from the ns-1 flow manager,
00042 // but architected somewhat differently to better fit the ns-2
00043 // object framework -KF
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 //                if (trace_) {
00091 //                  sprintf(trace_->buffer(), "Tagged prob %g, p %g, count %d",
00092 //                          prob, p, count1);
00093 //                  trace_->dump();
00094 //                }
00095         }
00096 
00097         if (retVal == 0) {
00098             hdr_flags::access(pkt)->pri_=1; //Tag the packet as In.
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  * Methods for Tagger
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         // insane but true: egcs 2.96 doesnt think "int eprops() const"
00169         // matches %d
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,            // 1: time
00172                 f->flowid(),    // 2: flowid
00173                 0,              // 3: category
00174                 f->ptype(),     // 4: type (from common header)
00175                 f->flowid(),    // 5: flowid (formerly class)
00176                 f->src(),       // 6: sender
00177                 f->dst(),       // 7: receiver
00178                 f->parrivals(), // 8: arrivals this flow (pkts)
00179                 f->barrivals(), // 9: arrivals this flow (bytes)
00180                 int(f->epdrops()),   // 10: early drops this flow (pkts)
00181                 int(f->ebdrops()),   // 11: early drops this flow (bytes)
00182                 parrivals(),    // 12: all arrivals (pkts)
00183                 barrivals(),    // 13: all arrivals (bytes)
00184                 int(epdrops()),      // 14: total early drops (pkts)
00185                 int(ebdrops()),      // 15: total early drops (bytes)
00186                 pdrops(),       // 16: total drops (pkts)
00187                 bdrops(),       // 17: total drops (bytes)
00188                 f->pdrops(),    // 18: drops this flow (pkts) [includes edrops]
00189                 f->bdrops(),    // 19: drops this flow (bytes) [includes edrops]
00190                 pmarks()        // 20: marks this flow (pkts)
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  * Methods for FlowMon
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 //added for monitored early drops - ratul
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 /* no 64-bit int */
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,            // 1: time
00385                 f->flowid(),    // 2: flowid
00386                 0,              // 3: category
00387                 f->ptype(),     // 4: type (from common header)
00388                 f->flowid(),    // 5: flowid (formerly class)
00389                 f->src(),       // 6: sender
00390                 f->dst(),       // 7: receiver
00391                 f->parrivals(), // 8: arrivals this flow (pkts)
00392                 f->barrivals(), // 9: arrivals this flow (bytes)
00393                 f->epdrops(),   // 10: early drops this flow (pkts)
00394                 f->ebdrops(),   // 11: early drops this flow (bytes)
00395                 parrivals(),    // 12: all arrivals (pkts)
00396                 barrivals(),    // 13: all arrivals (bytes)
00397                 epdrops(),      // 14: total early drops (pkts)
00398                 ebdrops(),      // 15: total early drops (bytes)
00399                 pdrops(),       // 16: total drops (pkts)
00400                 bdrops(),       // 17: total drops (bytes)
00401                 f->pdrops(),    // 18: drops this flow (pkts) [includes edrops]
00402                 f->bdrops()     // 19: drops this flow (bytes) [includes edrops]
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                         //      printf("command says gimme flow list\n");
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  * Tcl Stuff
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 /* Added by Yun Wang */
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 /* Added by Yun Wang */
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 /* Added by Yun Wang */
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 

Generated on Tue Apr 20 12:14:17 2004 for NS2.26SourcesOriginal by doxygen 1.3.3