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
00364 *queue = 0;
00365 *prec = 0;
00366 printf("ERROR: No match found for code point %d in PHB Table.\n", codePt);
00367 assert (false);
00368 }
00369
00370
00371
00372
00373
00374
00375 void dsREDQueue::addPHBEntry(int codePt, int queue, int prec) {
00376 if (phbEntries == MAX_CP) {
00377 printf("ERROR: PHB Table size limit exceeded.\n");
00378 } else {
00379 phb_[phbEntries].codePt_ = codePt;
00380 phb_[phbEntries].queue_ = queue;
00381 phb_[phbEntries].prec_ = prec;
00382 stats.valid_CP[codePt] = 1;
00383 phbEntries++;
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392 double dsREDQueue::getStat(int argc, const char*const* argv) {
00393
00394 if (argc == 3) {
00395 if (strcmp(argv[2], "drops") == 0)
00396 return (stats.drops*1.0);
00397 if (strcmp(argv[2], "edrops") == 0)
00398 return (stats.edrops*1.0);
00399 if (strcmp(argv[2], "pkts") == 0)
00400 return (stats.pkts*1.0);
00401 }
00402 if (argc == 4) {
00403 if (strcmp(argv[2], "drops") == 0)
00404 return (stats.drops_CP[atoi(argv[3])]*1.0);
00405 if (strcmp(argv[2], "edrops") == 0)
00406 return (stats.edrops_CP[atoi(argv[3])]*1.0);
00407 if (strcmp(argv[2], "pkts") == 0)
00408 return (stats.pkts_CP[atoi(argv[3])]*1.0);
00409 }
00410 return -1.0;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 void dsREDQueue::setNumPrec(int prec) {
00420 int i;
00421
00422 if (prec > MAX_PREC) {
00423 printf("ERROR: Cannot declare more than %d prcedence levels (as defined by MAX_PREC)\n",MAX_PREC);
00424 } else {
00425 numPrec = prec;
00426
00427 for (i = 0; i < MAX_QUEUES; i++)
00428 redq_[i].numPrec = numPrec;
00429 }
00430 }
00431
00432
00433
00434
00435
00436 void dsREDQueue::setMREDMode(const char* mode, const char* queue) {
00437 int i;
00438 mredModeType tempMode;
00439
00440 if (strcmp(mode, "RIO-C") == 0)
00441 tempMode = rio_c;
00442 else if (strcmp(mode, "RIO-D") == 0)
00443 tempMode = rio_d;
00444 else if (strcmp(mode, "WRED") == 0)
00445 tempMode = wred;
00446 else if (strcmp(mode, "DROP") == 0)
00447 tempMode = dropTail;
00448 else {
00449 printf("Error: MRED mode %s does not exist\n",mode);
00450 return;
00451 }
00452
00453 if (!queue)
00454 for (i = 0; i < MAX_QUEUES; i++)
00455 redq_[i].mredMode = tempMode;
00456 else
00457 redq_[atoi(queue)].mredMode = tempMode;
00458 }
00459
00460
00461
00462
00463
00464
00465 void dsREDQueue::printPHBTable() {
00466 printf("PHB Table:\n");
00467 for (int i = 0; i < phbEntries; i++)
00468 printf("Code Point %d is associated with Queue %d, Precedence %d\n", phb_[i].codePt_, phb_[i].queue_, phb_[i].prec_);
00469 printf("\n");
00470 }
00471
00472
00473
00474
00475
00476
00477 void dsREDQueue::printStats() {
00478 printf("\nPackets Statistics\n");
00479 printf("=======================================\n");
00480 printf(" CP TotPkts TxPkts ldrops edrops\n");
00481 printf(" -- ------- ------ ------ ------\n");
00482 printf("All %8ld %8ld %8ld %8ld\n",stats.pkts,stats.pkts-stats.drops-stats.edrops,stats.drops,stats.edrops);
00483 for (int i = 0; i < MAX_CP; i++)
00484 if (stats.pkts_CP[i] != 0)
00485 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]);
00486
00487 }
00488
00489
00490 void dsREDQueue::printWRRcount() {
00491 int i;
00492 for (i = 0; i < numQueues_; i++){
00493 printf("%d: %d %d %d.\n", i, slicecount[i],pktcount[i],queueWeight[i]);
00494 }
00495 }
00496
00497
00498
00499
00500
00501
00502 void dsREDQueue::setSchedularMode(const char* schedtype) {
00503 if (strcmp(schedtype, "RR") == 0)
00504 schedMode = schedModeRR;
00505 else if (strcmp(schedtype, "WRR") == 0)
00506 schedMode = schedModeWRR;
00507 else if (strcmp(schedtype, "WIRR") == 0)
00508 schedMode = schedModeWIRR;
00509 else if (strcmp(schedtype, "PRI") == 0)
00510 schedMode = schedModePRI;
00511 else
00512 printf("Error: Scheduler type %s does not exist\n",schedtype);
00513 }
00514
00515
00516
00517
00518
00519
00520 void dsREDQueue::addQueueWeights(int queueNum, int weight) {
00521 if(queueNum < MAX_QUEUES){
00522 queueWeight[queueNum]=weight;
00523 } else {
00524 printf("The queue number is out of range.\n");
00525 }
00526 }
00527
00528
00529 void dsREDQueue::addQueueRate(int queueNum, int rate) {
00530 if(queueNum < MAX_QUEUES){
00531
00532 queueMaxRate[queueNum]=(double)rate/8.0;
00533 } else {
00534 printf("The queue number is out of range.\n");
00535 }
00536 }
00537
00538
00539
00540
00541
00542 int dsREDQueue::command(int argc, const char*const* argv) {
00543 if (strcmp(argv[1], "configQ") == 0) {
00544
00545 redq_[atoi(argv[2])].config(atoi(argv[3]), argc, argv);
00546 return(TCL_OK);
00547 }
00548 if (strcmp(argv[1], "addPHBEntry") == 0) {
00549 addPHBEntry(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
00550 return (TCL_OK);
00551 }
00552 if (strcmp(argv[1], "meanPktSize") == 0) {
00553 for (int i = 0; i < MAX_QUEUES; i++)
00554 redq_[i].setMPS(atoi(argv[2]));
00555 return(TCL_OK);
00556 }
00557 if (strcmp(argv[1], "setNumPrec") == 0) {
00558 setNumPrec(atoi(argv[2]));
00559 return(TCL_OK);
00560 }
00561 if (strcmp(argv[1], "getAverage") == 0) {
00562 Tcl& tcl = Tcl::instance();
00563 tcl.resultf("%f", redq_[atoi(argv[2])].getWeightedLength());
00564 return(TCL_OK);
00565 }
00566 if (strcmp(argv[1], "getStat") == 0) {
00567 Tcl& tcl = Tcl::instance();
00568 tcl.resultf("%f", getStat(argc,argv));
00569 return(TCL_OK);
00570 }
00571 if (strcmp(argv[1], "getCurrent") == 0) {
00572 Tcl& tcl = Tcl::instance();
00573 tcl.resultf("%f", redq_[atoi(argv[2])].getRealLength()*1.0);
00574 return(TCL_OK);
00575 }
00576 if (strcmp(argv[1], "printStats") == 0) {
00577 printStats();
00578 return (TCL_OK);
00579 }
00580 if (strcmp(argv[1], "printWRRcount") == 0) {
00581 printWRRcount();
00582 return (TCL_OK);
00583 }
00584 if (strcmp(argv[1], "printPHBTable") == 0) {
00585 printPHBTable();
00586 return (TCL_OK);
00587 }
00588 if (strcmp(argv[1], "link") == 0) {
00589 Tcl& tcl = Tcl::instance();
00590 LinkDelay* del = (LinkDelay*) TclObject::lookup(argv[2]);
00591 if (del == 0) {
00592 tcl.resultf("RED: no LinkDelay object %s",
00593 argv[2]);
00594 return(TCL_ERROR);
00595 }
00596 link_ = del;
00597 return (TCL_OK);
00598 }
00599 if (strcmp(argv[1], "early-drop-target") == 0) {
00600 Tcl& tcl = Tcl::instance();
00601 NsObject* p = (NsObject*)TclObject::lookup(argv[2]);
00602 if (p == 0) {
00603 tcl.resultf("no object %s", argv[2]);
00604 return (TCL_ERROR);
00605 }
00606 de_drop_ = p;
00607 return (TCL_OK);
00608 }
00609 if (strcmp(argv[1], "setSchedularMode") == 0) {
00610 setSchedularMode(argv[2]);
00611 return(TCL_OK);
00612 }
00613 if (strcmp(argv[1], "setMREDMode") == 0) {
00614 if (argc == 3)
00615 setMREDMode(argv[2],0);
00616 else
00617 setMREDMode(argv[2],argv[3]);
00618 return(TCL_OK);
00619 }
00620 if (strcmp(argv[1], "addQueueWeights") == 0) {
00621 addQueueWeights(atoi(argv[2]), atoi(argv[3]));
00622 return(TCL_OK);
00623 }
00624 if (strcmp(argv[1], "addQueueRate") == 0) {
00625 addQueueRate(atoi(argv[2]), atoi(argv[3]));
00626 return(TCL_OK);
00627 }
00628
00629
00630 if (strcmp(argv[1], "getAverageV") == 0) {
00631 Tcl& tcl = Tcl::instance();
00632 tcl.resultf("%f",
00633 redq_[atoi(argv[2])].getWeightedLength_v(atoi(argv[3])));
00634 return(TCL_OK);
00635 }
00636
00637
00638 if (strcmp(argv[1], "getCurrentV") == 0) {
00639 Tcl& tcl = Tcl::instance();
00640 tcl.resultf("%f",
00641 redq_[atoi(argv[2])].getRealLength_v(atoi(argv[3]))*1.0);
00642 return(TCL_OK);
00643 }
00644
00645 return(Queue::command(argc, argv));
00646 }
00647
00648