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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 The 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 Daedalus Research
  17.  *  Group at the University of California at Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be used
  19.  *    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.  * semantic-packetqueue.cc: contributed by the Daedalus Research Group, 
  35.  * UC Berkeley (http://daedalus.cs.berkeley.edu).
  36.  */
  37. #include "ip.h"
  38. #include "tcp.h"
  39. #include "template.h"
  40. #include "semantic-packetqueue.h"
  41. #include "ack-recons.h"
  42. static class SemanticPacketQueueClass : public TclClass {
  43. public:
  44. SemanticPacketQueueClass() : TclClass("PacketQueue/Semantic") {}
  45. TclObject* create(int , const char*const*) {
  46. return (new SemanticPacketQueue());
  47. }
  48. } class_semanticpacketqueue;
  49. SemanticPacketQueue::SemanticPacketQueue() : ack_count(0), data_count(0), 
  50. acks_to_send(0), marked_count_(0), unmarked_count_(0) 
  51. {
  52. bind_bool("acksfirst_", &acksfirst_);
  53. bind_bool("filteracks_", &filteracks_);
  54. bind_bool("reconsAcks_", &reconsAcks_);
  55. bind_bool("replace_head_", &replace_head_);
  56. bind_bool("priority_drop_", &priority_drop_);
  57. bind_bool("random_drop_", &random_drop_);
  58. bind_bool("random_ecn_", &random_ecn_);
  59. }
  60. int
  61. SemanticPacketQueue::command(int argc, const char*const* argv)
  62. {
  63. if (argc == 3) {
  64. if (strcmp(argv[1], "ackrecons") == 0) {
  65. if ((reconsCtrl_ = (AckReconsController *) 
  66.      TclObject::lookup(argv[2]))) {
  67. reconsCtrl_->spq_ = this;
  68. reconsAcks_ = 1;
  69. }
  70. }
  71. return (TCL_OK);
  72. }
  73. return (TclObject::command(argc, argv));
  74. }
  75. /* 
  76.  * Deque TCP acks before any other type of packet.
  77.  */
  78. Packet* 
  79. SemanticPacketQueue::deque_acksfirst() {
  80. Packet* p = head_;
  81. Packet* pp = NULL;
  82. packet_t type;
  83. if (ack_count > 0) {
  84. while (p) {
  85. type = hdr_cmn::access(p)->ptype_;
  86. if (type == PT_ACK)
  87. break;
  88. pp = p;
  89. p = p->next_;
  90. }
  91. if (!p) 
  92. fprintf(stderr, "In deque_acksfirst(): ack_count: %d but no acks in queue, length = %dn", ack_count, length());
  93. PacketQueue::remove(p, pp);
  94. } else {
  95. p = PacketQueue::deque();
  96. }
  97. return p;
  98. }
  99. /*
  100.  * Purge the queue of acks that are older (i.e., have a smaller sequence 
  101.  * number) than the most recent ack. If replace_head is set, the most recent
  102.  * ack (pointed to by pkt) takes the place of the oldest ack that is purged. 
  103.  * Otherwise, it remains at the tail of the queue.  pkt must be an ACK -- this
  104.  * is checked by the caller.
  105.  */
  106. void
  107. SemanticPacketQueue::filterAcks(Packet *pkt, int replace_head) 
  108. {
  109. int done_replacement = 0;
  110. Packet *p, *pp, *new_p;
  111. hdr_tcp *tcph = hdr_tcp::access(pkt);
  112. int &ack = tcph->seqno();
  113. hdr_ip *iph = hdr_ip::access(pkt);
  114. for (p = head(), pp = p; p != 0; ) {
  115. /* 
  116.  * Check if packet in the queue belongs to the 
  117.  * same connection as the most recent ack
  118.  */
  119. if (compareFlows(hdr_ip::access(p), iph)) {
  120. /* check if queued packet is an ack */
  121. if (hdr_cmn::access(p)->ptype_==PT_ACK) {
  122. hdr_tcp *th = hdr_tcp::access(p);
  123. /* is this ack older than the current one? */
  124. if ((th->seqno() < ack) ||
  125.     (replace_head && th->seqno() == ack)) { 
  126. /* 
  127.  * If we haven't yet replaced the ack 
  128.  * closest to the head with the most 
  129.  * recent ack, do so now.
  130.  */
  131. if (replace_head && pkt != p &&
  132.     !done_replacement) {
  133. PacketQueue::remove(pkt);
  134. ack_count--; /* XXX */
  135. pkt->next_ = p;
  136. if (pp)
  137. pp->next_ = pkt;
  138. pp = pkt;
  139. done_replacement = 1;
  140. continue;
  141. } else if (done_replacement||pkt != p){
  142. new_p = p->next_;
  143. /* 
  144.  * If p is in scheduler queue,
  145.  * cancel the event. Also, 
  146.  * print out a warning because
  147.  * this should never happen.
  148.  */
  149. Scheduler &s = Scheduler::instance();
  150. if (s.lookup(p->uid_)) {
  151. s.cancel(p);
  152. fprintf(stderr, "Warning: In filterAcks(): packet being dropped from queue is in scheduler queuen");
  153. }
  154. PacketQueue::remove(p, pp);
  155. /* XXX should drop, but we
  156.    don't have access to q */
  157. Packet::free(p); 
  158. ack_count--;
  159. p = new_p;
  160. continue;
  161. }
  162. if (ack_count <= 0)
  163. fprintf(stderr, 
  164. "oops! ackcount %dn",
  165. ack_count);
  166. }
  167. }
  168. }
  169. pp = p;
  170. p = p->next_;
  171. }
  172. }
  173. /* check if packet is marked */
  174. int
  175. SemanticPacketQueue::isMarked(Packet *p) 
  176. {
  177. return (hdr_flags::access(p)->fs_);
  178. }
  179. /* pick out the index'th of the appropriate kind (marked/unmarked) depending on markedFlag */
  180. Packet*
  181. SemanticPacketQueue::lookup(int index, int markedFlag) 
  182. {
  183. if (index < 0) {
  184. fprintf(stderr, "In SemanticPacketQueue::lookup(): index = %dn", index);
  185. return (NULL);
  186. }
  187. for (Packet* p = head_; p != 0; p = p->next_) {
  188. if (isMarked(p) == markedFlag)
  189. if (--index < 0)
  190. return (p);
  191. }
  192. return (NULL);
  193. }
  194. /*
  195.  * If random_ecn_ is set, pick out the packet for ECN at random from among the
  196.  * packets in the queue and the packet that just arrived ('pkt'). Otherwise, just
  197.  * pick the packet that just arrived.
  198.  */
  199. Packet*
  200. SemanticPacketQueue::pickPacketForECN(Packet* pkt) 
  201. {
  202. Packet *victim;
  203. int victimIndex;
  204. if (random_ecn_) {
  205. victimIndex = Random::integer(length()+1);
  206. if (victimIndex == length())
  207. victim = pkt;
  208. else
  209. victim = PacketQueue::lookup(victimIndex);
  210. }
  211. else 
  212. victim = pkt;
  213. return (victim);
  214. }
  215. /* 
  216.  * If priority_drop_ is set, drop marked packets before unmarked ones.
  217.  * If in addition or separately random_drop_ is set, use randomization in
  218.  * picking out the victim. XXX not used at present 
  219.  */
  220. Packet*
  221. SemanticPacketQueue::pickPacketToDrop()
  222. {
  223. Packet *victim;
  224. int victimIndex, victimMarked;
  225. if (!priority_drop_) {
  226. if (random_drop_)
  227. victim=PacketQueue::lookup(Random::integer(length()));
  228. else
  229. victim = PacketQueue::lookup(length() - 1);
  230. } else {
  231. /* if there are marked (low priority) packets */
  232. if (marked_count_) {
  233. victimMarked = 1;
  234. if (!random_drop_) 
  235. victimIndex = marked_count_ - 1;
  236. else
  237. victimIndex = Random::integer(marked_count_);
  238. }
  239. else {
  240. victimMarked = 0;
  241. if (!random_drop_)
  242. victimIndex = unmarked_count_ - 1;
  243. else
  244. victimIndex = Random::integer(unmarked_count_);
  245. }
  246. victim = lookup(victimIndex, victimMarked);
  247. }
  248. return (victim);
  249. }
  250. Packet*
  251. SemanticPacketQueue::enque(Packet *pkt)
  252. {
  253. if (reconsAcks_&&(hdr_cmn::access(pkt)->ptype_==PT_ACK)) {
  254. reconsCtrl_->recv(pkt);
  255. return NULL;
  256. }
  257. if (hdr_cmn::access(pkt)->ptype_ == PT_ACK)
  258. ack_count++;
  259. else
  260. data_count++;
  261. if (isMarked(pkt)) 
  262. marked_count_++;
  263. else
  264. unmarked_count_++;
  265. Packet* pt = PacketQueue::enque(pkt); /* actually enque the packet */
  266. if (filteracks_ && (hdr_cmn::access(pkt)->ptype_==PT_ACK))
  267. filterAcks(pkt, replace_head_);
  268. return pt;
  269. }
  270. Packet *
  271. SemanticPacketQueue::deque()
  272. {
  273. Packet *pkt;
  274. if (acksfirst_)
  275. pkt = deque_acksfirst();
  276. else
  277. pkt = PacketQueue::deque();
  278. if (pkt) {
  279. if (hdr_cmn::access(pkt)->ptype_ == PT_ACK)
  280. ack_count--;
  281. else
  282. data_count--;
  283. if (isMarked(pkt))
  284. marked_count_--;
  285. else
  286. unmarked_count_--;
  287. }
  288. return pkt;
  289. }
  290. void 
  291. SemanticPacketQueue::remove(Packet *pkt)
  292. {
  293. PacketQueue::remove(pkt);
  294. if (pkt) {
  295. if (hdr_cmn::access(pkt)->ptype_ == PT_ACK)
  296. ack_count--;
  297. else
  298. data_count--;
  299. if (isMarked(pkt))
  300. marked_count_--;
  301. else
  302. unmarked_count_--;
  303. }
  304. }