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 #ifndef lint
00050 static const char rcsid[] =
00051 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/xcp/xcp.cc,v 1.10 2005/08/25 18:58:14 johnh Exp $";
00052 #endif
00053
00054
00055 #include "xcp.h"
00056 #include "red.h"
00057
00058 static unsigned int next_router = 0;
00059
00060 static class XCPClass : public TclClass {
00061 public:
00062 XCPClass() : TclClass("Queue/XCP") {}
00063 TclObject* create(int, const char*const*) {
00064 return (new XCPWrapQ);
00065 }
00066 } class_xcp_queue;
00067
00068 XCPWrapQ::XCPWrapQ() : xcpq_(0), qToDq_(0), spread_bytes_(0), tcp_xcp_on_(0)
00069 {
00070
00071
00072 for (int i = 0; i<MAX_QNUM; ++i) {
00073 q_[i] = 0;
00074 wrrTemp_[i] = 0.0;
00075 queueWeight_[i]= 1 / MAX_QNUM;
00076 }
00077
00078 bind("spread_bytes_", &spread_bytes_);
00079 routerId_ = next_router++;
00080
00081
00082
00083
00084
00085
00086
00087 Tcl& tcl = Tcl::instance();
00088 tcl.evalf("Queue/XCP set tcp_xcp_on_");
00089 if (strcmp(tcl.result(), "0") != 0)
00090 tcp_xcp_on_ = true;
00091 else
00092 tcp_xcp_on_ = false;
00093
00094 }
00095
00096 void XCPWrapQ::setVirtualQueues() {
00097 qToDq_ = 0;
00098 queueWeight_[XCPQ] = 0.5;
00099 queueWeight_[TCPQ] = 0.5;
00100 queueWeight_[OTHERQ] = 0;
00101
00102
00103 if (xcpq_) {
00104 xcpq_->routerId(this, routerId_);
00105 xcpq_->spread_bytes(spread_bytes_);
00106 xcpq_->setupTimers();
00107 }
00108 }
00109
00110
00111 int XCPWrapQ::command(int argc, const char*const* argv)
00112 {
00113 Tcl& tcl = Tcl::instance();
00114
00115 if (argc == 2) {
00116
00117 if (strcmp(argv[1], "queue-read-drops") == 0) {
00118 if (xcpq_) {
00119 tcl.resultf("%g", xcpq_->totalDrops());
00120 return (TCL_OK);
00121 } else {
00122 tcl.add_errorf("XCP queue is not set\n");
00123 return TCL_ERROR;
00124 }
00125 }
00126
00127 }
00128
00129 if (argc == 3) {
00130 if (strcmp(argv[1], "set-xcpQ") == 0) {
00131
00132 q_[XCPQ] = xcpq_ = (XCPQueue *)(TclObject::lookup(argv[2]));
00133
00134 if (xcpq_ == NULL) {
00135 tcl.add_errorf("Wrong xcp virtual queue %s\n", argv[2]);
00136 return TCL_ERROR;
00137 }
00138 setVirtualQueues();
00139 return TCL_OK;
00140 }
00141 else if (strcmp(argv[1], "set-tcpQ") == 0) {
00142
00143 q_[TCPQ] = (XCPQueue *)(TclObject::lookup(argv[2]));
00144
00145 if (q_[TCPQ] == NULL) {
00146 tcl.add_errorf("Wrong tcp virtual queue %s\n", argv[2]);
00147 return TCL_ERROR;
00148 }
00149 return TCL_OK;
00150 }
00151 else if (strcmp(argv[1], "set-otherQ") == 0) {
00152
00153 q_[OTHERQ] = (XCPQueue *)(TclObject::lookup(argv[2]));
00154
00155 if (q_[OTHERQ] == NULL) {
00156 tcl.add_errorf("Wrong 'other' virtual queue %s\n", argv[2]);
00157 return TCL_ERROR;
00158 }
00159 return TCL_OK;
00160 }
00161 else if (strcmp(argv[1], "set-link-capacity") == 0) {
00162 double link_capacity_bitps = strtod(argv[2], 0);
00163 if (link_capacity_bitps < 0.0) {
00164 printf("Error: BW < 0");
00165 exit(1);
00166 }
00167 if (tcp_xcp_on_)
00168 link_capacity_bitps = link_capacity_bitps * queueWeight_[XCPQ];
00169
00170 xcpq_->setBW(link_capacity_bitps/8.0);
00171 return TCL_OK;
00172 }
00173
00174 else if (strcmp(argv[1], "drop-target") == 0) {
00175 drop_ = (NsObject*)TclObject::lookup(argv[2]);
00176 if (drop_ == 0) {
00177 tcl.resultf("no object %s", argv[2]);
00178 return (TCL_ERROR);
00179 }
00180 for (int n=0; n < MAX_QNUM; n++)
00181 if (q_[n])
00182 q_[n]->setDropTarget(drop_);
00183
00184 return (TCL_OK);
00185 }
00186
00187 else if (strcmp(argv[1], "attach") == 0) {
00188 int mode;
00189 const char* id = argv[2];
00190 Tcl_Channel queue_trace_file = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
00191 if (queue_trace_file == 0) {
00192 tcl.resultf("queue.cc: trace-drops: can't attach %s for writing", id);
00193 return (TCL_ERROR);
00194 }
00195 xcpq_->setChannel(queue_trace_file);
00196
00197
00198
00199
00200
00201 return (TCL_OK);
00202 }
00203
00204 else if (strcmp(argv[1], "queue-sample-everyrtt") == 0) {
00205 double e_rtt = strtod(argv[2],0);
00206
00207 xcpq_->setEffectiveRtt(e_rtt);
00208 return (TCL_OK);
00209 }
00210
00211 else if (strcmp(argv[1], "num-mice") == 0) {
00212 int nm = atoi(argv[2]);
00213
00214 xcpq_->setNumMice(nm);
00215 return (TCL_OK);
00216 }
00217 }
00218 return (Queue::command(argc, argv));
00219 }
00220
00221
00222 void XCPWrapQ::recv(Packet* p, Handler* h)
00223 {
00224 mark(p);
00225 Queue::recv(p, h);
00226 }
00227
00228 void XCPWrapQ::addQueueWeights(int queueNum, int weight) {
00229 if (queueNum < MAX_QNUM)
00230 queueWeight_[queueNum] = weight;
00231 else {
00232 fprintf(stderr, "Queue number is out of range.\n");
00233 }
00234 }
00235
00236 int XCPWrapQ::queueToDeque()
00237 {
00238 int i = 0;
00239
00240 if (wrrTemp_[qToDq_] <= 0) {
00241 qToDq_ = ((qToDq_ + 1) % MAX_QNUM);
00242 wrrTemp_[qToDq_] = queueWeight_[qToDq_] - 1;
00243 } else {
00244 wrrTemp_[qToDq_] = wrrTemp_[qToDq_] -1;
00245 }
00246 while ((i < MAX_QNUM) && (q_[qToDq_]->length() == 0)) {
00247 wrrTemp_[qToDq_] = 0;
00248 qToDq_ = ((qToDq_ + 1) % MAX_QNUM);
00249 wrrTemp_[qToDq_] = queueWeight_[qToDq_] - 1;
00250 i++;
00251 }
00252 return (qToDq_);
00253 }
00254
00255 int XCPWrapQ::queueToEnque(int cp)
00256 {
00257 int n;
00258 switch (cp) {
00259 case CP_XCP:
00260 return (n = XCPQ);
00261
00262 case CP_TCP:
00263 return (n = TCPQ);
00264
00265 case CP_OTHER:
00266 return (n = OTHERQ);
00267
00268 default:
00269 fprintf(stderr, "Unknown codepoint %d\n", cp);
00270 exit(1);
00271 }
00272 }
00273
00274
00275
00276 int XCPWrapQ::getCodePt(Packet *p) {
00277
00278 hdr_ip* iph = hdr_ip::access(p);
00279 return(iph->prio());
00280 }
00281
00282 Packet* XCPWrapQ::deque()
00283 {
00284 Packet *p = NULL;
00285 int n = queueToDeque();
00286
00287
00288 p = q_[n]->deque();
00289 return(p);
00290 }
00291
00292
00293 void XCPWrapQ::enque(Packet* pkt)
00294 {
00295 int codePt;
00296
00297 codePt = getCodePt(pkt);
00298 int n = queueToEnque(codePt);
00299
00300 q_[n]->enque(pkt);
00301 }
00302
00303
00304 void XCPWrapQ::mark(Packet *p) {
00305
00306 int codePt;
00307 hdr_cmn* cmnh = hdr_cmn::access(p);
00308 hdr_xcp *xh = hdr_xcp::access(p);
00309 hdr_ip *iph = hdr_ip::access(p);
00310
00311 if ((codePt = iph->prio_) > 0)
00312 return;
00313
00314 else {
00315 if (xh->xcp_enabled_ != hdr_xcp::XCP_DISABLED)
00316 codePt = CP_XCP;
00317 else
00318 if (cmnh->ptype() == PT_TCP || cmnh->ptype() == PT_ACK)
00319 codePt = CP_TCP;
00320 else
00321 codePt = CP_OTHER;
00322
00323 iph->prio_ = codePt;
00324 }
00325 }