xcp.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:7k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
  2.  *
  3.  * Copyright (C) 2004 by USC/ISI
  4.  *               2002 by Dina Katabi
  5.  *
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation, advertising
  11.  * materials, and other materials related to such distribution and use
  12.  * acknowledge that the software was developed by the University of
  13.  * Southern California, Information Sciences Institute.  The name of the
  14.  * University may not be used to endorse or promote products derived from
  15.  * this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  */
  22. #ifndef lint
  23. static const char rcsid[] =
  24. "@(#) $Header: /cvsroot/nsnam/ns-2/xcp/xcp.cc,v 1.11 2006/05/30 20:30:30 pradkin Exp $";
  25. #endif
  26. #include "xcp.h"
  27. #include "red.h"
  28. static unsigned int next_router = 0;
  29. static class XCPClass : public TclClass {
  30. public:
  31. XCPClass() : TclClass("Queue/XCP") {}
  32. TclObject* create(int, const char*const*) {
  33. return (new XCPWrapQ);
  34. }
  35. } class_xcp_queue;
  36. XCPWrapQ::XCPWrapQ() : xcpq_(0), qToDq_(0),  tcp_xcp_on_(0)
  37. {
  38. // If needed wrrTemp and queueWeight will be reset to more useful
  39. // values in XCPWrapQ::setVirtualQueues
  40. for (int i = 0; i<MAX_QNUM; ++i) {
  41. q_[i] = 0;
  42. wrrTemp_[i] = 0.0;
  43. queueWeight_[i]=  1 / MAX_QNUM;
  44. }
  45. routerId_ = next_router++;
  46. // XXX Temporary fix XXX
  47. // set flag to 1 when supporting both tcp and xcp flows; 
  48. // temporary fix for allocating link BW between xcp and 
  49. // tcp queues until dynamic queue weights come into effect. 
  50. // This fix should then go away.
  51. Tcl& tcl = Tcl::instance();
  52. tcl.evalf("Queue/XCP set tcp_xcp_on_");
  53. if (strcmp(tcl.result(), "0") != 0)  
  54. tcp_xcp_on_ = true;              //tcp_xcp_on flag is set
  55. else
  56. tcp_xcp_on_ = false; // Not strictly required with
  57. // the initializer above.
  58. }
  59.  
  60. void XCPWrapQ::setVirtualQueues() {
  61. qToDq_ = 0;
  62. queueWeight_[XCPQ] = 0.5;
  63. queueWeight_[TCPQ] = 0.5;
  64. queueWeight_[OTHERQ] = 0;
  65.   
  66. // setup timers for xcp queue only
  67. if (xcpq_) {
  68. xcpq_->routerId(this, routerId_);
  69. xcpq_->setupTimers();
  70. }
  71. }
  72. int XCPWrapQ::command(int argc, const char*const* argv)
  73. {
  74. Tcl& tcl = Tcl::instance();
  75. if (argc == 2) {
  76. // for Dina's parking-lot experiment data
  77. if (strcmp(argv[1], "queue-read-drops") == 0) {
  78. if (xcpq_) {
  79. tcl.resultf("%g", xcpq_->totalDrops());
  80. return (TCL_OK);
  81. } else {
  82. tcl.add_errorf("XCP queue is not setn");
  83. return TCL_ERROR;
  84. }
  85. }
  86. if (argc == 3) {
  87. if (strcmp(argv[1], "set-xcpQ") == 0) {
  88. q_[XCPQ] = xcpq_ = (XCPQueue *)(TclObject::lookup(argv[2]));
  89. if (xcpq_ == NULL) {
  90. tcl.add_errorf("Wrong xcp virtual queue %sn", argv[2]);
  91. return TCL_ERROR;
  92. }
  93. setVirtualQueues();
  94. return TCL_OK;
  95. }
  96. else if (strcmp(argv[1], "set-tcpQ") == 0) {
  97. q_[TCPQ] = (XCPQueue *)(TclObject::lookup(argv[2]));
  98. if (q_[TCPQ] == NULL) {
  99. tcl.add_errorf("Wrong tcp virtual queue %sn", argv[2]);
  100. return TCL_ERROR;
  101. }
  102. return TCL_OK;
  103. }
  104. else if (strcmp(argv[1], "set-otherQ") == 0) {
  105. q_[OTHERQ] = (XCPQueue *)(TclObject::lookup(argv[2]));
  106. if (q_[OTHERQ] == NULL) {
  107. tcl.add_errorf("Wrong 'other' virtual queue %sn", argv[2]);
  108. return TCL_ERROR;
  109. }
  110. return TCL_OK;
  111. }
  112. else if (strcmp(argv[1], "set-link-capacity") == 0) {
  113. double link_capacity_bitps = strtod(argv[2], 0);
  114. if (link_capacity_bitps < 0.0) {
  115. printf("Error: BW < 0"); 
  116. exit(1);
  117. }
  118. if (tcp_xcp_on_) // divide between xcp and tcp queues
  119. link_capacity_bitps = link_capacity_bitps * queueWeight_[XCPQ];
  120. xcpq_->setBW(link_capacity_bitps/8.0); 
  121. return TCL_OK;
  122. }
  123.     
  124. else if (strcmp(argv[1], "drop-target") == 0) {
  125. drop_ = (NsObject*)TclObject::lookup(argv[2]);
  126. if (drop_ == 0) {
  127. tcl.resultf("no object %s", argv[2]);
  128. return (TCL_ERROR);
  129. }
  130. for (int n=0; n < MAX_QNUM; n++)
  131. if (q_[n])
  132. q_[n]->setDropTarget(drop_);
  133. return (TCL_OK);
  134. }
  135. else if (strcmp(argv[1], "attach") == 0) {
  136. int mode;
  137. const char* id = argv[2];
  138. Tcl_Channel queue_trace_file = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);
  139. if (queue_trace_file == 0) {
  140. tcl.resultf("queue.cc: trace-drops: can't attach %s for writing", id);
  141. return (TCL_ERROR);
  142. }
  143. xcpq_->setChannel(queue_trace_file); //XXX virtual queues had
  144.      //better be attached from
  145.      //tcl in a similar manner
  146.      //(this way xcpq_ is
  147.      //singled out).
  148. return (TCL_OK);
  149. }
  150.     
  151. else if (strcmp(argv[1], "queue-sample-everyrtt") == 0) {
  152. double e_rtt = strtod(argv[2],0);
  153. //printf(" timer at %f n",e_rtt);
  154. xcpq_->setEffectiveRtt(e_rtt);
  155. return (TCL_OK);
  156. }
  157.     
  158. else if (strcmp(argv[1], "num-mice") == 0) {
  159. int nm = atoi(argv[2]);
  160. xcpq_->setNumMice(nm);
  161. return (TCL_OK);
  162. }
  163. }
  164. return (Queue::command(argc, argv));
  165. }
  166. void XCPWrapQ::recv(Packet* p, Handler* h)
  167. {
  168. mark(p);
  169. Queue::recv(p, h);
  170. }
  171. void XCPWrapQ::addQueueWeights(int queueNum, int weight) {
  172. if (queueNum < MAX_QNUM)
  173. queueWeight_[queueNum] = weight;
  174. else {
  175. fprintf(stderr, "Queue number is out of range.n");
  176. }
  177. }
  178. int XCPWrapQ::queueToDeque()
  179. {
  180. int i = 0;
  181.   
  182. if (wrrTemp_[qToDq_] <= 0) {
  183. qToDq_ = ((qToDq_ + 1) % MAX_QNUM);
  184. wrrTemp_[qToDq_] = queueWeight_[qToDq_] - 1;
  185. } else {
  186. wrrTemp_[qToDq_] = wrrTemp_[qToDq_] -1;
  187. }
  188. while ((i < MAX_QNUM) && (q_[qToDq_]->length() == 0)) {
  189. wrrTemp_[qToDq_] = 0;
  190. qToDq_ = ((qToDq_ + 1) % MAX_QNUM);
  191. wrrTemp_[qToDq_] = queueWeight_[qToDq_] - 1;
  192. i++;
  193. }
  194. return (qToDq_);
  195. }
  196. int XCPWrapQ::queueToEnque(int cp)
  197. {
  198. int n;
  199. switch (cp) {
  200. case CP_XCP:
  201. return (n = XCPQ);
  202.     
  203. case CP_TCP:
  204. return (n = TCPQ);
  205.     
  206. case CP_OTHER:
  207. return (n = OTHERQ);
  208. default:
  209. fprintf(stderr, "Unknown codepoint %dn", cp);
  210. exit(1);
  211. }
  212. }
  213. // Extracts the code point marking from packet header.
  214. int XCPWrapQ::getCodePt(Packet *p) {
  215. hdr_ip* iph = hdr_ip::access(p);
  216. return(iph->prio());
  217. }
  218. Packet* XCPWrapQ::deque()
  219. {
  220. Packet *p = NULL;
  221. int n = queueToDeque();
  222. // Deque a packet from the underlying queue:
  223. p = q_[n]->deque();
  224. return(p);
  225. }
  226. void XCPWrapQ::enque(Packet* pkt)
  227. {
  228. int codePt;
  229.   
  230. codePt = getCodePt(pkt);
  231. int n = queueToEnque(codePt);
  232.   
  233. q_[n]->enque(pkt);
  234. }
  235. void XCPWrapQ::mark(Packet *p) {
  236.   
  237. int codePt;
  238. hdr_cmn* cmnh = hdr_cmn::access(p);
  239. hdr_xcp *xh = hdr_xcp::access(p);
  240. hdr_ip *iph = hdr_ip::access(p);
  241. if ((codePt = iph->prio_) > 0)
  242. return;
  243. else {
  244. if (xh->xcp_enabled_ != hdr_xcp::XCP_DISABLED)
  245. codePt = CP_XCP;
  246. else 
  247. if (cmnh->ptype() == PT_TCP || cmnh->ptype() == PT_ACK)
  248. codePt = CP_TCP;
  249. else // for others
  250. codePt = CP_OTHER;
  251.     
  252. iph->prio_ = codePt;
  253. }
  254. }