From 356580224728ed0e626f937c923a2a3300816521 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Tue, 7 May 2019 12:02:43 -0700 Subject: [PATCH 1/2] pimd: ensure that the oif is removed from all the mroutes pre-vifi deletion When a link goes down the vifi was being deleted but the OIF stayed in the OIL with a stale vifi - oroot@act-7726-03:~# net show pim state Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN Installed Source Group IIF OIL 1 * 239.1.1.111 swp1s1 pimreg(I ), ipmr-lo( J ) 1 6.0.0.28 239.1.1.111 lo pimreg( J ), ipmr-lo( *), swp1s1( J ) root@act-7726-03:~# ip link set swp1s1 down root@act-7726-03:~# net show pim state Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN Installed Source Group IIF OIL 1 * 239.1.1.111 swp1s0 pimreg(I ), ipmr-lo( J ) 1 6.0.0.28 239.1.1.111 lo ipmr-lo( *), swp1s0( J ), ( J ) >>>>>>>> root@act-7726-03:~# The problem was as a part ifchannel_delete the join state of the channel was checked to avoid incorrect OIF deletion this was preventing the OIF from being flushed. Fix is to flip the channel join-state to NOINFO before deleting it. Signed-off-by: Anuradha Karuppiah Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 3fb3da8f44..8f6c68f055 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -227,6 +227,8 @@ void pim_ifchannel_delete_all(struct interface *ifp) while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) { ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, + ch, PIM_IFJOIN_NOINFO); pim_ifchannel_delete(ch); } } From 71056a69c34c590094bc656e94cc38484adaebdd Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Fri, 7 Jun 2019 10:17:39 -0700 Subject: [PATCH 2/2] pimd: remove pim and igmp OIFs when ifchannel_delete happens In a pim-evpn setup (say TORC11<=>TORC12) an mroute can have a mix of PIM and IGMP joins. The vxlan termination device ipmr-lo is IGMP joined on termination mroutes and the peerlink-rif can be pim joined on the same mroute if the MLAG peer (TORC11) loses all its uplinks to underlay - root@TORC12:~# net show pim state 239.1.1.101|grep pimreg 1 * 239.1.1.101 uplink-1 pimreg(I ), ipmr-lo( J ), peerlink-3.4094( J ) root@TORC12:~# When the uplinks come back up on TORC11 it will prune the peerlink-rif and join the RP (say spine) via the uplinks. TORC12 is rxing the prune and removing the if_channel (pim_ifchannel_delete). However it is not removing the OIF from mfcc_ttl basically leaving behind a leaked OIF in the forwarding entry. And this is because it is deriving the owner flag from the parent upstream entry and incorrectly concluding that all OIFs are IGMP joined. Thix fix flushes out both PIM and IGMP ownership when the ifchannel is deleted. There is a second fix in the commit and that is to set the proto mask correctly (to STAR) for inherited OIFs. (S,G) entries can inherit the OIF from the (*, G) entry and this decision can change when the pim/igmp ifchannel is removed. The earlier code was setting the proto-mask incorrectly to PIM or IGMP. Signed-off-by: Anuradha Karuppiah Signed-off-by: Donald Sharp (cherry picked from commit d4d1d968dbbe61347393f7dace8b675496ff1024) --- pimd/pim_ifchannel.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 8f6c68f055..15bdf6ee6e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -133,7 +133,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) if (ch->upstream->channel_oil) { uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) - mask = PIM_OIF_FLAG_PROTO_IGMP; + mask |= PIM_OIF_FLAG_PROTO_IGMP; /* * A S,G RPT channel can have an empty oil, we also @@ -142,13 +142,15 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) * being inherited. So let's figure out what * needs to be done here */ - if (pim_upstream_evaluate_join_desired_interface( - ch->upstream, ch, ch->parent)) + if ((ch->sg.src.s_addr != INADDR_ANY) && + pim_upstream_evaluate_join_desired_interface( + ch->upstream, ch, ch->parent)) pim_channel_add_oif(ch->upstream->channel_oil, - ch->interface, mask); - else - pim_channel_del_oif(ch->upstream->channel_oil, - ch->interface, mask); + ch->interface, + PIM_OIF_FLAG_PROTO_STAR); + + pim_channel_del_oif(ch->upstream->channel_oil, + ch->interface, mask); /* * Do we have any S,G's that are inheriting? * Nuke from on high too.