00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
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_);
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) {
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);
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
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
00334
00335
00336 Packet* JoBS::deque() {
00337 double cur_time = Scheduler::instance().clock();
00338 double error;
00339 double maxError;
00340 int svc_class = 0;
00341
00342 error = 0;
00343
00344
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;
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
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;
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
00416
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
00433 if (!shared_buffer_ && backlog_Pkts_[prio] > qlim_/NO_CLASSES) {
00434
00435
00436
00437
00438 if (drop_front_)
00439 dropFront(prio, WITH_UPDATE);
00440 else
00441 dropTail(prio, WITH_UPDATE);
00442 } else {
00443
00444 if (total_backlog_Pkts_ > qlim_) {
00445 if (!concerned_RLC_[prio]) {
00446 if (!concerned_ALC_[prio]) {
00447
00448 if (drop_front_)
00449 dropFront(prio, WITH_UPDATE);
00450 else
00451 dropTail(prio, WITH_UPDATE);
00452 } else {
00453
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
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
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();
00478
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
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
00514
00515
00516
00517
00518
00519
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
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
00609
00610
00611
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
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
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
00669
00670
00671
00672 double* JoBS::assignRateDropsADC() {
00673 double* x;
00674
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
00721
00722 highest = 1;
00723 lowest = NO_CLASSES;
00724
00725 while ((highest < NO_CLASSES+1)&&(available[highest] >= 0))
00726 highest++;
00727 while ((lowest > 0)&&(available[lowest] <= 0))
00728 lowest--;
00729
00730
00731 while ((highest != NO_CLASSES+1)&&(lowest != 0)) {
00732
00733 if (available[lowest]+available[highest] > 0) {
00734
00735
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++;
00744
00745 } else if (available[lowest]+available[highest] == 0) {
00746
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++;
00755 while ((lowest > 0)&&(available[lowest] <= 0))
00756 lowest--;
00757
00758 } else if (available[lowest]+available[highest] < 0) {
00759
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--;
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
00779
00780 if (highest != NO_CLASSES+1) {
00781
00782 if (adc_resolution_type_ == SHARED_PAIN) {
00783
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
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
00857
00858
00859
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;
00892
00893 }
00894 return;
00895 }
00896
00897
00898
00899
00900
00901
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
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
00926 min_rate_[i] = ARC_[i];
00927 }
00928 } else
00929 min_rate_[i] = INFINITY;
00930 } else if (concerned_ARC_[i]) {
00931
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
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;
00953 }
00954
00955
00956
00957
00958
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;
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];
01006 class_dropped = i;
01007
01008
01009
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;
01020 } else
01021 class_dropped = NO_CLASSES+1;
01022 }
01023
01024 if (class_dropped != -1) {
01025
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];
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
01060
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
01088
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
01115
01116
01117
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
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
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 }