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
00036
00037 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/queue/sfq.cc,v 1.11 2002/05/06 22:23:16 difa Exp $ (ANS)";
00040 #endif
00041
00042 #include <stdlib.h>
00043
00044 #include "config.h"
00045 #include "queue.h"
00046
00047 class PacketSFQ;
00048 class SFQ;
00049
00050 class PacketSFQ : public PacketQueue {
00051 PacketSFQ() : pkts(0), prev(0), next(0) {}
00052 friend class SFQ;
00053 protected:
00054 void sfqdebug();
00055 int pkts;
00056 PacketSFQ *prev;
00057 PacketSFQ *next;
00058 inline PacketSFQ * activate(PacketSFQ *head) {
00059 if (head) {
00060 this->prev = head->prev;
00061 this->next = head;
00062 head->prev->next = this;
00063 head->prev = this;
00064 return head;
00065 }
00066 this->prev = this;
00067 this->next = this;
00068 return this;
00069 }
00070 inline PacketSFQ * idle(PacketSFQ *head) {
00071 if (head == this) {
00072 if (this->next == this)
00073 return 0;
00074 this->next->prev = this->prev;
00075 this->prev->next = this->next;
00076 return this->next;
00077 }
00078 return head;
00079 }
00080 };
00081
00082 class SFQ : public Queue {
00083 public:
00084 SFQ();
00085 virtual int command(int argc, const char*const* argv);
00086 Packet *deque(void);
00087 void enque(Packet *pkt);
00088 protected:
00089 int maxqueue_;
00090 int buckets_;
00091 PacketSFQ *bucket;
00092 void initsfq();
00093 void clear();
00094 int hash(Packet *);
00095 PacketSFQ *active;
00096 int occupied;
00097 int fairshare;
00098 };
00099
00100 static class SFQClass : public TclClass {
00101 public:
00102 SFQClass() : TclClass("Queue/SFQ") {}
00103 TclObject* create(int, const char*const*) {
00104 return (new SFQ);
00105 }
00106 } class_sfq;
00107
00108 SFQ::SFQ()
00109 {
00110 maxqueue_ = 40;
00111 buckets_ = 16;
00112 bucket = 0;
00113 active = 0;
00114 bind("maxqueue_", &maxqueue_);
00115 bind("buckets_", &buckets_);
00116 }
00117
00118 void SFQ::clear()
00119 {
00120 PacketSFQ *q = bucket;
00121 int i = buckets_;
00122
00123 if (!q)
00124 return;
00125 while (i) {
00126 if (q->pkts) {
00127 fprintf(stderr, "SFQ changed while queue occupied\n");
00128 exit(1);
00129 }
00130 ++q;
00131 }
00132 delete[](bucket);
00133 bucket = 0;
00134 }
00135
00136 void SFQ::initsfq()
00137 {
00138 bucket = new PacketSFQ[buckets_];
00139 active = 0;
00140 occupied = 0;
00141 fairshare = maxqueue_ / buckets_;
00142
00143 }
00144
00145
00146
00147
00148
00149
00150 int SFQ::command(int argc, const char*const* argv)
00151 {
00152 if (argc == 3) {
00153 if (strcmp(argv[1], "limit") == 0) {
00154 maxqueue_ = atoi(argv[2]);
00155 fairshare = maxqueue_ / buckets_;
00156 return (TCL_OK);
00157 }
00158 if (strcmp(argv[1], "buckets") == 0) {
00159 clear();
00160 buckets_ = atoi(argv[2]);
00161 return (TCL_OK);
00162 }
00163 }
00164 return (Queue::command(argc, argv));
00165 }
00166
00167 void PacketSFQ::sfqdebug()
00168 {
00169 PacketSFQ *q = this;
00170 fprintf(stderr, "sfq: ");
00171 while (q) {
00172 fprintf(stderr, " 0x%p(%d)", q, q->pkts);
00173 q = q->next;
00174 if (q == this)
00175 break;
00176 }
00177 fprintf(stderr, "\n");
00178 }
00179
00180 Packet* SFQ::deque(void)
00181 {
00182 Packet* pkt;
00183
00184 if (!bucket)
00185 initsfq();
00186 if (!active) {
00187
00188 return (0);
00189 }
00190 --active->pkts;
00191 --occupied;
00192 pkt = active->deque();
00193
00194
00195
00196 if (active->pkts == 0)
00197 active = active->idle(active);
00198 else
00199 active = active->next;
00200 return pkt;
00201 }
00202
00203 void SFQ::enque(Packet* pkt)
00204 {
00205 int which;
00206 PacketSFQ *q;
00207 int used, left;
00208
00209 if (!bucket)
00210 initsfq();
00211 which = hash(pkt) % buckets_;
00212 q = &bucket[which];
00213
00214 used = q->pkts;
00215 left = maxqueue_ - occupied;
00216
00217 if ((used >= (left >> 1))
00218 || (left < buckets_ && used > fairshare)
00219 || (left <= 0)) {
00220
00221 drop(pkt);
00222
00223 return;
00224 }
00225 q->enque(pkt);
00226 ++occupied;
00227 ++q->pkts;
00228 if (q->pkts == 1)
00229 active = q->activate(active);
00230
00231
00232 }
00233
00234 int SFQ::hash(Packet* pkt)
00235 {
00236 hdr_ip* iph = hdr_ip::access(pkt);
00237 int i = (int)iph->saddr();
00238 int j = (int)iph->daddr();
00239 int k = i + j;
00240
00241 return (k + (k >> 8) + ~(k >> 4)) % ((2<<19)-1);
00242 }