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 #include <stdio.h>
00038 #include "ip.h"
00039 #include "dsred.h"
00040 #include "delay.h"
00041 #include "random.h"
00042 #include "flags.h"
00043 #include "tcp.h"
00044 #include "dsredq.h"
00045
00046
00047
00048
00049
00050
00051
00052 static class dsREDClass : public TclClass {
00053 public:
00054 dsREDClass() : TclClass("Queue/dsRED") {}
00055 TclObject* create(int, const char*const*) {
00056 return (new dsREDQueue);
00057 }
00058 } class_dsred;
00059
00060
00061
00062
00063
00064
00065
00066
00067 dsREDQueue::dsREDQueue() : de_drop_(NULL), link_(NULL) {
00068 bind("numQueues_", &numQueues_);
00069 bind_bool("ecn_", &ecn_);
00070 int i;
00071
00072 numPrec = MAX_PREC;
00073 schedMode = schedModeRR;
00074
00075 for(i=0;i<MAX_QUEUES;i++){
00076 queueMaxRate[i] = 0;
00077 queueWeight[i]=1;
00078 }
00079
00080 queuesDone = MAX_QUEUES;
00081 phbEntries = 0;
00082
00083 reset();
00084 }
00085
00086
00087 void dsREDQueue::reset() {
00088 int i;
00089
00090 qToDq = 0;
00091
00092 for(i=0;i<MAX_QUEUES;i++){
00093 queueAvgRate[i] = 0.0;
00094 queueArrTime[i] = 0.0;
00095 slicecount[i]=0;
00096 pktcount[i]=0;
00097 wirrTemp[i]=0;
00098 wirrqDone[i]=0;
00099 }
00100
00101 stats.drops = 0;
00102 stats.edrops = 0;
00103 stats.pkts = 0;
00104
00105 for(i=0;i<MAX_CP;i++){
00106 stats.drops_CP[i]=0;
00107 stats.edrops_CP[i]=0;
00108 stats.pkts_CP[i]=0;
00109 }
00110
00111 for (i = 0; i < MAX_QUEUES; i++)
00112 redq_[i].qlim = limit();
00113
00114
00115
00116
00117 if (link_)
00118 for (int i = 0; i < MAX_QUEUES; i++)
00119 redq_[i].setPTC(link_->bandwidth());
00120
00121 Queue::reset();
00122 }
00123
00124
00125
00126
00127
00128
00129 void dsREDQueue::edrop(Packet* p)
00130 {
00131
00132 if (de_drop_ != 0){
00133 de_drop_->recv(p);
00134 }
00135 else {
00136 drop(p);
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 void dsREDQueue::applyTSWMeter(int q_id, int pkt_size) {
00151 double now, bytesInTSW, newBytes;
00152 double winLen = 1.0;
00153
00154 bytesInTSW = queueAvgRate[q_id] * winLen;
00155
00156
00157
00158
00159 newBytes = bytesInTSW + pkt_size;
00160
00161
00162 now = Scheduler::instance().clock();
00163 queueAvgRate[q_id] = newBytes / (now - queueArrTime[q_id] + winLen);
00164 queueArrTime[q_id] = now;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 void dsREDQueue::enque(Packet* pkt) {
00175 int codePt, eq_id, prec;
00176 hdr_ip* iph = hdr_ip::access(pkt);
00177
00178 codePt = iph->prio();
00179 int ecn = 0;
00180
00181
00182 lookupPHBTable(codePt, &eq_id, &prec);
00183
00184
00185
00186
00187 hdr_flags* hf = hdr_flags::access(pkt);
00188
00189 if (ecn_ && hf->ect()) ecn = 1;
00190
00191 stats.pkts_CP[codePt]++;
00192 stats.pkts++;
00193
00194 switch(redq_[eq_id].enque(pkt, prec, ecn)) {
00195 case PKT_ENQUEUED:
00196 break;
00197 case PKT_DROPPED:
00198 stats.drops_CP[codePt]++;
00199 stats.drops++;
00200 drop(pkt);
00201 break;
00202 case PKT_EDROPPED:
00203 stats.edrops_CP[codePt]++;
00204 stats.edrops++;
00205 edrop(pkt);
00206 break;
00207 case PKT_MARKED:
00208 hf->ce() = 1;
00209 break;
00210 default:
00211 break;
00212 }
00213 }
00214
00215
00216 Packet* dsREDQueue::deque() {
00217 Packet *p = NULL;
00218 int queue, prec;
00219 hdr_ip* iph;
00220 int fid;
00221 int dq_id;
00222
00223
00224 dq_id = selectQueueToDeque();
00225
00226
00227 if (dq_id < numQueues_)
00228 p = redq_[dq_id].deque();
00229
00230 if (p) {
00231 iph= hdr_ip::access(p);
00232 fid = iph->flowid()/32;
00233 pktcount[dq_id]+=1;
00234
00235
00236
00237
00238
00239
00240
00241 if (schedMode==schedModePRI)
00242 for (int i=0;i<numQueues_;i++)
00243 if (queueMaxRate[i])
00244 applyTSWMeter(i, (i == dq_id) ? hdr_cmn::access(p)->size() : 0);
00245
00246
00247
00248 lookupPHBTable(getCodePt(p), &queue, &prec);
00249
00250
00251
00252
00253 redq_[dq_id].updateVREDLen(prec);
00254
00255 redq_[dq_id].updateREDStateVar(prec);
00256 }
00257
00258
00259 return(p);
00260 }
00261
00262
00263 int dsREDQueue::getCodePt(Packet *p) {
00264 hdr_ip* iph = hdr_ip::access(p);
00265 return(iph->prio());
00266 }
00267
00268
00269 int dsREDQueue::selectQueueToDeque() {
00270
00271
00272 int i = 0;
00273
00274
00275 if(schedMode==schedModeRR){
00276
00277 qToDq = ((qToDq + 1) % numQueues_);
00278 while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00279 qToDq = ((qToDq + 1) % numQueues_);
00280 i++;
00281 }
00282 } else if (schedMode==schedModeWRR) {
00283 if(wirrTemp[qToDq]<=0){
00284 qToDq = ((qToDq + 1) % numQueues_);
00285 wirrTemp[qToDq] = queueWeight[qToDq] - 1;
00286 } else {
00287 wirrTemp[qToDq] = wirrTemp[qToDq] -1;
00288 }
00289 while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00290 wirrTemp[qToDq] = 0;
00291 qToDq = ((qToDq + 1) % numQueues_);
00292 wirrTemp[qToDq] = queueWeight[qToDq] - 1;
00293 i++;
00294 }
00295 } else if (schedMode==schedModeWIRR) {
00296 qToDq = ((qToDq + 1) % numQueues_);
00297 while ((i<numQueues_) && ((redq_[qToDq].getRealLength()==0) || (wirrqDone[qToDq]))) {
00298 if (!wirrqDone[qToDq]) {
00299 queuesDone++;
00300 wirrqDone[qToDq]=1;
00301 }
00302 qToDq = ((qToDq + 1) % numQueues_);
00303 i++;
00304 }
00305
00306 if (wirrTemp[qToDq] == 1) {
00307 queuesDone +=1;
00308 wirrqDone[qToDq]=1;
00309 }
00310 wirrTemp[qToDq]-=1;
00311 if(queuesDone >= numQueues_) {
00312 queuesDone = 0;
00313 for(i=0;i<numQueues_;i++) {
00314 wirrTemp[i] = queueWeight[i];
00315 wirrqDone[i]=0;
00316 }
00317 }
00318 } else if (schedMode==schedModePRI) {
00319
00320
00321
00322
00323
00324 i = 0;
00325 while (i < numQueues_ &&
00326 (redq_[i].getRealLength() == 0 ||
00327 (queueMaxRate[i] && queueAvgRate[i]>queueMaxRate[i]))){
00328 i++;
00329 }
00330 qToDq = i;
00331
00332
00333
00334
00335
00336
00337
00338 if (i == numQueues_) {
00339 i = qToDq = 0;
00340 while ((i < numQueues_) && (redq_[qToDq].getRealLength() == 0)) {
00341 qToDq = ((qToDq + 1) % numQueues_);
00342 i++;
00343 }
00344 }
00345 }
00346 return(qToDq);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 void dsREDQueue::lookupPHBTable(int codePt, int* queue, int* prec) {
00356 for (int i = 0; i < phbEntries; i++) {
00357 if (phb_[i].codePt_ == codePt) {
00358 *queue = phb_[i].queue_;
00359 *prec = phb_[i].prec_;
00360 return;
00361 }
00362 }
00363 printf("ERROR: No match found for code point %d in PHB Table.\n", codePt);
00364 }
00365
00366
00367
00368
00369
00370
00371 void dsREDQueue::addPHBEntry(int codePt, int queue, int prec) {
00372 if (phbEntries == MAX_CP) {
00373 printf("ERROR: PHB Table size limit exceeded.\n");
00374 } else {
00375 phb_[phbEntries].codePt_ = codePt;
00376 phb_[phbEntries].queue_ = queue;
00377 phb_[phbEntries].prec_ = prec;
00378 stats.valid_CP[codePt] = 1;
00379 phbEntries++;
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388 double dsREDQueue::getStat(int argc, const char*const* argv) {
00389
00390 if (argc == 3) {
00391 if (strcmp(argv[2], "drops") == 0)
00392 return (stats.drops*1.0);
00393 if (strcmp(argv[2], "edrops") == 0)
00394 return (stats.edrops*1.0);
00395 if (strcmp(argv[2], "pkts") == 0)
00396 return (stats.pkts*1.0);
00397 }
00398 if (argc == 4) {
00399 if (strcmp(argv[2], "drops") == 0)
00400 return (stats.drops_CP[atoi(argv[3])]*1.0);
00401 if (strcmp(argv[2], "edrops") == 0)
00402 return (stats.edrops_CP[atoi(argv[3])]*1.0);
00403 if (strcmp(argv[2], "pkts") == 0)
00404 return (stats.pkts_CP[atoi(argv[3])]*1.0);
00405 }
00406 return -1.0;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415 void dsREDQueue::setNumPrec(int prec) {
00416 int i;
00417
00418 if (prec > MAX_PREC) {
00419 printf("ERROR: Cannot declare more than %d prcedence levels (as defined by MAX_PREC)\n",MAX_PREC);
00420 } else {
00421 numPrec = prec;
00422
00423 for (i = 0; i < MAX_QUEUES; i++)
00424 redq_[i].numPrec = numPrec;
00425 }
00426 }
00427
00428
00429
00430
00431
00432 void dsREDQueue::setMREDMode(const char* mode, const char* queue) {
00433 int i;
00434 mredModeType tempMode;
00435
00436 if (strcmp(mode, "RIO-C") == 0)
00437 tempMode = rio_c;
00438 else if (strcmp(mode, "RIO-D") == 0)
00439 tempMode = rio_d;
00440 else if (strcmp(mode, "WRED") == 0)
00441 tempMode = wred;
00442 else if (strcmp(mode, "DROP") == 0)
00443 tempMode = dropTail;
00444 else {
00445 printf("Error: MRED mode %s does not exist\n",mode);
00446 return;
00447 }
00448
00449 if (!queue)
00450 for (i = 0; i < MAX_QUEUES; i++)
00451 redq_[i].mredMode = tempMode;
00452 else
00453 redq_[atoi(queue)].mredMode = tempMode;
00454 }
00455
00456
00457
00458
00459
00460
00461 void dsREDQueue::printPHBTable() {
00462 printf("PHB Table:\n");
00463 for (int i = 0; i < phbEntries; i++)
00464 printf("Code Point %d is associated with Queue %d, Precedence %d\n", phb_[i].codePt_, phb_[i].queue_, phb_[i].prec_);
00465 printf("\n");
00466 }
00467
00468
00469
00470
00471
00472
00473 void dsREDQueue::printStats() {
00474 printf("\nPackets Statistics\n");
00475 printf("=======================================\n");
00476 printf(" CP TotPkts TxPkts ldrops edrops\n");
00477 printf(" -- ------- ------ ------ ------\n");
00478 printf("All %8ld %8ld %8ld %8ld\n",stats.pkts,stats.pkts-stats.drops-stats.edrops,stats.drops,stats.edrops);
00479 for (int i = 0; i < MAX_CP; i++)
00480 if (stats.pkts_CP[i] != 0)
00481 printf("%3d %8ld %8ld %8ld %8ld\n",i,stats.pkts_CP[i],stats.pkts_CP[i]-stats.drops_CP[i]-stats.edrops_CP[i],stats.drops_CP[i],stats.edrops_CP[i]);
00482
00483 }
00484
00485
00486 void dsREDQueue::printWRRcount() {
00487 int i;
00488 for (i = 0; i < numQueues_; i++){
00489 printf("%d: %d %d %d.\n", i, slicecount[i],pktcount[i],queueWeight[i]);
00490 }
00491 }
00492
00493
00494
00495
00496
00497
00498 void dsREDQueue::setSchedularMode(const char* schedtype) {
00499 if (strcmp(schedtype, "RR") == 0)
00500 schedMode = schedModeRR;
00501 else if (strcmp(schedtype, "WRR") == 0)
00502 schedMode = schedModeWRR;
00503 else if (strcmp(schedtype, "WIRR") == 0)
00504 schedMode = schedModeWIRR;
00505 else if (strcmp(schedtype, "PRI") == 0)
00506 schedMode = schedModePRI;
00507 else
00508 printf("Error: Scheduler type %s does not exist\n",schedtype);
00509 }
00510
00511
00512
00513
00514
00515
00516 void dsREDQueue::addQueueWeights(int queueNum, int weight) {
00517 if(queueNum < MAX_QUEUES){
00518 queueWeight[queueNum]=weight;
00519 } else {
00520 printf("The queue number is out of range.\n");
00521 }
00522 }
00523
00524
00525 void dsREDQueue::addQueueRate(int queueNum, int rate) {
00526 if(queueNum < MAX_QUEUES){
00527
00528 queueMaxRate[queueNum]=(double)rate/8.0;
00529 } else {
00530 printf("The queue number is out of range.\n");
00531 }
00532 }
00533
00534
00535
00536
00537
00538 int dsREDQueue::command(int argc, const char*const* argv) {
00539 if (strcmp(argv[1], "configQ") == 0) {
00540
00541 redq_[atoi(argv[2])].config(atoi(argv[3]), argc, argv);
00542 return(TCL_OK);
00543 }
00544 if (strcmp(argv[1], "addPHBEntry") == 0) {
00545 addPHBEntry(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
00546 return (TCL_OK);
00547 }
00548 if (strcmp(argv[1], "meanPktSize") == 0) {
00549 for (int i = 0; i < MAX_QUEUES; i++)
00550 redq_[i].setMPS(atoi(argv[2]));
00551 return(TCL_OK);
00552 }
00553 if (strcmp(argv[1], "setNumPrec") == 0) {
00554 setNumPrec(atoi(argv[2]));
00555 return(TCL_OK);
00556 }
00557 if (strcmp(argv[1], "getAverage") == 0) {
00558 Tcl& tcl = Tcl::instance();
00559 tcl.resultf("%f", redq_[atoi(argv[2])].getWeightedLength());
00560 return(TCL_OK);
00561 }
00562 if (strcmp(argv[1], "getStat") == 0) {
00563 Tcl& tcl = Tcl::instance();
00564 tcl.resultf("%f", getStat(argc,argv));
00565 return(TCL_OK);
00566 }
00567 if (strcmp(argv[1], "getCurrent") == 0) {
00568 Tcl& tcl = Tcl::instance();
00569 tcl.resultf("%f", redq_[atoi(argv[2])].getRealLength()*1.0);
00570 return(TCL_OK);
00571 }
00572 if (strcmp(argv[1], "printStats") == 0) {
00573 printStats();
00574 return (TCL_OK);
00575 }
00576 if (strcmp(argv[1], "printWRRcount") == 0) {
00577 printWRRcount();
00578 return (TCL_OK);
00579 }
00580 if (strcmp(argv[1], "printPHBTable") == 0) {
00581 printPHBTable();
00582 return (TCL_OK);
00583 }
00584 if (strcmp(argv[1], "link") == 0) {
00585 Tcl& tcl = Tcl::instance();
00586 LinkDelay* del = (LinkDelay*) TclObject::lookup(argv[2]);
00587 if (del == 0) {
00588 tcl.resultf("RED: no LinkDelay object %s",
00589 argv[2]);
00590 return(TCL_ERROR);
00591 }
00592 link_ = del;
00593 return (TCL_OK);
00594 }
00595 if (strcmp(argv[1], "early-drop-target") == 0) {
00596 Tcl& tcl = Tcl::instance();
00597 NsObject* p = (NsObject*)TclObject::lookup(argv[2]);
00598 if (p == 0) {
00599 tcl.resultf("no object %s", argv[2]);
00600 return (TCL_ERROR);
00601 }
00602 de_drop_ = p;
00603 return (TCL_OK);
00604 }
00605 if (strcmp(argv[1], "setSchedularMode") == 0) {
00606 setSchedularMode(argv[2]);
00607 return(TCL_OK);
00608 }
00609 if (strcmp(argv[1], "setMREDMode") == 0) {
00610 if (argc == 3)
00611 setMREDMode(argv[2],0);
00612 else
00613 setMREDMode(argv[2],argv[3]);
00614 return(TCL_OK);
00615 }
00616 if (strcmp(argv[1], "addQueueWeights") == 0) {
00617 addQueueWeights(atoi(argv[2]), atoi(argv[3]));
00618 return(TCL_OK);
00619 }
00620 if (strcmp(argv[1], "addQueueRate") == 0) {
00621 addQueueRate(atoi(argv[2]), atoi(argv[3]));
00622 return(TCL_OK);
00623 }
00624
00625
00626 if (strcmp(argv[1], "getAverageV") == 0) {
00627 Tcl& tcl = Tcl::instance();
00628 tcl.resultf("%f",
00629 redq_[atoi(argv[2])].getWeightedLength_v(atoi(argv[3])));
00630 return(TCL_OK);
00631 }
00632
00633
00634 if (strcmp(argv[1], "getCurrentV") == 0) {
00635 Tcl& tcl = Tcl::instance();
00636 tcl.resultf("%f",
00637 redq_[atoi(argv[2])].getRealLength_v(atoi(argv[3]))*1.0);
00638 return(TCL_OK);
00639 }
00640
00641 return(Queue::command(argc, argv));
00642 }
00643
00644