aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/tcp_stacks/fastpath.c2
-rw-r--r--sys/netinet/tcp_subr.c74
-rw-r--r--sys/netinet/tcp_timer.c22
-rw-r--r--sys/netinet/tcp_timer.h8
-rw-r--r--sys/netinet/tcp_var.h12
5 files changed, 33 insertions, 85 deletions
diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c
index a447b88669b4..5529fd8224de 100644
--- a/sys/netinet/tcp_stacks/fastpath.c
+++ b/sys/netinet/tcp_stacks/fastpath.c
@@ -2386,7 +2386,6 @@ struct tcp_function_block __tcp_fastslow = {
NULL,
NULL,
NULL,
- NULL,
0,
0
@@ -2403,7 +2402,6 @@ struct tcp_function_block __tcp_fastack = {
NULL,
NULL,
NULL,
- NULL,
0,
0
};
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index aa2429901778..178ea77eb81f 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -244,7 +244,6 @@ static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int);
static void tcp_mtudisc(struct inpcb *, int);
static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th,
void *ip4hdr, const void *ip6hdr);
-static void tcp_timer_discard(struct tcpcb *, uint32_t);
static struct tcp_function_block tcp_def_funcblk = {
@@ -258,7 +257,6 @@ static struct tcp_function_block tcp_def_funcblk = {
NULL,
NULL,
NULL,
- NULL,
0,
0
};
@@ -528,7 +526,6 @@ register_tcp_functions(struct tcp_function_block *blk, int wait)
return (EINVAL);
}
if (blk->tfb_tcp_timer_stop_all ||
- blk->tfb_tcp_timers_left ||
blk->tfb_tcp_timer_activate ||
blk->tfb_tcp_timer_active ||
blk->tfb_tcp_timer_stop) {
@@ -537,7 +534,6 @@ register_tcp_functions(struct tcp_function_block *blk, int wait)
* must have them all.
*/
if ((blk->tfb_tcp_timer_stop_all == NULL) ||
- (blk->tfb_tcp_timers_left == NULL) ||
(blk->tfb_tcp_timer_activate == NULL) ||
(blk->tfb_tcp_timer_active == NULL) ||
(blk->tfb_tcp_timer_stop == NULL)) {
@@ -1343,13 +1339,21 @@ tcp_discardcb(struct tcpcb *tp)
* callout, and the last discard function called will take care of
* deleting the tcpcb.
*/
+ tp->t_timers->tt_draincnt = 0;
tcp_timer_stop(tp, TT_REXMT);
tcp_timer_stop(tp, TT_PERSIST);
tcp_timer_stop(tp, TT_KEEP);
tcp_timer_stop(tp, TT_2MSL);
tcp_timer_stop(tp, TT_DELACK);
if (tp->t_fb->tfb_tcp_timer_stop_all) {
- /* Call the stop-all function of the methods */
+ /*
+ * Call the stop-all function of the methods,
+ * this function should call the tcp_timer_stop()
+ * method with each of the function specific timeouts.
+ * That stop will be called via the tfb_tcp_timer_stop()
+ * which should use the async drain function of the
+ * callout system (see tcp_var.h).
+ */
tp->t_fb->tfb_tcp_timer_stop_all(tp);
}
@@ -1434,13 +1438,8 @@ tcp_discardcb(struct tcpcb *tp)
CC_ALGO(tp) = NULL;
inp->inp_ppcb = NULL;
- if ((tp->t_timers->tt_flags & TT_MASK) == 0) {
+ if (tp->t_timers->tt_draincnt == 0) {
/* We own the last reference on tcpcb, let's free it. */
- if ((tp->t_fb->tfb_tcp_timers_left) &&
- (tp->t_fb->tfb_tcp_timers_left(tp))) {
- /* Some fb timers left running! */
- return;
- }
if (tp->t_fb->tfb_tcp_fb_fini)
(*tp->t_fb->tfb_tcp_fb_fini)(tp);
refcount_release(&tp->t_fb->tfb_refcnt);
@@ -1453,45 +1452,12 @@ tcp_discardcb(struct tcpcb *tp)
}
void
-tcp_timer_2msl_discard(void *xtp)
-{
-
- tcp_timer_discard((struct tcpcb *)xtp, TT_2MSL);
-}
-
-void
-tcp_timer_keep_discard(void *xtp)
-{
-
- tcp_timer_discard((struct tcpcb *)xtp, TT_KEEP);
-}
-
-void
-tcp_timer_persist_discard(void *xtp)
-{
-
- tcp_timer_discard((struct tcpcb *)xtp, TT_PERSIST);
-}
-
-void
-tcp_timer_rexmt_discard(void *xtp)
-{
-
- tcp_timer_discard((struct tcpcb *)xtp, TT_REXMT);
-}
-
-void
-tcp_timer_delack_discard(void *xtp)
-{
-
- tcp_timer_discard((struct tcpcb *)xtp, TT_DELACK);
-}
-
-void
-tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
+tcp_timer_discard(void *ptp)
{
struct inpcb *inp;
-
+ struct tcpcb *tp;
+
+ tp = (struct tcpcb *)ptp;
CURVNET_SET(tp->t_vnet);
INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
@@ -1500,16 +1466,9 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
INP_WLOCK(inp);
KASSERT((tp->t_timers->tt_flags & TT_STOPPED) != 0,
("%s: tcpcb has to be stopped here", __func__));
- KASSERT((tp->t_timers->tt_flags & timer_type) != 0,
- ("%s: discard callout should be running", __func__));
- tp->t_timers->tt_flags &= ~timer_type;
- if ((tp->t_timers->tt_flags & TT_MASK) == 0) {
+ tp->t_timers->tt_draincnt--;
+ if (tp->t_timers->tt_draincnt == 0) {
/* We own the last reference on this tcpcb, let's free it. */
- if ((tp->t_fb->tfb_tcp_timers_left) &&
- (tp->t_fb->tfb_tcp_timers_left(tp))) {
- /* Some fb timers left running! */
- goto leave;
- }
if (tp->t_fb->tfb_tcp_fb_fini)
(*tp->t_fb->tfb_tcp_fb_fini)(tp);
refcount_release(&tp->t_fb->tfb_refcnt);
@@ -1521,7 +1480,6 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
return;
}
}
-leave:
INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 172c39419739..5d6865c6bf4d 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -927,7 +927,6 @@ void
tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
{
struct callout *t_callout;
- timeout_t *f_callout;
uint32_t f_reset;
tp->t_timers->tt_flags |= TT_STOPPED;
@@ -935,27 +934,22 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
switch (timer_type) {
case TT_DELACK:
t_callout = &tp->t_timers->tt_delack;
- f_callout = tcp_timer_delack_discard;
f_reset = TT_DELACK_RST;
break;
case TT_REXMT:
t_callout = &tp->t_timers->tt_rexmt;
- f_callout = tcp_timer_rexmt_discard;
f_reset = TT_REXMT_RST;
break;
case TT_PERSIST:
t_callout = &tp->t_timers->tt_persist;
- f_callout = tcp_timer_persist_discard;
f_reset = TT_PERSIST_RST;
break;
case TT_KEEP:
t_callout = &tp->t_timers->tt_keep;
- f_callout = tcp_timer_keep_discard;
f_reset = TT_KEEP_RST;
break;
case TT_2MSL:
t_callout = &tp->t_timers->tt_2msl;
- f_callout = tcp_timer_2msl_discard;
f_reset = TT_2MSL_RST;
break;
default:
@@ -971,21 +965,13 @@ tcp_timer_stop(struct tcpcb *tp, uint32_t timer_type)
}
if (tp->t_timers->tt_flags & timer_type) {
- if ((callout_stop(t_callout) > 0) &&
- (tp->t_timers->tt_flags & f_reset)) {
- tp->t_timers->tt_flags &= ~(timer_type | f_reset);
- } else {
+ if (callout_async_drain(t_callout, tcp_timer_discard) == 0) {
/*
* Can't stop the callout, defer tcpcb actual deletion
- * to the last tcp timer discard callout.
- * The TT_STOPPED flag will ensure that no tcp timer
- * callouts can be restarted on our behalf, and
- * past this point currently running callouts waiting
- * on inp lock will return right away after the
- * classical check for callout reset/stop events:
- * callout_pending() || !callout_active()
+ * to the last one. We do this using the async drain
+ * function and incrementing the count in
*/
- callout_reset(t_callout, 1, f_callout, tp);
+ tp->t_timers->tt_draincnt++;
}
}
}
diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h
index 252560a4c099..12481b5708a8 100644
--- a/sys/netinet/tcp_timer.h
+++ b/sys/netinet/tcp_timer.h
@@ -146,7 +146,7 @@ struct tcp_timer {
struct callout tt_2msl; /* 2*msl TIME_WAIT timer */
struct callout tt_delack; /* delayed ACK timer */
uint32_t tt_flags; /* Timers flags */
- uint32_t tt_spare; /* TDB */
+ uint32_t tt_draincnt; /* Count being drained */
};
/*
@@ -193,17 +193,13 @@ extern int tcp_fast_finwait2_recycle;
void tcp_timer_init(void);
void tcp_timer_2msl(void *xtp);
+void tcp_timer_discard(void *);
struct tcptw *
tcp_tw_2msl_scan(int reuse); /* XXX temporary? */
void tcp_timer_keep(void *xtp);
void tcp_timer_persist(void *xtp);
void tcp_timer_rexmt(void *xtp);
void tcp_timer_delack(void *xtp);
-void tcp_timer_2msl_discard(void *xtp);
-void tcp_timer_keep_discard(void *xtp);
-void tcp_timer_persist_discard(void *xtp);
-void tcp_timer_rexmt_discard(void *xtp);
-void tcp_timer_delack_discard(void *xtp);
void tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer,
struct xtcp_timer *xtimer);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index d60ad9f50d3d..f2c76a889553 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -106,6 +106,17 @@ struct inpcb;
struct sockopt;
struct socket;
+/*
+ * If defining the optional tcp_timers, in the
+ * tfb_tcp_timer_stop call you must use the
+ * callout_async_drain() function with the
+ * tcp_timer_discard callback. You should check
+ * the return of callout_async_drain() and if 0
+ * increment tt_draincnt. Since the timer sub-system
+ * does not know your callbacks you must provide a
+ * stop_all function that loops through and calls
+ * tcp_timer_stop() with each of your defined timers.
+ */
struct tcp_function_block {
char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX];
int (*tfb_tcp_output)(struct tcpcb *);
@@ -120,7 +131,6 @@ struct tcp_function_block {
void (*tfb_tcp_fb_fini)(struct tcpcb *);
/* Optional timers, must define all if you define one */
int (*tfb_tcp_timer_stop_all)(struct tcpcb *);
- int (*tfb_tcp_timers_left)(struct tcpcb *);
void (*tfb_tcp_timer_activate)(struct tcpcb *,
uint32_t, u_int);
int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t);