root / slirp / tcp_output.c @ 65850a02
History | View | Annotate | Download (14.1 kB)
1 | f0cbd3ec | bellard | /*
|
---|---|---|---|
2 | f0cbd3ec | bellard | * Copyright (c) 1982, 1986, 1988, 1990, 1993
|
3 | f0cbd3ec | bellard | * The Regents of the University of California. All rights reserved.
|
4 | f0cbd3ec | bellard | *
|
5 | f0cbd3ec | bellard | * Redistribution and use in source and binary forms, with or without
|
6 | f0cbd3ec | bellard | * modification, are permitted provided that the following conditions
|
7 | f0cbd3ec | bellard | * are met:
|
8 | f0cbd3ec | bellard | * 1. Redistributions of source code must retain the above copyright
|
9 | f0cbd3ec | bellard | * notice, this list of conditions and the following disclaimer.
|
10 | f0cbd3ec | bellard | * 2. Redistributions in binary form must reproduce the above copyright
|
11 | f0cbd3ec | bellard | * notice, this list of conditions and the following disclaimer in the
|
12 | f0cbd3ec | bellard | * documentation and/or other materials provided with the distribution.
|
13 | 2f5f8996 | aliguori | * 3. Neither the name of the University nor the names of its contributors
|
14 | f0cbd3ec | bellard | * may be used to endorse or promote products derived from this software
|
15 | f0cbd3ec | bellard | * without specific prior written permission.
|
16 | f0cbd3ec | bellard | *
|
17 | f0cbd3ec | bellard | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
18 | f0cbd3ec | bellard | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 | f0cbd3ec | bellard | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 | f0cbd3ec | bellard | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
21 | f0cbd3ec | bellard | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 | f0cbd3ec | bellard | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 | f0cbd3ec | bellard | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 | f0cbd3ec | bellard | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | f0cbd3ec | bellard | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 | f0cbd3ec | bellard | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 | f0cbd3ec | bellard | * SUCH DAMAGE.
|
28 | f0cbd3ec | bellard | *
|
29 | f0cbd3ec | bellard | * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
|
30 | f0cbd3ec | bellard | * tcp_output.c,v 1.3 1994/09/15 10:36:55 davidg Exp
|
31 | f0cbd3ec | bellard | */
|
32 | f0cbd3ec | bellard | |
33 | f0cbd3ec | bellard | /*
|
34 | f0cbd3ec | bellard | * Changes and additions relating to SLiRP
|
35 | f0cbd3ec | bellard | * Copyright (c) 1995 Danny Gasparovski.
|
36 | 5fafdf24 | ths | *
|
37 | 5fafdf24 | ths | * Please read the file COPYRIGHT for the
|
38 | f0cbd3ec | bellard | * terms and conditions of the copyright.
|
39 | f0cbd3ec | bellard | */
|
40 | f0cbd3ec | bellard | |
41 | f0cbd3ec | bellard | #include <slirp.h> |
42 | f0cbd3ec | bellard | |
43 | 9634d903 | blueswir1 | static const u_char tcp_outflags[TCP_NSTATES] = { |
44 | f0cbd3ec | bellard | TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
|
45 | 5fafdf24 | ths | TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, |
46 | f0cbd3ec | bellard | TH_FIN|TH_ACK, TH_ACK, TH_ACK, |
47 | f0cbd3ec | bellard | }; |
48 | f0cbd3ec | bellard | |
49 | f0cbd3ec | bellard | |
50 | f0cbd3ec | bellard | #define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ |
51 | f0cbd3ec | bellard | |
52 | f0cbd3ec | bellard | /*
|
53 | f0cbd3ec | bellard | * Tcp output routine: figure out what should be sent and send it.
|
54 | f0cbd3ec | bellard | */
|
55 | f0cbd3ec | bellard | int
|
56 | 511d2b14 | blueswir1 | tcp_output(struct tcpcb *tp)
|
57 | f0cbd3ec | bellard | { |
58 | f0cbd3ec | bellard | register struct socket *so = tp->t_socket; |
59 | f0cbd3ec | bellard | register long len, win; |
60 | f0cbd3ec | bellard | int off, flags, error;
|
61 | f0cbd3ec | bellard | register struct mbuf *m; |
62 | f0cbd3ec | bellard | register struct tcpiphdr *ti; |
63 | f0cbd3ec | bellard | u_char opt[MAX_TCPOPTLEN]; |
64 | f0cbd3ec | bellard | unsigned optlen, hdrlen;
|
65 | f0cbd3ec | bellard | int idle, sendalot;
|
66 | 5fafdf24 | ths | |
67 | f0cbd3ec | bellard | DEBUG_CALL("tcp_output");
|
68 | f0cbd3ec | bellard | DEBUG_ARG("tp = %lx", (long )tp); |
69 | 5fafdf24 | ths | |
70 | f0cbd3ec | bellard | /*
|
71 | f0cbd3ec | bellard | * Determine length of data that should be transmitted,
|
72 | f0cbd3ec | bellard | * and flags that will be used.
|
73 | f0cbd3ec | bellard | * If there is some data or critical controls (SYN, RST)
|
74 | f0cbd3ec | bellard | * to send, then transmit; otherwise, investigate further.
|
75 | f0cbd3ec | bellard | */
|
76 | f0cbd3ec | bellard | idle = (tp->snd_max == tp->snd_una); |
77 | f0cbd3ec | bellard | if (idle && tp->t_idle >= tp->t_rxtcur)
|
78 | f0cbd3ec | bellard | /*
|
79 | f0cbd3ec | bellard | * We have been idle for "a while" and no acks are
|
80 | f0cbd3ec | bellard | * expected to clock out any data we send --
|
81 | f0cbd3ec | bellard | * slow start to get ack "clock" running again.
|
82 | f0cbd3ec | bellard | */
|
83 | f0cbd3ec | bellard | tp->snd_cwnd = tp->t_maxseg; |
84 | f0cbd3ec | bellard | again:
|
85 | f0cbd3ec | bellard | sendalot = 0;
|
86 | f0cbd3ec | bellard | off = tp->snd_nxt - tp->snd_una; |
87 | f0cbd3ec | bellard | win = min(tp->snd_wnd, tp->snd_cwnd); |
88 | f0cbd3ec | bellard | |
89 | f0cbd3ec | bellard | flags = tcp_outflags[tp->t_state]; |
90 | 5fafdf24 | ths | |
91 | f0cbd3ec | bellard | DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
|
92 | 5fafdf24 | ths | |
93 | f0cbd3ec | bellard | /*
|
94 | f0cbd3ec | bellard | * If in persist timeout with window of 0, send 1 byte.
|
95 | f0cbd3ec | bellard | * Otherwise, if window is small but nonzero
|
96 | f0cbd3ec | bellard | * and timer expired, we will send what we can
|
97 | f0cbd3ec | bellard | * and go to transmit state.
|
98 | f0cbd3ec | bellard | */
|
99 | f0cbd3ec | bellard | if (tp->t_force) {
|
100 | f0cbd3ec | bellard | if (win == 0) { |
101 | f0cbd3ec | bellard | /*
|
102 | f0cbd3ec | bellard | * If we still have some data to send, then
|
103 | f0cbd3ec | bellard | * clear the FIN bit. Usually this would
|
104 | f0cbd3ec | bellard | * happen below when it realizes that we
|
105 | f0cbd3ec | bellard | * aren't sending all the data. However,
|
106 | f0cbd3ec | bellard | * if we have exactly 1 byte of unset data,
|
107 | f0cbd3ec | bellard | * then it won't clear the FIN bit below,
|
108 | f0cbd3ec | bellard | * and if we are in persist state, we wind
|
109 | f0cbd3ec | bellard | * up sending the packet without recording
|
110 | f0cbd3ec | bellard | * that we sent the FIN bit.
|
111 | f0cbd3ec | bellard | *
|
112 | f0cbd3ec | bellard | * We can't just blindly clear the FIN bit,
|
113 | f0cbd3ec | bellard | * because if we don't have any more data
|
114 | f0cbd3ec | bellard | * to send then the probe will be the FIN
|
115 | f0cbd3ec | bellard | * itself.
|
116 | f0cbd3ec | bellard | */
|
117 | f0cbd3ec | bellard | if (off < so->so_snd.sb_cc)
|
118 | f0cbd3ec | bellard | flags &= ~TH_FIN; |
119 | f0cbd3ec | bellard | win = 1;
|
120 | f0cbd3ec | bellard | } else {
|
121 | f0cbd3ec | bellard | tp->t_timer[TCPT_PERSIST] = 0;
|
122 | f0cbd3ec | bellard | tp->t_rxtshift = 0;
|
123 | f0cbd3ec | bellard | } |
124 | f0cbd3ec | bellard | } |
125 | f0cbd3ec | bellard | |
126 | f0cbd3ec | bellard | len = min(so->so_snd.sb_cc, win) - off; |
127 | f0cbd3ec | bellard | |
128 | f0cbd3ec | bellard | if (len < 0) { |
129 | f0cbd3ec | bellard | /*
|
130 | f0cbd3ec | bellard | * If FIN has been sent but not acked,
|
131 | f0cbd3ec | bellard | * but we haven't been called to retransmit,
|
132 | f0cbd3ec | bellard | * len will be -1. Otherwise, window shrank
|
133 | f0cbd3ec | bellard | * after we sent into it. If window shrank to 0,
|
134 | f0cbd3ec | bellard | * cancel pending retransmit and pull snd_nxt
|
135 | f0cbd3ec | bellard | * back to (closed) window. We will enter persist
|
136 | f0cbd3ec | bellard | * state below. If the window didn't close completely,
|
137 | f0cbd3ec | bellard | * just wait for an ACK.
|
138 | f0cbd3ec | bellard | */
|
139 | f0cbd3ec | bellard | len = 0;
|
140 | f0cbd3ec | bellard | if (win == 0) { |
141 | f0cbd3ec | bellard | tp->t_timer[TCPT_REXMT] = 0;
|
142 | f0cbd3ec | bellard | tp->snd_nxt = tp->snd_una; |
143 | f0cbd3ec | bellard | } |
144 | f0cbd3ec | bellard | } |
145 | 5fafdf24 | ths | |
146 | f0cbd3ec | bellard | if (len > tp->t_maxseg) {
|
147 | f0cbd3ec | bellard | len = tp->t_maxseg; |
148 | f0cbd3ec | bellard | sendalot = 1;
|
149 | f0cbd3ec | bellard | } |
150 | f0cbd3ec | bellard | if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
|
151 | f0cbd3ec | bellard | flags &= ~TH_FIN; |
152 | f0cbd3ec | bellard | |
153 | f0cbd3ec | bellard | win = sbspace(&so->so_rcv); |
154 | f0cbd3ec | bellard | |
155 | f0cbd3ec | bellard | /*
|
156 | f0cbd3ec | bellard | * Sender silly window avoidance. If connection is idle
|
157 | f0cbd3ec | bellard | * and can send all data, a maximum segment,
|
158 | f0cbd3ec | bellard | * at least a maximum default-size segment do it,
|
159 | f0cbd3ec | bellard | * or are forced, do it; otherwise don't bother.
|
160 | f0cbd3ec | bellard | * If peer's buffer is tiny, then send
|
161 | f0cbd3ec | bellard | * when window is at least half open.
|
162 | f0cbd3ec | bellard | * If retransmitting (possibly after persist timer forced us
|
163 | f0cbd3ec | bellard | * to send into a small window), then must resend.
|
164 | f0cbd3ec | bellard | */
|
165 | f0cbd3ec | bellard | if (len) {
|
166 | f0cbd3ec | bellard | if (len == tp->t_maxseg)
|
167 | f0cbd3ec | bellard | goto send;
|
168 | f0cbd3ec | bellard | if ((1 || idle || tp->t_flags & TF_NODELAY) && |
169 | f0cbd3ec | bellard | len + off >= so->so_snd.sb_cc) |
170 | f0cbd3ec | bellard | goto send;
|
171 | f0cbd3ec | bellard | if (tp->t_force)
|
172 | f0cbd3ec | bellard | goto send;
|
173 | f0cbd3ec | bellard | if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) |
174 | f0cbd3ec | bellard | goto send;
|
175 | f0cbd3ec | bellard | if (SEQ_LT(tp->snd_nxt, tp->snd_max))
|
176 | f0cbd3ec | bellard | goto send;
|
177 | f0cbd3ec | bellard | } |
178 | f0cbd3ec | bellard | |
179 | f0cbd3ec | bellard | /*
|
180 | f0cbd3ec | bellard | * Compare available window to amount of window
|
181 | f0cbd3ec | bellard | * known to peer (as advertised window less
|
182 | f0cbd3ec | bellard | * next expected input). If the difference is at least two
|
183 | f0cbd3ec | bellard | * max size segments, or at least 50% of the maximum possible
|
184 | f0cbd3ec | bellard | * window, then want to send a window update to peer.
|
185 | f0cbd3ec | bellard | */
|
186 | f0cbd3ec | bellard | if (win > 0) { |
187 | 5fafdf24 | ths | /*
|
188 | f0cbd3ec | bellard | * "adv" is the amount we can increase the window,
|
189 | f0cbd3ec | bellard | * taking into account that we are limited by
|
190 | f0cbd3ec | bellard | * TCP_MAXWIN << tp->rcv_scale.
|
191 | f0cbd3ec | bellard | */
|
192 | f0cbd3ec | bellard | long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - |
193 | f0cbd3ec | bellard | (tp->rcv_adv - tp->rcv_nxt); |
194 | f0cbd3ec | bellard | |
195 | f0cbd3ec | bellard | if (adv >= (long) (2 * tp->t_maxseg)) |
196 | f0cbd3ec | bellard | goto send;
|
197 | f0cbd3ec | bellard | if (2 * adv >= (long) so->so_rcv.sb_datalen) |
198 | f0cbd3ec | bellard | goto send;
|
199 | f0cbd3ec | bellard | } |
200 | f0cbd3ec | bellard | |
201 | f0cbd3ec | bellard | /*
|
202 | f0cbd3ec | bellard | * Send if we owe peer an ACK.
|
203 | f0cbd3ec | bellard | */
|
204 | f0cbd3ec | bellard | if (tp->t_flags & TF_ACKNOW)
|
205 | f0cbd3ec | bellard | goto send;
|
206 | f0cbd3ec | bellard | if (flags & (TH_SYN|TH_RST))
|
207 | f0cbd3ec | bellard | goto send;
|
208 | f0cbd3ec | bellard | if (SEQ_GT(tp->snd_up, tp->snd_una))
|
209 | f0cbd3ec | bellard | goto send;
|
210 | f0cbd3ec | bellard | /*
|
211 | f0cbd3ec | bellard | * If our state indicates that FIN should be sent
|
212 | f0cbd3ec | bellard | * and we have not yet done so, or we're retransmitting the FIN,
|
213 | f0cbd3ec | bellard | * then we need to send.
|
214 | f0cbd3ec | bellard | */
|
215 | f0cbd3ec | bellard | if (flags & TH_FIN &&
|
216 | f0cbd3ec | bellard | ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
|
217 | f0cbd3ec | bellard | goto send;
|
218 | f0cbd3ec | bellard | |
219 | f0cbd3ec | bellard | /*
|
220 | f0cbd3ec | bellard | * TCP window updates are not reliable, rather a polling protocol
|
221 | f0cbd3ec | bellard | * using ``persist'' packets is used to insure receipt of window
|
222 | f0cbd3ec | bellard | * updates. The three ``states'' for the output side are:
|
223 | f0cbd3ec | bellard | * idle not doing retransmits or persists
|
224 | f0cbd3ec | bellard | * persisting to move a small or zero window
|
225 | f0cbd3ec | bellard | * (re)transmitting and thereby not persisting
|
226 | f0cbd3ec | bellard | *
|
227 | f0cbd3ec | bellard | * tp->t_timer[TCPT_PERSIST]
|
228 | f0cbd3ec | bellard | * is set when we are in persist state.
|
229 | f0cbd3ec | bellard | * tp->t_force
|
230 | f0cbd3ec | bellard | * is set when we are called to send a persist packet.
|
231 | f0cbd3ec | bellard | * tp->t_timer[TCPT_REXMT]
|
232 | f0cbd3ec | bellard | * is set when we are retransmitting
|
233 | f0cbd3ec | bellard | * The output side is idle when both timers are zero.
|
234 | f0cbd3ec | bellard | *
|
235 | f0cbd3ec | bellard | * If send window is too small, there is data to transmit, and no
|
236 | f0cbd3ec | bellard | * retransmit or persist is pending, then go to persist state.
|
237 | f0cbd3ec | bellard | * If nothing happens soon, send when timer expires:
|
238 | f0cbd3ec | bellard | * if window is nonzero, transmit what we can,
|
239 | f0cbd3ec | bellard | * otherwise force out a byte.
|
240 | f0cbd3ec | bellard | */
|
241 | f0cbd3ec | bellard | if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && |
242 | f0cbd3ec | bellard | tp->t_timer[TCPT_PERSIST] == 0) {
|
243 | f0cbd3ec | bellard | tp->t_rxtshift = 0;
|
244 | f0cbd3ec | bellard | tcp_setpersist(tp); |
245 | f0cbd3ec | bellard | } |
246 | f0cbd3ec | bellard | |
247 | f0cbd3ec | bellard | /*
|
248 | f0cbd3ec | bellard | * No reason to send a segment, just return.
|
249 | f0cbd3ec | bellard | */
|
250 | f0cbd3ec | bellard | return (0); |
251 | f0cbd3ec | bellard | |
252 | f0cbd3ec | bellard | send:
|
253 | f0cbd3ec | bellard | /*
|
254 | f0cbd3ec | bellard | * Before ESTABLISHED, force sending of initial options
|
255 | f0cbd3ec | bellard | * unless TCP set not to do any options.
|
256 | f0cbd3ec | bellard | * NOTE: we assume that the IP/TCP header plus TCP options
|
257 | f0cbd3ec | bellard | * always fit in a single mbuf, leaving room for a maximum
|
258 | f0cbd3ec | bellard | * link header, i.e.
|
259 | f0cbd3ec | bellard | * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
|
260 | f0cbd3ec | bellard | */
|
261 | f0cbd3ec | bellard | optlen = 0;
|
262 | f0cbd3ec | bellard | hdrlen = sizeof (struct tcpiphdr); |
263 | f0cbd3ec | bellard | if (flags & TH_SYN) {
|
264 | f0cbd3ec | bellard | tp->snd_nxt = tp->iss; |
265 | f0cbd3ec | bellard | if ((tp->t_flags & TF_NOOPT) == 0) { |
266 | f0cbd3ec | bellard | u_int16_t mss; |
267 | f0cbd3ec | bellard | |
268 | f0cbd3ec | bellard | opt[0] = TCPOPT_MAXSEG;
|
269 | f0cbd3ec | bellard | opt[1] = 4; |
270 | f0cbd3ec | bellard | mss = htons((u_int16_t) tcp_mss(tp, 0));
|
271 | f0cbd3ec | bellard | memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss)); |
272 | f0cbd3ec | bellard | optlen = 4;
|
273 | f0cbd3ec | bellard | } |
274 | f0cbd3ec | bellard | } |
275 | 5fafdf24 | ths | |
276 | f0cbd3ec | bellard | hdrlen += optlen; |
277 | 5fafdf24 | ths | |
278 | f0cbd3ec | bellard | /*
|
279 | f0cbd3ec | bellard | * Adjust data length if insertion of options will
|
280 | f0cbd3ec | bellard | * bump the packet length beyond the t_maxseg length.
|
281 | f0cbd3ec | bellard | */
|
282 | f0cbd3ec | bellard | if (len > tp->t_maxseg - optlen) {
|
283 | f0cbd3ec | bellard | len = tp->t_maxseg - optlen; |
284 | f0cbd3ec | bellard | sendalot = 1;
|
285 | f0cbd3ec | bellard | } |
286 | f0cbd3ec | bellard | |
287 | f0cbd3ec | bellard | /*
|
288 | f0cbd3ec | bellard | * Grab a header mbuf, attaching a copy of data to
|
289 | f0cbd3ec | bellard | * be transmitted, and initialize the header from
|
290 | f0cbd3ec | bellard | * the template for sends on this connection.
|
291 | f0cbd3ec | bellard | */
|
292 | f0cbd3ec | bellard | if (len) {
|
293 | 460fec67 | Jan Kiszka | m = m_get(so->slirp); |
294 | f0cbd3ec | bellard | if (m == NULL) { |
295 | f0cbd3ec | bellard | error = 1;
|
296 | f0cbd3ec | bellard | goto out;
|
297 | f0cbd3ec | bellard | } |
298 | 9634d903 | blueswir1 | m->m_data += IF_MAXLINKHDR; |
299 | f0cbd3ec | bellard | m->m_len = hdrlen; |
300 | 3b46e624 | ths | |
301 | 0d62c4cf | Jan Kiszka | sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
|
302 | 0d62c4cf | Jan Kiszka | m->m_len += len; |
303 | f0cbd3ec | bellard | |
304 | f0cbd3ec | bellard | /*
|
305 | f0cbd3ec | bellard | * If we're sending everything we've got, set PUSH.
|
306 | f0cbd3ec | bellard | * (This will keep happy those implementations which only
|
307 | f0cbd3ec | bellard | * give data to the user when a buffer fills or
|
308 | f0cbd3ec | bellard | * a PUSH comes in.)
|
309 | f0cbd3ec | bellard | */
|
310 | f0cbd3ec | bellard | if (off + len == so->so_snd.sb_cc)
|
311 | f0cbd3ec | bellard | flags |= TH_PUSH; |
312 | f0cbd3ec | bellard | } else {
|
313 | 460fec67 | Jan Kiszka | m = m_get(so->slirp); |
314 | f0cbd3ec | bellard | if (m == NULL) { |
315 | f0cbd3ec | bellard | error = 1;
|
316 | f0cbd3ec | bellard | goto out;
|
317 | f0cbd3ec | bellard | } |
318 | 9634d903 | blueswir1 | m->m_data += IF_MAXLINKHDR; |
319 | f0cbd3ec | bellard | m->m_len = hdrlen; |
320 | f0cbd3ec | bellard | } |
321 | f0cbd3ec | bellard | |
322 | f0cbd3ec | bellard | ti = mtod(m, struct tcpiphdr *);
|
323 | 5fafdf24 | ths | |
324 | f0cbd3ec | bellard | memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr)); |
325 | f0cbd3ec | bellard | |
326 | f0cbd3ec | bellard | /*
|
327 | f0cbd3ec | bellard | * Fill in fields, remembering maximum advertised
|
328 | f0cbd3ec | bellard | * window for use in delaying messages about window sizes.
|
329 | f0cbd3ec | bellard | * If resending a FIN, be sure not to use a new sequence number.
|
330 | f0cbd3ec | bellard | */
|
331 | 5fafdf24 | ths | if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
|
332 | f0cbd3ec | bellard | tp->snd_nxt == tp->snd_max) |
333 | f0cbd3ec | bellard | tp->snd_nxt--; |
334 | f0cbd3ec | bellard | /*
|
335 | f0cbd3ec | bellard | * If we are doing retransmissions, then snd_nxt will
|
336 | f0cbd3ec | bellard | * not reflect the first unsent octet. For ACK only
|
337 | f0cbd3ec | bellard | * packets, we do not want the sequence number of the
|
338 | f0cbd3ec | bellard | * retransmitted packet, we want the sequence number
|
339 | f0cbd3ec | bellard | * of the next unsent octet. So, if there is no data
|
340 | f0cbd3ec | bellard | * (and no SYN or FIN), use snd_max instead of snd_nxt
|
341 | f0cbd3ec | bellard | * when filling in ti_seq. But if we are in persist
|
342 | f0cbd3ec | bellard | * state, snd_max might reflect one byte beyond the
|
343 | f0cbd3ec | bellard | * right edge of the window, so use snd_nxt in that
|
344 | f0cbd3ec | bellard | * case, since we know we aren't doing a retransmission.
|
345 | f0cbd3ec | bellard | * (retransmit and persist are mutually exclusive...)
|
346 | f0cbd3ec | bellard | */
|
347 | f0cbd3ec | bellard | if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
|
348 | f0cbd3ec | bellard | ti->ti_seq = htonl(tp->snd_nxt); |
349 | f0cbd3ec | bellard | else
|
350 | f0cbd3ec | bellard | ti->ti_seq = htonl(tp->snd_max); |
351 | f0cbd3ec | bellard | ti->ti_ack = htonl(tp->rcv_nxt); |
352 | f0cbd3ec | bellard | if (optlen) {
|
353 | f0cbd3ec | bellard | memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
|
354 | f0cbd3ec | bellard | ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; |
355 | f0cbd3ec | bellard | } |
356 | f0cbd3ec | bellard | ti->ti_flags = flags; |
357 | f0cbd3ec | bellard | /*
|
358 | f0cbd3ec | bellard | * Calculate receive window. Don't shrink window,
|
359 | f0cbd3ec | bellard | * but avoid silly window syndrome.
|
360 | f0cbd3ec | bellard | */
|
361 | f0cbd3ec | bellard | if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) |
362 | f0cbd3ec | bellard | win = 0;
|
363 | f0cbd3ec | bellard | if (win > (long)TCP_MAXWIN << tp->rcv_scale) |
364 | f0cbd3ec | bellard | win = (long)TCP_MAXWIN << tp->rcv_scale;
|
365 | f0cbd3ec | bellard | if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) |
366 | f0cbd3ec | bellard | win = (long)(tp->rcv_adv - tp->rcv_nxt);
|
367 | f0cbd3ec | bellard | ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale)); |
368 | 5fafdf24 | ths | |
369 | f0cbd3ec | bellard | if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
370 | f0cbd3ec | bellard | ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq))); |
371 | f0cbd3ec | bellard | ti->ti_flags |= TH_URG; |
372 | f0cbd3ec | bellard | } else
|
373 | f0cbd3ec | bellard | /*
|
374 | f0cbd3ec | bellard | * If no urgent pointer to send, then we pull
|
375 | f0cbd3ec | bellard | * the urgent pointer to the left edge of the send window
|
376 | f0cbd3ec | bellard | * so that it doesn't drift into the send window on sequence
|
377 | f0cbd3ec | bellard | * number wraparound.
|
378 | f0cbd3ec | bellard | */
|
379 | f0cbd3ec | bellard | tp->snd_up = tp->snd_una; /* drag it along */
|
380 | f0cbd3ec | bellard | |
381 | f0cbd3ec | bellard | /*
|
382 | f0cbd3ec | bellard | * Put TCP length in extended header, and then
|
383 | f0cbd3ec | bellard | * checksum extended header and data.
|
384 | f0cbd3ec | bellard | */
|
385 | f0cbd3ec | bellard | if (len + optlen)
|
386 | f0cbd3ec | bellard | ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + |
387 | f0cbd3ec | bellard | optlen + len)); |
388 | f0cbd3ec | bellard | ti->ti_sum = cksum(m, (int)(hdrlen + len));
|
389 | f0cbd3ec | bellard | |
390 | f0cbd3ec | bellard | /*
|
391 | f0cbd3ec | bellard | * In transmit state, time the transmission and arrange for
|
392 | f0cbd3ec | bellard | * the retransmit. In persist state, just set snd_max.
|
393 | f0cbd3ec | bellard | */
|
394 | f0cbd3ec | bellard | if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { |
395 | f0cbd3ec | bellard | tcp_seq startseq = tp->snd_nxt; |
396 | f0cbd3ec | bellard | |
397 | f0cbd3ec | bellard | /*
|
398 | f0cbd3ec | bellard | * Advance snd_nxt over sequence space of this segment.
|
399 | f0cbd3ec | bellard | */
|
400 | f0cbd3ec | bellard | if (flags & (TH_SYN|TH_FIN)) {
|
401 | f0cbd3ec | bellard | if (flags & TH_SYN)
|
402 | f0cbd3ec | bellard | tp->snd_nxt++; |
403 | f0cbd3ec | bellard | if (flags & TH_FIN) {
|
404 | f0cbd3ec | bellard | tp->snd_nxt++; |
405 | f0cbd3ec | bellard | tp->t_flags |= TF_SENTFIN; |
406 | f0cbd3ec | bellard | } |
407 | f0cbd3ec | bellard | } |
408 | f0cbd3ec | bellard | tp->snd_nxt += len; |
409 | f0cbd3ec | bellard | if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
|
410 | f0cbd3ec | bellard | tp->snd_max = tp->snd_nxt; |
411 | f0cbd3ec | bellard | /*
|
412 | f0cbd3ec | bellard | * Time this transmission if not a retransmission and
|
413 | f0cbd3ec | bellard | * not currently timing anything.
|
414 | f0cbd3ec | bellard | */
|
415 | f0cbd3ec | bellard | if (tp->t_rtt == 0) { |
416 | f0cbd3ec | bellard | tp->t_rtt = 1;
|
417 | f0cbd3ec | bellard | tp->t_rtseq = startseq; |
418 | f0cbd3ec | bellard | } |
419 | f0cbd3ec | bellard | } |
420 | f0cbd3ec | bellard | |
421 | f0cbd3ec | bellard | /*
|
422 | f0cbd3ec | bellard | * Set retransmit timer if not currently set,
|
423 | f0cbd3ec | bellard | * and not doing an ack or a keep-alive probe.
|
424 | f0cbd3ec | bellard | * Initial value for retransmit timer is smoothed
|
425 | f0cbd3ec | bellard | * round-trip time + 2 * round-trip time variance.
|
426 | f0cbd3ec | bellard | * Initialize shift counter which is used for backoff
|
427 | f0cbd3ec | bellard | * of retransmit time.
|
428 | f0cbd3ec | bellard | */
|
429 | f0cbd3ec | bellard | if (tp->t_timer[TCPT_REXMT] == 0 && |
430 | f0cbd3ec | bellard | tp->snd_nxt != tp->snd_una) { |
431 | f0cbd3ec | bellard | tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; |
432 | f0cbd3ec | bellard | if (tp->t_timer[TCPT_PERSIST]) {
|
433 | f0cbd3ec | bellard | tp->t_timer[TCPT_PERSIST] = 0;
|
434 | f0cbd3ec | bellard | tp->t_rxtshift = 0;
|
435 | f0cbd3ec | bellard | } |
436 | f0cbd3ec | bellard | } |
437 | f0cbd3ec | bellard | } else
|
438 | f0cbd3ec | bellard | if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
|
439 | f0cbd3ec | bellard | tp->snd_max = tp->snd_nxt + len; |
440 | f0cbd3ec | bellard | |
441 | f0cbd3ec | bellard | /*
|
442 | f0cbd3ec | bellard | * Fill in IP length and desired time to live and
|
443 | f0cbd3ec | bellard | * send to IP level. There should be a better way
|
444 | f0cbd3ec | bellard | * to handle ttl and tos; we could keep them in
|
445 | f0cbd3ec | bellard | * the template, but need a way to checksum without them.
|
446 | f0cbd3ec | bellard | */
|
447 | f0cbd3ec | bellard | m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
|
448 | 5fafdf24 | ths | |
449 | f0cbd3ec | bellard | { |
450 | 3b46e624 | ths | |
451 | f0cbd3ec | bellard | ((struct ip *)ti)->ip_len = m->m_len;
|
452 | f0cbd3ec | bellard | |
453 | 9634d903 | blueswir1 | ((struct ip *)ti)->ip_ttl = IPDEFTTL;
|
454 | f0cbd3ec | bellard | ((struct ip *)ti)->ip_tos = so->so_iptos;
|
455 | 3b46e624 | ths | |
456 | f0cbd3ec | bellard | error = ip_output(so, m); |
457 | f0cbd3ec | bellard | } |
458 | f0cbd3ec | bellard | if (error) {
|
459 | f0cbd3ec | bellard | out:
|
460 | f0cbd3ec | bellard | return (error);
|
461 | f0cbd3ec | bellard | } |
462 | f0cbd3ec | bellard | |
463 | f0cbd3ec | bellard | /*
|
464 | f0cbd3ec | bellard | * Data sent (as far as we can tell).
|
465 | f0cbd3ec | bellard | * If this advertises a larger window than any other segment,
|
466 | f0cbd3ec | bellard | * then remember the size of the advertised window.
|
467 | f0cbd3ec | bellard | * Any pending ACK has now been sent.
|
468 | f0cbd3ec | bellard | */
|
469 | f0cbd3ec | bellard | if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) |
470 | f0cbd3ec | bellard | tp->rcv_adv = tp->rcv_nxt + win; |
471 | f0cbd3ec | bellard | tp->last_ack_sent = tp->rcv_nxt; |
472 | f0cbd3ec | bellard | tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); |
473 | f0cbd3ec | bellard | if (sendalot)
|
474 | f0cbd3ec | bellard | goto again;
|
475 | f0cbd3ec | bellard | |
476 | f0cbd3ec | bellard | return (0); |
477 | f0cbd3ec | bellard | } |
478 | f0cbd3ec | bellard | |
479 | f0cbd3ec | bellard | void
|
480 | 511d2b14 | blueswir1 | tcp_setpersist(struct tcpcb *tp)
|
481 | f0cbd3ec | bellard | { |
482 | f0cbd3ec | bellard | int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; |
483 | f0cbd3ec | bellard | |
484 | f0cbd3ec | bellard | /*
|
485 | f0cbd3ec | bellard | * Start/restart persistence timer.
|
486 | f0cbd3ec | bellard | */
|
487 | f0cbd3ec | bellard | TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], |
488 | f0cbd3ec | bellard | t * tcp_backoff[tp->t_rxtshift], |
489 | f0cbd3ec | bellard | TCPTV_PERSMIN, TCPTV_PERSMAX); |
490 | f0cbd3ec | bellard | if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
|
491 | f0cbd3ec | bellard | tp->t_rxtshift++; |
492 | f0cbd3ec | bellard | } |