|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
59: */
60:
61: #ifndef TUBA_INCLUDE
62: #include <sys/param.h>
63: #include <sys/systm.h>
64: #include <sys/malloc.h>
65: #include <sys/mbuf.h>
66: #include <sys/socket.h>
67: #include <sys/socketvar.h>
68: #include <sys/protosw.h>
69: #include <sys/errno.h>
70:
71: #include <net/if.h>
72: #include <net/route.h>
73:
74: #include <netinet/in.h>
75: #include <netinet/in_systm.h>
76: #include <netinet/ip.h>
77: #include <netinet/in_pcb.h>
78: #include <netinet/ip_var.h>
79: #include <netinet/tcp.h>
80: #include <netinet/tcp_fsm.h>
81: #include <netinet/tcp_seq.h>
82: #include <netinet/tcp_timer.h>
83: #include <netinet/tcp_var.h>
84: #include <netinet/tcpip.h>
85:
86: #include <kern/kdebug.h>
87:
88: #if KDEBUG
89:
90: #define DBG_FNC_TCP_FAST NETDBG_CODE(DBG_NETTCP, (5 << 8))
91: #define DBG_FNC_TCP_SLOW NETDBG_CODE(DBG_NETTCP, (5 << 8) | 1)
92:
93: #endif
94:
95: int tcp_keepidle = TCPTV_KEEP_IDLE;
96: int tcp_keepintvl = TCPTV_KEEPINTVL;
97: int tcp_keepcnt = TCPTV_KEEPCNT; /* max idle probes */
98: int tcp_maxpersistidle = TCPTV_KEEP_IDLE; /* max idle time in persist */
99: int tcp_maxidle;
100: #else /* TUBA_INCLUDE */
101:
102: extern int tcp_maxpersistidle;
103: #endif /* TUBA_INCLUDE */
104:
105: extern struct inpcb *tcp_hash_array[];
106:
107: struct inpcb time_wait_slots[N_TIME_WAIT_SLOTS];
108: int cur_tw_slot = 0;
109:
110: #if DELACK_BITMASK_ON
111: u_long delack_bitmask[N_TCP_HASH_ELEMENTS / 32];
112: u_long current_active_connections = 0;
113: u_long last_active_conn_count = 0;
114:
115: #endif
116:
117: void add_to_time_wait(tp)
118: struct tcpcb *tp;
119: {
120: int tw_slot;
121:
122: remque((queue_t) tp->t_inpcb);
123:
124: if (tp->t_timer[TCPT_2MSL] == 0)
125: tp->t_timer[TCPT_2MSL] = 1;
126: else
127: if (tp->t_timer[TCPT_2MSL] >= N_TIME_WAIT_SLOTS)
128: tp->t_timer[TCPT_2MSL] = N_TIME_WAIT_SLOTS -1;
129:
130: tw_slot = tp->t_timer[TCPT_2MSL] - 1 + cur_tw_slot;
131:
132: if (tw_slot >= N_TIME_WAIT_SLOTS)
133: tw_slot -= N_TIME_WAIT_SLOTS;
134:
135: insque((queue_t) tp->t_inpcb, (queue_t) &time_wait_slots[tw_slot]);
136:
137: }
138:
139:
140:
141:
142: /*
143: * Fast timeout routine for processing delayed acks
144: */
145: void
146: tcp_fasttimo()
147: {
148: register struct inpcb *inp;
149: register struct tcpcb *tp;
150:
151: #if DELACK_BITMASK_ON
152: register u_long i,j;
153: register u_long temp_mask;
154: register u_long elem_base = 0;
155: #endif
156: int s = splnet();
157:
158:
159: #if KDEBUG
160: register int checked = 0;
161: #endif
162: KERNEL_DEBUG(DBG_FNC_TCP_FAST | DBG_FUNC_START, 0,0,0,0,0);
163:
164: #if DELACK_BITMASK_ON
165:
166: if ((current_active_connections > DELACK_BITMASK_THRESH) &&
167: (last_active_conn_count > DELACK_BITMASK_THRESH)) {
168: for (i=0; i < (N_TCP_HASH_ELEMENTS / 32); i++) {
169: if (delack_bitmask[i]) {
170: temp_mask = 1;
171: for (j=0; j < 32; j++) {
172: if (temp_mask & delack_bitmask[i]) {
173: inp = tcp_hash_array[elem_base + j];
174: for (; inp != 0; inp = inp->hash_next) {
175: #if KDEBUG
176: checked++;
177: #endif
178: if ((tp = (struct tcpcb *)inp->inp_ppcb) && (tp->t_flags & TF_DELACK)) {
179: tp->t_flags &= ~TF_DELACK;
180: tp->t_flags |= TF_ACKNOW;
181: tcpstat.tcps_delack++;
182: (void) tcp_output(tp);
183: }
184: }
185: }
186: temp_mask <<= 1;
187: }
188: delack_bitmask[i] = 0;
189: }
190: elem_base += 32;
191: }
192: }
193: else
194: #endif
195: {
196: inp = tcb.inp_next;
197: if (inp)
198: for (; inp != &tcb; inp = inp->inp_next)
199: if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
200: (tp->t_flags & TF_DELACK)) {
201: tp->t_flags &= ~TF_DELACK;
202: tp->t_flags |= TF_ACKNOW;
203: tcpstat.tcps_delack++;
204: (void) tcp_output(tp);
205: }
206:
207: }
208:
209: #if DELACK_BITMASK_ON
210: last_active_conn_count = current_active_connections;
211: #endif
212:
213: splx(s);
214: #if KDEBUG
215: KERNEL_DEBUG(DBG_FNC_TCP_FAST | DBG_FUNC_END, checked,tcpstat.tcps_delack,0,0,0);
216: #endif
217: }
218:
219: /*
220: * Tcp protocol timeout routine called every 500 ms.
221: * Updates the timers in all active tcb's and
222: * causes finite state machine actions if timers expire.
223: */
224: void
225: tcp_slowtimo()
226: {
227: register struct inpcb *ip, *ipnxt;
228: register struct tcpcb *tp;
229: int s = splnet();
230: register int i;
231: #if KDEBUG
232: register int checked = 0;
233: #endif
234: KERNEL_DEBUG(DBG_FNC_TCP_SLOW | DBG_FUNC_START, 0,0,0,0,0);
235:
236: tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
237: /*
238: * Search through tcb's and update active timers.
239: */
240: if (ip = tcb.inp_next) {
241: for (; ip != &tcb; ip = ipnxt) {
242: #if KDEBUG
243: checked++;
244: #endif
245: ipnxt = ip->inp_next;
246: tp = intotcpcb(ip);
247: if (tp == 0 || tp->t_state == TCPS_LISTEN)
248: continue;
249: for (i = 0; i < TCPT_NTIMERS; i++) {
250: if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
251: (void) tcp_usrreq(tp->t_inpcb->inp_socket,
252: PRU_SLOWTIMO, (struct mbuf *)0,
253: (struct mbuf *)i, (struct mbuf *)0);
254: if (ipnxt->inp_prev != ip)
255: goto tpgone;
256: }
257: }
258: tp->t_idle++;
259: if (tp->t_rtt)
260: tp->t_rtt++;
261: tpgone:
262: ;
263: }
264: }
265: #if KDEBUG
266: KERNEL_DEBUG(DBG_FNC_TCP_SLOW | DBG_FUNC_NONE, checked,0,0,0,0);
267:
268: checked = 0;
269: #endif
270: /*
271: * Process the items in the current time-wait slot
272: */
273:
274: for (ip = time_wait_slots[cur_tw_slot].inp_next;
275: ip != &time_wait_slots[cur_tw_slot];
276: ip = ipnxt)
277: {
278: #if KDEBUG
279: checked++;
280: #endif
281: ipnxt = ip->inp_next;
282: tp = intotcpcb(ip);
283: tp->t_timer[TCPT_2MSL] = 0;
284: (void) tcp_usrreq(ip->inp_socket,
285: PRU_SLOWTIMO, (struct mbuf *)0,
286: (struct mbuf *) TCPT_2MSL, (struct mbuf *)0);
287: }
288:
289: time_wait_slots[cur_tw_slot].inp_next = &time_wait_slots[cur_tw_slot];
290: time_wait_slots[cur_tw_slot].inp_prev = &time_wait_slots[cur_tw_slot];
291: if (++cur_tw_slot >= N_TIME_WAIT_SLOTS)
292: cur_tw_slot = 0;
293:
294: tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
295: #ifdef TCP_COMPAT_42
296: if ((int)tcp_iss < 0)
297: tcp_iss = TCP_ISSINCR; /* XXX */
298: #endif
299: tcp_now++; /* for timestamps */
300: splx(s);
301:
302: #if KDEBUG
303: KERNEL_DEBUG(DBG_FNC_TCP_SLOW | DBG_FUNC_END, checked, cur_tw_slot,0,0,0);
304: #endif
305: }
306: #ifndef TUBA_INCLUDE
307:
308: /*
309: * Cancel all timers for TCP tp.
310: */
311: void
312: tcp_canceltimers(tp)
313: struct tcpcb *tp;
314: {
315: register int i;
316:
317: for (i = 0; i < TCPT_NTIMERS; i++)
318: tp->t_timer[i] = 0;
319: }
320:
321: int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
322: { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
323:
324: int tcp_totbackoff = 511; /* sum of tcp_backoff[] */
325:
326: /*
327: * TCP timer processing.
328: */
329: struct tcpcb *
330: tcp_timers(tp, timer)
331: register struct tcpcb *tp;
332: int timer;
333: {
334: register int rexmt;
335:
336: switch (timer) {
337:
338: /*
339: * 2 MSL timeout in shutdown went off. If we're closed but
340: * still waiting for peer to close and connection has been idle
341: * too long, or if 2MSL time is up from TIME_WAIT, delete connection
342: * control block. Otherwise, check again in a bit.
343: */
344: case TCPT_2MSL:
345: if (tp->t_state != TCPS_TIME_WAIT &&
346: tp->t_idle <= tcp_maxidle) {
347: tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
348:
349: add_to_time_wait(tp);
350: }
351: else
352: tp = tcp_close(tp);
353: break;
354:
355: /*
356: * Retransmission timer went off. Message has not
357: * been acked within retransmit interval. Back off
358: * to a longer retransmit interval and retransmit one segment.
359: */
360: case TCPT_REXMT:
361: if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
362: tp->t_rxtshift = TCP_MAXRXTSHIFT;
363: tcpstat.tcps_timeoutdrop++;
364: tp = tcp_drop(tp, tp->t_softerror ?
365: tp->t_softerror : ETIMEDOUT);
366: break;
367: }
368: tcpstat.tcps_rexmttimeo++;
369: rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
370: TCPT_RANGESET(tp->t_rxtcur, rexmt,
371: tp->t_rttmin, TCPTV_REXMTMAX);
372: tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
373: /*
374: * If losing, let the lower level know and try for
375: * a better route. Also, if we backed off this far,
376: * our srtt estimate is probably bogus. Clobber it
377: * so we'll take the next rtt measurement as our srtt;
378: * move the current srtt into rttvar to keep the current
379: * retransmit times until then.
380: */
381: if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
382: in_losing(tp->t_inpcb);
383: tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
384: tp->t_srtt = 0;
385: }
386: tp->snd_nxt = tp->snd_una;
387: /*
388: * If timing a segment in this window, stop the timer.
389: */
390: tp->t_rtt = 0;
391: /*
392: * Close the congestion window down to one segment
393: * (we'll open it by one segment for each ack we get).
394: * Since we probably have a window's worth of unacked
395: * data accumulated, this "slow start" keeps us from
396: * dumping all that data as back-to-back packets (which
397: * might overwhelm an intermediate gateway).
398: *
399: * There are two phases to the opening: Initially we
400: * open by one mss on each ack. This makes the window
401: * size increase exponentially with time. If the
402: * window is larger than the path can handle, this
403: * exponential growth results in dropped packet(s)
404: * almost immediately. To get more time between
405: * drops but still "push" the network to take advantage
406: * of improving conditions, we switch from exponential
407: * to linear window opening at some threshhold size.
408: * For a threshhold, we use half the current window
409: * size, truncated to a multiple of the mss.
410: *
411: * (the minimum cwnd that will give us exponential
412: * growth is 2 mss. We don't allow the threshhold
413: * to go below this.)
414: */
415: {
416: u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
417: if (win < 2)
418: win = 2;
419: tp->snd_cwnd = tp->t_maxseg;
420: tp->snd_ssthresh = win * tp->t_maxseg;
421: tp->t_dupacks = 0;
422: }
423: (void) tcp_output(tp);
424: break;
425:
426: /*
427: * Persistance timer into zero window.
428: * Force a byte to be output, if possible.
429: */
430: case TCPT_PERSIST:
431: tcpstat.tcps_persisttimeo++;
432: /*
433: * Hack: if the peer is dead/unreachable, we do not
434: * time out if the window is closed. After a full
435: * backoff, drop the connection if the idle time
436: * (no responses to probes) reaches the maximum
437: * backoff that we would use if retransmitting.
438: */
439: if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
440: (tp->t_idle >= tcp_maxpersistidle ||
441: tp->t_idle >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
442: tcpstat.tcps_persistdrop++;
443: tp = tcp_drop(tp, ETIMEDOUT);
444: break;
445: }
446: tcp_setpersist(tp);
447: tp->t_force = 1;
448: (void) tcp_output(tp);
449: tp->t_force = 0;
450: break;
451:
452: /*
453: * Keep-alive timer went off; send something
454: * or drop connection if idle for too long.
455: */
456: case TCPT_KEEP:
457: tcpstat.tcps_keeptimeo++;
458: if (tp->t_state < TCPS_ESTABLISHED)
459: goto dropit;
460: if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
461: tp->t_state <= TCPS_CLOSE_WAIT) {
462: if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
463: goto dropit;
464: /*
465: * Send a packet designed to force a response
466: * if the peer is up and reachable:
467: * either an ACK if the connection is still alive,
468: * or an RST if the peer has closed the connection
469: * due to timeout or reboot.
470: * Using sequence number tp->snd_una-1
471: * causes the transmitted zero-length segment
472: * to lie outside the receive window;
473: * by the protocol spec, this requires the
474: * correspondent TCP to respond.
475: */
476: tcpstat.tcps_keepprobe++;
477: #ifdef TCP_COMPAT_42
478: /*
479: * The keepalive packet must have nonzero length
480: * to get a 4.2 host to respond.
481: */
482: tcp_respond(tp, tp->t_template, (struct mbuf *)NULL,
483: tp->rcv_nxt - 1, tp->snd_una - 1, 0);
484: #else
485: tcp_respond(tp, tp->t_template, (struct mbuf *)NULL,
486: tp->rcv_nxt, tp->snd_una - 1, 0);
487: #endif
488: tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
489: } else
490: tp->t_timer[TCPT_KEEP] = tcp_keepidle;
491: break;
492: dropit:
493: tcpstat.tcps_keepdrops++;
494: tp = tcp_drop(tp, ETIMEDOUT);
495: break;
496: }
497: return (tp);
498: }
499: #endif /* TUBA_INCLUDE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.