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

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.2 2003/02/04 20:45:55 xuanc 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.2 2003/02/04 20:45:55 xuanc 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];
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 Apr 20 12:14:21 2004 for NS2.26SourcesOriginal by doxygen 1.3.3