rio.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) 1990-1997 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 Computer Systems
00017  *  Engineering Group at Lawrence Berkeley 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  * Here is one set of parameters from one of Sally's simulations
00036  * (this is from tcpsim, the older simulator):
00037  * 
00038  * ed [ q_weight=0.002 thresh=5 linterm=30 maxthresh=15
00039  *         mean_pktsize=500 dropmech=random-drop queue-size=60
00040  *         plot-file=none bytes=false doubleq=false dqthresh=50 
00041  *     wait=true ]
00042  * 
00043  * 1/"linterm" is the max probability of dropping a packet. 
00044  * There are different options that make the code
00045  * more messy that it would otherwise be.  For example,
00046  * "doubleq" and "dqthresh" are for a queue that gives priority to
00047  *   small (control) packets, 
00048  * "bytes" indicates whether the queue should be measured in bytes 
00049  *   or in packets, 
00050  * "dropmech" indicates whether the drop function should be random-drop 
00051  *   or drop-tail when/if the queue overflows, and 
00052  *   the commented-out Holt-Winters method for computing the average queue 
00053  *   size can be ignored.
00054  * "wait" indicates whether the gateway should wait between dropping
00055  *   packets.
00056  */
00057 
00058 /* Bugreport about rio.cc:
00059  *
00060  * David Ros and LuiWei have both reported, in June 2002 and in May 2001,
00061  * that rio.cc has a bug in that RIO does not calculate a new average
00062  * queue length when an OUT packet arrives.
00063  * 
00064  * This bug has not been checked or repaired.
00065  */
00066 
00067 #ifndef lint
00068 static const char rcsid[] =
00069     "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/rio.cc,v 1.12 2004/05/25 03:23:05 sfloyd Exp $ (LBL)";
00070 #endif
00071 
00072 #include "rio.h"
00073 #include "tclcl.h"
00074 #include "packet.h"
00075 #include "random.h"
00076 #include "flags.h"
00077 #include "delay.h"
00078 #include "template.h"
00079 #include "red.h"
00080 
00081 static class RIOClass : public TclClass {
00082 public:
00083     RIOClass() : TclClass("Queue/RED/RIO") {}
00084     TclObject* create(int, const char*const*) {
00085         return (new RIOQueue);
00086     }
00087 } class_rio;
00088 
00089 RIOQueue::RIOQueue() : in_len_(0), in_bcount_(0), in_idle_(1)
00090 {
00091     bind("in_thresh_", &edp_in_.th_min);        // In_minthresh
00092     bind("in_maxthresh_", &edp_in_.th_max);     // In_maxthresh
00093     bind("out_thresh_", &edp_out_.th_min);      // Out_minthresh
00094     bind("out_maxthresh_", &edp_out_.th_max);   // Out_maxthresh
00095     bind("in_linterm_", &edp_in_.max_p_inv);
00096 
00097     /* added by ratul- allows a finer control over the policy.
00098        gentle automatically means both the below are gentle */
00099     bind_bool("in_gentle_",&edp_in_.gentle);    // drop prob. slowly
00100     bind_bool("out_gentle_",&edp_out_.gentle);  // when ave queue
00101                             // exceeds maxthresh
00102     bind("in_ave_", &edv_in_.v_ave);        // In average queue sie
00103     bind("out_ave_", &edv_out_.v_ave);      // Out average queue sie
00104     bind("in_prob1_", &edv_in_.v_prob1);        // In dropping probability
00105     bind("out_prob1_", &edv_out_.v_prob1);      // Out dropping probability
00106     bind("priority_method_", &priority_method_); // method for setting
00107                             // priority
00108 //  q_ = new PacketQueue();             // underlying queue
00109 //  pq_ = q_;
00110 //  reset();
00111 
00112 }
00113 
00114 void RIOQueue::reset()
00115 {
00116     /*
00117      * If queue is measured in bytes, scale min/max thresh
00118      * by the size of an average packet (which is specified by user).
00119      */
00120 
00121     if (qib_) {
00122         edp_in_.th_min *= edp_.mean_pktsize;
00123         edp_in_.th_max *= edp_.mean_pktsize;
00124 
00125         edp_out_.th_min *= edp_.mean_pktsize;
00126         edp_out_.th_max *= edp_.mean_pktsize;
00127     }
00128 
00129     //modified - ratul
00130     if (edp_.gentle) {
00131         edp_in_.gentle = true;
00132         edp_out_.gentle = true;
00133     }
00134     if (edp_in_.gentle) {
00135         edv_in_.v_c = ( 1.0 - 1 / edp_in_.max_p_inv ) / edp_in_.th_max;
00136         edv_in_.v_d = 2 / edp_in_.max_p_inv - 1.0;
00137     }       
00138     if (edp_out_.gentle) {
00139         edv_out_.v_c = ( 1.0 - 1 / edp_.max_p_inv ) / edp_out_.th_max;
00140         edv_out_.v_d = 2 / edp_.max_p_inv - 1.0;
00141     }
00142 
00143         /* Added by Wenjia */
00144         edv_in_.v_ave = 0.0;
00145         edv_in_.v_slope = 0.0;
00146         edv_in_.drops = 0;
00147         edv_in_.count = 0;
00148         edv_in_.count_bytes = 0;
00149         edv_in_.old = 0;
00150         edv_in_.v_a = 1 / (edp_in_.th_max - edp_in_.th_min);
00151         edv_in_.v_b = - edp_in_.th_min / (edp_in_.th_max - edp_in_.th_min);
00152 
00153         /* Added by Wenjia */
00154         edv_out_.v_ave = 0.0;
00155         edv_out_.v_slope = 0.0;
00156         edv_out_.drops = 0;
00157         edv_out_.count = 0;
00158         edv_out_.count_bytes = 0;
00159         edv_out_.old = 0;
00160         edv_out_.v_a = 1 / (edp_out_.th_max - edp_out_.th_min);
00161         edv_out_.v_b = - edp_out_.th_min / (edp_out_.th_max - edp_out_.th_min);
00162 
00163     in_idle_ = 1;
00164     if (&Scheduler::instance() == NULL) {
00165         in_idletime_ = 0.0; /* sched not instantiated yet */
00166         }     
00167     REDQueue::reset();
00168 }
00169 
00170 /*
00171  * Return the next packet in the queue for transmission.
00172  */
00173 Packet* RIOQueue::deque()
00174 {
00175     Packet *p;
00176     p = REDQueue::deque();
00177         // printf( "qlen %d %d\n", q_->length(), length());
00178     if (p != 0) {
00179         hdr_flags* hf = hdr_flags::access(p);
00180                 if (hf->pri_) {   
00181           /* Regular In packets */
00182                   in_idle_ = 0;
00183           in_bcount_ -= hdr_cmn::access(p)->size();
00184           --in_len_;
00185         }
00186     } else {
00187                 in_idle_ = 1;
00188     }
00189     return (p);
00190 }
00191 
00192 /*
00193  * should the packet be dropped/marked due to a probabilistic drop?
00194  */
00195 int
00196 RIOQueue::drop_in_early(Packet* pkt)
00197 {
00198     hdr_cmn* ch = hdr_cmn::access(pkt);
00199 
00200         edv_in_.v_prob1 = REDQueue::calculate_p(edv_in_.v_ave, edp_in_.th_max, 
00201       edp_in_.gentle, edv_in_.v_a, edv_in_.v_b, edv_in_.v_c, 
00202       edv_in_.v_d, edp_in_.max_p_inv);
00203         edv_in_.v_prob = REDQueue::modify_p(edv_in_.v_prob1, edv_in_.count, 
00204       edv_in_.count_bytes, edp_.bytes, edp_.mean_pktsize, edp_.wait, 
00205       ch->size());
00206 
00207     // drop probability is computed, pick random number and act
00208     double u = Random::uniform();
00209     if (u <= edv_in_.v_prob) {
00210         // DROP or MARK
00211         edv_in_.count = 0;
00212         edv_in_.count_bytes = 0;
00213         hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
00214         if (edp_.setbit && hf->ect() && 
00215                 edv_in_.v_ave < edp_in_.th_max) {
00216             hf->ce() = 1;   // mark Congestion Experienced bit
00217             return (0); // no drop
00218         } else {
00219             return (1); // drop
00220         }
00221     }
00222     return (0);         // no DROP/mark
00223 }
00224 
00225 /*
00226  * Obsolete note from original version of code:
00227  * The rationale here is that if the edv_in_.v_ave is close
00228  * to the edp_in_.th_max, (we are about to turn over to the
00229  * congestion control phase, presumably because of Out packets),
00230  * then we should drop Out packets more severely.
00231  */
00232 
00233 int RIOQueue::drop_out_early(Packet* pkt)
00234 {
00235         hdr_cmn* ch = hdr_cmn::access(pkt);
00236 
00237         edv_out_.v_prob1 = REDQueue::calculate_p(edv_.v_ave, edp_out_.th_max, 
00238       edp_out_.gentle, edv_out_.v_a, edv_out_.v_b, edv_out_.v_c, 
00239       edv_out_.v_d, edp_.max_p_inv);
00240         edv_out_.v_prob = REDQueue::modify_p(edv_out_.v_prob1, edv_out_.count, 
00241       edv_out_.count_bytes, edp_.bytes, edp_.mean_pktsize, edp_.wait, 
00242       ch->size());
00243 
00244         // drop probability is computed, pick random number and act
00245         double u = Random::uniform();
00246         if (u <= edv_out_.v_prob) {
00247             // DROP or MARK
00248             edv_out_.count = 0;
00249             edv_out_.count_bytes = 0;
00250             hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));
00251             if (edp_.setbit && hf->ecn_capable_ &&
00252                 edv_.v_ave < edp_out_.th_max) {
00253             hf->ce() = 1;   // mark Congestion Experienced bit
00254             return (0); // no drop
00255                 } else {
00256                     return (1);
00257                 }
00258         }
00259         return (0);  // no DROP/mark
00260 }
00261 
00262 
00263 /*
00264  * Receive a new packet arriving at the queue.
00265  * The average queue size is computed.  If the average size
00266  * exceeds the threshold, then the dropping probability is computed,
00267  * and the newly-arriving packet is dropped with that probability.
00268  * The packet is also dropped if the maximum queue size is exceeded.
00269  *
00270  * "Forced" drops mean a packet arrived when the underlying queue was
00271  * full or when the average q size exceeded maxthresh.
00272  * "Unforced" means a RED random drop.
00273  *
00274  * For forced drops, either the arriving packet is dropped or one in the
00275  * queue is dropped, depending on the setting of drop_tail_.
00276  * For unforced drops, the arriving packet is always the victim.
00277  */
00278 
00279 #define DTYPE_NONE  0   /* ok, no drop */
00280 #define DTYPE_FORCED    1   /* a "forced" drop */
00281 #define DTYPE_UNFORCED  2   /* an "unforced" (random) drop */
00282 
00283 void RIOQueue::enque(Packet* pkt)
00284 {
00285         /* Duplicate the RED algorithm to carry out a separate
00286          * calculation for Out packets -- Wenjia */
00287     hdr_flags* hf = hdr_flags::access(pkt);
00288     hdr_ip* iph = hdr_ip::access(pkt);
00289     if (priority_method_ == 1) {
00290         hf->pri_ = iph->flowid();
00291     }
00292 
00293     //printf("RIOQueue::enque queue %d queue-length %d priority %d\n", 
00294     //      q_, q_->length(), hf->pri_);
00295         if (hf->pri_) {  /* Regular In packets */
00296 
00297     /*
00298      * if we were idle, we pretend that m packets arrived during
00299      * the idle period.  m is set to be the ptc times the amount
00300      * of time we've been idle for
00301      */
00302 
00303     int m = 0;
00304     int m_in = 0;
00305     double now = Scheduler::instance().clock();
00306         /* To account for the period when the queue was empty.  */
00307     if (in_idle_) {
00308         in_idle_ = 0;
00309         m_in = int(edp_.ptc * (now - idletime_));
00310     } 
00311     if (idle_) {
00312                 idle_ = 0;
00313                 m = int(edp_.ptc * (now - idletime_));
00314         }
00315 
00316     /*
00317      * Run the estimator with either 1 new packet arrival, or with
00318      * the scaled version above [scaled by m due to idle time]
00319      */
00320 
00321         // printf( "qlen %d\n", q_->length());
00322     edv_.v_ave = REDQueue::estimator(qib_ ? q_->byteLength() : q_->length(), m + 1,
00323         edv_.v_ave, edp_.q_w);
00324     edv_in_.v_ave = REDQueue::estimator(qib_ ? in_bcount_ : in_len_,
00325         m_in + 1, edv_in_.v_ave, edp_.q_w);
00326 
00327     /*
00328      * count and count_bytes keeps a tally of arriving traffic
00329      * that has not been dropped (i.e. how long, in terms of traffic,
00330      * it has been since the last early drop)
00331      */
00332 
00333     hdr_cmn* ch = hdr_cmn::access(pkt);
00334     ++edv_.count;
00335     edv_.count_bytes += ch->size();
00336 
00337         /* added by Yun */
00338         ++edv_in_.count;
00339         edv_in_.count_bytes += ch->size();
00340 
00341     /*
00342      * DROP LOGIC:
00343      *  q = current q size, ~q = averaged q size
00344      *  1> if ~q > maxthresh, this is a FORCED drop
00345      *  2> if minthresh < ~q < maxthresh, this may be an UNFORCED drop
00346      *  3> if (q+1) > hard q limit, this is a FORCED drop
00347      */
00348 
00349     // register double qavg = edv_.v_ave;
00350     register double in_qavg = edv_in_.v_ave;
00351     int droptype = DTYPE_NONE;
00352     int qlen = qib_ ? q_->byteLength() : q_->length();
00353     int in_qlen = qib_ ? in_bcount_ : in_len_;
00354     int qlim = qib_ ? (qlim_ * edp_.mean_pktsize) : qlim_;
00355 
00356     curq_ = qlen;   // helps to trace queue during arrival, if enabled
00357 
00358     if (in_qavg >= edp_in_.th_min && in_qlen > 1) {
00359         if ((!edp_in_.gentle && in_qavg >= edp_in_.th_max) ||
00360             (edp_in_.gentle && in_qavg >= 2 * edp_in_.th_max)) {
00361             droptype = DTYPE_FORCED;
00362         } else if (edv_in_.old == 0) {
00363             /* 
00364              * The average queue size has just crossed the
00365              * threshold from below to above "minthresh", or
00366              * from above "minthresh" with an empty queue to
00367              * above "minthresh" with a nonempty queue.
00368              */
00369             edv_in_.count = 1;
00370             edv_in_.count_bytes = ch->size();
00371             edv_in_.old = 1;
00372         } else if (drop_in_early(pkt)) {
00373             droptype = DTYPE_UNFORCED;
00374         }
00375     } else {
00376         /* No packets are being dropped.  */
00377         edv_in_.v_prob = 0.0;
00378         edv_in_.old = 0;        
00379     }
00380     if (qlen >= qlim) {
00381         // see if we've exceeded the queue size
00382         droptype = DTYPE_FORCED;
00383     }
00384 
00385     if (droptype == DTYPE_UNFORCED) {
00386         /* pick packet for ECN, which is dropping in this case */
00387         Packet *pkt_to_drop = pickPacketForECN(pkt);
00388         /* 
00389          * If the packet picked is different that the one that just
00390          * arrived, add it to the queue and remove the chosen packet.
00391          */
00392         if (pkt_to_drop != pkt) {
00393             q_->enque(pkt);
00394                         // printf( "in: qlen %d %d\n", q_->length(), length());
00395                         ++in_len_;
00396             in_bcount_ += ch->size();
00397             q_->remove(pkt_to_drop);
00398                         // printf("remove qlen %d %d\n",q_->length(),length());
00399                         if (hdr_flags::access(pkt_to_drop)->pri_)
00400                            {
00401                              in_bcount_ -= 
00402                      hdr_cmn::access(pkt_to_drop)->size();
00403                              --in_len_;
00404                            }
00405             pkt = pkt_to_drop; /* ok 'cause pkt not needed anymore */
00406         }
00407         // deliver to special "edrop" target, if defined
00408         if (de_drop_ != NULL)
00409             de_drop_->recv(pkt);
00410         else
00411             drop(pkt);
00412     } else {
00413         /* forced drop, or not a drop: first enqueue pkt */
00414         q_->enque(pkt);
00415                 // printf( "in: qlen %d %d\n", q_->length(), length());
00416                 ++in_len_;
00417         in_bcount_ += ch->size();
00418 
00419         /* drop a packet if we were told to */
00420         if (droptype == DTYPE_FORCED) {
00421             /* drop random victim or last one */
00422             pkt = pickPacketToDrop();
00423             q_->remove(pkt);
00424                         // printf("remove qlen %d %d\n",q_->length(),length());
00425                         if (hdr_flags::access(pkt)->pri_) {
00426                           in_bcount_ -= hdr_cmn::access(pkt)->size(); 
00427                           --in_len_;
00428                           }
00429             drop(pkt);
00430             if (!ns1_compat_) {
00431                 // bug-fix from Philip Liu, <phill@ece.ubc.ca>
00432                 edv_.count = 0;
00433                 edv_.count_bytes = 0;
00434                 edv_in_.count = 0;
00435                 edv_in_.count_bytes = 0;
00436             }
00437         }
00438             }
00439         }
00440 
00441     else {     /* Out packets and default regular packets */
00442           /*
00443            * count and count_bytes keeps a tally of arriving traffic
00444            * that has not been dropped (i.e. how long, in terms of traffic,
00445            * it has been since the last early drop)
00446            */
00447 
00448           hdr_cmn* ch = hdr_cmn::access(pkt);
00449           ++edv_.count;
00450           edv_.count_bytes += ch->size();
00451 
00452           /* added by Yun */
00453           ++edv_out_.count;
00454           edv_out_.count_bytes += ch->size();
00455 
00456           /*
00457            * DROP LOGIC:
00458            *    q = current q size, ~q = averaged q size
00459            *    1> if ~q > maxthresh, this is a FORCED drop
00460            *    2> if minthresh < ~q < maxthresh, this may be an UNFORCED drop
00461            *    3> if (q+1) > hard q limit, this is a FORCED drop
00462            */
00463 
00464                 /* if the average queue is below the out_th_min
00465                  * then we have no need to worry.
00466                  */
00467 
00468           register double qavg = edv_.v_ave;
00469           // register double in_qavg = edv_in_.v_ave;
00470           int droptype = DTYPE_NONE;
00471           int qlen = qib_ ? q_->byteLength() : q_->length();
00472           /* added by Yun, seems not useful */
00473           // int out_qlen = qib_ ? out_bcount_ : q_->out_length();
00474 
00475           int qlim = qib_ ?  (qlim_ * edp_.mean_pktsize) : qlim_;
00476 
00477           curq_ = qlen; // helps to trace queue during arrival, if enabled
00478 
00479           if (qavg >= edp_out_.th_min && qlen > 1) {
00480                   if (!edp_out_.gentle && qavg >= edp_out_.th_max ||
00481               (edp_out_.gentle && qavg >= 2 * edp_out_.th_max)) {
00482                         droptype = DTYPE_FORCED;  // ? not sure, Yun
00483                   } else if (edv_out_.old == 0) {
00484             /* 
00485              * The average queue size has just crossed the
00486              * threshold from below to above "minthresh", or
00487              * from above "minthresh" with an empty queue to
00488              * above "minthresh" with a nonempty queue.
00489              */
00490                         edv_out_.count = 1;
00491                         edv_out_.count_bytes = ch->size();
00492                         edv_out_.old = 1;
00493                   } else if (drop_out_early(pkt)) {
00494                         droptype = DTYPE_UNFORCED; // ? not sure, Yun
00495                   }
00496           } else {
00497                   edv_out_.v_prob = 0.0;
00498                   edv_out_.old = 0;              // explain
00499           }
00500           if (qlen >= qlim) {
00501                   // see if we've exceeded the queue size
00502                   droptype = DTYPE_FORCED;   //need more consideration, Yun
00503           }
00504 
00505           if (droptype == DTYPE_UNFORCED) {
00506                   /* pick packet for ECN, which is dropping in this case */
00507                   Packet *pkt_to_drop = pickPacketForECN(pkt);
00508                   /*
00509                    * If the packet picked is different that the one that just
00510                    * arrived, add it to the queue and remove the chosen packet.
00511                    */
00512                   if (pkt_to_drop != pkt) {
00513                           q_->enque(pkt);
00514               //printf("out: qlen %d %d\n", q_->length(), length());
00515                           q_->remove(pkt_to_drop);
00516               //printf("remove qlen %d %d\n",q_->length(),length());
00517                           if (hdr_flags::access(pkt_to_drop)->pri_)
00518               {
00519                              in_bcount_ -=hdr_cmn::access(pkt_to_drop)->size();
00520                  --in_len_;
00521               }
00522                           pkt = pkt_to_drop;/* ok cause pkt not needed anymore */
00523                   }
00524                   // deliver to special "edrop" target, if defined
00525                   if (de_drop_ != NULL)
00526                           de_drop_->recv(pkt);
00527                   else
00528                           drop(pkt);
00529           } else {
00530                   /* forced drop, or not a drop: first enqueue pkt */
00531                   q_->enque(pkt);
00532           //printf("out: qlen %d %d\n", q_->length(), length());
00533 
00534                   /* drop a packet if we were told to */
00535                   if (droptype == DTYPE_FORCED) {
00536                           /* drop random victim or last one */
00537                           pkt = pickPacketToDrop();
00538                           q_->remove(pkt);
00539               //printf("remove qlen %d %d\n",q_->length(),length());
00540                           if (hdr_flags::access(pkt)->pri_)
00541               {
00542                             in_bcount_ -= hdr_cmn::access(pkt)->size();
00543                 --in_len_;
00544               }
00545                           drop(pkt);
00546                   }
00547           }
00548     }
00549 
00550     return;
00551 }
00552 
00553 /*
00554  * Routine called by TracedVar facility when variables change values.
00555  * Currently used to trace values of avg queue size, drop probability,
00556  * and the instantaneous queue size seen by arriving packets.
00557  * Note that the tracing of each var must be enabled in tcl to work.
00558  */
00559 
00560 void
00561 RIOQueue::trace(TracedVar* v)
00562 {
00563     char wrk[500], *p;
00564 
00565     if (((p = strstr(v->name(), "ave")) == NULL) &&
00566         ((p = strstr(v->name(), "in_ave")) == NULL) &&
00567         ((p = strstr(v->name(), "out_ave")) == NULL) &&
00568         ((p = strstr(v->name(), "prob")) == NULL) &&
00569         ((p = strstr(v->name(), "in_prob")) == NULL) &&
00570         ((p = strstr(v->name(), "out_prob")) == NULL) &&
00571         ((p = strstr(v->name(), "curq")) == NULL)) {
00572         fprintf(stderr, "RIO:unknown trace var %s\n",
00573             v->name());
00574         return;
00575     }
00576 
00577     if (tchan_) {
00578         int n;
00579         double t = Scheduler::instance().clock();
00580         // XXX: be compatible with nsv1 RED trace entries
00581         if (*p == 'c') {
00582             sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));
00583         } else {
00584             sprintf(wrk, "%c %g %g", *p, t,
00585                 double(*((TracedDouble*) v)));
00586         }
00587         n = strlen(wrk);
00588         wrk[n] = '\n'; 
00589         wrk[n+1] = 0;
00590         (void)Tcl_Write(tchan_, wrk, n+1);
00591     }
00592     return; 
00593 }
00594 
00595 /* for debugging help */
00596 void RIOQueue::print_edp()
00597 {
00598     REDQueue::print_edp();
00599     printf("in_minth: %f, in_maxth: %f\n", edp_in_.th_min, edp_in_.th_max);
00600     printf("out_minth: %f, out_maxth: %f\n", 
00601                 edp_out_.th_min, edp_out_.th_max);
00602     printf("qlim: %d, in_idletime: %f\n", qlim_, in_idletime_);
00603     printf("=========\n");
00604 }
00605 
00606 void RIOQueue::print_edv()
00607 {
00608     REDQueue::print_edv();
00609     printf("in_v_a: %f, in_v_b: %f\n", edv_in_.v_a, edv_in_.v_b);
00610     printf("out_v_a: %f, out_v_b: %f\n", edv_out_.v_a, edv_out_.v_b);
00611 }

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