From e9484001ee2a1030228de39c997e19f90e32516b Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 13 Jul 2023 02:54:27 -0700 Subject: [PATCH] pim6d: Fixing core while running MLD conformance test. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit While running MLD conformance test 9.2 core is getting generated. Test setps: 1. ANVL: Listen (for upto seconds) on . 2. DUT: Send MLD General Query Message. 3. ANVL: Send MLD Report Message to containing: • IPv6 Source Address field set to link-local IPv6 Address of HOST-1 • IPv6 Destination Address field set to • MLD Multicast Address field set to . 4. ANVL: Wait for seconds for DUT to process and add to its Multicast Address list. 5. ANVL: Send MLD General Query Message to containing: • IPv6 Source Address field set to link-local IPv6 Address of RTR-1 which is numerically less than the link-local IPv6 unicast address of • IPv6 Destination Address field set to link-scope all-nodes multicast address. 6. ANVL: Send MLD Multicast-Address-Specific Query Message to containing: • IPv6 Source Address field set to link-local IPv6 Address of RTR-1 • IPv6 Destination Address field set to • MLD Multicast Address field set to • MLD Maximum Response Delay field value set to 0. 7. ANVL: Verify that the Maximum Response Delay timer for is set to zero. While running above test, when group specific query is received we start gm_t_sg_expire timer. Once this timer expires, we clear the corresponding entry. During this sg->state was still set to JOIN. This happened because receiver went down without sending leave. Added a condition to update the sg->state before starting the timer. If receiver goes down without sending leave we will update sg->state to GM_SG_JOIN_EXPIRING or GM_SG_NOPRUNE_EXPIRING based on previous state. If we receive a join then sg->state will be refreshed and will be updated to JOIN state. Fixes: #13387 Signed-off-by: Abhishek N R --- pimd/pim6_mld.c | 2 ++ pimd/pim6_mld.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c index 52496325c4..ed9967e7a8 100644 --- a/pimd/pim6_mld.c +++ b/pimd/pim6_mld.c @@ -1243,6 +1243,7 @@ static void gm_handle_q_groupsrc(struct gm_if *gm_ifp, for (i = 0; i < n_src; i++) { sg = gm_sg_find(gm_ifp, grp, srcs[i]); + GM_UPDATE_SG_STATE(sg); gm_sg_timer_start(gm_ifp, sg, timers->expire_wait); } } @@ -1317,6 +1318,7 @@ static void gm_handle_q_group(struct gm_if *gm_ifp, if (PIM_DEBUG_GM_TRACE) zlog_debug(log_ifp("*,%pPAs expiry timer starting"), &grp); + GM_UPDATE_SG_STATE(sg); gm_sg_timer_start(gm_ifp, sg, timers->expire_wait); sg = gm_sgs_next(gm_ifp->sgs, sg); diff --git a/pimd/pim6_mld.h b/pimd/pim6_mld.h index 7634fb2ec4..183ab2fc50 100644 --- a/pimd/pim6_mld.h +++ b/pimd/pim6_mld.h @@ -36,6 +36,21 @@ enum gm_sg_state { GM_SG_NOPRUNE_EXPIRING, }; +/* If the timer gm_t_sg_expire is started without a leave message being received, + * the sg->state should be moved to expiring states. + * When the timer expires, we do not expect the state to be in join state. + * If a JOIN message is received while the timer is running, + * the state will be moved to JOIN and this timer will be switched off. + * Hence the below state transition is done. + */ +#define GM_UPDATE_SG_STATE(sg) \ + do { \ + if (sg->state == GM_SG_JOIN) \ + sg->state = GM_SG_JOIN_EXPIRING; \ + else if (sg->state == GM_SG_NOPRUNE) \ + sg->state = GM_SG_NOPRUNE_EXPIRING; \ + } while (0) + static inline bool gm_sg_state_want_join(enum gm_sg_state state) { return state != GM_SG_NOINFO && state != GM_SG_PRUNE; -- 2.39.5