00001
00002
00003
00004
00005
00006
00007
00008 #include <object.h>
00009 #include <packet.h>
00010 #include <cmu-trace.h>
00011 #include <dsr-priqueue.h>
00012
00013 #define PRIQUEUE_DEBUG 0
00014
00015 static class CMUPriQueueClass : public TclClass {
00016 public:
00017 CMUPriQueueClass() : TclClass("CMUPriQueue") {}
00018 TclObject* create(int, const char*const*) {
00019 return (new CMUPriQueue);
00020 }
00021 } class_CMUPriQueue;
00022
00023
00024
00025
00026 void CMUPriQueueHandler::handle(Event*)
00027 {
00028 qh_ifq->prq_resume();
00029 }
00030
00031
00032
00033
00034 CMUPriQueue::CMUPriQueue() : Connector(), prq_qh_(this)
00035 {
00036 int i;
00037
00038 for(i = 0; i < IFQ_MAX; i++) {
00039 prq_snd_[i].ifq_head = prq_snd_[i].ifq_tail = 0;
00040 prq_snd_[i].ifq_len = 0;
00041 prq_snd_[i].ifq_maxlen = IFQ_MAXLEN;
00042 prq_snd_[i].ifq_drops = 0;
00043
00044 last_ifqlen_[i] = 0;
00045 }
00046 prq_logtarget_ = 0;
00047 prq_ipaddr_ = 0;
00048 prq_blocked_ = 0;
00049
00050 bind("qlen_logthresh_", &qlen_logthresh_);
00051 bind("fw_logthresh_", &fw_logthresh_);
00052 assert(qlen_logthresh_ > 0 && fw_logthresh_ > 0);
00053
00054 bzero(last_ifqlen_, sizeof(last_ifqlen_));
00055 stat_send_ = stat_recv_ = stat_blocked_ = 0;
00056 }
00057
00058 int
00059 CMUPriQueue::command(int argc, const char*const* argv)
00060 {
00061 if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {
00062 Terminate();
00063
00064 } else if(argc == 3) {
00065 if(strcmp(argv[1], "logtarget") == 0) {
00066 prq_logtarget_ = (Trace*) TclObject::lookup(argv[2]);
00067 assert(prq_logtarget_);
00068 return (TCL_OK);
00069 }
00070 else if(strcmp(argv[1], "ipaddr") == 0) {
00071 prq_ipaddr_ = atoi(argv[2]);
00072 assert(prq_ipaddr_ > 0);
00073 return (TCL_OK);
00074 }
00075 }
00076 return Connector::command(argc, argv);
00077 }
00078
00079 void
00080 CMUPriQueue::log_stats()
00081 {
00082 int q, s = 0, d = 0;
00083
00084 assert(IFQ_MAX == 4);
00085
00086
00087
00088
00089 for(q = 0; q < IFQ_MAX; q++) {
00090 s += prq_snd_[q].ifq_len;
00091 d += (prq_snd_[q].ifq_len - last_ifqlen_[q]);
00092 }
00093 if(d < 0)
00094 d = -d;
00095
00096
00097
00098
00099
00100
00101
00102 if(s >= qlen_logthresh_ || d >= qlen_logthresh_ ||
00103 stat_recv_ > fw_logthresh_) {
00104 if (prq_logtarget_->pt_->tagged()) {
00105
00106 trace("I "TIME_FORMAT" -prq:adr %d -prq:rx %d -prq:tx %d -prq:bl %d -prq:snd0 {%d %d} -prq:snd1 {%d %d} -prq:snd2 {%d %d} -prq:snd3 {%d %d}",
00107 Scheduler::instance().clock(),
00108 prq_ipaddr_,
00109 stat_recv_, stat_send_, stat_blocked_,
00110 prq_snd_[0].ifq_len, prq_snd_[0].ifq_len-last_ifqlen_[0],
00111 prq_snd_[1].ifq_len, prq_snd_[1].ifq_len-last_ifqlen_[1],
00112 prq_snd_[2].ifq_len, prq_snd_[2].ifq_len-last_ifqlen_[2],
00113 prq_snd_[3].ifq_len, prq_snd_[3].ifq_len-last_ifqlen_[3]);
00114 } else {
00115 trace("I %.9f _%d_ ifq rx %d tx %d bl %d [%d %d] [%d %d] [%d %d] [%d %d]",
00116 Scheduler::instance().clock(),
00117 prq_ipaddr_,
00118 stat_recv_, stat_send_, stat_blocked_,
00119 prq_snd_[0].ifq_len, prq_snd_[0].ifq_len-last_ifqlen_[0],
00120 prq_snd_[1].ifq_len, prq_snd_[1].ifq_len-last_ifqlen_[1],
00121 prq_snd_[2].ifq_len, prq_snd_[2].ifq_len-last_ifqlen_[2],
00122 prq_snd_[3].ifq_len, prq_snd_[3].ifq_len-last_ifqlen_[3]);
00123 }
00124 }
00125
00126 for(q = 0; q < IFQ_MAX; q++) {
00127 last_ifqlen_[q] = prq_snd_[q].ifq_len;
00128 }
00129 stat_send_ = stat_recv_ = stat_blocked_ = 0;
00130 }
00131
00132 void
00133 CMUPriQueue::trace(char* fmt, ...)
00134 {
00135 va_list ap;
00136
00137 assert(prq_logtarget_);
00138
00139 va_start(ap, fmt);
00140 vsprintf(prq_logtarget_->pt_->buffer(), fmt, ap);
00141 prq_logtarget_->pt_->dump();
00142 va_end(ap);
00143 }
00144
00145 void
00146 CMUPriQueue::recv(Packet *p, Handler *)
00147 {
00148 #if PRIQUEUE_DEBUG > 0
00149 prq_validate();
00150 #endif
00151 stat_recv_++;
00152 if(prq_blocked_ == 1) {
00153 stat_blocked_++;
00154 } else {
00155 assert(prq_length() == 0);
00156 }
00157 prq_enqueue(p);
00158 #if PRIQUEUE_DEBUG > 0
00159 prq_validate();
00160 #endif
00161 }
00162
00163 void
00164 CMUPriQueue::prq_resume()
00165 {
00166 Packet *p;
00167
00168 assert(prq_blocked_);
00169 #if PRIQUEUE_DEBUG > 0
00170 prq_validate();
00171 #endif
00172 p = prq_dequeue();
00173 if (p != 0) {
00174 stat_send_++;
00175 target_->recv(p, &prq_qh_);
00176 } else {
00177 prq_blocked_ = 0;
00178 }
00179 }
00180
00181
00182
00183
00184
00185 void
00186 CMUPriQueue::Terminate()
00187 {
00188 Packet *p;
00189 while((p = prq_dequeue())) {
00190 drop(p, DROP_END_OF_SIMULATION);
00191 }
00192 }
00193
00194 Packet*
00195 CMUPriQueue::prq_get_nexthop(nsaddr_t id)
00196 {
00197 int q;
00198 Packet *p, *pprev = 0;
00199 struct ifqueue *ifq;
00200
00201 #if PRIQUEUE_DEBUG > 0
00202 prq_validate();
00203 #endif
00204 for(q = 0; q < IFQ_MAX; q++) {
00205 ifq = &prq_snd_[q];
00206 pprev = 0;
00207 for(p = ifq->ifq_head; p; p = p->next_) {
00208 struct hdr_cmn *ch = HDR_CMN(p);
00209
00210 if(ch->next_hop() == id)
00211 break;
00212 pprev = p;
00213 }
00214
00215 if(p) {
00216 if(p == ifq->ifq_head) {
00217 assert(pprev == 0);
00218
00219 IF_DEQUEUE(ifq, p);
00220
00221 #if PRIQUEUE_DEBUG > 0
00222 prq_validate();
00223 #endif
00224 return p;
00225 } else {
00226 assert(pprev);
00227 pprev->next_ = p->next_;
00228
00229 if(p == ifq->ifq_tail)
00230 ifq->ifq_tail = pprev;
00231 ifq->ifq_len--;
00232
00233 #if PRIQUEUE_DEBUG > 0
00234 prq_validate();
00235 #endif
00236 p->next_ = 0;
00237 return p;
00238 }
00239 }
00240 }
00241
00242 return (Packet*) 0;
00243 }
00244
00245 int
00246 CMUPriQueue::prq_isfull(Packet *p)
00247 {
00248 int q = prq_assign_queue(p);
00249 struct ifqueue *ifq = &prq_snd_[q];
00250
00251 if(IF_QFULL(ifq))
00252 return 1;
00253 else
00254 return 0;
00255 }
00256
00257 int
00258 CMUPriQueue::prq_length()
00259 {
00260 int q, tlen = 0;
00261
00262 for(q = 0; q < IFQ_MAX; q++) {
00263 tlen += prq_snd_[q].ifq_len;
00264 }
00265
00266 return tlen;
00267 }
00268
00269
00270
00271
00272 void
00273 CMUPriQueue::prq_enqueue(Packet *p)
00274 {
00275 int q = prq_assign_queue(p);
00276 struct ifqueue *ifq = &prq_snd_[q];
00277
00278 if(IF_QFULL(ifq)) {
00279 IF_DROP(ifq);
00280 drop(p, DROP_IFQ_QFULL);
00281 return;
00282 }
00283 IF_ENQUEUE(ifq, p);
00284
00285
00286
00287
00288 if(prq_blocked_ == 0) {
00289 p = prq_dequeue();
00290 prq_blocked_ = 1;
00291
00292 stat_send_++;
00293 target_->recv(p, &prq_qh_);
00294 }
00295 }
00296
00297 Packet*
00298 CMUPriQueue::prq_dequeue(void)
00299 {
00300 Packet *p;
00301 int q;
00302
00303 for(q = 0; q < IFQ_MAX; q++) {
00304 if(prq_snd_[q].ifq_len > 0) {
00305 IF_DEQUEUE(&prq_snd_[q], p);
00306 return p;
00307 } else {
00308 assert(prq_snd_[q].ifq_head == 0);
00309 }
00310 }
00311 return (Packet*) 0;
00312 }
00313
00314 int
00315 CMUPriQueue::prq_assign_queue(Packet *p)
00316 {
00317 struct hdr_cmn *ch = HDR_CMN(p);
00318
00319 switch(ch->ptype()) {
00320 case PT_AODV:
00321 case PT_DSR:
00322 case PT_IMEP:
00323 case PT_MESSAGE:
00324 case PT_TORA:
00325 return IFQ_RTPROTO;
00326
00327 case PT_AUDIO:
00328 case PT_VIDEO:
00329 return IFQ_REALTIME;
00330
00331 case PT_ACK:
00332 return IFQ_LOWDELAY;
00333
00334 default:
00335 return IFQ_NORMAL;
00336 }
00337 }
00338
00339 void
00340 CMUPriQueue::prq_validate()
00341 {
00342 int q, qlen;
00343 Packet *p;
00344 struct ifqueue *ifq;
00345
00346 for(q = 0; q < IFQ_MAX; q++) {
00347 ifq = &prq_snd_[q];
00348 qlen = 0;
00349
00350 if(ifq->ifq_head == 0) {
00351 assert(ifq->ifq_len == 0);
00352 assert(ifq->ifq_head == ifq->ifq_tail);
00353 } else {
00354
00355 for(p = ifq->ifq_head; p; p = p->next_) {
00356 if(p->next_ == 0)
00357 assert(p == ifq->ifq_tail);
00358 qlen++;
00359 }
00360
00361 assert(qlen == ifq->ifq_len);
00362 assert(qlen <= ifq->ifq_maxlen);
00363 }
00364 }
00365 }