jobs.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000-2002, by the Rector and Board of Visitors of the 
00003  * University of Virginia.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, 
00007  * with or without modification, are permitted provided 
00008  * that the following conditions are met:
00009  *
00010  * Redistributions of source code must retain the above 
00011  * copyright notice, this list of conditions and the following 
00012  * disclaimer. 
00013  *
00014  * Redistributions in binary form must reproduce the above 
00015  * copyright notice, this list of conditions and the following 
00016  * disclaimer in the documentation and/or other materials provided 
00017  * with the distribution. 
00018  *
00019  * Neither the name of the University of Virginia nor the names 
00020  * of its contributors may be used to endorse or promote products 
00021  * derived from this software without specific prior written 
00022  * permission. 
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
00025  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
00026  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00027  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00028  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 
00029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
00030  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00031  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00032  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
00033  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00034  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
00035  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
00036  * THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 /*
00039  *                                                                     
00040  * JoBS - ns-2 prototype implementation                                
00041  *                                                                     
00042  * Author: Nicolas Christin <nicolas@cs.virginia.edu>, 2000-2002       
00043  *                                    
00044  * JoBS algorithms originally devised and proposed by             
00045  * Nicolas Christin and Jorg Liebeherr                                 
00046  * Grateful acknowledgments to Tarek Abdelzaher for his help and       
00047  * comments.                                                           
00048  *                                                                     
00049  * $Id: jobs.cc,v 1.3 2005/07/27 01:13:44 tomh Exp $                   
00050  *                                        
00051  */
00052 
00053 #include "jobs.h"
00054 
00055 static class JoBSClass : public TclClass {
00056 public:
00057   JoBSClass() : TclClass("Queue/JoBS") {}
00058   TclObject* create(int, const char*const*) {
00059     return (new JoBS);
00060   }
00061 } class_jobs;
00062 
00063 JoBS::JoBS() : link_(NULL) {
00064     for (int i=1; i<=NO_CLASSES; i++) 
00065         cls_[i] = new PacketQueue;
00066 
00067     bind_bool("drop_front_", &drop_front_);
00068     bind_bool("trace_hop_", &trace_hop_);
00069     bind("mean_pkt_size_", &mean_pkt_size_);  // avg pkt size
00070     bind("adc_resolution_type_", &adc_resolution_type_);
00071     bind_bool("shared_buffer_", &shared_buffer_);
00072     total_backlog_Pkts_     = 0;
00073     total_backlog_Bits_     = 0;
00074     pkt_count_ = 0;
00075     idle_ = 1;
00076     ABS_present_ = FALSE;
00077     monitoring_window_ = 0;
00078     last_arrival_ = 0;
00079     last_monitor_update_ = 0;
00080     sliding_arv_pkts_=0;
00081     util_ = 0;
00082 
00083     for (int i=1; i<=NO_CLASSES; i++) {
00084         RDC_[i] = (double)i; 
00085         RLC_[i] = (double)i;
00086         ADC_[i] = INFINITY;
00087         ALC_[i] = INFINITY;
00088         sliding_serviced_pkts_[i] = 0;
00089         sliding_serviced_bits_[i] = 0;
00090         sliding_arv_pkts_c[i] = 0;
00091         sliding_class_delay_[i] = 0;
00092         sliding_class_service_rate_[i] = 0;
00093         last_xmit_[i] = 0;
00094         
00095         avg_elapsed_[i] = 0.0;
00096         excess_drops_[i] = 0.0;
00097         Rout_last_up_[i] = 0.0;
00098         min_drop_[i] = 0.0;
00099         max_drop_[i] = 1.0;
00100         error_[i] = 0.0;
00101         min_rate_[i] = 0.0;
00102         backlog_Pkts_[i] = 0;
00103         backlog_Bits_[i] = 0;
00104         service_rate_[i] = 0;
00105         current_loss_[i] = 0;
00106         Rout_[i] = 0;
00107         Rin_[i] = 0;
00108         Rout_th_[i] = 0;
00109         last_rate_update_[i] = 0;
00110     }  
00111 }
00112 
00113 int JoBS::command(int argc, const char*const* argv) {
00114     Tcl& tcl = Tcl::instance();
00115     double tmp[NO_CLASSES+1];
00116 
00117     if (argc >= NO_CLASSES+2) { /* input RDCs/RLCs/ADCs/ALCs */
00118         if (strcmp(argv[1], "init-rdcs") == 0) {
00119             RDC_[0] = -1;
00120             for (int i=1; i<=NO_CLASSES; i++) {
00121                 RDC_[i] = atof(argv[i+1]);
00122                 if (RDC_[i] == -1)
00123                     concerned_RDC_[i] = FALSE;
00124                 else
00125                   concerned_RDC_[i] = TRUE;
00126             }
00127             for (int i=1; i<=NO_CLASSES;i++) {
00128                 tmp[i] = 1.0;
00129                 for (int j = 1; j <= i-1; j++) 
00130                   if (concerned_RDC_[j]) tmp[i] *= RDC_[j];
00131             }
00132 
00133             for (int i=1; i<=NO_CLASSES; i++) {
00134                 prod_others_[i] = 1.0;
00135                 for (int j = 1; j <= NO_CLASSES; j++) 
00136                     if ((j != i)&&(concerned_RDC_[j]))
00137                       prod_others_[i] *= tmp[j];
00138             }
00139             if (argc == NO_CLASSES+2) {
00140                 fprintf(stdout, "\nConfigured RDC, with:\n");
00141                 for (int i=1; i<=NO_CLASSES; i++) {
00142                     fprintf(stdout, "\tClass %d: ",i);
00143                     if (concerned_RDC_[i]) 
00144                         fprintf(stdout, "\t%f\t(%f)\n", (double)RDC_[i], (double) prod_others_[i]);
00145                     else 
00146                         fprintf(stdout, "\tNot concerned\n");
00147                 }
00148             }
00149             return (TCL_OK);
00150         }
00151 
00152         if (strcmp(argv[1], "init-rlcs") == 0) {
00153             RLC_[0] = -1;
00154             for (int i=1; i<=NO_CLASSES; i++) {
00155                 RLC_[i] = atof(argv[i+1]);
00156                 if (RLC_[i] == -1)
00157                     concerned_RLC_[i] = FALSE;
00158                 else
00159                     concerned_RLC_[i] = TRUE;
00160             }
00161 
00162             for (int i=1; i<=NO_CLASSES;i++) {
00163                 tmp[i] = 1.0;
00164                 for (int j = 1; j <= i-1; j++) 
00165                     if (concerned_RLC_[j]) 
00166                         tmp[i] *= RLC_[j];
00167             }
00168 
00169             for (int i=1; i<=NO_CLASSES; i++) {
00170                 loss_prod_others_[i] = 1.0;
00171                 for (int j = 1; j <= NO_CLASSES; j++) 
00172                     if ((j != i)&&(concerned_RLC_[j]))
00173                         loss_prod_others_[i] *= tmp[j];
00174             }
00175             if (argc == NO_CLASSES+2) {
00176                 fprintf(stdout, "\nConfigured RLC, with:\n");
00177                 for (int i=1; i<=NO_CLASSES; i++) {
00178                     fprintf(stdout, "\tClass %d: ",i);
00179                     if (concerned_RLC_[i]) 
00180                         fprintf(stdout, "\t%f\t(%f)\n", (double)RLC_[i], (double)loss_prod_others_[i]);
00181                     else 
00182                         fprintf(stdout, "\tNot concerned\n");
00183                 }
00184             }
00185             
00186             return (TCL_OK);
00187         }
00188         if (strcmp(argv[1], "init-adcs") == 0) {
00189             ADC_[0] = -1;
00190             for (int i=1; i<=NO_CLASSES; i++) {
00191                 ADC_[i] = atof(argv[i+1]);
00192                 if (ADC_[i] == -1) {
00193                     concerned_ADC_[i] = FALSE;
00194                     ADC_[i] = INFINITY;
00195                 } else {
00196                     concerned_ADC_[i] = TRUE;
00197                     ABS_present_ = TRUE;
00198                 }
00199             }
00200             if (argc == NO_CLASSES+2) {
00201                 fprintf(stdout, "\nConfigured ADC, with:\n");
00202                 for (int i=1; i<=NO_CLASSES; i++) {
00203                     fprintf(stdout, "\tClass %d: ", i);
00204                     if (concerned_ADC_[i]) 
00205                         fprintf(stdout, "\t%f secs\n", (double)ADC_[i]);
00206                     else 
00207                         fprintf(stdout, "\tNot concerned\n");
00208                 }
00209             }
00210 
00211             return (TCL_OK);
00212         }
00213         if (strcmp(argv[1], "init-alcs") == 0) {
00214             ALC_[0] = -1;
00215             for (int i=1; i<=NO_CLASSES; i++) {
00216                 ALC_[i] = atof(argv[i+1]);
00217                 if (ALC_[i] == -1) {
00218                     concerned_ALC_[i] = FALSE;
00219                     ALC_[i] = INFINITY;
00220                 } else
00221                     concerned_ALC_[i] = TRUE;
00222             }
00223             if (argc == NO_CLASSES+2) {
00224                 fprintf(stdout, "\nConfigured ALC, with:\n");
00225                 for (int i=1; i<=NO_CLASSES; i++) {
00226                     fprintf(stdout, "\tClass %d: ",i);
00227                     if (concerned_ALC_[i])  
00228                         fprintf(stdout, "\t%f\n", (double)ALC_[i]);
00229                     else 
00230                         fprintf(stdout, "\tNot concerned\n");   
00231                 }
00232             }
00233             return (TCL_OK);
00234         }
00235         if (strcmp(argv[1], "init-arcs") == 0) {
00236             ARC_[0] = -1;
00237             for (int i=1; i<=NO_CLASSES; i++) {
00238                 ARC_[i] = atof(argv[i+1]);
00239                 if (ARC_[i] == -1) {
00240                     concerned_ARC_[i] = FALSE;
00241                     ARC_[i] = 0;
00242                 } else {
00243                     concerned_ARC_[i] = TRUE;
00244                     ABS_present_ = TRUE;
00245                 }
00246             }
00247             if (argc == NO_CLASSES+2) {
00248                 fprintf(stdout, "\nConfigured ARC, with:\n");
00249                 for (int i=1; i<=NO_CLASSES; i++) {
00250                     fprintf(stdout, "\tClass %d: ",i);
00251                     if (concerned_ARC_[i])  
00252                         fprintf(stdout, "\t%f\n", (double)ARC_[i]);
00253                     else 
00254                         fprintf(stdout, "\tNot concerned\n");   
00255                 }
00256             }
00257             return (TCL_OK);
00258         }
00259     } else if (argc == 3) {
00260         if (strcmp(argv[1], "link") == 0) {
00261             LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);
00262             if (del == 0) {
00263                 tcl.resultf("JoBS: no LinkDelay object %s",
00264                         argv[2]);
00265                 return(TCL_ERROR);
00266             }
00267             link_ = del;
00268             for (int i=1; i <= NO_CLASSES; i++)
00269                 service_rate_[i] = 0;
00270             return (TCL_OK);
00271         }
00272         if (strcmp(argv[1], "sampling-period") == 0) {
00273             sampling_period_ = atoi(argv[2]);
00274             if (sampling_period_ < 0) {
00275                 fprintf(stderr, "JoBS: sampling period must be positive!!\n");
00276                 abort();
00277                 return (TCL_ERROR); // __NOT REACHED__
00278             } else 
00279                 return (TCL_OK);      
00280         }
00281         if (strcmp(argv[1], "id") == 0) {
00282             link_id_ = (int)atof(argv[2]);
00283             return (TCL_OK);
00284         }
00285         if (strcmp(argv[1], "trace-file") == 0) {
00286             file_name_ = new(char[500]);
00287             strcpy(file_name_, argv[2]);
00288             if (strcmp(file_name_, "null")) {
00289                 trace_hop_ = true;
00290             } else {
00291                 trace_hop_ = false;
00292             }
00293             return (TCL_OK);
00294         }
00295     } else if (argc == 2) {
00296         if (strcmp(argv[1], "initialize") == 0) {
00297             double myMaxPi=0;
00298             for (int i = 1; i <= NO_CLASSES; i++) 
00299                 if (prod_others_[i] > myMaxPi) 
00300                     myMaxPi = prod_others_[i];
00301 
00302             Kp_static_ = -2/(double)(myMaxPi*mean_pkt_size_*sampling_period_);
00303 
00304       // Open files
00305             if (trace_hop_) {
00306                 if ((hop_trace_ = fopen(file_name_, "w"))==NULL) {
00307                     fprintf(stderr, "Problem with opening the per-hop trace file: %s\n", file_name_);
00308                     abort();      
00309                 }
00310             }    
00311             return (TCL_OK);
00312         }
00313         if (strcmp(argv[1], "copyright-info") == 0) {
00314             fprintf(stdout, "\n----------------------------------------------------------\n\n");
00315             fprintf(stdout, "JoBS scheduler/dropper [prototype ns-2 implementation]\n");
00316             fprintf(stdout, "Version 1.0 (CVS Revision: $Id: jobs.cc,v 1.3 2005/07/27 01:13:44 tomh Exp $)\n\n");
00317             fprintf(stdout, "ns-2 implementation by Nicolas Christin <nicolas@cs.virginia.edu>\n");
00318             fprintf(stdout, "JoBS algorithms proposed by Nicolas Christin and Jorg Liebeherr.\n");
00319             fprintf(stdout, "Grateful acknowledgments to Tarek Abdelzaher for his help and comments.\n");
00320             fprintf(stdout, "Visit http://qosbox.cs.virginia.edu for more\n");
00321             fprintf(stdout, "information.\n\n");
00322             fprintf(stdout, "Copyright (c) 2000-2002 by the Rector and Board of Visitors of the\n");
00323             fprintf(stdout, "University of Virginia.\n");
00324             fprintf(stdout, "All Rights Reserved.\n");
00325             fprintf(stdout, "----------------------------------------------------------\n\n");
00326             return (TCL_OK);
00327         }
00328     }
00329     return (Queue::command(argc, argv));
00330 }
00331 
00332 // *******************************************************************
00333 // JoBS: Simplified Packetization of the Fluid Flow Model.
00334 // *******************************************************************
00335 
00336 Packet* JoBS::deque() { // Lower classes are better. 
00337     double  cur_time  = Scheduler::instance().clock(); 
00338     double  error;
00339     double  maxError;
00340     int svc_class = 0;
00341   
00342     error = 0;
00343 
00344     // Fast translation of service rates into packet forwarding decisions
00345 
00346     maxError = -INFINITY;
00347     for (int i=1; i<=NO_CLASSES; i++) {
00348         if (cls_[i]->head()) {
00349             error = (double)Rout_th_[i] - Rout_[i];
00350             if (error > maxError) {
00351                 maxError = error;
00352                 svc_class = i;
00353             }
00354         }
00355     }
00356 
00357     if (svc_class == 0) {
00358         idle_ = 1;
00359         if (&Scheduler::instance() != NULL)
00360             idletime_ = cur_time;
00361         else
00362             idletime_ = 0.0;
00363         return NULL; /* Idle system */
00364     } else {
00365         idle_ = 0;
00366         Packet* p = cls_[svc_class]->deque();
00367         hdr_cmn* cm_h = hdr_cmn::access(p);
00368     
00369         total_backlog_Pkts_--;
00370         total_backlog_Bits_ -= 8*cm_h->size();
00371         backlog_Pkts_[svc_class]--;
00372         backlog_Bits_[svc_class] -= 8*cm_h->size();
00373         Rout_[svc_class] += 8*cm_h->size();
00374         Rout_last_up_[svc_class] = cur_time;
00375         
00376         sliding_serviced_pkts_[svc_class] ++;
00377         sliding_serviced_bits_[svc_class] += 8*cm_h->size();
00378         sliding_class_delay_[svc_class] 
00379           = ((sliding_serviced_pkts_[svc_class]-1)*(sliding_class_delay_[svc_class])
00380              +(cur_time-cm_h->ts_))/(sliding_serviced_pkts_[svc_class]);
00381         last_xmit_[svc_class] = cur_time+(8.*cm_h->size()/(double)link_->bandwidth());
00382         return(p);
00383     }
00384 }
00385 
00386 // *******************************************************************
00387 // JoBS: Enqueue packet 
00388 // *******************************************************************
00389 
00390 void JoBS::enque(Packet* pkt) {
00391     double* DeltaR;
00392     int i;
00393     hdr_ip*  ip_h = hdr_ip::access(pkt);
00394     hdr_cmn* cm_h = hdr_cmn::access(pkt);
00395     
00396     int prio = ip_h->prio_;
00397     if ((prio < 1) || (prio > NO_CLASSES)) {
00398         printf("Bad priority value\n");
00399         abort();
00400     }
00401   
00402     double cur_time = Scheduler::instance().clock(); 
00403     cm_h->ts_ = cur_time; // timestamp the packet
00404     cls_[prio]->enque(pkt);
00405     
00406     monitoring_window_ -= cur_time-last_monitor_update_;
00407     last_monitor_update_ = cur_time;
00408     if (monitoring_window_ <= 0) {
00409         updateStats(pkt, RESET_STATS);
00410         monitoring_window_ = MON_WINDOW_SIZE;
00411     } else {
00412         updateStats(pkt, UPDATE_STATS);
00413     }
00414     
00415     // Reset arrival, input, and service curves if the scheduler is 
00416     // not busy
00417 
00418     if (idle_) {
00419         for (i=1; i<= NO_CLASSES; i++) {
00420           Arrival_[i]=0.0;
00421           Rin_[i]=0.0;
00422           Rout_[i]=0.0;
00423           Rout_th_[i]=0.0;
00424           last_rate_update_[i] = 0;
00425           Rout_last_up_[i] = cur_time;
00426           idle_ = 0;
00427         }
00428     }
00429     
00430     arvAccounting(pkt);
00431     
00432     /* Is the buffer full? */  
00433     if (!shared_buffer_ && backlog_Pkts_[prio] > qlim_/NO_CLASSES) {
00434         /* separate buffers: no guarantees on packet drops 
00435          * can be offered
00436          * thus we drop the incoming packet
00437          */
00438         if (drop_front_)
00439             dropFront(prio, WITH_UPDATE);
00440         else
00441             dropTail(prio, WITH_UPDATE);    
00442     } else {
00443       /* shared buffer */
00444         if (total_backlog_Pkts_ > qlim_) {
00445             if (!concerned_RLC_[prio]) {
00446                 if (!concerned_ALC_[prio]) {
00447                     // No ALC, no RLC on that class. Drop the incoming packet.
00448                     if (drop_front_)
00449                         dropFront(prio, WITH_UPDATE);
00450                     else
00451                         dropTail(prio, WITH_UPDATE);
00452                 } else {
00453                     // No RLC on that class. Drop the incoming packet if you can...
00454                     if (current_loss_[prio]+(double)8*cm_h -> size()/(double)Arrival_[prio] <= ALC_[prio]) {
00455                         if (drop_front_)
00456                             dropFront(prio, WITH_UPDATE);
00457                         else        
00458                             dropTail(prio, WITH_UPDATE);
00459                     } else {
00460                         // If it doesn't work, pick another class
00461                         if (drop_front_)
00462                             dropFront(pickDroppedRLC(RESOLVE_OVERFLOW), WITH_UPDATE);
00463                         else        
00464                             dropTail(pickDroppedRLC(RESOLVE_OVERFLOW), WITH_UPDATE);
00465                     }
00466                 }
00467             } else {
00468                 // RLC on that class (w/ or w/o ALC), pick a class according to the RLC
00469               if (drop_front_)
00470                 dropFront(pickDroppedRLC(RESOLVE_OVERFLOW), WITH_UPDATE);
00471               else      
00472                 dropTail(pickDroppedRLC(RESOLVE_OVERFLOW), WITH_UPDATE);
00473             }
00474         }
00475     }
00476     pkt_count_ ++;
00477     enforceWC(); // Change rates if some classes have entered/left the system
00478     // since the last update
00479 
00480     if ((ABS_present_)&&(!minRatesNeeded(ip_h -> prio()))) {
00481         DeltaR = assignRateDropsADC();   
00482 
00483         if (DeltaR != NULL) {
00484             for (i = 1; i <= NO_CLASSES; i++) 
00485                 service_rate_[i] += DeltaR[i];
00486             delete []DeltaR; 
00487         }
00488 
00489         DeltaR = adjustRatesRDC();
00490         
00491         if (DeltaR) {
00492             for (i = 1; i <= NO_CLASSES; i++) 
00493                 service_rate_[i] += DeltaR[i];
00494             delete []DeltaR;   
00495         }
00496 
00497         pkt_count_ = 0;
00498 
00499     } else if (pkt_count_ >= sampling_period_) {
00500         /* Is it time for a new evaluation of the system? */
00501         DeltaR = adjustRatesRDC();
00502         if (DeltaR != NULL) {
00503             for (i = 1; i <= NO_CLASSES; i++)
00504                 service_rate_[i] += DeltaR[i];
00505             delete []DeltaR;
00506         } 
00507         pkt_count_ = 0;
00508     }
00509     return;
00510 }
00511 
00512 // *******************************************************************
00513 // Auxiliary functions (helpers) follow
00514 // *******************************************************************
00515 
00516 // 1) Scheduling Primitives
00517 
00518 // *******************************************************************
00519 // JoBS: Enforce Work-Conserving Property
00520 // *******************************************************************
00521 
00522 int JoBS::enforceWC() {
00523     int i;
00524     int activeClasses;
00525     int updated;
00526     
00527     updated = FALSE;
00528     activeClasses = 0;
00529     
00530     for (i = 1; i <= NO_CLASSES; i++) {
00531         if (cls_[i]->head()) 
00532             activeClasses++;
00533         if ((cls_[i] -> head() && service_rate_[i] <= PRECISION_ERROR)
00534             ||(cls_[i] -> head() == NULL && service_rate_[i] > 0)) 
00535           updated = TRUE;
00536     }
00537 
00538     if (updated) {
00539         for (i = 1; i <= NO_CLASSES; i++) {
00540             if (cls_[i]->head() == NULL) {
00541                 service_rate_[i] = 0;
00542             } else {
00543                 if (activeClasses > 0)
00544                     service_rate_[i] = link_->bandwidth()/(double)activeClasses;
00545                 else 
00546                     service_rate_[i] = 0 ;
00547             }
00548         }
00549     }
00550     
00551     return (updated);
00552 }
00553 
00554 // *******************************************************************
00555 // JoBS: Adjusts the rates for meeting the RDCs
00556 // *******************************************************************
00557 
00558 double* JoBS::adjustRatesRDC() {
00559     int i, j;
00560     int RDC_Classes, activeClasses;
00561     double* result;
00562     double credit, available, lower_bound, upper_bound;
00563     double bk;
00564     double cur_time;
00565     
00566     cur_time = Scheduler::instance().clock(); 
00567   
00568     activeClasses = 0;
00569     RDC_Classes = 0;
00570 
00571     upper_bound = link_ -> bandwidth();
00572 
00573     for (i = 1; i <= NO_CLASSES; i++)
00574         if (cls_[i]->head() != NULL) {
00575             activeClasses++;
00576             if (concerned_RDC_[i]) 
00577                 RDC_Classes++;
00578             else 
00579                 upper_bound -= service_rate_[i];
00580         }
00581 
00582     result = new double[NO_CLASSES+1];
00583 
00584     if (result == NULL) 
00585         return NULL;
00586 
00587     for (i = 0; i <= NO_CLASSES; i++) 
00588         result[i] = 0;
00589 
00590     if (upper_bound < PRECISION_ERROR || activeClasses == 0) return result;
00591     
00592     credit = 0;
00593     lower_bound = 0;
00594     
00595     updateError();
00596     min_share_ = 1.0;
00597     bk = 0;
00598     
00599     for (i = 1; i <= NO_CLASSES; i++) 
00600         if (concerned_RDC_[i])
00601             bk += Rin_[i];
00602 
00603     for (i = 1; i <= NO_CLASSES; i++) 
00604         if ((double)Rin_[i]/(double)bk < min_share_)
00605             min_share_ = (double)Rin_[i]/(double)bk;
00606   
00607     /*
00608      * note that the formula for Kp is slightly different 
00609      * from the formula derived in CS-2001-21. 
00610      * the formula used here provides better results 
00611      * at the expense of more complicated computations.
00612      */
00613     
00614     Kp_dynamic_ = Kp_static_*pow(upper_bound, 2.)*min_share_*util_*max(util_, 1.0);
00615 
00616     credit = 0;
00617     for (i = 1; i <= NO_CLASSES; i++) {
00618         if ((cls_[i]->head() != NULL)&&(concerned_RDC_[i])) {
00619             result[i] = Kp_dynamic_*(error_[i]); 
00620         }
00621     }
00622 
00623     // saturation 
00624 
00625     for (i = 1; i <= NO_CLASSES; i++) 
00626         if (cls_[i]->head() != NULL) {
00627             if (concerned_RDC_[i]) {
00628                 lower_bound += max(0, min_rate_[i]);
00629             } 
00630         }
00631 
00632     for (i = 1; i <= NO_CLASSES; i++) {
00633         if ((concerned_RDC_[i])&&(result[i] + service_rate_[i] > upper_bound)) {
00634             for (j = 0; j <= NO_CLASSES; j++) {
00635                 if (concerned_RDC_[j]) {
00636                     if (j == i) 
00637                         result[j] = (upper_bound-service_rate_[j])  
00638                             + min_rate_[j] - lower_bound;
00639                     else
00640                         result[j] = -service_rate_[j]+min_rate_[j];
00641                 }
00642             }
00643             return result;
00644         }
00645         if (concerned_RDC_[i] && result[i] + service_rate_[i] < min_rate_[i]) {
00646             credit += service_rate_[i]+result[i]-min_rate_[i]; 
00647             // "credit" is in fact a negative number
00648             result[i] = -service_rate_[i]+min_rate_[i];
00649         }
00650     }
00651 
00652     for (i = NO_CLASSES; (i > 0)&&(credit < 0); i--) {
00653         if ((cls_[i]->head() != NULL)&&(concerned_RDC_[i])) {
00654             available = result[i] + service_rate_[i]-min_rate_[i];
00655             if (available >= -credit) {
00656                 result[i] += credit;
00657                 credit = 0;
00658             } else {
00659                 result[i] -= available;
00660                 credit += available;
00661             }      
00662         }
00663     }
00664     return result;
00665 }
00666 
00667 // *******************************************************************
00668 // JoBS: Assigns the rates (and possibly drops some traffic) 
00669 // needed for meeting the ADCs
00670 // *******************************************************************
00671 
00672 double* JoBS::assignRateDropsADC() {
00673     double* x;
00674     //double myRatios[NO_CLASSES+1];
00675     double c[NO_CLASSES+1], n[NO_CLASSES+1];
00676     double k[NO_CLASSES+1], target[NO_CLASSES+1];
00677     double available[NO_CLASSES+1];
00678     double toDrop;
00679     int lowest, highest;
00680     int victim_class, keep_going;
00681     int i;
00682     Packet* p; 
00683     hdr_cmn* cm_h; 
00684     double cur_time = Scheduler::instance().clock(); 
00685     
00686     x = new double[NO_CLASSES+1];
00687     
00688     if (x == NULL) return NULL;
00689     
00690     for (i = 0;i <= NO_CLASSES; i++) 
00691         x[i] = 0;
00692     
00693     keep_going = TRUE;
00694     
00695     for (i = 1; i <= NO_CLASSES; i++) {
00696         if (cls_[i]->head() != NULL) {
00697             p = cls_[i]->head();
00698             cm_h = hdr_cmn::access(p);
00699             n[i] = (double)service_rate_[i];
00700             k[i] = (double)backlog_Bits_[i];
00701             available[i] = service_rate_[i];
00702             
00703             if (concerned_ADC_[i]) { 
00704                 c[i] = (double)max((double)ADC_[i]-(cur_time-cm_h->ts_),1e-10);
00705                 target[i] = (double)k[i]/(double)c[i];
00706                 available[i] = -(target[i] - n[i]); 
00707             } 
00708             if (concerned_ARC_[i]) { 
00709                 if (n[i] - ARC_[i] < available[i])
00710                     available[i] = n[i] - ARC_[i];
00711             }
00712         } else {
00713             available[i] = service_rate_[i];
00714             n[i] = 0;
00715             k[i] = 0;
00716             c[i] = 0;
00717         }
00718     }
00719     
00720     // Step 1: Adjust rates 
00721     
00722     highest = 1;
00723     lowest  = NO_CLASSES;
00724     
00725     while ((highest < NO_CLASSES+1)&&(available[highest] >= 0))
00726         highest++; // which is the highest class that needs more service? 
00727     while ((lowest > 0)&&(available[lowest] <= 0))
00728         lowest--;  // which is the lowest class that needs less service? 
00729     
00730     
00731     while ((highest != NO_CLASSES+1)&&(lowest != 0)) {
00732         // give the excess service from lowest to highest 
00733         if (available[lowest]+available[highest] > 0) {
00734             // Still some "credit" left 
00735             // Give all that is needed by "highest" 
00736             n[lowest]  -= -available[highest];
00737             n[highest] += -available[highest];
00738             
00739             available[lowest]  -= -available[highest];
00740             available[highest] = 0;
00741             
00742             while ((highest < NO_CLASSES+1)&&(available[highest] >= 0))
00743                 highest++;  // which is the highest class that needs more service? 
00744             
00745         } else if (available[lowest]+available[highest] == 0) {
00746             // No more credit left but it's fine 
00747             n[lowest]  -= -available[highest];
00748             n[highest] += -available[highest];
00749             
00750             available[highest] = 0;
00751             available[lowest]  = 0;
00752             
00753             while ((highest < NO_CLASSES+1)&&(available[highest] >= 0))
00754                 highest++;  // which is the highest class that needs more service? 
00755             while ((lowest > 0)&&(available[lowest] <= 0))
00756                 lowest--;   // which is the lowest class that needs less service? 
00757 
00758         } else if (available[lowest]+available[highest] < 0) {
00759             // No more credit left and we need to switch to another class 
00760             n[lowest]  -= available[lowest];
00761             n[highest] += available[lowest];
00762 
00763             available[highest] += available[lowest];
00764             available[lowest]  = 0;
00765             
00766             while ((lowest > 0)&&(available[lowest] <= 0))
00767                 lowest--;  // which is the lowest class that needs less service? 
00768         }
00769     }
00770     
00771     for (i = 1; i <= NO_CLASSES; i++) {
00772         if (cls_[i]->head() != NULL)
00773             x[i] = n[i] - (double)service_rate_[i];
00774         else 
00775             x[i] = - (double)service_rate_[i] ;
00776     }
00777     
00778     // Step 2: Adjust drops 
00779     
00780     if (highest != NO_CLASSES+1) {
00781         // Some class still needs additional service 
00782         if (adc_resolution_type_ == SHARED_PAIN) {
00783             // Drop from all classes
00784             toDrop = 0;
00785             for (i = 1; i <= NO_CLASSES; i++) 
00786                 if (available[i] < 0 && concerned_ADC_[i] && cls_[i]->head()) 
00787                     toDrop += k[i] - c[i]*n[i];
00788             
00789             while ((toDrop > 0)&&(keep_going)) {
00790                 victim_class = pickDroppedRLC(RESOLVE_ADC);
00791                 if (drop_front_) 
00792                     p = cls_[victim_class] -> head();
00793                 else
00794                     p = cls_[victim_class] -> tail();
00795           
00796                 cm_h = hdr_cmn::access(p);
00797 
00798                 if (current_loss_[victim_class]+(double)8*cm_h -> size()/(double)Arrival_[victim_class] > ALC_[victim_class]) {
00799                     keep_going = FALSE;
00800                 } else {
00801                     toDrop -= (double)8*cm_h -> size();
00802 
00803                     if (drop_front_) 
00804                         dropFront(victim_class, WITH_UPDATE);
00805                     else
00806                         dropTail(victim_class, WITH_UPDATE);
00807                 }
00808             }   
00809         } else {
00810             // Drop solely from the class(es) that need(s) more service
00811             for (i = 1; i <= NO_CLASSES; i++) {
00812                 if (available[i] < 0 && cls_[i] -> head()) {
00813                     k[i] = c[i]*n[i];   
00814 
00815                     while ((backlog_Bits_[i] > k[i])&&(keep_going)) {
00816                         if (drop_front_) {
00817                             p = cls_[i] -> head();
00818                             cm_h = hdr_cmn::access(p);
00819                             if (current_loss_[i]+(double)8*cm_h -> size()/(double)Arrival_[i] > ALC_[i]) {
00820                                 keep_going = FALSE;
00821                             } else 
00822                                 dropFront(i, WITH_UPDATE);
00823                         } else {
00824                             p = cls_[i] -> tail();
00825                             cm_h = hdr_cmn::access(p);
00826                             if (current_loss_[i]+(double)8*cm_h -> size()/(double)Arrival_[i] > ALC_[i]) {
00827                                 keep_going = FALSE;
00828                             } else 
00829                                 dropTail(i, WITH_UPDATE);
00830                         }
00831                     }
00832                     k[i] = backlog_Bits_[i];
00833                 }
00834             }      
00835         }
00836     } 
00837 
00838     for (i = 1; i <= NO_CLASSES; i++) 
00839         if (cls_[i]->head() && concerned_ADC_[i]) {
00840             if (c[i] > 0) {
00841                 if (concerned_ADC_[i] && !concerned_ARC_[i]) {
00842                     min_rate_[i] = (double)k[i]/(double)c[i];
00843                 } else 
00844                     min_rate_[i] = (double)n[i];
00845             } else {
00846                 min_rate_[i] = INFINITY;
00847             }
00848         } else  if (cls_[i]->head() && concerned_ARC_[i]) {
00849             min_rate_[i] = n[i];
00850         } else {
00851           min_rate_[i] = 0.0;    
00852         }
00853     return (x);
00854 }
00855 
00856 // 1bis) Scheduling Helpers
00857 
00858 // *******************************************************************
00859 // JoBS: Update Error - used by the RDC feedback loop controller
00860 // *******************************************************************
00861 
00862 void JoBS::updateError() {
00863     int i;
00864     int activeClasses, backloggedClasses;
00865     double meanWeightedDelay;
00866 
00867     meanWeightedDelay = 0;
00868     activeClasses = 0 ; 
00869     backloggedClasses = 0;
00870     
00871     for (i = 1; i <= NO_CLASSES; i++) 
00872         if (cls_[i]->head() != NULL) {
00873             backloggedClasses++;
00874             if (concerned_RDC_[i]) {
00875                 meanWeightedDelay += prod_others_[i]*projDelay(i);
00876                 activeClasses ++;
00877             }    
00878         }
00879 
00880     if (activeClasses > 0) 
00881         meanWeightedDelay /= (double)activeClasses;
00882     else if (backloggedClasses == 0) {
00883         fprintf(stderr, "JoBS::updateError() called but there's no backlog!\n");
00884         abort();
00885     }
00886     
00887     for (i = 1; i <= NO_CLASSES; i++) 
00888         if ((cls_[i]->head() != NULL)&&(concerned_RDC_[i])) {
00889             error_[i] = meanWeightedDelay-prod_others_[i]*projDelay(i);
00890         } else {
00891             error_[i] = 0.0; // either the class isn't concerned, or it's not backlogged
00892             // in any case, the rate shouldn't be adjusted.
00893         }
00894     return;
00895 }
00896 // *******************************************************************
00897 // JoBS: Derives the rates needed for meeting the ADC.
00898 // Returns true if the sum of the rates needed for meeting the ADC
00899 // is less than the link's bandwidth, false otherwise.
00900 // It's also the place where the "RED" algorithm is triggered.
00901 // Side effect (desired): assigns a value to min_rate_[i]
00902 // *******************************************************************
00903 
00904 int JoBS::minRatesNeeded(int priority) {
00905     int result;
00906     int i;
00907     double cur_time;
00908     Packet* p;
00909     hdr_cmn* cm_h; 
00910 
00911     cur_time = Scheduler::instance().clock();
00912     result = TRUE;
00913   
00914     for (i = 1; i <= NO_CLASSES; i++) {
00915         if (cls_[i]->head() != 0 && (concerned_ADC_[i] || concerned_ARC_[i])) {
00916             p = cls_[i]->head();
00917             cm_h = hdr_cmn::access(p);
00918 
00919             if (concerned_ADC_[i]) { 
00920                 if ((ADC_[i] - (cur_time-cm_h->ts_)) > 0 ) {
00921                     // min rate needed for ADC
00922                     min_rate_[i] = (double)(backlog_Bits_[i])
00923                         /(double)(ADC_[i] - (cur_time-cm_h->ts_));
00924                     if (concerned_ARC_[i] && ARC_[i] > min_rate_[i]) {
00925                         // min rate needed for ADC+ARC
00926                         min_rate_[i] = ARC_[i];
00927                     }
00928                 } else 
00929                     min_rate_[i] = INFINITY;    
00930             } else if (concerned_ARC_[i]) {
00931                 // no ADC, an ARC
00932                 min_rate_[i] = ARC_[i];
00933             }
00934             if (min_rate_[i] > service_rate_[i]) 
00935                 result = FALSE;
00936         } else 
00937             min_rate_[i] = 0.0;
00938     }
00939     return result;
00940 }
00941 
00942 // *******************************************************************
00943 // JoBS: Returns the value of the delay metric for class i
00944 // *******************************************************************
00945 
00946 double JoBS::projDelay(int i) {
00947     double cur_time  = Scheduler::instance().clock(); 
00948     if (cls_[i]->head() != NULL) {
00949         Packet* p = cls_[i]->head();
00950         hdr_cmn* cm_h = hdr_cmn::access(p);
00951         return (cur_time - cm_h -> ts_);
00952     } else return 0.0; // __NOT REACHED__
00953 }
00954 
00955 // 2) Dropping Primitives
00956 
00957 // *******************************************************************
00958 // JoBS: Choose which class to drop from in case of a buffer overflow
00959 // *******************************************************************
00960 
00961 int JoBS::pickDroppedRLC(int mode) {
00962     double Mean;
00963     double loss_error[NO_CLASSES+1];
00964     int i, activeClasses, backloggedClasses;
00965     int class_dropped;
00966     double maxError;
00967     double maxALC;
00968     double cur_time  = Scheduler::instance().clock(); 
00969 
00970     hdr_cmn* cm_h; 
00971     
00972     class_dropped = -1;
00973     maxError = 0;
00974     Mean = 0;
00975     activeClasses = 0;
00976     backloggedClasses = 0;
00977     
00978     for (i = 1; i <= NO_CLASSES; i++) 
00979         if (cls_[i]->head() != NULL) {
00980             backloggedClasses ++;
00981             if (concerned_RLC_[i]) {
00982                 Mean += loss_prod_others_[i]*current_loss_[i];
00983                 activeClasses ++;
00984             }    
00985         }
00986     
00987     if (activeClasses > 0) 
00988         Mean /= (double)activeClasses;
00989     else if (backloggedClasses == 0) {
00990         fprintf(stderr, "JoBS::pickDroppedRLC() called but there's no backlog!\n");
00991         abort();
00992     }
00993 
00994     if (activeClasses == 0) 
00995         class_dropped = NO_CLASSES+1; // no classes are concerned by RLCs (NO_CLASSES+1 means "ignore RLC")
00996     else {
00997         for (i = 1; i <= NO_CLASSES; i++) 
00998             if ((cls_[i]->head() != NULL)&&(concerned_RLC_[i])) 
00999                 loss_error[i]=loss_prod_others_[i]*current_loss_[i]-Mean;
01000             else 
01001                 loss_error[i] = INFINITY; 
01002     
01003         for (i = 1; i <= NO_CLASSES; i++)
01004             if ((cls_[i]->head() != NULL)&&(loss_error[i] <= maxError)) {
01005                 maxError = loss_error[i]; // Find out which class is the most below the mean
01006                 class_dropped = i;   // It's the one that needs to be dropped
01007                 // Ties are broken in favor of the higher priority classes (i.e., if
01008                 // two classes present the same deviation, the lower priority class 
01009                 // will get dropped).
01010             } 
01011         
01012         if (class_dropped != -1) {
01013             if (drop_front_)
01014                 cm_h = hdr_cmn::access(cls_[class_dropped] -> head());
01015             else
01016                 cm_h = hdr_cmn::access(cls_[class_dropped] -> tail());
01017 
01018             if (current_loss_[class_dropped]+(double)8*cm_h -> size()/(double)Arrival_[class_dropped] > ALC_[class_dropped])
01019                 class_dropped = NO_CLASSES+1; // the class to drop for meeting the RLC will defeat the ALC: ignore RLC.
01020         } else 
01021             class_dropped = NO_CLASSES+1;
01022     }
01023 
01024     if (class_dropped != -1) { // this test is here only for "safety purposes" 
01025         // it should always return true at this point.
01026         if (class_dropped == NO_CLASSES+1) {
01027             maxALC = -INFINITY;
01028             for (i = 1; i <= NO_CLASSES; i++) {
01029                 if (cls_[i] -> tail() != NULL) {
01030                     if (ALC_[i]-current_loss_[i] > maxALC);
01031                     maxALC = ALC_[i]-current_loss_[i]; // pick the class which is the furthest from its ALC
01032                     class_dropped = i;
01033                 }
01034             }
01035             if (drop_front_)
01036               cm_h = hdr_cmn::access(cls_[class_dropped]->head());
01037             else
01038               cm_h = hdr_cmn::access(cls_[class_dropped]->tail());
01039             if ((mode == RESOLVE_OVERFLOW)
01040                 &&(current_loss_[class_dropped]+(double)8*cm_h -> size()/(double)Arrival_[class_dropped] > ALC_[class_dropped])) {
01041 
01042                 fprintf(stderr, "*** Warning at time t=%f: ALC violated in class %d on link %d\n(reason: buffer overflow impossible to resolve otherwise)\nPkt size=%d bits\told_loss[%d]=%f\tnew_loss[%d]=%f\tArrival_[%d]=%f\tALC[%d]=%f\n",
01043                     cur_time, link_id_,
01044                     class_dropped, 8*cm_h -> size(),
01045                     class_dropped, current_loss_[class_dropped],
01046                     class_dropped, current_loss_[class_dropped]+(double)8*cm_h -> size()/(double)Arrival_[class_dropped],
01047                     class_dropped, (double)Arrival_[class_dropped],
01048                     class_dropped, ALC_[class_dropped]);
01049             }
01050         }       
01051     } else {
01052         fprintf(stderr, "Trying to drop a packet, but there's nothing in any queue!\n");
01053         abort();
01054     }
01055     return class_dropped;
01056 }
01057 
01058 // *******************************************************************
01059 // JoBS: Drops traffic from the tail of the specified class, and 
01060 // update the statistics.
01061 // *******************************************************************
01062 
01063 void JoBS::dropTail(int prio, int strategy) {
01064     Packet *p;
01065     hdr_cmn *cm_h;
01066     
01067     p = cls_[prio] -> tail();
01068     cm_h = hdr_cmn::access(p);
01069     
01070     total_backlog_Pkts_ --;
01071     total_backlog_Bits_ -= 8*cm_h->size();
01072     backlog_Pkts_[prio] --;
01073     backlog_Bits_[prio] -= 8*cm_h->size();
01074     Rin_[prio] -= 8*cm_h->size();
01075     if (strategy == WITH_UPDATE) {
01076         for (int i = 1; i <= NO_CLASSES; i++) 
01077             current_loss_[i] = min_drop_[i];
01078         current_loss_[prio] += (double)8*cm_h -> size() 
01079             /(double)Arrival_[prio];
01080     }
01081     cls_[prio] -> remove(p);
01082     drop(p);
01083     return;
01084 }
01085 
01086 // *******************************************************************
01087 // JoBS: Drops traffic from the head of the specified class, and 
01088 // update the statistics.
01089 // *******************************************************************
01090 
01091 void JoBS::dropFront(int prio, int strategy) {
01092     Packet *p;
01093     hdr_cmn *cm_h;
01094     
01095     p = cls_[prio] -> head();
01096     cm_h = hdr_cmn::access(p);
01097     total_backlog_Pkts_ --;
01098     total_backlog_Bits_ -= 8*cm_h->size();
01099     backlog_Pkts_[prio] --;
01100     backlog_Bits_[prio] -= 8*cm_h->size();
01101     Rin_[prio] -= 8*cm_h->size();
01102     if (strategy == WITH_UPDATE) {
01103         for (int i = 1; i <= NO_CLASSES; i++) 
01104             current_loss_[i] = min_drop_[i];
01105         current_loss_[prio] += (double)8*cm_h -> size() 
01106           /(double)Arrival_[prio];
01107     }
01108     cls_[prio] -> remove(p);
01109     drop(p);
01110     return;
01111 }  
01112 
01113 
01114 // 3) Other Helpers
01115 
01116 // *******************************************************************
01117 // JoBS: Update internal variables upon a packet arrival.
01118 // *******************************************************************
01119 
01120 void JoBS::arvAccounting(Packet* thePacket) {
01121     int i;
01122     double cur_time;
01123     hdr_cmn* cm_h;
01124     hdr_cmn* cm_h1;
01125     hdr_cmn* cm_h2; 
01126     hdr_ip*  ip_h; 
01127     
01128     cur_time = Scheduler::instance().clock();
01129     cm_h = hdr_cmn::access(thePacket);
01130     ip_h = hdr_ip::access(thePacket);
01131     
01132     /* Update curves */
01133     
01134     Arrival_[ip_h -> prio()]      += 8*cm_h -> size();
01135     Rin_    [ip_h -> prio()]      += 8*cm_h -> size();
01136     if (last_rate_update_[ip_h -> prio()] == 0) {
01137         last_rate_update_[ip_h -> prio()] = cur_time;
01138     } else {
01139         Rout_th_ [ip_h -> prio()]      += (cur_time-last_rate_update_[ip_h -> prio()])*service_rate_[ip_h -> prio()];
01140         last_rate_update_[ip_h -> prio()] = cur_time;
01141     }
01142     backlog_Pkts_[ip_h -> prio()] ++;
01143     backlog_Bits_[ip_h -> prio()] += 8*cm_h -> size();
01144     total_backlog_Bits_ += 8*cm_h -> size();
01145     total_backlog_Pkts_ ++;
01146     
01147     for (i = 1; i <= NO_CLASSES; i++) {
01148         if (Arrival_[i] > 0) {
01149             current_loss_[i] = (double)(Arrival_[i] - Rin_[i])/(double)(Arrival_[i]);
01150             min_drop_[i] = (double)(max(0.0, (1.0-(double)(Rin_[i])/(double)Arrival_[i])));
01151             max_drop_[i] = (double)(min(1.0, (1.0-(double)((double)Rout_[i]/(double)Arrival_[i]))));    
01152         } else {
01153             current_loss_[i] = 0;
01154             min_drop_[i] = 0.0;
01155             max_drop_[i] = 0.0;
01156         }
01157         
01158         if (cls_[i]->head() != NULL) {
01159             cm_h1 = hdr_cmn::access(cls_[i]->head());
01160             cm_h2 = hdr_cmn::access(cls_[i]->tail());
01161             avg_elapsed_[i] = (2*cur_time - cm_h1 -> ts_ - cm_h2 -> ts_)/((backlog_Pkts_[i]>1)? 2.0 :1.0);
01162         }
01163     }
01164     return;
01165 }
01166 
01167 // 4) Debugging Tools
01168 
01169 void JoBS::updateStats(Packet* p, int action) {
01170     double cur_time = Scheduler::instance().clock();
01171     hdr_cmn* cm_h;
01172     hdr_ip* ip_h;
01173     
01174     cm_h = hdr_cmn::access(p);
01175     ip_h = hdr_ip::access(p);
01176     if (action == UPDATE_STATS) {
01177         sliding_arv_pkts_++;
01178         sliding_arv_pkts_c[ip_h->prio()]++;
01179         sliding_inter_ = (cur_time - last_arrival_ + sliding_inter_ * (sliding_arv_pkts_-1))
01180             /(double)sliding_arv_pkts_;
01181         sliding_avg_pkt_size_ = (sliding_avg_pkt_size_*(sliding_arv_pkts_ - 1) + 8*cm_h->size())
01182             /(double)sliding_arv_pkts_; 
01183         last_arrival_ = cur_time;
01184     } else if (action == RESET_STATS) {
01185         if (trace_hop_) {
01186             fprintf(hop_trace_, "%f\t", cur_time);
01187             for (int i=1;i<=NO_CLASSES;i++) {
01188                 fprintf(hop_trace_, "%.8f\t", max(current_loss_[i],0.00000001));
01189             }
01190             for (int i=1;i<=NO_CLASSES;i++) {
01191                 fprintf(hop_trace_, "%.8f\t", max(sliding_class_delay_[i],0.00000001));
01192             }
01193             for (int i=1;i<=NO_CLASSES;i++) {
01194                 sliding_class_service_rate_[i] = sliding_serviced_bits_[i]/(double)MON_WINDOW_SIZE;
01195                 fprintf(hop_trace_, "%.0f\t", max(sliding_class_service_rate_[i], 1));
01196                 sliding_serviced_pkts_[i] = 0;
01197                 sliding_serviced_bits_[i] = 0;
01198                 sliding_class_delay_[i] = 0;
01199                 sliding_class_service_rate_[i] = 0;
01200             }
01201             for (int i=1;i<=NO_CLASSES;i++) {
01202                 fprintf(hop_trace_, "%.0f\t", (double)cls_[i]->length());
01203             }
01204             fprintf(hop_trace_, "\n");
01205         }
01206         sliding_arv_pkts_ = 1;
01207         sliding_arv_pkts_c[ip_h->prio()] = 1;
01208         sliding_inter_ = cur_time - last_arrival_;
01209         sliding_avg_pkt_size_ = 8*cm_h->size();
01210         last_arrival_ = cur_time;
01211     }
01212     util_ = sliding_avg_pkt_size_ / (sliding_inter_*link_->bandwidth());
01213     return;
01214 }

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