Back when we had T/TCP support, we used to apply different

timeouts for TCP and T/TCP connections in the TIME_WAIT
state, and we had two separate timed wait queues for them.
Now that is has gone, the timeout is always 2*MSL again,
and there is no reason to keep two queues (the first was
unused anyway!).

Also, reimplement the remaining queue using a TAILQ (it
was technically impossible before, with two queues).
This commit is contained in:
Ruslan Ermilov 2006-09-07 13:06:00 +00:00
parent b3c0f300fb
commit 751dea2935
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162111
7 changed files with 30 additions and 55 deletions

View File

@ -3187,7 +3187,7 @@ tcp_timewait(inp, to, th, m, tlen)
const int isipv6 = 0;
#endif
/* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */
/* tcbinfo lock required for tcp_twclose(), tcp_timer_2msl_reset(). */
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(inp);
@ -3256,7 +3256,7 @@ tcp_timewait(inp, to, th, m, tlen)
if (thflags & TH_FIN) {
seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
if (seq + 1 == tw->rcv_nxt)
tcp_timer_2msl_reset(tw, 2 * tcp_msl, 1);
tcp_timer_2msl_reset(tw, 1);
}
/*

View File

@ -3187,7 +3187,7 @@ tcp_timewait(inp, to, th, m, tlen)
const int isipv6 = 0;
#endif
/* tcbinfo lock required for tcp_twclose(), tcp_2msl_reset. */
/* tcbinfo lock required for tcp_twclose(), tcp_timer_2msl_reset(). */
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(inp);
@ -3256,7 +3256,7 @@ tcp_timewait(inp, to, th, m, tlen)
if (thflags & TH_FIN) {
seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
if (seq + 1 == tw->rcv_nxt)
tcp_timer_2msl_reset(tw, 2 * tcp_msl, 1);
tcp_timer_2msl_reset(tw, 1);
}
/*

View File

@ -1736,7 +1736,7 @@ tcp_twstart(struct tcpcb *tp)
{
struct tcptw *tw;
struct inpcb *inp;
int tw_time, acknow;
int acknow;
struct socket *so;
INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */
@ -1781,7 +1781,6 @@ tcp_twstart(struct tcpcb *tp)
* be used for fin-wait-2 state also, then we may need
* a ts_recent from the last segment.
*/
tw_time = 2 * tcp_msl;
acknow = tp->t_flags & TF_ACKNOW;
/*
@ -1803,7 +1802,7 @@ tcp_twstart(struct tcpcb *tp)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
inp->inp_vflag |= INP_TIMEWAIT;
tcp_timer_2msl_reset(tw, tw_time, 0);
tcp_timer_2msl_reset(tw, 0);
/*
* If the inpcb owns the sole reference to the socket, then we can

View File

@ -230,45 +230,30 @@ tcp_timer_2msl(xtp)
}
/*
* The timed wait lists contain references to each of the TCP sessions
* currently TIME_WAIT state. The list pointers, including the list pointers
* in each tcptw structure, are protected using the global tcbinfo lock,
* which must be held over list iteration and modification.
* The timed wait queue contains references to each of the TCP sessions
* currently in the TIME_WAIT state. The queue pointers, including the
* queue pointers in each tcptw structure, are protected using the global
* tcbinfo lock, which must be held over queue iteration and modification.
*/
struct twlist {
LIST_HEAD(, tcptw) tw_list;
struct tcptw tw_tail;
};
#define TWLIST_NLISTS 2
static struct twlist twl_2msl[TWLIST_NLISTS];
static TAILQ_HEAD(, tcptw) twq_2msl;
void
tcp_timer_init(void)
{
int i;
struct twlist *twl;
for (i = 0; i < TWLIST_NLISTS; i++) {
twl = &twl_2msl[i];
LIST_INIT(&twl->tw_list);
LIST_INSERT_HEAD(&twl->tw_list, &twl->tw_tail, tw_2msl);
}
TAILQ_INIT(&twq_2msl);
}
void
tcp_timer_2msl_reset(struct tcptw *tw, int timeo, int rearm)
tcp_timer_2msl_reset(struct tcptw *tw, int rearm)
{
int i;
struct tcptw *tw_tail;
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(tw->tw_inpcb);
if (rearm)
LIST_REMOVE(tw, tw_2msl);
tw->tw_time = timeo + ticks;
i = timeo > tcp_msl ? 1 : 0;
tw_tail = &twl_2msl[i].tw_tail;
LIST_INSERT_BEFORE(tw_tail, tw, tw_2msl);
TAILQ_REMOVE(&twq_2msl, tw, tw_2msl);
tw->tw_time = ticks + 2 * tcp_msl;
TAILQ_INSERT_TAIL(&twq_2msl, tw, tw_2msl);
}
void
@ -276,31 +261,23 @@ tcp_timer_2msl_stop(struct tcptw *tw)
{
INP_INFO_WLOCK_ASSERT(&tcbinfo);
LIST_REMOVE(tw, tw_2msl);
TAILQ_REMOVE(&twq_2msl, tw, tw_2msl);
}
struct tcptw *
tcp_timer_2msl_tw(int reuse)
{
struct tcptw *tw, *tw_tail;
struct twlist *twl;
int i;
struct tcptw *tw;
INP_INFO_WLOCK_ASSERT(&tcbinfo);
for (i = 0; i < TWLIST_NLISTS; i++) {
twl = &twl_2msl[i];
tw_tail = &twl->tw_tail;
for (;;) {
tw = LIST_FIRST(&twl->tw_list);
if (tw == tw_tail || (!reuse && tw->tw_time > ticks))
break;
INP_LOCK(tw->tw_inpcb);
tcp_twclose(tw, reuse);
if (reuse)
return (tw);
}
for (;;) {
tw = TAILQ_FIRST(&twq_2msl);
if (tw == NULL || (!reuse && tw->tw_time > ticks))
break;
INP_LOCK(tw->tw_inpcb);
tcp_twclose(tw, reuse);
if (reuse)
return (tw);
}
return (NULL);
}

View File

@ -156,7 +156,7 @@ void tcp_timer_init(void);
void tcp_timer_2msl(void *xtp);
struct tcptw *
tcp_timer_2msl_tw(int _reuse); /* XXX temporary */
void tcp_timer_2msl_reset(struct tcptw *_tw, int _timeo, int rearm);
void tcp_timer_2msl_reset(struct tcptw *_tw, int rearm);
void tcp_timer_2msl_stop(struct tcptw *_tw);
void tcp_timer_keep(void *xtp);
void tcp_timer_persist(void *xtp);

View File

@ -1736,7 +1736,7 @@ tcp_twstart(struct tcpcb *tp)
{
struct tcptw *tw;
struct inpcb *inp;
int tw_time, acknow;
int acknow;
struct socket *so;
INP_INFO_WLOCK_ASSERT(&tcbinfo); /* tcp_timer_2msl_reset(). */
@ -1781,7 +1781,6 @@ tcp_twstart(struct tcpcb *tp)
* be used for fin-wait-2 state also, then we may need
* a ts_recent from the last segment.
*/
tw_time = 2 * tcp_msl;
acknow = tp->t_flags & TF_ACKNOW;
/*
@ -1803,7 +1802,7 @@ tcp_twstart(struct tcpcb *tp)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
inp->inp_vflag |= INP_TIMEWAIT;
tcp_timer_2msl_reset(tw, tw_time, 0);
tcp_timer_2msl_reset(tw, 0);
/*
* If the inpcb owns the sole reference to the socket, then we can

View File

@ -276,7 +276,7 @@ struct tcptw {
u_long t_recent;
u_long t_starttime;
int tw_time;
LIST_ENTRY(tcptw) tw_2msl;
TAILQ_ENTRY(tcptw) tw_2msl;
};
#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb)