]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: rp_new & rp_del split into 2 tier functions & implement rp_change
authorsaravanank <saravanank@vmware.com>
Thu, 2 May 2019 16:23:48 +0000 (09:23 -0700)
committersaravanank <saravanank@vmware.com>
Wed, 15 May 2019 04:35:45 +0000 (21:35 -0700)
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>
pimd/pim_bsm.c
pimd/pim_bsm.h
pimd/pim_cmd.c
pimd/pim_rp.c
pimd/pim_rp.h

index b1548af1364fda484b257bec245487e0e1ffc408..7af9d3e1c8f690e5456294a0376bda4344c4da61 100644 (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;
 
@@ -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;
+}
index 68e9ecdb757ef6b6b86628e95764358bc9832d1b..65df83d8e83cc1978295c7802ee4985dab22d7f8 100644 (file)
 #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
index 26796d14c01f454586ef3e4caab67fe45a33a4a5..6308189eafdeaa6e305e30ab97af53667f210303 100644 (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);
index 42e6805d23346fd187e93245bdb517330ffaf015..ca865d28c31e1ec5ef786011b3ece75ecbc206d5 100644 (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,
-              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, "<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);
index 7ec45d3a3f453dcaeb3f670c44991b7fa865b88c..6dc26c07a95ca63e362a7a28f6ef3c26a883af2f 100644 (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);