diff options
author | Robert Mustacchi <rm@joyent.com> | 2015-03-23 20:23:30 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2015-05-15 16:36:42 -0700 |
commit | f5db8fb084e8d3d9f551ce34defa3c80d56edebc (patch) | |
tree | 01d99f3741a16acabe26b6d06f94262425b5e9db /usr/src | |
parent | e7619b69689d6a40a07425ef14002f2ab4d724d9 (diff) | |
download | illumos-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.c | 46 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 21 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip_stack.h | 4 |
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; |