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 <saravanank@vmware.com>
This commit is contained in:
saravanank 2019-05-02 09:23:48 -07:00
parent 16c926c85d
commit d0e418b42c
5 changed files with 318 additions and 102 deletions

View File

@ -36,8 +36,7 @@ static int pim_on_bs_timer(struct thread *t);
static void pim_bs_timer_stop(struct bsm_scope *scope); static void pim_bs_timer_stop(struct bsm_scope *scope);
/* pim_bsm_write_config - Write the interface pim bsm configuration.*/ /* pim_bsm_write_config - Write the interface pim bsm configuration.*/
void void pim_bsm_write_config(struct vty *vty, struct interface *ifp)
pim_bsm_write_config(struct vty *vty, struct interface *ifp)
{ {
struct pim_interface *pim_ifp = ifp->info; 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) if (bsgrp_node->bsrp_list)
list_delete(&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) if (pim->global_scope.bsm_list)
list_delete(&pim->global_scope.bsm_list); list_delete(&pim->global_scope.bsm_list);
for(rn = route_top(pim->global_scope.bsrp_table); for (rn = route_top(pim->global_scope.bsrp_table); rn;
rn; rn = route_next(rn)) { rn = route_next(rn)) {
bsgrp = rn->info; bsgrp = rn->info;
if (!bsgrp) if (!bsgrp)
continue; continue;
@ -111,8 +110,7 @@ static void pim_bs_timer_stop(struct bsm_scope *scope)
{ {
if (PIM_DEBUG_BSM) if (PIM_DEBUG_BSM)
zlog_debug("%s : BS timer being stopped of sz: %d", zlog_debug("%s : BS timer being stopped of sz: %d",
__PRETTY_FUNCTION__, __PRETTY_FUNCTION__, scope->sz_id);
scope->sz_id);
THREAD_OFF(scope->bs_timer); 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 (!scope) {
if (PIM_DEBUG_BSM) if (PIM_DEBUG_BSM)
zlog_debug("%s : Invalid scope(NULL).", zlog_debug("%s : Invalid scope(NULL).",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);
} }
THREAD_OFF(scope->bs_timer); THREAD_OFF(scope->bs_timer);
if (PIM_DEBUG_BSM) if (PIM_DEBUG_BSM)
zlog_debug("%s : starting bs timer for scope %d with timeout %d secs", 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, 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;
}

View File

@ -31,25 +31,24 @@
#include "pim_msg.h" #include "pim_msg.h"
/* Defines */ /* Defines */
#define PIM_GBL_SZ_ID 0 /* global scope zone id set to 0 */ #define PIM_GBL_SZ_ID 0 /* global scope zone id set to 0 */
#define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */ #define PIM_BS_TIME 60 /* RFC 5059 - Sec 5 */
#define PIM_BSR_DEFAULT_TIMEOUT 130 /* RFC 5059 - Sec 5 */ #define PIM_BSR_DEFAULT_TIMEOUT 130 /* RFC 5059 - Sec 5 */
/* These structures are only encoded IPv4 specific */ /* These structures are only encoded IPv4 specific */
#define PIM_BSM_HDR_LEN sizeof(struct bsm_hdr) #define PIM_BSM_HDR_LEN sizeof(struct bsm_hdr)
#define PIM_BSM_GRP_LEN sizeof(struct bsmmsg_grpinfo) #define PIM_BSM_GRP_LEN sizeof(struct bsmmsg_grpinfo)
#define PIM_BSM_RP_LEN sizeof(struct bsmmsg_rpinfo) #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 /* Datastructures
* ============== * ==============
*/ */
/* Non candidate BSR states */ /* Non candidate BSR states */
enum ncbsr_state{ enum ncbsr_state {
NO_INFO = 0, NO_INFO = 0,
ACCEPT_ANY, ACCEPT_ANY,
ACCEPT_PREFERRED ACCEPT_PREFERRED
@ -57,19 +56,19 @@ enum ncbsr_state{
/* BSM scope - bsm processing is per scope */ /* BSM scope - bsm processing is per scope */
struct bsm_scope { struct bsm_scope {
int sz_id; /* scope zone id */ int sz_id; /* scope zone id */
enum ncbsr_state state; /* non candidate BSR state */ enum ncbsr_state state; /* non candidate BSR state */
bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */ bool accept_nofwd_bsm; /* no fwd bsm accepted for scope */
struct in_addr current_bsr; /* current elected BSR for the sz */ struct in_addr current_bsr; /* current elected BSR for the sz */
uint32_t current_bsr_prio; /* current BSR priority */ uint32_t current_bsr_prio; /* current BSR priority */
int64_t current_bsr_first_ts; /* current BSR elected time */ int64_t current_bsr_first_ts; /* current BSR elected time */
int64_t current_bsr_last_ts; /* Last BSM received from E-BSR */ int64_t current_bsr_last_ts; /* Last BSM received from E-BSR */
uint16_t bsm_frag_tag; /* Last received frag tag 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 */ uint8_t hashMasklen; /* Mask in hash calc RFC 7761 4.7.2 */
struct pim_instance *pim; /* Back pointer to pim instance */ 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 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; struct thread *sz_timer;
}; };
@ -85,12 +84,12 @@ struct bsm_info {
* this node maintains the list of rp for the group. * this node maintains the list of rp for the group.
*/ */
struct bsgrp_node { struct bsgrp_node {
struct prefix group; /* Group range */ struct prefix group; /* Group range */
struct bsm_scope *scope; /* Back ptr to scope */ struct bsm_scope *scope; /* Back ptr to scope */
struct list *bsrp_list; /* list of RPs adv by BSR */ struct list *bsrp_list; /* list of RPs adv by BSR */
struct list *partial_bsrp_list; /* maintained until all RPs received */ struct list *partial_bsrp_list; /* maintained until all RPs received */
int pend_rp_cnt; /* Total RP - Received RP */ int pend_rp_cnt; /* Total RP - Received RP */
uint16_t frag_tag; /* frag tag to identify the fragment */ uint16_t frag_tag; /* frag tag to identify the fragment */
}; };
/* This is the list node of bsrp_list and partial bsrp list in /* 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 hm_len;
uint8_t bsr_prio; uint8_t bsr_prio;
struct pim_encoded_ipv4_unicast bsr_addr; struct pim_encoded_ipv4_unicast bsr_addr;
}__attribute__((packed)); } __attribute__((packed));
struct bsmmsg_grpinfo { struct bsmmsg_grpinfo {
struct pim_encoded_group_ipv4 group; struct pim_encoded_group_ipv4 group;
uint8_t rp_count; uint8_t rp_count;
uint8_t frag_rp_count; uint8_t frag_rp_count;
uint16_t reserved; uint16_t reserved;
}__attribute__((packed)); } __attribute__((packed));
struct bsmmsg_rpinfo { struct bsmmsg_rpinfo {
struct pim_encoded_ipv4_unicast rpaddr; struct pim_encoded_ipv4_unicast rpaddr;
uint16_t rp_holdtime; uint16_t rp_holdtime;
uint8_t rp_pri; uint8_t rp_pri;
uint8_t reserved; uint8_t reserved;
}__attribute__((packed)); } __attribute__((packed));
/* API */ /* API */
void pim_bsm_proc_init(struct pim_instance *pim); void pim_bsm_proc_init(struct pim_instance *pim);
void pim_bsm_proc_free(struct pim_instance *pim); void pim_bsm_proc_free(struct pim_instance *pim);
void pim_bsm_write_config(struct vty *vty, struct interface *ifp); 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 #endif

View File

@ -5210,7 +5210,13 @@ static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
{ {
int result; 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) { if (result == PIM_GROUP_BAD_ADDRESS) {
vty_out(vty, "%% Bad group address specified: %s\n", group); 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 *rp, const char *group,
const char *plist) 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) { if (result == PIM_GROUP_BAD_ADDRESS) {
vty_out(vty, "%% Bad group address specified: %s\n", group); vty_out(vty, "%% Bad group address specified: %s\n", group);

View File

@ -48,6 +48,7 @@
#include "pim_mroute.h" #include "pim_mroute.h"
#include "pim_oil.h" #include "pim_oil.h"
#include "pim_zebra.h" #include "pim_zebra.h"
#include "pim_bsm.h"
/* Cleanup pim->rpf_hash each node data */ /* Cleanup pim->rpf_hash each node data */
void pim_rp_list_hash_clean(void *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); pim_zebra_update_all_interfaces(pim);
} }
int pim_rp_new(struct pim_instance *pim, const char *rp, int pim_rp_new_config(struct pim_instance *pim, const char *rp,
const char *group_range, const char *plist) const char *group_range, const char *plist)
{ {
int result = 0; 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_info;
struct rp_info *rp_all; struct rp_info *rp_all;
struct prefix group_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; struct rp_info *tmp_rp_info;
char buffer[BUFSIZ]; char buffer[BUFSIZ];
struct prefix nht_p; struct prefix nht_p;
struct prefix temp;
struct route_node *rn; struct route_node *rn;
struct pim_upstream *up; struct pim_upstream *up;
struct listnode *upnode; struct listnode *upnode;
rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); 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.family = AF_INET;
rp_info->rp.rpf_addr.prefixlen = IPV4_MAX_PREFIXLEN; 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_addr;
&rp_info->rp.rpf_addr.u.prefix4); prefix_copy(&rp_info->group, &group);
rp_info->rp_src = rp_src_flag;
if (result <= 0) { inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp, sizeof(rp));
XFREE(MTYPE_PIM_RP, rp_info);
return PIM_RP_BAD_ADDRESS;
}
if (plist) { 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 if (rp_info->rp.rpf_addr.u.prefix4.s_addr
== tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) { == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr) {
if (tmp_rp_info->plist) if (tmp_rp_info->plist)
pim_rp_del(pim, rp, NULL, pim_rp_del_config(pim, rp, NULL,
tmp_rp_info->plist); tmp_rp_info->plist);
else else
pim_rp_del( pim_rp_del_config(
pim, rp, pim, rp,
prefix2str(&tmp_rp_info->group, prefix2str(&tmp_rp_info->group,
buffer, BUFSIZ), 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 && rp_info->rp.rpf_addr.u.prefix4.s_addr
== tmp_rp_info->rp.rpf_addr.u.prefix4 == tmp_rp_info->rp.rpf_addr.u.prefix4
.s_addr) { .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) if (prefix_same(&rp_all->group, &rp_info->group)
&& pim_rpf_addr_is_inaddr_none(&rp_all->rp)) { && pim_rpf_addr_is_inaddr_none(&rp_all->rp)) {
rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; rp_all->rp.rpf_addr = rp_info->rp.rpf_addr;
rp_all->rp_src = rp_src_flag;
XFREE(MTYPE_PIM_RP, rp_info); XFREE(MTYPE_PIM_RP, rp_info);
/* Register addr with Zebra NHT */ /* 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.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN; grp.prefixlen = IPV4_MAX_BITLEN;
grp.u.prefix4 = up->sg.grp; grp.u.prefix4 = up->sg.grp;
trp_info = pim_rp_find_match_group(pim, trp_info = pim_rp_find_match_group(
&grp); pim, &grp);
if (trp_info == rp_all) if (trp_info == rp_all)
pim_upstream_update(pim, up); 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_check_interfaces(pim, rp_all);
pim_rp_refresh_group_to_rp_mapping(pim); pim_rp_refresh_group_to_rp_mapping(pim);
pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all, pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_all,
false, NULL); false, NULL);
@ -573,17 +588,20 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
&rp_all->rp.source_nexthop, &rp_all->rp.source_nexthop,
&nht_p, &rp_all->group, 1)) &nht_p, &rp_all->group, 1))
return PIM_RP_NO_PATH; return PIM_RP_NO_PATH;
return PIM_SUCCESS; return PIM_SUCCESS;
} }
/* /*
* Return if the group is already configured for this RP * Return if the group is already configured for this RP
*/ */
if (pim_rp_find_exact(pim, rp_info->rp.rpf_addr.u.prefix4, tmp_rp_info = pim_rp_find_exact(
&rp_info->group)) { 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); 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, if (prefix_same(&rp_info->group,
&tmp_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); 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 ", zlog_debug("%s: NHT Register RP addr %s grp %s with Zebra ",
__PRETTY_FUNCTION__, buf, buf1); __PRETTY_FUNCTION__, buf, buf1);
} }
pim_find_or_track_nexthop(pim, &nht_p, NULL, rp_info, false, NULL); 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, if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, &nht_p,
&rp_info->group, 1)) &rp_info->group, 1))
@ -664,21 +693,12 @@ int pim_rp_new(struct pim_instance *pim, const char *rp,
return PIM_SUCCESS; return PIM_SUCCESS;
} }
int pim_rp_del(struct pim_instance *pim, const char *rp, int pim_rp_del_config(struct pim_instance *pim, const char *rp,
const char *group_range, const char *plist) const char *group_range, const char *plist)
{ {
struct prefix group; struct prefix group;
struct in_addr rp_addr; struct in_addr rp_addr;
struct prefix g_all;
struct rp_info *rp_info;
struct rp_info *rp_all;
int result; 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) if (group_range == NULL)
result = str2prefix("224.0.0.0/4", &group); 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) if (result <= 0)
return PIM_RP_BAD_ADDRESS; 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, "<rp?>");
prefix2str(&group, grp_str, sizeof(grp_str));
if (plist) if (plist)
rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist); rp_info = pim_rp_find_prefix_list(pim, rp_addr, plist);
else else
@ -705,6 +751,42 @@ int pim_rp_del(struct pim_instance *pim, const char *rp,
was_plist = true; 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, "<bsrp?>");
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 */ /* Deregister addr with Zebra NHT */
nht_p.family = AF_INET; nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN; 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 /* Find the upstream (*, G) whose upstream address is
* same as the deleted RP * same as the deleted RP
*/ */
if ((up->upstream_addr.s_addr == rp_addr.s_addr) && if ((up->upstream_addr.s_addr
(up->sg.src.s_addr == INADDR_ANY)) { == rp_info->rp.rpf_addr.u.prefix4.s_addr)
&& (up->sg.src.s_addr == INADDR_ANY)) {
struct prefix grp; struct prefix grp;
grp.family = AF_INET; grp.family = AF_INET;
grp.prefixlen = IPV4_MAX_BITLEN; 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 /* Find the upstream (*, G) whose upstream address is same as
* the deleted RP * the deleted RP
*/ */
if ((up->upstream_addr.s_addr == rp_addr.s_addr) && if ((up->upstream_addr.s_addr
(up->sg.src.s_addr == INADDR_ANY)) { == rp_info->rp.rpf_addr.u.prefix4.s_addr)
&& (up->sg.src.s_addr == INADDR_ANY)) {
struct prefix grp; struct prefix grp;
grp.family = AF_INET; 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 */ /* RP not found for the group grp */
if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) { if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
pim_upstream_rpf_clear(pim, up); pim_upstream_rpf_clear(pim, up);
pim_rp_set_upstream_addr(pim, pim_rp_set_upstream_addr(
&up->upstream_addr, pim, &up->upstream_addr, up->sg.src,
up->sg.src, up->sg.grp); up->sg.grp);
} }
/* RP found for the group 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; 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) void pim_rp_setup(struct pim_instance *pim)
{ {
struct listnode *node; 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)) if (pim_rpf_addr_is_inaddr_none(&rp_info->rp))
continue; continue;
if (rp_info->rp_src == RP_SRC_BSR)
continue;
if (rp_info->plist) if (rp_info->plist)
vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces, vty_out(vty, "%sip pim rp %s prefix-list %s\n", spaces,
inet_ntop(AF_INET, 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", json_row, "group",
prefix2str(&rp_info->group, buf, prefix2str(&rp_info->group, buf,
48)); 48));
json_object_string_add(json_row, json_object_string_add(json_row, "source",
"source",
source); source);
json_object_array_add(json_rp_rows, json_row); json_object_array_add(json_rp_rows, json_row);

View File

@ -46,10 +46,18 @@ void pim_rp_free(struct pim_instance *pim);
void pim_rp_list_hash_clean(void *data); void pim_rp_list_hash_clean(void *data);
int pim_rp_new(struct pim_instance *pim, const char *rp, const char *group, int pim_rp_new_config(struct pim_instance *pim, const char *rp,
const char *plist); const char *group, const char *plist);
int pim_rp_del(struct pim_instance *pim, const char *rp, const char *group, int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
const char *plist); 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, void pim_rp_prefix_list_update(struct pim_instance *pim,
struct prefix_list *plist); struct prefix_list *plist);