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

📄 tcp-full.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) Intel Corporation 2001. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * Copyright (c) 1997, 1998 The 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 Network Research * 	Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory 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. *//* * Full-TCP : A two-way TCP very similar to the 4.4BSD version of Reno TCP. * This version also includes variants Tahoe, NewReno, and SACK. * * This code below has received a fairly major restructuring (Aug. 2001). * The ReassemblyQueue structure is now removed to a separate module and * entirely re-written. * Also, the SACK functionality has been re-written (almost) entirely. * -KF [kfall@intel.com] * * This code below was motivated in part by code contributed by * Kathie Nichols (nichols@baynetworks.com).  The code below is based primarily * on the 4.4BSD TCP implementation. -KF [kfall@ee.lbl.gov] * * Kathie Nichols and Van Jacobson have contributed significant bug fixes, * especially with respect to the the handling of sequence numbers during * connection establishment/clearin.  Additional fixes have followed * theirs. * * Fixes for gensack() and ReassemblyQueue::add() contributed by Richard  * Mortier <Richard.Mortier@cl.cam.ac.uk> * * Some warnings and comments: *	this version of TCP will not work correctly if the sequence number *	goes above 2147483648 due to sequence number wrap * *	this version of TCP by default sends data at the beginning of a *	connection in the "typical" way... That is, *		A   ------> SYN ------> B *		A   <----- SYN+ACK ---- B *		A   ------> ACK ------> B *		A   ------> data -----> B * *	there is no dynamic receiver's advertised window.   The advertised *	window is simulated by simply telling the sender a bound on the window *	size (wnd_). * *	in real TCP, a user process performing a read (via PRU_RCVD) *		calls tcp_output each time to (possibly) send a window *		update.  Here we don't have a user process, so we simulate *		a user process always ready to consume all the receive buffer * * Notes: *	wnd_, wnd_init_, cwnd_, ssthresh_ are in segment units *	sequence and ack numbers are in byte units * * Futures: *      there are different existing TCPs with respect to how *      ack's are handled on connection startup.  Some delay *      the ack for the first segment, which can cause connections *      to take longer to start up than if we be sure to ack it quickly. * *      some TCPs arrange for immediate ACK generation if the incoming segment *      contains the PUSH bit * * */#ifndef lintstatic const char rcsid[] =    "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-full.cc,v 1.118 2005/08/02 04:02:58 tomh Exp $ (LBL)";#endif#include "ip.h"#include "tcp-full.h"#include "flags.h"#include "random.h"#include "template.h"#ifndef TRUE#define	TRUE 	1#endif#ifndef FALSE#define	FALSE 	0#endif/* * Tcl Linkage for the following: *	Agent/TCP/FullTcp, Agent/TCP/FullTcp/Tahoe, *	Agent/TCP/FullTcp/Newreno, Agent/TCP/FullTcp/Sack * * See tcl/lib/ns-default.tcl for init methods for *	Tahoe, Newreno, and Sack */static class FullTcpClass : public TclClass { public:	FullTcpClass() : TclClass("Agent/TCP/FullTcp") {}	TclObject* create(int, const char*const*) { 		return (new FullTcpAgent());	}} class_full;static class TahoeFullTcpClass : public TclClass { public:	TahoeFullTcpClass() : TclClass("Agent/TCP/FullTcp/Tahoe") {}	TclObject* create(int, const char*const*) { 		// ns-default sets reno_fastrecov_ to false		return (new TahoeFullTcpAgent());	}} class_tahoe_full;static class NewRenoFullTcpClass : public TclClass { public:	NewRenoFullTcpClass() : TclClass("Agent/TCP/FullTcp/Newreno") {}	TclObject* create(int, const char*const*) { 		// ns-default sets open_cwnd_on_pack_ to false		return (new NewRenoFullTcpAgent());	}} class_newreno_full;static class SackFullTcpClass : public TclClass { public:	SackFullTcpClass() : TclClass("Agent/TCP/FullTcp/Sack") {}	TclObject* create(int, const char*const*) { 		// ns-default sets reno_fastrecov_ to false		// ns-default sets open_cwnd_on_pack_ to false		return (new SackFullTcpAgent());	}} class_sack_full;/* * Delayed-binding variable linkage */voidFullTcpAgent::delay_bind_init_all(){        delay_bind_init_one("segsperack_");        delay_bind_init_one("segsize_");        delay_bind_init_one("tcprexmtthresh_");        delay_bind_init_one("iss_");        delay_bind_init_one("nodelay_");        delay_bind_init_one("data_on_syn_");        delay_bind_init_one("dupseg_fix_");        delay_bind_init_one("dupack_reset_");        delay_bind_init_one("close_on_empty_");        delay_bind_init_one("signal_on_empty_");        delay_bind_init_one("interval_");        delay_bind_init_one("ts_option_size_");        delay_bind_init_one("reno_fastrecov_");        delay_bind_init_one("pipectrl_");        delay_bind_init_one("open_cwnd_on_pack_");        delay_bind_init_one("halfclose_");        delay_bind_init_one("nopredict_");        delay_bind_init_one("spa_thresh_");	TcpAgent::delay_bind_init_all();             	reset();}intFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer){        if (delay_bind(varName, localName, "segsperack_", &segs_per_ack_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "segsize_", &maxseg_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "tcprexmtthresh_", &tcprexmtthresh_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "iss_", &iss_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "spa_thresh_", &spa_thresh_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "nodelay_", &nodelay_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "data_on_syn_", &data_on_syn_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "dupseg_fix_", &dupseg_fix_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "dupack_reset_", &dupack_reset_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "close_on_empty_", &close_on_empty_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "signal_on_empty_", &signal_on_empty_, tracer)) return TCL_OK;        if (delay_bind_time(varName, localName, "interval_", &delack_interval_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "ts_option_size_", &ts_option_size_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "reno_fastrecov_", &reno_fastrecov_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "pipectrl_", &pipectrl_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "open_cwnd_on_pack_", &open_cwnd_on_pack_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "halfclose_", &halfclose_, tracer)) return TCL_OK;        if (delay_bind_bool(varName, localName, "nopredict_", &nopredict_, tracer)) return TCL_OK;        return TcpAgent::delay_bind_dispatch(varName, localName, tracer);}voidSackFullTcpAgent::delay_bind_init_all(){        delay_bind_init_one("clear_on_timeout_");        delay_bind_init_one("sack_rtx_cthresh_");        delay_bind_init_one("sack_rtx_bthresh_");        delay_bind_init_one("sack_block_size_");        delay_bind_init_one("sack_option_size_");        delay_bind_init_one("max_sack_blocks_");        delay_bind_init_one("sack_rtx_threshmode_");	FullTcpAgent::delay_bind_init_all();}intSackFullTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer){        if (delay_bind_bool(varName, localName, "clear_on_timeout_", &clear_on_timeout_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "sack_rtx_cthresh_", &sack_rtx_cthresh_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "sack_rtx_bthresh_", &sack_rtx_bthresh_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "sack_rtx_threshmode_", &sack_rtx_threshmode_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "sack_block_size_", &sack_block_size_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "sack_option_size_", &sack_option_size_, tracer)) return TCL_OK;        if (delay_bind(varName, localName, "max_sack_blocks_", &max_sack_blocks_, tracer)) return TCL_OK;        return FullTcpAgent::delay_bind_dispatch(varName, localName, tracer);}intFullTcpAgent::command(int argc, const char*const* argv){	// would like to have some "connect" primitive	// here, but the problem is that we get called before	// the simulation is running and we want to send a SYN.	// Because no routing exists yet, this fails.	// Instead, see code in advance().	//	// listen can happen any time because it just changes state_	//	// close is designed to happen at some point after the	// simulation is running (using an ns 'at' command)	if (argc == 2) {		if (strcmp(argv[1], "listen") == 0) {			// just a state transition			listen();			return (TCL_OK);		}		if (strcmp(argv[1], "close") == 0) {			usrclosed();			return (TCL_OK);		}	}	if (argc == 3) {		if (strcmp(argv[1], "advance") == 0) {			advanceby(atoi(argv[2]));			return (TCL_OK);		}		if (strcmp(argv[1], "advanceby") == 0) {			advanceby(atoi(argv[2]));			return (TCL_OK);		}		if (strcmp(argv[1], "advance-bytes") == 0) {			advance_bytes(atoi(argv[2]));			return (TCL_OK);		}	}	if (argc == 4) {		if (strcmp(argv[1], "sendmsg") == 0) {			sendmsg(atoi(argv[2]), argv[3]);			return (TCL_OK);		}	}	return (TcpAgent::command(argc, argv));}/* * "User Interface" Functions for Full TCP *	advanceby(number of packets) *	advance_bytes(number of bytes) *	sendmsg(int bytes, char* buf) *	listen *	close *//* * the 'advance' interface to the regular tcp is in packet * units.  Here we scale this to bytes for full tcp. * * 'advance' is normally called by an "application" (i.e. data source) * to signal that there is something to send * * 'curseq_' is the sequence number of the last byte provided * by the application.  In the case where no data has been supplied * by the application, curseq_ is the iss_. */voidFullTcpAgent::advanceby(int np){	// XXX hack:	//	because np is in packets and a data source	//	may pass a *huge* number as a way to tell us	//	to go forever, just look for the huge number	//	and if it's there, pre-divide it	if (np >= 0x10000000)		np /= maxseg_;	advance_bytes(np * maxseg_);	return;}/* * the byte-oriented interface: advance_bytes(int nbytes) */voidFullTcpAgent::advance_bytes(int nb){	//	// state-specific operations:	//	if CLOSED or LISTEN, reset and try a new active open/connect	//	if ESTABLISHED, queue and try to send more	//	if SYN_SENT or SYN_RCVD, just queue	//	if above ESTABLISHED, we are closing, so don't allow	//	switch (state_) {	case TCPS_CLOSED:	case TCPS_LISTEN:                reset();                curseq_ = iss_ + nb;                connect();              // initiate new connection		break;	case TCPS_ESTABLISHED:	case TCPS_SYN_SENT:	case TCPS_SYN_RECEIVED:                if (curseq_ < iss_)                         curseq_ = iss_;                 curseq_ += nb;		break;	default:	    fprintf(stderr,	    "%f: FullTcpAgent::advance(%s): cannot advance while in state %s\n",		 now(), name(), statestr(state_));	}	if (state_ == TCPS_ESTABLISHED)		send_much(0, REASON_NORMAL, maxburst_);  	return;}/* * If MSG_EOF is set, by setting close_on_empty_ to TRUE, we ensure that * a FIN will be sent when the send buffer emptys. * If DAT_EOF is set, the callback function done_data is called * when the send buffer empty *  * When (in the future?) FullTcpAgent implements T/TCP, avoidance of 3-way  * handshake can be handled in this function. */voidFullTcpAgent::sendmsg(int nbytes, const char *flags){	if (flags && strcmp(flags, "MSG_EOF") == 0) 		close_on_empty_ = TRUE;		if (flags && strcmp(flags, "DAT_EOF") == 0) 		signal_on_empty_ = TRUE;		if (nbytes == -1) {		infinite_send_ = TRUE;		advance_bytes(0);	} else		advance_bytes(nbytes);}/* * do an active open * (in real TCP, see tcp_usrreq, case PRU_CONNECT) */voidFullTcpAgent::connect(){	newstate(TCPS_SYN_SENT);	// sending a SYN now	sent(iss_, foutput(iss_, REASON_NORMAL));	return;}/* * be a passive opener * (in real TCP, see tcp_usrreq, case PRU_LISTEN) * (for simulation, make this peer's ptype ACKs) */voidFullTcpAgent::listen(){	newstate(TCPS_LISTEN);	type_ = PT_ACK;	// instead of PT_TCP}/** This function is invoked when the sender buffer is empty. It in turn* invokes the Tcl done_data procedure that was registered with TCP.*/ voidFullTcpAgent::bufferempty(){   	signal_on_empty_=FALSE;	Tcl::instance().evalf("%s done_data", this->name());

⌨️ 快捷键说明

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