flowmon.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:14k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
  2.  *
  3.  * Copyright (c) 1997 The Regents of the University of California.
  4.  * All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *  This product includes software developed by the Network Research
  17.  *  Group at Lawrence Berkeley National Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. #ifndef lint
  35. static const char rcsid[] =
  36.     "@(#) $Header: /cvsroot/nsnam/ns-2/tools/flowmon.cc,v 1.27 2006/02/21 15:20:20 mahrenho Exp $ (LBL)";
  37. #endif
  38. //
  39. // flow-monitor, basically a port from the ns-1 flow manager,
  40. // but architected somewhat differently to better fit the ns-2
  41. // object framework -KF
  42. //
  43. #include "flowmon.h"
  44. void TaggerTSWFlow::tagging(Packet *pkt)
  45. {
  46.         double now = Scheduler::instance().clock();;
  47.         double  p, prob, u;
  48.         int count1;
  49.         int retVal;
  50.         run_rate_estimator(pkt, now);
  51.         if (avg_rate_ <= target_rate_) {
  52.                 prob = 0;
  53.                 retVal = 0;
  54.         }
  55.         else {
  56.                prob = (avg_rate_ - target_rate_) / avg_rate_;
  57.                p    = prob;
  58.                count1 = count;
  59.                if ( p < 0.5) {
  60.                  if (wait_) {
  61.                    if (count1 * p < 1)
  62.                      p = 0;
  63.                    else if (count1 * p < 2)
  64.                      p /= (2 - count1 *p);
  65.                    else
  66.                      p = 1;
  67.                  }
  68.                  else if (!wait_) {
  69.                    if (count1 * p < 1)
  70.                      p /= (1 - count1 * p);
  71.                    else
  72.                      p = 1;
  73.                  }
  74.                }
  75.                 u = Random::uniform();
  76.                 if (u < p) {
  77.                     retVal = 1;
  78.                 }
  79.                 else
  80.                   retVal = 0;
  81. //                if (trace_) {
  82. //                  sprintf(trace_->buffer(), "Tagged prob %g, p %g, count %d",
  83. //                          prob, p, count1);
  84. //                  trace_->dump();
  85. //                }
  86.         }
  87.         if (retVal == 0) {
  88.             hdr_flags::access(pkt)->pri_=1; //Tag the packet as In.
  89.             total_in = total_in + 1;
  90.             ++count;
  91.         }
  92.         else {
  93.             total_out = total_out + 1;
  94.             count = 0;
  95.         }
  96. }
  97. /* ####################################
  98.  * Methods for Tagger
  99.  * ####################################
  100.  */
  101. void
  102. Tagger::in(Packet *p)
  103. {
  104.         Flow* desc;
  105.         EDQueueMonitor::in(p);
  106.         if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
  107.                 desc->setfields(p);
  108. desc->tagging(p);
  109.                 desc->in(p);
  110.         }
  111. void
  112. Tagger::dumpflows()
  113. {
  114.         register int i, j = classifier_->maxslot();
  115.         Flow* f;
  116.         for (i = 0; i <= j; i++) {
  117.                 if ((f = (Flow*)classifier_->slot(i)) != NULL)
  118.                         dumpflow(channel_, f);
  119.         }
  120. }
  121. char*
  122. Tagger::flow_list()
  123. {
  124.         register const char* z;
  125.         register int i, j = classifier_->maxslot();
  126.         Flow* f;
  127.         register char* p = wrk_;
  128.         register char* q;
  129.         q = p + sizeof(wrk_) - 2;
  130.         *p = '';
  131.         for (i = 0; i <= j; i++) {
  132.                 if ((f = (Flow*)classifier_->slot(i)) != NULL) {
  133.                         z = f->name();
  134.                         while (*z && p < q)
  135.                                 *p++ = *z++;
  136.                         *p++ = ' ';
  137.                 }
  138.                 if (p >= q) {
  139.                         fprintf(stderr, "Tagger:: flow list exceeded working buffern");
  140.                         fprintf(stderr, "t  recompile ns with larger Tagger::wrk_[] arrayn");
  141.                         exit (1);
  142.                 }
  143.         }
  144.         if (p != wrk_)
  145.                 *--p = '';
  146.         return (wrk_);
  147. }
  148. void
  149. Tagger::fformat(Flow* f)
  150. {
  151.         double now = Scheduler::instance().clock();
  152.         sprintf(wrk_, "%8.3f %d %d %d %d %d %d "
  153. STRTOI64_FMTSTR" "STRTOI64_FMTSTR" %d %d "
  154. STRTOI64_FMTSTR" "STRTOI64_FMTSTR" %d %d %d %d %d %d %d",
  155.                 now,            // 1: time
  156.                 f->flowid(),    // 2: flowid
  157.                 0,              // 3: category
  158.                 f->ptype(),     // 4: type (from common header)
  159.                 f->flowid(),    // 5: flowid (formerly class)
  160.                 f->src(),       // 6: sender
  161.                 f->dst(),       // 7: receiver
  162.                 f->parrivals(), // 8: arrivals this flow (pkts)
  163.                 f->barrivals(), // 9: arrivals this flow (bytes)
  164.                 f->epdrops(),   // 10: early drops this flow (pkts)
  165.                 f->ebdrops(),   // 11: early drops this flow (bytes)
  166.                 parrivals(),    // 12: all arrivals (pkts)
  167.                 barrivals(),    // 13: all arrivals (bytes)
  168.                 epdrops(),      // 14: total early drops (pkts)
  169.                 ebdrops(),      // 15: total early drops (bytes)
  170.                 pdrops(),       // 16: total drops (pkts)
  171.                 bdrops(),       // 17: total drops (bytes)
  172.                 f->pdrops(),    // 18: drops this flow (pkts) [includes edrops]
  173.                 f->bdrops(),    // 19: drops this flow (bytes) [includes edrops]
  174. pmarks() // 20: marks this flow (pkts)
  175.         );
  176. }
  177. void
  178. Tagger::dumpflow(Tcl_Channel tc, Flow* f)
  179. {
  180.         fformat(f);
  181.         if (tc != 0) {
  182.                 int n = strlen(wrk_);
  183.                 wrk_[n++] = 'n';
  184.                 wrk_[n] = '';
  185.                 (void)Tcl_Write(tc, wrk_, n);
  186.                 wrk_[n-1] = '';
  187.         }
  188. }
  189. int
  190. Tagger::command(int argc, const char*const* argv)
  191. {
  192.         Tcl& tcl = Tcl::instance();
  193.         if (argc == 2) {
  194.                 if (strcmp(argv[1], "classifier") == 0) {
  195.                         if (classifier_)
  196.                                 tcl.resultf("%s", classifier_->name());
  197.                         else
  198.                                 tcl.resultf("");
  199.                         return (TCL_OK);
  200.                 }
  201.                 if (strcmp(argv[1], "dump") == 0) {
  202.                         dumpflows();
  203.                         return (TCL_OK);
  204.                 }
  205.                 if (strcmp(argv[1], "flows") == 0) {
  206.                         tcl.result(flow_list());
  207.                         return (TCL_OK);
  208.                 }
  209.         } else if (argc == 3) {
  210.                 if (strcmp(argv[1], "classifier") == 0) {
  211.                         classifier_ = (Classifier*)
  212.                                 TclObject::lookup(argv[2]);
  213.                         if (classifier_ == NULL)
  214.                                 return (TCL_ERROR);
  215.                         return (TCL_OK);
  216.                 }
  217.                 if (strcmp(argv[1], "attach") == 0) {
  218.                         int mode;
  219.                         const char* id = argv[2];
  220.                         channel_ = Tcl_GetChannel(tcl.interp(),
  221.                                 (char*) id, &mode);
  222.                         if (channel_ == NULL) {
  223.                                 tcl.resultf("Tagger (%s): can't attach %s for writing",
  224.                                         name(), id);
  225.                                 return (TCL_ERROR);
  226.                         }
  227.                         return (TCL_OK);
  228.                 }
  229.         }
  230.         return (EDQueueMonitor::command(argc, argv));
  231. }
  232. /* ####################################
  233.  * Methods for FlowMon
  234.  * ####################################
  235.  */
  236. FlowMon::FlowMon() : classifier_(NULL), channel_(NULL),
  237. enable_in_(1), enable_out_(1), enable_drop_(1), enable_edrop_(1), enable_mon_edrop_(1)
  238. {
  239. bind_bool("enable_in_", &enable_in_);
  240. bind_bool("enable_out_", &enable_out_);
  241. bind_bool("enable_drop_", &enable_drop_);
  242. bind_bool("enable_edrop_", &enable_edrop_);
  243. }
  244. void
  245. FlowMon::in(Packet *p)
  246. {
  247. Flow* desc;
  248. EDQueueMonitor::in(p);
  249. if (!enable_in_)
  250. return;
  251. if ((desc = ((Flow *)classifier_->find(p))) != NULL) {
  252. desc->setfields(p);
  253. desc->in(p);
  254. }
  255. }
  256. void
  257. FlowMon::out(Packet *p)
  258. {
  259. Flow* desc;
  260. EDQueueMonitor::out(p);
  261. if (!enable_out_)
  262. return;
  263. if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
  264. desc->setfields(p);
  265. desc->out(p);
  266. }
  267. }
  268. void
  269. FlowMon::drop(Packet *p)
  270. {
  271. Flow* desc;
  272. EDQueueMonitor::drop(p);
  273. if (!enable_drop_)
  274. return;
  275. if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
  276. desc->setfields(p);
  277. desc->drop(p);
  278. }
  279. }
  280. void
  281. FlowMon::edrop(Packet *p)
  282. {
  283. Flow* desc;
  284. EDQueueMonitor::edrop(p);
  285. if (!enable_edrop_)
  286. return;
  287. if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
  288. desc->setfields(p);
  289. desc->edrop(p);
  290. }
  291. }
  292. //added for monitored early drops - ratul
  293. void
  294. FlowMon::mon_edrop(Packet *p)
  295. {
  296. Flow* desc;
  297. EDQueueMonitor::mon_edrop(p);
  298. if (!enable_mon_edrop_)
  299. return;
  300. if ((desc = ((Flow*)classifier_->find(p))) != NULL) {
  301. desc->setfields(p);
  302. desc->mon_edrop(p);
  303. }
  304. }
  305. void
  306. FlowMon::dumpflows()
  307. {
  308. register int i, j = classifier_->maxslot();
  309. Flow* f;
  310. for (i = 0; i <= j; i++) {
  311. if ((f = (Flow*)classifier_->slot(i)) != NULL)
  312. dumpflow(channel_, f);
  313. }
  314. }
  315. char*
  316. FlowMon::flow_list()
  317. {
  318. register const char* z;
  319. register int i, j = classifier_->maxslot();
  320. Flow* f;
  321. register char* p = wrk_;
  322. register char* q;
  323. q = p + sizeof(wrk_) - 2;
  324. *p = '';
  325. for (i = 0; i <= j; i++) {
  326. if ((f = (Flow*)classifier_->slot(i)) != NULL) {
  327. z = f->name();
  328. while (*z && p < q) {
  329. *p++ = *z++;
  330. }
  331. *p++ = ' ';
  332. }
  333. if (p >= q) {
  334. fprintf(stderr, "FlowMon:: flow list exceeded working buffern");
  335. fprintf(stderr, "t  recompile ns with larger FlowMon::wrk_[] arrayn");
  336. exit (1);
  337. }
  338. }
  339. if (p != wrk_)
  340. *--p = '';
  341. return (wrk_);
  342. }
  343. void
  344. FlowMon::fformat(Flow* f)
  345. {
  346. double now = Scheduler::instance().clock();
  347. #if defined(HAVE_INT64)
  348. 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",
  349. #else /* no 64-bit int */
  350. 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",
  351. #endif
  352. now, // 1: time
  353. f->flowid(), // 2: flowid
  354. 0, // 3: category
  355. f->ptype(), // 4: type (from common header)
  356. f->flowid(), // 5: flowid (formerly class)
  357. f->src(), // 6: sender
  358. f->dst(), // 7: receiver
  359. f->parrivals(), // 8: arrivals this flow (pkts)
  360. f->barrivals(), // 9: arrivals this flow (bytes)
  361. f->epdrops(), // 10: early drops this flow (pkts)
  362. f->ebdrops(), // 11: early drops this flow (bytes)
  363. parrivals(), // 12: all arrivals (pkts)
  364. barrivals(), // 13: all arrivals (bytes)
  365. epdrops(), // 14: total early drops (pkts)
  366. ebdrops(), // 15: total early drops (bytes)
  367. pdrops(), // 16: total drops (pkts)
  368. bdrops(), // 17: total drops (bytes)
  369. f->pdrops(), // 18: drops this flow (pkts) [includes edrops]
  370. f->bdrops(), // 19: drops this flow (bytes) [includes edrops]
  371. f->qs_pkts(), // 20: Quick-Start packets this flow
  372. f->qs_bytes(),  // 21: Quick-Start bytes this flow
  373. f->qs_drops() // 22: dropped Quick-Start pkts this flow
  374. );
  375. }
  376. void
  377. FlowMon::dumpflow(Tcl_Channel tc, Flow* f)
  378. {
  379. fformat(f);
  380. if (tc != 0) {
  381. int n = strlen(wrk_);
  382. wrk_[n++] = 'n';
  383. wrk_[n] = '';
  384. (void)Tcl_Write(tc, wrk_, n);
  385. wrk_[n-1] = '';
  386. }
  387. }
  388. int
  389. FlowMon::command(int argc, const char*const* argv)
  390. {
  391. Tcl& tcl = Tcl::instance();
  392. if (argc == 2) {
  393. if (strcmp(argv[1], "classifier") == 0) {
  394. if (classifier_)
  395. tcl.resultf("%s", classifier_->name());
  396. else
  397. tcl.resultf("");
  398. return (TCL_OK);
  399. }
  400. if (strcmp(argv[1], "dump") == 0) {
  401. dumpflows();
  402. return (TCL_OK);
  403. }
  404. if (strcmp(argv[1], "flows") == 0) {
  405. // printf("command says gimme flow listn");
  406. tcl.result(flow_list());
  407. return (TCL_OK);
  408. }
  409. } else if (argc == 3) {
  410. if (strcmp(argv[1], "classifier") == 0) {
  411. classifier_ = (Classifier*)
  412. TclObject::lookup(argv[2]);
  413. if (classifier_ == NULL)
  414. return (TCL_ERROR);
  415. return (TCL_OK);
  416. }
  417. if (strcmp(argv[1], "attach") == 0) {
  418. int mode;
  419. const char* id = argv[2];
  420. channel_ = Tcl_GetChannel(tcl.interp(),
  421. (char*) id, &mode);
  422. if (channel_ == NULL) {
  423. tcl.resultf("FlowMon (%s): can't attach %s for writing",
  424. name(), id);
  425. return (TCL_ERROR);
  426. }
  427. return (TCL_OK);
  428. }
  429. }
  430. return (EDQueueMonitor::command(argc, argv));
  431. }
  432. /*#####################################
  433.  * Tcl Stuff
  434.  *#####################################
  435.  */
  436. static class FlowMonitorClass : public TclClass {
  437.  public:
  438. FlowMonitorClass() : TclClass("QueueMonitor/ED/Flowmon") {}
  439. TclObject* create(int, const char*const*) {
  440. return (new FlowMon);
  441. }
  442. } flow_monitor_class;
  443. static class FlowClass : public TclClass {
  444.  public:
  445. FlowClass() : TclClass("QueueMonitor/ED/Flow") {}
  446. TclObject* create(int, const char*const*) {
  447. return (new Flow);
  448. }
  449. } flow_class;
  450. /* Added by Yun Wang */
  451. static class TaggerTBFlowClass : public TclClass {
  452.  public:
  453. TaggerTBFlowClass() : TclClass("QueueMonitor/ED/Flow/TB") {}
  454. TclObject* create(int, const char*const*) {
  455. return (new TaggerTBFlow);
  456. }
  457. } flow_tb_class;
  458. /* Added by Yun Wang */
  459. static class TaggerTSWFlowClass : public TclClass {
  460.  public:
  461. TaggerTSWFlowClass() : TclClass("QueueMonitor/ED/Flow/TSW") {}
  462. TclObject* create(int, const char*const*) {
  463. return (new TaggerTSWFlow);
  464. }
  465. } flow_tsw_class;
  466. /* Added by Yun Wang */
  467. static class TaggerClass : public TclClass {
  468.  public:
  469. TaggerClass() : TclClass("QueueMonitor/ED/Tagger") {}
  470. TclObject* create(int, const char*const*) {
  471. return (new Tagger);
  472. }
  473. } tagger_class;