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 #ifndef lint
00036 static const char rcsid[] =
00037 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/fq.cc,v 1.12 2005/08/22 05:08:34 tomh Exp $ (ANS)";
00038 #endif
00039
00040 #include "config.h"
00041 #include <stdlib.h>
00042 #include <float.h>
00043 #include "queue.h"
00044
00045
00046 #define MAXFLOW 32
00047
00048 class FQ : public Queue {
00049 public:
00050 FQ();
00051 virtual int command(int argc, const char*const* argv);
00052 Packet *deque(void);
00053 void enque(Packet *pkt);
00054 void recv(Packet* p, Handler* h);
00055 protected:
00056 int update();
00057 struct flowState {
00058 Queue* q_;
00059 Packet* hol_;
00060 double finishTime_;
00061 double delta_;
00062 Handler* handler_;
00063 } fs_[MAXFLOW];
00064 inline double finish(const flowState& fs, int nactive)
00065 {
00066 return (fs.finishTime_ + fs.delta_ * nactive);
00067 }
00068 int maxflow_;
00069 double secsPerByte_;
00070 };
00071
00072 static class FQClass : public TclClass {
00073 public:
00074 FQClass() : TclClass("Queue/FQ") {}
00075 TclObject* create(int, const char*const*) {
00076 return (new FQ);
00077 }
00078 } class_fq;
00079
00080 FQ::FQ()
00081 {
00082 for (int i = 0; i < MAXFLOW; ++i) {
00083 fs_[i].q_ = 0;
00084 fs_[i].hol_ = 0;
00085 fs_[i].finishTime_ = 0.;
00086 }
00087 maxflow_ = -1;
00088 secsPerByte_ = 0.;
00089 bind("secsPerByte_", &secsPerByte_);
00090 }
00091
00092 int FQ::command(int argc, const char*const* argv)
00093 {
00094 if (argc == 4) {
00095 if (strcmp(argv[1], "install") == 0) {
00096 int flowID = atoi(argv[2]);
00097 fs_[flowID].q_ = (Queue*)TclObject::lookup(argv[3]);
00098 if (flowID > maxflow_)
00099 maxflow_ = flowID;
00100
00101 if (flowID >= MAXFLOW)
00102 abort();
00103 return (TCL_OK);
00104 }
00105 }
00106 return (Queue::command(argc, argv));
00107 }
00108
00109
00110 int FQ::update()
00111 {
00112 int nactive = 0;
00113 for (int i = 0; i <= maxflow_; ++i) {
00114 Queue* q = fs_[i].q_;
00115 if (q != 0) {
00116 if (fs_[i].hol_ == 0) {
00117 Packet* p = q->deque();
00118 if (p != 0) {
00119 fs_[i].hol_ = p;
00120 ++nactive;
00121 }
00122 } else
00123 ++nactive;
00124 }
00125 }
00126 return (nactive);
00127 }
00128
00129 Packet* FQ::deque()
00130
00131 {
00132 int nactive = update();
00133 int target = -1;
00134 double best = DBL_MAX;
00135 for (int i = 0; i <= maxflow_; ++i) {
00136 if (fs_[i].hol_ != 0) {
00137 if (target < 0) {
00138 target = i;
00139 best = finish(fs_[i], nactive);
00140 } else {
00141 double F = finish(fs_[i], nactive);
00142 if (F < best) {
00143 target = i;
00144 best = F;
00145 }
00146 }
00147 }
00148 }
00149 if (target >= 0) {
00150 Packet* p = fs_[target].hol_;
00151 fs_[target].hol_ = 0;
00152 fs_[target].finishTime_ = best;
00153
00154 Handler* h = fs_[target].handler_;
00155
00156 h->handle(0);
00157 return (p);
00158 }
00159 return (0);
00160 }
00161
00162
00163
00164
00165
00166 void FQ::recv(Packet* p, Handler* handler)
00167 {
00168 hdr_ip* h = hdr_ip::access(p);
00169 int flowid = h->flowid();
00170
00171 if (flowid >= MAXFLOW || fs_[flowid].hol_ != 0)
00172 abort();
00173
00174
00175
00176
00177
00178
00179 fs_[flowid].hol_ = p;
00180 double now = Scheduler::instance().clock();
00181 if (now > fs_[flowid].finishTime_)
00182 fs_[flowid].finishTime_ = now;
00183 fs_[flowid].handler_ = handler;
00184 int size = hdr_cmn::access(p)->size();
00185 fs_[flowid].delta_ = size * secsPerByte_;
00186
00187 if (!blocked_) {
00188
00189
00190
00191
00192
00193
00194 p = deque();
00195 if (p != 0) {
00196 blocked_ = 1;
00197 target_->recv(p, &qh_);
00198 }
00199 }
00200 }
00201
00202 void FQ::enque(Packet*)
00203 {
00204
00205 abort();
00206 }