xcp.cc

Go to the documentation of this file.
00001 // -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
00002 
00003 /*
00004  * Copyright (C) 2004 by the University of Southern California
00005  * Copyright (C) 2004 by USC/ISI
00006  *               2002 by Dina Katabi
00007  * $Id: xcp.cc,v 1.10 2005/08/25 18:58:14 johnh Exp $
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License,
00011  * version 2, as published by the Free Software Foundation.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License along
00019  * with this program; if not, write to the Free Software Foundation, Inc.,
00020  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00021  *
00022  *
00023  * The copyright of this module includes the following
00024  * linking-with-specific-other-licenses addition:
00025  *
00026  * In addition, as a special exception, the copyright holders of
00027  * this module give you permission to combine (via static or
00028  * dynamic linking) this module with free software programs or
00029  * libraries that are released under the GNU LGPL and with code
00030  * included in the standard release of ns-2 under the Apache 2.0
00031  * license or under otherwise-compatible licenses with advertising
00032  * requirements (or modified versions of such code, with unchanged
00033  * license).  You may copy and distribute such a system following the
00034  * terms of the GNU GPL for this module and the licenses of the
00035  * other code concerned, provided that you include the source code of
00036  * that other code when and as the GNU GPL requires distribution of
00037  * source code.
00038  *
00039  * Note that people who make modified versions of this module
00040  * are not obligated to grant this special exception for their
00041  * modified versions; it is their choice whether to do so.  The GNU
00042  * General Public License gives permission to release a modified
00043  * version without this exception; this exception also makes it
00044  * possible to release a modified version which carries forward this
00045  * exception.
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     // If needed wrrTemp and queueWeight will be reset to more useful
00071     // values in XCPWrapQ::setVirtualQueues
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     // XXX Temporary fix XXX
00082     // set flag to 1 when supporting both tcp and xcp flows; 
00083     // temporary fix for allocating link BW between xcp and 
00084     // tcp queues until dynamic queue weights come into effect. 
00085     // This fix should then go away.
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;              //tcp_xcp_on flag is set
00091     else
00092         tcp_xcp_on_ = false;        // Not strictly required with
00093                         // the initializer above.
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     // setup timers for xcp queue only
00103     if (xcpq_) {
00104         xcpq_->routerId(this, routerId_);
00105         xcpq_->spread_bytes(spread_bytes_);// this order is important as Te_ depends on spread_bytes_ flag
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         // for Dina's parking-lot experiment data
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_) // divide between xcp and tcp queues
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); //XXX virtual queues had
00196                                  //better be attached from
00197                                  //tcl in a similar manner
00198                                  //(this way xcpq_ is
00199                                  //singled out).
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             //printf(" timer at %f \n",e_rtt);
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 // Extracts the code point marking from packet header.
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 // Deque a packet from the underlying queue:
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 // for others
00321                 codePt = CP_OTHER;
00322     
00323         iph->prio_ = codePt;
00324     }
00325 }

Generated on Tue Mar 6 16:47:53 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6