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 #include "nilist.h"
00041 #include "chost.h"
00042 #include "tcp-int.h"
00043 #include "random.h"
00044
00045 CorresHost::CorresHost() : slink(), TcpFsAgent(),
00046 lastackTS_(0), dontAdjustOwnd_(0), dontIncrCwnd_(0), rexmtSegCount_(0),
00047 connWithPktBeforeFS_(NULL)
00048 {
00049 nActive_ = nTimeout_ = nFastRec_ = 0;
00050 ownd_ = 0;
00051 owndCorrection_ = 0;
00052 closecwTS_ = 0;
00053 connIter_ = new Islist_iter<IntTcpAgent> (conns_);
00054 rtt_seg_ = NULL;
00055 }
00056
00057
00058
00059
00060
00061 void
00062 CorresHost::opencwnd(int , IntTcpAgent *sender)
00063 {
00064 if (cwnd_ < ssthresh_) {
00065
00066 cwnd_ += 1;
00067 } else {
00068
00069
00070 if (!proxyopt_) {
00071 switch (wnd_option_) {
00072 case 0:
00073 if ((count_ = count_ + winInc_) >= cwnd_) {
00074 count_ = 0;
00075 cwnd_ += winInc_;
00076 }
00077 break;
00078 case 1:
00079
00080 cwnd_ += winInc_ / cwnd_;
00081 break;
00082 default:
00083 #ifdef notdef
00084
00085 error("illegal window option %d", wnd_option_);
00086 #endif
00087 abort();
00088 }
00089 } else {
00090 switch (wnd_option_) {
00091 case 0:
00092 case 1:
00093 if (sender->highest_ack_ >= sender->wndIncSeqno_) {
00094 cwnd_ += winInc_;
00095 sender->wndIncSeqno_ = 0;
00096 }
00097 break;
00098 default:
00099 #ifdef notdef
00100
00101 error("illegal window option %d", wnd_option_);
00102 #endif
00103 abort();
00104 }
00105 }
00106 }
00107
00108 if (maxcwnd_ && (int(cwnd_) > maxcwnd_))
00109 cwnd_ = maxcwnd_;
00110
00111 return;
00112 }
00113
00114 void
00115 CorresHost::closecwnd(int how, double ts, IntTcpAgent *sender)
00116 {
00117 if (proxyopt_) {
00118 if (!sender || ts > sender->closecwTS_)
00119 closecwnd(how, sender);
00120 }
00121 else {
00122 if (ts > closecwTS_)
00123 closecwnd(how, sender);
00124 }
00125 }
00126
00127 void
00128 CorresHost::closecwnd(int how, IntTcpAgent *sender)
00129 {
00130 int sender_ownd = 0;
00131 if (sender)
00132 sender_ownd = sender->maxseq_ - sender->highest_ack_;
00133 closecwTS_ = Scheduler::instance().clock();
00134 if (proxyopt_) {
00135 if (sender)
00136 sender->closecwTS_ = closecwTS_;
00137 how += 10;
00138 }
00139 switch (how) {
00140 case 0:
00141 case 10:
00142
00143
00144
00145
00146
00147
00148
00149 ssthresh_ = int(cwnd_ * winMult_);
00150 cwnd_ = int(wndInit_);
00151 break;
00152
00153 case 1:
00154
00155
00156
00157
00158
00159
00160
00161 cwnd_ *= winMult_;
00162 ssthresh_ = int(cwnd_);
00163 if (ssthresh_ < 2)
00164 ssthresh_ = 2;
00165 break;
00166
00167 case 11:
00168
00169
00170 cwnd_ = ownd_ - sender_ownd*(1-winMult_);
00171 ssthresh_ = int(cwnd_);
00172 if (ssthresh_ < 2)
00173 ssthresh_ = 2;
00174 break;
00175
00176 case 3:
00177 case 13:
00178
00179 cwnd_ = wndInit_;
00180 break;
00181
00182 default:
00183 abort();
00184 }
00185 fcnt_ = 0.;
00186 count_ = 0;
00187 if (sender)
00188 sender->count_ = 0;
00189 }
00190
00191 Segment*
00192 CorresHost::add_pkts(int , int seqno, int sessionSeqno, int daddr, int dport,
00193 int sport, double ts, IntTcpAgent *sender)
00194 {
00195 class Segment *news;
00196
00197 ownd_ += 1;
00198 news = new Segment;
00199 news->seqno_ = seqno;
00200 news->sessionSeqno_ = sessionSeqno;
00201 news->daddr_ = daddr;
00202 news->dport_ = dport;
00203 news->sport_ = sport;
00204 news->ts_ = ts;
00205 news->size_ = 1;
00206 news->dupacks_ = 0;
00207 news->later_acks_ = 0;
00208 news->thresh_dupacks_ = 0;
00209 news->partialack_ = 0;
00210 news->rxmitted_ = 0;
00211 news->sender_ = sender;
00212 seglist_.append(news);
00213 return news;
00214 }
00215
00216 void
00217 CorresHost::adjust_ownd(int size)
00218 {
00219 if (double(owndCorrection_) < size)
00220 ownd_ -= min(double(ownd_), size - double(owndCorrection_));
00221 owndCorrection_ -= min(double(owndCorrection_),size);
00222 if (double(ownd_) < -0.5 || double(owndCorrection_ < -0.5))
00223 printf("In adjust_ownd(): ownd_ = %g owndCorrection_ = %g\n", double(ownd_), double(owndCorrection_));
00224 }
00225
00226 int
00227 CorresHost::clean_segs(int , Packet *pkt, IntTcpAgent *sender, int sessionSeqno, int amt_data_acked)
00228 {
00229 Segment *cur, *prev=NULL, *newseg;
00230 int i;
00231
00232
00233
00234 int latest_susp_loss = rmv_old_segs(pkt, sender, amt_data_acked);
00235
00236
00237
00238
00239
00240 if (amt_data_acked == 0 && latest_susp_loss <= recover_ &&
00241 !dontAdjustOwnd_ && last_cwnd_action_ != CWND_ACTION_TIMEOUT) {
00242 owndCorrection_ += min(double(ownd_),1);
00243 ownd_ -= min(double(ownd_),1);
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 for (i=0; i < rexmtSegCount_; i++) {
00255 int remove_flag = 0;
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 cur = curArray_[i];
00267 prev = prevArray_[i];
00268 if (cur->partialack_ || cur->dupacks_ > 0 ||
00269 cur->sender_->num_thresh_dupack_segs_ > 1 ) {
00270 if (cur->thresh_dupacks_) {
00271 cur->thresh_dupacks_ = 0;
00272 cur->sender_->num_thresh_dupack_segs_--;
00273 }
00274 if (cur->sessionSeqno_ <= recover_ &&
00275 last_cwnd_action_ != CWND_ACTION_TIMEOUT )
00276 dontAdjustOwnd_ = 1;
00277 if ((cur->sessionSeqno_ > recover_) ||
00278 (last_cwnd_action_ == CWND_ACTION_TIMEOUT )
00279 || (proxyopt_ && cur->seqno_ > cur->sender_->recover_)
00280 || (proxyopt_ && cur->sender_->last_cwnd_action_ == CWND_ACTION_TIMEOUT )) {
00281
00282 closecwnd(1, cur->ts_, cur->sender_);
00283 recover_ = sessionSeqno - 1;
00284 last_cwnd_action_ = CWND_ACTION_DUPACK ;
00285 cur->sender_->recover_ = cur->sender_->maxseq_;
00286 cur->sender_->last_cwnd_action_ =
00287 CWND_ACTION_DUPACK ;
00288 dontAdjustOwnd_ = 0;
00289 }
00290 if ((newseg = cur->sender_->rxmit_last(TCP_REASON_DUPACK,
00291 cur->seqno_, cur->sessionSeqno_, cur->ts_))) {
00292 newseg->rxmitted_ = 1;
00293 adjust_ownd(cur->size_);
00294 if (!dontAdjustOwnd_) {
00295 owndCorrection_ +=
00296 min(double(ownd_),cur->dupacks_);
00297 ownd_ -= min(double(ownd_),cur->dupacks_);
00298 }
00299 seglist_.remove(cur, prev);
00300 remove_flag = 1;
00301 delete cur;
00302 }
00303
00304
00305
00306
00307
00308 if (remove_flag && cur == prevArray_[i+1])
00309 prevArray_[i+1] = prev;
00310 }
00311 }
00312 rexmtSegCount_ = 0;
00313 return(0);
00314 }
00315
00316
00317 int
00318 CorresHost::rmv_old_segs(Packet *pkt, IntTcpAgent *sender, int amt_data_acked)
00319 {
00320 Islist_iter<Segment> seg_iter(seglist_);
00321 Segment *cur, *prev=0;
00322 int found = 0;
00323 int done = 0;
00324 int new_data_acked = 0;
00325 int partialack = 0;
00326 int latest_susp_loss = -1;
00327 hdr_tcp *tcph = hdr_tcp::access(pkt);
00328
00329 if (tcph->ts_echo() > lastackTS_)
00330 lastackTS_ = tcph->ts_echo();
00331
00332 while (((cur = seg_iter()) != NULL) &&
00333 (!done || tcph->ts_echo() > cur->ts_)) {
00334 int remove_flag = 0;
00335
00336 if (sender != cur->sender_ && tcph->ts_echo() > cur->ts_) {
00337 if (!disableIntLossRecov_)
00338 cur->later_acks_++;
00339 latest_susp_loss =
00340 max(latest_susp_loss,cur->sessionSeqno_);
00341 dontIncrCwnd_ = 1;
00342 }
00343
00344 else if (sender == cur->sender_) {
00345
00346 if (tcph->seqno() == cur->seqno_ &&
00347 tcph->ts_echo() == cur->ts_)
00348 found = 1;
00349
00350 if (tcph->seqno() >= cur->seqno_) {
00351 adjust_ownd(cur->size_);
00352 seglist_.remove(cur, prev);
00353 remove_flag = 1;
00354 new_data_acked += cur->size_;
00355 if (new_data_acked >= amt_data_acked)
00356 done = 1;
00357 if (prev == cur)
00358 prev = NULL;
00359 if (cur == rtt_seg_)
00360 rtt_seg_ = NULL;
00361 delete cur;
00362 if (seg_iter.get_cur() && prev)
00363 seg_iter.set_cur(prev);
00364 else if (seg_iter.get_cur())
00365 seg_iter.set_cur(seg_iter.get_last());
00366 }
00367
00368
00369 else if (amt_data_acked > 0 &&
00370 tcph->seqno() == cur->seqno_-1 &&
00371 cur->seqno_ <= sender->recover_ &&
00372 sender->last_cwnd_action_ == CWND_ACTION_DUPACK) {
00373 cur->partialack_ = 1;
00374 partialack = 1;
00375 latest_susp_loss =
00376 max(latest_susp_loss,cur->sessionSeqno_);
00377 if (new_data_acked >= amt_data_acked)
00378 done = 1;
00379 dontIncrCwnd_ = 1;
00380 }
00381
00382
00383
00384
00385
00386
00387 else if (!amt_data_acked && !cur->rxmitted_ &&
00388 tcph->seqno() == cur->seqno_-1) {
00389 cur->dupacks_++;
00390 latest_susp_loss =
00391 max(latest_susp_loss,cur->sessionSeqno_);
00392 done = 1;
00393 dontIncrCwnd_ = 1;
00394 }
00395 }
00396 if (cur->dupacks_+cur->later_acks_ >= sender->numdupacks_ &&
00397 !cur->thresh_dupacks_) {
00398 cur->thresh_dupacks_ = 1;
00399 cur->sender_->num_thresh_dupack_segs_++;
00400 }
00401
00402 if (amt_data_acked==0 && tcph->seqno()==cur->seqno_-1)
00403 done = 1;
00404
00405
00406 if (!remove_flag &&
00407 cur->seqno_ == cur->sender_->highest_ack_ + 1 &&
00408 (cur->dupacks_ + cur->later_acks_ >= sender->numdupacks_ ||
00409 cur->partialack_)) {
00410 curArray_[rexmtSegCount_] = cur;
00411 prevArray_[rexmtSegCount_] = prev;
00412 rexmtSegCount_++;
00413 }
00414 if (!remove_flag)
00415 prev = cur;
00416 }
00417
00418 if (partialack && fs_enable_ && fs_mode_) {
00419 timeout(TCP_TIMER_RESET);
00420 rexmtSegCount_ = 0;
00421 }
00422 return latest_susp_loss;
00423 }
00424
00425 void
00426 CorresHost::add_agent(IntTcpAgent *agent, int , double winMult,
00427 int winInc, int )
00428 {
00429 if (nActive_ >= MAX_PARALLEL_CONN) {
00430 printf("In add_agent(): reached limit of number of parallel conn (%d); returning\n", nActive_);
00431 return;
00432 }
00433 nActive_++;
00434 if ((!fixedIw_ && nActive_ > 1) || cwnd_ == 0)
00435 cwnd_ += 1;
00436 wndInit_ = 1;
00437 winMult_ = winMult;
00438 winInc_ = winInc;
00439
00440 conns_.append(agent);
00441 }
00442
00443 int
00444 CorresHost::ok_to_snd(int )
00445 {
00446 if (ownd_ <= -0.5)
00447 printf("In ok_to_snd(): ownd_ = %g owndCorrection_ = %g\n", double(ownd_), double(owndCorrection_));
00448 return (cwnd_ >= ownd_+1);
00449 }
00450
00451
00452
00453
00454