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

通讯编程

开发平台:

Visual C++

  1. /* -*- c++ -*-
  2.    priqueue.cc
  3.    
  4.    A simple priority queue with a remove packet function
  5.    $Id: dsr-priqueue.cc,v 1.2 2002/09/11 20:11:09 buchheim Exp $
  6.    */
  7. #include <object.h>
  8. #include <packet.h>
  9. #include <cmu-trace.h>
  10. #include <dsr-priqueue.h>
  11. #define PRIQUEUE_DEBUG 0
  12. static class CMUPriQueueClass : public TclClass {
  13. public:
  14.   CMUPriQueueClass() : TclClass("CMUPriQueue") {}
  15.   TclObject* create(int, const char*const*) {
  16.     return (new CMUPriQueue);
  17.   }
  18. } class_CMUPriQueue;
  19. /* ======================================================================
  20.    Priority Queue Handler
  21.    ====================================================================== */
  22. void CMUPriQueueHandler::handle(Event*)
  23. {
  24.         qh_ifq->prq_resume();
  25. }       
  26. /* ======================================================================
  27.    CMUPriQueue - public routines
  28.    ====================================================================== */
  29. CMUPriQueue::CMUPriQueue() : Connector(), prq_qh_(this)
  30. {
  31. int i;
  32. for(i = 0; i < IFQ_MAX; i++) {
  33. prq_snd_[i].ifq_head = prq_snd_[i].ifq_tail = 0;
  34. prq_snd_[i].ifq_len = 0;
  35. prq_snd_[i].ifq_maxlen = IFQ_MAXLEN;
  36. prq_snd_[i].ifq_drops = 0;
  37. last_ifqlen_[i] = 0;
  38. }
  39. prq_logtarget_ = 0; // no logging target by default
  40. prq_ipaddr_ = 0;
  41. prq_blocked_ = 0;
  42. bind("qlen_logthresh_", &qlen_logthresh_);
  43. bind("fw_logthresh_", &fw_logthresh_);
  44. assert(qlen_logthresh_ > 0 && fw_logthresh_ > 0);
  45. bzero(last_ifqlen_, sizeof(last_ifqlen_));
  46. stat_send_ = stat_recv_ = stat_blocked_ = 0;
  47. }
  48. int
  49. CMUPriQueue::command(int argc, const char*const* argv)
  50. {
  51. if (argc == 2 && strcasecmp(argv[1], "reset") == 0) {
  52. Terminate();
  53. //FALL-THROUGH to give parents a chance to reset
  54. } else if(argc == 3) {
  55. if(strcmp(argv[1], "logtarget") == 0) {
  56. prq_logtarget_ = (Trace*) TclObject::lookup(argv[2]);
  57. assert(prq_logtarget_);
  58. return (TCL_OK);
  59. }
  60. else if(strcmp(argv[1], "ipaddr") == 0) {
  61. prq_ipaddr_ = atoi(argv[2]);
  62. assert(prq_ipaddr_ > 0);
  63. return (TCL_OK);
  64. }
  65. }
  66. return Connector::command(argc, argv);
  67. }
  68. void
  69. CMUPriQueue::log_stats()
  70. {
  71. int q, s = 0, d = 0;
  72. assert(IFQ_MAX == 4);
  73. /*
  74.  * avoid logging useless information
  75.  */
  76. for(q = 0; q < IFQ_MAX; q++) {
  77. s += prq_snd_[q].ifq_len;
  78. d += (prq_snd_[q].ifq_len - last_ifqlen_[q]);
  79. }
  80. if(d < 0)
  81. d = -d;
  82. /*
  83.  * Only write an entry to the log file is the queue length
  84.  * or "delta change" over the last second meets the threshold
  85.  * level OR, if this node is generally busy (forwarding more
  86.  * than a certain number of packets per second).
  87.  */
  88. if(s >= qlen_logthresh_ || d >= qlen_logthresh_ ||
  89.    stat_recv_ > fw_logthresh_) {
  90. if (prq_logtarget_->pt_->tagged()) {
  91.    // using the new tagged trace format
  92.    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}",
  93.       Scheduler::instance().clock(),
  94.       prq_ipaddr_,
  95.       stat_recv_, stat_send_, stat_blocked_,
  96.       prq_snd_[0].ifq_len, prq_snd_[0].ifq_len-last_ifqlen_[0],
  97.       prq_snd_[1].ifq_len, prq_snd_[1].ifq_len-last_ifqlen_[1],
  98.       prq_snd_[2].ifq_len, prq_snd_[2].ifq_len-last_ifqlen_[2],
  99.       prq_snd_[3].ifq_len, prq_snd_[3].ifq_len-last_ifqlen_[3]);
  100. } else {
  101.    trace("I %.9f _%d_ ifq rx %d tx %d bl %d [%d %d] [%d %d] [%d %d] [%d %d]",
  102.       Scheduler::instance().clock(),
  103.       prq_ipaddr_,
  104.       stat_recv_, stat_send_, stat_blocked_,
  105.       prq_snd_[0].ifq_len, prq_snd_[0].ifq_len-last_ifqlen_[0],
  106.       prq_snd_[1].ifq_len, prq_snd_[1].ifq_len-last_ifqlen_[1],
  107.       prq_snd_[2].ifq_len, prq_snd_[2].ifq_len-last_ifqlen_[2],
  108.       prq_snd_[3].ifq_len, prq_snd_[3].ifq_len-last_ifqlen_[3]);
  109. }
  110. }
  111. for(q = 0; q < IFQ_MAX; q++) {
  112. last_ifqlen_[q] = prq_snd_[q].ifq_len;
  113. }
  114. stat_send_ = stat_recv_ = stat_blocked_ = 0;
  115. }
  116. void
  117. CMUPriQueue::trace(char* fmt, ...)
  118. {
  119. va_list ap;
  120.   
  121. assert(prq_logtarget_);
  122. va_start(ap, fmt);
  123. vsprintf(prq_logtarget_->pt_->buffer(), fmt, ap);
  124. prq_logtarget_->pt_->dump();
  125. va_end(ap);
  126. }
  127. void
  128. CMUPriQueue::recv(Packet *p, Handler *)
  129. {
  130. #if PRIQUEUE_DEBUG > 0
  131. prq_validate();
  132. #endif
  133. stat_recv_++;
  134. if(prq_blocked_ == 1) {
  135. stat_blocked_++;
  136. } else {
  137. assert(prq_length() == 0);
  138. }
  139. prq_enqueue(p);
  140. #if PRIQUEUE_DEBUG > 0
  141. prq_validate();
  142. #endif
  143. }
  144. void
  145. CMUPriQueue::prq_resume()
  146. {
  147. Packet *p;
  148. assert(prq_blocked_);
  149. #if PRIQUEUE_DEBUG > 0
  150. prq_validate();
  151. #endif
  152. p = prq_dequeue();
  153. if (p != 0) {
  154. stat_send_++;
  155.                 target_->recv(p, &prq_qh_);
  156.         } else {
  157. prq_blocked_ = 0;
  158.         }
  159. }
  160. /*
  161.  * Called at the end of the simulation to purge the IFQ.
  162.  */
  163. void
  164. CMUPriQueue::Terminate()
  165. {
  166. Packet *p;
  167. while((p = prq_dequeue())) {
  168. drop(p, DROP_END_OF_SIMULATION);
  169. }
  170. }
  171. Packet*
  172. CMUPriQueue::prq_get_nexthop(nsaddr_t id)
  173. {
  174. int q;
  175. Packet *p, *pprev = 0;
  176. struct ifqueue *ifq;
  177. #if PRIQUEUE_DEBUG > 0
  178. prq_validate();
  179. #endif
  180. for(q = 0; q < IFQ_MAX; q++) {
  181. ifq = &prq_snd_[q];
  182. pprev = 0;
  183. for(p = ifq->ifq_head; p; p = p->next_) {
  184. struct hdr_cmn *ch = HDR_CMN(p);
  185. if(ch->next_hop() == id)
  186. break;
  187. pprev = p;
  188. }
  189. if(p) {
  190. if(p == ifq->ifq_head) {
  191. assert(pprev == 0);
  192. IF_DEQUEUE(ifq, p);
  193. /* don't increment drop counter */
  194. #if PRIQUEUE_DEBUG > 0
  195. prq_validate();
  196. #endif
  197. return p;
  198. } else {
  199. assert(pprev);
  200. pprev->next_ = p->next_;
  201. if(p == ifq->ifq_tail)
  202. ifq->ifq_tail = pprev;
  203. ifq->ifq_len--;
  204. #if PRIQUEUE_DEBUG > 0
  205. prq_validate();
  206. #endif
  207. p->next_ = 0;
  208. return p;
  209. }
  210. }
  211.      }
  212. return (Packet*) 0;
  213. }
  214. int
  215. CMUPriQueue::prq_isfull(Packet *p)
  216. {
  217. int q = prq_assign_queue(p);
  218. struct ifqueue *ifq = &prq_snd_[q];
  219. if(IF_QFULL(ifq))
  220. return 1;
  221. else
  222. return 0;
  223. }
  224. int
  225. CMUPriQueue::prq_length()
  226. {
  227. int q, tlen = 0;
  228. for(q = 0; q < IFQ_MAX; q++) {
  229. tlen += prq_snd_[q].ifq_len;
  230. }
  231. return tlen;
  232. }
  233. /* ======================================================================
  234.    CMUPriQueue - private routines
  235.    ====================================================================== */
  236. void
  237. CMUPriQueue::prq_enqueue(Packet *p)
  238. {
  239. int q = prq_assign_queue(p);
  240. struct ifqueue *ifq = &prq_snd_[q];
  241. if(IF_QFULL(ifq)) {
  242. IF_DROP(ifq);
  243. drop(p, DROP_IFQ_QFULL);
  244. return;
  245. }
  246. IF_ENQUEUE(ifq, p);
  247. /*
  248.  * Start queue if idle...
  249.  */
  250. if(prq_blocked_ == 0) {
  251. p = prq_dequeue();
  252. prq_blocked_ = 1;
  253. stat_send_++;
  254. target_->recv(p, &prq_qh_);
  255. }
  256. }
  257. Packet*
  258. CMUPriQueue::prq_dequeue(void)
  259. {
  260. Packet *p;
  261. int q;
  262. for(q = 0; q < IFQ_MAX; q++) {
  263. if(prq_snd_[q].ifq_len > 0) {
  264. IF_DEQUEUE(&prq_snd_[q], p);
  265. return p;
  266. } else {
  267. assert(prq_snd_[q].ifq_head == 0);
  268. }
  269. }
  270. return (Packet*) 0;
  271. }
  272. int
  273. CMUPriQueue::prq_assign_queue(Packet *p)
  274. {
  275.         struct hdr_cmn *ch = HDR_CMN(p);
  276. switch(ch->ptype()) {
  277. case PT_AODV:
  278. case PT_DSR:
  279. case PT_IMEP:
  280. case PT_MESSAGE: /* used by DSDV */
  281. case PT_TORA:
  282. return IFQ_RTPROTO;
  283. case PT_AUDIO:
  284. case PT_VIDEO:
  285. return IFQ_REALTIME;
  286. case PT_ACK:
  287. return IFQ_LOWDELAY;
  288. default:
  289. return IFQ_NORMAL;
  290. }
  291. }
  292. void
  293. CMUPriQueue::prq_validate()
  294. {
  295. int q, qlen;
  296. Packet *p;
  297. struct ifqueue *ifq;
  298. for(q = 0; q < IFQ_MAX; q++) {
  299. ifq = &prq_snd_[q];
  300. qlen = 0;
  301. if(ifq->ifq_head == 0) {
  302. assert(ifq->ifq_len == 0);
  303. assert(ifq->ifq_head == ifq->ifq_tail);
  304. } else {
  305. for(p = ifq->ifq_head; p; p = p->next_) {
  306. if(p->next_ == 0)
  307. assert(p == ifq->ifq_tail);
  308. qlen++;
  309. }
  310. assert(qlen == ifq->ifq_len);
  311. assert(qlen <= ifq->ifq_maxlen);
  312. }
  313. }
  314. }