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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [netinet/] [tcp_timer.c] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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