xref: /csrg-svn/sys/netinet/tcp_output.c (revision 5075)
1*5075Swnj /*	tcp_output.c	4.18	81/11/25	*/
24677Swnj 
34677Swnj #include "../h/param.h"
44677Swnj #include "../h/systm.h"
54677Swnj #include "../h/mbuf.h"
64677Swnj #include "../h/socket.h"
74804Swnj #include "../h/socketvar.h"
84804Swnj #include "../net/inet.h"
94885Swnj #include "../net/inet_pcb.h"
104804Swnj #include "../net/inet_systm.h"
114804Swnj #include "../net/imp.h"
124804Swnj #include "../net/ip.h"
134900Swnj #include "../net/ip_var.h"
144804Swnj #include "../net/tcp.h"
154804Swnj #include "../net/tcp_var.h"
164804Swnj #include "../net/tcp_fsm.h"
174804Swnj #include "/usr/include/errno.h"
184677Swnj 
194678Swnj /*
20*5075Swnj  * Tcp output routine: figure out what should be sent
21*5075Swnj  * and, if nothing, send a null segment anyways if force is nonzero
22*5075Swnj  * (e.g. to be sure to send an ACK).
23*5075Swnj  *
24*5075Swnj  * This routine can be called only after SYNs have been exchanged.
254678Swnj  */
26*5075Swnj tcp_output(tp)
27*5075Swnj 	register struct tcpcb *tp;
284678Swnj {
29*5075Swnj 	register struct socket *so = tp->t_inpcb->inp_socket;
30*5075Swnj 	register int len;
31*5075Swnj 	struct mbuf *m0;
32*5075Swnj 	int off, flags;
33*5075Swnj 	register struct mbuf *m;
34*5075Swnj 	register struct tcpiphdr *ti;
35*5075Swnj 	int win;
364678Swnj 
37*5075Swnj COUNT(TCP_OUTPUT);
384678Swnj 
39*5075Swnj 	/*
40*5075Swnj 	 * Determine length of data that can be transmitted.
41*5075Swnj 	 * If will transmit to end of data and no more data
42*5075Swnj 	 * is coming, then send FIN also.
43*5075Swnj 	 * Make a copy of the data (if any).  If no data
44*5075Swnj 	 * and not forced to transmit, just return.
45*5075Swnj 	 */
46*5075Swnj 	off = tp->snd_nxt - tp->snd_una;
47*5075Swnj 	len = MIN(so->so_snd.sb_cc, tp->snd_wnd) - off;
48*5075Swnj 	if (len > tp->mtu)
49*5075Swnj 		len = tp->mtu;
50*5075Swnj 	if (len == so->so_snd.sb_cc && (so->so_state & SS_CANTSNDMORE))
51*5075Swnj 		flags = TH_FIN;
52*5075Swnj 	else
53*5075Swnj 		flags = 0;
54*5075Swnj 	if (len)
55*5075Swnj 		goto send;
564678Swnj 
57*5075Swnj 	/*
58*5075Swnj 	 * No data to send: see if something else makes us want to send.
59*5075Swnj 	 * First check if we owe peer and ack or have a unacked FIN to send.
60*5075Swnj 	 */
61*5075Swnj 	if (tp->t_flags & TF_OWEACK)
62*5075Swnj 		goto send;
63*5075Swnj 	if ((so->so_state & SS_CANTSNDMORE) &&
64*5075Swnj 	    TCPS_OURFINISACKED(tp->t_state) == 0)
65*5075Swnj 		goto send;
66*5075Swnj 	if (tp->t_state == TCPS_SYN_SENT) {
67*5075Swnj 		flags = TH_SYN;
68*5075Swnj 		goto send;
694678Swnj 	}
70*5075Swnj 	if (tp->t_state == TCPS_CLOSED) {
71*5075Swnj 		flags = TH_RST;
72*5075Swnj 		goto send;
73*5075Swnj 	}
744678Swnj 
75*5075Swnj 	/*
76*5075Swnj 	 * Calculate available window in i, and also amount
77*5075Swnj 	 * of window known to peer (as advertised window less
78*5075Swnj 	 * next expected input.)  If this is 35% or more of the
79*5075Swnj 	 * maximum possible window, then want to send a segment to peer.
80*5075Swnj 	 */
81*5075Swnj 	i = sbspace(&so->so_rcv) - tp->seqcnt;
82*5075Swnj 	if (i > 0 &&
83*5075Swnj 	    ((100*(i-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35))
84*5075Swnj 		goto send;
854678Swnj 
86*5075Swnj 	/*
87*5075Swnj 	 * No reason to send a segment, just return.
88*5075Swnj 	 */
89*5075Swnj 	return;
904678Swnj 
91*5075Swnj send:
92*5075Swnj 	/*
93*5075Swnj 	 * Grab a header mbuf, attaching a copy of data to
94*5075Swnj 	 * be transmitted, and initialize the header from
95*5075Swnj 	 * the template for sends on this connection.
96*5075Swnj 	 */
974677Swnj 	MGET(m, 0);
984677Swnj 	if (m == 0)
994677Swnj 		return (0);
1004885Swnj 	m->m_off = MMAXOFF - sizeof(struct tcpiphdr);
1014885Swnj 	m->m_len = sizeof (struct tcpiphdr);
102*5075Swnj 	if (len) {
103*5075Swnj 		m->m_next = m_copy(so->so_snd.sb_mb, off, len);
104*5075Swnj 		if (m->m_next == 0)
105*5075Swnj 			len = 0;
106*5075Swnj 	}
107*5075Swnj 	ti = mtod(m, struct tcpiphdr *);
108*5075Swnj 	if (tp->t_template == 0)
109*5075Swnj 		panic("tcp_output");
110*5075Swnj 	bcopy((caddr_t)tp->t_template, ti, sizeof (struct tcpiphdr));
111*5075Swnj 
112*5075Swnj 	/*
113*5075Swnj 	 * Fill in fields, remembering maximum advertised
114*5075Swnj 	 * window for use in delaying messages about window sizes.
115*5075Swnj 	 */
116*5075Swnj 	ti->ti_seq = htonl(tp->snd_nxt);
117*5075Swnj 	ti->ti_ackno = htonl(tp->rcv_nxt);
118*5075Swnj 	/* OPTIONS */
1194677Swnj 	if (flags & TH_SYN)
120*5075Swnj 		ti->ti_flags = flags;
121*5075Swnj 	else
122*5075Swnj 		ti->ti_flags = flags | TH_ACK;
123*5075Swnj 	win = sbspace(&so->so_rcv);
124*5075Swnj 	if (win > 0)
125*5075Swnj 		ti->ti_win = htons(win);
126*5075Swnj 	if (SEQ_GT(tp->snd_urp, tp->snd_nxt))
127*5075Swnj 		ti->ti_urp = htons((u_short)(tp->snd_urp - tp->snd_nxt));
128*5075Swnj 		ti->ti_flags |= TH_URG;
129*5075Swnj 	} else
130*5075Swnj 		/*
131*5075Swnj 		 * If no urgent pointer to send, then we pull
132*5075Swnj 		 * the urgent pointer to the left edge of the send window
133*5075Swnj 		 * so that it doesn't drift into the send window on sequence
134*5075Swnj 		 * number wraparound.
135*5075Swnj 		 */
136*5075Swnj 		tp->snd_urp = tp->snd_una;		/* drag it along */
137*5075Swnj 
138*5075Swnj 	/*
139*5075Swnj 	 * Put TCP length in extended header, and then
140*5075Swnj 	 * checksum extended header and data.
141*5075Swnj 	 */
142*5075Swnj 	if (len)
143*5075Swnj 		ti->ti_len = htons((u_short)(len + sizeof (struct tcphdr)));
144*5075Swnj 	ti->ti_sum = inet_cksum(m, sizeof (struct tcpiphdr) + len);
145*5075Swnj 
146*5075Swnj 	/*
147*5075Swnj 	 * Fill in IP length and desired time to live and
148*5075Swnj 	 * send to IP level.
149*5075Swnj 	 */
150*5075Swnj 	((struct ip *)ti)->ip_len = len + sizeof (struct tcpiphdr);
151*5075Swnj 	((struct ip *)ti)->ip_ttl = TCP_TTL;
152*5075Swnj 	if (ip_output(m) == 0)
153*5075Swnj 		return;
154*5075Swnj 
155*5075Swnj 	/*
156*5075Swnj 	 * Data sent (as far as we can tell).
157*5075Swnj 	 * If this advertises a larger window than any other segment,
158*5075Swnj 	 * then record its sequence to be used in suppressing messages.
159*5075Swnj 	 * Advance snd_nxt to reflect transmitted sequence space,
160*5075Swnj 	 * drop send for purpose of ACK requirements,
161*5075Swnj 	 * and time transmission if not a retransmit.
162*5075Swnj 	 */
163*5075Swnj 	if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
164*5075Swnj 		tp->rcv_adv = tp->rcv_nxt + win;
165*5075Swnj 	tp->snd_nxt += len;
166*5075Swnj 	tp->t_flags &= ~(TF_OWEACK|TF_DELACK);
1674677Swnj 	if (flags & TH_FIN)
168*5075Swnj 		tp->snd_nxt++;
169*5075Swnj 	if (SEQ_GT(tp->snd_nxt, tp->snd_hi)) {
170*5075Swnj 		tp->snd_hi = tp->snd_nxt;
171*5075Swnj 		/* TIME TRANSMIT */
1724677Swnj 	}
173*5075Swnj 	return;
1744677Swnj }
175