#include <tcp-sink.h>
Inheritance diagram for Sacker:


Definition at line 85 of file tcp-sink.h.
Public Member Functions | |
| void | append_ack (hdr_cmn *, hdr_tcp *, int oldSeqno) const |
| void | configure (TcpSink *) |
| int | ecn_unacked () |
| int | Maxseen () const |
| void | reset () |
| void | resize_buffers (int sz) |
| Sacker () | |
| int | Seqno () const |
| double | ts_to_echo () |
| int | update (int seqno, int numBytes) |
| void | update_ecn_unacked (int value) |
| void | update_ts (int seqno, double ts, int rfc1323=0) |
| ~Sacker () | |
Data Fields | |
| int | last_ack_sent_ |
Protected Member Functions | |
| void | trace (TracedVar *) |
Protected Attributes | |
| int | base_nblocks_ |
| int * | dsacks_ |
| int | ecn_unacked_ |
| int | is_dup_ |
| int | maxseen_ |
| int | next_ |
| int * | seen_ |
| SackStack * | sf_ |
| double | ts_to_echo_ |
| int | wndmask_ |
|
|
Definition at line 87 of file tcp-sink.h. 00087 : base_nblocks_(-1), sf_(0) { };
|
|
|
Definition at line 589 of file tcp-sink.cc. References sf_. 00590 { 00591 delete sf_; 00592 }
|
|
||||||||||||||||
|
Reimplemented from Acker. Definition at line 594 of file tcp-sink.cc. References base_nblocks_, SackStack::cnt(), dsacks_, Scheduler::instance(), Acker::is_dup_, Acker::maxseen_, SackStack::reset(), hdr_tcp::sa_left(), hdr_tcp::sa_right(), Acker::seen_, Acker::Seqno(), sf_, and Acker::wndmask_. 00595 { 00596 // ch and h are the common and tcp headers of the Ack being constructed 00597 // old_seqno is the sequence # of the packet we just got 00598 00599 int sack_index, i, sack_right, sack_left; 00600 int recent_sack_left, recent_sack_right; 00601 00602 int seqno = Seqno(); 00603 // the last in-order packet seen (i.e. the cumulative ACK # - 1) 00604 00605 sack_index = 0; 00606 sack_left = sack_right = -1; 00607 // initialization; sack_index=0 and sack_{left,right}= -1 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 // if the Cumulative ACK seqno is at or beyond the right edge 00614 // of the window, and if the SackStack is not empty, reset it 00615 // (empty it) 00616 else if (( (seqno < maxseen_) || is_dup_ ) && (base_nblocks_ > 0)) { 00617 // Otherwise, if the received packet is to the left of 00618 // the right edge of the receive window (but not at 00619 // the right edge), OR if it is a duplicate, AND we 00620 // can have 1 or more Sack blocks, then execute the 00621 // following, which computes the most recent Sack 00622 // block 00623 00624 if ((*dsacks_) && is_dup_) { 00625 // Record the DSACK Block 00626 h->sa_left(sack_index) = old_seqno; 00627 h->sa_right(sack_index) = old_seqno+1; 00628 // record the block 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 // Build FIRST (traditional) SACK block 00638 00639 // If we already had a DSACK block due to a duplicate 00640 // packet, and if that duplicate packet is in the 00641 // receiver's window (i.e. the packet's sequence 00642 // number is > than the cumulative ACK) then the 00643 // following should find the SACK block it's a subset 00644 // of. If it's <= cum ACK field then the following 00645 // shouldn't record a superset SACK block for it. 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 // look rightward for first hole 00653 // start at the current packet 00654 for (i=old_seqno; i<=maxseen_; i++) { 00655 if (!seen_[i & wndmask_]) { 00656 sack_right=i; 00657 break; 00658 } 00659 } 00660 00661 // if there's no hole set the right edge of the sack 00662 // to be the next expected packet 00663 if (sack_right == -1) { 00664 sack_right = maxseen_+1; 00665 } 00666 00667 // if the current packet's seqno is smaller than the 00668 // left edge of the window, set the sack_left to 0 00669 if (old_seqno <= seqno) { 00670 sack_left = 0; 00671 // don't record/send the block 00672 } else { 00673 // look leftward from right edge for first hole 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 // printf("pkt_seqno: %i cuml_seqno: %i sa_idx: %i sa_left: %i sa_right: %i\n" ,old_seqno, seqno, sack_index, sack_left, sack_right); 00684 // record the block 00685 sack_index++; 00686 } 00687 00688 recent_sack_left = sack_left; 00689 recent_sack_right = sack_right; 00690 00691 // first sack block is built, check the others 00692 // make sure that if max_sack_blocks has been made 00693 // large from tcl we don't over-run the stuff we 00694 // allocated in Sacker::Sacker() 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 // no more history 00702 if (sack_left < 0 || sack_right < 0 || 00703 sack_right > maxseen_ + 1) 00704 break; 00705 00706 // newest ack "covers up" this one 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 // printf("pkt_seqno: %i cuml_seqno: %i sa_idx: %i sa_left: %i sa_right: %i\n" ,old_seqno, seqno, sack_index, sack_left, sack_right); 00718 00719 // store the old sack (i.e. move it down one) 00720 sack_index++; 00721 k++; 00722 } 00723 00724 00725 if (old_seqno > seqno) { 00726 /* put most recent block onto stack */ 00727 sf_->push(); 00728 // this just moves things down 1 from the 00729 // beginning, but it doesn't push any values 00730 // on the stack 00731 sf_->head_left() = recent_sack_left; 00732 sf_->head_right() = recent_sack_right; 00733 // this part stores the left/right values at 00734 // the top of the stack (slot 0) 00735 } 00736 00737 } // this '}' is for the DSACK base_nblocks_ >= test; 00738 // (didn't feel like re-indenting all the code and 00739 // causing a large diff) 00740 00741 } 00742 h->sa_length() = sack_index; 00743 // set the Length of the sack stack in the header 00744 ch->size() += sack_index * 8; 00745 // change the size of the common header to account for the 00746 // Sack strings (2 4-byte words for each element) 00747 }
Here is the call graph for this function: ![]() |
|
|
Definition at line 548 of file tcp-sink.cc. References base_nblocks_, dsacks_, TcpSink::generate_dsacks_, TcpSink::max_sack_blocks_, NSA, and sf_. Referenced by Sack1DelAckTcpSinkClass::create(), and Sack1TcpSinkClass::create(). 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 }
|
|
|
Definition at line 66 of file tcp-sink.h. References Acker::ecn_unacked_. Referenced by XcpSink::ack(). 00066 { return ecn_unacked_;}
|
|
|
Definition at line 67 of file tcp-sink.h. References Acker::maxseen_. 00067 { return (maxseen_); }
|
|
|
Reimplemented from Acker. Definition at line 583 of file tcp-sink.cc. References Acker::reset(), SackStack::reset(), and sf_. 00584 { 00585 sf_->reset(); 00586 Acker::reset(); 00587 }
Here is the call graph for this function: ![]() |
|
|
Definition at line 66 of file tcp-sink.cc. References Acker::maxseen_, Acker::next_, Acker::seen_, and Acker::wndmask_. Referenced by Acker::update(). 00066 { 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 }
|
|
|
Definition at line 62 of file tcp-sink.h. References Acker::next_. Referenced by XcpSink::ack(), and append_ack(). 00062 { return (next_ - 1); }
|
|
|
Definition at line 567 of file tcp-sink.cc. References base_nblocks_, NSA, and sf_. 00568 { 00569 // we come here if "nblocks" changed 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 }
|
|
|
Definition at line 65 of file tcp-sink.h. References Acker::ts_to_echo_. Referenced by XcpSink::ack(). 00065 { return ts_to_echo_;}
|
|
||||||||||||
|
Definition at line 100 of file tcp-sink.cc. References FALSE, Scheduler::instance(), Acker::is_dup_, Acker::maxseen_, Acker::next_, Acker::resize_buffers(), Acker::seen_, TRUE, and Acker::wndmask_. Referenced by TcpAsymSink::recv(). 00101 { 00102 bool just_marked_as_seen = FALSE; 00103 is_dup_ = FALSE; 00104 // start by assuming the segment hasn't been received before 00105 if (numBytes <= 0) 00106 printf("Error, received TCP packet size <= 0\n"); 00107 int numToDeliver = 0; 00108 while(seq + 1 - next_ >= wndmask_) { 00109 // next_ is next packet expected; wndmask_ is the maximum 00110 // window size minus 1; if somehow the seqno of the 00111 // packet is greater than the one we're expecting+wndmask_, 00112 // then resize the buffer. 00113 resize_buffers((wndmask_+1)*2); 00114 } 00115 00116 if (seq > maxseen_) { 00117 // the packet is the highest one we've seen so far 00118 int i; 00119 for (i = maxseen_ + 1; i < seq; ++i) 00120 seen_[i & wndmask_] = 0; 00121 // we record the packets between the old maximum and 00122 // the new max as being "unseen" i.e. 0 bytes of each 00123 // packet have been received 00124 maxseen_ = seq; 00125 seen_[maxseen_ & wndmask_] = numBytes; 00126 // store how many bytes have been seen for this packet 00127 seen_[(maxseen_ + 1) & wndmask_] = 0; 00128 // clear the array entry for the packet immediately 00129 // after this one 00130 just_marked_as_seen = TRUE; 00131 // necessary so this packet isn't confused as being a duplicate 00132 } 00133 int next = next_; 00134 if (seq < next) { 00135 // Duplicate packet case 1: the packet is to the left edge of 00136 // the receive window; therefore we must have seen it 00137 // before 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 // next is the left edge of the recv window; maxseen_ 00146 // is the right edge; execute this block if there are 00147 // missing packets in the recv window AND if current 00148 // packet falls within those gaps 00149 00150 if (seen_[seq & wndmask_] && !just_marked_as_seen) { 00151 // Duplicate case 2: the segment has already been 00152 // recorded as being received (AND not because we just 00153 // marked it as such) 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 // record the packet as being seen 00161 while (seen_[next & wndmask_]) { 00162 // this loop first gets executed if seq==next; 00163 // i.e., this is the next packet in order that 00164 // we've been waiting for. the loop sets how 00165 // many bytes we can now deliver to the 00166 // application, due to this packet arriving 00167 // (and the prior arrival of any segments 00168 // immediately to the right) 00169 00170 numToDeliver += seen_[next & wndmask_]; 00171 ++next; 00172 } 00173 next_ = next; 00174 // store the new left edge of the window 00175 } 00176 return numToDeliver; 00177 }
Here is the call graph for this function: ![]() |
|
|
Definition at line 232 of file tcp-sink.cc. References Acker::ecn_unacked_. Referenced by XcpSink::ack(). 00233 { 00234 ecn_unacked_ = value; 00235 }
|
|
||||||||||||||||
|
Definition at line 87 of file tcp-sink.cc. References Acker::last_ack_sent_, and Acker::ts_to_echo_. Referenced by TcpAsymSink::recv(). 00088 { 00089 // update timestamp if segment advances with ACK. 00090 // Code changed by Andrei Gurtov. 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 //rfc1323-bis, update timestamps from duplicate segments 00095 ts_to_echo_ = ts; 00096 }
|
|
|
Definition at line 93 of file tcp-sink.h. Referenced by append_ack(), configure(), and trace(). |
|
|
Definition at line 94 of file tcp-sink.h. Referenced by append_ack(), and configure(). |
|
|
Definition at line 74 of file tcp-sink.h. Referenced by Acker::ecn_unacked(), and Acker::update_ecn_unacked(). |
|
|
Definition at line 78 of file tcp-sink.h. Referenced by append_ack(), and Acker::update(). |
|
|
Definition at line 80 of file tcp-sink.h. Referenced by XcpSink::ack(), and Acker::update_ts(). |
|
|
Definition at line 72 of file tcp-sink.h. Referenced by append_ack(), Acker::Maxseen(), Acker::reset(), Acker::resize_buffers(), and Acker::update(). |
|
|
Definition at line 71 of file tcp-sink.h. Referenced by Acker::reset(), Acker::resize_buffers(), Acker::Seqno(), and Acker::update(). |
|
|
Definition at line 76 of file tcp-sink.h. Referenced by Acker::Acker(), append_ack(), Acker::reset(), Acker::resize_buffers(), Acker::update(), and Acker::~Acker(). |
|
|
Definition at line 95 of file tcp-sink.h. Referenced by append_ack(), configure(), reset(), trace(), and ~Sacker(). |
|
|
Definition at line 77 of file tcp-sink.h. Referenced by Acker::ts_to_echo(), and Acker::update_ts(). |
|
|
Definition at line 73 of file tcp-sink.h. Referenced by append_ack(), Acker::reset(), Acker::resize_buffers(), and Acker::update(). |
1.4.6