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

📄 tp_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		idleticks = tpcb->tp_inact_ticks - tpcb->tp_timer[TM_inact];		if (idleticks > tpcb->tp_dt_ticks)			/*			 * We have been idle for "a while" and no acks are			 * expected to clock out any data we send --			 * slow start to get ack "clock" running again.			 */			tpcb->tp_cong_win = tpcb->tp_l_tpdusize;	}	cong_win = tpcb->tp_cong_win;	highseq = SEQ(tpcb, tpcb->tp_fcredit + tpcb->tp_snduna);	if (tpcb->tp_Xsnd.sb_mb)		highseq = SEQ_MIN(tpcb, highseq, tpcb->tp_sndnew);			IFDEBUG(D_DATA)		printf("tp_send enter tpcb 0x%x nxt 0x%x win %d high 0x%x\n",				tpcb, tpcb->tp_sndnxt, cong_win, highseq);	ENDDEBUG	IFTRACE(D_DATA)		tptraceTPCB( TPPTmisc, "tp_send sndnew snduna", 			tpcb->tp_sndnew,  tpcb->tp_snduna, 0, 0);		tptraceTPCB( TPPTmisc, "tp_send tpcb->tp_sndnxt win fcredit congwin", 			tpcb->tp_sndnxt, cong_win, tpcb->tp_fcredit, tpcb->tp_cong_win);	ENDTRACE	IFTRACE(D_DATA)		tptraceTPCB( TPPTmisc, "tp_send 2 nxt high fcredit congwin", 			tpcb->tp_sndnxt, highseq, tpcb->tp_fcredit, cong_win);	ENDTRACE	if (tpcb->tp_sndnxt_m)		m = tpcb->tp_sndnxt_m;	else {		off = SEQ_SUB(tpcb, tpcb->tp_sndnxt, tpcb->tp_snduna);		for (m = sb->sb_mb; m && off > 0; m = m->m_next)			off--;	}send:	/*	 * Avoid silly window syndrome here . . . figure out how!	 */	checkseq = tpcb->tp_sndnum;	if (idle && SEQ_LT(tpcb, tpcb->tp_sndnum, highseq))		checkseq = highseq; /* i.e. DON'T retain highest assigned packet */	while ((SEQ_LT(tpcb, tpcb->tp_sndnxt, highseq)) && m && cong_win > 0) {		eotsdu = (m->m_flags & M_EOR) != 0;		len = m->m_pkthdr.len;		if (tpcb->tp_sndnxt == checkseq && eotsdu == 0 &&			len < (tpcb->tp_l_tpdusize / 2))				break;  /* Nagle . . . . . */		cong_win -= len;		/* make a copy - mb goes into the retransmission list 		 * while m gets emitted.  m_copy won't copy a zero-length mbuf.		 */		mb = m;		m = m_copy(mb, 0, M_COPYALL);		if (m == MNULL)				break;		IFTRACE(D_STASH)			tptraceTPCB( TPPTmisc, 				"tp_send mcopy nxt high eotsdu len", 				tpcb->tp_sndnxt, highseq, eotsdu, len);		ENDTRACE		IFDEBUG(D_DATA)			printf("tp_sending tpcb 0x%x nxt 0x%x\n",				tpcb, tpcb->tp_sndnxt);		ENDDEBUG		/* when headers are precomputed, may need to fill			   in checksum here */		if (tpcb->tp_sock->so_error =			tp_emit(DT_TPDU_type, tpcb, tpcb->tp_sndnxt, eotsdu, m)) {			/* error */			break;		}		m = mb->m_nextpkt;		tpcb->tp_sndnxt_m = m;		if (tpcb->tp_sndnxt == tpcb->tp_sndnew) {			SEQ_INC(tpcb, tpcb->tp_sndnew);			/*			 * Time this transmission if not a retransmission and			 * not currently timing anything.			 */			if (tpcb->tp_rttemit == 0) {				tpcb->tp_rttemit = ticks;				tpcb->tp_rttseq = tpcb->tp_sndnxt;			}			tpcb->tp_sndnxt = tpcb->tp_sndnew;		} else			SEQ_INC(tpcb, tpcb->tp_sndnxt);		/*		 * Set retransmit timer if not currently set.		 * Initial value for retransmit timer is smoothed		 * round-trip time + 2 * round-trip time variance.		 * Initialize shift counter which is used for backoff		 * of retransmit time.		 */		if (tpcb->tp_timer[TM_data_retrans] == 0 &&			tpcb->tp_class != TP_CLASS_0) {			tpcb->tp_timer[TM_data_retrans] = tpcb->tp_dt_ticks;			tpcb->tp_timer[TM_sendack] = tpcb->tp_keepalive_ticks;			tpcb->tp_rxtshift = 0;		}	}	if (SEQ_GT(tpcb, tpcb->tp_sndnew, tpcb->tp_sndnum))		tpcb->tp_oktonagle = 0;#ifdef TP_PERF_MEAS	IFPERF(tpcb)		{			register int npkts;			int	 elapsed = ticks - send_start_time, *t;			struct timeval now;			npkts = SEQ_SUB(tpcb, tpcb->tp_sndnxt, oldnxt);			if (npkts > 0) 				tpcb->tp_Nwindow++;			if (npkts > TP_PM_MAX) 				npkts = TP_PM_MAX; 			t = &(tpcb->tp_p_meas->tps_sendtime[npkts]);			*t += (t - elapsed) >> TP_RTT_ALPHA;			if (mb == 0) {				IncPStat(tpcb, tps_win_lim_by_data[npkts] );			} else {				IncPStat(tpcb, tps_win_lim_by_cdt[npkts] );				/* not true with congestion-window being used */			}			now.tv_sec = elapsed / hz;			now.tv_usec = (elapsed - (hz * now.tv_sec)) * 1000000 / hz;			tpmeas( tpcb->tp_lref, 					TPsbsend, &elapsed, newseq, tpcb->tp_Nwindow, npkts);		}	ENDPERF#endif /* TP_PERF_MEAS */	IFTRACE(D_DATA)		tptraceTPCB( TPPTmisc, 			"tp_send at end: new nxt eotsdu error",			tpcb->tp_sndnew, tpcb->tp_sndnxt, eotsdu, tpcb->tp_sock->so_error);			ENDTRACE}int TPNagleok;int TPNagled;tp_packetize(tpcb, m, eotsdu)register struct tp_pcb *tpcb;register struct mbuf *m;int eotsdu;{	register struct mbuf *n;	register struct sockbuf *sb = &tpcb->tp_sock->so_snd;	int	maxsize = tpcb->tp_l_tpdusize 			- tp_headersize(DT_TPDU_type, tpcb)			- (tpcb->tp_use_checksum?4:0) ;	int totlen = m->m_pkthdr.len;	struct mbuf *m_split();	/*	 * Pre-packetize the data in the sockbuf	 * according to negotiated mtu.  Do it here	 * where we can safely wait for mbufs.	 *	 * This presumes knowledge of sockbuf conventions.	 * TODO: allocate space for header and fill it in (once!).	 */	IFDEBUG(D_DATA)		printf("SEND BF: maxsize %d totlen %d eotsdu %d sndnum 0x%x\n",			maxsize, totlen, eotsdu, tpcb->tp_sndnum);	ENDTRACE	if (tpcb->tp_oktonagle) {		if ((n = sb->sb_mb) == 0)			panic("tp_packetize");		while (n->m_act)			n = n->m_act;		if (n->m_flags & M_EOR)			panic("tp_packetize 2");		SEQ_INC(tpcb, tpcb->tp_sndnum);		if (totlen + n->m_pkthdr.len < maxsize) {			/* There is an unsent packet with space, combine data */			struct mbuf *old_n = n;			tpsbcheck(tpcb,3);			n->m_pkthdr.len += totlen;			while (n->m_next)				n = n->m_next;			sbcompress(sb, m, n);			tpsbcheck(tpcb,4);			n = old_n;			TPNagled++;			goto out;		}	}	while (m) {		n = m;		if (totlen > maxsize) {			if ((m = m_split(n, maxsize, M_WAIT)) == 0)				panic("tp_packetize");		} else			m = 0;		totlen -= maxsize;		tpsbcheck(tpcb, 5);		sbappendrecord(sb, n);		tpsbcheck(tpcb, 6);		SEQ_INC(tpcb, tpcb->tp_sndnum);	}out:	if (eotsdu) {		n->m_flags |= M_EOR;  /* XXX belongs at end */		tpcb->tp_oktonagle = 0;	} else {		SEQ_DEC(tpcb, tpcb->tp_sndnum);		tpcb->tp_oktonagle = 1;		TPNagleok++;	}	IFDEBUG(D_DATA)		printf("SEND out: oktonagle %d sndnum 0x%x\n",			tpcb->tp_oktonagle, tpcb->tp_sndnum);	ENDTRACE	return 0;}/* * NAME: tp_stash() * CALLED FROM: *	tp.trans on arrival of a DT tpdu * FUNCTION, ARGUMENTS, and RETURN VALUE: * 	Returns 1 if  *		a) something new arrived and it's got eotsdu_reached bit on, * 		b) this arrival was caused other out-of-sequence things to be *    	accepted, or * 		c) this arrival is the highest seq # for which we last gave credit *   	(sender just sent a whole window) *  In other words, returns 1 if tp should send an ack immediately, 0 if  *  the ack can wait a while. * * Note: this implementation no longer renegs on credit, (except * when debugging option D_RENEG is on, for the purpose of testing * ack subsequencing), so we don't  need to check for incoming tpdus  * being in a reneged portion of the window. */tp_stash(tpcb, e)	register struct tp_pcb		*tpcb;	register struct tp_event	*e;{	register int		ack_reason= tpcb->tp_ack_strat & ACK_STRAT_EACH;									/* 0--> delay acks until full window */									/* 1--> ack each tpdu */#ifndef lint#define E e->ATTR(DT_TPDU)#else /* lint */#define E e->ev_union.EV_DT_TPDU#endif /* lint */	if ( E.e_eot ) {		register struct mbuf *n = E.e_data;		n->m_flags |= M_EOR;		n->m_act = 0;	}		IFDEBUG(D_STASH)			dump_mbuf(tpcb->tp_sock->so_rcv.sb_mb, 				"stash: so_rcv before appending");			dump_mbuf(E.e_data,				"stash: e_data before appending");		ENDDEBUG	IFPERF(tpcb)		PStat(tpcb, Nb_from_ll) += E.e_datalen;		tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,			E.e_seq, (u_int)PStat(tpcb, Nb_from_ll), (u_int)E.e_datalen);	ENDPERF	if (E.e_seq == tpcb->tp_rcvnxt) {		IFDEBUG(D_STASH)			printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x\n", 			E.e_seq, E.e_datalen, E.e_eot);		ENDDEBUG		IFTRACE(D_STASH)			tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", 			E.e_seq, E.e_datalen, E.e_eot, 0);		ENDTRACE		SET_DELACK(tpcb);		sbappend(&tpcb->tp_sock->so_rcv, E.e_data);		SEQ_INC( tpcb, tpcb->tp_rcvnxt );		/* 		 * move chains from the reassembly queue to the socket buffer		 */		if (tpcb->tp_rsycnt) {			register struct mbuf **mp;			struct mbuf **mplim;			mp = tpcb->tp_rsyq + (tpcb->tp_rcvnxt % tpcb->tp_maxlcredit);			mplim = tpcb->tp_rsyq + tpcb->tp_maxlcredit;			while (tpcb->tp_rsycnt && *mp) {				sbappend(&tpcb->tp_sock->so_rcv, *mp);				tpcb->tp_rsycnt--;				*mp = 0;				SEQ_INC(tpcb, tpcb->tp_rcvnxt);				ack_reason |= ACK_REORDER;				if (++mp == mplim)					mp = tpcb->tp_rsyq;			}		}		IFDEBUG(D_STASH)			dump_mbuf(tpcb->tp_sock->so_rcv.sb_mb, 				"stash: so_rcv after appending");		ENDDEBUG	} else {		register struct mbuf **mp;		SeqNum uwe;		IFTRACE(D_STASH)			tptraceTPCB(TPPTmisc, "stash Reseq: seq rcvnxt lcdt", 			E.e_seq, tpcb->tp_rcvnxt, tpcb->tp_lcredit, 0);		ENDTRACE		if (tpcb->tp_rsyq == 0)			tp_rsyset(tpcb);		uwe = SEQ(tpcb, tpcb->tp_rcvnxt + tpcb->tp_maxlcredit);		if (tpcb->tp_rsyq == 0 ||						!IN_RWINDOW(tpcb, E.e_seq, tpcb->tp_rcvnxt, uwe)) {			ack_reason = ACK_DONT;			m_freem(E.e_data);		} else if (*(mp = tpcb->tp_rsyq + (E.e_seq % tpcb->tp_maxlcredit))) {			IFDEBUG(D_STASH)				printf("tp_stash - drop & ack\n");			ENDDEBUG			/* retransmission - drop it and force an ack */			IncStat(ts_dt_dup);			IFPERF(tpcb)				IncPStat(tpcb, tps_n_ack_cuz_dup);			ENDPERF			m_freem(E.e_data);			ack_reason |= ACK_DUP;		} else {			*mp = E.e_data;			tpcb->tp_rsycnt++;			ack_reason = ACK_DONT;		}	}	/* there were some comments of historical interest here. */	{		LOCAL_CREDIT(tpcb);		if ( E.e_seq ==  tpcb->tp_sent_uwe )			ack_reason |= ACK_STRAT_FULLWIN;		IFTRACE(D_STASH)			tptraceTPCB(TPPTmisc, 				"end of stash, eot, ack_reason, sent_uwe ",				E.e_eot, ack_reason, tpcb->tp_sent_uwe, 0); 		ENDTRACE		if ( ack_reason == ACK_DONT ) {			IncStat( ts_ackreason[ACK_DONT] );			return 0;		} else {			IFPERF(tpcb)				if(ack_reason & ACK_STRAT_EACH) {					IncPStat(tpcb, tps_n_ack_cuz_strat);				} else if(ack_reason & ACK_STRAT_FULLWIN) {					IncPStat(tpcb, tps_n_ack_cuz_fullwin);				} else if(ack_reason & ACK_REORDER) {					IncPStat(tpcb, tps_n_ack_cuz_reorder);				}				tpmeas(tpcb->tp_lref, TPtime_ack_sent, 0, 							SEQ_ADD(tpcb, E.e_seq, 1), 0, 0);			ENDPERF			{				register int i;				/* keep track of all reasons that apply */				for( i=1; i<_ACK_NUM_REASONS_ ;i++) {					if( ack_reason & (1<<i) ) 						IncStat( ts_ackreason[i] );				}			}			return 1;		}	}}/* * tp_rsyflush - drop all the packets on the reassembly queue. * Do this when closing the socket, or when somebody has changed * the space avaible in the receive socket (XXX). */tp_rsyflush(tpcb)register struct tp_pcb *tpcb;{	register struct mbuf *m, **mp;	if (tpcb->tp_rsycnt) {		for (mp == tpcb->tp_rsyq + tpcb->tp_maxlcredit;									 --mp >= tpcb->tp_rsyq; )			if (*mp) {				tpcb->tp_rsycnt--;				m_freem(*mp);			}		if (tpcb->tp_rsycnt) {			printf("tp_rsyflush %x\n", tpcb);			tpcb->tp_rsycnt = 0;		}	}	free((caddr_t)tpcb->tp_rsyq, M_PCB);	tpcb->tp_rsyq = 0;}tp_rsyset(tpcb)register struct tp_pcb *tpcb;{	register struct socket *so = tpcb->tp_sock;	int maxcredit  = tpcb->tp_xtd_format ? 0xffff : 0xf;	int old_credit = tpcb->tp_maxlcredit;	caddr_t	rsyq;	tpcb->tp_maxlcredit = maxcredit = min(maxcredit,		  (so->so_rcv.sb_hiwat + tpcb->tp_l_tpdusize)/ tpcb->tp_l_tpdusize);	if (old_credit == tpcb->tp_maxlcredit && tpcb->tp_rsyq != 0)		return;	maxcredit *= sizeof(struct mbuf *);	if (tpcb->tp_rsyq)		tp_rsyflush(tpcb);	if (rsyq = (caddr_t)malloc(maxcredit, M_PCB, M_NOWAIT))		bzero(rsyq, maxcredit);	tpcb->tp_rsyq = (struct mbuf **)rsyq;}tpsbcheck(tpcb, i)struct tp_pcb *tpcb;{	register struct mbuf *n, *m;	register int len = 0, mbcnt = 0, pktlen;	struct sockbuf *sb = &tpcb->tp_sock->so_snd;	for (n = sb->sb_mb; n; n = n->m_nextpkt) {		if ((n->m_flags & M_PKTHDR) == 0)			panic("tpsbcheck nohdr");		pktlen = len + n->m_pkthdr.len;	    for (m = n; m; m = m->m_next) {			len += m->m_len;			mbcnt += MSIZE;			if (m->m_flags & M_EXT)				mbcnt += m->m_ext.ext_size;		}		if (len != pktlen) {			printf("test %d; len %d != pktlen %d on mbuf 0x%x\n",				i, len, pktlen, n);			panic("tpsbcheck short");		}	}	if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {		printf("test %d: cc %d != %d || mbcnt %d != %d\n", i, len, sb->sb_cc,		    mbcnt, sb->sb_mbcnt);		panic("tpsbcheck");	}}

⌨️ 快捷键说明

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