00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef lint
00041 static const char rcsid[] =
00042 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/scoreboard-rh.cc,v 1.2 2000/08/12 21:45:39 sfloyd Exp $ (LBL)";
00043 #endif
00044
00045
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <sys/types.h>
00049 #include <math.h>
00050
00051 #include "packet.h"
00052 #include "scoreboard-rh.h"
00053 #include "tcp.h"
00054
00055 #define ASSERT(x) if (!(x)) {printf ("Assert SB failed\n"); exit(1);}
00056 #define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)\n"); exit(1);}
00057
00058 #define SBNI SBN[i%SBSIZE]
00059
00060
00061 int ScoreBoardRH::UpdateScoreBoard (int last_ack, hdr_tcp* tcph, int rh_id)
00062 {
00063 int i, sack_index, sack_left, sack_right;
00064 int sack_max = 0;
00065 int retran_decr = 0;
00066
00067
00068 #if 0
00069 if (tcph->sa_length() == 0) {
00070
00071 this->ClearScoreBoard();
00072 return(0);
00073 }
00074 #endif
00075
00076
00077 if ((tcph->sa_length() == 0) && (length_ == 0)) {
00078 return(0);
00079 }
00080
00081
00082
00083 if (length_ == 0) {
00084 i = last_ack+1;
00085 SBNI.seq_no_ = i;
00086 SBNI.ack_flag_ = 0;
00087 SBNI.sack_flag_ = 0;
00088 SBNI.retran_ = 0;
00089 SBNI.snd_nxt_ = 0;
00090 SBNI.sack_cnt_ = 0;
00091 SBNI.rh_id_ = 0;
00092 first_ = i%SBSIZE;
00093 length_++;
00094 if (length_ >= SBSIZE) {
00095 printf ("Error, scoreboard too large (increase SBSIZE for more space)\n");
00096 exit(1);
00097 }
00098 }
00099
00100
00101 if (SBN[first_].seq_no_ <= last_ack) {
00102 for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) {
00103
00104 if (SBNI.seq_no_ <= last_ack) {
00105 ASSERT(first_ == i%SBSIZE);
00106 first_ = (first_+1)%SBSIZE;
00107 length_--;
00108 ASSERT1(length_ >= 0);
00109 SBNI.ack_flag_ = 1;
00110 SBNI.sack_flag_ = 1;
00111 if (SBNI.retran_) {
00112 SBNI.retran_ = 0;
00113 SBNI.snd_nxt_ = 0;
00114 retran_decr++;
00115 retran_sacked_ = rh_id;
00116 }
00117 if (length_==0)
00118 break;
00119 }
00120 }
00121 }
00122
00123 for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
00124 sack_left = tcph->sa_left(sack_index);
00125 sack_right = tcph->sa_right(sack_index);
00126
00127
00128 if (sack_right > sack_max) {
00129 sack_max = sack_right;
00130 }
00131
00132
00133 if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
00134
00135 for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
00136 SBNI.seq_no_ = i;
00137 SBNI.ack_flag_ = 0;
00138 SBNI.sack_flag_ = 0;
00139 SBNI.retran_ = 0;
00140 SBNI.snd_nxt_ = 0;
00141 SBNI.sack_cnt_ = 0;
00142 SBNI.rh_id_ = 0;
00143 length_++;
00144 if (length_ >= SBSIZE) {
00145 printf ("Error, scoreboard too large (increase SBSIZE for more space)\n");
00146 exit(1);
00147 }
00148 }
00149 }
00150
00151 for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) {
00152
00153 if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
00154 if (! SBNI.sack_flag_) {
00155 SBNI.sack_flag_ = 1;
00156 }
00157 if (SBNI.retran_) {
00158 SBNI.retran_ = 0;
00159 SBNI.snd_nxt_ = 0;
00160 retran_decr++;
00161 retran_sacked_ = rh_id;
00162 }
00163 }
00164 }
00165 }
00166
00167
00168
00169 if (length_ != 0) {
00170 for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) {
00171
00172 if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
00173 SBNI.sack_cnt_++;
00174 }
00175 }
00176 }
00177
00178 retran_decr += CheckSndNxt(sack_max);
00179
00180 return (retran_decr);
00181 }
00182 int ScoreBoardRH::CheckSndNxt (int sack_max)
00183 {
00184 int i;
00185 int num_lost = 0;
00186
00187 if (length_ != 0) {
00188 for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_max; i++) {
00189
00190 if (SBNI.retran_ && SBNI.snd_nxt_ < sack_max) {
00191
00192 SBNI.retran_ = 0;
00193 SBNI.snd_nxt_ = 0;
00194 SBNI.sack_cnt_ = 1;
00195 num_lost++;
00196 }
00197 }
00198 }
00199 return (num_lost);
00200
00201
00202 }
00203
00204 void ScoreBoardRH::ClearScoreBoard()
00205 {
00206 length_ = 0;
00207 }
00208
00209
00210
00211
00212
00213 int ScoreBoardRH::GetNextRetran()
00214 {
00215 int i;
00216
00217 if (length_) {
00218 for (i=SBN[(first_)%SBSIZE].seq_no_;
00219 i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
00220 if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && !SBNI.retran_
00221 && (SBNI.sack_cnt_ >= *numdupacks_)) {
00222 return (i);
00223 }
00224 }
00225 }
00226 return (-1);
00227 }
00228
00229
00230 void ScoreBoardRH::MarkRetran (int retran_seqno, int snd_nxt, int rh_id)
00231 {
00232 SBN[retran_seqno%SBSIZE].retran_ = 1;
00233 SBN[retran_seqno%SBSIZE].snd_nxt_ = snd_nxt;
00234 SBN[retran_seqno%SBSIZE].rh_id_ = rh_id;
00235 retran_occured_ = rh_id;
00236 }
00237
00238 int ScoreBoardRH::GetFack (int last_ack)
00239 {
00240 if (length_) {
00241 return(SBN[(first_)%SBSIZE].seq_no_+length_-1);
00242 }
00243 else {
00244 return(last_ack);
00245 }
00246 }
00247
00248 int ScoreBoardRH::GetNewHoles ()
00249 {
00250 int i, new_holes=0;
00251
00252 for (i=SBN[(first_)%SBSIZE].seq_no_;
00253 i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
00254
00255 #if 1
00256 if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == 1) {
00257 new_holes++;
00258 }
00259 #else
00260 if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && SBNI.sack_cnt_ == *numdupacks_) {
00261 new_holes++;
00262 }
00263 #endif
00264 }
00265 return (new_holes);
00266 }
00267
00268 void ScoreBoardRH::TimeoutScoreBoard (int snd_nxt)
00269 {
00270 int i, sack_right;
00271
00272 if (length_ == 0) {
00273
00274 return;
00275 }
00276
00277 sack_right = snd_nxt;
00278
00279
00280 if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
00281
00282 for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
00283 SBNI.seq_no_ = i;
00284 SBNI.ack_flag_ = 0;
00285 SBNI.sack_flag_ = 0;
00286 SBNI.retran_ = 0;
00287 SBNI.snd_nxt_ = 0;
00288 SBNI.sack_cnt_ = 0;
00289 SBNI.rh_id_ = 0;
00290 length_++;
00291 if (length_ >= SBSIZE) {
00292 printf ("Error, scoreboard too large (increase SBSIZE for more space)\n");
00293 exit(1);
00294 }
00295 }
00296 }
00297
00298
00299
00300 for (i=SBN[(first_)%SBSIZE].seq_no_;
00301 i<SBN[(first_)%SBSIZE].seq_no_+length_; i++) {
00302
00303 if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
00304 SBNI.retran_ = 0;
00305 SBNI.snd_nxt_ = 0;
00306 SBNI.sack_cnt_ = *numdupacks_;
00307 }
00308 }
00309
00310
00311 i=SBN[(first_)%SBSIZE].seq_no_;
00312 if (!SBNI.ack_flag_ && SBNI.sack_flag_) {
00313 printf ("Renege!!! seqno = %d\n", SBNI.seq_no_);
00314 SBNI.sack_flag_ = 0;
00315 SBNI.retran_ = 0;
00316 SBNI.snd_nxt_ = 0;
00317 SBNI.sack_cnt_ = *numdupacks_;
00318 }
00319 }
00320
00321 #if 0
00322
00323
00324
00325 int ScoreBoardRH::FakeSack (int last_ack, int num_dupacks)
00326 {
00327 int i, sack_left, sack_right;
00328 int retran_decr = 0;
00329
00330
00331 if (length_ == 0) {
00332 i = last_ack+1;
00333 SBNI.seq_no_ = i;
00334 SBNI.ack_flag_ = 0;
00335 SBNI.sack_flag_ = 0;
00336 SBNI.retran_ = 0;
00337 SBNI.snd_nxt_ = 0;
00338 SBNI.sack_cnt_ = 0;
00339 SBNI.rh_id_ = 0;
00340 first_ = i%SBSIZE;
00341 length_++;
00342 if (length_ >= SBSIZE) {
00343 printf ("Error, scoreboard too large (increase SBSIZE for more space)\n");
00344 exit(1);
00345 }
00346 }
00347
00348
00349 if (SBN[first_].seq_no_ <= last_ack) {
00350 for (i=SBN[(first_)%SBSIZE].seq_no_; i<=last_ack; i++) {
00351
00352 if (SBNI.seq_no_ <= last_ack) {
00353 ASSERT(first_ == i%SBSIZE);
00354 first_ = (first_+1)%SBSIZE;
00355 length_--;
00356 ASSERT1(length_ >= 0);
00357 SBNI.ack_flag_ = 1;
00358 SBNI.sack_flag_ = 1;
00359 if (SBNI.retran_) {
00360 SBNI.retran_ = 0;
00361 SBNI.snd_nxt_ = 0;
00362 retran_decr++;
00363 }
00364 if (length_==0)
00365 break;
00366 }
00367 }
00368
00369 i=SBN[(first_)%SBSIZE].seq_no_;
00370 SBNI.ack_flag_ = 0;
00371 SBNI.sack_flag_ = 0;
00372 SBNI.retran_ = 0;
00373 SBNI.snd_nxt_ = 0;
00374 SBNI.rh_id_ = 0;
00375 SBNI.sack_cnt_ = num_dupacks;
00376 }
00377
00378 sack_left = last_ack + 1;
00379 sack_right = sack_left + num_dupacks - 1;
00380
00381
00382 if (sack_right > SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_) {
00383
00384 for (i = SBN[(first_+length_+SBSIZE-1)%SBSIZE].seq_no_+1; i<sack_right; i++) {
00385 SBNI.seq_no_ = i;
00386 SBNI.ack_flag_ = 0;
00387 SBNI.sack_flag_ = 0;
00388 SBNI.retran_ = 0;
00389 SBNI.snd_nxt_ = 0;
00390 SBNI.sack_cnt_ = 0;
00391 SBNI.rh_id_ = 0;
00392 length_++;
00393 if (length_ >= SBSIZE) {
00394 printf ("Error, scoreboard too large (increase SBSIZE for more space)\n");
00395 exit(1);
00396 }
00397 }
00398 }
00399
00400 for (i=SBN[(first_)%SBSIZE].seq_no_; i<sack_right; i++) {
00401
00402 if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
00403 if (! SBNI.sack_flag_) {
00404 SBNI.sack_flag_ = 1;
00405 }
00406 if (SBNI.retran_) {
00407 SBNI.retran_ = 0;
00408 retran_decr++;
00409 }
00410 }
00411 }
00412
00413
00414
00415
00416 i=SBN[(first_)%SBSIZE].seq_no_;
00417
00418 if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
00419 SBNI.sack_cnt_++;
00420 }
00421
00422 return (retran_decr);
00423 }
00424
00425 #endif
00426
00427 int ScoreBoardRH::RetranSacked (int rh_id) {
00428 return (retran_sacked_ == rh_id);
00429 }