summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarita Patra <saritap@vmware.com>2022-11-10 22:59:58 -0800
committerSarita Patra <saritap@vmware.com>2022-11-14 00:17:48 -0800
commit93d4f4f0dd6c3d9b42d5f7604a064a7303c0c282 (patch)
tree1282064bf402f169017d6ecfbd74d54df871476a
parent12211791a9e6bb7002c3c24af68c2defa02ff747 (diff)
pimd, pim6d: Update upstream rpf disable/enable pim on interface
Problem: When "no ip pim" is executed on source connected interface, its ifp->info is set to NULL. But KAT on this interface is still running, it wrongly dereferences NULL. This leads to crash. Root Cause: pim upstream IIF is still pointing towards the source connected interface which is not pim enabled and Mroute is still present in the kernel. Fix: When “no ip pim” command gets executed on source connected interface, then loop through all the pnc->nexthop, if any new nexthop found, then update the upstream IIF accordindly, if not found then update the upstream IIF as Unknown and uninstall the mroute from kernel. When “ip pim” command gets executed on source connected interface, then also loop through all the pnc->nexthop and update the upstream IIF, install the mroute in kernel. Issue: #10782 Issue: #11931 Signed-off-by: Sarita Patra <saritap@vmware.com>
-rw-r--r--pimd/pim_nb_config.c3
-rw-r--r--pimd/pim_nht.c34
-rw-r--r--pimd/pim_nht.h2
3 files changed, 38 insertions, 1 deletions
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 12f8ffedfe..c4ff912cde 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -24,6 +24,7 @@
#include "lib/northbound_cli.h"
#include "pim_igmpv3.h"
#include "pim_neighbor.h"
+#include "pim_nht.h"
#include "pim_pim.h"
#include "pim_mlag.h"
#include "pim_bfd.h"
@@ -146,6 +147,7 @@ static int pim_cmd_interface_add(struct interface *ifp)
pim_ifp->pim_enable = true;
pim_if_addr_add_all(ifp);
+ pim_upstream_nh_if_update(pim_ifp->pim, ifp);
pim_if_membership_refresh(ifp);
pim_if_create_pimreg(pim_ifp->pim);
@@ -171,6 +173,7 @@ static int pim_cmd_interface_delete(struct interface *ifp)
if (!pim_ifp->gm_enable) {
pim_if_addr_del_all(ifp);
+ pim_upstream_nh_if_update(pim_ifp->pim, ifp);
pim_if_delete(ifp);
}
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index f9a9aeb1b0..c3e72557b7 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -469,6 +469,40 @@ static int pim_update_upstream_nh(struct pim_instance *pim,
return 0;
}
+static int pim_upstream_nh_if_update_helper(struct hash_bucket *bucket,
+ void *arg)
+{
+ struct pim_nexthop_cache *pnc = bucket->data;
+ struct pnc_hash_walk_data *pwd = arg;
+ struct pim_instance *pim = pwd->pim;
+ struct interface *ifp = pwd->ifp;
+ struct nexthop *nh_node = NULL;
+ ifindex_t first_ifindex;
+
+ for (nh_node = pnc->nexthop; nh_node; nh_node = nh_node->next) {
+ first_ifindex = nh_node->ifindex;
+ if (ifp != if_lookup_by_index(first_ifindex, pim->vrf->vrf_id))
+ continue;
+
+ if (pnc->upstream_hash->count) {
+ pim_update_upstream_nh(pim, pnc);
+ break;
+ }
+ }
+
+ return HASHWALK_CONTINUE;
+}
+
+void pim_upstream_nh_if_update(struct pim_instance *pim, struct interface *ifp)
+{
+ struct pnc_hash_walk_data pwd;
+
+ pwd.pim = pim;
+ pwd.ifp = ifp;
+
+ hash_walk(pim->rpf_hash, pim_upstream_nh_if_update_helper, &pwd);
+}
+
uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp)
{
uint32_t hash_val;
diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h
index 316b7b46ee..f487a21ba4 100644
--- a/pimd/pim_nht.h
+++ b/pimd/pim_nht.h
@@ -82,5 +82,5 @@ void pim_nht_bsr_del(struct pim_instance *pim, pim_addr bsr_addr);
/* RPF(bsr_addr) == src_ip%src_ifp? */
bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr,
struct interface *src_ifp, pim_addr src_ip);
-
+void pim_upstream_nh_if_update(struct pim_instance *pim, struct interface *ifp);
#endif