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

📄 tcp-int.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. * * Contributed by the Daedalus Research Group, U.C.Berkeley * http://daedalus.cs.berkeley.edu * * $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-int.cc,v 1.15 2000/09/01 03:04:07 haoboy Exp $ *//* * We separate TCP functionality into two parts: that having to do with  * providing a reliable, ordered byte-stream service, and that having to do with * congestion control and loss recovery. The former is done on a per-connection * basis and is implemented as part of IntTcpAgent ("integrated TCP"). The  * latter is done in an integrated fashion across multiple TCP connections, and * is implemented as part of TcpSessionAgent ("TCP session"). TcpSessionAgent is * derived from CorresHost ("correspondent host"), which keeps track of the  * state of all TCP (TCP/Int) connections to a host that it is corresponding  * with. * * The motivation for this separation of functionality is to make an ensemble of * connection more well-behaved than a set of independent TCP connections. * The packet loss rate is cut down and the chances of losses being recovered  * via data-driven techniques (rather than via timeouts) is improved. At the  * same time, we do not introduce any unnecessary coupling between the  * logically-independent byte-streams that the set of connections represents.  * This is in contrast to the coupling that is inherent in the multiplexing at  * the application layer of multiple byte-streams onto a single TCP connection. */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include "packet.h"#include "ip.h"#include "tcp.h"#include "flags.h"#include "nilist.h"#include "tcp-int.h"#include "chost.h"#include "tcp-session.h"#include "random.h"Islist<TcpSessionAgent> TcpSessionAgent::sessionList_;static class IntTcpClass : public TclClass {public:	IntTcpClass() : TclClass("Agent/TCP/Int") {}	TclObject* create(int, const char*const*) {		return (new IntTcpAgent());	}} class_tcp_int;IntTcpAgent::IntTcpAgent() : TcpAgent(), slink(), 	session_(0), closecwTS_(0), lastTS_(-1), count_(0), 	wt_(1), wndIncSeqno_(0), num_thresh_dupack_segs_(0){	bind("rightEdge_", &rightEdge_);	bind("uniqTS_", &uniqTS_);	bind("winInc_", &winInc_);	bind("winMult_", &winMult_);}intIntTcpAgent::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 3) {		if (!strcmp(argv[1], "setwt")) {			if (!session_)				createTcpSession();			session_->set_weight(this,atoi(argv[2]));			return (TCL_OK);		}	}	else if (argc == 2) {		if (!strcmp(argv[1], "session")) {			if (!session_)				createTcpSession();			tcl.resultf("%s", session_->name());			return (TCL_OK);		}	}	return (TcpAgent::command(argc,argv));}/*  * Update the ack information and reset the timer. RTT update is done in  * TcpSessionAgent. */voidIntTcpAgent::newack(Packet* pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	last_ack_ = tcph->seqno();	highest_ack_ = last_ack_;	if (t_seqno_ < last_ack_ + 1)		t_seqno_ = last_ack_ + 1;	/* if the connection is done, call finish() */	if ((highest_ack_ >= curseq_-1) && !closed_) {		closed_ = 1;		finish();	}}void IntTcpAgent::recv(Packet *pkt, Handler *){	hdr_tcp *tcph = hdr_tcp::access(pkt);	int amt_data_acked = 0;	if (tcph->seqno() > last_ack_) {		amt_data_acked = tcph->seqno() - last_ack_;		newack(pkt);	} 	session_->recv(this, pkt, amt_data_acked);}voidIntTcpAgent::createTcpSession(){	Tcl& tcl = Tcl::instance();	tcl.evalf("%s set node_", name());	tcl.evalf("%s createTcpSession %d", tcl.result(), daddr());	Islist_iter<TcpSessionAgent> session_iter(TcpSessionAgent::sessionList_);	TcpSessionAgent *cur;	while ((cur = session_iter()) != NULL) {		if (cur->addr()/256 == addr() && cur->daddr() == daddr()) {			session_ = cur;			break;		}	}	if (!session_) {		printf("In IntTcpAgent::createTcpSession(): failed\n");		abort();	}	session_->add_agent(this, size_, winMult_, winInc_, ssthresh_);}voidIntTcpAgent::output(int seqno, int reason){	Packet *pkt = allocpkt();	hdr_tcp *tcph = hdr_tcp::access(pkt);	tcph->seqno() = seqno;	tcph->ts() = Scheduler::instance().clock();	tcph->ts_echo() = ts_peer_;	tcph->reason() = reason;	session_->setflags(pkt);		int bytes = hdr_cmn::access(pkt)->size();	/* call helper function to fill in additional fields */	output_helper(pkt);        ++ndatapack_;	ndatabytes_ += bytes;	send(pkt, 0);	if (seqno == curseq_ && seqno > maxseq_)		idle();  // Tell application I have sent everything so far	if (seqno > maxseq_) {		maxseq_ = seqno;	}	else {        	++nrexmitpack_;        	nrexmitbytes_ += bytes;	}	if (wndIncSeqno_ == 0)		wndIncSeqno_ = maxseq_;}/* * Unlike in other flavors of TCP, IntTcpAgent does not decide when to send  * packets and how many of them to send. That decision is made by  * TcpSessionAgent. So send_much() does little more than defer to  * TcpSessionAgent. */voidIntTcpAgent::send_much(int force, int reason, int /*maxburst*/){	if (!session_)		createTcpSession();	if (!force && delsnd_timer_.status() == TIMER_PENDING)		return;	if (overhead_ && !force) {		delsnd_timer_.resched(Random::uniform(overhead_));		return;	}	session_->send_much(this, force,reason);}/* * Send one new packet. */voidIntTcpAgent::send_one(int sessionSeqno){	int dst_addr = daddr();	int dst_port = dport();	int sport = port();	if (!session_)		createTcpSession();	/* 	 * XXX We assume that the session layer has already made sure that	 * we have data to send.	 */	output(t_seqno_++); 	session_->add_pkts(size_, t_seqno_ - 1, sessionSeqno,			   dst_addr, dst_port, sport, lastTS_, this); }/* * open up the congestion window */void IntTcpAgent::opencwnd(){	session_->opencwnd(size_, this);}/* * close down the congestion window */void IntTcpAgent::closecwnd(int how){   	session_->closecwnd(how, this);}Segment *IntTcpAgent::rxmit_last(int reason, int seqno, int sessionSeqno, double /*ts*/){	session_->agent_rcov(this);	/* 	 * XXX kludge -- IntTcpAgent is not supposed to deal with 	 * rtx timer 	 */	session_->reset_rtx_timer(1,0); 	output(seqno, reason);	daddr_ = daddr();	dport_ = dport();	sport_ = port();	return (session_->add_pkts(size_, seqno, sessionSeqno, daddr_, 				   dport_, sport_, lastTS_, this));	return NULL;}unsigned long output_helper_count=0;double last_clock=0;voidIntTcpAgent::output_helper(Packet *p){	double now = Scheduler::instance().clock();	output_helper_count++;	last_clock = now;	hdr_tcp *tcph = hdr_tcp::access(p);	/* This is to make sure that we get unique times for each xmission */	while (uniqTS_ && now <= lastTS_) {		now += 0.000001; // something arbitrarily small	}	lastTS_ = now;	tcph->ts() = now;	/* if this is a fast start pkt and not a retransmission, mark it */	if (session_->fs_pkt() && tcph->seqno() > maxseq_)		hdr_flags::access(p)->fs_ = 1;	return;}int IntTcpAgent::data_left_to_send() {	return (curseq_ > t_seqno_);}

⌨️ 快捷键说明

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