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

📄 snoop.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 2 页
字号:
voidSnoop::savepkt_(Packet *p, int seq, int i){	pkts_[i] = p->copy();	Packet *pkt = pkts_[i];	hdr_snoop *sh = hdr_snoop::access(pkt);	sh->seqno() = seq;	sh->numRxmit() = 0;	sh->senderRxmit() = 0;	sh->sndTime() = Scheduler::instance().clock();}/* * Ack processing in snoop protocol.  We know for sure that this is an ack. * Return SNOOP_SUPPRESS if ack is to be suppressed and SNOOP_PROPAGATE o.w. */intSnoop::snoop_ack(Packet *p){	Packet *pkt;	int ack = hdr_tcp::access(p)->seqno();	/*	 * There are 3 cases:	 * 1. lastAck_ > ack.  In this case what has happened is	 *    that the acks have come out of order, so we don't	 *    do any local processing but forward it on.	 * 2. lastAck_ == ack.  This is a duplicate ack. If we have	 *    the packet we resend it, and drop the dupack.	 *    Otherwise we never got it from the fixed host, so we	 *    need to let the dupack get through.	 *    Set expDupacks_ to number of packets already sent	 *    This is the number of dup acks to ignore.	 * 3. lastAck_ < ack.  Set lastAck_ = ack, and update	 *    the head of the buffer queue. Also clean up ack'd packets.	 */	if (fstate_ & SNOOP_CLOSED || lastAck_ > ack) 		return SNOOP_PROPAGATE;	// send ack onward	if (lastAck_ == ack) {			/* A duplicate ack; pure window updates don't occur in ns. */		pkt = pkts_[buftail_];				if (pkt == 0) 			return SNOOP_PROPAGATE;				hdr_snoop *sh = hdr_snoop::access(pkt);		if (pkt == 0 || sh->seqno() > ack + 1) 			/* don't have packet, letting thru' */		        return SNOOP_PROPAGATE;		/* 		 * We have the packet: one of 3 possibilities:		 * 1. We are not expecting any dupacks (expDupacks_ == 0)		 * 2. We are expecting dupacks (expDupacks_ > 0)		 * 3. We are in an inconsistent state (expDupacks_ == -1)		 */					if (expDupacks_ == 0) {	// not expecting it#define RTX_THRESH 1						static int thresh = 0;			if (thresh++ < RTX_THRESH) 				/* no action if under RTX_THRESH */				return SNOOP_PROPAGATE;						thresh = 0;						// if the packet is a sender retransmission, pass on			if (sh->senderRxmit()) 				return SNOOP_PROPAGATE;						/*			 * Otherwise, not triggered by sender.  If this is			 * the first dupack recd., we must determine how many			 * dupacks will arrive that must be ignored, and also			 * rexmit the desired packet.  Note that expDupacks_			 * will be -1 if we miscount for some reason.			 */									expDupacks_ = bufhead_ - expNextAck_;			if (expDupacks_ < 0)				expDupacks_ += SNOOP_MAXWIND;			expDupacks_ -= RTX_THRESH + 1;			expNextAck_ = next(buftail_);			if (sh->numRxmit() == 0) 				return snoop_rxmit(pkt);		} else if (expDupacks_ > 0) {			expDupacks_--;			return SNOOP_SUPPRESS;		} else if (expDupacks_ == -1) {			if (sh->numRxmit() < 2) {				return snoop_rxmit(pkt);			}		} else		// let sender deal with it			return SNOOP_PROPAGATE;	} else {		// a new ack		fstate_ &= ~SNOOP_NOACK; // have seen at least 1 new ack		/* free buffers */		double sndTime = snoop_cleanbufs_(ack);				if (sndTime != -1)			snoop_rtt(sndTime);		expDupacks_ = 0;		expNextAck_ = buftail_;		lastAck_ = ack;	}	return SNOOP_PROPAGATE;}/*  * Handle data packets that arrive from a wireless link, and we're not * the end recipient.  See if there are any holes in the transmission, and * if there are, mark them as candidates for wireless loss.  Then, when * (dup)acks troop back for this loss, set the ELN bit in their header, to * help the sender (or a snoop agent downstream) retransmit. */voidSnoop::snoop_wless_data(Packet *p){	hdr_tcp *th = hdr_tcp::access(p);	int i, seq = th->seqno();	if (wl_state_ & SNOOP_WLALIVE && seq == 0)		wlreset();	wl_state_ |= SNOOP_WLALIVE;	if (wl_state_ & SNOOP_WLEMPTY && seq >= wl_lastAck_) {		wlseqs_[wl_bufhead_]->seq = seq;		wlseqs_[wl_bufhead_]->num = 1;		wl_buftail_ = wl_bufhead_;		wl_bufhead_ = wl_next(wl_bufhead_);		wl_lastSeen_ = seq;		wl_state_ &= ~SNOOP_WLEMPTY;		return;	}	/* WL data list definitely not empty at this point. */	if (seq >= wl_lastSeen_) {		wl_lastSeen_ = seq;		i = wl_prev(wl_bufhead_);		if (wlseqs_[i]->seq + wlseqs_[i]->num == seq) {			wlseqs_[i]->num++;			return;		}		i = wl_bufhead_;		wl_bufhead_ = wl_next(wl_bufhead_);	} else if (seq == wlseqs_[i = wl_buftail_]->seq - 1) {	} else		return;	wlseqs_[i]->seq = seq;	wlseqs_[i]->num++;	/* Ignore network out-of-ordering and retransmissions for now */	return;}/* * Ack from wired side (for sender on "other" side of wireless link. */void Snoop::snoop_wired_ack(Packet *p){	hdr_tcp *th = hdr_tcp::access(p);	int ack = th->seqno();	int i;		if (ack == wl_lastAck_ && snoop_wlessloss(ack)) {		hdr_flags::access(p)->eln_ = 1;	} else if (ack > wl_lastAck_) {		/* update info about unack'd data */		for (i = wl_buftail_; i != wl_bufhead_; i = wl_next(i)) {			hdr_seq *t = wlseqs_[i];			if (t->seq + t->num - 1 <= ack) {				t->seq = t->num = 0;			} else if (ack < t->seq) {				break;			} else if (ack < t->seq + t->num - 1) {				/* ack for part of a block */				t->num -= ack - t->seq +1;				t->seq = ack + 1;				break;			}		}		wl_buftail_ = i;		if (wl_buftail_ == wl_bufhead_)			wl_state_ |= SNOOP_WLEMPTY;		wl_lastAck_ = ack;		/* Even a new ack could cause an ELN to be set. */		if (wl_bufhead_ != wl_buftail_ && snoop_wlessloss(ack))			hdr_flags::access(p)->eln_ = 1;	}}/*  * Return 1 if we think this packet loss was not congestion-related, and  * 0 otherwise.  This function simply implements the lookup into the table * that maintains this info; most of the hard work is done in  * snoop_wless_data() and snoop_wired_ack(). */intSnoop::snoop_wlessloss(int ack){	if ((wl_bufhead_ == wl_buftail_) || wlseqs_[wl_buftail_]->seq > ack+1)		return 1;	return 0;}/* * clean snoop cache of packets that have been acked. */doubleSnoop::snoop_cleanbufs_(int ack){	Scheduler &s = Scheduler::instance();	double sndTime = -1;	if (toutPending_) {		s.cancel(toutPending_);		// xxx: I think that toutPending_ doesn't need to be freed because snoop didn't allocate it (but I'm not sure).		toutPending_ = 0;	};	if (empty_())		return sndTime;	int i = buftail_;	do {		hdr_snoop *sh = hdr_snoop::access(pkts_[i]);		int seq = hdr_tcp::access(pkts_[i])->seqno();		if (seq <= ack) {			sndTime = sh->sndTime();			Packet::free(pkts_[i]);			pkts_[i] = 0;			fstate_ &= ~SNOOP_FULL;	/* XXX redundant? */		} else if (seq > ack)			break;		i = next(i);	} while (i != bufhead_);	if ((i != buftail_) || (bufhead_ != buftail_)) {		fstate_ &= ~SNOOP_FULL;		buftail_ = i;	}	if (!empty_()) {		toutPending_ = (Event *) (pkts_[buftail_]);		s.schedule(rxmitHandler_, toutPending_, timeout());		hdr_snoop *sh = hdr_snoop::access(pkts_[buftail_]);		tailTime_ = sh->sndTime();	}	return sndTime;}/*  * Calculate smoothed rtt estimate and linear deviation. */voidSnoop::snoop_rtt(double sndTime){	double rtt = Scheduler::instance().clock() - sndTime;	if (parent_->integrate()) {		parent_->snoop_rtt(sndTime);		return;	}		if (rtt > 0) {		srtt_ = g_*srtt_ + (1-g_)*rtt;		double delta = rtt - srtt_;		if (delta < 0)			delta = -delta;		if (rttvar_ != 0)			rttvar_ = g_*delta + (1-g_)*rttvar_;		else 			rttvar_ = delta;	}}/*  * Calculate smoothed rtt estimate and linear deviation. */voidLLSnoop::snoop_rtt(double sndTime){	double rtt = Scheduler::instance().clock() - sndTime;	if (rtt > 0) {		srtt_ = g_*srtt_ + (1-g_)*rtt;		double delta = rtt - srtt_;		if (delta < 0)			delta = -delta;		if (rttvar_ != 0)			rttvar_ = g_*delta + (1-g_)*rttvar_;		else 			rttvar_ = delta;	}}/* * Returns 1 if recent queue length is <= half the maximum and 0 otherwise. */int Snoop::snoop_qlong(){	/* For now only instantaneous lengths */	//	if (parent_->ifq()->length() <= 3*parent_->ifq()->limit()/4)		return 1;		//	return 0;}/* * Ideally, would like to schedule snoop retransmissions at higher priority. */intSnoop::snoop_rxmit(Packet *pkt){	Scheduler& s = Scheduler::instance();	if (pkt != 0) {		hdr_snoop *sh = hdr_snoop::access(pkt);		if (sh->numRxmit() < SNOOP_MAX_RXMIT && snoop_qlong()) {			/*			&& sh->seqno() == lastAck_+1)  */			#if 0			printf("%f Rxmitting packet %d\n", s.clock(), 			       hdr_tcp::access(pkt)->seqno());#endif						// need to specify direction, in this case, down			hdr_cmn *ch = HDR_CMN(pkt);       			ch->direction() = hdr_cmn::DOWN;  // Ben added			sh->sndTime() = s.clock();			sh->numRxmit() = sh->numRxmit() + 1;			Packet *p = pkt->copy();			parent_->sendDown(p);		} else 			return SNOOP_PROPAGATE;	}	/* Reset timeout for later time. */	if (toutPending_) {		s.cancel(toutPending_);		// xxx: I think that toutPending_ doesn't need to be freed because snoop didn't allocate it (but I'm not sure).	};	toutPending_ = (Event *)pkt;	s.schedule(rxmitHandler_, toutPending_, timeout());	return SNOOP_SUPPRESS;}void Snoop::snoop_cleanup(){}voidSnoopRxmitHandler::handle(Event *){	Packet *p = snoop_->pkts_[snoop_->buftail_];	snoop_->toutPending_ = 0;	if (p == 0)		return;	hdr_snoop *sh = hdr_snoop::access(p);	if (sh->seqno() != snoop_->lastAck_ + 1)		return;	if ((snoop_->bufhead_ != snoop_->buftail_) || 	    (snoop_->fstate_ & SNOOP_FULL)) {		//		printf("%f Snoop timeout\n", Scheduler::instance().clock());		if (snoop_->snoop_rxmit(p) == SNOOP_SUPPRESS)			snoop_->expNextAck_ = snoop_->next(snoop_->buftail_);	}}

⌨️ 快捷键说明

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