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

📄 tcp-full.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
}/* * called when user/application performs 'close' */voidFullTcpAgent::usrclosed(){	curseq_ = maxseq_ - 1;	// now, no more data	infinite_send_ = FALSE;	// stop infinite send	switch (state_) {	case TCPS_CLOSED:	case TCPS_LISTEN:		cancel_timers();		newstate(TCPS_CLOSED);		finish();		break;	case TCPS_SYN_SENT:		newstate(TCPS_CLOSED);		/* fall through */	case TCPS_LAST_ACK:		flags_ |= TF_NEEDFIN;		send_much(1, REASON_NORMAL, maxburst_);		break;	case TCPS_SYN_RECEIVED:	case TCPS_ESTABLISHED:		newstate(TCPS_FIN_WAIT_1);		flags_ |= TF_NEEDFIN;		send_much(1, REASON_NORMAL, maxburst_);		break;	case TCPS_CLOSE_WAIT:		newstate(TCPS_LAST_ACK);		flags_ |= TF_NEEDFIN;		send_much(1, REASON_NORMAL, maxburst_);		break;	case TCPS_FIN_WAIT_1:	case TCPS_FIN_WAIT_2:	case TCPS_CLOSING:		/* usr asked for a close more than once [?] */		fprintf(stderr,		  "%f FullTcpAgent(%s): app close in bad state %s\n",		  now(), name(), statestr(state_));		break;	default:		fprintf(stderr,		  "%f FullTcpAgent(%s): app close in unknown state %s\n",		  now(), name(), statestr(state_));	}	return;}/* * Utility type functions */voidFullTcpAgent::cancel_timers(){	// cancel: rtx, burstsend, delsnd	TcpAgent::cancel_timers();      	// cancel: delack	delack_timer_.force_cancel();}voidFullTcpAgent::newstate(int state){//printf("%f(%s): state changed from %s to %s\n",//now(), name(), statestr(state_), statestr(state));	state_ = state;}voidFullTcpAgent::prpkt(Packet *pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	// TCP header	hdr_cmn *th = hdr_cmn::access(pkt);	// common header (size, etc)	//hdr_flags *fh = hdr_flags::access(pkt);	// flags (CWR, CE, bits)	hdr_ip* iph = hdr_ip::access(pkt);	int datalen = th->size() - tcph->hlen(); // # payload bytes	fprintf(stdout, " [%d:%d.%d>%d.%d] (hlen:%d, dlen:%d, seq:%d, ack:%d, flags:0x%x (%s), salen:%d, reason:0x%x)\n",		th->uid(),		iph->saddr(), iph->sport(),		iph->daddr(), iph->dport(),		tcph->hlen(),		datalen,		tcph->seqno(),		tcph->ackno(),		tcph->flags(), flagstr(tcph->flags()),		tcph->sa_length(),		tcph->reason());}char *FullTcpAgent::flagstr(int hflags){	// update this if tcp header flags change	static char *flagstrs[28] = {		"<null>", "<FIN>", "<SYN>", "<SYN,FIN>",	// 0-3		"<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>",	// 4-7		"<PSH>", "<PSH,FIN>", "<PSH,SYN>", "<PSH,SYN,FIN>", // 0x08-0x0b		/* do not use <??, in next line because that's an ANSI trigraph */		"<?>", "<?,FIN>", "<?,SYN>", "<?,SYN,FIN>",	    // 0x0c-0x0f		"<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x10-0x13		"<ACK>", "<ACK,FIN>", "<ACK,SYN>", "<ACK,SYN,FIN>", // 0x14-0x17		"<PSH,ACK>", "<PSH,ACK,FIN>", "<PSH,ACK,SYN>", "<PSH,ACK,SYN,FIN>", // 0x18-0x1b	};	if (hflags < 0 || (hflags > 28)) {		/* Added strings for CWR and ECE  -M. Weigle 6/27/02 */		if (hflags == 72) 	 		return ("<ECE,PSH>");	 	else if (hflags == 80)	 		return ("<ECE,ACK>");	 	else if (hflags == 88) 	 		return ("<ECE,PSH,ACK>");	 	else if (hflags == 152) 	 		return ("<CWR,PSH,ACK>");		else if (hflags == 153)			return ("<CWR,PSH,ACK,FIN>");		else			return ("<invalid>");	}	return (flagstrs[hflags]);}char *FullTcpAgent::statestr(int state){	static char *statestrs[TCP_NSTATES] = {		"CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",		"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",		"LAST_ACK", "FIN_WAIT_2"	};	if (state < 0 || (state >= TCP_NSTATES))		return ("INVALID");	return (statestrs[state]);}voidDelAckTimer::expire(Event *) {        a_->timeout(TCP_TIMER_DELACK);}/* * reset to starting point, don't set state_ here, * because our starting point might be LISTEN rather * than CLOSED if we're a passive opener */voidFullTcpAgent::reset(){	cancel_timers();	// cancel timers first      	TcpAgent::reset();	// resets most variables	rq_.clear();		// clear reassembly queue	rtt_init();		// zero rtt, srtt, backoff	last_ack_sent_ = -1;	rcv_nxt_ = -1;	pipe_ = 0;	rtxbytes_ = 0;	flags_ = 0;	t_seqno_ = iss_;	maxseq_ = -1;	irs_ = -1;	last_send_time_ = -1.0;	if (ts_option_)		recent_ = recent_age_ = 0.0;	else		recent_ = recent_age_ = -1.0;	fastrecov_ = FALSE;}/* * This function is invoked when the connection is done. It in turn * invokes the Tcl finish procedure that was registered with TCP. * This function mimics tcp_close() */voidFullTcpAgent::finish(){	Tcl::instance().evalf("%s done", this->name());}/* * headersize: *	how big is an IP+TCP header in bytes; include options such as ts * this function should be virtual so others (e.g. SACK) can override */intFullTcpAgent::headersize(){	int total = tcpip_base_hdr_size_;	if (total < 1) {		fprintf(stderr,		    "%f: FullTcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",			now(), name(), tcpip_base_hdr_size_);	}	if (ts_option_)		total += ts_option_size_;	return (total);}/* * flags that are completely dependent on the tcp state * these are used for the next outgoing packet in foutput() * (in real TCP, see tcp_fsm.h, the "tcp_outflags" array) */intFullTcpAgent::outflags(){	// in real TCP an RST is added in the CLOSED state	static int tcp_outflags[TCP_NSTATES] = {		TH_ACK,          	/* 0, CLOSED */  		0,                      /* 1, LISTEN */ 		TH_SYN,                 /* 2, SYN_SENT */		TH_SYN|TH_ACK,          /* 3, SYN_RECEIVED */		TH_ACK,                 /* 4, ESTABLISHED */		TH_ACK,                 /* 5, CLOSE_WAIT */		TH_FIN|TH_ACK,          /* 6, FIN_WAIT_1 */		TH_FIN|TH_ACK,          /* 7, CLOSING */		TH_FIN|TH_ACK,          /* 8, LAST_ACK */		TH_ACK,                 /* 9, FIN_WAIT_2 */		/* 10, TIME_WAIT --- not used in simulator */	};	if (state_ < 0 || (state_ >= TCP_NSTATES)) {		fprintf(stderr, "%f FullTcpAgent(%s): invalid state %d\n",			now(), name(), state_);		return (0x0);	}	return (tcp_outflags[state_]);}/* * reaass() -- extract the appropriate fields from the packet *	and pass this info the ReassemblyQueue add routine * * returns the TCP header flags representing the "or" of *	the flags contained in the adjacent sequence # blocks */intFullTcpAgent::reass(Packet* pkt){          hdr_tcp *tcph =  hdr_tcp::access(pkt);        hdr_cmn *th = hdr_cmn::access(pkt);           int start = tcph->seqno();        int end = start + th->size() - tcph->hlen();        int tiflags = tcph->flags();	int fillshole = (start == rcv_nxt_);	int flags;   	// end contains the seq of the last byte of	// in the packet plus one	if (start == end && (tiflags & TH_FIN) == 0) {		fprintf(stderr, "%f: FullTcpAgent(%s)::reass() -- bad condition - adding non-FIN zero-len seg\n",			now(), name());		abort();	}	flags = rq_.add(start, end, tiflags, 0);	//present:	//	// If we've never received a SYN (unlikely)	// or this is an out of order addition, no reason to coalesce	//	if (TCPS_HAVERCVDSYN(state_) == 0 || !fillshole) {	 	return (0x00);	}	//	// If we get some data in SYN_RECVD, no need to present to user yet	//	if (state_ == TCPS_SYN_RECEIVED && (end > start))		return (0x00);	// clear out data that has been passed, up to rcv_nxt_,	// collects flags	flags |= rq_.cleartonxt();        return (flags);}/* * utility function to set rcv_next_ during inital exchange of seq #s */intFullTcpAgent::rcvseqinit(int seq, int dlen){	return (seq + dlen + 1);}/* * build a header with the timestamp option if asked */intFullTcpAgent::build_options(hdr_tcp* tcph){	int total = 0;	if (ts_option_) {		tcph->ts() = now();		tcph->ts_echo() = recent_;		total += ts_option_size_;	} else {		tcph->ts() = tcph->ts_echo() = -1.0;	}	return (total);}/* * pack() -- is the ACK a partial ACK? (not past recover_) */intFullTcpAgent::pack(Packet *pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	/* Added check for fast recovery.  -M. Weigle 5/2/02 */	return (fastrecov_ && tcph->ackno() >= highest_ack_ &&		tcph->ackno() < recover_);}/* * baseline reno TCP exists fast recovery on a partial ACK */voidFullTcpAgent::pack_action(Packet*){	if (reno_fastrecov_ && fastrecov_ && cwnd_ > double(ssthresh_)) {		cwnd_ = double(ssthresh_); // retract window if inflated	}	fastrecov_ = FALSE;//printf("%f: EXITED FAST RECOVERY\n", now());	dupacks_ = 0;}/* * ack_action -- same as partial ACK action for base Reno TCP */voidFullTcpAgent::ack_action(Packet* p){	FullTcpAgent::pack_action(p);}/* * sendpacket:  *	allocate a packet, fill in header fields, and send *	also keeps stats on # of data pkts, acks, re-xmits, etc * * fill in packet fields.  Agent::allocpkt() fills * in most of the network layer fields for us. * So fill in tcp hdr and adjust the packet size. * * Also, set the size of the tcp header. */voidFullTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen, int reason){        Packet* p = allocpkt();        hdr_tcp *tcph = hdr_tcp::access(p);	hdr_flags *fh = hdr_flags::access(p);	/* build basic header w/options */        tcph->seqno() = seqno;        tcph->ackno() = ackno;        tcph->flags() = pflags;        tcph->reason() |= reason; // make tcph->reason look like ns1 pkt->flags?	tcph->sa_length() = 0;    // may be increased by build_options()        tcph->hlen() = tcpip_base_hdr_size_;	tcph->hlen() += build_options(tcph);	/*	 * Explicit Congestion Notification (ECN) related:	 * Bits in header:	 * 	ECT (EC Capable Transport),	 * 	ECNECHO (ECHO of ECN Notification generated at router),	 * 	CWR (Congestion Window Reduced from RFC 2481)	 * States in TCP:	 *	ecn_: I am supposed to do ECN if my peer does	 *	ect_: I am doing ECN (ecn_ should be T and peer does ECN)	 */	// set ect on data packets (not syn or ack packets)	if ( datalen > 0 && ecn_ ){		fh->ect() = ect_;	// on after mutual agreement on ECT	}	else {		/* Set ect() to 0.  -M. Weigle 1/19/05 */		fh->ect() = 0;	}        // fill in CWR and ECE bits which don't actually sit in        // the tcp_flags but in hdr_flags        if ( pflags & TH_ECE) {                fh->ecnecho() = 1;        } else {                fh->ecnecho() = 0;        }        if ( pflags & TH_CWR ) {                fh->cong_action() = 1;        }	else {		/* Set cong_action() to 0  -M. Weigle 1/19/05 */		fh->cong_action() = 0;	}	/* actual size is data length plus header length */        hdr_cmn *ch = hdr_cmn::access(p);        ch->size() = datalen + tcph->hlen();        if (datalen <= 0)                ++nackpack_;        else {                ++ndatapack_;                ndatabytes_ += datalen;		last_send_time_ = now();	// time of last data        }        if (reason == REASON_TIMEOUT || reason == REASON_DUPACK || reason == REASON_SACK) {                ++nrexmitpack_;                nrexmitbytes_ += datalen;

⌨️ 快捷键说明

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