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);
/* 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;
@ -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);
}
@ -133,3 +131,21 @@ static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout)
&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

@ -40,10 +40,9 @@
#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
* ==============
*/
@ -188,4 +187,6 @@ struct bsmmsg_rpinfo {
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

View File

@ -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);

View File

@ -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,
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,
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,9 +623,21 @@ 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 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,
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, "<rp?>");
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, "<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 */
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);

View File

@ -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);