OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [bsd_tcpip/] [current/] [src/] [sys/] [netinet/] [tcp_timer.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/sys/netinet/tcp_timer.c
4
//
5
//==========================================================================
6
// ####BSDCOPYRIGHTBEGIN####                                    
7
// -------------------------------------------                  
8
// This file is part of eCos, the Embedded Configurable Operating System.
9
//
10
// Portions of this software may have been derived from FreeBSD 
11
// or other sources, and if so are covered by the appropriate copyright
12
// and license included herein.                                 
13
//
14
// Portions created by the Free Software Foundation are         
15
// Copyright (C) 2002 Free Software Foundation, Inc.            
16
// -------------------------------------------                  
17
// ####BSDCOPYRIGHTEND####                                      
18
//==========================================================================
19
 
20
/*
21
 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
22
 *      The Regents of the University of California.  All rights reserved.
23
 *
24
 * Redistribution and use in source and binary forms, with or without
25
 * modification, are permitted provided that the following conditions
26
 * are met:
27
 * 1. Redistributions of source code must retain the above copyright
28
 *    notice, this list of conditions and the following disclaimer.
29
 * 2. Redistributions in binary form must reproduce the above copyright
30
 *    notice, this list of conditions and the following disclaimer in the
31
 *    documentation and/or other materials provided with the distribution.
32
 * 3. All advertising materials mentioning features or use of this software
33
 *    must display the following acknowledgement:
34
 *      This product includes software developed by the University of
35
 *      California, Berkeley and its contributors.
36
 * 4. Neither the name of the University nor the names of its contributors
37
 *    may be used to endorse or promote products derived from this software
38
 *    without specific prior written permission.
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 *
52
 *      @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
53
 * $FreeBSD: src/sys/netinet/tcp_timer.c,v 1.34.2.11 2001/08/22 00:59:12 silby Exp $
54
 */
55
 
56
#include <sys/param.h>
57
#include <sys/sysctl.h>
58
#include <sys/mbuf.h>
59
#include <sys/socket.h>
60
#include <sys/socketvar.h>
61
#include <sys/protosw.h>
62
 
63
#include <net/route.h>
64
 
65
#include <netinet/in.h>
66
#include <netinet/in_systm.h>
67
#include <netinet/in_pcb.h>
68
#ifdef INET6
69
#include <netinet6/in6_pcb.h>
70
#endif
71
#include <netinet/ip_var.h>
72
#include <netinet/tcp.h>
73
#include <netinet/tcp_fsm.h>
74
#include <netinet/tcp_seq.h>
75
#include <netinet/tcp_timer.h>
76
#include <netinet/tcp_var.h>
77
#include <netinet/tcpip.h>
78
#ifdef TCPDEBUG
79
#include <netinet/tcp_debug.h>
80
#endif
81
 
82
#ifdef CYGPKG_NET_FREEBSD_SYSCTL
83
static int
84
sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
85
{
86
        int error, s, tt;
87
 
88
        tt = *(int *)oidp->oid_arg1;
89
        s = tt * 1000 / hz;
90
 
91
        error = sysctl_handle_int(oidp, &s, 0, req);
92
        if (error || !req->newptr)
93
                return (error);
94
 
95
        tt = s * hz / 1000;
96
        if (tt < 1)
97
                return (EINVAL);
98
 
99
        *(int *)oidp->oid_arg1 = tt;
100
        return (0);
101
}
102
static int
103
sysctl_rexmitmax_rangecheck(SYSCTL_HANDLER_ARGS)
104
{
105
        int error, tt;
106
 
107
        tt = *(int *)oidp->oid_arg1;
108
 
109
        error = sysctl_handle_int(oidp, &tt, 0, req);
110
        if (error || !req->newptr)
111
                return (error);
112
 
113
        if (tt > TCP_MAXRXTSHIFT)
114
                return (EINVAL);
115
 
116
        if (tt < 2)
117
                return (EINVAL);
118
 
119
        *(int *)oidp->oid_arg1 = tt;
120
        return (0);
121
}
122
#endif
123
int     tcp_keepinit;
124
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, CTLTYPE_INT|CTLFLAG_RW,
125
    &tcp_keepinit, 0, sysctl_msec_to_ticks, "I", "");
126
 
127
int     tcp_keepidle;
128
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, CTLTYPE_INT|CTLFLAG_RW,
129
    &tcp_keepidle, 0, sysctl_msec_to_ticks, "I", "");
130
 
131
int     tcp_keepintvl;
132
SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, CTLTYPE_INT|CTLFLAG_RW,
133
    &tcp_keepintvl, 0, sysctl_msec_to_ticks, "I", "");
134
 
135
int     tcp_delacktime;
136
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime,
137
    CTLTYPE_INT|CTLFLAG_RW, &tcp_delacktime, 0, sysctl_msec_to_ticks, "I",
138
    "Time before a delayed ACK is sent");
139
 
140
int     tcp_msl;
141
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW,
142
    &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime");
143
 
144
static int      always_keepalive = 0;
145
SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW,
146
    &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections");
147
 
148
int     tcp_rexmit_min;
149
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW,
150
    &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I", "Minimum retransmission timeout");
151
 
152
int     tcp_rexmit_shift_max = TCP_MAXRXTSHIFT;
153
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_shift_max, CTLTYPE_INT|CTLFLAG_RW,
154
    &tcp_rexmit_shift_max, 0, sysctl_rexmitmax_rangecheck, "I", "Maximum TCP retransmissions");
155
 
156
static int      tcp_keepcnt = TCPTV_KEEPCNT;
157
        /* max idle probes */
158
int     tcp_maxpersistidle;
159
        /* max idle time in persist */
160
int     tcp_maxidle;
161
 
162
/*
163
 * Tcp protocol timeout routine called every 500 ms.
164
 * Updates timestamps used for TCP
165
 * causes finite state machine actions if timers expire.
166
 */
167
void
168
tcp_slowtimo()
169
{
170
        int s;
171
 
172
        s = splnet();
173
 
174
        tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
175
 
176
        splx(s);
177
}
178
 
179
/*
180
 * Cancel all timers for TCP tp.
181
 */
182
void
183
tcp_canceltimers(tp)
184
        struct tcpcb *tp;
185
{
186
        callout_stop(tp->tt_2msl);
187
        callout_stop(tp->tt_persist);
188
        callout_stop(tp->tt_keep);
189
        callout_stop(tp->tt_rexmt);
190
}
191
 
192
int     tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
193
    { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
194
 
195
int     tcp_backoff[TCP_MAXRXTSHIFT + 1] =
196
    { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
197
 
198
static int tcp_totbackoff = 511;        /* sum of tcp_backoff[] */
199
 
200
/*
201
 * TCP timer processing.
202
 */
203
void
204
tcp_timer_delack(xtp)
205
        void *xtp;
206
{
207
        struct tcpcb *tp = xtp;
208
        int s;
209
 
210
        s = splnet();
211
        if (callout_pending(tp->tt_delack) || !callout_active(tp->tt_delack)) {
212
                splx(s);
213
                return;
214
        }
215
        callout_deactivate(tp->tt_delack);
216
 
217
        tp->t_flags |= TF_ACKNOW;
218
        tcpstat.tcps_delack++;
219
        (void) tcp_output(tp);
220
        splx(s);
221
}
222
 
223
void
224
tcp_timer_2msl(xtp)
225
        void *xtp;
226
{
227
        struct tcpcb *tp = xtp;
228
        int s;
229
#ifdef TCPDEBUG
230
        int ostate;
231
 
232
        ostate = tp->t_state;
233
#endif
234
        s = splnet();
235
        if (callout_pending(tp->tt_2msl) || !callout_active(tp->tt_2msl)) {
236
                splx(s);
237
                return;
238
        }
239
        callout_deactivate(tp->tt_2msl);
240
        /*
241
         * 2 MSL timeout in shutdown went off.  If we're closed but
242
         * still waiting for peer to close and connection has been idle
243
         * too long, or if 2MSL time is up from TIME_WAIT, delete connection
244
         * control block.  Otherwise, check again in a bit.
245
         */
246
        if (tp->t_state != TCPS_TIME_WAIT &&
247
            (ticks - tp->t_rcvtime) <= tcp_maxidle) {
248
                callout_reset(tp->tt_2msl, tcp_keepintvl,
249
                              tcp_timer_2msl, tp);
250
        }
251
        else {
252
                tp = tcp_close(tp);
253
        }
254
 
255
#ifdef TCPDEBUG
256
        if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
257
                tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
258
                          PRU_SLOWTIMO);
259
#endif
260
        splx(s);
261
}
262
 
263
void
264
tcp_timer_keep(xtp)
265
        void *xtp;
266
{
267
        struct tcpcb *tp = xtp;
268
        struct tcptemp *t_template;
269
        int s;
270
#ifdef TCPDEBUG
271
        int ostate;
272
 
273
        ostate = tp->t_state;
274
#endif
275
        s = splnet();
276
        if (callout_pending(tp->tt_keep) || !callout_active(tp->tt_keep)) {
277
                splx(s);
278
                return;
279
        }
280
        callout_deactivate(tp->tt_keep);
281
        /*
282
         * Keep-alive timer went off; send something
283
         * or drop connection if idle for too long.
284
         */
285
        tcpstat.tcps_keeptimeo++;
286
        if (tp->t_state < TCPS_ESTABLISHED)
287
                goto dropit;
288
        if ((always_keepalive ||
289
             tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
290
            tp->t_state <= TCPS_CLOSING) {
291
                if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle)
292
                        goto dropit;
293
                /*
294
                 * Send a packet designed to force a response
295
                 * if the peer is up and reachable:
296
                 * either an ACK if the connection is still alive,
297
                 * or an RST if the peer has closed the connection
298
                 * due to timeout or reboot.
299
                 * Using sequence number tp->snd_una-1
300
                 * causes the transmitted zero-length segment
301
                 * to lie outside the receive window;
302
                 * by the protocol spec, this requires the
303
                 * correspondent TCP to respond.
304
                 */
305
                tcpstat.tcps_keepprobe++;
306
                t_template = tcp_maketemplate(tp);
307
                if (t_template) {
308
                        tcp_respond(tp, t_template->tt_ipgen,
309
                                    &t_template->tt_t, (struct mbuf *)NULL,
310
                                    tp->rcv_nxt, tp->snd_una - 1, 0);
311
                        (void) m_free(dtom(t_template));
312
                }
313
                callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
314
        } else
315
                callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
316
 
317
#ifdef TCPDEBUG
318
        if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
319
                tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
320
                          PRU_SLOWTIMO);
321
#endif
322
        splx(s);
323
        return;
324
 
325
dropit:
326
        tcpstat.tcps_keepdrops++;
327
        tp = tcp_drop(tp, ETIMEDOUT);
328
 
329
#ifdef TCPDEBUG
330
        if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
331
                tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
332
                          PRU_SLOWTIMO);
333
#endif
334
        splx(s);
335
}
336
 
337
void
338
tcp_timer_persist(xtp)
339
        void *xtp;
340
{
341
        struct tcpcb *tp = xtp;
342
        int s;
343
#ifdef TCPDEBUG
344
        int ostate;
345
 
346
        ostate = tp->t_state;
347
#endif
348
        s = splnet();
349
        if (callout_pending(tp->tt_persist) || !callout_active(tp->tt_persist)){
350
                splx(s);
351
                return;
352
        }
353
        callout_deactivate(tp->tt_persist);
354
        /*
355
         * Persistance timer into zero window.
356
         * Force a byte to be output, if possible.
357
         */
358
        tcpstat.tcps_persisttimeo++;
359
        /*
360
         * Hack: if the peer is dead/unreachable, we do not
361
         * time out if the window is closed.  After a full
362
         * backoff, drop the connection if the idle time
363
         * (no responses to probes) reaches the maximum
364
         * backoff that we would use if retransmitting.
365
         */
366
        if (tp->t_rxtshift == tcp_rexmit_shift_max &&
367
            ((ticks - tp->t_rcvtime) >= tcp_maxpersistidle ||
368
             (ticks - tp->t_rcvtime) >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
369
                tcpstat.tcps_persistdrop++;
370
                tp = tcp_drop(tp, ETIMEDOUT);
371
                goto out;
372
        }
373
        tcp_setpersist(tp);
374
        tp->t_force = 1;
375
        (void) tcp_output(tp);
376
        tp->t_force = 0;
377
 
378
out:
379
#ifdef TCPDEBUG
380
        if (tp && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
381
                tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
382
                          PRU_SLOWTIMO);
383
#endif
384
        splx(s);
385
}
386
 
387
void
388
tcp_timer_rexmt(xtp)
389
        void *xtp;
390
{
391
        struct tcpcb *tp = xtp;
392
        int s;
393
        int rexmt;
394
#ifdef TCPDEBUG
395
        int ostate;
396
 
397
        ostate = tp->t_state;
398
#endif
399
        s = splnet();
400
        if (callout_pending(tp->tt_rexmt) || !callout_active(tp->tt_rexmt)) {
401
                splx(s);
402
                return;
403
        }
404
        callout_deactivate(tp->tt_rexmt);
405
        /*
406
         * Retransmission timer went off.  Message has not
407
         * been acked within retransmit interval.  Back off
408
         * to a longer retransmit interval and retransmit one segment.
409
         */
410
        if (++tp->t_rxtshift > tcp_rexmit_shift_max) {
411
                tp->t_rxtshift = tcp_rexmit_shift_max;
412
                tcpstat.tcps_timeoutdrop++;
413
                tp = tcp_drop(tp, tp->t_softerror ?
414
                              tp->t_softerror : ETIMEDOUT);
415
                goto out;
416
        }
417
        if (tp->t_rxtshift == 1) {
418
                /*
419
                 * first retransmit; record ssthresh and cwnd so they can
420
                 * be recovered if this turns out to be a "bad" retransmit.
421
                 * A retransmit is considered "bad" if an ACK for this
422
                 * segment is received within RTT/2 interval; the assumption
423
                 * here is that the ACK was already in flight.  See
424
                 * "On Estimating End-to-End Network Path Properties" by
425
                 * Allman and Paxson for more details.
426
                 */
427
                tp->snd_cwnd_prev = tp->snd_cwnd;
428
                tp->snd_ssthresh_prev = tp->snd_ssthresh;
429
                tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
430
        }
431
        tcpstat.tcps_rexmttimeo++;
432
        if (tp->t_state == TCPS_SYN_SENT)
433
                rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
434
        else
435
                rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
436
        TCPT_RANGESET(tp->t_rxtcur, rexmt,
437
                      tp->t_rttmin, TCPTV_REXMTMAX);
438
        /*
439
         * Disable rfc1323 and rfc1644 if we havn't got any response to
440
         * our third SYN to work-around some broken terminal servers
441
         * (most of which have hopefully been retired) that have bad VJ
442
         * header compression code which trashes TCP segments containing
443
         * unknown-to-them TCP options.
444
         */
445
        if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3))
446
                tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_REQ_CC);
447
        /*
448
         * If losing, let the lower level know and try for
449
         * a better route.  Also, if we backed off this far,
450
         * our srtt estimate is probably bogus.  Clobber it
451
         * so we'll take the next rtt measurement as our srtt;
452
         * move the current srtt into rttvar to keep the current
453
         * retransmit times until then.
454
         */
455
        if (tp->t_rxtshift > tcp_rexmit_shift_max / 4) {
456
#ifdef INET6
457
                if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
458
                        in6_losing(tp->t_inpcb);
459
                else
460
#endif
461
                in_losing(tp->t_inpcb);
462
                tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
463
                tp->t_srtt = 0;
464
        }
465
        tp->snd_nxt = tp->snd_una;
466
        /*
467
         * Note:  We overload snd_recover to function also as the
468
         * snd_last variable described in RFC 2582
469
         */
470
        tp->snd_recover = tp->snd_max;
471
        /*
472
         * Force a segment to be sent.
473
         */
474
        tp->t_flags |= TF_ACKNOW;
475
        /*
476
         * If timing a segment in this window, stop the timer.
477
         */
478
        tp->t_rtttime = 0;
479
        /*
480
         * Close the congestion window down to one segment
481
         * (we'll open it by one segment for each ack we get).
482
         * Since we probably have a window's worth of unacked
483
         * data accumulated, this "slow start" keeps us from
484
         * dumping all that data as back-to-back packets (which
485
         * might overwhelm an intermediate gateway).
486
         *
487
         * There are two phases to the opening: Initially we
488
         * open by one mss on each ack.  This makes the window
489
         * size increase exponentially with time.  If the
490
         * window is larger than the path can handle, this
491
         * exponential growth results in dropped packet(s)
492
         * almost immediately.  To get more time between
493
         * drops but still "push" the network to take advantage
494
         * of improving conditions, we switch from exponential
495
         * to linear window opening at some threshhold size.
496
         * For a threshhold, we use half the current window
497
         * size, truncated to a multiple of the mss.
498
         *
499
         * (the minimum cwnd that will give us exponential
500
         * growth is 2 mss.  We don't allow the threshhold
501
         * to go below this.)
502
         */
503
        {
504
                u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
505
                if (win < 2)
506
                        win = 2;
507
                tp->snd_cwnd = tp->t_maxseg;
508
                tp->snd_ssthresh = win * tp->t_maxseg;
509
                tp->t_dupacks = 0;
510
        }
511
        (void) tcp_output(tp);
512
 
513
out:
514
#ifdef TCPDEBUG
515
        if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
516
                tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
517
                          PRU_SLOWTIMO);
518
#endif
519
        splx(s);
520
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.