]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: PIM not sending register packets after changing from non DR to DR
authorSai Gomathi N <nsaigomathi@vmware.com>
Fri, 17 Mar 2023 10:51:16 +0000 (03:51 -0700)
committerSai Gomathi N <nsaigomathi@vmware.com>
Fri, 17 Mar 2023 10:51:16 +0000 (03:51 -0700)
When the router is non dr for an interface, it installs mroute to drop
the packets from directly connected source. This was done to avoid packets
coming to cpu as nocache hit. Later when it gets change from non-DR to DR,
these entries are not cleared. So the packets are still dropped.
This causes register packets not getting generated.
So cleaning up the mroute entries and channel oil without
upstream reference which was created to drop.

Co-authored-by: Saravanan K <saravanank@vmware.com>
Signed-off-by: Sai Gomathi N <nsaigomathi@vmware.com>
pimd/pim_neighbor.c
pimd/pim_oil.c
pimd/pim_oil.h

index 0b7ea0ad9d1e7135b75b04276d4d794cd7b836fc..6adf7a9edaeebb1ef33f6d33a219c00c22ee3a50 100644 (file)
@@ -29,6 +29,7 @@
 #include "pim_jp_agg.h"
 #include "pim_bfd.h"
 #include "pim_register.h"
+#include "pim_oil.h"
 
 static void dr_election_by_addr(struct interface *ifp)
 {
@@ -123,9 +124,10 @@ int pim_if_dr_election(struct interface *ifp)
                pim_if_update_could_assert(ifp);
                pim_if_update_assert_tracking_desired(ifp);
 
-               if (PIM_I_am_DR(pim_ifp))
+               if (PIM_I_am_DR(pim_ifp)) {
                        pim_ifp->am_i_dr = true;
-               else {
+                       pim_clear_nocache_state(pim_ifp);
+               } else {
                        if (pim_ifp->am_i_dr == true) {
                                pim_reg_del_on_couldreg_fail(ifp);
                                pim_ifp->am_i_dr = false;
index 63ddb85d001bc0682311368bcfa1bac4bb5abf69..4d3c51b7f0610eaf46305883d302ff3193a42734 100644 (file)
@@ -149,6 +149,31 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
        return c_oil;
 }
 
+
+/*
+ * Clean up mroute and channel oil created for dropping pkts from directly
+ * connected source when the interface was non DR.
+ */
+void pim_clear_nocache_state(struct pim_interface *pim_ifp)
+{
+       struct channel_oil *c_oil;
+
+       frr_each_safe (rb_pim_oil, &pim_ifp->pim->channel_oil_head, c_oil) {
+
+               if ((!c_oil->up) ||
+                   !(PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(c_oil->up->flags)))
+                       continue;
+
+               if (*oil_parent(c_oil) != pim_ifp->mroute_vif_index)
+                       continue;
+
+               THREAD_OFF(c_oil->up->t_ka_timer);
+               PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(c_oil->up->flags);
+               PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(c_oil->up->flags);
+               pim_upstream_del(pim_ifp->pim, c_oil->up, __func__);
+       }
+}
+
 struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
                                        const char *name)
 {
index 45b337cc720fa075589f5644ece7283d88bdd51a..dc66eaace454c1fab9e80ca1b892b7d7f7e60194 100644 (file)
@@ -182,6 +182,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
                                         pim_sgaddr *sg);
 struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
                                        pim_sgaddr *sg, const char *name);
+void pim_clear_nocache_state(struct pim_interface *pim_ifp);
 struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
                                        const char *name);