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

📄 tcp_output.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 	}  	/*	 * Send a timestamp and echo-reply if this is a SYN and our side 	 * wants to use timestamps (TF_REQ_TSTMP is set) or both our side	 * and our peer have sent timestamps in our SYN's. 	 *//* 	if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && *	     (flags & TH_RST) == 0 && *	    ((flags & (TH_SYN|TH_ACK)) == TH_SYN || *	     (tp->t_flags & TF_RCVD_TSTMP))) { *		u_int32_t *lp = (u_int32_t *)(opt + optlen); * *		/ * Form timestamp option as shown in appendix A of RFC 1323. *  / *		*lp++ = htonl(TCPOPT_TSTAMP_HDR); *		*lp++ = htonl(tcp_now); *		*lp   = htonl(tp->ts_recent); *		optlen += TCPOLEN_TSTAMP_APPA; *	} */ 	hdrlen += optlen; 	/*	 * Adjust data length if insertion of options will	 * bump the packet length beyond the t_maxseg length.	 */	 if (len > tp->t_maxseg - optlen) {		len = tp->t_maxseg - optlen;		sendalot = 1;	 }	/*	 * Grab a header mbuf, attaching a copy of data to	 * be transmitted, and initialize the header from	 * the template for sends on this connection.	 */	if (len) {		if (tp->t_force && len == 1)			tcpstat.tcps_sndprobe++;		else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {			tcpstat.tcps_sndrexmitpack++;			tcpstat.tcps_sndrexmitbyte += len;		} else {			tcpstat.tcps_sndpack++;			tcpstat.tcps_sndbyte += len;		}		m = m_get();		if (m == NULL) {/*			error = ENOBUFS; */			error = 1;			goto out;		}		m->m_data += if_maxlinkhdr;		m->m_len = hdrlen;				/* 		 * This will always succeed, since we make sure our mbufs		 * are big enough to hold one MSS packet + header + ... etc.		 *//*		if (len <= MHLEN - hdrlen - max_linkhdr) { */			sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);			m->m_len += len;/*		} else { *			m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); *			if (m->m_next == 0) *				len = 0; *		} */		/*		 * If we're sending everything we've got, set PUSH.		 * (This will keep happy those implementations which only		 * give data to the user when a buffer fills or		 * a PUSH comes in.)		 */		if (off + len == so->so_snd.sb_cc)			flags |= TH_PUSH;	} else {		if (tp->t_flags & TF_ACKNOW)			tcpstat.tcps_sndacks++;		else if (flags & (TH_SYN|TH_FIN|TH_RST))			tcpstat.tcps_sndctrl++;		else if (SEQ_GT(tp->snd_up, tp->snd_una))			tcpstat.tcps_sndurg++;		else			tcpstat.tcps_sndwinup++;		m = m_get();		if (m == NULL) {/*			error = ENOBUFS; */			error = 1;			goto out;		}		m->m_data += if_maxlinkhdr;		m->m_len = hdrlen;	}	ti = mtod(m, struct tcpiphdr *);		memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));	/*	 * Fill in fields, remembering maximum advertised	 * window for use in delaying messages about window sizes.	 * If resending a FIN, be sure not to use a new sequence number.	 */	if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && 	    tp->snd_nxt == tp->snd_max)		tp->snd_nxt--;	/*	 * If we are doing retransmissions, then snd_nxt will	 * not reflect the first unsent octet.  For ACK only	 * packets, we do not want the sequence number of the	 * retransmitted packet, we want the sequence number	 * of the next unsent octet.  So, if there is no data	 * (and no SYN or FIN), use snd_max instead of snd_nxt	 * when filling in ti_seq.  But if we are in persist	 * state, snd_max might reflect one byte beyond the	 * right edge of the window, so use snd_nxt in that	 * case, since we know we aren't doing a retransmission.	 * (retransmit and persist are mutually exclusive...)	 */	if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])		ti->ti_seq = htonl(tp->snd_nxt);	else		ti->ti_seq = htonl(tp->snd_max);	ti->ti_ack = htonl(tp->rcv_nxt);	if (optlen) {		memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);		ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;	}	ti->ti_flags = flags;	/*	 * Calculate receive window.  Don't shrink window,	 * but avoid silly window syndrome.	 */	if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)		win = 0;	if (win > (long)TCP_MAXWIN << tp->rcv_scale)		win = (long)TCP_MAXWIN << tp->rcv_scale;	if (win < (long)(tp->rcv_adv - tp->rcv_nxt))		win = (long)(tp->rcv_adv - tp->rcv_nxt);	ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));		if (SEQ_GT(tp->snd_up, tp->snd_una)) {		ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));#ifdef notdef			if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {		ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));#endif		ti->ti_flags |= TH_URG;	} else		/*		 * If no urgent pointer to send, then we pull		 * the urgent pointer to the left edge of the send window		 * so that it doesn't drift into the send window on sequence		 * number wraparound.		 */		tp->snd_up = tp->snd_una;		/* drag it along */	/*	 * Put TCP length in extended header, and then	 * checksum extended header and data.	 */	if (len + optlen)		ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) +		    optlen + len));	ti->ti_sum = cksum(m, (int)(hdrlen + len));	/*	 * In transmit state, time the transmission and arrange for	 * the retransmit.  In persist state, just set snd_max.	 */	if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {		tcp_seq startseq = tp->snd_nxt;		/*		 * Advance snd_nxt over sequence space of this segment.		 */		if (flags & (TH_SYN|TH_FIN)) {			if (flags & TH_SYN)				tp->snd_nxt++;			if (flags & TH_FIN) {				tp->snd_nxt++;				tp->t_flags |= TF_SENTFIN;			}		}		tp->snd_nxt += len;		if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {			tp->snd_max = tp->snd_nxt;			/*			 * Time this transmission if not a retransmission and			 * not currently timing anything.			 */			if (tp->t_rtt == 0) {				tp->t_rtt = 1;				tp->t_rtseq = startseq;				tcpstat.tcps_segstimed++;			}		}		/*		 * Set retransmit timer if not currently set,		 * and not doing an ack or a keep-alive probe.		 * 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 (tp->t_timer[TCPT_REXMT] == 0 &&		    tp->snd_nxt != tp->snd_una) {			tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;			if (tp->t_timer[TCPT_PERSIST]) {				tp->t_timer[TCPT_PERSIST] = 0;				tp->t_rxtshift = 0;			}		}	} else		if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))			tp->snd_max = tp->snd_nxt + len;	/*	 * Fill in IP length and desired time to live and	 * send to IP level.  There should be a better way	 * to handle ttl and tos; we could keep them in	 * the template, but need a way to checksum without them.	 */	m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */	    {	    	((struct ip *)ti)->ip_len = m->m_len;	((struct ip *)ti)->ip_ttl = ip_defttl;	((struct ip *)ti)->ip_tos = so->so_iptos;	    /* #if BSD >= 43 */	/* Don't do IP options... *//*	error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, *	    so->so_options & SO_DONTROUTE, 0); */	error = ip_output(so, m);/* #else *	error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,  *	    so->so_options & SO_DONTROUTE); * #endif */    }	if (error) {out:/*		if (error == ENOBUFS) { *			tcp_quench(tp->t_inpcb, 0); *			return (0); *		} *//*		if ((error == EHOSTUNREACH || error == ENETDOWN) *		    && TCPS_HAVERCVDSYN(tp->t_state)) { *			tp->t_softerror = error; *			return (0); *		} */		return (error);	}	tcpstat.tcps_sndtotal++;	/*	 * Data sent (as far as we can tell).	 * If this advertises a larger window than any other segment,	 * then remember the size of the advertised window.	 * Any pending ACK has now been sent.	 */	if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))		tp->rcv_adv = tp->rcv_nxt + win;	tp->last_ack_sent = tp->rcv_nxt;	tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);	if (sendalot)		goto again;	return (0);}voidtcp_setpersist(tp)	register struct tcpcb *tp;{    int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;/*	if (tp->t_timer[TCPT_REXMT]) *		panic("tcp_output REXMT"); */	/*	 * Start/restart persistence timer.	 */	TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],	    t * tcp_backoff[tp->t_rxtshift],	    TCPTV_PERSMIN, TCPTV_PERSMAX);	if (tp->t_rxtshift < TCP_MAXRXTSHIFT)		tp->t_rxtshift++;}

⌨️ 快捷键说明

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