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

📄 tcp-abs.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (C) 1999 by the University of Southern California * $Id: tcp-abs.cc,v 1.3 2005/08/25 18:58:12 johnh Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * * The copyright of this module includes the following * linking-with-specific-other-licenses addition: * * In addition, as a special exception, the copyright holders of * this module give you permission to combine (via static or * dynamic linking) this module with free software programs or * libraries that are released under the GNU LGPL and with code * included in the standard release of ns-2 under the Apache 2.0 * license or under otherwise-compatible licenses with advertising * requirements (or modified versions of such code, with unchanged * license).  You may copy and distribute such a system following the * terms of the GNU GPL for this module and the licenses of the * other code concerned, provided that you include the source code of * that other code when and as the GNU GPL requires distribution of * source code. * * Note that people who make modified versions of this module * are not obligated to grant this special exception for their * modified versions; it is their choice whether to do so.  The GNU * General Public License gives permission to release a modified * version without this exception; this exception also makes it * possible to release a modified version which carries forward this * exception. * *//*  * Contributed by Polly Huang (USC/ISI), http://www-scf.usc.edu/~bhuang * @(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-abs.cc,v 1.3 2005/08/25 18:58:12 johnh Exp $ (LBL)"; */#include "ip.h"#include "tcp.h"#include "tcp-abs.h"//AbsTcpAbsTcpAgent::AbsTcpAgent() : Agent(PT_TCP), rtt_(0), current_(NULL),offset_(0), seqno_lb_(-1), connection_size_(0), timer_(this), rescheduled_(0){	size_ = 1000;}void AbsTcpAgent::timeout(){	if (rescheduled_ == 0 && current_->transition_[offset_]!= current_->transition_[0]) {		set_timer(2*rtt_);		rescheduled_ = 1;	} else {		rescheduled_ = 0;		seqno_lb_ += current_->batch_size_;		if (current_->drop_[offset_] == NULL) {			printf("Error: This fsm can't handle multi losses per connection\n");			exit(0);		}		current_ = current_->drop_[offset_];		send_batch();	}}void AbsTcpAgent::sendmsg(int pktcnt){	connection_size_ = pktcnt;	start();}void AbsTcpAgent::advanceby(int pktcnt){	connection_size_ = pktcnt;	start();}void AbsTcpAgent::start(){	//printf("starting fsm tcp, %d\n", connection_size_);	send_batch();}void AbsTcpAgent::send_batch() {	int seqno = seqno_lb_;		offset_ = 0;	//printf("sending batch, %d\n", current_->batch_size_);	for (int i=0; i<current_->batch_size_ && seqno < connection_size_-1; i++) {		seqno++;		output(seqno);	}	if (seqno == connection_size_-1) {		finish();	}	else if (seqno < connection_size_-1) {		if (current_->drop_[offset_] == NULL) {			printf("Error: current fsm can't handle this tcp connection flow id %d (possibly too long)\n", fid_);			exit(0);		} 		//printf("start timer %d\n", current_->transition_[offset_]);		if (current_->transition_[offset_] == 0) {			current_ = current_->drop_[offset_];			send_batch();		} else if (current_->transition_[offset_] == RTT) {			set_timer(rtt_);		} else if (current_->transition_[offset_] == TIMEOUT) {			set_timer(rtt_ * 3);		} else {			printf("Error: weird transition timer\n");			exit(0);		}	} else {		printf("Error: sending more than %d packets\n", connection_size_);		exit(0);	}}void AbsTcpAgent::drop(int seqno){	//printf("dropped: %d\n", seqno);	if (offset_ != 0) {		printf("Error: Sorry, can't handle multiple drops per batch\n");		exit(0);	}	offset_ = seqno - seqno_lb_;	connection_size_++;}void AbsTcpAgent::finish(){	//printf("finish: sent %d\n", seqno_lb_+1);	cancel_timer();}void AbsTcpAgent::output(int seqno){        Packet* p = allocpkt();        hdr_tcp *tcph = hdr_tcp::access(p);        tcph->seqno() = seqno;        send(p, 0);}void AbsTcpAgent::recv(Packet* pkt, Handler*){	Packet::free(pkt);}int AbsTcpAgent::command(int argc, const char*const* argv){        if (argc == 3 ) {                if (strcmp(argv[1], "rtt") == 0) {			rtt_ = atof(argv[2]);			//printf("rtt %f\n", rtt_);			return (TCL_OK);		}                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], "print-stats") == 0) {			// xxx: works best if invoked on a new fsm			// (otherwise you don't get the whole thing).			int n = atoi(argv[2]);			if (n < 0 || n >= 17)				return TCL_ERROR;			FSM::print_FSM_stats(current_, n);                        return (TCL_OK);		};	} else if (argc == 2) {                if (strcmp(argv[1], "print") == 0) {			// xxx: works best if invoked on a new fsm			// (otherwise you don't get the whole thing).			FSM::print_FSM(current_);                        return (TCL_OK);		};	};	return (Agent::command(argc, argv));}void AbsTcpTimer::expire(Event*){        a_->timeout();}//AbsTCP/TahoeAckstatic class AbsTcpTahoeAckClass : public TclClass {public:	AbsTcpTahoeAckClass() : TclClass("Agent/AbsTCP/TahoeAck") {}	TclObject* create(int, const char*const*) {		return (new AbsTcpTahoeAckAgent());	}} class_abstcptahoeack;AbsTcpTahoeAckAgent::AbsTcpTahoeAckAgent() : AbsTcpAgent(){	size_ = 1000;	current_ = TahoeAckFSM::instance().start_state();	DropTargetAgent::instance().insert_tcp(this);}//AbsTCP/RenoAckstatic class AbsTcpRenoAckClass : public TclClass {public:	AbsTcpRenoAckClass() : TclClass("Agent/AbsTCP/RenoAck") {}	TclObject* create(int, const char*const*) {		return (new AbsTcpRenoAckAgent());	}} class_abstcprenoack;AbsTcpRenoAckAgent::AbsTcpRenoAckAgent() : AbsTcpAgent(){	size_ = 1000;	current_ = RenoAckFSM::instance().start_state();	DropTargetAgent::instance().insert_tcp(this);}//AbsTCP/TahoeDelAckstatic class AbsTcpTahoeDelAckClass : public TclClass {public:	AbsTcpTahoeDelAckClass() : TclClass("Agent/AbsTCP/TahoeDelAck") {}	TclObject* create(int, const char*const*) {		return (new AbsTcpTahoeDelAckAgent());	}} class_abstcptahoedelack;AbsTcpTahoeDelAckAgent::AbsTcpTahoeDelAckAgent() : AbsTcpAgent(){	size_ = 1000;	current_ = TahoeDelAckFSM::instance().start_state();	DropTargetAgent::instance().insert_tcp(this);}//AbsTCP/RenoDelAckstatic class AbsTcpRenoDelAckClass : public TclClass {public:	AbsTcpRenoDelAckClass() : TclClass("Agent/AbsTCP/RenoDelAck") {}	TclObject* create(int, const char*const*) {		return (new AbsTcpRenoDelAckAgent());	}} class_abstcprenodelack;AbsTcpRenoDelAckAgent::AbsTcpRenoDelAckAgent() : AbsTcpAgent(){	size_ = 1000;	current_ = RenoDelAckFSM::instance().start_state();	DropTargetAgent::instance().insert_tcp(this);}//AbsTcpSinkstatic class AbsTcpSinkClass : public TclClass {public:        AbsTcpSinkClass() : TclClass("Agent/AbsTCPSink") {}        TclObject* create(int, const char*const*) {                return (new AbsTcpSink());        }} class_abstcpsink;AbsTcpSink::AbsTcpSink() : Agent(PT_ACK){	size_ = 40;}void AbsTcpSink::recv(Packet* pkt, Handler*){	Packet* p = allocpkt();	send(p, 0);        Packet::free(pkt);}static class AbsDelAckSinkClass : public TclClass {public:        AbsDelAckSinkClass() : TclClass("Agent/AbsTCPSink/DelAck") {}        TclObject* create(int, const char*const*) {                return (new AbsDelAckSink());        }} class_absdelacksink;AbsDelAckSink::AbsDelAckSink() : AbsTcpSink(), delay_timer_(this){	size_ = 40;	interval_ = 0.1;}void AbsDelAckSink::recv(Packet* pkt, Handler*){        if (delay_timer_.status() != TIMER_PENDING) {		delay_timer_.resched(interval_);	} else {                delay_timer_.cancel();		Packet* p = allocpkt();		send(p, 0);	}        Packet::free(pkt);}void AbsDelAckSink::timeout(){        /*         * The timer expired so we ACK the last packet seen.         * (shouldn't this check for a particular time out#?  -kf)         */	Packet* p = allocpkt();	send(p, 0);}void AbsDelayTimer::expire(Event */*e*/) {        a_->timeout();}//Special drop target agentDropTargetAgent* DropTargetAgent::instance_;static class DropTargetClass : public TclClass {public:        DropTargetClass() : TclClass("DropTargetAgent") {}        TclObject* create(int, const char*const*) {                return (new DropTargetAgent());        }} class_droptarget;DropTargetAgent::DropTargetAgent(): Connector(), dropper_list_(NULL){	instance_ = this;}void DropTargetAgent::recv(Packet* pkt, Handler*){	Dropper* tmp = dropper_list_;        hdr_tcp *tcph = hdr_tcp::access(pkt);        hdr_ip *iph = hdr_ip::access(pkt);        //printf("flow %d dropping seqno %d\n", iph->flowid(),tcph->seqno());	while(tmp != NULL) {		if(tmp->agent_->flowid() == iph->flowid())			tmp->agent_->drop(tcph->seqno());		tmp = tmp->next_;	}	Packet::free(pkt);}void DropTargetAgent::insert_tcp(AbsTcpAgent* tcp){	Dropper* dppr = new Dropper;	dppr->agent_=tcp;	dppr->next_ = dropper_list_;	dropper_list_ = dppr;}

⌨️ 快捷键说明

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