From e7016ceb4c03297712afb48e23b90957ade813d4 Mon Sep 17 00:00:00 2001 From: vdhingra Date: Mon, 21 Dec 2020 02:24:11 -0800 Subject: [PATCH] pimd : Added the command to clear the pim bsr data. This command has been added in the context of PIM BSM functionality. This command will clear the data structs having bsr information. Co-authored-by: Sarita Patra Signed-off-by: vishaldhingra --- doc/user/pim.rst | 7 +++ pimd/pim_bsm.c | 6 +- pimd/pim_bsm.h | 3 + pimd/pim_cmd.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_rp.c | 2 +- pimd/pim_rp.h | 1 + 6 files changed, 162 insertions(+), 4 deletions(-) diff --git a/doc/user/pim.rst b/doc/user/pim.rst index bacf8637ae..05297a0609 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -726,6 +726,13 @@ Clear commands reset various variables. Rescan PIM OIL (output interface list). +.. index:: clear ip pim [vrf NAME] bsr-data +.. clicmd:: clear ip pim [vrf NAME] bsr-data + + This command will clear the BSM scope data struct. This command also + removes the next hop tracking for the bsr and resets the upstreams + for the dynamically learnt RPs. + PIM EVPN configuration ====================== To use PIM in the underlay for overlay BUM forwarding associate a multicast diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 1acfece895..e873af5759 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -63,7 +63,7 @@ void pim_bsm_write_config(struct vty *vty, struct interface *ifp) } } -static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) +void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) { if (bsgrp_node->bsrp_list) list_delete(&bsgrp_node->bsrp_list); @@ -72,7 +72,7 @@ static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node); } -static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) +void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp) { struct route_node *rn; @@ -222,7 +222,7 @@ static int pim_on_bs_timer(struct thread *t) return 0; } -static void pim_bs_timer_stop(struct bsm_scope *scope) +void pim_bs_timer_stop(struct bsm_scope *scope) { if (PIM_DEBUG_BSM) zlog_debug("%s : BS timer being stopped of sz: %d", __func__, diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h index 0758c94f19..2829c1e05a 100644 --- a/pimd/pim_bsm.h +++ b/pimd/pim_bsm.h @@ -195,4 +195,7 @@ int pim_bsm_process(struct interface *ifp, bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp); struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, struct prefix *grp); +void pim_bs_timer_stop(struct bsm_scope *scope); +void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node); +void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp); #endif diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 8e7b13cc17..ff85151839 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4001,6 +4001,152 @@ DEFUN (clear_ip_pim_oil, return CMD_SUCCESS; } +static void clear_pim_bsr_db(struct pim_instance *pim) +{ + struct route_node *rn; + struct route_node *rpnode; + struct bsgrp_node *bsgrp; + struct prefix nht_p; + struct prefix g_all; + struct rp_info *rp_all; + struct pim_upstream *up; + struct rp_info *rp_info; + bool is_bsr_tracking = true; + + /* Remove next hop tracking for the bsr */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = pim->global_scope.current_bsr; + if (PIM_DEBUG_BSM) { + zlog_debug("%s: Deregister BSR addr %pFX with Zebra NHT", + __func__, &nht_p); + } + pim_delete_tracked_nexthop(pim, &nht_p, NULL, NULL, is_bsr_tracking); + + /* Reset scope zone data */ + pim->global_scope.accept_nofwd_bsm = false; + pim->global_scope.state = ACCEPT_ANY; + pim->global_scope.current_bsr.s_addr = INADDR_ANY; + pim->global_scope.current_bsr_prio = 0; + pim->global_scope.current_bsr_first_ts = 0; + pim->global_scope.current_bsr_last_ts = 0; + pim->global_scope.bsm_frag_tag = 0; + list_delete_all_node(pim->global_scope.bsm_list); + + pim_bs_timer_stop(&pim->global_scope); + + for (rn = route_top(pim->global_scope.bsrp_table); rn; + rn = route_next(rn)) { + bsgrp = rn->info; + if (!bsgrp) + continue; + + rpnode = route_node_lookup(pim->rp_table, &bsgrp->group); + + if (!rpnode) { + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, + &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + continue; + } + + rp_info = (struct rp_info *)rpnode->info; + + if ((!rp_info) || (rp_info->rp_src != RP_SRC_BSR)) { + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, + &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + continue; + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + + if (PIM_DEBUG_PIM_NHT_RP) { + zlog_debug("%s: Deregister RP addr %pFX with Zebra ", + __func__, &nht_p); + } + + pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false); + + if (!str2prefix("224.0.0.0/4", &g_all)) + return; + + rp_all = pim_rp_find_match_group(pim, &g_all); + + if (rp_all == rp_info) { + rp_all->rp.rpf_addr.family = AF_INET; + rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE; + rp_all->i_am_rp = 0; + } else { + /* Delete the rp_info from rp-list */ + listnode_delete(pim->rp_list, rp_info); + + /* Delete the rp node from rp_table */ + rpnode->info = NULL; + route_unlock_node(rpnode); + route_unlock_node(rpnode); + } + + XFREE(MTYPE_PIM_RP, rp_info); + + pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group); + pim_free_bsgrp_data(bsgrp); + } + pim_rp_refresh_group_to_rp_mapping(pim); + + + frr_each (rb_pim_upstream, &pim->upstream_head, up) { + /* Find the upstream (*, G) whose upstream address is same as + * the RP + */ + if (up->sg.src.s_addr != INADDR_ANY) + continue; + + struct prefix grp; + struct rp_info *trp_info; + + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = up->sg.grp; + + trp_info = pim_rp_find_match_group(pim, &grp); + + /* RP not found for the group grp */ + if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) { + pim_upstream_rpf_clear(pim, up); + pim_rp_set_upstream_addr(pim, &up->upstream_addr, + up->sg.src, up->sg.grp); + } else { + /* RP found for the group grp */ + pim_upstream_update(pim, up); + } + } +} + + +DEFUN (clear_ip_pim_bsr_db, + clear_ip_pim_bsr_db_cmd, + "clear ip pim [vrf NAME] bsr-data", + CLEAR_STR + IP_STR + CLEAR_IP_PIM_STR + VRF_CMD_HELP_STR + "Reset pim bsr data\n") +{ + int idx = 2; + struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + + if (!vrf) + return CMD_WARNING; + + clear_pim_bsr_db(vrf->info); + + return CMD_SUCCESS; +} + DEFUN (show_ip_igmp_interface, show_ip_igmp_interface_cmd, "show ip igmp [vrf NAME] interface [detail|WORD] [json]", @@ -11396,6 +11542,7 @@ void pim_cmd_init(void) install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd); install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd); install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd); + install_element(ENABLE_NODE, &clear_ip_pim_bsr_db_cmd); install_element(ENABLE_NODE, &show_debugging_pim_cmd); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index fa5d6f37bf..301a27001f 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -271,7 +271,7 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, * * This is a placeholder function for now. */ -static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim) +void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim) { pim_msdp_i_am_rp_changed(pim); pim_upstream_reeval_use_rpt(pim); diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 8a12cb076c..dd7cd5d75e 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -86,4 +86,5 @@ int pim_rp_list_cmp(void *v1, void *v2); struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, const struct prefix *group); void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up); +void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim); #endif -- 2.39.5