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


Public Member Functions | |
| Sacker () | |
| ~Sacker () | |
| void | append_ack (hdr_cmn *, hdr_tcp *, int oldSeqno) const |
| void | reset () |
| void | configure (TcpSink *) |
| void | update_ts (int seqno, double ts) |
| int | update (int seqno, int numBytes) |
| void | update_ecn_unacked (int value) |
| int | Seqno () const |
| double | ts_to_echo () |
| int | ecn_unacked () |
| int | Maxseen () const |
| void | resize_buffers (int sz) |
Protected Member Functions | |
| void | trace (TracedVar *) |
Protected Attributes | |
| int | base_nblocks_ |
| int * | dsacks_ |
| SackStack * | sf_ |
| int | next_ |
| int | maxseen_ |
| int | wndmask_ |
| int | ecn_unacked_ |
| int * | seen_ |
| double | ts_to_echo_ |
| int | is_dup_ |
|
|
Definition at line 85 of file tcp-sink.h. References base_nblocks_, and sf_.
00085 : base_nblocks_(-1), sf_(0) { }; |
|
|
Definition at line 572 of file tcp-sink.cc. References sf_.
00573 {
00574 delete sf_;
00575 }
|
|
||||||||||||||||
|
Reimplemented from Acker. Definition at line 577 of file tcp-sink.cc. References base_nblocks_, SackStack::cnt(), SackStack::head_left(), SackStack::head_right(), Scheduler::instance(), Acker::is_dup_, Acker::maxseen_, SackStack::pop(), SackStack::push(), SackStack::reset(), hdr_tcp::sa_left(), hdr_tcp::sa_length(), hdr_tcp::sa_right(), Acker::seen_, Acker::Seqno(), sf_, hdr_cmn::size(), and Acker::wndmask_.
00578 {
00579 // ch and h are the common and tcp headers of the Ack being constructed
00580 // old_seqno is the sequence # of the packet we just got
00581
00582 int sack_index, i, sack_right, sack_left;
00583 int recent_sack_left, recent_sack_right;
00584
00585 int seqno = Seqno();
00586 // the last in-order packet seen (i.e. the cumulative ACK # - 1)
00587
00588 sack_index = 0;
00589 sack_left = sack_right = -1;
00590 // initialization; sack_index=0 and sack_{left,right}= -1
00591
00592 if (old_seqno < 0) {
00593 printf("Error: invalid packet number %d\n", old_seqno);
00594 } else if (seqno >= maxseen_ && (sf_->cnt() != 0))
00595 sf_->reset();
00596 // if the Cumulative ACK seqno is at or beyond the right edge
00597 // of the window, and if the SackStack is not empty, reset it
00598 // (empty it)
00599 else if (( (seqno < maxseen_) || is_dup_ ) && (base_nblocks_ > 0)) {
00600 // Otherwise, if the received packet is to the left of
00601 // the right edge of the receive window (but not at
00602 // the right edge), OR if it is a duplicate, AND we
00603 // can have 1 or more Sack blocks, then execute the
00604 // following, which computes the most recent Sack
00605 // block
00606
00607 if ((*dsacks_) && is_dup_) {
00608 // Record the DSACK Block
00609 h->sa_left(sack_index) = old_seqno;
00610 h->sa_right(sack_index) = old_seqno+1;
00611 // record the block
00612 sack_index++;
00613 #ifdef DEBUGDSACK
00614 printf("%f\t Generating D-SACK for packet %d\n", Scheduler::instance().clock(),old_seqno);
00615 #endif
00616
00617
00618 }
00619
00620 // Build FIRST (traditional) SACK block
00621
00622 // If we already had a DSACK block due to a duplicate
00623 // packet, and if that duplicate packet is in the
00624 // receiver's window (i.e. the packet's sequence
00625 // number is > than the cumulative ACK) then the
00626 // following should find the SACK block it's a subset
00627 // of. If it's <= cum ACK field then the following
00628 // shouldn't record a superset SACK block for it.
00629
00630 if (sack_index >= base_nblocks_) {
00631 printf("Error: can't use DSACK with less than 2 SACK blocks\n");
00632 } else {
00633 sack_right=-1;
00634
00635 // look rightward for first hole
00636 // start at the current packet
00637 for (i=old_seqno; i<=maxseen_; i++) {
00638 if (!seen_[i & wndmask_]) {
00639 sack_right=i;
00640 break;
00641 }
00642 }
00643
00644 // if there's no hole set the right edge of the sack
00645 // to be the next expected packet
00646 if (sack_right == -1) {
00647 sack_right = maxseen_+1;
00648 }
00649
00650 // if the current packet's seqno is smaller than the
00651 // left edge of the window, set the sack_left to 0
00652 if (old_seqno <= seqno) {
00653 sack_left = 0;
00654 // don't record/send the block
00655 } else {
00656 // look leftward from right edge for first hole
00657 for (i = sack_right-1; i > seqno; i--) {
00658 if (!seen_[i & wndmask_]) {
00659 sack_left = i+1;
00660 break;
00661 }
00662 }
00663 h->sa_left(sack_index) = sack_left;
00664 h->sa_right(sack_index) = sack_right;
00665
00666 // 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);
00667 // record the block
00668 sack_index++;
00669 }
00670
00671 recent_sack_left = sack_left;
00672 recent_sack_right = sack_right;
00673
00674 // first sack block is built, check the others
00675 // make sure that if max_sack_blocks has been made
00676 // large from tcl we don't over-run the stuff we
00677 // allocated in Sacker::Sacker()
00678 int k = 0;
00679 while (sack_index < base_nblocks_) {
00680
00681 sack_left = sf_->head_left(k);
00682 sack_right = sf_->head_right(k);
00683
00684 // no more history
00685 if (sack_left < 0 || sack_right < 0 ||
00686 sack_right > maxseen_ + 1)
00687 break;
00688
00689 // newest ack "covers up" this one
00690
00691 if (recent_sack_left <= sack_left &&
00692 recent_sack_right >= sack_right) {
00693 sf_->pop(k);
00694 continue;
00695 }
00696
00697 h->sa_left(sack_index) = sack_left;
00698 h->sa_right(sack_index) = sack_right;
00699
00700 // 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);
00701
00702 // store the old sack (i.e. move it down one)
00703 sack_index++;
00704 k++;
00705 }
00706
00707
00708 if (old_seqno > seqno) {
00709 /* put most recent block onto stack */
00710 sf_->push();
00711 // this just moves things down 1 from the
00712 // beginning, but it doesn't push any values
00713 // on the stack
00714 sf_->head_left() = recent_sack_left;
00715 sf_->head_right() = recent_sack_right;
00716 // this part stores the left/right values at
00717 // the top of the stack (slot 0)
00718 }
00719
00720 } // this '}' is for the DSACK base_nblocks_ >= test;
00721 // (didn't feel like re-indenting all the code and
00722 // causing a large diff)
00723
00724 }
00725 h->sa_length() = sack_index;
00726 // set the Length of the sack stack in the header
00727 ch->size() += sack_index * 8;
00728 // change the size of the common header to account for the
00729 // Sack strings (2 4-byte words for each element)
00730 }
|
Here is the call graph for this function:

|
|
Definition at line 531 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().
00532 {
00533 if (sink == NULL) {
00534 fprintf(stderr, "warning: Sacker::configure(): no TCP sink!\n");
00535 return;
00536 }
00537
00538 TracedInt& nblocks = sink->max_sack_blocks_;
00539 if (int(nblocks) > NSA) {
00540 fprintf(stderr, "warning(Sacker::configure): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(nblocks));
00541 nblocks = NSA;
00542 }
00543 sf_ = new SackStack(int(nblocks));
00544 nblocks.tracer(this);
00545 base_nblocks_ = int(nblocks);
00546 dsacks_ = &(sink->generate_dsacks_);
00547 }
|
|
|
Definition at line 66 of file tcp-sink.h. References Acker::ecn_unacked_. Referenced by TcpSink::ack(), and QSTcpSink::ack().
00066 { return ecn_unacked_;}
|
|
|
Definition at line 67 of file tcp-sink.h. References Acker::maxseen_. Referenced by DelAckSink::recv().
00067 { return (maxseen_); }
|
|
|
Reimplemented from Acker. Definition at line 566 of file tcp-sink.cc. References Acker::reset(), SackStack::reset(), and sf_.
00567 {
00568 sf_->reset();
00569 Acker::reset();
00570 }
|
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 TcpSink::ack(), QSTcpSink::ack(), append_ack(), DelAckSink::recv(), and TcpAsymSink::recv().
00062 { return (next_ - 1); }
|
|
|
Definition at line 550 of file tcp-sink.cc. References base_nblocks_, NSA, and sf_.
00551 {
00552 // we come here if "nblocks" changed
00553 TracedInt* ti = (TracedInt*) v;
00554
00555 if (int(*ti) > NSA) {
00556 fprintf(stderr, "warning(Sacker::trace): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(*ti));
00557 *ti = NSA;
00558 }
00559
00560 int newval = int(*ti);
00561 delete sf_;
00562 sf_ = new SackStack(newval);
00563 base_nblocks_ = newval;
00564 }
|
|
|
Definition at line 65 of file tcp-sink.h. References Acker::ts_to_echo_. Referenced by TcpSink::ack(), and QSTcpSink::ack().
00065 { return ts_to_echo_;}
|
|
||||||||||||
|
Definition at line 95 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 DelAckSink::recv(), TcpSink::recv(), QSTcpSink::recv(), and TcpAsymSink::recv().
00096 {
00097 bool just_marked_as_seen = FALSE;
00098 is_dup_ = FALSE;
00099 // start by assuming the segment hasn't been received before
00100 if (numBytes <= 0)
00101 printf("Error, received TCP packet size <= 0\n");
00102 int numToDeliver = 0;
00103 while(seq + 1 - next_ >= wndmask_) {
00104 // next_ is next packet expected; wndmask_ is the maximum
00105 // window size minus 1; if somehow the seqno of the
00106 // packet is greater than the one we're expecting+wndmask_,
00107 // then resize the buffer.
00108 resize_buffers((wndmask_+1)*2);
00109 }
00110
00111 if (seq > maxseen_) {
00112 // the packet is the highest one we've seen so far
00113 int i;
00114 for (i = maxseen_ + 1; i < seq; ++i)
00115 seen_[i & wndmask_] = 0;
00116 // we record the packets between the old maximum and
00117 // the new max as being "unseen" i.e. 0 bytes of each
00118 // packet have been received
00119 maxseen_ = seq;
00120 seen_[maxseen_ & wndmask_] = numBytes;
00121 // store how many bytes have been seen for this packet
00122 seen_[(maxseen_ + 1) & wndmask_] = 0;
00123 // clear the array entry for the packet immediately
00124 // after this one
00125 just_marked_as_seen = TRUE;
00126 // necessary so this packet isn't confused as being a duplicate
00127 }
00128 int next = next_;
00129 if (seq < next) {
00130 // Duplicate packet case 1: the packet is to the left edge of
00131 // the receive window; therefore we must have seen it
00132 // before
00133 #ifdef DEBUGDSACK
00134 printf("%f\t Received duplicate packet %d\n",Scheduler::instance().clock(),seq);
00135 #endif
00136 is_dup_ = TRUE;
00137 }
00138
00139 if (seq >= next && seq <= maxseen_) {
00140 // next is the left edge of the recv window; maxseen_
00141 // is the right edge; execute this block if there are
00142 // missing packets in the recv window AND if current
00143 // packet falls within those gaps
00144
00145 if (seen_[seq & wndmask_] && !just_marked_as_seen) {
00146 // Duplicate case 2: the segment has already been
00147 // recorded as being received (AND not because we just
00148 // marked it as such)
00149 is_dup_ = TRUE;
00150 #ifdef DEBUGDSACK
00151 printf("%f\t Received duplicate packet %d\n",Scheduler::instance().clock(),seq);
00152 #endif
00153 }
00154 seen_[seq & wndmask_] = numBytes;
00155 // record the packet as being seen
00156 while (seen_[next & wndmask_]) {
00157 // this loop first gets executed if seq==next;
00158 // i.e., this is the next packet in order that
00159 // we've been waiting for. the loop sets how
00160 // many bytes we can now deliver to the
00161 // application, due to this packet arriving
00162 // (and the prior arrival of any segments
00163 // immediately to the right)
00164
00165 numToDeliver += seen_[next & wndmask_];
00166 ++next;
00167 }
00168 next_ = next;
00169 // store the new left edge of the window
00170 }
00171 return numToDeliver;
00172 }
|
Here is the call graph for this function:

|
|
Definition at line 224 of file tcp-sink.cc. References Acker::ecn_unacked_. Referenced by TcpSink::ack(), and QSTcpSink::ack().
00225 {
00226 ecn_unacked_ = value;
00227 }
|
|
||||||||||||
|
Definition at line 87 of file tcp-sink.cc. References Acker::next_, ts, and Acker::ts_to_echo_. Referenced by DelAckSink::recv(), TcpSink::recv(), QSTcpSink::recv(), and TcpAsymSink::recv().
00088 {
00089 if (ts >= ts_to_echo_ && seqno <= next_)
00090 ts_to_echo_ = ts;
00091 }
|
|
|
Definition at line 91 of file tcp-sink.h. Referenced by append_ack(), configure(), Sacker(), and trace(). |
|
|
Definition at line 92 of file tcp-sink.h. Referenced by 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 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(), Acker::update(), and Acker::update_ts(). |
|
|
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 93 of file tcp-sink.h. Referenced by append_ack(), configure(), reset(), Sacker(), 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.3.3