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
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043
00044 #include "scoreboard.h"
00045 #include "tcp.h"
00046
00047 #define ASSERT(x) if (!(x)) {printf ("Assert SB failed\n"); exit(1);}
00048 #define ASSERT1(x) if (!(x)) {printf ("Assert1 SB (length)\n"); exit(1);}
00049
00050 #define SBNI SBN[i%sbsize_]
00051
00052
00053 int ScoreBoard::UpdateScoreBoard (int last_ack, hdr_tcp* tcph)
00054 {
00055 int i, sack_index, sack_left, sack_right;
00056 int retran_decr = 0;
00057
00058 changed_ = 0;
00059
00060
00061 if (length_ && SBN[first_%sbsize_].seq_no_ <= last_ack) {
00062 for (i=SBN[first_%sbsize_].seq_no_; i<=last_ack; i++) {
00063
00064 if (SBNI.seq_no_ <= last_ack) {
00065 ASSERT(first_ == i);
00066 first_ = (first_+1);
00067 length_--;
00068 ASSERT1(length_ >= 0);
00069 SBNI.ack_flag_ = 1;
00070 SBNI.sack_flag_ = 1;
00071 if (SBNI.retran_) {
00072 SBNI.retran_ = 0;
00073 SBNI.snd_nxt_ = 0;
00074 retran_decr++;
00075 }
00076 changed_++;
00077 if (length_==0)
00078 break;
00079 }
00080 }
00081 }
00082
00083
00084 if (length_ == 0 && tcph->sa_length()) {
00085 i = last_ack+1;
00086 SBNI.seq_no_ = i;
00087 SBNI.ack_flag_ = 0;
00088 SBNI.sack_flag_ = 0;
00089 SBNI.retran_ = 0;
00090 SBNI.snd_nxt_ = 0;
00091 first_ = i;
00092 length_++;
00093 if (length_ >= sbsize_) {
00094 printf ("Error, scoreboard too large (increase sbsize_ for more space)\n");
00095 exit(1);
00096 }
00097 changed_++;
00098 }
00099
00100 for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
00101 sack_left = tcph->sa_left(sack_index);
00102 sack_right = tcph->sa_right(sack_index);
00103
00104
00105 if (sack_right > SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_) {
00106
00107
00108 while((sack_right - last_ack) >= sbsize_ -1 ){
00109 resizeSB(sbsize_*2);
00110 }
00111
00112
00113 for (i = SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_+1; i<sack_right; i++) {
00114 SBNI.seq_no_ = i;
00115 SBNI.ack_flag_ = 0;
00116 SBNI.sack_flag_ = 0;
00117 SBNI.retran_ = 0;
00118 SBNI.snd_nxt_ = 0;
00119 length_++;
00120 if (length_ >= sbsize_) {
00121 fprintf(stderr, "ERROR: Scoreboard got too large!!!\n");
00122 fprintf(stderr, " SBN[first (mod) sbsize_]: %i, sack_right: %i length_: %i\n", SBN[first_%sbsize_].seq_no_,sack_right , length_);
00123 fprintf(stderr, "last_ack: %i SBN[(first_+length_+sbsize_-1) (mod) sbsize_].seq_no_: %i, sbsize_: %i\n", last_ack, SBN[(first_+length_+sbsize_-1)%sbsize_].seq_no_ , sbsize_);
00124 exit(1);
00125 }
00126 changed_++;
00127 }
00128 }
00129
00130 for (i=SBN[(first_)%sbsize_].seq_no_; i<sack_right; i++) {
00131
00132 if (SBNI.seq_no_ >= sack_left && SBNI.seq_no_ < sack_right) {
00133 if (! SBNI.sack_flag_) {
00134 SBNI.sack_flag_ = 1;
00135 changed_++;
00136 }
00137 if (SBNI.retran_) {
00138 SBNI.retran_ = 0;
00139 retran_decr++;
00140 }
00141 }
00142 }
00143 }
00144 return (retran_decr);
00145 }
00146 int ScoreBoard::CheckSndNxt (hdr_tcp* tcph)
00147 {
00148 int i, sack_index, sack_left, sack_right;
00149 int force_timeout = 0;
00150
00151 for (sack_index=0; sack_index < tcph->sa_length(); sack_index++) {
00152 sack_left = tcph->sa_left(sack_index);
00153 sack_right = tcph->sa_right(sack_index);
00154
00155 for (i=SBN[(first_)%sbsize_].seq_no_; i<sack_right; i++) {
00156
00157 if (SBNI.retran_ && SBNI.snd_nxt_ < sack_right) {
00158
00159 SBNI.retran_ = 0;
00160 SBNI.snd_nxt_ = 0;
00161 force_timeout = 1;
00162 }
00163 }
00164 }
00165 return (force_timeout);
00166 }
00167
00168 void ScoreBoard::ClearScoreBoard()
00169 {
00170 length_ = 0;
00171 }
00172
00173
00174
00175
00176
00177 int ScoreBoard::GetNextRetran()
00178 {
00179 int i;
00180
00181 if (length_) {
00182 for (i=SBN[(first_)%sbsize_].seq_no_;
00183 i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00184 if (!SBNI.ack_flag_ && !SBNI.sack_flag_ && !SBNI.retran_) {
00185 return (i);
00186 }
00187 }
00188 }
00189 return (-1);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 int ScoreBoard::GetNextUnacked (int seqno)
00199 {
00200 int i;
00201 if (!length_) {
00202 return (-1);
00203 } else if (seqno < SBN[(first_)%sbsize_].seq_no_ ||
00204 seqno >= SBN[(first_)%sbsize_].seq_no_+length_) {
00205 return (-1);
00206 } else {
00207 for (i=seqno; i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00208 if (!SBNI.ack_flag_ && !SBNI.sack_flag_) {
00209 return (i);
00210 }
00211 }
00212 }
00213 return (-1);
00214
00215 }
00216
00217 void ScoreBoard::MarkRetran (int retran_seqno, int snd_nxt)
00218 {
00219 SBN[retran_seqno%sbsize_].retran_ = 1;
00220 SBN[retran_seqno%sbsize_].snd_nxt_ = snd_nxt;
00221 }
00222
00223 void ScoreBoard::MarkRetran (int retran_seqno)
00224 {
00225 SBN[retran_seqno%sbsize_].retran_ = 1;
00226 }
00227
00228 void ScoreBoard::resizeSB(int sz)
00229 {
00230 ScoreBoardNode *newSBN = new ScoreBoardNode[sz+1];
00231
00232 if(!newSBN){
00233 fprintf(stderr, "Unable to allocate new ScoreBoardNode[%i]\n", sz);
00234 exit(1);
00235 }
00236
00237 for(int i = SBN[first_%sbsize_].seq_no_;
00238 i<=SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00239 newSBN[i%sz] = SBN[i%sbsize_];
00240 }
00241
00242 delete[] SBN;
00243 SBN = newSBN;
00244 sbsize_ = sz;
00245 }
00246
00247 void ScoreBoard::Dump()
00248 {
00249 int i;
00250
00251 printf("SB len: %d ", length_);
00252 if (length_) {
00253 for (i=SBN[(first_)%sbsize_].seq_no_;
00254 i<SBN[(first_)%sbsize_].seq_no_+length_; i++) {
00255 printf("seq: %d [ ", i);
00256 if(SBNI.ack_flag_)
00257 printf("A");
00258 if(SBNI.sack_flag_)
00259 printf("S");
00260 if(SBNI.retran_)
00261 printf("R");
00262 printf(" ]");
00263 }
00264 }
00265 printf("\n");
00266 }
00267