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 #include "flags.h"
00038 #include "ip.h"
00039 #include "tcp-sink.h"
00040 #include "hdr_qs.h"
00041
00042 static class TcpSinkClass : public TclClass {
00043 public:
00044 TcpSinkClass() : TclClass("Agent/TCPSink") {}
00045 TclObject* create(int, const char*const*) {
00046 return (new TcpSink(new Acker));
00047 }
00048 } class_tcpsink;
00049
00050 Acker::Acker() : next_(0), maxseen_(0), wndmask_(MWM), ecn_unacked_(0),
00051 ts_to_echo_(0), last_ack_sent_(0)
00052 {
00053 seen_ = new int[MWS];
00054 memset(seen_, 0, (sizeof(int) * (MWS)));
00055 }
00056
00057 void Acker::reset()
00058 {
00059 next_ = 0;
00060 maxseen_ = 0;
00061 memset(seen_, 0, (sizeof(int) * (wndmask_ + 1)));
00062 }
00063
00064
00065
00066 void Acker::resize_buffers(int sz) {
00067 int* new_seen = new int[sz];
00068 int new_wndmask = sz - 1;
00069
00070 if(!new_seen){
00071 fprintf(stderr, "Unable to allocate buffer seen_[%i]\n", sz);
00072 exit(1);
00073 }
00074
00075 memset(new_seen, 0, (sizeof(int) * (sz)));
00076
00077 for(int i = next_; i <= maxseen_+1; i++){
00078 new_seen[i & new_wndmask] = seen_[i&wndmask_];
00079 }
00080
00081 delete[] seen_;
00082 seen_ = new_seen;
00083 wndmask_ = new_wndmask;
00084 return;
00085 }
00086
00087 void Acker::update_ts(int seqno, double ts, int rfc1323)
00088 {
00089
00090
00091 if (rfc1323 && seqno == last_ack_sent_ + 1)
00092 ts_to_echo_ = ts;
00093 else if (ts >= ts_to_echo_ && seqno <= last_ack_sent_ + 1)
00094
00095 ts_to_echo_ = ts;
00096 }
00097
00098
00099
00100 int Acker::update(int seq, int numBytes)
00101 {
00102 bool just_marked_as_seen = FALSE;
00103 is_dup_ = FALSE;
00104
00105 if (numBytes <= 0)
00106 printf("Error, received TCP packet size <= 0\n");
00107 int numToDeliver = 0;
00108 while(seq + 1 - next_ >= wndmask_) {
00109
00110
00111
00112
00113 resize_buffers((wndmask_+1)*2);
00114 }
00115
00116 if (seq > maxseen_) {
00117
00118 int i;
00119 for (i = maxseen_ + 1; i < seq; ++i)
00120 seen_[i & wndmask_] = 0;
00121
00122
00123
00124 maxseen_ = seq;
00125 seen_[maxseen_ & wndmask_] = numBytes;
00126
00127 seen_[(maxseen_ + 1) & wndmask_] = 0;
00128
00129
00130 just_marked_as_seen = TRUE;
00131
00132 }
00133 int next = next_;
00134 if (seq < next) {
00135
00136
00137
00138 #ifdef DEBUGDSACK
00139 printf("%f\t Received duplicate packet %d\n",Scheduler::instance().clock(),seq);
00140 #endif
00141 is_dup_ = TRUE;
00142 }
00143
00144 if (seq >= next && seq <= maxseen_) {
00145
00146
00147
00148
00149
00150 if (seen_[seq & wndmask_] && !just_marked_as_seen) {
00151
00152
00153
00154 is_dup_ = TRUE;
00155 #ifdef DEBUGDSACK
00156 printf("%f\t Received duplicate packet %d\n",Scheduler::instance().clock(),seq);
00157 #endif
00158 }
00159 seen_[seq & wndmask_] = numBytes;
00160
00161 while (seen_[next & wndmask_]) {
00162
00163
00164
00165
00166
00167
00168
00169
00170 numToDeliver += seen_[next & wndmask_];
00171 ++next;
00172 }
00173 next_ = next;
00174
00175 }
00176 return numToDeliver;
00177 }
00178
00179 TcpSink::TcpSink(Acker* acker) : Agent(PT_ACK), acker_(acker), save_(NULL),
00180 lastreset_(0.0)
00181 {
00182 bytes_ = 0;
00183 bind("bytes_", &bytes_);
00184
00185
00186
00187
00188
00189 #if defined(TCP_DELAY_BIND_ALL) && 0
00190 #else
00191 bind("maxSackBlocks_", &max_sack_blocks_);
00192 #endif
00193 }
00194
00195 void
00196 TcpSink::delay_bind_init_all()
00197 {
00198 delay_bind_init_one("packetSize_");
00199 delay_bind_init_one("ts_echo_bugfix_");
00200 delay_bind_init_one("ts_echo_rfc1323_");
00201 delay_bind_init_one("bytes_");
00202 delay_bind_init_one("generateDSacks_");
00203 delay_bind_init_one("qs_enabled_");
00204 delay_bind_init_one("RFC2581_immediate_ack_");
00205 #if defined(TCP_DELAY_BIND_ALL) && 0
00206 delay_bind_init_one("maxSackBlocks_");
00207 #endif
00208
00209 Agent::delay_bind_init_all();
00210 }
00211
00212 int
00213 TcpSink::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
00214 {
00215 if (delay_bind(varName, localName, "packetSize_", &size_, tracer)) return TCL_OK;
00216 if (delay_bind_bool(varName, localName, "ts_echo_bugfix_", &ts_echo_bugfix_, tracer)) return TCL_OK;
00217 if (delay_bind_bool(varName, localName, "ts_echo_rfc1323_", &ts_echo_rfc1323_, tracer)) return TCL_OK;
00218 if (delay_bind_bool(varName, localName, "generateDSacks_", &generate_dsacks_, tracer)) return TCL_OK;
00219 if (delay_bind_bool(varName, localName, "qs_enabled_", &qs_enabled_, tracer)) return TCL_OK;
00220 if (delay_bind_bool(varName, localName, "RFC2581_immediate_ack_", &RFC2581_immediate_ack_, tracer)) return TCL_OK;
00221 #if defined(TCP_DELAY_BIND_ALL) && 0
00222 if (delay_bind(varName, localName, "maxSackBlocks_", &max_sack_blocks_, tracer)) return TCL_OK;
00223 #endif
00224
00225 return Agent::delay_bind_dispatch(varName, localName, tracer);
00226 }
00227
00228 void Acker::append_ack(hdr_cmn*, hdr_tcp*, int) const
00229 {
00230 }
00231
00232 void Acker::update_ecn_unacked(int value)
00233 {
00234 ecn_unacked_ = value;
00235 }
00236
00237 int TcpSink::command(int argc, const char*const* argv)
00238 {
00239 if (argc == 2) {
00240 if (strcmp(argv[1], "reset") == 0) {
00241 reset();
00242 return (TCL_OK);
00243 }
00244 if (strcmp(argv[1], "resize_buffers") == 0) {
00245
00246 fprintf(stderr,"DEPRECIATED: resize_buffers\n");
00247 return (TCL_OK);
00248 }
00249 }
00250
00251 return (Agent::command(argc, argv));
00252 }
00253
00254 void TcpSink::reset()
00255 {
00256 acker_->reset();
00257 save_ = NULL;
00258 lastreset_ = Scheduler::instance().clock();
00259
00260 }
00261
00262 void TcpSink::ack(Packet* opkt)
00263 {
00264 Packet* npkt = allocpkt();
00265
00266
00267 double now = Scheduler::instance().clock();
00268
00269 hdr_tcp *otcp = hdr_tcp::access(opkt);
00270 hdr_ip *oiph = hdr_ip::access(opkt);
00271 hdr_tcp *ntcp = hdr_tcp::access(npkt);
00272
00273 if (qs_enabled_) {
00274
00275 hdr_qs *oqsh = hdr_qs::access(opkt);
00276 hdr_qs *nqsh = hdr_qs::access(npkt);
00277 if (otcp->seqno() == 0 && oqsh->flag() == QS_REQUEST) {
00278 nqsh->flag() = QS_RESPONSE;
00279 nqsh->ttl() = (oiph->ttl() - oqsh->ttl()) % 256;
00280 nqsh->rate() = (oqsh->rate() < MWS) ? oqsh->rate() : MWS;
00281 }
00282 else {
00283 nqsh->flag() = QS_DISABLE;
00284 }
00285 }
00286
00287
00288
00289 ntcp->seqno() = acker_->Seqno();
00290
00291
00292 ntcp->ts() = now;
00293
00294
00295 if (ts_echo_bugfix_)
00296 ntcp->ts_echo() = acker_->ts_to_echo();
00297 else
00298 ntcp->ts_echo() = otcp->ts();
00299
00300
00301 hdr_ip* oip = hdr_ip::access(opkt);
00302 hdr_ip* nip = hdr_ip::access(npkt);
00303
00304 nip->flowid() = oip->flowid();
00305
00306
00307 hdr_flags* of = hdr_flags::access(opkt);
00308 hdr_flags* nf = hdr_flags::access(npkt);
00309 hdr_flags* sf;
00310 if (save_ != NULL)
00311 sf = hdr_flags::access(save_);
00312 else
00313 sf = 0;
00314
00315 if ( (sf != 0 && sf->cong_action()) || of->cong_action() )
00316
00317 acker_->update_ecn_unacked(0);
00318 if ( (sf != 0 && sf->ect() && sf->ce()) ||
00319 (of->ect() && of->ce()) )
00320
00321 acker_->update_ecn_unacked(1);
00322 if ( (sf != 0 && sf->ect()) || of->ect() )
00323
00324 nf->ecnecho() = acker_->ecn_unacked();
00325 if (!of->ect() && of->ecnecho() ||
00326 (sf != 0 && !sf->ect() && sf->ecnecho()) )
00327
00328
00329
00330
00331 nf->ecnecho() = 1;
00332 acker_->append_ack(hdr_cmn::access(npkt),
00333 ntcp, otcp->seqno());
00334 add_to_ack(npkt);
00335
00336
00337
00338 acker_->last_ack_sent_ = ntcp->seqno();
00339
00340
00341 send(npkt, 0);
00342
00343 }
00344
00345 void TcpSink::add_to_ack(Packet*)
00346 {
00347 return;
00348 }
00349
00350
00351 void TcpSink::recv(Packet* pkt, Handler*)
00352 {
00353 int numToDeliver;
00354 int numBytes = hdr_cmn::access(pkt)->size();
00355
00356 hdr_tcp *th = hdr_tcp::access(pkt);
00357
00358 if (th->ts() < lastreset_) {
00359
00360 Packet::free(pkt);
00361 return;
00362 }
00363 acker_->update_ts(th->seqno(),th->ts(),ts_echo_rfc1323_);
00364
00365
00366 numToDeliver = acker_->update(th->seqno(), numBytes);
00367
00368
00369
00370 if (numToDeliver) {
00371 bytes_ += numToDeliver;
00372 recvBytes(numToDeliver);
00373 }
00374
00375 ack(pkt);
00376
00377 Packet::free(pkt);
00378
00379 }
00380
00381 static class DelSinkClass : public TclClass {
00382 public:
00383 DelSinkClass() : TclClass("Agent/TCPSink/DelAck") {}
00384 TclObject* create(int, const char*const*) {
00385 return (new DelAckSink(new Acker));
00386 }
00387 } class_delsink;
00388
00389 DelAckSink::DelAckSink(Acker* acker) : TcpSink(acker), delay_timer_(this)
00390 {
00391 bind_time("interval_", &interval_);
00392
00393
00394 }
00395
00396 void DelAckSink::reset() {
00397 if (delay_timer_.status() == TIMER_PENDING)
00398 delay_timer_.cancel();
00399 TcpSink::reset();
00400 }
00401
00402 void DelAckSink::recv(Packet* pkt, Handler*)
00403 {
00404 int numToDeliver;
00405 int numBytes = hdr_cmn::access(pkt)->size();
00406 hdr_tcp *th = hdr_tcp::access(pkt);
00407
00408 if (th->ts() < lastreset_) {
00409
00410 Packet::free(pkt);
00411 return;
00412 }
00413 acker_->update_ts(th->seqno(),th->ts(),ts_echo_rfc1323_);
00414 numToDeliver = acker_->update(th->seqno(), numBytes);
00415 if (numToDeliver) {
00416 bytes_ += numToDeliver;
00417 recvBytes(numToDeliver);
00418 }
00419
00420
00421
00422 if (delay_timer_.status() != TIMER_PENDING &&
00423 th->seqno() == acker_->Seqno()) {
00424
00425
00426
00427
00428
00429
00430
00431
00432 if (RFC2581_immediate_ack_ &&
00433 (th->seqno() < acker_->Maxseen())) {
00434
00435
00436 } else {
00437
00438 save_ = pkt;
00439 delay_timer_.resched(interval_);
00440 return;
00441 }
00442 }
00443
00444 if (delay_timer_.status() == TIMER_PENDING)
00445 delay_timer_.cancel();
00446 ack(pkt);
00447 if (save_ != NULL) {
00448 Packet::free(save_);
00449 save_ = NULL;
00450 }
00451
00452 Packet::free(pkt);
00453 }
00454
00455 void DelAckSink::timeout(int)
00456 {
00457
00458 if ( save_ != NULL ) {
00459 Packet* pkt = save_;
00460 ack(pkt);
00461 save_ = NULL;
00462 Packet::free(pkt);
00463 }
00464 }
00465
00466 void DelayTimer::expire(Event* ) {
00467 a_->timeout(0);
00468 }
00469
00470
00471
00472 class SackStack {
00473 protected:
00474 int size_;
00475 int cnt_;
00476 struct Sf_Entry {
00477 int left_;
00478 int right_;
00479 } *SFE_;
00480 public:
00481 SackStack(int);
00482 ~SackStack();
00483 int& head_right(int n = 0) { return SFE_[n].right_; }
00484 int& head_left(int n = 0) { return SFE_[n].left_; }
00485 int cnt() { return cnt_; }
00486 void reset() {
00487 register int i;
00488 for (i = 0; i < cnt_; i++)
00489 SFE_[i].left_ = SFE_[i].right_ = -1;
00490
00491 cnt_ = 0;
00492 }
00493
00494 inline void push(int n = 0) {
00495 if (cnt_ >= size_) cnt_ = size_ - 1;
00496 register int i;
00497 for (i = cnt_-1; i >= n; i--)
00498 SFE_[i+1] = SFE_[i];
00499 cnt_++;
00500 }
00501
00502 inline void pop(int n = 0) {
00503 register int i;
00504 for (i = n; i < cnt_-1; i++)
00505 SFE_[i] = SFE_[i+1];
00506 SFE_[i].left_ = SFE_[i].right_ = -1;
00507 cnt_--;
00508 }
00509 };
00510
00511 SackStack::SackStack(int sz)
00512 {
00513 register int i;
00514 size_ = sz;
00515 SFE_ = new Sf_Entry[sz];
00516 for (i = 0; i < sz; i++)
00517 SFE_[i].left_ = SFE_[i].right_ = -1;
00518 cnt_ = 0;
00519 }
00520
00521 SackStack::~SackStack()
00522 {
00523 delete SFE_;
00524 }
00525
00526 static class Sack1TcpSinkClass : public TclClass {
00527 public:
00528 Sack1TcpSinkClass() : TclClass("Agent/TCPSink/Sack1") {}
00529 TclObject* create(int, const char*const*) {
00530 Sacker* sacker = new Sacker;
00531 TcpSink* sink = new TcpSink(sacker);
00532 sacker->configure(sink);
00533 return (sink);
00534 }
00535 } class_sack1tcpsink;
00536
00537 static class Sack1DelAckTcpSinkClass : public TclClass {
00538 public:
00539 Sack1DelAckTcpSinkClass() : TclClass("Agent/TCPSink/Sack1/DelAck") {}
00540 TclObject* create(int, const char*const*) {
00541 Sacker* sacker = new Sacker;
00542 TcpSink* sink = new DelAckSink(sacker);
00543 sacker->configure(sink);
00544 return (sink);
00545 }
00546 } class_sack1delacktcpsink;
00547
00548 void Sacker::configure(TcpSink *sink)
00549 {
00550 if (sink == NULL) {
00551 fprintf(stderr, "warning: Sacker::configure(): no TCP sink!\n");
00552 return;
00553 }
00554
00555 TracedInt& nblocks = sink->max_sack_blocks_;
00556 if (int(nblocks) > NSA) {
00557 fprintf(stderr, "warning(Sacker::configure): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(nblocks));
00558 nblocks = NSA;
00559 }
00560 sf_ = new SackStack(int(nblocks));
00561 nblocks.tracer(this);
00562 base_nblocks_ = int(nblocks);
00563 dsacks_ = &(sink->generate_dsacks_);
00564 }
00565
00566 void
00567 Sacker::trace(TracedVar *v)
00568 {
00569
00570 TracedInt* ti = (TracedInt*) v;
00571
00572 if (int(*ti) > NSA) {
00573 fprintf(stderr, "warning(Sacker::trace): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(*ti));
00574 *ti = NSA;
00575 }
00576
00577 int newval = int(*ti);
00578 delete sf_;
00579 sf_ = new SackStack(newval);
00580 base_nblocks_ = newval;
00581 }
00582
00583 void Sacker::reset()
00584 {
00585 sf_->reset();
00586 Acker::reset();
00587 }
00588
00589 Sacker::~Sacker()
00590 {
00591 delete sf_;
00592 }
00593
00594 void Sacker::append_ack(hdr_cmn* ch, hdr_tcp* h, int old_seqno) const
00595 {
00596
00597
00598
00599 int sack_index, i, sack_right, sack_left;
00600 int recent_sack_left, recent_sack_right;
00601
00602 int seqno = Seqno();
00603
00604
00605 sack_index = 0;
00606 sack_left = sack_right = -1;
00607
00608
00609 if (old_seqno < 0) {
00610 printf("Error: invalid packet number %d\n", old_seqno);
00611 } else if (seqno >= maxseen_ && (sf_->cnt() != 0))
00612 sf_->reset();
00613
00614
00615
00616 else if (( (seqno < maxseen_) || is_dup_ ) && (base_nblocks_ > 0)) {
00617
00618
00619
00620
00621
00622
00623
00624 if ((*dsacks_) && is_dup_) {
00625
00626 h->sa_left(sack_index) = old_seqno;
00627 h->sa_right(sack_index) = old_seqno+1;
00628
00629 sack_index++;
00630 #ifdef DEBUGDSACK
00631 printf("%f\t Generating D-SACK for packet %d\n", Scheduler::instance().clock(),old_seqno);
00632 #endif
00633
00634
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 if (sack_index >= base_nblocks_) {
00648 printf("Error: can't use DSACK with less than 2 SACK blocks\n");
00649 } else {
00650 sack_right=-1;
00651
00652
00653
00654 for (i=old_seqno; i<=maxseen_; i++) {
00655 if (!seen_[i & wndmask_]) {
00656 sack_right=i;
00657 break;
00658 }
00659 }
00660
00661
00662
00663 if (sack_right == -1) {
00664 sack_right = maxseen_+1;
00665 }
00666
00667
00668
00669 if (old_seqno <= seqno) {
00670 sack_left = 0;
00671
00672 } else {
00673
00674 for (i = sack_right-1; i > seqno; i--) {
00675 if (!seen_[i & wndmask_]) {
00676 sack_left = i+1;
00677 break;
00678 }
00679 }
00680 h->sa_left(sack_index) = sack_left;
00681 h->sa_right(sack_index) = sack_right;
00682
00683
00684
00685 sack_index++;
00686 }
00687
00688 recent_sack_left = sack_left;
00689 recent_sack_right = sack_right;
00690
00691
00692
00693
00694
00695 int k = 0;
00696 while (sack_index < base_nblocks_) {
00697
00698 sack_left = sf_->head_left(k);
00699 sack_right = sf_->head_right(k);
00700
00701
00702 if (sack_left < 0 || sack_right < 0 ||
00703 sack_right > maxseen_ + 1)
00704 break;
00705
00706
00707
00708 if (recent_sack_left <= sack_left &&
00709 recent_sack_right >= sack_right) {
00710 sf_->pop(k);
00711 continue;
00712 }
00713
00714 h->sa_left(sack_index) = sack_left;
00715 h->sa_right(sack_index) = sack_right;
00716
00717
00718
00719
00720 sack_index++;
00721 k++;
00722 }
00723
00724
00725 if (old_seqno > seqno) {
00726
00727 sf_->push();
00728
00729
00730
00731 sf_->head_left() = recent_sack_left;
00732 sf_->head_right() = recent_sack_right;
00733
00734
00735 }
00736
00737 }
00738
00739
00740
00741 }
00742 h->sa_length() = sack_index;
00743
00744 ch->size() += sack_index * 8;
00745
00746
00747 }