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

通讯编程

开发平台:

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. /* 
  35.  * TCP-Linux module for NS2 
  36.  *
  37.  * May 2006
  38.  *
  39.  * Author: Xiaoliang (David) Wei  (DavidWei@acm.org)
  40.  *
  41.  * NetLab, the California Institute of Technology 
  42.  * http://netlab.caltech.edu
  43.  *
  44.  * Module: scoreboard1.cc
  45.  *      This is the Scoreboard implementation for TCP-Linux in NS-2.
  46.  *      We loosely follow the Linux implementation (clearn_rtx_queue and sacktag_write_queue in tcp_input.c) in Scoreboard Update.
  47.  *
  48.  */
  49. #include <stdlib.h>
  50. #include <stdio.h>
  51. #include "scoreboard1.h"
  52. #include "tcp.h"
  53. #include "linux/ns-linux-util.h"
  54. #define ASSERT(x) if (!(x)) {printf ("Assert SB failedn"); exit(1);}
  55. #define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)n"); exit(1);}
  56. #define ASSERT2(x,y...) if (!(x)) {printf(y); exit(1); }
  57. bool ScoreBoard1::CleanRtxQueue(int last_ack, unsigned char* flag) 
  58. {
  59. int cmp;
  60. bool changed_acked_rtx = false;
  61. //clean the acked packets
  62. while ((head_) && ((cmp=head_->ShouldClean(last_ack))!=0)) {
  63. int pkt_num = (cmp<0) ? head_->GetLength(): cmp;
  64. switch (head_->GetFlag()) {
  65. case SKB_FLAG_SACKED: 
  66. sack_out_ -= pkt_num;
  67. ASSERT2((sack_out_>=0), "SACK_OUT %d get negative when advancing edge, last_ack %dn", sack_out_, last_ack);
  68. break;
  69. case SKB_FLAG_LOST:
  70. fack_out_ -= pkt_num;
  71. ASSERT2((fack_out_>=0), "fack_out %d get negative when advancing edge, last_ack %dn", fack_out_, last_ack);
  72. break;
  73. }
  74. //printf("%d: %d %dn", last_ack, cmp, head_->GetFlag());
  75. if (cmp<0) {
  76. ScoreBoardNode1* tmp=head_;
  77. head_=head_->GetNext();
  78. if (tmp->GetFlag()==SKB_FLAG_RETRANSMITTED) {
  79. if (tmp->GetRtx()>acked_rtx_id_) {
  80. changed_acked_rtx = true;
  81. acked_rtx_id_ = tmp->GetRtx();
  82. }
  83. (*flag) |= FLAG_UNSURE_TSTAMP;
  84. }
  85. if (tmp == nxt_to_retrx_) nxt_to_retrx_ = head_;
  86. delete tmp;
  87. } else {
  88. head_->SetBegin(last_ack+1);
  89. break;
  90. }
  91. }
  92. return changed_acked_rtx;
  93. }
  94. // last_ack = TCP last ack
  95. int ScoreBoard1::UpdateScoreBoard (int last_ack, hdr_tcp* tcph, int dupack_threshold)
  96. {
  97. // This one pass process is not completely accurate:
  98. //
  99. // There is some case such that the acked_rtx_id_ is increased in the later part of the process,
  100. // and this change may mark some earlier packet in the queue to be lost 
  101. // One example:
  102. // 1 (retran=1) 2-5 (sacked) 6(retran=5) 
  103. // if this sack block has 6 in its sack, 1 won't be marked lost in the round.
  104. // However, 1 will be marked as lost when the next SACK arrives
  105. //
  106. // Also, if there is some new packet loss happens after the right most seq of this SACK, this
  107. // pass will not find the loss since it stops at the right most seq of this SACK.
  108. // However, the lost packets will be marked when there is new SACK come back. 
  109. //printf("clean rtxn");
  110. unsigned char flag = 0;
  111. bool thorough = CleanRtxQueue(last_ack, &flag);
  112. if (head_==NULL) {
  113. ClearScoreBoard();
  114. thorough=false;
  115. // if there is no outstanding lost packets, we might not need to do the rest
  116. }
  117. if ((!thorough) && (tcph->sa_length()==0)) return (flag);
  118. // SACK pre-processing
  119. // we filter D-SACK and sort the SACKs below
  120. int sa_length = 0;
  121. int left[NSA+1];
  122. int right[NSA+1];
  123. for (int i=0; i < tcph->sa_length(); i++) {
  124. int sack_left = tcph->sa_left(i);
  125. int sack_right = tcph->sa_right(i);
  126. if (sack_left >= last_ack) { //here we filter the D-SACK
  127. int j = sa_length;
  128. sa_length++;
  129. while ((j>0) && (left[j-1] > sack_left)) { 
  130. left[j] = left[j-1]; 
  131. right[j] = right[j-1]; 
  132. j--;
  133. }
  134. //insert to the right place to keep increasing order
  135. left[j] = sack_left;
  136. right[j] = sack_right;
  137. }
  138. }
  139. if ((!thorough)&&(sa_length == 0)) return (flag); //same reason as the first return 0
  140. if ((sa_length > 0) && (fack_ < (right[sa_length-1]-1))) {
  141. // advance fack_. right[sa_length-1]-1 is the right most of all the sacks in the packet. 
  142. fack_ = right[sa_length-1]-1;
  143. thorough = true;
  144. }
  145. //  If there is no scoreboard, create one.
  146. if (head_==NULL) {
  147. head_ = new ScoreBoardNode1(last_ack+1, fack_,0);
  148. //initially, create a block from snd_una to facked, 
  149. //  with flag==0 meaning that packets are in flight
  150. };
  151. // From now, we process the score board
  152. nxt_to_retrx_ = NULL;
  153. // printf("start traversen");
  154. int lost_seq_threshold = fack_ - (dupack_threshold+1);
  155. ScoreBoardNode1* now = head_; // the block we are processing
  156. ScoreBoardNode1* prev = NULL;
  157. int sack_index = 0; //the sack that is currently focused 
  158. while ((now != NULL) && ((sack_index<sa_length)||thorough)) {
  159. if (now->GetFlag()!=SKB_FLAG_SACKED) {
  160. while ((sack_index<sa_length) && (right[sack_index]<=now->GetStart()) )
  161. sack_index++;
  162. //find the sack that match "now"
  163. if (sack_index<sa_length) {
  164. //printf("Sack block: [%d %d], now block: %d[%d %d]n", left[sack_index], right[sack_index], now->GetFlag(), now->GetStart(), now->GetEnd());
  165. if (left[sack_index]<=now->GetEnd()) {
  166. // We share some intersection between this SACK and this "now"
  167. if (left[sack_index]>now->GetStart()) {
  168. //printf("split to make some sackesn");
  169. // the first part of "now" is not SACKED
  170. now->Split(left[sack_index]);
  171. } else {
  172. if (right[sack_index]<=now->GetEnd()) {
  173. //partially sacked
  174. //printf("going to splitn");
  175. now->Split(right[sack_index]);
  176. //printf("done splitn");
  177. };
  178. int pktnum = now->GetLength();
  179. switch (now->GetFlag()) {
  180. case SKB_FLAG_LOST:
  181. fack_out_ -= pktnum;
  182. break;
  183. case SKB_FLAG_RETRANSMITTED:
  184. acked_rtx_id_ = now->GetRtx();
  185. flag |= FLAG_UNSURE_TSTAMP;
  186. thorough = true;
  187. break;
  188. }
  189. sack_out_ += pktnum;
  190. flag |= FLAG_DATA_SACKED;
  191. now->SetFlag(SKB_FLAG_SACKED);
  192. }
  193. };
  194. }
  195. if ((sack_index>=sa_length)|| (left[sack_index]>now->GetEnd())) {
  196. //printf("now block: %d[%d %d]n", now->GetFlag(),now->GetStart(), now->GetEnd());
  197. switch (now->GetFlag()) {
  198. case SKB_FLAG_RETRANSMITTED:
  199. // check if it is lost again
  200. if (((now->GetSndNxt() <= fack_)
  201. ||((now->GetRtx() + dupack_threshold+1) < acked_rtx_id_))) {
  202. now->SetFlag(SKB_FLAG_LOST);
  203. fack_out_++;
  204. flag |= FLAG_DATA_LOST;
  205. if (!nxt_to_retrx_) nxt_to_retrx_ = now;
  206. break;
  207. case SKB_FLAG_INFLIGHT:
  208. //check if it is lost
  209. if (now->GetStart() <= lost_seq_threshold) {
  210. //some packets might be lost
  211. if (lost_seq_threshold<now->GetEnd()) {
  212. //partial loss
  213. now->Split(lost_seq_threshold+1);
  214. }
  215. now->SetFlag(SKB_FLAG_LOST);
  216. fack_out_ += now->GetLength();
  217. flag |= FLAG_DATA_LOST;
  218. if (!nxt_to_retrx_) nxt_to_retrx_ = now;
  219. }
  220. break;
  221. case SKB_FLAG_LOST:
  222. if (!nxt_to_retrx_) nxt_to_retrx_ = now;
  223. break;
  224. }
  225. }
  226. }
  227. //printf("now block: %d[%d %d]n", now->GetFlag(),now->GetStart(), now->GetEnd());
  228. if ((prev) && (prev->Mergable())) {
  229. //Try to merge with previous node
  230. //printf("Merging %d [%d,%d] + %d [%d, %d]n", prev->GetFlag(), prev->GetStart(), prev->GetEnd(), now->GetFlag(), now->GetStart(), now->GetEnd());
  231. prev->Merge();
  232. } else {
  233. prev = now;
  234. }
  235. if ((prev->GetNext()==NULL) && (prev->GetEnd()<fack_)) {
  236. //printf("appending %d %dn",prev->GetEnd()+1, fack_);
  237. prev->Append(new ScoreBoardNode1(prev->GetEnd()+1, fack_,0));
  238. //extend the scoreboard
  239. }
  240. now = prev -> GetNext();
  241. };
  242. return (flag);
  243. }
  244. void ScoreBoard1::MarkLoss(int snd_una, int snd_nxt) {
  245. nxt_to_retrx_ = NULL;
  246. ScoreBoardNode1* now = head_;
  247. ScoreBoardNode1* prev = NULL;
  248. bool last_lost = false;
  249. while (now) {
  250. if (!(now->GetFlag() & (SKB_FLAG_SACKED))) {
  251. if (! (now->GetFlag() & SKB_FLAG_LOST)) 
  252. fack_out_ += now->GetEnd() - now->GetStart() + 1;
  253. now->SetFlag(SKB_FLAG_LOST);
  254. if (last_lost) {
  255. prev->Merge();
  256. now=prev;
  257. } else {
  258. if (nxt_to_retrx_==NULL) nxt_to_retrx_ = now;
  259. }
  260. last_lost = true;
  261. } else {
  262. last_lost = false;
  263. }
  264. prev = now;
  265. now = now->GetNext();
  266. if ((now==NULL) && ((prev->GetEnd()+1) < snd_nxt)) {
  267. //all the packets that we sent have lost
  268. now = new ScoreBoardNode1(prev->GetEnd()+1, snd_nxt-1, SKB_FLAG_INFLIGHT);
  269. prev->Append(now);
  270. }
  271. }
  272. if ((prev==NULL) && (snd_una<snd_nxt)) {
  273. //the score board is empty
  274. head_ = new ScoreBoardNode1(snd_una, snd_nxt-1, SKB_FLAG_LOST);
  275. nxt_to_retrx_ = head_;
  276. fack_out_ += snd_nxt - snd_una;
  277. }
  278. rtx_id_ = 0;
  279. acked_rtx_id_ = -1;
  280. }
  281. void ScoreBoard1::ClearScoreBoard()
  282. {
  283. rtx_id_ = 0;
  284. acked_rtx_id_ = -1;
  285.         fack_out_ = 0;
  286.         sack_out_ = 0;
  287. fack_ = 0;
  288. nxt_to_retrx_ = NULL;
  289. while (head_) {
  290. ScoreBoardNode1* temp = head_;
  291. head_ = head_->GetNext();
  292. delete temp;
  293. }
  294. }
  295. /*
  296.  * GetNextRetran() returns "-1" if there is no packet that is
  297.  *   not acked and not sacked and not retransmitted.
  298.  */
  299. int ScoreBoard1::GetNextRetran()
  300. {
  301. while ((nxt_to_retrx_) && (nxt_to_retrx_->GetFlag() != SKB_FLAG_LOST))
  302. nxt_to_retrx_ = nxt_to_retrx_->GetNext();
  303. if (nxt_to_retrx_) {
  304. return nxt_to_retrx_->GetStart();
  305. } else
  306. return -1;
  307. }
  308. void ScoreBoard1::MarkRetran (int retran_seqno, int snd_nxt)
  309. {
  310. ASSERT2(((nxt_to_retrx_) && (nxt_to_retrx_->Inside(retran_seqno))), "Trying to mark a retransmission outside the recommended one: %p %d, snd_nxt: %dn", nxt_to_retrx_, retran_seqno, snd_nxt);
  311. fack_out_ --;
  312. ASSERT2((fack_out_>=0), "fack_out gets negative in Mark Retran, %d, snd_nxt: %d, rtx_seq:%dn", fack_out_, snd_nxt, retran_seqno);
  313. nxt_to_retrx_->MarkRetran(snd_nxt, rtx_id_);
  314. rtx_id_++;
  315. last_rtx_seq_=retran_seqno;
  316. }
  317. void ScoreBoard1::Dump()
  318. {
  319.        if (head_ == NULL ) { printf("SB: No entryn"); return; };
  320.        printf("SB len:%d fack:%d sack_out:%d fack_out:%d acked_rtx_id:%d next_rtx_id:%dn", 
  321. fack_-head_->GetStart(), 
  322. fack_, 
  323. sack_out_,
  324. fack_out_,
  325. acked_rtx_id_,
  326. rtx_id_
  327. );
  328. ScoreBoardNode1* now=head_;
  329. while (now) {
  330. if (now->GetFlag()==SKB_FLAG_RETRANSMITTED) 
  331. printf("seq:%d (%d snd_nxt:%d rtxid:%d)n", now->GetStart(), now->GetFlag(), now->GetSndNxt(), now->GetRtx());
  332. else
  333. printf("seq:[%d,%d] (%d)n", now->GetStart(), now->GetEnd(), now->GetFlag());
  334. now=now->GetNext();
  335.        }
  336.        printf("n");
  337. }
  338. void ScoreBoard1::test() 
  339. {
  340. ClearScoreBoard();
  341. hdr_tcp test;
  342. test.sa_length_ =  1;
  343. test.sack_area_[0][0]= 4;
  344. test.sack_area_[0][1]= 5;
  345. printf(" 1 x x 4  n");
  346. UpdateScoreBoard(1, &test); Dump();
  347.         test.sack_area_[0][0]= 7;
  348.         test.sack_area_[0][1]= 8;
  349. printf(" 1 x x 4 x x 7 n");
  350. UpdateScoreBoard(1, &test); Dump();
  351. printf(" 1 R x 4 x x 7n");
  352. MarkRetran(GetNextRetran(),8); Dump();
  353. test.sack_area_[0][0]= 9;
  354. test.sack_area_[0][1]= 10;
  355. printf(" 1 x x 4 x x 7 x 9 n");
  356. UpdateScoreBoard(1, &test); Dump();
  357. test.sack_area_[0][0]= 7;
  358.         test.sack_area_[0][1]= 9;
  359.         printf(" 1 x x 4 x x 7 8 9n");
  360.         UpdateScoreBoard(1, &test); Dump();
  361. printf(" 1 R x 4 x x 7 8 9n");
  362.         MarkRetran(GetNextRetran(),60); Dump();
  363. printf(" 1 R R 4 x x 7 8 9n");
  364.         MarkRetran(GetNextRetran(),60); Dump();
  365. test.sack_area_[0][0]= 3;
  366.         test.sack_area_[0][1]= 4;
  367.         printf(" 1 R 3 4 x x 7 8 9n");
  368.         UpdateScoreBoard(1, &test); Dump();
  369. test.sack_area_[0][0]= 15;
  370.         test.sack_area_[0][1]= 19;
  371.         printf(" 1 R 3 4 x x 7 8 9 x x x x x 15 - 19n");
  372.         UpdateScoreBoard(1, &test); Dump();
  373. printf(" 1 R R 4 R x 7 8 9 x x x x x 15 - 19n");
  374.         MarkRetran(GetNextRetran(),60); Dump();
  375. printf(" 1 R 3 4 R R 7 8 9 x x x x x 15 - 19n");
  376.         MarkRetran(GetNextRetran(),60); Dump();
  377. printf(" 1 R R 4 R R 7 8 9 R x x x x 15 - 19n");
  378.         MarkRetran(GetNextRetran(),60); Dump();
  379.         printf(" 1 R 3 4 R R 7 8 9 R R x x x 15 16n");
  380.         MarkRetran(GetNextRetran(),60); Dump();
  381.         printf(" 1 R 3 4 R R 7 8 9 R R R x x 15 16n");
  382.         MarkRetran(GetNextRetran(),60); Dump();
  383.         printf(" 1 R 3 4 R R 7 8 9 R R R R x 15 16n");
  384.         MarkRetran(GetNextRetran(),60); Dump();
  385. printf(" 1 R 3 4 R R 7 8 9 R R R R R 15 16n");
  386.         MarkRetran(GetNextRetran(),60); Dump();
  387.         test.sack_area_[0][0]= 5;
  388.         test.sack_area_[0][1]= 11;
  389.         printf(" 1 R 3 4 5 6 7 8 9 10 R R R R 15 16n");
  390.         UpdateScoreBoard(1, &test); Dump();
  391. test.sack_area_[0][0]= 25;
  392.         test.sack_area_[0][1]= 40;
  393.         printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 25-40n");
  394.         UpdateScoreBoard(1, &test); Dump();
  395. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 Rn");
  396.         MarkRetran(GetNextRetran(),90); Dump();
  397. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 R Rn");
  398.         MarkRetran(GetNextRetran(),20); Dump();
  399. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 R R Rn");
  400.         MarkRetran(GetNextRetran(),20); Dump();
  401. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 R R R Rn");
  402.         MarkRetran(GetNextRetran(),20); Dump();
  403. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 R R R R Rn");
  404.         MarkRetran(GetNextRetran(),20); Dump();
  405. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16 R R R R R Rn");
  406.         MarkRetran(GetNextRetran(),20); Dump();
  407.         test.sack_area_[0][0]= 11;
  408.         test.sack_area_[0][1]= 16;
  409.         printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 14 15 16 25-40n");
  410.         UpdateScoreBoard(1, &test); Dump();
  411. test.sack_area_[0][0]= 11;
  412.         test.sack_area_[0][1]= 16;
  413.         printf(" 1 x 3 4 5 6 7 8 9 10 11 12 13 14 15 16 25-40n");
  414.         UpdateScoreBoard(1, &test); Dump();
  415. printf(" 1 R 3 4 5 6 7 8 9 10 11 12 13 R 15 16n");
  416. MarkRetran(GetNextRetran(),20); Dump();
  417. UpdateScoreBoard(3, &test); Dump();
  418. }