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

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

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