summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2015-03-23 20:23:30 +0000
committerRobert Mustacchi <rm@joyent.com>2015-05-15 16:36:42 -0700
commitf5db8fb084e8d3d9f551ce34defa3c80d56edebc (patch)
tree01d99f3741a16acabe26b6d06f94262425b5e9db /usr/src
parente7619b69689d6a40a07425ef14002f2ab4d724d9 (diff)
downloadillumos-joyent-f5db8fb084e8d3d9f551ce34defa3c80d56edebc.tar.gz
5893 igmp timout logic induces panic
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/ip/igmp.c46
-rw-r--r--usr/src/uts/common/inet/ip/ip.c21
-rw-r--r--usr/src/uts/common/inet/ip_stack.h4
3 files changed, 57 insertions, 14 deletions
diff --git a/usr/src/uts/common/inet/ip/igmp.c b/usr/src/uts/common/inet/ip/igmp.c
index 411a781e6d..423bb2a816 100644
--- a/usr/src/uts/common/inet/ip/igmp.c
+++ b/usr/src/uts/common/inet/ip/igmp.c
@@ -149,12 +149,16 @@ igmp_start_timers(unsigned next, ip_stack_t *ipst)
}
if (ipst->ips_igmp_timeout_id == 0) {
/*
- * The timer is inactive. We need to start a timer
+ * The timer is inactive. We need to start a timer if we haven't
+ * been asked to quiesce.
*/
ipst->ips_igmp_time_to_next = next;
- ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler,
- (void *)ipst, MSEC_TO_TICK(ipst->ips_igmp_time_to_next));
- ipst->ips_igmp_timer_scheduled_last = ddi_get_lbolt();
+ if (ipst->ips_igmp_timer_quiesce != B_TRUE) {
+ ipst->ips_igmp_timeout_id =
+ timeout(igmp_timeout_handler, (void *)ipst,
+ MSEC_TO_TICK(ipst->ips_igmp_time_to_next));
+ ipst->ips_igmp_timer_scheduled_last = ddi_get_lbolt();
+ }
ipst->ips_igmp_timer_setter_active = B_FALSE;
mutex_exit(&ipst->ips_igmp_timer_lock);
return;
@@ -193,7 +197,8 @@ igmp_start_timers(unsigned next, ip_stack_t *ipst)
ASSERT(ipst->ips_igmp_timeout_id != 0);
ipst->ips_igmp_timeout_id = 0;
}
- if (ipst->ips_igmp_time_to_next != 0) {
+ if (ipst->ips_igmp_time_to_next != 0 &&
+ ipst->ips_igmp_timer_quiesce != B_TRUE) {
ipst->ips_igmp_time_to_next =
MIN(ipst->ips_igmp_time_to_next, next);
ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler,
@@ -235,12 +240,16 @@ mld_start_timers(unsigned next, ip_stack_t *ipst)
}
if (ipst->ips_mld_timeout_id == 0) {
/*
- * The timer is inactive. We need to start a timer
+ * The timer is inactive. We need to start a timer, if we
+ * haven't been asked to quiesce.
*/
ipst->ips_mld_time_to_next = next;
- ipst->ips_mld_timeout_id = timeout(mld_timeout_handler,
- (void *)ipst, MSEC_TO_TICK(ipst->ips_mld_time_to_next));
- ipst->ips_mld_timer_scheduled_last = ddi_get_lbolt();
+ if (ipst->ips_mld_timer_quiesce != B_TRUE) {
+ ipst->ips_mld_timeout_id = timeout(mld_timeout_handler,
+ (void *)ipst,
+ MSEC_TO_TICK(ipst->ips_mld_time_to_next));
+ ipst->ips_mld_timer_scheduled_last = ddi_get_lbolt();
+ }
ipst->ips_mld_timer_setter_active = B_FALSE;
mutex_exit(&ipst->ips_mld_timer_lock);
return;
@@ -279,7 +288,8 @@ mld_start_timers(unsigned next, ip_stack_t *ipst)
ASSERT(ipst->ips_mld_timeout_id != 0);
ipst->ips_mld_timeout_id = 0;
}
- if (ipst->ips_mld_time_to_next != 0) {
+ if (ipst->ips_mld_time_to_next != 0 &&
+ ipst->ips_mld_timer_quiesce == B_FALSE) {
ipst->ips_mld_time_to_next =
MIN(ipst->ips_mld_time_to_next, next);
ipst->ips_mld_timeout_id = timeout(mld_timeout_handler,
@@ -1737,8 +1747,12 @@ igmp_slowtimo(void *arg)
rw_exit(&ipst->ips_ill_g_lock);
ill_mcast_timer_start(ipst);
mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
- ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
- MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
+ if (ipst->ips_igmp_slowtimeout_quiesce != B_TRUE) {
+ ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo,
+ (void *)ipst, MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
+ } else {
+ ipst->ips_igmp_slowtimeout_id = 0;
+ }
mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
}
@@ -1796,8 +1810,12 @@ mld_slowtimo(void *arg)
rw_exit(&ipst->ips_ill_g_lock);
ill_mcast_timer_start(ipst);
mutex_enter(&ipst->ips_mld_slowtimeout_lock);
- ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
- MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
+ if (ipst->ips_mld_slowtimeout_quiesce != B_TRUE) {
+ ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo,
+ (void *)ipst, MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
+ } else {
+ ipst->ips_mld_slowtimeout_id = 0;
+ }
mutex_exit(&ipst->ips_mld_slowtimeout_lock);
}
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index c8eda26549..f006e83a1f 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -4421,6 +4421,27 @@ ip_stack_fini(netstackid_t stackid, void *arg)
dce_stack_destroy(ipst);
ip_mrouter_stack_destroy(ipst);
+ /*
+ * Quiesce all of our timers. Note we set the quiesce flags before we
+ * call untimeout. The slowtimers may actually kick off another instance
+ * of the non-slow timers.
+ */
+ mutex_enter(&ipst->ips_igmp_timer_lock);
+ ipst->ips_igmp_timer_quiesce = B_TRUE;
+ mutex_exit(&ipst->ips_igmp_timer_lock);
+
+ mutex_enter(&ipst->ips_mld_timer_lock);
+ ipst->ips_mld_timer_quiesce = B_TRUE;
+ mutex_exit(&ipst->ips_mld_timer_lock);
+
+ mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
+ ipst->ips_igmp_slowtimeout_quiesce = B_TRUE;
+ mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
+
+ mutex_enter(&ipst->ips_mld_slowtimeout_lock);
+ ipst->ips_mld_slowtimeout_quiesce = B_TRUE;
+ mutex_exit(&ipst->ips_mld_slowtimeout_lock);
+
ret = untimeout(ipst->ips_igmp_timeout_id);
if (ret == -1) {
ASSERT(ipst->ips_igmp_timeout_id == 0);
diff --git a/usr/src/uts/common/inet/ip_stack.h b/usr/src/uts/common/inet/ip_stack.h
index e46a3b6a3c..ab954c7c31 100644
--- a/usr/src/uts/common/inet/ip_stack.h
+++ b/usr/src/uts/common/inet/ip_stack.h
@@ -205,6 +205,7 @@ struct ip_stack {
int ips_igmp_deferred_next;
timeout_id_t ips_igmp_timeout_id;
boolean_t ips_igmp_timer_setter_active;
+ boolean_t ips_igmp_timer_quiesce;
/* Following protected by mld_timer_lock */
int ips_mld_time_to_next; /* Time since last timeout */
@@ -212,14 +213,17 @@ struct ip_stack {
int ips_mld_deferred_next;
timeout_id_t ips_mld_timeout_id;
boolean_t ips_mld_timer_setter_active;
+ boolean_t ips_mld_timer_quiesce;
/* Protected by igmp_slowtimeout_lock */
timeout_id_t ips_igmp_slowtimeout_id;
kmutex_t ips_igmp_slowtimeout_lock;
+ boolean_t ips_igmp_slowtimeout_quiesce;
/* Protected by mld_slowtimeout_lock */
timeout_id_t ips_mld_slowtimeout_id;
kmutex_t ips_mld_slowtimeout_lock;
+ boolean_t ips_mld_slowtimeout_quiesce;
/* IPv4 forwarding table */
struct radix_node_head *ips_ip_ftable;