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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
  2.  *
  3.  * Copyright (c) Xerox Corporation 1997. All rights reserved.
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18.  *
  19.  * Linking this file statically or dynamically with other modules is making
  20.  * a combined work based on this file.  Thus, the terms and conditions of
  21.  * the GNU General Public License cover the whole combination.
  22.  *
  23.  * In addition, as a special exception, the copyright holders of this file
  24.  * give you permission to combine this file with free software programs or
  25.  * libraries that are released under the GNU LGPL and with code included in
  26.  * the standard release of ns-2 under the Apache 2.0 license or under
  27.  * otherwise-compatible licenses with advertising requirements (or modified
  28.  * versions of such code, with unchanged license).  You may copy and
  29.  * distribute such a system following the terms of the GNU GPL for this
  30.  * file and the licenses of the other code concerned, provided that you
  31.  * include the source code of that other code when and as the GNU GPL
  32.  * requires distribution of source code.
  33.  *
  34.  * Note that people who make modified versions of this file are not
  35.  * obligated to grant this special exception for their modified versions;
  36.  * it is their choice whether to do so.  The GNU General Public License
  37.  * gives permission to release a modified version without this exception;
  38.  * this exception also makes it possible to release a modified version
  39.  * which carries forward this exception.
  40.  *
  41.  * This file contributed by Sandeep Bajaj <bajaj@parc.xerox.com>, Mar 1997.
  42.  *
  43.  * $Header: /cvsroot/nsnam/ns-2/queue/drr.cc,v 1.11 2005/08/26 05:05:29 tomh Exp $
  44.  */
  45. #ifndef lint
  46. static const char rcsid[] =
  47.     "@(#) $Header: /cvsroot/nsnam/ns-2/queue/drr.cc,v 1.11 2005/08/26 05:05:29 tomh Exp $ (Xerox)";
  48. #endif
  49. #include "config.h"   // for string.h
  50. #include <stdlib.h>
  51. #include "queue.h"
  52. class PacketDRR;
  53. class DRR;
  54. class PacketDRR : public PacketQueue {
  55. PacketDRR(): pkts(0),src(-1),bcount(0),prev(0),next(0),deficitCounter(0),turn(0) {}
  56. friend class DRR;
  57. protected :
  58. int pkts;
  59. int src;    //to detect collisions keep track of actual src address
  60. int bcount; //count of bytes in each flow to find the max flow;
  61. PacketDRR *prev;
  62. PacketDRR *next;
  63. int deficitCounter; 
  64. int turn;
  65. inline PacketDRR * activate(PacketDRR *head) {
  66. if (head) {
  67. this->prev = head->prev;
  68. this->next = head;
  69. head->prev->next = this;
  70. head->prev = this;
  71. return head;
  72. }
  73. this->prev = this;
  74. this->next = this;
  75. return this;
  76. }
  77. inline PacketDRR * idle(PacketDRR *head) {
  78. if (head == this) {
  79. if (this->next == this)
  80. return 0;
  81. this->next->prev = this->prev;
  82. this->prev->next = this->next;
  83. return this->next;
  84. }
  85. this->next->prev = this->prev;
  86. this->prev->next = this->next;
  87. return head;
  88. }
  89. };
  90. class DRR : public Queue {
  91. public :
  92. DRR();
  93. virtual int command(int argc, const char*const* argv);
  94. Packet *deque(void);
  95. void enque(Packet *pkt);
  96. int hash(Packet *pkt);
  97. void clear();
  98. protected:
  99. int buckets_ ; //total number of flows allowed
  100. int blimit_;    //total number of bytes allowed across all flows
  101. int quantum_;  //total number of bytes that a flow can send
  102. int mask_;     /*if set hashes on just the node address otherwise on 
  103.  node+port address*/
  104. int bytecnt ; //cumulative sum of bytes across all flows
  105. int pktcnt ; // cumulative sum of packets across all flows
  106. int flwcnt ; //total number of active flows
  107. PacketDRR *curr; //current active flow
  108. PacketDRR *drr ; //pointer to the entire drr struct
  109. inline PacketDRR *getMaxflow (PacketDRR *curr) { //returns flow with max pkts
  110. int i;
  111. PacketDRR *tmp;
  112. PacketDRR *maxflow=curr;
  113. for (i=0,tmp=curr; i < flwcnt; i++,tmp=tmp->next) {
  114. if (maxflow->bcount < tmp->bcount)
  115. maxflow=tmp;
  116. }
  117. return maxflow;
  118. }
  119.   
  120. public:
  121. //returns queuelength in packets
  122. inline int length () {
  123. return pktcnt;
  124. }
  125. //returns queuelength in bytes
  126. inline int blength () {
  127. return bytecnt;
  128. }
  129. };
  130. static class DRRClass : public TclClass {
  131. public:
  132. DRRClass() : TclClass("Queue/DRR") {}
  133. TclObject* create(int, const char*const*) {
  134. return (new DRR);
  135. }
  136. } class_drr;
  137. DRR::DRR()
  138. {
  139. buckets_=16;
  140. quantum_=250;
  141. drr=0;
  142. curr=0;
  143. flwcnt=0;
  144. bytecnt=0;
  145. pktcnt=0;
  146. mask_=0;
  147. bind("buckets_",&buckets_);
  148. bind("blimit_",&blimit_);
  149. bind("quantum_",&quantum_);
  150. bind("mask_",&mask_);
  151. }
  152.  
  153. void DRR::enque(Packet* pkt)
  154. {
  155. PacketDRR *q,*remq;
  156. int which;
  157. hdr_cmn *ch= hdr_cmn::access(pkt);
  158. hdr_ip *iph = hdr_ip::access(pkt);
  159. if (!drr)
  160. drr=new PacketDRR[buckets_];
  161. which= hash(pkt) % buckets_;
  162. q=&drr[which];
  163. /*detect collisions here */
  164. int compare=(!mask_ ? ((int)iph->saddr()) : ((int)iph->saddr()&0xfff0));
  165. if (q->src ==-1)
  166. q->src=compare;
  167. else
  168. if (q->src != compare)
  169. fprintf(stderr,"Collisions between %d and %d src addressesn",q->src,(int)iph->saddr());      
  170. q->enque(pkt);
  171. ++q->pkts;
  172. ++pktcnt;
  173. q->bcount += ch->size();
  174. bytecnt +=ch->size();
  175. if (q->pkts==1)
  176. {
  177. curr = q->activate(curr);
  178. q->deficitCounter=0;
  179. ++flwcnt;
  180. }
  181. while (bytecnt > blimit_) {
  182. Packet *p;
  183. hdr_cmn *remch;
  184. hdr_ip *remiph;
  185. remq=getMaxflow(curr);
  186. p=remq->deque();
  187. remch=hdr_cmn::access(p);
  188. remiph=hdr_ip::access(p);
  189. remq->bcount -= remch->size();
  190. bytecnt -= remch->size();
  191. drop(p);
  192. --remq->pkts;
  193. --pktcnt;
  194. if (remq->pkts==0) {
  195. curr=remq->idle(curr);
  196. --flwcnt;
  197. }
  198. }
  199. }
  200. Packet *DRR::deque(void) 
  201. {
  202. hdr_cmn *ch;
  203. hdr_ip *iph;
  204. Packet *pkt=0;
  205. if (bytecnt==0) {
  206. //fprintf (stderr,"No active flown");
  207. return(0);
  208. }
  209.   
  210. while (!pkt) {
  211. if (!curr->turn) {
  212. curr->deficitCounter+=quantum_;
  213. curr->turn=1;
  214. }
  215. pkt=curr->lookup(0);  
  216. ch=hdr_cmn::access(pkt);
  217. iph=hdr_ip::access(pkt);
  218. if (curr->deficitCounter >= ch->size()) {
  219. curr->deficitCounter -= ch->size();
  220. pkt=curr->deque();
  221. curr->bcount -= ch->size();
  222. --curr->pkts;
  223. --pktcnt;
  224. bytecnt -= ch->size();
  225. if (curr->pkts == 0) {
  226. curr->turn=0;
  227. --flwcnt;
  228. curr->deficitCounter=0;
  229. curr=curr->idle(curr);
  230. }
  231. return pkt;
  232. }
  233. else {
  234. curr->turn=0;
  235. curr=curr->next;
  236. pkt=0;
  237. }
  238. }
  239. return 0;    // not reached
  240. }
  241. void DRR::clear()
  242. {
  243. PacketDRR *q =drr;
  244. int i = buckets_;
  245. if (!q)
  246. return;
  247. while (i--) {
  248. if (q->pkts) {
  249. fprintf(stderr, "Changing non-empty bucket from drrn");
  250. exit(1);
  251. }
  252. ++q;
  253. }
  254. delete[](drr);
  255. drr = 0;
  256. }
  257. /*
  258.  *Allows one to change blimit_ and bucket_ for a particular drrQ :
  259.  *
  260.  *
  261.  */
  262. int DRR::command(int argc, const char*const* argv)
  263. {
  264. if (argc==3) {
  265. if (strcmp(argv[1], "blimit") == 0) {
  266. blimit_ = atoi(argv[2]);
  267. if (bytecnt > blimit_)
  268. {
  269. fprintf (stderr,"More packets in buffer than the new limit");
  270. exit (1);
  271. }
  272. return (TCL_OK);
  273. }
  274. if (strcmp(argv[1], "buckets") == 0) {
  275. clear();
  276. buckets_ = atoi(argv[2]);
  277. return (TCL_OK);
  278. }
  279. if (strcmp(argv[1],"quantum") == 0) {
  280. quantum_ = atoi(argv[2]);
  281. return (TCL_OK);
  282. }
  283. if (strcmp(argv[1],"mask")==0) {
  284. mask_= atoi(argv[2]);
  285. return (TCL_OK);
  286. }
  287. }
  288. return (Queue::command(argc, argv));
  289. }
  290. int DRR::hash(Packet* pkt)
  291. {
  292. hdr_ip *iph=hdr_ip::access(pkt);
  293. int i;
  294. if (mask_)
  295. i = (int)iph->saddr() & (0xfff0);
  296. else
  297. i = (int)iph->saddr();
  298. return ((i + (i >> 8) + ~(i>>4)) % ((2<<23)-1))+1; // modulo a large prime
  299. }