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.26 2005/09/18 23:33:35 tomh 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         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,            // 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                 f->epdrops(),   // 10: early drops this flow (pkts)
00181                 f->ebdrops(),   // 11: early drops this flow (bytes)
00182                 parrivals(),    // 12: all arrivals (pkts)
00183                 barrivals(),    // 13: all arrivals (bytes)
00184                 epdrops(),      // 14: total early drops (pkts)
00185                 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 %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 %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         f->qs_pkts(),   // 20: Quick-Start packets this flow
00404         f->qs_bytes(),  // 21: Quick-Start bytes this flow
00405         f->qs_drops()   // 22: dropped Quick-Start pkts this flow
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             //  printf("command says gimme flow list\n");
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  * Tcl Stuff
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 /* Added by Yun Wang */
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 /* Added by Yun Wang */
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 /* Added by Yun Wang */
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 

Generated on Tue Mar 6 16:47:45 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6