⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp-sink.cc.bak

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 BAK
📖 第 1 页 / 共 2 页
字号:
      	ack(pkt);	// ACK the packet	Packet::free(pkt);	// remove it from the system}static class DelSinkClass : public TclClass {public:	DelSinkClass() : TclClass("Agent/TCPSink/DelAck") {}	TclObject* create(int, const char*const*) {		return (new DelAckSink(new Acker));	}} class_delsink;DelAckSink::DelAckSink(Acker* acker) : TcpSink(acker), delay_timer_(this){	bind_time("interval_", &interval_);	// Deleted the line below, since this is bound in TcpSink.	// bind("bytes_", &bytes_); // useby JOBS}void DelAckSink::reset() {    if (delay_timer_.status() == TIMER_PENDING)        delay_timer_.cancel();    TcpSink::reset();}void DelAckSink::recv(Packet* pkt, Handler*){	int numToDeliver;	int numBytes = hdr_cmn::access(pkt)->size();	hdr_tcp *th = hdr_tcp::access(pkt);	/* W.N. Check if packet is from previous incarnation */	if (th->ts() < lastreset_) {		// Remove packet and do nothing		Packet::free(pkt);		return;	}	acker_->update_ts(th->seqno(),th->ts(),ts_echo_rfc1323_);	numToDeliver = acker_->update(th->seqno(), numBytes);	if (numToDeliver) {                bytes_ += numToDeliver; // for JOBS                recvBytes(numToDeliver);        }	        // If there's no timer and the packet is in sequence, set a timer.        // Otherwise, send the ack and update the timer.        if (delay_timer_.status() != TIMER_PENDING &&                                th->seqno() == acker_->Seqno()) {                // There's no timer, so we can set one and choose		// to delay this ack.		// If we're following RFC2581 (section 4.2) exactly,		// we should only delay the ACK if we're know we're		// not doing recovery, i.e. not gap-filling.		// Since this is a change to previous ns behaviour,		// it's controlled by an optional bound flag.		// discussed April 2000 in the ns-users list archives.		if (RFC2581_immediate_ack_ && 			(th->seqno() < acker_->Maxseen())) {			// don't delay the ACK since			// we're filling in a gap		} else {			// delay the ACK and start the timer.	                save_ = pkt;        	        delay_timer_.resched(interval_);                	return;		}        }        // If there was a timer, turn it off.	if (delay_timer_.status() == TIMER_PENDING) 		delay_timer_.cancel();	ack(pkt);        if (save_ != NULL) {                Packet::free(save_);                save_ = NULL;        }	Packet::free(pkt);}void DelAckSink::timeout(int){	// The timer expired so we ACK the last packet seen.	if ( save_ != NULL ) {		Packet* pkt = save_;		ack(pkt);		save_ = NULL;		Packet::free(pkt);	}}void DelayTimer::expire(Event* /*e*/) {	a_->timeout(0);}/* "sack1-tcp-sink" is for Matt and Jamshid's implementation of sack. */class SackStack {protected:	int size_;	int cnt_;	struct Sf_Entry {		int left_;		int right_;	} *SFE_;public:	SackStack(int); 	// create a SackStack of size (int)	~SackStack();	int& head_right(int n = 0) { return SFE_[n].right_; }	int& head_left(int n = 0) { return SFE_[n].left_; }	int cnt() { return cnt_; }  	// how big is the stack	void reset() {		register int i;		for (i = 0; i < cnt_; i++)			SFE_[i].left_ = SFE_[i].right_ = -1;		cnt_ = 0;	}	inline void push(int n = 0) { 		if (cnt_ >= size_) cnt_ = size_ - 1;  // overflow check		register int i;		for (i = cnt_-1; i >= n; i--)			SFE_[i+1] = SFE_[i];	// not efficient for big size		cnt_++;	}	inline void pop(int n = 0) {		register int i;		for (i = n; i < cnt_-1; i++)			SFE_[i] = SFE_[i+1];	// not efficient for big size		SFE_[i].left_ = SFE_[i].right_ = -1;		cnt_--;	}};SackStack::SackStack(int sz){	register int i;	size_ = sz;	SFE_ = new Sf_Entry[sz];	for (i = 0; i < sz; i++)		SFE_[i].left_ = SFE_[i].right_ = -1;	cnt_ = 0;}SackStack::~SackStack(){	delete SFE_;}static class Sack1TcpSinkClass : public TclClass {public:        Sack1TcpSinkClass() : TclClass("Agent/TCPSink/Sack1") {}	TclObject* create(int, const char*const*) {		Sacker* sacker = new Sacker;		TcpSink* sink = new TcpSink(sacker);		sacker->configure(sink);		return (sink);        }} class_sack1tcpsink;static class Sack1DelAckTcpSinkClass : public TclClass {public:	Sack1DelAckTcpSinkClass() : TclClass("Agent/TCPSink/Sack1/DelAck") {}	TclObject* create(int, const char*const*) {		Sacker* sacker = new Sacker;		TcpSink* sink = new DelAckSink(sacker);		sacker->configure(sink);		return (sink);	}} class_sack1delacktcpsink;void Sacker::configure(TcpSink *sink){	if (sink == NULL) {		fprintf(stderr, "warning: Sacker::configure(): no TCP sink!\n");		return;	}	TracedInt& nblocks = sink->max_sack_blocks_;	if (int(nblocks) > NSA) {		fprintf(stderr, "warning(Sacker::configure): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(nblocks));		nblocks = NSA;	}	sf_ = new SackStack(int(nblocks));	nblocks.tracer(this);	base_nblocks_ = int(nblocks);	dsacks_ = &(sink->generate_dsacks_);}voidSacker::trace(TracedVar *v){	// we come here if "nblocks" changed	TracedInt* ti = (TracedInt*) v;	if (int(*ti) > NSA) {		fprintf(stderr, "warning(Sacker::trace): TCP header limits number of SACK blocks to %d, not %d\n", NSA, int(*ti));		*ti = NSA;	}	int newval = int(*ti);	delete sf_;	sf_ = new SackStack(newval);	base_nblocks_ = newval;}void Sacker::reset() {	sf_->reset();	Acker::reset();}Sacker::~Sacker(){	delete sf_;}void Sacker::append_ack(hdr_cmn* ch, hdr_tcp* h, int old_seqno) const{	// ch and h are the common and tcp headers of the Ack being constructed	// old_seqno is the sequence # of the packet we just got	        int sack_index, i, sack_right, sack_left;	int recent_sack_left, recent_sack_right;          	int seqno = Seqno();	// the last in-order packet seen (i.e. the cumulative ACK # - 1)        sack_index = 0;	sack_left = sack_right = -1;	// initialization; sack_index=0 and sack_{left,right}= -1        if (old_seqno < 0) {                printf("Error: invalid packet number %d\n", old_seqno);        } else if (seqno >= maxseen_ && (sf_->cnt() != 0))		sf_->reset();	// if the Cumulative ACK seqno is at or beyond the right edge	// of the window, and if the SackStack is not empty, reset it	// (empty it)	else if (( (seqno < maxseen_) || is_dup_ ) && (base_nblocks_ > 0)) {		// Otherwise, if the received packet is to the left of		// the right edge of the receive window (but not at		// the right edge), OR if it is a duplicate, AND we		// can have 1 or more Sack blocks, then execute the		// following, which computes the most recent Sack		// block		if ((*dsacks_) && is_dup_) {			// Record the DSACK Block			h->sa_left(sack_index) = old_seqno;			h->sa_right(sack_index) = old_seqno+1;			// record the block			sack_index++;#ifdef DEBUGDSACK			printf("%f\t Generating D-SACK for packet %d\n", Scheduler::instance().clock(),old_seqno);#endif					}		//  Build FIRST (traditional) SACK block		// If we already had a DSACK block due to a duplicate		// packet, and if that duplicate packet is in the		// receiver's window (i.e. the packet's sequence		// number is > than the cumulative ACK) then the		// following should find the SACK block it's a subset		// of.  If it's <= cum ACK field then the following		// shouldn't record a superset SACK block for it.                if (sack_index >= base_nblocks_) {			printf("Error: can't use DSACK with less than 2 SACK blocks\n");		} else {                sack_right=-1;		// look rightward for first hole 		// start at the current packet                 for (i=old_seqno; i<=maxseen_; i++) {			if (!seen_[i & wndmask_]) {				sack_right=i;				break;			}		}		// if there's no hole set the right edge of the sack		// to be the next expected packet                if (sack_right == -1) {			sack_right = maxseen_+1;                }		// if the current packet's seqno is smaller than the		// left edge of the window, set the sack_left to 0		if (old_seqno <= seqno) {			sack_left = 0;			// don't record/send the block		} else {			// look leftward from right edge for first hole 	                for (i = sack_right-1; i > seqno; i--) {				if (!seen_[i & wndmask_]) {					sack_left = i+1;					break;				}	                }			h->sa_left(sack_index) = sack_left;			h->sa_right(sack_index) = sack_right;						// 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);			// record the block			sack_index++;		}		recent_sack_left = sack_left;		recent_sack_right = sack_right;		// first sack block is built, check the others 		// make sure that if max_sack_blocks has been made		// large from tcl we don't over-run the stuff we		// allocated in Sacker::Sacker()		int k = 0;                while (sack_index < base_nblocks_) {			sack_left = sf_->head_left(k);			sack_right = sf_->head_right(k);			// no more history 			if (sack_left < 0 || sack_right < 0 ||				sack_right > maxseen_ + 1)				break;			// newest ack "covers up" this one 			if (recent_sack_left <= sack_left &&			    recent_sack_right >= sack_right) {				sf_->pop(k);				continue;			}			h->sa_left(sack_index) = sack_left;			h->sa_right(sack_index) = sack_right;						// 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);						// store the old sack (i.e. move it down one)			sack_index++;			k++;                }		if (old_seqno > seqno) {		 	/* put most recent block onto stack */			sf_->push();			// this just moves things down 1 from the			// beginning, but it doesn't push any values			// on the stack			sf_->head_left() = recent_sack_left;			sf_->head_right() = recent_sack_right;			// this part stores the left/right values at			// the top of the stack (slot 0)		}		} // this '}' is for the DSACK base_nblocks_ >= test;		  // (didn't feel like re-indenting all the code and 		  // causing a large diff)		        }	h->sa_length() = sack_index;	// set the Length of the sack stack in the header	ch->size() += sack_index * 8;	// change the size of the common header to account for the	// Sack strings (2 4-byte words for each element)}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -