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:
parent
b3c0f300fb
commit
751dea2935
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162111
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user