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

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 2000  International Computer Science Institute
  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 ACIRI, the AT&T 
  17.  *      Center for Internet Research at ICSI (the International Computer
  18.  *      Science Institute).
  19.  * 4. Neither the name of ACIRI nor of ICSI may be used
  20.  *    to endorse or promote products derived from this software without
  21.  *    specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  *
  35.  */
  36. #include "pushback-queue.h"
  37. #include "ip.h"
  38. #include "pushback.h"
  39. #include "rate-limit.h"
  40. static class PushbackQueueClass : public TclClass {
  41. public:
  42.   PushbackQueueClass() : TclClass("Queue/RED/Pushback") {}
  43.   TclObject * create(int argc, const char*const* argv) {
  44.     if (argc==4) {
  45.       printf("Missing Argument for Pushback Queue Constructorn");
  46.       exit(-1);
  47.     }
  48.     return (new PushbackQueue(argv[4]));
  49.   }
  50. } class_pushback_queue;
  51. PushbackQueue::PushbackQueue(const char* const pba): pushbackID_(-1), src_(-1), dst_(-1), 
  52.   qmon_(NULL), RLDropTrace_(NULL) {
  53.   
  54.   pushback_ = (PushbackAgent *)TclObject::lookup(pba);
  55.   if (pushback_ == NULL) {
  56.     printf("Wrong Argument for Pushback Queue Constructorn");
  57.     exit(-1);
  58.   }
  59.   bind("pushbackID_", &pushbackID_);
  60.   bind_bool("rate_limiting_", &rate_limiting_);
  61.   verbose_ = pushback_->verbose_;
  62.   
  63.   timer_ = new PushbackQueueTimer(this);
  64.   timer_->resched(SUSTAINED_CONGESTION_PERIOD);
  65.   rateEstimator_=new RateEstimator();
  66.   rlsList_ = new RateLimitSessionList();
  67.   if (verbose_) printf("pushback queue instantiated %dn",pushback_->last_index_);
  68.   
  69. }
  70. void
  71. PushbackQueue::reportDrop(Packet *p) {
  72.   if (debug_) 
  73.     printf("PBQ:(%d:%d) rate limiting = %dn", src_, dst_, rate_limiting_);
  74.   
  75.   if (rate_limiting_) 
  76.     pushback_->reportDrop(pushbackID_, p);
  77.   
  78. }
  79. int 
  80. PushbackQueue::command(int argc, const char*const* argv)
  81. {
  82.   Tcl& tcl = Tcl::instance();
  83.   if (argc==2) {
  84.   if (strcmp(argv[1], "rldrop-trace") == 0) {
  85.   if (RLDropTrace_ != NULL) {
  86.   tcl.resultf("%s", RLDropTrace_->name());
  87.   }
  88.   else {
  89.   tcl.resultf("0");
  90.   }
  91.   return (TCL_OK);
  92.   }
  93.   
  94.   }
  95.   else if (argc == 3) {
  96.   if (strcmp(argv[1], "set-monitor") == 0) {
  97.   qmon_ = (EDQueueMonitor *)TclObject::lookup(argv[2]);
  98.   if (qmon_ == NULL) {
  99.   tcl.resultf("Got Invalid Queue Monitorn");
  100.   return TCL_ERROR;
  101.   }
  102.   return TCL_OK;
  103.   }
  104.   else if (strcmp(argv[1], "rldrop-trace") == 0) {
  105.   
  106.   RLDropTrace_ = (NsObject *) TclObject::lookup(argv[2]);
  107.   if (RLDropTrace_ == NULL) {
  108.   if (debug_) printf("Error Attaching Tracen");
  109.   return (TCL_ERROR);
  110.   }
  111.   if (debug_) 
  112.   printf("PBQ: RLDropTrace Set to %sn", RLDropTrace_->name());
  113.   return (TCL_OK);
  114.  }
  115.   } else if (argc == 4) {
  116.      if (strcmp(argv[1], "set-src-dst") == 0) {
  117.        src_ = atoi(argv[2]);
  118.        dst_ = atoi(argv[3]);
  119.        if (src_ < 0 || dst_ < 0) {
  120.  tcl.resultf("Got Invalid Source or Destinationn");
  121.  return TCL_ERROR;
  122.        }
  123.        return TCL_OK;
  124.      }
  125.   } 
  126.   
  127.   return REDQueue::command(argc, argv);
  128. }
  129.  
  130. void 
  131. PushbackQueue::timeout(int from) {
  132.   
  133.   int barrivals = qmon_->barrivals() - qmon_->mon_ebdrops();
  134.   int bdrops = qmon_->bdrops() - qmon_->mon_ebdrops();
  135.   int bdeps = qmon_->bdepartures();
  136.   // an alternate way of calculating this is using the arrivals and drops from above, 
  137.   // but the below is more accurate as RED avg queue takes time to come down and
  138.   // hence drop rate goes down much slower.
  139.   double dropRate1= getDropRate();
  140.   double dropRate2= ((double)bdrops/barrivals);
  141.   if (dropRate1 > 0 || dropRate2 > 0) {
  142.   if (verbose_) 
  143.   printf("PBQ:(%d:%d) (%g) arrs %d  drops %d deps %d mdrops %d dr %g %gn", 
  144.  src_, dst_, Scheduler::instance().clock(), 
  145.  barrivals*8, bdrops*8, bdeps*8, qmon_->mon_ebdrops()*8, dropRate1, dropRate2);
  146.   fflush(stdout);
  147.   }
  148.   Tcl& tcl = Tcl::instance();
  149.   tcl.evalf("%s reset",qmon_->name());
  150.   
  151.   if (rate_limiting_ && 
  152.       dropRate1 >= SUSTAINED_CONGESTION_DROPRATE && 
  153.       dropRate2 >= SUSTAINED_CONGESTION_DROPRATE/2) {
  154.   if (verbose_) {
  155.       printf("PBQ:(%d:%d) (%g) Arr: %d (%g) Drops: %d (%g %g) BW: %gn", 
  156.      src_, dst_, Scheduler::instance().clock(), 
  157.      barrivals, rateEstimator_->estRate_, 
  158.      bdrops, dropRate1, dropRate2, link_->bandwidth());
  159.       fflush(stdout);
  160.   }
  161.   
  162.     // this function call would 
  163.     //  1) start a rate limiting session, 
  164.     //  2) insert it in the queues rate limiting session list.
  165.     //  3) will also set up appropriate timers.
  166.     pushback_->identifyAggregate(pushbackID_, rateEstimator_->estRate_, link_->bandwidth());
  167.   }
  168.   else if (rlsList_->noMySessions(pushback_->node_->nodeid()) && LOWER_BOUND_MODE == 1) {
  169.       pushback_->calculateLowerBound(pushbackID_, rateEstimator_->estRate_);
  170.   }
  171.   //reset the drop history at the agent
  172.   pushback_->resetDropLog(pushbackID_);
  173.   timer_->resched(SUSTAINED_CONGESTION_PERIOD);
  174. }
  175.   
  176. void 
  177. PushbackQueue::enque(Packet *p) {
  178.   hdr_cmn * hdr = HDR_CMN(p);
  179.   if (debug_) 
  180.     printf("In queue enque with ptype %d %dn", hdr->ptype(), PT_PUSHBACK);
  181.   if (hdr->ptype_ == PT_PUSHBACK) {
  182.   if (verbose_) printf("PBQ:(%d:%d). Got a pushback packet.n",src_, dst_);
  183.   q_->enqueHead(p);
  184.   return;
  185.   }
  186.   int dropped = 0;
  187.   //set lowDemand to 0 to switch off the low-demand feature.
  188.   int qlen = qib_ ? q_->byteLength() : q_->length();
  189.   int lowDemand = (edv_.v_ave < edp_.th_min || qlen < 1 || getDropRate() < 0.1*TARGET_DROPRATE );
  190.   //  lowDemand = 0;
  191.   
  192.   //this would 
  193.   // 1. check to see if a packet belongs to any of the aggregate being rate-limited
  194.   // 2. if yes, log the packet and 
  195.   // 3. drop it if necessary (based on rate-limiting dynamics).
  196.   // 4. dropped = 1, if dropped.
  197.   if (rlsList_->noSessions_) 
  198.     dropped = rlsList_->filter(p, lowDemand);
  199.   
  200.   if (dropped) {
  201.     //first trace the monitored early drop
  202.   if (RLDropTrace_!= NULL) 
  203.      ((Trace *)RLDropTrace_)->recvOnly(p);
  204.      
  205.   qmon_->mon_edrop(p);
  206.   
  207.   //this is buggy. 
  208.   //this drop is not recorded by any other monitor attached to the link.
  209.   Packet::free(p);
  210.   return;
  211.   }
  212.   
  213.   //estimate rate only for enqued packets (insignificant bw of pushback messages).
  214.   //also counts packet not dropped because of low demand (minor effects to overall demand calculations I believe).
  215.   rateEstimator_->estimateRate(p);
  216.   REDQueue::enque(p);
  217. }
  218. double
  219. PushbackQueue::getRate() {
  220.   return rateEstimator_->estRate_; 
  221. }
  222. double 
  223. PushbackQueue::getBW() { 
  224.   return link_->bandwidth(); 
  225. }
  226. double
  227. PushbackQueue::getDropRate() {
  228.   if (rateEstimator_->estRate_ < getBW()) {
  229.     return 0;
  230.   } else {
  231.     return 1 - getBW()/rateEstimator_->estRate_;
  232.   }
  233. }
  234.