From 00fed6ed3b412c24a3c9aff455065b39f8ec8f6b Mon Sep 17 00:00:00 2001 From: Abhishek N R Date: Thu, 23 Mar 2023 21:55:06 -0700 Subject: [PATCH] pim6d: Fixing mroutes not created after disabling and enabling PIMv6. After doing "no ipv6 pim" and "ipv6 pim" on receiver interface in LHR, mroutes were not created. When we enable pim after disabling it, we refresh the membership on pim interface. First we clear the membership on the interface, then we add it back. For PIMv6 we were only clearing it, membership was not added back. So mroutes were not created. Now added code to fetch all the local membership information into PIM. Fixes: #12005, #12820 Signed-off-by: Abhishek N R --- pimd/pim6_mld.c | 6 ++---- pimd/pim6_mld.h | 3 +++ pimd/pim_nb_config.c | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c index fa699cca5e..70d057f324 100644 --- a/pimd/pim6_mld.c +++ b/pimd/pim6_mld.c @@ -99,7 +99,7 @@ static inline uint8_t in6_multicast_scope(const pim_addr *addr) return addr->s6_addr[1] & 0xf; } -static inline bool in6_multicast_nofwd(const pim_addr *addr) +bool in6_multicast_nofwd(const pim_addr *addr) { return in6_multicast_scope(addr) <= IPV6_MULTICAST_SCOPE_LINK; } @@ -182,13 +182,11 @@ DECLARE_HASH(gm_gsq_pends, struct gm_gsq_pending, itm, gm_gsq_pending_cmp, * interface -> (S,G) */ -static int gm_sg_cmp(const struct gm_sg *a, const struct gm_sg *b) +int gm_sg_cmp(const struct gm_sg *a, const struct gm_sg *b) { return pim_sgaddr_cmp(a->sgaddr, b->sgaddr); } -DECLARE_RBTREE_UNIQ(gm_sgs, struct gm_sg, itm, gm_sg_cmp); - static struct gm_sg *gm_sg_find(struct gm_if *gm_ifp, pim_addr grp, pim_addr src) { diff --git a/pimd/pim6_mld.h b/pimd/pim6_mld.h index 2af1c77c24..282fad8a25 100644 --- a/pimd/pim6_mld.h +++ b/pimd/pim6_mld.h @@ -113,6 +113,8 @@ struct gm_sg { */ struct gm_packet_sg *most_recent; }; +int gm_sg_cmp(const struct gm_sg *a, const struct gm_sg *b); +DECLARE_RBTREE_UNIQ(gm_sgs, struct gm_sg, itm, gm_sg_cmp); /* host tracking entry. addr will be one of: * @@ -352,5 +354,6 @@ static inline void gm_ifp_teardown(struct interface *ifp) #endif extern void gm_cli_init(void); +bool in6_multicast_nofwd(const pim_addr *addr); #endif /* PIM6_MLD_H */ diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index fa6f664149..c8543ea999 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -71,12 +71,19 @@ static void pim_if_membership_clear(struct interface *ifp) static void pim_if_membership_refresh(struct interface *ifp) { struct pim_interface *pim_ifp; +#if PIM_IPV == 4 struct listnode *grpnode; struct gm_group *grp; - +#else + struct gm_if *gm_ifp; + struct gm_sg *sg, *sg_start; +#endif pim_ifp = ifp->info; assert(pim_ifp); +#if PIM_IPV == 6 + gm_ifp = pim_ifp->mld; +#endif if (!pim_ifp->pim_enable) return; @@ -90,6 +97,7 @@ static void pim_if_membership_refresh(struct interface *ifp) pim_ifchannel_membership_clear(ifp); +#if PIM_IPV == 4 /* * Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on * the interface @@ -116,6 +124,16 @@ static void pim_if_membership_refresh(struct interface *ifp) } /* scan group sources */ } /* scan igmp groups */ +#else + sg_start = gm_sgs_first(gm_ifp->sgs); + + frr_each_from (gm_sgs, gm_ifp->sgs, sg, sg_start) { + if (!in6_multicast_nofwd(&sg->sgaddr.grp)) { + pim_ifchannel_local_membership_add( + ifp, &sg->sgaddr, false /*is_vxlan*/); + } + } +#endif /* * Finally delete every PIM (S,G) entry lacking all state info -- 2.39.5