|
|
1.1 root 1: /* tcp_output.c 6.1 83/07/29 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/mbuf.h"
6: #include "../h/protosw.h"
7: #include "../h/socket.h"
8: #include "../h/socketvar.h"
9: #include "../h/errno.h"
10:
11: #include "../net/route.h"
12:
13: #include "../netinet/in.h"
14: #include "../netinet/in_pcb.h"
15: #include "../netinet/in_systm.h"
16: #include "../netinet/ip.h"
17: #include "../netinet/ip_var.h"
18: #include "../netinet/tcp.h"
19: #define TCPOUTFLAGS
20: #include "../netinet/tcp_fsm.h"
21: #include "../netinet/tcp_seq.h"
22: #include "../netinet/tcp_timer.h"
23: #include "../netinet/tcp_var.h"
24: #include "../netinet/tcpip.h"
25: #include "../netinet/tcp_debug.h"
26:
27: /*
28: * Initial options.
29: */
30: u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, };
31:
32: /*
33: * Tcp output routine: figure out what should be sent and send it.
34: */
35: tcp_output(tp)
36: register struct tcpcb *tp;
37: {
38: register struct socket *so = tp->t_inpcb->inp_socket;
39: register int len;
40: struct mbuf *m0;
41: int off, flags, win, error;
42: register struct mbuf *m;
43: register struct tcpiphdr *ti;
44: u_char *opt;
45: unsigned optlen = 0;
46: int sendalot;
47:
48: /*
49: * Determine length of data that should be transmitted,
50: * and flags that will be used.
51: * If there is some data or critical controls (SYN, RST)
52: * to send, then transmit; otherwise, investigate further.
53: */
54: again:
55: sendalot = 0;
56: off = tp->snd_nxt - tp->snd_una;
57: len = MIN(so->so_snd.sb_cc, tp->snd_wnd+tp->t_force) - off;
58: if (len < 0)
59: return (0); /* ??? */ /* past FIN */
60: if (len > tp->t_maxseg) {
61: len = tp->t_maxseg;
62: sendalot = 1;
63: }
64:
65: flags = tcp_outflags[tp->t_state];
66: if (tp->snd_nxt + len < tp->snd_una + so->so_snd.sb_cc)
67: flags &= ~TH_FIN;
68: if (flags & (TH_SYN|TH_RST|TH_FIN))
69: goto send;
70: if (SEQ_GT(tp->snd_up, tp->snd_una))
71: goto send;
72:
73: /*
74: * Sender silly window avoidance. If can send all data,
75: * a maximum segment, at least 1/4 of window do it,
76: * or are forced, do it; otherwise don't bother.
77: */
78: if (len) {
79: if (len == tp->t_maxseg || off+len >= so->so_snd.sb_cc)
80: goto send;
81: if (len * 4 >= tp->snd_wnd) /* a lot */
82: goto send;
83: if (tp->t_force)
84: goto send;
85: }
86:
87: /*
88: * Send if we owe peer an ACK.
89: */
90: if (tp->t_flags&TF_ACKNOW)
91: goto send;
92:
93:
94: /*
95: * Calculate available window in i, and also amount
96: * of window known to peer (as advertised window less
97: * next expected input.) If this is 35% or more of the
98: * maximum possible window, then want to send a segment to peer.
99: */
100: win = sbspace(&so->so_rcv);
101: if (win > 0 &&
102: ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35))
103: goto send;
104:
105: /*
106: * TCP window updates are not reliable, rather a polling protocol
107: * using ``persist'' packets is used to insure receipt of window
108: * updates. The three ``states'' for the output side are:
109: * idle not doing retransmits or persists
110: * persisting to move a zero window
111: * (re)transmitting and thereby not persisting
112: *
113: * tp->t_timer[TCPT_PERSIST]
114: * is set when we are in persist state.
115: * tp->t_force
116: * is set when we are called to send a persist packet.
117: * tp->t_timer[TCPT_REXMT]
118: * is set when we are retransmitting
119: * The output side is idle when both timers are zero.
120: *
121: * If send window is closed, there is data to transmit, and no
122: * retransmit or persist is pending, then go to persist state,
123: * arranging to force out a byte to get more current window information
124: * if nothing happens soon.
125: */
126: if (tp->snd_wnd == 0 && so->so_snd.sb_cc &&
127: tp->t_timer[TCPT_REXMT] == 0 && tp->t_timer[TCPT_PERSIST] == 0) {
128: tp->t_rxtshift = 0;
129: tcp_setpersist(tp);
130: }
131:
132: /*
133: * No reason to send a segment, just return.
134: */
135: return (0);
136:
137: send:
138: /*
139: * Grab a header mbuf, attaching a copy of data to
140: * be transmitted, and initialize the header from
141: * the template for sends on this connection.
142: */
143: MGET(m, M_DONTWAIT, MT_HEADER);
144: if (m == NULL)
145: return (ENOBUFS);
146: m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
147: m->m_len = sizeof (struct tcpiphdr);
148: if (len) {
149: m->m_next = m_copy(so->so_snd.sb_mb, off, len);
150: if (m->m_next == 0)
151: len = 0;
152: }
153: ti = mtod(m, struct tcpiphdr *);
154: if (tp->t_template == 0)
155: panic("tcp_output");
156: bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr));
157:
158: /*
159: * Fill in fields, remembering maximum advertised
160: * window for use in delaying messages about window sizes.
161: */
162: ti->ti_seq = tp->snd_nxt;
163: ti->ti_ack = tp->rcv_nxt;
164: ti->ti_seq = htonl(ti->ti_seq);
165: ti->ti_ack = htonl(ti->ti_ack);
166: /*
167: * Before ESTABLISHED, force sending of initial options
168: * unless TCP set to not do any options.
169: */
170: if (tp->t_state < TCPS_ESTABLISHED) {
171: if (tp->t_flags&TF_NOOPT)
172: goto noopt;
173: opt = tcp_initopt;
174: optlen = sizeof (tcp_initopt);
175: *(u_short *)(opt + 2) = MIN(so->so_rcv.sb_hiwat / 2, 1024);
176: *(u_short *)(opt + 2) = htons(*(u_short *)(opt + 2));
177: } else {
178: if (tp->t_tcpopt == 0)
179: goto noopt;
180: opt = mtod(tp->t_tcpopt, u_char *);
181: optlen = tp->t_tcpopt->m_len;
182: }
183: if (opt) {
184: m0 = m->m_next;
185: m->m_next = m_get(M_DONTWAIT, MT_DATA);
186: if (m->m_next == 0) {
187: (void) m_free(m);
188: m_freem(m0);
189: return (ENOBUFS);
190: }
191: m->m_next->m_next = m0;
192: m0 = m->m_next;
193: m0->m_len = optlen;
194: bcopy((caddr_t)opt, mtod(m0, caddr_t), optlen);
195: opt = (u_char *)(mtod(m0, caddr_t) + optlen);
196: while (m0->m_len & 0x3) {
197: *opt++ = TCPOPT_EOL;
198: m0->m_len++;
199: }
200: optlen = m0->m_len;
201: ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
202: }
203: noopt:
204: ti->ti_flags = flags;
205: win = sbspace(&so->so_rcv);
206: if (win < so->so_rcv.sb_hiwat / 4) /* avoid silly window */
207: win = 0;
208: if (win > 0)
209: ti->ti_win = htons((u_short)win);
210: if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
211: ti->ti_urp = tp->snd_up - tp->snd_nxt;
212: ti->ti_urp = htons(ti->ti_urp);
213: ti->ti_flags |= TH_URG;
214: } else
215: /*
216: * If no urgent pointer to send, then we pull
217: * the urgent pointer to the left edge of the send window
218: * so that it doesn't drift into the send window on sequence
219: * number wraparound.
220: */
221: tp->snd_up = tp->snd_una; /* drag it along */
222: /*
223: * If anything to send and we can send it all, set PUSH.
224: * (This will keep happy those implementations which only
225: * give data to the user when a buffer fills or a PUSH comes in.)
226: */
227: if (len && off+len == so->so_snd.sb_cc)
228: ti->ti_flags |= TH_PUSH;
229:
230: /*
231: * Put TCP length in extended header, and then
232: * checksum extended header and data.
233: */
234: if (len + optlen) {
235: ti->ti_len = sizeof (struct tcphdr) + optlen + len;
236: ti->ti_len = htons((u_short)ti->ti_len);
237: }
238: ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int)optlen + len);
239:
240: /*
241: * In transmit state, time the transmission and arrange for
242: * the retransmit. In persist state, reset persist time for
243: * next persist.
244: */
245: if (tp->t_force == 0) {
246: /*
247: * Advance snd_nxt over sequence space of this segment.
248: */
249: if (flags & (TH_SYN|TH_FIN))
250: tp->snd_nxt++;
251: tp->snd_nxt += len;
252: if (SEQ_GT(tp->snd_nxt, tp->snd_max))
253: tp->snd_max = tp->snd_nxt;
254:
255: /*
256: * Time this transmission if not a retransmission and
257: * not currently timing anything.
258: */
259: if (SEQ_GT(tp->snd_nxt, tp->snd_max) && tp->t_rtt == 0) {
260: tp->t_rtt = 1;
261: tp->t_rtseq = tp->snd_nxt - len;
262: }
263:
264: /*
265: * Set retransmit timer if not currently set.
266: * Initial value for retransmit timer to tcp_beta*tp->t_srtt.
267: * Initialize shift counter which is used for exponential
268: * backoff of retransmit time.
269: */
270: if (tp->t_timer[TCPT_REXMT] == 0 &&
271: tp->snd_nxt != tp->snd_una) {
272: TCPT_RANGESET(tp->t_timer[TCPT_REXMT],
273: tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX);
274: tp->t_rtt = 0;
275: tp->t_rxtshift = 0;
276: }
277: tp->t_timer[TCPT_PERSIST] = 0;
278: } else {
279: if (SEQ_GT(tp->snd_una+1, tp->snd_max))
280: tp->snd_max = tp->snd_una+1;
281: }
282:
283: /*
284: * Trace.
285: */
286: if (so->so_options & SO_DEBUG)
287: tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0);
288:
289: /*
290: * Fill in IP length and desired time to live and
291: * send to IP level.
292: */
293: ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len;
294: ((struct ip *)ti)->ip_ttl = TCP_TTL;
295: if (so->so_options & SO_DONTROUTE)
296: error =
297: ip_output(m, tp->t_ipopt, (struct route *)0, IP_ROUTETOIF);
298: else
299: error = ip_output(m, tp->t_ipopt, &tp->t_inpcb->inp_route, 0);
300: if (error)
301: return (error);
302:
303: /*
304: * Data sent (as far as we can tell).
305: * If this advertises a larger window than any other segment,
306: * then remember the size of the advertised window.
307: * Drop send for purpose of ACK requirements.
308: */
309: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
310: tp->rcv_adv = tp->rcv_nxt + win;
311: tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
312: if (sendalot && tp->t_force == 0)
313: goto again;
314: return (0);
315: }
316:
317: tcp_setpersist(tp)
318: register struct tcpcb *tp;
319: {
320:
321: if (tp->t_timer[TCPT_REXMT])
322: panic("tcp_output REXMT");
323: /*
324: * Start/restart persistance timer.
325: */
326: TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
327: ((int)(tcp_beta * tp->t_srtt)) << tp->t_rxtshift,
328: TCPTV_PERSMIN, TCPTV_MAX);
329: tp->t_rxtshift++;
330: if (tp->t_rxtshift >= TCP_MAXRXTSHIFT)
331: tp->t_rxtshift = 0;
332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.