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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *  This product includes software developed by the MASH Research
  17.  *  Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. #ifndef lint
  35. static const char rcsid[] =
  36. "@(#) $Header: /cvsroot/nsnam/ns-2/queue/fq.cc,v 1.12 2005/08/22 05:08:34 tomh Exp $ (ANS)";
  37. #endif
  38. #include "config.h"
  39. #include <stdlib.h>
  40. #include <float.h>
  41. #include "queue.h"
  42. /*XXX*/
  43. #define MAXFLOW 32
  44. class FQ : public Queue {
  45. public: 
  46. FQ();
  47. virtual int command(int argc, const char*const* argv);
  48. Packet *deque(void);
  49. void enque(Packet *pkt);
  50. void recv(Packet* p, Handler* h);
  51. protected:
  52. int update();
  53. struct flowState {
  54. Queue* q_;
  55. Packet* hol_; /* head-of-line packet for each flow */
  56. double finishTime_; /* FQ finish time for hol packet */
  57. double delta_;
  58. Handler* handler_;
  59. } fs_[MAXFLOW];
  60. inline double finish(const flowState& fs, int nactive)
  61. {
  62. return (fs.finishTime_ + fs.delta_ * nactive);
  63. }
  64. int maxflow_;
  65. double secsPerByte_;
  66. };
  67. static class FQClass : public TclClass {
  68. public:
  69. FQClass() : TclClass("Queue/FQ") {}
  70. TclObject* create(int, const char*const*) {
  71. return (new FQ);
  72. }
  73. } class_fq;
  74. FQ::FQ()
  75. {
  76. for (int i = 0; i < MAXFLOW; ++i) {
  77. fs_[i].q_ = 0;
  78. fs_[i].hol_ = 0;
  79. fs_[i].finishTime_ = 0.;
  80. }
  81. maxflow_ = -1;
  82. secsPerByte_ = 0.;
  83. bind("secsPerByte_", &secsPerByte_);
  84. }
  85. int FQ::command(int argc, const char*const* argv)
  86. {
  87. if (argc == 4) {
  88. if (strcmp(argv[1], "install") == 0) {
  89. int flowID = atoi(argv[2]);
  90. fs_[flowID].q_ = (Queue*)TclObject::lookup(argv[3]);
  91. if (flowID > maxflow_)
  92. maxflow_ = flowID;
  93. /*XXX*/
  94. if (flowID >= MAXFLOW)
  95. abort();
  96. return (TCL_OK);
  97. }
  98. }
  99. return (Queue::command(argc, argv));
  100. }
  101. /*XXX this is quite inefficient.*/
  102. int FQ::update()
  103. {
  104. int nactive = 0;
  105. for (int i = 0; i <= maxflow_; ++i) {
  106. Queue* q = fs_[i].q_;
  107. if (q != 0) {
  108. if (fs_[i].hol_ == 0) {
  109. Packet* p = q->deque();
  110. if (p != 0) {
  111. fs_[i].hol_ = p;
  112. ++nactive;
  113. }
  114. } else
  115. ++nactive;
  116. }
  117. }
  118. return (nactive);
  119. }
  120. Packet* FQ::deque()
  121. {
  122. int nactive = update();
  123. int target = -1;
  124. double best = DBL_MAX;
  125. for (int i = 0; i <= maxflow_; ++i) {
  126. if (fs_[i].hol_ != 0) {
  127. if (target < 0) { 
  128. target = i;
  129. best = finish(fs_[i], nactive);
  130. } else {
  131. double F = finish(fs_[i], nactive);
  132. if (F < best) {
  133. target = i;
  134. best = F;
  135. }
  136. }
  137. }
  138. }
  139. if (target >= 0) {
  140. Packet* p = fs_[target].hol_;
  141. fs_[target].hol_ = 0;
  142. fs_[target].finishTime_ = best;
  143. /* let this upstream queue resume */
  144. Handler* h = fs_[target].handler_;
  145. /*XXX null event okay because queue doesn't use it*/
  146. h->handle(0);
  147. return (p);
  148. }
  149. return (0);
  150. }
  151. /*
  152.  * Called when one of our queues is unblocked by us in FQ::deque
  153.  * (or gets its first packet).
  154.  */
  155. void FQ::recv(Packet* p, Handler* handler)
  156. {
  157. hdr_ip* h = hdr_ip::access(p);
  158. int flowid = h->flowid();
  159. /* shouldn't be called when head-of-line is pending */
  160. if (flowid >= MAXFLOW || fs_[flowid].hol_ != 0)
  161. abort();
  162. /*
  163.  * Put this packet at the head-of-line for its queue
  164.  * and set up scheduling state according to the
  165.  * standard fair-queueing "finish time" equation.
  166.  */
  167. fs_[flowid].hol_ = p;
  168. double now = Scheduler::instance().clock();
  169. if (now > fs_[flowid].finishTime_)
  170. fs_[flowid].finishTime_ = now;
  171. fs_[flowid].handler_ = handler;
  172. int size = hdr_cmn::access(p)->size();
  173. fs_[flowid].delta_ = size * secsPerByte_;
  174. if (!blocked_) {
  175. /*
  176.  * We're not blocked.  Get a packet and send it on.
  177.  * We perform an extra check because the queue
  178.  * might drop the packet even if it was
  179.  * previously empty!  (e.g., RED can do this.)
  180.  */
  181. p = deque();
  182. if (p != 0) {
  183. blocked_ = 1;
  184. target_->recv(p, &qh_);
  185. }
  186. }
  187. }
  188. void FQ::enque(Packet*)
  189. {
  190. /* should never be called because we override recv */
  191. abort();
  192. }