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 #ifndef lint
00037 static const char rcsid[] =
00038 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/red-pd.cc,v 1.7 2002/01/01 00:05:54 sfloyd Exp $ (ACIRI)";
00039 #endif
00040
00041 #include "red-pd.h"
00042 #include "red.h"
00043 #include "flowmon.h"
00044
00045 static class ReDPDClass : public TclClass {
00046 public:
00047 ReDPDClass() : TclClass("Queue/RED/PD") {}
00048 TclObject* create(int argc, const char*const* argv) {
00049
00050 if (argc==4) {
00051 return (new RedPDQueue("Drop", "Drop"));
00052 }
00053 else {
00054 char args[100];
00055 strcpy(args, argv[4]);
00056
00057 char * arg1 = strtok(args," ");
00058 char * arg2 = strtok(NULL," ");
00059
00060 if (arg2 == NULL) {
00061 printf("calling null arg2\n");
00062 return (new RedPDQueue(arg1, "Drop"));
00063 }
00064 else {
00065 return (new RedPDQueue(arg1, arg2));
00066 }
00067 }
00068
00069 }
00070 } red_pd_class;
00071
00072 static class RedPDFlowClass : public TclClass {
00073 public:
00074 RedPDFlowClass() : TclClass("QueueMonitor/ED/Flow/RedPD") {}
00075 TclObject* create(int, const char*const*) {
00076 return (new RedPDFlow);
00077 }
00078 } red_pd_flow_class;
00079
00080 RedPDQueue::RedPDQueue(const char * medtype, const char * edtype): REDQueue(edtype),
00081 auto_(0), global_target_(0), targetBW_(0), noMonitored_(0),
00082 unresponsive_penalty_(1), P_testFRp_(-1), noidle_(0),
00083 flowMonitor_(NULL), MEDTrace(NULL) {
00084
00085
00086 if (strlen(medtype) >=20) {
00087 printf("RedPD : Too Long a trace type. Change the field length in red-pd.h and recompile\n");
00088 exit(0);
00089 }
00090 strcpy(medTraceType, medtype);
00091
00092 off_ip_ = hdr_ip::offset();
00093
00094 bind_bool("auto_", &auto_);
00095 bind_bool("global_target_", &global_target_);
00096 bind_bool("noidle_", &noidle_);
00097 bind_bw("targetBW_", &targetBW_);
00098 bind("noMonitored_", &noMonitored_);
00099 bind("unresponsive_penalty_", &unresponsive_penalty_);
00100 bind("P_testFRp_", &P_testFRp_);
00101 }
00102
00103
00104 void RedPDQueue::reset() {
00105
00106 REDQueue::reset();
00107
00108
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 void RedPDQueue::enque(Packet* pkt) {
00122
00123 double P_monFlow=0;
00124
00125
00126
00127
00128
00129 if (flowMonitor_ == NULL) {
00130 printf("RedPD: ERROR: FlowMonitor Not Found --\n");
00131 abort();
00132 }
00133
00134 RedPDFlow * flow = (RedPDFlow *) flowMonitor_->find(pkt);
00135
00136 if (flow == NULL) {
00137 printf("RedPD: ERROR: Flow Not Found\n");
00138 abort();
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 if (flow->monitored()) {
00150
00151
00152
00153 if (flow->auto_) {
00154 flow->currentBW_ = flow->estRate_;
00155 }
00156
00157
00158 if (global_target_) {
00159 P_monFlow = getP_monFlow(flow->currentBW_, targetBW_);
00160 }
00161 else {
00162 P_monFlow = getP_monFlow(flow->currentBW_, flow->targetBW_);
00163 }
00164
00165 if (flow->unresponsive_) {
00166
00167 P_monFlow *= unresponsive_penalty_;
00168 }
00169
00170 if (P_monFlow != 0) {
00171 flow->lastDropTime_ = Scheduler::instance().clock();
00172 double mod_p = modify_p(P_monFlow, flow->count, 0, 0, 0, 0, 0);
00173
00174 P_monFlow = mod_p;
00175 double u = Random::uniform();
00176
00177 int drop=0;
00178
00179
00180 if (P_testFRp_ != -1 && u <= P_monFlow) {
00181 drop =1;
00182 }
00183
00184
00185
00186
00187 int qlen = qib_ ? q_->byteLength() : q_->length();
00188 if ( P_testFRp_ == -1 && u<= P_monFlow &&
00189 (
00190 (!flow->unresponsive_ && edv_.v_ave >= edp_.th_min && qlen > 1) ||
00191 (flow->unresponsive_ && ( qlen > 1 || !noidle_))
00192 )
00193 ) {
00194 drop = 1;
00195 }
00196
00197 if (drop) {
00198
00199 if (MEDTrace!= NULL)
00200 ((Trace *)MEDTrace)->recvOnly(pkt);
00201
00202 flowMonitor_->mon_edrop(pkt);
00203
00204
00205
00206
00207 Packet::free(pkt);
00208
00209 flow->count = 0;
00210 return;
00211 }
00212 else {
00213 flow->count++;
00214 }
00215 }
00216 }
00217
00218
00219
00220 if (P_testFRp_ != -1) {
00221 double p = P_testFRp_;
00222 int size = (hdr_cmn::access(pkt))->size();
00223 if (edp_.bytes) {
00224 p = (p * size) / edp_.mean_pktsize;
00225 }
00226 if (debug_)
00227 printf("FRp_ mode ON with %g\n",P_testFRp_);
00228 double u = Random::uniform();
00229 if (u <= p) {
00230 drop(pkt);
00231 return;
00232 }
00233 }
00234
00235 REDQueue::enque(pkt);
00236 }
00237
00238
00239 int RedPDQueue::command(int argc, const char*const* argv) {
00240
00241 Tcl& tcl = Tcl::instance();
00242 if (argc==2) {
00243 if (strcmp(argv[1], "mon-edrop-trace") == 0) {
00244 if (MEDTrace != NULL) {
00245 tcl.resultf("%s", MEDTrace->name());
00246
00247 }
00248 else {
00249
00250 tcl.resultf("0");
00251 }
00252 return (TCL_OK);
00253 }
00254 if (strcmp(argv[1], "mon-trace-type") == 0) {
00255 tcl.resultf("%s",medTraceType);
00256 return (TCL_OK);
00257 }
00258 }
00259 else if (argc == 3) {
00260
00261 if (strcmp(argv[1], "attach-flowmon") == 0) {
00262
00263 flowMonitor_ = (FlowMon *) TclObject::lookup(argv[2]);
00264 if (flowMonitor_ == NULL) {
00265 if (debug_) printf("Error Creating Flowmonitor\n");
00266 return (TCL_ERROR);
00267 }
00268 if (debug_)
00269 printf("RedPD: Flow Monitor Set to %s\n", flowMonitor_->name());
00270
00271 de_drop_ = (NsObject *) flowMonitor_;
00272 return (TCL_OK);
00273 }
00274
00275
00276 else if (strcmp(argv[1], "showme") == 0) {
00277
00278 RedPDFlow * flow = (RedPDFlow *) TclObject::lookup(argv[2]);
00279 printf("showing now : %s = %d\n", flow->name(), flow->monitored_);
00280 return (TCL_OK);
00281 }
00282
00283
00284 else if (strcmp(argv[1], "mon-edrop-trace") == 0) {
00285
00286 MEDTrace = (NsObject *) TclObject::lookup(argv[2]);
00287 if (MEDTrace == NULL) {
00288 if (debug_) printf("Error Attaching Trace\n");
00289 return (TCL_ERROR);
00290 }
00291 if (debug_)
00292 printf("RedPD: MEDTrace Set to %s\n", flowMonitor_->name());
00293 return (TCL_OK);
00294 }
00295
00296 else if (strcmp(argv[1], "unmonitor-flow") == 0) {
00297 RedPDFlow * flow = (RedPDFlow *) TclObject::lookup(argv[2]);
00298
00299 if (flow->monitored_ != 1) {
00300 tcl.resultf("Cannot unmonitor an unmonitored flow: %d\n", flow->flowid());
00301 return(TCL_ERROR);
00302 }
00303
00304 flow->monitored_ = 0;
00305 flow->unresponsive_ = 0;
00306 flow->monitorStartTime_ = 0;
00307 flow->lastDropTime_ = 0;
00308 flow->unresponsiveStartTime_ = 0;
00309
00310 noMonitored_--;
00311
00312 if ( noMonitored_ < 0 ) {
00313 tcl.resultf("noMonitored gone below ZERO\n");
00314 return TCL_ERROR;
00315 }
00316 return TCL_OK;
00317 }
00318
00319
00320 else if (strcmp(argv[1], "unresponsive-flow") == 0) {
00321 RedPDFlow * flow = (RedPDFlow *) TclObject::lookup(argv[2]);
00322
00323 if (flow->monitored_ != 1) {
00324 tcl.resultf("Cannot make an unmonitored flow unresponsive: %d\n",
00325 flow->flowid());
00326 return(TCL_ERROR);
00327 }
00328
00329 if (flow->unresponsive_ != 1) {
00330 flow->unresponsive_ = 1;
00331 flow->unresponsiveStartTime_ = Scheduler::instance().clock();
00332 }
00333
00334 if (flow->auto_) {
00335 flow->estimate_rate_=1;
00336 }
00337
00338 return TCL_OK;
00339 }
00340
00341 else if (strcmp(argv[1], "responsive-flow") == 0) {
00342 RedPDFlow * flow = (RedPDFlow *) TclObject::lookup(argv[2]);
00343
00344 if (flow->unresponsive_ != 1) {
00345 tcl.resultf("Cannot make a responsive flow responsive: %d\n",
00346 flow->flowid());
00347 return(TCL_ERROR);
00348 }
00349 flow->unresponsive_ = 0;
00350 flow->unresponsiveStartTime_ = 0;
00351
00352 return TCL_OK;
00353 }
00354 }
00355 else if (argc == 4) {
00356
00357
00358 if (strcmp(argv[1], "monitor-flow") == 0) {
00359
00360
00361
00362 tcl.evalf("%s monitor-flow %s %g 1",name(), argv[2], 1 - atof(argv[3]));
00363 return(TCL_OK);
00364 }
00365 }
00366 else if (argc == 5) {
00367
00368 if (strcmp(argv[1], "monitor-flow") == 0) {
00369 RedPDFlow * flow = (RedPDFlow *) TclObject::lookup(argv[2]);
00370
00371 tcl.evalf("%s set targetBW_ %s", flow->name(), argv[3]);
00372 tcl.evalf("%s set currentBW_ %s", flow->name(), argv[4]);
00373
00374 if (flow->monitored_ != 1) {
00375 flow->monitored_=1;
00376 noMonitored_ ++;
00377 flow->monitorStartTime_ = Scheduler::instance().clock();
00378 }
00379
00380
00381 if (auto_) {
00382 flow->estimate_rate_=1;
00383 flow->estRate_ = flow->currentBW_;
00384 }
00385
00386 return (TCL_OK);
00387 }
00388 }
00389
00390 return (REDQueue::command(argc, argv));
00391 }
00392