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

📄 chost.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1997 Regents of the University of California. * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: * 	This product includes software developed by the Daedalus Research * 	Group at the University of California Berkeley. * 4. Neither the name of the University nor of the Research Group may be *    used to endorse or promote products derived from this software without *    specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/chost.cc,v 1.13 2000/09/01 03:04:05 haoboy Exp $ *//* * Functions invoked by TcpSessionAgent */#include "nilist.h"#include "chost.h"#include "tcp-int.h"#include "random.h"CorresHost::CorresHost() : slink(), TcpFsAgent(),	lastackTS_(0), dontAdjustOwnd_(0), dontIncrCwnd_(0), rexmtSegCount_(0),	connWithPktBeforeFS_(NULL){	nActive_ = nTimeout_ = nFastRec_ = 0;	ownd_ = 0;	owndCorrection_ = 0;	closecwTS_ = 0;	connIter_ = new Islist_iter<IntTcpAgent> (conns_);	rtt_seg_ = NULL;}/* * Open up the congestion window. */void CorresHost::opencwnd(int /*size*/, IntTcpAgent *sender){	if (cwnd_ < ssthresh_) {		/* slow-start (exponential) */		cwnd_ += 1;	} else {		/* linear */		//double f;		if (!proxyopt_) {			switch (wnd_option_) {			case 0:				if ((count_ = count_ + winInc_) >= cwnd_) {					count_ = 0;					cwnd_ += winInc_;				}				break;			case 1:				/* This is the standard algorithm. */				cwnd_ += winInc_ / cwnd_;				break;			default:#ifdef notdef				/*XXX*/				error("illegal window option %d", wnd_option_);#endif				abort();			}		} else {	// proxy			switch (wnd_option_) {			case 0: 			case 1:				if (sender->highest_ack_ >= sender->wndIncSeqno_) {					cwnd_ += winInc_;					sender->wndIncSeqno_ = 0;				}				break;			default:#ifdef notdef				/*XXX*/				error("illegal window option %d", wnd_option_);#endif				abort();			}		}	}	// if maxcwnd_ is set (nonzero), make it the cwnd limit	if (maxcwnd_ && (int(cwnd_) > maxcwnd_))		cwnd_ = maxcwnd_;		return;}void CorresHost::closecwnd(int how, double ts, IntTcpAgent *sender){	if (proxyopt_) {		if (!sender || ts > sender->closecwTS_)			closecwnd(how, sender);	}	else {		if (ts > closecwTS_)			closecwnd(how, sender);	}}void CorresHost::closecwnd(int how, IntTcpAgent *sender){	int sender_ownd = 0;	if (sender)		sender_ownd = sender->maxseq_ - sender->highest_ack_;	closecwTS_ = Scheduler::instance().clock();	if (proxyopt_) {		if (sender)			sender->closecwTS_ = closecwTS_;		how += 10;	}	switch (how) {	case 0:	case 10:		/* timeouts */		/* 		 * XXX we use cwnd_ instead of ownd_ here, which may not be		 * appropriate if the sender does not fully utilize the		 * available congestion window (ownd_ < cwnd_).		 */		ssthresh_ = int(cwnd_ * winMult_);		cwnd_ = int(wndInit_);		break;			case 1:		/* Reno dup acks, or after a recent congestion indication. */		/* 		 * XXX we use cwnd_ instead of ownd_ here, which may not be		 * appropriate if the sender does not fully utilize the		 * available congestion window (ownd_ < cwnd_).		 */		cwnd_ *= winMult_;		ssthresh_ = int(cwnd_);		if (ssthresh_ < 2)			ssthresh_ = 2;		break;	case 11:		/* Reno dup acks, or after a recent congestion indication. */		/* XXX fix this -- don't make it dependent on ownd */		cwnd_ = ownd_ - sender_ownd*(1-winMult_);		ssthresh_ = int(cwnd_);		if (ssthresh_ < 2)			ssthresh_ = 2;		break;	case 3:	case 13:		/* idle time >= t_rtxcur_ */		cwnd_ = wndInit_;		break;			default:		abort();	}	fcnt_ = 0.;	count_ = 0;	if (sender)		sender->count_ = 0;}Segment* CorresHost::add_pkts(int /*size*/, int seqno, int sessionSeqno, int daddr, int dport, 		     int sport, double ts, IntTcpAgent *sender){	class Segment *news;	ownd_ += 1;	news = new Segment;	news->seqno_ = seqno;	news->sessionSeqno_ = sessionSeqno;	news->daddr_ = daddr;	news->dport_ = dport;	news->sport_ = sport;	news->ts_ = ts;	news->size_ = 1;	news->dupacks_ = 0;	news->later_acks_ = 0;	news->thresh_dupacks_ = 0;	news->partialack_ = 0;	news->rxmitted_ = 0;	news->sender_ = sender;	seglist_.append(news);	return news;}voidCorresHost::adjust_ownd(int size) {	if (double(owndCorrection_) < size)		ownd_ -= min(double(ownd_), size - double(owndCorrection_));	owndCorrection_ -= min(double(owndCorrection_),size);	if (double(ownd_) < -0.5 || double(owndCorrection_ < -0.5))		printf("In adjust_ownd(): ownd_ = %g  owndCorrection_ = %g\n", double(ownd_), double(owndCorrection_));}intCorresHost::clean_segs(int /*size*/, Packet *pkt, IntTcpAgent *sender, int sessionSeqno, int amt_data_acked){     Segment *cur, *prev=NULL, *newseg;    int i;    //int rval = -1;    /* remove all acked pkts from list */    int latest_susp_loss = rmv_old_segs(pkt, sender, amt_data_acked);    /*      * XXX If no new data is acked and the last time we shrunk the window      * covers the most recent suspected loss, update the estimate of the amount     * of outstanding data.     */    if (amt_data_acked == 0 && latest_susp_loss <= recover_ && 	!dontAdjustOwnd_ && last_cwnd_action_ != CWND_ACTION_TIMEOUT) {	    owndCorrection_ += min(double(ownd_),1);	    ownd_ -= min(double(ownd_),1);    }    /*     * A pkt is a candidate for retransmission if it is the leftmost one in the     * unacked window for the connection AND has at least numdupacks_     * dupacks/later acks AND (at least one dupack OR a later packet also     * with the threshold number of dup/later acks). A pkt is also a candidate     * for immediate retransmission if it has partialack_ set, indicating that     * a partial new ack has been received for it.     */    for (i=0; i < rexmtSegCount_; i++) {	    int remove_flag = 0;	    /* 	     * curArray_ only contains segments that are the first oldest	     * unacked segments of their connection (i.e., they are at the left	     * edge of their window) and have either received a	     * partial ack and/or have received at least cur->numdupacks_	     * dupacks/later acks. Thus, segments in curArray_ have a high	     * probability (but not certain) of being eligible for 	     * retransmission. Using curArray_ avoids having to scan	     * through all the segments.	     */	    cur = curArray_[i];	    prev = prevArray_[i];	    if (cur->partialack_ || cur->dupacks_ > 0 || 		cur->sender_->num_thresh_dupack_segs_ > 1 ) {		    if (cur->thresh_dupacks_) {			    cur->thresh_dupacks_ = 0;			    cur->sender_->num_thresh_dupack_segs_--;		    }		    if (cur->sessionSeqno_ <= recover_ && 			last_cwnd_action_ != CWND_ACTION_TIMEOUT /* XXX 2 */)			    dontAdjustOwnd_ = 1;		    if ((cur->sessionSeqno_ > recover_) || 			(last_cwnd_action_ == CWND_ACTION_TIMEOUT /* XXX 2 */)			|| (proxyopt_ && cur->seqno_ > cur->sender_->recover_)			|| (proxyopt_ && cur->sender_->last_cwnd_action_ == CWND_ACTION_TIMEOUT /* XXX 2 */)) { 			    /* new loss window */			    closecwnd(1, cur->ts_, cur->sender_);			    recover_ = sessionSeqno - 1;			    last_cwnd_action_ = CWND_ACTION_DUPACK /* XXX 1 */;			    cur->sender_->recover_ = cur->sender_->maxseq_;			    cur->sender_->last_cwnd_action_ = 				    CWND_ACTION_DUPACK /* XXX 1 */;			    dontAdjustOwnd_ = 0;		    }		    if ((newseg = cur->sender_->rxmit_last(TCP_REASON_DUPACK, 			   cur->seqno_, cur->sessionSeqno_, cur->ts_))) {			    newseg->rxmitted_ = 1;			    adjust_ownd(cur->size_);			    if (!dontAdjustOwnd_) {				    owndCorrection_ += 					    min(double(ownd_),cur->dupacks_);				    ownd_ -= min(double(ownd_),cur->dupacks_);			    }			    seglist_.remove(cur, prev);			    remove_flag = 1;			    delete cur;		    }		    /* 		     * if segment just removed used to be the one just previous		     * to the next segment in the array, update prev for the		     * next segment		     */		    if (remove_flag && cur == prevArray_[i+1])			    prevArray_[i+1] = prev;	    }    }    rexmtSegCount_ = 0;    return(0);}		    intCorresHost::rmv_old_segs(Packet *pkt, IntTcpAgent *sender, int amt_data_acked){	Islist_iter<Segment> seg_iter(seglist_);	Segment *cur, *prev=0;	int found = 0;	int done = 0;	int new_data_acked = 0;	int partialack = 0;	int latest_susp_loss = -1;	hdr_tcp *tcph = hdr_tcp::access(pkt);	if (tcph->ts_echo() > lastackTS_)		lastackTS_ = tcph->ts_echo();	while (((cur = seg_iter()) != NULL) &&	       (!done || tcph->ts_echo() > cur->ts_)) {		int remove_flag = 0;		/* ack for older pkt of another connection */		if (sender != cur->sender_ && tcph->ts_echo() > cur->ts_) { 			if (!disableIntLossRecov_)				cur->later_acks_++;			latest_susp_loss = 				max(latest_susp_loss,cur->sessionSeqno_);			dontIncrCwnd_ = 1;		} 		/* ack for same connection */		else if (sender == cur->sender_) {			/* found packet acked */			if (tcph->seqno() == cur->seqno_ && 			    tcph->ts_echo() == cur->ts_) 				found = 1;			/* higher ack => clean up acked packets */			if (tcph->seqno() >= cur->seqno_) {				adjust_ownd(cur->size_);				seglist_.remove(cur, prev);				remove_flag = 1;				new_data_acked += cur->size_;				if (new_data_acked >= amt_data_acked)					done = 1;				if (prev == cur) 					prev = NULL;				if (cur == rtt_seg_)					rtt_seg_ = NULL;				delete cur;				if (seg_iter.get_cur() && prev)					seg_iter.set_cur(prev);				else if (seg_iter.get_cur())					seg_iter.set_cur(seg_iter.get_last());			} 			/* partial new ack => rexmt immediately */			/* XXX should we check recover for session? */			else if (amt_data_acked > 0 && 				 tcph->seqno() == cur->seqno_-1 &&				 cur->seqno_ <= sender->recover_ &&				 sender->last_cwnd_action_ == CWND_ACTION_DUPACK) {				cur->partialack_ = 1;				partialack = 1;				latest_susp_loss = 					max(latest_susp_loss,cur->sessionSeqno_);				if (new_data_acked >= amt_data_acked)					done = 1;				dontIncrCwnd_ = 1;			}			/* 			 * If no new data has been acked AND this segment has			 * not been retransmitted before AND the ack indicates 			 * that this is the next segment to be acked, then			 * increment dupack count.			 */			else if (!amt_data_acked && !cur->rxmitted_ &&				 tcph->seqno() == cur->seqno_-1) {				cur->dupacks_++;				latest_susp_loss = 					max(latest_susp_loss,cur->sessionSeqno_);				done = 1;				dontIncrCwnd_ = 1;			} 		}		if (cur->dupacks_+cur->later_acks_ >= sender->numdupacks_ &&		    !cur->thresh_dupacks_) {			cur->thresh_dupacks_ = 1;			cur->sender_->num_thresh_dupack_segs_++;		}		if (amt_data_acked==0 && tcph->seqno()==cur->seqno_-1)			done = 1;		/* XXX we could check for rexmt candidates here if we ignore 		   the num_thresh_dupack_segs_ check */		if (!remove_flag &&		    cur->seqno_ == cur->sender_->highest_ack_ + 1 &&		    (cur->dupacks_ + cur->later_acks_ >= sender->numdupacks_ ||		     cur->partialack_)) {			curArray_[rexmtSegCount_] = cur;			prevArray_[rexmtSegCount_] = prev;			rexmtSegCount_++;		}		if (!remove_flag)			prev = cur;	}	/* partial ack => terminate fast start mode */	if (partialack && fs_enable_ && fs_mode_) {		timeout(TCP_TIMER_RESET);		rexmtSegCount_ = 0;	}	return latest_susp_loss;}	voidCorresHost::add_agent(IntTcpAgent *agent, int /*size*/, double winMult, 		      int winInc, int /*ssthresh*/){	if (nActive_ >= MAX_PARALLEL_CONN) {		printf("In add_agent(): reached limit of number of parallel conn (%d); returning\n", nActive_);		return;	}	nActive_++;	if ((!fixedIw_ && nActive_ > 1) || cwnd_ == 0)		cwnd_ += 1; /* XXX should this be done? */	wndInit_ = 1;	winMult_ = winMult;	winInc_ = winInc;/*	ssthresh_ = ssthresh;*/	conns_.append(agent);}intCorresHost::ok_to_snd(int /*size*/){	if (ownd_ <= -0.5)		printf("In ok_to_snd(): ownd_ = %g  owndCorrection_ = %g\n", double(ownd_), double(owndCorrection_));	return (cwnd_ >= ownd_+1);}

⌨️ 快捷键说明

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