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

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1996 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 Network Research
  17.  *  Group at Lawrence Berkeley National Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory 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. /* 9/96 Pittsburgh Supercomputing Center
  35.  *      UpdateScoreBoard, CheckSndNxt, MarkRetran modified for fack
  36.  */
  37. #ifndef lint
  38. static const char rcsid[] =
  39.     "@(#) $Header: /cvsroot/nsnam/ns-2/tcp/scoreboard-rh.cc,v 1.2 2000/08/12 21:45:39 sfloyd Exp $ (LBL)";
  40. #endif
  41. /*  A quick hack version of the scoreboard  */
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <sys/types.h>
  45. #include <math.h>
  46. #include "packet.h"
  47. #include "scoreboard-rh.h"
  48. #include "tcp.h"
  49. #define ASSERT(x) if (!(x)) {printf ("Assert SB failedn"); exit(1);}
  50. #define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)n"); exit(1);}
  51. #define SBNI SBN[i%SBSIZE]
  52. // last_ack = TCP last ack
  53. int ScoreBoardRH::UpdateScoreBoard (int last_ack, hdr_tcp* tcph, int rh_id)
  54. {
  55. int i, sack_index, sack_left, sack_right;
  56. int sack_max = 0;
  57. int retran_decr = 0;
  58. /* Can't do this, because we need to process out the retran_decr  */
  59. #if 0
  60. if (tcph->sa_length() == 0) {
  61. // There are no SACK blocks, so clear the scoreboard.
  62. this->ClearScoreBoard();
  63. return(0);
  64. }
  65. #endif
  66. /*  What we do need to do is not create a scoreboard if we don't need one.  */
  67. if ((tcph->sa_length() == 0) && (length_ == 0)) {
  68. return(0);
  69. }
  70. //  If there is no scoreboard, create one.
  71. if (length_ == 0) {
  72. i = last_ack+1;
  73. SBNI.seq_no_ = i;
  74. SBNI.ack_flag_ = 0;
  75. SBNI.sack_flag_ = 0;
  76. SBNI.retran_ = 0;
  77. SBNI.snd_nxt_ = 0;
  78. SBNI.sack_cnt_ = 0;
  79. SBNI.rh_id_ = 0;
  80. first_ = i%SBSIZE;
  81. length_++;
  82. if (length_ >= SBSIZE) {
  83. printf ("Error, scoreboard too large (increase SBSIZE for more space)n");
  84. exit(1);
  85. }
  86. }
  87. //  Advance the left edge of the block.
  88. if (SBN[first_].seq_no_ <= last_ack) {
  89. for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) {
  90. //  Advance the ACK
  91. if (SBNI.seq_no_ <= last_ack) {
  92. ASSERT(first_ == i%SBSIZE);
  93. first_ = (first_+1)%SBSIZE; 
  94. length_--;
  95. ASSERT1(length_ >= 0);
  96. SBNI.ack_flag_ = 1;
  97. SBNI.sack_flag_ = 1;
  98. if (SBNI.retran_) {
  99. SBNI.retran_ = 0;
  100. SBNI.snd_nxt_ = 0;
  101. retran_decr++;
  102. retran_sacked_ = rh_id;
  103. }
  104. if (length_==0) 
  105. break;
  106. }
  107. }
  108. }
  109. for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
  110. sack_left = tcph->sa_left(sack_index);
  111. sack_right = tcph->sa_right(sack_index);
  112. /*  Remember the highest segment SACKed by this packet  */
  113. if (sack_right > sack_max) {
  114. sack_max = sack_right;
  115. }
  116. //  Create new entries off the right side.
  117. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
  118. //  Create new entries
  119. for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
  120. SBNI.seq_no_ = i;
  121. SBNI.ack_flag_ = 0;
  122. SBNI.sack_flag_ = 0;
  123. SBNI.retran_ = 0;
  124. SBNI.snd_nxt_ = 0;
  125. SBNI.sack_cnt_ = 0;
  126. SBNI.rh_id_ = 0;
  127. length_++;
  128. if (length_ >= SBSIZE) {
  129. printf ("Error, scoreboard too large (increase SBSIZE for more space)n");
  130. exit(1);
  131. }
  132. }
  133. }
  134. for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) {
  135. //  Check to see if this segment is now covered by the sack block
  136. if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
  137. if (! SBNI.sack_flag_) {
  138. SBNI.sack_flag_ = 1;
  139. }
  140. if (SBNI.retran_) {
  141. SBNI.retran_ = 0;
  142. SBNI.snd_nxt_ = 0;
  143. retran_decr++;
  144. retran_sacked_ = rh_id;
  145. }
  146. }
  147. }
  148. }
  149. /*  Now go through the whole scoreboard and update sack_cnt
  150.     on holes which still exist.  */
  151. if (length_ != 0) {
  152. for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) {
  153. //  Check to see if this segment is a hole
  154. if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
  155. SBNI.sack_cnt_++;
  156. }
  157. }
  158. }
  159. retran_decr += CheckSndNxt(sack_max);
  160. return (retran_decr);
  161. }
  162. int ScoreBoardRH::CheckSndNxt (int sack_max)
  163. {
  164. int i;
  165. int num_lost = 0;
  166. if (length_ != 0) {
  167. for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) {
  168. //  Check to see if this segment's snd_nxt_ is now covered by the sack block
  169. if (SBNI.retran_ && SBNI.snd_nxt_ < sack_max) {
  170. // the packet was lost again
  171. SBNI.retran_ = 0;
  172. SBNI.snd_nxt_ = 0;
  173. SBNI.sack_cnt_ = 1;
  174. num_lost++;
  175. }
  176. }
  177. }
  178. return (num_lost);
  179. }
  180. void ScoreBoardRH::ClearScoreBoard()
  181. {
  182. length_ = 0;
  183. }
  184. /*
  185.  * GetNextRetran() returns "-1" if there is no packet that is
  186.  *   not acked and not sacked and not retransmitted.
  187.  */
  188. int ScoreBoardRH::GetNextRetran() // Returns sequence number of next pkt...
  189. {
  190. int i;
  191. if (length_) {
  192. for (i=SBN[(first_)%SBSIZE].seq_no_; 
  193.      i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
  194. if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && !SBNI.retran_
  195.     && (SBNI.sack_cnt_ >= *numdupacks_)) {
  196. return (i);
  197. }
  198. }
  199. }
  200. return (-1);
  201. }
  202. void ScoreBoardRH::MarkRetran (int retran_seqno, int snd_nxt, int rh_id)
  203. {
  204. SBN[retran_seqno%SBSIZE].retran_ = 1;
  205. SBN[retran_seqno%SBSIZE].snd_nxt_ = snd_nxt;
  206. SBN[retran_seqno%SBSIZE].rh_id_ = rh_id;
  207. retran_occured_ = rh_id;
  208. }
  209. int ScoreBoardRH::GetFack (int last_ack)
  210. {
  211. if (length_) {
  212. return(SBN[(first_)%SBSIZE].seq_no_+length_-1);
  213. }
  214. else {
  215. return(last_ack);
  216. }
  217. }
  218. int ScoreBoardRH::GetNewHoles ()
  219. {
  220. int i, new_holes=0;
  221. for (i=SBN[(first_)%SBSIZE].seq_no_;
  222.      i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
  223. //  Check to see if this segment is a new hole
  224. #if 1
  225. if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == 1) {
  226. new_holes++;
  227. }
  228. #else
  229. if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == *numdupacks_) {
  230. new_holes++;
  231. }
  232. #endif
  233. }
  234. return (new_holes);
  235. }
  236. void ScoreBoardRH::TimeoutScoreBoard (int snd_nxt)
  237. {
  238. int i, sack_right;
  239. if (length_ == 0) {
  240. // No need to do anything!  
  241. return;
  242. }
  243. sack_right = snd_nxt;  // Use this to know how far to extend.
  244. //  Create new entries off the right side.
  245. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
  246. //  Create new entries
  247. for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
  248. SBNI.seq_no_ = i;
  249. SBNI.ack_flag_ = 0;
  250. SBNI.sack_flag_ = 0;
  251. SBNI.retran_ = 0;
  252. SBNI.snd_nxt_ = 0;
  253. SBNI.sack_cnt_ = 0;
  254. SBNI.rh_id_ = 0;
  255. length_++;
  256. if (length_ >= SBSIZE) {
  257. printf ("Error, scoreboard too large (increase SBSIZE for more space)n");
  258. exit(1);
  259. }
  260. }
  261. }
  262. /*  Now go through the whole scoreboard and update sack_cnt on holes;
  263.     clear retran flag on everything.  */
  264. for (i=SBN[(first_)%SBSIZE].seq_no_;
  265.      i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
  266. //  Check to see if this segment is a hole
  267. if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
  268. SBNI.retran_ = 0;
  269. SBNI.snd_nxt_ = 0;
  270. SBNI.sack_cnt_ = *numdupacks_;  // This forces all holes to be retransmitted.
  271. }
  272. }
  273. /*  And, finally, check the first segment in case of a renege.  */
  274. i=SBN[(first_)%SBSIZE].seq_no_;
  275. if (!SBNI.ack_flag_ && SBNI.sack_flag_) {
  276. printf ("Renege!!! seqno = %dn", SBNI.seq_no_);
  277. SBNI.sack_flag_ = 0;
  278. SBNI.retran_ = 0;
  279. SBNI.snd_nxt_ = 0;
  280. SBNI.sack_cnt_ = *numdupacks_;  // This forces it to be retransmitted.
  281. }
  282. }
  283. #if 0
  284. /*  This routine inserts a fake sack block of length num_dupacks,
  285.     starting at last_ack+1.  It is for use during NewReno recovery.
  286. */
  287. int ScoreBoardRH::FakeSack (int last_ack, int num_dupacks)
  288. {
  289. int i, sack_left, sack_right;
  290. int retran_decr = 0;
  291. //  If there is no scoreboard, create one.
  292. if (length_ == 0) {
  293. i = last_ack+1;
  294. SBNI.seq_no_ = i;
  295. SBNI.ack_flag_ = 0;
  296. SBNI.sack_flag_ = 0;
  297. SBNI.retran_ = 0;
  298. SBNI.snd_nxt_ = 0;
  299. SBNI.sack_cnt_ = 0;
  300. SBNI.rh_id_ = 0;
  301. first_ = i%SBSIZE;
  302. length_++;
  303. if (length_ >= SBSIZE) {
  304. printf ("Error, scoreboard too large (increase SBSIZE for more space)n");
  305. exit(1);
  306. }
  307. }
  308. //  Advance the left edge of the scoreboard.
  309. if (SBN[first_].seq_no_ <= last_ack) {
  310. for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) {
  311. //  Advance the ACK
  312. if (SBNI.seq_no_ <= last_ack) {
  313. ASSERT(first_ == i%SBSIZE);
  314. first_ = (first_+1)%SBSIZE; 
  315. length_--;
  316. ASSERT1(length_ >= 0);
  317. SBNI.ack_flag_ = 1;
  318. SBNI.sack_flag_ = 1;
  319. if (SBNI.retran_) {
  320. SBNI.retran_ = 0;
  321. SBNI.snd_nxt_ = 0;
  322. retran_decr++;
  323. }
  324. if (length_==0) 
  325. break;
  326. }
  327. }
  328. /*  Now create a new hole in the first position  */
  329. i=SBN[(first_)%SBSIZE].seq_no_;
  330. SBNI.ack_flag_ = 0;
  331. SBNI.sack_flag_ = 0;
  332. SBNI.retran_ = 0;
  333. SBNI.snd_nxt_ = 0;
  334. SBNI.rh_id_ = 0;
  335. SBNI.sack_cnt_ = num_dupacks;
  336. }
  337. sack_left = last_ack + 1;
  338. sack_right = sack_left + num_dupacks - 1;
  339. //  Create new entries off the right side.
  340. if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
  341. //  Create new entries
  342. for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
  343. SBNI.seq_no_ = i;
  344. SBNI.ack_flag_ = 0;
  345. SBNI.sack_flag_ = 0;
  346. SBNI.retran_ = 0;
  347. SBNI.snd_nxt_ = 0;
  348. SBNI.sack_cnt_ = 0;
  349. SBNI.rh_id_ = 0;
  350. length_++;
  351. if (length_ >= SBSIZE) {
  352. printf ("Error, scoreboard too large (increase SBSIZE for more space)n");
  353. exit(1);
  354. }
  355. }
  356. }
  357. for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) {
  358. //  Check to see if this segment is now covered by the sack block
  359. if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
  360. if (! SBNI.sack_flag_) {
  361. SBNI.sack_flag_ = 1;
  362. }
  363. if (SBNI.retran_) {
  364. SBNI.retran_ = 0;
  365. retran_decr++;
  366. }
  367. }
  368. }
  369. /*  Now go through the whole scoreboard and update sack_cnt
  370.     on holes which still exist.  In this case the only possible 
  371.     case is the first hole.  */
  372.         i=SBN[(first_)%SBSIZE].seq_no_;
  373. //  Check to see if this segment is a hole
  374. if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
  375. SBNI.sack_cnt_++;
  376. }
  377. return (retran_decr);
  378. }
  379. #endif
  380. int ScoreBoardRH::RetranSacked (int rh_id) {
  381. return (retran_sacked_ == rh_id);
  382. }