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

📄 tcp-advw.cc

📁 P2P文件共享基于ns2的仿真代码
💻 CC
📖 第 1 页 / 共 2 页
字号:
                                /*                                 * If we have outstanding data                                 * this is a completely                                 * duplicate ack,                                 * the ack is the biggest we've                                 * seen and we've seen exactly our rexmt                                 * threshhold of them, assume a packet                                 * has been dropped and retransmit it.                                 *                                 * We know we're losing at the current                                 * window size so do congestion avoidance.                                 *                                 * Dup acks mean that packets have left the                                 * network (they're now cached at the receiver)                                 * so bump cwnd by the amount in the receiver                                 * to keep a constant cwnd packets in the                                 * network.                                 */				if ((rtx_timer_.status() != TIMER_PENDING) ||				    ackno != highest_ack_) {					// not timed, or re-ordered ACK					dupacks_ = 0;				} else if (++dupacks_ == tcprexmtthresh_) {					fastrecov_ = TRUE;					/* re-sync the pipe_ estimate */					pipe_ = maxseq_ - highest_ack_;					pipe_ /= maxseg_;					pipe_ -= (dupacks_ + 1);pipe_ = int(cwnd_) - dupacks_ - 1;					dupack_action(); // maybe fast rexmt					goto drop;				} else if (dupacks_ > tcprexmtthresh_) {					if (reno_fastrecov_) {						// we just measure cwnd in						// packets, so don't scale by						// maxseg_ as real						// tcp does						cwnd_++;					}					send_much(0, REASON_NORMAL, maxburst_);					goto drop;				}			} else {				// non zero-length [dataful] segment				// with a dup ack (normal for dataful segs)				// (or window changed in real TCP).				if (dupack_reset_) {					dupacks_ = 0;					fastrecov_ = FALSE;				}			}			break;	/* take us to "step6" */		} /* end of dup acks */		/*		 * we've finished the fast retransmit/recovery period		 * (i.e. received an ACK which advances highest_ack_)		 * The ACK may be "good" or "partial"		 */process_ACK:		if (ackno > maxseq_) {			// ack more than we sent(!?)			fprintf(stderr,			    "%f: FullTcpAgent::recv(%s) too-big ACK (ack: %d, maxseq:%d)\n",				now(), name(), int(ackno), int(maxseq_));			goto dropafterack;		}                /*                 * If we have a timestamp reply, update smoothed                 * round trip time.  If no timestamp is present but                 * transmit timer is running and timed sequence                 * number was acked, update smoothed round trip time.                 * Since we now have an rtt measurement, cancel the                 * timer backoff (cf., Phil Karn's retransmit alg.).                 * Recompute the initial retransmit timer.		 *                 * If all outstanding data is acked, stop retransmit                 * If there is more data to be acked, restart retransmit                 * timer, using current (possibly backed-off) value.                 */		newack(pkt);	// handle timers, update highest_ack_		--pipe_;		/*		 * if this is a partial ACK, invoke whatever we should		 */		int partial = pack(pkt);		if (partial)			pack_action(pkt);		else			ack_action(pkt);		/*		 * if this is an ACK with an ECN indication, handle this		 */		if (fh->ecnecho())			ecn(highest_ack_);  // updated by newack(), above		// CHECKME: handling of rtx timer		if (ackno == maxseq_) {			needoutput = TRUE;		}		/*		 * If no data (only SYN) was ACK'd,		 *    skip rest of ACK processing.		 */		if (ackno == (highest_ack_ + 1))			goto step6;		// if we are delaying initial cwnd growth (probably due to		// large initial windows), then only open cwnd if data has		// been received                /*                 * When new data is acked, open the congestion window.                 * If the window gives us less than ssthresh packets                 * in flight, open exponentially (maxseg per packet).                 * Otherwise open about linearly: maxseg per window                 * (maxseg^2 / cwnd per packet).                 */		if ((!delay_growth_ || (rcv_nxt_ > 0)) &&		    last_state_ == TCPS_ESTABLISHED) {			if (!partial || open_cwnd_on_pack_)				opencwnd();		}		// K: added state check in equal but diff way		if ((state_ >= TCPS_FIN_WAIT_1) && (ackno == maxseq_)) {			ourfinisacked = TRUE;		} else {			ourfinisacked = FALSE;		}		// additional processing when we're in special states		switch (state_) {                /*                 * In FIN_WAIT_1 STATE in addition to the processing                 * for the ESTABLISHED state if our FIN is now acknowledged                 * then enter FIN_WAIT_2.                 */		case TCPS_FIN_WAIT_1:	/* doing active close */			if (ourfinisacked) {				// got the ACK, now await incoming FIN				newstate(TCPS_FIN_WAIT_2);				cancel_timers();				needoutput = FALSE;			}			break;                /*                 * In CLOSING STATE in addition to the processing for                 * the ESTABLISHED state if the ACK acknowledges our FIN                 * then enter the TIME-WAIT state, otherwise ignore                 * the segment.                 */		case TCPS_CLOSING:	/* simultaneous active close */;			if (ourfinisacked) {				newstate(TCPS_CLOSED);				cancel_timers();			}			break;                /*                 * In LAST_ACK, we may still be waiting for data to drain                 * and/or to be acked, as well as for the ack of our FIN.                 * If our FIN is now acknowledged,                 * enter the closed state and return.                 */		case TCPS_LAST_ACK:	/* passive close */			// K: added state change here			if (ourfinisacked) {				newstate(TCPS_CLOSED);#ifdef notdefcancel_timers();	// DOES THIS BELONG HERE?, probably (see tcp_cose#endif				finish();				goto drop;			} else {				// should be a FIN we've seen				hdr_ip* iph = hdr_ip::access(pkt);                                fprintf(stderr,                                "%f: %d.%d>%d.%d FullTcpAgent::recv(%s) received non-ACK (state:%d)\n",                                        now(),                                        iph->saddr(), iph->sport(),                                        iph->daddr(), iph->dport(),                                        name(), state_);                        }			break;		/* no case for TIME_WAIT in simulator */		}  // inner switch	} // outer switchstep6:	/* real TCP handles window updates and URG data here *//* dodata: this label is in the "real" code.. here only for reference */	/*	 * DATA processing	 */	if ((datalen > 0 || (tiflags & TH_FIN)) &&	    TCPS_HAVERCVDFIN(state_) == 0) {		if (tcph->seqno() == rcv_nxt_ && rq_.empty()) {			// see the "TCP_REASS" macro for this code:			// got the in-order packet we were looking			// for, nobody is in the reassembly queue,			// so this is the common case...			// note: in "real" TCP we must also be in			// ESTABLISHED state to come here, because			// data arriving before ESTABLISHED is			// queued in the reassembly queue.  Since we			// don't really have a process anyhow, just			// accept the data here as-is (i.e. don't			// require being in ESTABLISHED state)			flags_ |= TF_DELACK;			rcv_nxt_ += datalen;			rcv_wnd_ -= datalen;				if (datalen)				recvBytes(datalen); // notify app. of "delivery"			tiflags = tcph->flags() & TH_FIN;			// give to "application" here			needoutput = need_send();		} else {			// see the "tcp_reass" function:			// not the one we want next (or it			// is but there's stuff on the reass queue);			// do whatever we need to do for out-of-order			// segments or hole-fills.  Also,			// send an ACK to the other side right now.			// K: some changes here, figure out			int rcv_nxt_old_ = rcv_nxt_; // notify app. if changes			tiflags = reass(pkt);			if (rcv_nxt_ > rcv_nxt_old_)				recvBytes(rcv_nxt_ - rcv_nxt_old_);			if (tiflags & TH_PUSH) {				// K: APPLICATION recv				needoutput = need_send();			} else {				flags_ |= TF_ACKNOW;			}		}	} else {		/*		 * we're closing down or this is a pure ACK that		 * wasn't handled by the header prediction part above		 * (e.g. because cwnd < wnd)		 */		// K: this is deleted		tiflags &= ~TH_FIN;	}	/*	 * if FIN is received, ACK the FIN	 * (let user know if we could do so)	 */	if (tiflags & TH_FIN) {		if (TCPS_HAVERCVDFIN(state_) == 0) {			flags_ |= TF_ACKNOW;			rcv_nxt_++;		}		switch (state_) {                /*                 * In SYN_RECEIVED and ESTABLISHED STATES                 * enter the CLOSE_WAIT state.		 * (passive close)                 */                case TCPS_SYN_RECEIVED:                case TCPS_ESTABLISHED:			newstate(TCPS_CLOSE_WAIT);                        break;                /*                 * If still in FIN_WAIT_1 STATE FIN has not been acked so                 * enter the CLOSING state.		 * (simultaneous close)                 */                case TCPS_FIN_WAIT_1:			newstate(TCPS_CLOSING);                        break;                /*                 * In FIN_WAIT_2 state enter the TIME_WAIT state,                 * starting the time-wait timer, turning off the other                 * standard timers.		 * (in the simulator, just go to CLOSED)		 * (completion of active close)                 */                case TCPS_FIN_WAIT_2:                        newstate(TCPS_CLOSED);			cancel_timers();                        break;		}	} /* end of if FIN bit on */	if (needoutput || (flags_ & TF_ACKNOW))		send_much(1, REASON_NORMAL, maxburst_);	else if (curseq_ >= highest_ack_ || infinite_send_)		send_much(0, REASON_NORMAL, maxburst_);	// K: which state to return to when nothing left?	if (!halfclose_ && state_ == TCPS_CLOSE_WAIT && highest_ack_ == maxseq_)		usrclosed();	//      	Packet::free(pkt);	// haoboy: Is here the place for done{} of active close? 	// It cannot be put in the switch above because we might need to do	// send_much() (an ACK)	if (state_ == TCPS_CLOSED) 		Tcl::instance().evalf("%s done", this->name());	return;dropafterack:	flags_ |= TF_ACKNOW;	send_much(1, REASON_NORMAL, maxburst_);	goto drop;dropwithreset:	/* we should be sending an RST here, but can't in simulator */	if (tiflags & TH_ACK) {		sendpacket(ackno, 0, 0x0, 0, REASON_NORMAL);	} else {		int ack = tcph->seqno() + datalen;		if (tiflags & TH_SYN)			ack--;		sendpacket(0, ack, TH_ACK, 0, REASON_NORMAL);	}drop://   	Packet::free(pkt);	return;}void AdvwTcpAgent::newack(Packet* pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	register int ackno = tcph->ackno();	int progress = (ackno > highest_ack_);	if (ackno == maxseq_) {		cancel_rtx_timer();	// all data ACKd	} else if (progress) {		set_rtx_timer();	}	// advance the ack number if this is for new data	if (progress) {		highest_ack_ = ackno;		if (app_)		  app_->upcall_send();	}		// if we have suffered a retransmit timeout, t_seqno_	// will have been reset to highest_ ack.  If the	// receiver has cached some data above t_seqno_, the	// new-ack value could (should) jump forward.  We must	// update t_seqno_ here, otherwise we would be doing	// go-back-n.	if (t_seqno_ < highest_ack_)		t_seqno_ = highest_ack_; // seq# to send next        /*         * Update RTT only if it's OK to do so from info in the flags header.         * This is needed for protocols in which intermediate agents         * in the network intersperse acks (e.g., ack-reconstructors) for         * various reasons (without violating e2e semantics).         */        hdr_flags *fh = hdr_flags::access(pkt);        if (!fh->no_ts_) {                if (ts_option_) {			recent_age_ = now();			recent_ = tcph->ts();                        rtt_update(now() - tcph->ts_echo());		} else if (rtt_active_ && ackno > rtt_seq_) {			// got an RTT sample, record it                        t_backoff_ = 1;                        rtt_active_ = FALSE;			rtt_update(now() - rtt_ts_);                }        } else {		printf("no_ts\n");	}	return;}voidAdvwTcpAgent::sendpacket(int seqno, int ackno, int pflags, int datalen, int reason){        Packet* p = allocpkt();        hdr_tcp *tcph = hdr_tcp::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);	tcph->advwin() = rcv_wnd_;	/* ECT, ECN, and congestion action */        hdr_flags *fh = hdr_flags::access(p);	fh->ect() = ect_;	// on after mutual agreement on ECT	if (ecn_ && !ect_)	// initializing; ect = 0, ecnecho = 1		fh->ecnecho() = 1;	else {		fh->ecnecho() = recent_ce_;	}	fh->cong_action() =  cong_action_;	/* 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) {                ++nrexmitpack_;                nrexmitbytes_ += datalen;        }	last_ack_sent_ = ackno;	send(p, 0);}int AdvwTcpAgent::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if(strcmp(argv[1], "inf-rcv")==0) {		if(strcmp(argv[2], "true")==0) 			infinite_rcv_ = TRUE;		if(strcmp(argv[2], "false")==0) 			infinite_rcv_ = FALSE;				return TCL_OK;	}	if(strcmp(argv[1], "recv")==0) {		tcp_command_block_receive(atoi(argv[2]));		return TCL_OK;	}	return FullTcpAgent::command(argc, argv);}	AdvwTcpApplication::AdvwTcpApplication(): Application(){}AdvwTcpApplication::~AdvwTcpApplication(){}int AdvwTcpApplication::upcall_recv(Packet *){  printf("AdvwTcpApplication upcall_recv\n");  }void AdvwTcpApplication::upcall_send(){}void AdvwTcpApplication::upcall_closing() {}int AdvwTcpApplication::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 3) {		if (strcmp(argv[1], "attach-agent") == 0) {			agent_ = (Agent*) TclObject::lookup(argv[2]);			if (agent_ == 0) {				tcl.resultf("no such agent %s", argv[2]);				return(TCL_ERROR);			}			awagent_ = (AdvwTcpAgent *)agent_;			awagent_->attachApp(this);			return(TCL_OK);		}	}	return Application::command(argc, argv);}

⌨️ 快捷键说明

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