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