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

通讯编程

开发平台:

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.  * This file contributed by Curtis Villamizar < curtis@ans.net >, Feb 1997.
  35.  */
  36. #ifndef lint
  37. static const char rcsid[] =
  38. "@(#) $Header: /cvsroot/nsnam/ns-2/queue/sfq.cc,v 1.12 2006/02/21 15:20:19 mahrenho Exp $ (ANS)";
  39. #endif
  40. #include <stdlib.h>
  41. #include "config.h"
  42. #include "queue.h"
  43. class PacketSFQ; // one queue
  44. class SFQ; // a set of SFQ queues
  45. class PacketSFQ : public PacketQueue {
  46.   PacketSFQ() : pkts(0), prev(0), next(0) {}
  47.   friend class SFQ;
  48. protected:
  49.   void sfqdebug();
  50.   int pkts;
  51.   PacketSFQ *prev;
  52.   PacketSFQ *next;
  53.   inline PacketSFQ * activate(PacketSFQ *head) {
  54.     if (head) {
  55.       this->prev = head->prev;
  56.       this->next = head;
  57.       head->prev->next = this;
  58.       head->prev = this;
  59.       return head;
  60.     }
  61.     this->prev = this;
  62.     this->next = this;
  63.     return this;
  64.   }
  65.   inline PacketSFQ * idle(PacketSFQ *head) {
  66.     if (head == this) {
  67.       if (this->next == this)
  68. return 0;
  69.       this->next->prev = this->prev;
  70.       this->prev->next = this->next;
  71.       return this->next;
  72.     }
  73.     return head;
  74.   }
  75. };
  76. class SFQ : public Queue {
  77. public: 
  78.   SFQ();
  79.   virtual int command(int argc, const char*const* argv);
  80.   Packet *deque(void);
  81.   void enque(Packet *pkt);
  82. protected:
  83.   int maxqueue_; // max queue size in packets
  84.   int buckets_; // number of queues
  85.   PacketSFQ *bucket;
  86.   void initsfq();
  87.   void clear();
  88.   int hash(Packet *);
  89.   PacketSFQ *active;
  90.   int occupied;
  91.   int fairshare;
  92. };
  93. static class SFQClass : public TclClass {
  94. public:
  95.   SFQClass() : TclClass("Queue/SFQ") {}
  96.   TclObject* create(int, const char*const*) {
  97.     return (new SFQ);
  98.   }
  99. } class_sfq;
  100. SFQ::SFQ()
  101. {
  102.   maxqueue_ = 40;
  103.   buckets_ = 16;
  104.   bucket = 0;
  105.   active = 0;
  106.   bind("maxqueue_", &maxqueue_);
  107.   bind("buckets_", &buckets_);
  108. }
  109. void SFQ::clear()
  110. {
  111.   PacketSFQ *q = bucket;
  112.   int i = buckets_;
  113.   if (!q)
  114.     return;
  115.   while (i) {
  116.     if (q->pkts) {
  117.       fprintf(stderr, "SFQ changed while queue occupiedn");
  118.       exit(1);
  119.     }
  120.     ++q;
  121.   }
  122.   delete[](bucket);
  123.   bucket = 0;
  124. }
  125. void SFQ::initsfq()
  126. {
  127.   bucket = new PacketSFQ[buckets_];
  128.   active = 0;
  129.   occupied = 0;
  130.   fairshare = maxqueue_ / buckets_;
  131.   // fprintf(stderr, "SFQ initsfq: %d %dn", maxqueue_, buckets_);
  132. }
  133. /*
  134.  * This implements the following tcl commands:
  135.  *  $sfq limit $size
  136.  *  $sfq buckets $num
  137.  */
  138. int SFQ::command(int argc, const char*const* argv)
  139. {
  140.   if (argc == 3) {
  141.     if (strcmp(argv[1], "limit") == 0) {
  142.       maxqueue_ = atoi(argv[2]);
  143.       fairshare = maxqueue_ / buckets_;
  144.       return (TCL_OK);
  145.     }
  146.     if (strcmp(argv[1], "buckets") == 0) {
  147.       clear();
  148.       buckets_ = atoi(argv[2]);
  149.       return (TCL_OK);
  150.     }
  151.   }
  152.   return (Queue::command(argc, argv));
  153. }
  154. void PacketSFQ::sfqdebug()
  155. {
  156.   PacketSFQ *q = this;
  157.   fprintf(stderr, "sfq: ");
  158.   while (q) {
  159.   fprintf(stderr, " 0x%p(%d)", static_cast<void *>(q), q->pkts);
  160.   q = q->next;
  161.   if (q == this)
  162.   break;
  163.   }
  164.   fprintf(stderr, "n");
  165. }
  166. Packet* SFQ::deque(void)
  167. {
  168.   Packet* pkt;
  169.   if (!bucket)
  170.     initsfq();
  171.   if (!active) {
  172.     // fprintf(stderr, "    dequeue: emptyn");
  173.     return (0);
  174.   }
  175.   --active->pkts;
  176.   --occupied;
  177.   pkt = active->deque();
  178.   // fprintf(stderr, "dequeue 0x%x(%d): 0x%xn",
  179.   //   (int)active, active->pkts, (int)pkt);
  180.   // active->sfqdebug();
  181.   if (active->pkts == 0)
  182.     active = active->idle(active);
  183.   else
  184.     active = active->next;
  185.   return pkt;
  186. }
  187. void SFQ::enque(Packet* pkt)
  188. {
  189.   int which;
  190.   PacketSFQ *q;
  191.   int used, left;
  192.   if (!bucket)
  193.     initsfq();
  194.   which = hash(pkt) % buckets_;
  195.   q = &bucket[which];
  196.   // log_packet_arrival(pkt);
  197.   used = q->pkts;
  198.   left = maxqueue_ - occupied;
  199.   // note: if maxqueue_ is changed while running left can be < 0
  200.   if ((used >= (left >> 1))
  201.       || (left < buckets_ && used > fairshare)
  202.       || (left <= 0)) {
  203.     // log_packet_drop(pkt);
  204.     drop(pkt);
  205.     // fprintf(stderr, "    drop: 0x%xn", (int)pkt);
  206.     return;
  207.   }
  208.   q->enque(pkt);
  209.   ++occupied;
  210.   ++q->pkts;
  211.   if (q->pkts == 1)
  212.     active = q->activate(active);
  213.   // fprintf(stderr, "    enqueue(%d=%d): 0x%xn", which, q->pkts, (int)pkt);
  214.   // active->sfqdebug();
  215. }
  216. int SFQ::hash(Packet* pkt)
  217. {
  218.   hdr_ip* iph = hdr_ip::access(pkt);
  219.   int i = (int)iph->saddr();
  220.   int j = (int)iph->daddr();
  221.   int k = i + j;
  222.   return (k + (k >> 8) + ~(k >> 4)) % ((2<<19)-1); // modulo a large prime
  223. }