#include "flags.h" #include "ip.h" #include "tcp-sink.h" static class SlidingSinkClass : public TclClass { public: SlidingSinkClass() : TclClass("Agent/TCPSink/SlidingWindowSink") {} TclObject* create(int, const char*const*) { return (new SlidingSink(new S_Acker)); } } class_slidingsink; S_Acker::S_Acker() : next_(0), maxseen_(0), ecn_unacked_(0), ts_to_echo_(0) { memset(seen_, 0, sizeof(seen_)); } void S_Acker::reset() { next_ = 0; maxseen_ = 0; memset(seen_, 0, sizeof(seen_)); } void S_Acker::update_ts(int seqno, double ts) { if (ts >= ts_to_echo_ && seqno <= next_) ts_to_echo_ = ts; } int S_Acker::update(int seq, int numBytes) { if (numBytes <= 0) printf("Error, received packet size <= 0\n"); int numToDeliver = 0; if (seq - next_ >= MWM) { return 0; } if (seq == maxseen_ + 1) { int i = maxseen_ + 1; seen_[i & MWM] = 0; maxseen_ = seq; seen_[maxseen_ & MWM] = numBytes; seen_[(maxseen_ + 1) & MWM] = 0; } int next = next_; if (seq >= next && seq <= maxseen_) { seen_[seq & MWM] = numBytes; while (seen_[next & MWM]) { numToDeliver += seen_[next & MWM]; ++next; } next_ = next; } return numToDeliver; } SlidingSink::SlidingSink(S_Acker* acker) : Agent(PT_ACK), acker_(acker) { bind("packetSize_", &size_); bind("maxSackBlocks_", &max_sack_blocks_); bind_bool("ts_echo_bugfix_", &ts_echo_bugfix_); } void S_Acker::append_ack(hdr_cmn*, hdr_tcp*, int) const { } void S_Acker::update_ecn_unacked(int value) { ecn_unacked_ = value; } int SlidingSink::command(int argc, const char*const* argv) { if (argc == 2) { if (strcmp(argv[1], "reset") == 0) { reset(); return (TCL_OK); } } return (Agent::command(argc, argv)); } void SlidingSink::reset() { acker_->reset(); save_ = NULL; } void SlidingSink::ack(Packet* opkt) { Packet* npkt = allocpkt(); double now = Scheduler::instance().clock(); hdr_flags *sf; hdr_tcp *otcp = hdr_tcp::access(opkt); hdr_tcp *ntcp = hdr_tcp::access(npkt); ntcp->seqno() = acker_->Seqno(); ntcp->ts() = now; if (ts_echo_bugfix_) /* TCP/IP Illustrated, Vol. 2, pg. 870 */ ntcp->ts_echo() = acker_->ts_to_echo(); else ntcp->ts_echo() = otcp->ts(); hdr_ip* oip = (hdr_ip*)opkt->access(off_ip_); hdr_ip* nip = (hdr_ip*)npkt->access(off_ip_); nip->flowid() = oip->flowid(); hdr_flags* of = (hdr_flags*)opkt->access(off_flags_); hdr_flags* nf = (hdr_flags*)npkt->access(off_flags_); if (save_ != NULL) sf = (hdr_flags*)save_->access(off_flags_); if ( (save_ != NULL && sf->cong_action()) || of->cong_action() ) acker_->update_ecn_unacked(0); if ( (save_ != NULL && sf->ect() && sf->ce()) || (of->ect() && of->ce()) ) acker_->update_ecn_unacked(1); if ( (save_ != NULL && sf->ect()) || of->ect() ) nf->ecnecho() = acker_->ecn_unacked(); if (!of->ect() && of->ecnecho() || (save_ != NULL && !sf->ect() && sf->ecnecho()) ) nf->ecnecho() = 1; acker_->append_ack((hdr_cmn*)npkt->access(off_cmn_), ntcp, otcp->seqno()); add_to_ack(npkt); send(npkt, 0); } void SlidingSink::add_to_ack(Packet*) { return; } void SlidingSink::recv(Packet* pkt, Handler*) { int numToDeliver; int numBytes = ((hdr_cmn*)pkt->access(off_cmn_))->size(); hdr_tcp *th = hdr_tcp::access(pkt); acker_->update_ts(th->seqno(),th->ts()); numToDeliver = acker_->update(th->seqno(), numBytes); if (numToDeliver) recvBytes(numToDeliver); ack(pkt); Packet::free(pkt); }