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