From: saravanank Date: Thu, 2 May 2019 16:23:48 +0000 (-0700) Subject: pimd: rp_new & rp_del split into 2 tier functions & implement rp_change X-Git-Tag: base_7.2~306^2~19 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=d0e418b42c319f4fcb8efe259f6f052a6fb07cf1;p=matthieu%2Ffrr.git pimd: rp_new & rp_del split into 2 tier functions & implement rp_change pim_rp_new split into pim_rp_new_config and pim_rp_new. pim_rp_new_config is called by CLI. pim_rp_new will be called by pim_rp_new_config and bsm rp config. pim_rp_del is split into pim_rp_del_config and pim_rp_del pim_rp_del_config is called by CLI. pim_rp_del is called by pim_rp_del_config and bsm rp config Signed-off-by: Saravanan K --- diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index b1548af136..7af9d3e1c8 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -36,8 +36,7 @@ static int pim_on_bs_timer(struct thread *t); static void pim_bs_timer_stop(struct bsm_scope *scope); /* pim_bsm_write_config - Write the interface pim bsm configuration.*/ -void -pim_bsm_write_config(struct vty *vty, struct interface *ifp) +void pim_bsm_write_config(struct vty *vty, struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; @@ -49,7 +48,7 @@ pim_bsm_write_config(struct vty *vty, struct interface *ifp) } } -static void pim_free_bsgrp_data(struct bsgrp_node * bsgrp_node) +static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node) { if (bsgrp_node->bsrp_list) list_delete(&bsgrp_node->bsrp_list); @@ -90,8 +89,8 @@ void pim_bsm_proc_free(struct pim_instance *pim) if (pim->global_scope.bsm_list) list_delete(&pim->global_scope.bsm_list); - for(rn = route_top(pim->global_scope.bsrp_table); - rn; rn = route_next(rn)) { + for (rn = route_top(pim->global_scope.bsrp_table); rn; + rn = route_next(rn)) { bsgrp = rn->info; if (!bsgrp) continue; @@ -111,8 +110,7 @@ static void pim_bs_timer_stop(struct bsm_scope *scope) { if (PIM_DEBUG_BSM) zlog_debug("%s : BS timer being stopped of sz: %d", - __PRETTY_FUNCTION__, - scope->sz_id); + __PRETTY_FUNCTION__, scope->sz_id); THREAD_OFF(scope->bs_timer); } @@ -121,15 +119,33 @@ static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout) if (!scope) { if (PIM_DEBUG_BSM) zlog_debug("%s : Invalid scope(NULL).", - __PRETTY_FUNCTION__); + __PRETTY_FUNCTION__); } THREAD_OFF(scope->bs_timer); if (PIM_DEBUG_BSM) zlog_debug("%s : starting bs timer for scope %d with timeout %d secs", - __PRETTY_FUNCTION__, scope->sz_id, bs_timeout); + __PRETTY_FUNCTION__, scope->sz_id, bs_timeout); thread_add_timer(router->master, pim_on_bs_timer, scope, bs_timeout, - &scope->bs_timer); + &scope->bs_timer); } +struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, + struct prefix *grp) +{ + struct route_node *rn; + struct bsgrp_node *bsgrp; + + rn = route_node_lookup(scope->bsrp_table, grp); + if (!rn) { + if (PIM_DEBUG_BSM) + zlog_debug("%s: Route node doesn't exist for the group", + __PRETTY_FUNCTION__); + return NULL; + } + bsgrp = rn->info; + route_unlock_node(rn); + + return bsgrp; +} diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h index 68e9ecdb75..65df83d8e8 100644 --- a/pimd/pim_bsm.h +++ b/pimd/pim_bsm.h @@ -31,25 +31,24 @@ #include "pim_msg.h" /* Defines */ -#define PIM_GBL_SZ_ID 0 /* global scope zone id set to 0 */ -#define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */ +#define PIM_GBL_SZ_ID 0 /* global scope zone id set to 0 */ +#define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */ #define PIM_BSR_DEFAULT_TIMEOUT 130 /* RFC 5059 - Sec 5 */ /* These structures are only encoded IPv4 specific */ -#define PIM_BSM_HDR_LEN sizeof(struct bsm_hdr) -#define PIM_BSM_GRP_LEN sizeof(struct bsmmsg_grpinfo) -#define PIM_BSM_RP_LEN sizeof(struct bsmmsg_rpinfo) +#define PIM_BSM_HDR_LEN sizeof(struct bsm_hdr) +#define PIM_BSM_GRP_LEN sizeof(struct bsmmsg_grpinfo) +#define PIM_BSM_RP_LEN sizeof(struct bsmmsg_rpinfo) + +#define PIM_MIN_BSM_LEN \ + (PIM_HDR_LEN + PIM_BSM_HDR_LEN + PIM_BSM_GRP_LEN + PIM_BSM_RP_LEN) -#define PIM_MIN_BSM_LEN (PIM_HDR_LEN + \ - PIM_BSM_HDR_LEN + \ - PIM_BSM_GRP_LEN + \ - PIM_BSM_RP_LEN) /* Datastructures * ============== */ /* Non candidate BSR states */ -enum ncbsr_state{ +enum ncbsr_state { NO_INFO = 0, ACCEPT_ANY, ACCEPT_PREFERRED @@ -57,19 +56,19 @@ enum ncbsr_state{ /* BSM scope - bsm processing is per scope */ struct bsm_scope { - int sz_id; /* scope zone id */ - enum ncbsr_state state; /* non candidate BSR state */ - bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */ + int sz_id; /* scope zone id */ + enum ncbsr_state state; /* non candidate BSR state */ + bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */ struct in_addr current_bsr; /* current elected BSR for the sz */ uint32_t current_bsr_prio; /* current BSR priority */ int64_t current_bsr_first_ts; /* current BSR elected time */ int64_t current_bsr_last_ts; /* Last BSM received from E-BSR */ - uint16_t bsm_frag_tag; /* Last received frag tag from E-BSR */ - uint8_t hashMasklen; /* Mask in hash calc RFC 7761 4.7.2 */ + uint16_t bsm_frag_tag; /* Last received frag tag from E-BSR */ + uint8_t hashMasklen; /* Mask in hash calc RFC 7761 4.7.2 */ struct pim_instance *pim; /* Back pointer to pim instance */ - struct list *bsm_list; /* list of bsm frag for frowarding */ + struct list *bsm_list; /* list of bsm frag for frowarding */ struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */ - struct thread *bs_timer; /* Boot strap timer */ + struct thread *bs_timer; /* Boot strap timer */ struct thread *sz_timer; }; @@ -85,12 +84,12 @@ struct bsm_info { * this node maintains the list of rp for the group. */ struct bsgrp_node { - struct prefix group; /* Group range */ - struct bsm_scope *scope; /* Back ptr to scope */ - struct list *bsrp_list; /* list of RPs adv by BSR */ + struct prefix group; /* Group range */ + struct bsm_scope *scope; /* Back ptr to scope */ + struct list *bsrp_list; /* list of RPs adv by BSR */ struct list *partial_bsrp_list; /* maintained until all RPs received */ - int pend_rp_cnt; /* Total RP - Received RP */ - uint16_t frag_tag; /* frag tag to identify the fragment */ + int pend_rp_cnt; /* Total RP - Received RP */ + uint16_t frag_tag; /* frag tag to identify the fragment */ }; /* This is the list node of bsrp_list and partial bsrp list in @@ -168,24 +167,26 @@ struct bsm_hdr { uint8_t hm_len; uint8_t bsr_prio; struct pim_encoded_ipv4_unicast bsr_addr; -}__attribute__((packed)); +} __attribute__((packed)); struct bsmmsg_grpinfo { struct pim_encoded_group_ipv4 group; uint8_t rp_count; uint8_t frag_rp_count; uint16_t reserved; -}__attribute__((packed)); +} __attribute__((packed)); struct bsmmsg_rpinfo { struct pim_encoded_ipv4_unicast rpaddr; uint16_t rp_holdtime; uint8_t rp_pri; uint8_t reserved; -}__attribute__((packed)); +} __attribute__((packed)); /* API */ void pim_bsm_proc_init(struct pim_instance *pim); void pim_bsm_proc_free(struct pim_instance *pim); void pim_bsm_write_config(struct vty *vty, struct interface *ifp); +struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope, + struct prefix *grp); #endif diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 26796d14c0..6308189eaf 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5210,7 +5210,13 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, { int result; - result = pim_rp_new(pim, rp, group, plist); + result = pim_rp_new_config(pim, rp, group, plist); + + if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) { + vty_out(vty, "%% Inconsistent address and mask: %s\n", + group); + return CMD_WARNING_CONFIG_FAILED; + } if (result == PIM_GROUP_BAD_ADDRESS) { vty_out(vty, "%% Bad group address specified: %s\n", group); @@ -5536,7 +5542,7 @@ static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty, const char *rp, const char *group, const char *plist) { - int result = pim_rp_del(pim, rp, group, plist); + int result = pim_rp_del_config(pim, rp, group, plist); if (result == PIM_GROUP_BAD_ADDRESS) { vty_out(vty, "%% Bad group address specified: %s\n", group); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 42e6805d23..ca865d28c3 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -48,6 +48,7 @@ #include "pim_mroute.h" #include "pim_oil.h" #include "pim_zebra.h" +#include "pim_bsm.h" /* Cleanup pim->rpf_hash each node data */ void pim_rp_list_hash_clean(void *data) @@ -406,10 +407,45 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up) pim_zebra_update_all_interfaces(pim); } -int pim_rp_new(struct pim_instance *pim, const char *rp, - const char *group_range, const char *plist) +int pim_rp_new_config(struct pim_instance *pim, const char *rp, + const char *group_range, const char *plist) { int result = 0; + struct prefix group; + struct in_addr rp_addr; + + if (group_range == NULL) + result = str2prefix("224.0.0.0/4", &group); + else { + result = str2prefix(group_range, &group); + if (result) { + struct prefix temp; + + prefix_copy(&temp, &group); + apply_mask(&temp); + if (!prefix_same(&group, &temp)) + return PIM_GROUP_BAD_ADDR_MASK_COMBO; + } + } + + if (!result) + return PIM_GROUP_BAD_ADDRESS; + + result = inet_pton(AF_INET, rp, &rp_addr); + + if (result <= 0) + return PIM_RP_BAD_ADDRESS; + + result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC); + return result; +} + +int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, + struct prefix group, const char *plist, + enum rp_source rp_src_flag) +{ + int result = 0; + char rp[INET_ADDRSTRLEN]; struct rp_info *rp_info; struct rp_info *rp_all; struct prefix group_all; @@ -417,41 +453,19 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, struct rp_info *tmp_rp_info; char buffer[BUFSIZ]; struct prefix nht_p; - struct prefix temp; struct route_node *rn; struct pim_upstream *up; struct listnode *upnode; rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (group_range == NULL) - result = str2prefix("224.0.0.0/4", &rp_info->group); - else { - result = str2prefix(group_range, &rp_info->group); - if (result) { - prefix_copy(&temp, &rp_info->group); - apply_mask(&temp); - if (!prefix_same(&rp_info->group, &temp)) { - XFREE(MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDR_MASK_COMBO; - } - } - } - - if (!result) { - XFREE(MTYPE_PIM_RP, rp_info); - return PIM_GROUP_BAD_ADDRESS; - } - rp_info->rp.rpf_addr.family = AF_INET; rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; - result = inet_pton(rp_info->rp.rpf_addr.family, rp, - &rp_info->rp.rpf_addr.u.prefix4); + rp_info->rp.rpf_addr.u.prefix4 = rp_addr; + prefix_copy(&rp_info->group, &group); + rp_info->rp_src = rp_src_flag; - if (result <= 0) { - XFREE(MTYPE_PIM_RP, rp_info); - return PIM_RP_BAD_ADDRESS; - } + inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp, sizeof(rp)); if (plist) { /* @@ -479,10 +493,10 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) { if (tmp_rp_info->plist) - pim_rp_del(pim, rp, NULL, - tmp_rp_info->plist); + pim_rp_del_config(pim, rp, NULL, + tmp_rp_info->plist); else - pim_rp_del( + pim_rp_del_config( pim, rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), @@ -516,7 +530,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, && rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4 .s_addr) { - pim_rp_del(pim, rp, NULL, tmp_rp_info->plist); + pim_rp_del_config(pim, rp, NULL, + tmp_rp_info->plist); } } @@ -526,6 +541,7 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, if (prefix_same(&rp_all->group, &rp_info->group) && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) { rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; + rp_all->rp_src = rp_src_flag; XFREE(MTYPE_PIM_RP, rp_info); /* Register addr with Zebra NHT */ @@ -556,8 +572,8 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, grp.family = AF_INET; grp.prefixlen = IPV4_MAX_BITLEN; grp.u.prefix4 = up->sg.grp; - trp_info = pim_rp_find_match_group(pim, - &grp); + trp_info = pim_rp_find_match_group( + pim, &grp); if (trp_info == rp_all) pim_upstream_update(pim, up); } @@ -565,7 +581,6 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, pim_rp_check_interfaces(pim, rp_all); pim_rp_refresh_group_to_rp_mapping(pim); - pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all, false, NULL); @@ -573,17 +588,20 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, &rp_all->rp.source_nexthop, &nht_p, &rp_all->group, 1)) return PIM_RP_NO_PATH; - return PIM_SUCCESS; } /* * Return if the group is already configured for this RP */ - if (pim_rp_find_exact(pim, rp_info->rp.rpf_addr.u.prefix4, - &rp_info->group)) { + tmp_rp_info = pim_rp_find_exact( + pim, rp_info->rp.rpf_addr.u.prefix4, &rp_info->group); + if (tmp_rp_info) { + if ((tmp_rp_info->rp_src != rp_src_flag) + && (rp_src_flag == RP_SRC_STATIC)) + tmp_rp_info->rp_src = rp_src_flag; XFREE(MTYPE_PIM_RP, rp_info); - return PIM_SUCCESS; + return result; } /* @@ -605,8 +623,20 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, */ if (prefix_same(&rp_info->group, &tmp_rp_info->group)) { + if ((rp_src_flag == RP_SRC_STATIC) + && (tmp_rp_info->rp_src + == RP_SRC_STATIC)) { + XFREE(MTYPE_PIM_RP, rp_info); + return PIM_GROUP_OVERLAP; + } + + result = pim_rp_change( + pim, + rp_info->rp.rpf_addr.u.prefix4, + tmp_rp_info->group, + rp_src_flag); XFREE(MTYPE_PIM_RP, rp_info); - return PIM_GROUP_OVERLAP; + return result; } } } @@ -655,7 +685,6 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ", __PRETTY_FUNCTION__, buf, buf1); } - pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL); if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p, &rp_info->group, 1)) @@ -664,21 +693,12 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, return PIM_SUCCESS; } -int pim_rp_del(struct pim_instance *pim, const char *rp, - const char *group_range, const char *plist) +int pim_rp_del_config(struct pim_instance *pim, const char *rp, + const char *group_range, const char *plist) { struct prefix group; struct in_addr rp_addr; - struct prefix g_all; - struct rp_info *rp_info; - struct rp_info *rp_all; int result; - struct prefix nht_p; - struct route_node *rn; - bool was_plist = false; - struct rp_info *trp_info; - struct pim_upstream *up; - struct listnode *upnode; if (group_range == NULL) result = str2prefix("224.0.0.0/4", &group); @@ -692,6 +712,32 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, if (result <= 0) return PIM_RP_BAD_ADDRESS; + result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC); + return result; +} + +int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, + struct prefix group, const char *plist, + enum rp_source rp_src_flag) +{ + struct prefix g_all; + struct rp_info *rp_info; + struct rp_info *rp_all; + struct prefix nht_p; + struct route_node *rn; + bool was_plist = false; + struct rp_info *trp_info; + struct pim_upstream *up; + struct listnode *upnode; + struct bsgrp_node *bsgrp = NULL; + struct bsm_rpinfo *bsrp = NULL; + char grp_str[PREFIX2STR_BUFFER]; + char rp_str[INET_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str))) + sprintf(rp_str, ""); + prefix2str(&group, grp_str, sizeof(grp_str)); + if (plist) rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist); else @@ -705,6 +751,42 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, was_plist = true; } + if (PIM_DEBUG_TRACE) + zlog_debug("%s: Delete RP %s for the group %s", + __PRETTY_FUNCTION__, rp_str, grp_str); + + /* While static RP is getting deleted, we need to check if dynamic RP + * present for the same group in BSM RP table, then install the dynamic + * RP for the group node into the main rp table + */ + if (rp_src_flag == RP_SRC_STATIC) { + bsgrp = pim_bsm_get_bsgrp_node(&pim->global_scope, &group); + + if (bsgrp) { + bsrp = listnode_head(bsgrp->bsrp_list); + if (bsrp) { + if (PIM_DEBUG_TRACE) { + char bsrp_str[INET_ADDRSTRLEN]; + + if (!inet_ntop(AF_INET, bsrp, bsrp_str, + sizeof(bsrp_str))) + sprintf(bsrp_str, ""); + + zlog_debug("%s: BSM RP %s found for the group %s", + __PRETTY_FUNCTION__, + bsrp_str, grp_str); + } + return pim_rp_change(pim, bsrp->rp_address, + group, RP_SRC_BSR); + } + } else { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: BSM RP not found for the group %s", + __PRETTY_FUNCTION__, grp_str); + } + } + /* Deregister addr with Zebra NHT */ nht_p.family = AF_INET; nht_p.prefixlen = IPV4_MAX_BITLEN; @@ -727,8 +809,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, /* Find the upstream (*, G) whose upstream address is * same as the deleted RP */ - if ((up->upstream_addr.s_addr == rp_addr.s_addr) && - (up->sg.src.s_addr == INADDR_ANY)) { + if ((up->upstream_addr.s_addr + == rp_info->rp.rpf_addr.u.prefix4.s_addr) + && (up->sg.src.s_addr == INADDR_ANY)) { struct prefix grp; grp.family = AF_INET; grp.prefixlen = IPV4_MAX_BITLEN; @@ -778,8 +861,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, /* Find the upstream (*, G) whose upstream address is same as * the deleted RP */ - if ((up->upstream_addr.s_addr == rp_addr.s_addr) && - (up->sg.src.s_addr == INADDR_ANY)) { + if ((up->upstream_addr.s_addr + == rp_info->rp.rpf_addr.u.prefix4.s_addr) + && (up->sg.src.s_addr == INADDR_ANY)) { struct prefix grp; grp.family = AF_INET; @@ -791,9 +875,9 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, /* 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); + pim_rp_set_upstream_addr( + pim, &up->upstream_addr, up->sg.src, + up->sg.grp); } /* RP found for the group grp */ @@ -806,6 +890,105 @@ int pim_rp_del(struct pim_instance *pim, const char *rp, return PIM_SUCCESS; } +int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, + struct prefix group, enum rp_source rp_src_flag) +{ + struct prefix nht_p; + struct route_node *rn; + int result = 0; + struct rp_info *rp_info = NULL; + struct pim_upstream *up; + struct listnode *upnode; + + rn = route_node_lookup(pim->rp_table, &group); + if (!rn) { + result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag); + return result; + } + + rp_info = rn->info; + + if (!rp_info) { + route_unlock_node(rn); + result = pim_rp_new(pim, new_rp_addr, group, NULL, rp_src_flag); + return result; + } + + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == new_rp_addr.s_addr) { + if (rp_info->rp_src != rp_src_flag) { + rp_info->rp_src = rp_src_flag; + route_unlock_node(rn); + return PIM_SUCCESS; + } + } + + /* Deregister old RP addr with Zebra NHT */ + if (rp_info->rp.rpf_addr.u.prefix4.s_addr != INADDR_ANY) { + 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) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&nht_p, buf, sizeof(buf)); + zlog_debug("%s: Deregister RP addr %s with Zebra ", + __PRETTY_FUNCTION__, buf); + } + pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info, false); + } + + pim_rp_nexthop_del(rp_info); + listnode_delete(pim->rp_list, rp_info); + /* Update the new RP address*/ + rp_info->rp.rpf_addr.u.prefix4 = new_rp_addr; + rp_info->rp_src = rp_src_flag; + rp_info->i_am_rp = 0; + + listnode_add_sort(pim->rp_list, rp_info); + + for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + if (up->sg.src.s_addr == INADDR_ANY) { + 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); + + if (trp_info == rp_info) + pim_upstream_update(pim, up); + } + } + + /* Register new RP addr with Zebra NHT */ + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_NHT_RP) { + char buf[PREFIX2STR_BUFFER]; + char buf1[PREFIX2STR_BUFFER]; + + prefix2str(&nht_p, buf, sizeof(buf)); + prefix2str(&rp_info->group, buf1, sizeof(buf1)); + zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ", + __PRETTY_FUNCTION__, buf, buf1); + } + + pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL); + if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p, + &rp_info->group, 1)) { + route_unlock_node(rn); + return PIM_RP_NO_PATH; + } + + pim_rp_check_interfaces(pim, rp_info); + + route_unlock_node(rn); + + pim_rp_refresh_group_to_rp_mapping(pim); + + return result; +} + void pim_rp_setup(struct pim_instance *pim) { struct listnode *node; @@ -1032,6 +1215,9 @@ int pim_rp_config_write(struct pim_instance *pim, struct vty *vty, if (pim_rpf_addr_is_inaddr_none(&rp_info->rp)) continue; + if (rp_info->rp_src == RP_SRC_BSR) + continue; + if (rp_info->plist) vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces, inet_ntop(AF_INET, @@ -1127,8 +1313,7 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj) json_row, "group", prefix2str(&rp_info->group, buf, 48)); - json_object_string_add(json_row, - "source", + json_object_string_add(json_row, "source", source); json_object_array_add(json_rp_rows, json_row); diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index 7ec45d3a3f..6dc26c07a9 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -46,10 +46,18 @@ void pim_rp_free(struct pim_instance *pim); void pim_rp_list_hash_clean(void *data); -int pim_rp_new(struct pim_instance *pim, const char *rp, const char *group, - const char *plist); -int pim_rp_del(struct pim_instance *pim, const char *rp, const char *group, - const char *plist); +int pim_rp_new_config(struct pim_instance *pim, const char *rp, + const char *group, const char *plist); +int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, + struct prefix group, const char *plist, + enum rp_source rp_src_flag); +int pim_rp_del_config(struct pim_instance *pim, const char *rp, + const char *group, const char *plist); +int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, + struct prefix group, const char *plist, + enum rp_source rp_src_flag); +int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, + struct prefix group, enum rp_source rp_src_flag); void pim_rp_prefix_list_update(struct pim_instance *pim, struct prefix_list *plist);