mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 05:21:31 +00:00
PIM: prefix-list support for selecting RP
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com> Reviewed-by: CCR-5173 Ticket: CM-12819
This commit is contained in:
parent
a9b5987989
commit
dfe43e25d8
@ -25,6 +25,7 @@
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
#include "zclient.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_mroute.h"
|
||||
@ -2439,27 +2440,52 @@ DEFUN (show_ip_ssmpingd,
|
||||
}
|
||||
|
||||
static int
|
||||
pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
|
||||
pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist)
|
||||
{
|
||||
int result;
|
||||
result = pim_rp_new (rp, group);
|
||||
|
||||
if (result == -1)
|
||||
result = pim_rp_new (rp, group, plist);
|
||||
|
||||
if (result == PIM_MALLOC_FAIL)
|
||||
{
|
||||
vty_out (vty, "%% Bad RP/group address specified: %s", rp);
|
||||
vty_out (vty, "%% Out of memory%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == -2)
|
||||
if (result == PIM_GROUP_BAD_ADDRESS)
|
||||
{
|
||||
vty_out (vty, "%% No Path to RP address specified: %s", rp);
|
||||
return CMD_WARNING;
|
||||
vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == -3)
|
||||
if (result == PIM_RP_BAD_ADDRESS)
|
||||
{
|
||||
vty_out (vty, "%% Group range specified cannot overlap");
|
||||
return CMD_ERR_NO_MATCH;
|
||||
vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == PIM_RP_NO_PATH)
|
||||
{
|
||||
vty_out (vty, "%% No Path to RP address specified: %s%s", rp, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == PIM_GROUP_OVERLAP)
|
||||
{
|
||||
vty_out (vty, "%% Group range specified cannot overlap%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == PIM_GROUP_PFXLIST_OVERLAP)
|
||||
{
|
||||
vty_out (vty, "%% This group is already covered by a RP prefix-list%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == PIM_RP_PFXLIST_IN_USE)
|
||||
{
|
||||
vty_out (vty, "%% The same prefix-list cannot be applied to multiple RPs%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -2526,23 +2552,43 @@ DEFUN (ip_pim_rp,
|
||||
"ip address of RP\n")
|
||||
{
|
||||
int idx_ipv4 = 3;
|
||||
return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
|
||||
return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
|
||||
}
|
||||
|
||||
DEFUN (ip_pim_rp_prefix_list,
|
||||
ip_pim_rp_prefix_list_cmd,
|
||||
"ip pim rp A.B.C.D prefix-list WORD",
|
||||
IP_STR
|
||||
"pim multicast routing\n"
|
||||
"Rendevous Point\n"
|
||||
"ip address of RP\n"
|
||||
"group prefix-list filter\n"
|
||||
"Name of a prefix-list\n")
|
||||
{
|
||||
return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg);
|
||||
}
|
||||
|
||||
static int
|
||||
pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
|
||||
pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group,
|
||||
const char *plist)
|
||||
{
|
||||
int result = pim_rp_del (rp, group);
|
||||
int result = pim_rp_del (rp, group, plist);
|
||||
|
||||
if (result == -1)
|
||||
if (result == PIM_GROUP_BAD_ADDRESS)
|
||||
{
|
||||
vty_out (vty, "%% Unable to Decode specified RP");
|
||||
vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == -2)
|
||||
if (result == PIM_RP_BAD_ADDRESS)
|
||||
{
|
||||
vty_out (vty, "%% Unable to find specified RP");
|
||||
vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (result == PIM_RP_NOT_FOUND)
|
||||
{
|
||||
vty_out (vty, "%% Unable to find specified RP%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@ -2559,7 +2605,21 @@ DEFUN (no_ip_pim_rp,
|
||||
"ip address of RP\n")
|
||||
{
|
||||
int idx_ipv4 = 4;
|
||||
return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
|
||||
return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
|
||||
}
|
||||
|
||||
DEFUN (no_ip_pim_rp_prefix_list,
|
||||
no_ip_pim_rp_prefix_list_cmd,
|
||||
"no ip pim rp A.B.C.D prefix-list WORD",
|
||||
NO_STR
|
||||
IP_STR
|
||||
"pim multicast routing\n"
|
||||
"Rendevous Point\n"
|
||||
"ip address of RP\n"
|
||||
"group prefix-list filter\n"
|
||||
"Name of a prefix-list\n")
|
||||
{
|
||||
return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg);
|
||||
}
|
||||
|
||||
DEFUN (ip_multicast_routing,
|
||||
@ -4821,6 +4881,8 @@ void pim_cmd_init()
|
||||
install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
|
||||
install_element (CONFIG_NODE, &ip_pim_rp_cmd);
|
||||
install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
|
||||
install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
|
||||
install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
|
||||
install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
|
||||
install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
|
||||
install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "if.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_str.h"
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pim_macro.h"
|
||||
#include "pimd.h"
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "pim_signals.h"
|
||||
#include "pim_zebra.h"
|
||||
#include "pim_msdp.h"
|
||||
#include "pim_rp.h"
|
||||
|
||||
#ifdef PIM_ZCLIENT_DEBUG
|
||||
extern int zclient_debug;
|
||||
@ -208,6 +209,9 @@ int main(int argc, char** argv, char** envp) {
|
||||
vrf_init ();
|
||||
access_list_init();
|
||||
prefix_list_init ();
|
||||
prefix_list_add_hook (pim_rp_prefix_list_update);
|
||||
prefix_list_delete_hook (pim_rp_prefix_list_update);
|
||||
|
||||
pim_route_map_init ();
|
||||
pim_init();
|
||||
pim_msdp_init ();
|
||||
|
@ -40,3 +40,4 @@ DEFINE_MTYPE(PIMD, PIM_SSMPINGD, "PIM sspimgd socket")
|
||||
DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE, "PIM Static Route")
|
||||
DEFINE_MTYPE(PIMD, PIM_BR, "PIM Bridge Router info")
|
||||
DEFINE_MTYPE(PIMD, PIM_RP, "PIM RP info")
|
||||
DEFINE_MTYPE(PIMD, PIM_FILTER_NAME, "PIM Filter Name")
|
||||
|
@ -39,5 +39,6 @@ DECLARE_MTYPE(PIM_SSMPINGD)
|
||||
DECLARE_MTYPE(PIM_STATIC_ROUTE)
|
||||
DECLARE_MTYPE(PIM_BR)
|
||||
DECLARE_MTYPE(PIM_RP)
|
||||
DECLARE_MTYPE(PIM_FILTER_NAME)
|
||||
|
||||
#endif /* _QUAGGA_PIM_MEMORY_H */
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "privs.h"
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_rpf.h"
|
||||
|
@ -23,6 +23,9 @@
|
||||
|
||||
#include "if.h"
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_vty.h"
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "if.h"
|
||||
#include "thread.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_mroute.h"
|
||||
|
358
pimd/pim_rp.c
358
pimd/pim_rp.c
@ -28,6 +28,7 @@
|
||||
#include "memory.h"
|
||||
#include "vty.h"
|
||||
#include "vrf.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_vty.h"
|
||||
@ -44,6 +45,7 @@ struct rp_info
|
||||
struct prefix group;
|
||||
struct pim_rpf rp;
|
||||
int i_am_rp;
|
||||
char *plist;
|
||||
};
|
||||
|
||||
static struct list *qpim_rp_list = NULL;
|
||||
@ -70,6 +72,24 @@ pim_rp_list_cmp (void *v1, void *v2)
|
||||
if (rp1 && !rp2)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Sort by RP IP address
|
||||
*/
|
||||
if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr)
|
||||
return -1;
|
||||
|
||||
if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Sort by group IP address
|
||||
*/
|
||||
if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr)
|
||||
return -1;
|
||||
|
||||
if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr)
|
||||
return 1;
|
||||
|
||||
if (rp1 == tail)
|
||||
return 1;
|
||||
|
||||
@ -106,6 +126,50 @@ pim_rp_free (void)
|
||||
list_free (qpim_rp_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an RP's prefix-list, return the RP's rp_info for that prefix-list
|
||||
*/
|
||||
static struct rp_info *
|
||||
pim_rp_find_prefix_list (struct in_addr rp, const char *plist)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr &&
|
||||
rp_info->plist && strcmp(rp_info->plist, plist) == 0)
|
||||
{
|
||||
return rp_info;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if plist is used by any rp_info
|
||||
*/
|
||||
static int
|
||||
pim_rp_prefix_list_used (const char *plist)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (rp_info->plist && strcmp(rp_info->plist, plist) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an RP's address, return the RP's rp_info that is an exact match for 'group'
|
||||
*/
|
||||
static struct rp_info *
|
||||
pim_rp_find_exact (struct in_addr rp, struct prefix *group)
|
||||
{
|
||||
@ -122,37 +186,67 @@ pim_rp_find_exact (struct in_addr rp, struct prefix *group)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rp_info *
|
||||
pim_rp_find_match (struct in_addr rp, struct prefix *group)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr &&
|
||||
prefix_match (&rp_info->group, group))
|
||||
return rp_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a group, return the rp_info for that group
|
||||
*/
|
||||
static struct rp_info *
|
||||
pim_rp_find_match_group (struct prefix *group)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
struct prefix_list *plist;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (prefix_match (&rp_info->group, group))
|
||||
return rp_info;
|
||||
if (rp_info->plist)
|
||||
{
|
||||
plist = prefix_list_lookup (AFI_IP, rp_info->plist);
|
||||
|
||||
if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT)
|
||||
return rp_info;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prefix_match (&rp_info->group, group))
|
||||
return rp_info;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the user makes "ip pim rp" configuration changes or if they change the
|
||||
* prefix-list(s) used by these statements we must tickle the upstream state
|
||||
* for each group to make them re-lookup who their RP should be.
|
||||
*
|
||||
* This is a placeholder function for now.
|
||||
*/
|
||||
static void
|
||||
pim_rp_refresh_group_to_rp_mapping()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
pim_rp_prefix_list_update (struct prefix_list *plist)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
int refresh_needed = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0)
|
||||
{
|
||||
refresh_needed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (refresh_needed)
|
||||
pim_rp_refresh_group_to_rp_mapping();
|
||||
}
|
||||
|
||||
static void
|
||||
pim_rp_check_interfaces (struct rp_info *rp_info)
|
||||
{
|
||||
@ -172,19 +266,19 @@ pim_rp_check_interfaces (struct rp_info *rp_info)
|
||||
}
|
||||
|
||||
int
|
||||
pim_rp_new (const char *rp, const char *group_range)
|
||||
pim_rp_new (const char *rp, const char *group_range, const char *plist)
|
||||
{
|
||||
int result;
|
||||
struct rp_info *rp_info;
|
||||
struct rp_info *rp_all;
|
||||
struct prefix group_all;
|
||||
|
||||
str2prefix ("224.0.0.0/4", &group_all);
|
||||
rp_all = pim_rp_find_match_group(&group_all);
|
||||
struct listnode *node, *nnode;
|
||||
struct rp_info *tmp_rp_info;
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info));
|
||||
if (!rp)
|
||||
return -1;
|
||||
if (!rp_info)
|
||||
return PIM_MALLOC_FAIL;
|
||||
|
||||
if (group_range == NULL)
|
||||
result = str2prefix ("224.0.0.0/4", &rp_info->group);
|
||||
@ -192,54 +286,147 @@ pim_rp_new (const char *rp, const char *group_range)
|
||||
result = str2prefix (group_range, &rp_info->group);
|
||||
|
||||
if (!result)
|
||||
return -1;
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_GROUP_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
rp_info->rp.rpf_addr.family = AF_INET;
|
||||
result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4);
|
||||
|
||||
if (result <= 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
|
||||
*/
|
||||
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;
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
if (!pim_rp_setup ())
|
||||
return -2;
|
||||
pim_rp_check_interfaces (rp_all);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return 0;
|
||||
return PIM_RP_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
if (pim_rp_find_match (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
|
||||
if (plist)
|
||||
{
|
||||
if (prefix_same (&group_all, &rp_info->group))
|
||||
/*
|
||||
* Return if the prefix-list is already configured for this RP
|
||||
*/
|
||||
if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist))
|
||||
{
|
||||
return 0;
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return -3;
|
||||
/*
|
||||
* Barf if the prefix-list is already configured for an RP
|
||||
*/
|
||||
if (pim_rp_prefix_list_used (plist))
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_RP_PFXLIST_IN_USE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any existing rp_info entries for this RP
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info))
|
||||
{
|
||||
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 (rp, NULL, tmp_rp_info->plist);
|
||||
else
|
||||
pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist);
|
||||
}
|
||||
else
|
||||
{
|
||||
str2prefix ("224.0.0.0/4", &group_all);
|
||||
rp_all = pim_rp_find_match_group(&group_all);
|
||||
|
||||
/*
|
||||
* Barf if group is a non-multicast subnet
|
||||
*/
|
||||
if (! prefix_match (&rp_all->group, &rp_info->group))
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_GROUP_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any prefix-list rp_info entries for this RP
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info))
|
||||
{
|
||||
if (tmp_rp_info->plist &&
|
||||
rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr)
|
||||
{
|
||||
pim_rp_del (rp, NULL, tmp_rp_info->plist);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
|
||||
*/
|
||||
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;
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
|
||||
if (!pim_rp_setup ())
|
||||
return PIM_RP_NO_PATH;
|
||||
|
||||
pim_rp_check_interfaces (rp_all);
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return if the group is already configured for this RP
|
||||
*/
|
||||
if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Barf if this group is already covered by some other RP
|
||||
*/
|
||||
tmp_rp_info = pim_rp_find_match_group (&rp_info->group);
|
||||
|
||||
if (tmp_rp_info)
|
||||
{
|
||||
if (tmp_rp_info->plist)
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_GROUP_PFXLIST_OVERLAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If the only RP that covers this group is an RP configured for
|
||||
* 224.0.0.0/4 that is fine, ignore that one. For all others
|
||||
* though we must return PIM_GROUP_OVERLAP
|
||||
*/
|
||||
if (! prefix_same (&group_all, &tmp_rp_info->group))
|
||||
{
|
||||
XFREE (MTYPE_PIM_RP, rp_info);
|
||||
return PIM_GROUP_OVERLAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listnode_add_sort (qpim_rp_list, rp_info);
|
||||
|
||||
if (!pim_rp_setup ())
|
||||
return -2;
|
||||
return PIM_RP_NO_PATH;
|
||||
|
||||
pim_rp_check_interfaces (rp_info);
|
||||
return 0;
|
||||
pim_rp_refresh_group_to_rp_mapping();
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
pim_rp_del (const char *rp, const char *group_range)
|
||||
pim_rp_del (const char *rp, const char *group_range, const char *plist)
|
||||
{
|
||||
struct prefix group;
|
||||
struct in_addr rp_addr;
|
||||
@ -248,35 +435,46 @@ pim_rp_del (const char *rp, const char *group_range)
|
||||
struct rp_info *rp_all;
|
||||
int result;
|
||||
|
||||
str2prefix ("224.0.0.0/4", &g_all);
|
||||
if (group_range == NULL)
|
||||
result = str2prefix ("224.0.0.0/4", &group);
|
||||
else
|
||||
result = str2prefix (group_range, &group);
|
||||
|
||||
if (!result)
|
||||
return -1;
|
||||
|
||||
rp_all = pim_rp_find_match_group (&g_all);
|
||||
return PIM_GROUP_BAD_ADDRESS;
|
||||
|
||||
result = inet_pton (AF_INET, rp, &rp_addr);
|
||||
if (result <= 0)
|
||||
return -1;
|
||||
return PIM_RP_BAD_ADDRESS;
|
||||
|
||||
if (plist)
|
||||
rp_info = pim_rp_find_prefix_list (rp_addr, plist);
|
||||
else
|
||||
rp_info = pim_rp_find_exact (rp_addr, &group);
|
||||
|
||||
rp_info = pim_rp_find_exact (rp_addr, &group);
|
||||
if (!rp_info)
|
||||
return -2;
|
||||
return PIM_RP_NOT_FOUND;
|
||||
|
||||
if (rp_info->plist)
|
||||
{
|
||||
XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
|
||||
rp_info->plist = NULL;
|
||||
}
|
||||
|
||||
str2prefix ("224.0.0.0/4", &g_all);
|
||||
rp_all = pim_rp_find_match_group (&g_all);
|
||||
|
||||
if (rp_all == rp_info)
|
||||
{
|
||||
rp_all->rp.rpf_addr.family = AF_INET;
|
||||
rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
|
||||
rp_all->i_am_rp = 0;
|
||||
return 0;
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
listnode_delete (qpim_rp_list, rp_info);
|
||||
return 0;
|
||||
pim_rp_refresh_group_to_rp_mapping();
|
||||
return PIM_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
@ -430,7 +628,8 @@ pim_rp_config_write (struct vty *vty)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rp_info *rp_info;
|
||||
char buffer[32];
|
||||
char rp_buffer[32];
|
||||
char group_buffer[32];
|
||||
int count = 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
@ -438,13 +637,15 @@ pim_rp_config_write (struct vty *vty)
|
||||
if (pim_rpf_addr_is_inaddr_none (&rp_info->rp))
|
||||
continue;
|
||||
|
||||
if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp))
|
||||
{
|
||||
char buf[32];
|
||||
vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, buffer, 32),
|
||||
prefix2str(&rp_info->group, buf, 32), VTY_NEWLINE);
|
||||
count++;
|
||||
}
|
||||
if (rp_info->plist)
|
||||
vty_out(vty, "ip pim rp %s prefix-list %s%s",
|
||||
inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32),
|
||||
rp_info->plist, VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, "ip pim rp %s %s%s",
|
||||
inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32),
|
||||
prefix2str(&rp_info->group, group_buffer, 32), VTY_NEWLINE);
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -486,18 +687,25 @@ pim_rp_show_information (struct vty *vty)
|
||||
struct rp_info *rp_info;
|
||||
struct listnode *node;
|
||||
|
||||
vty_out (vty, "RP Addr Group Oif I_am_RP%s", VTY_NEWLINE);
|
||||
vty_out (vty, "RP address group/prefix-list OIF I am RP%s", VTY_NEWLINE);
|
||||
for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
|
||||
{
|
||||
if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp))
|
||||
{
|
||||
char buf[48];
|
||||
vty_out (vty, "%-10s %-10s %-10s%-10d%s",
|
||||
inet_ntoa (rp_info->rp.rpf_addr.u.prefix4),
|
||||
prefix2str(&rp_info->group, buf, 48),
|
||||
rp_info->rp.source_nexthop.interface->name,
|
||||
rp_info->i_am_rp, VTY_NEWLINE);
|
||||
vty_out (vty, "%-15s ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4));
|
||||
|
||||
if (rp_info->plist)
|
||||
vty_out (vty, "%-18s ", rp_info->plist);
|
||||
else
|
||||
vty_out (vty, "%-18s ", prefix2str(&rp_info->group, buf, 48));
|
||||
|
||||
vty_out (vty, "%-10s ", rp_info->rp.source_nexthop.interface->name);
|
||||
|
||||
if (rp_info->i_am_rp)
|
||||
vty_out (vty, "yes%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out (vty, "no%s", VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -24,8 +24,9 @@
|
||||
void pim_rp_init (void);
|
||||
void pim_rp_free (void);
|
||||
|
||||
int pim_rp_new (const char *rp, const char *group);
|
||||
int pim_rp_del (const char *rp, const char *group);
|
||||
int pim_rp_new (const char *rp, const char *group, const char *plist);
|
||||
int pim_rp_del (const char *rp, const char *group, const char *plist);
|
||||
void pim_rp_prefix_list_update (struct prefix_list *plist);
|
||||
|
||||
int pim_rp_config_write (struct vty *vty);
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "memory.h"
|
||||
#include "thread.h"
|
||||
#include "linklist.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_pim.h"
|
||||
|
@ -23,7 +23,10 @@
|
||||
|
||||
#include "if.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "vrf.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_vty.h"
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "zclient.h"
|
||||
#include "stream.h"
|
||||
#include "network.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_pim.h"
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
#include "vty.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_cmd.h"
|
||||
|
12
pimd/pimd.h
12
pimd/pimd.h
@ -71,6 +71,18 @@
|
||||
#define PIM_MASK_STATIC (1 << 17)
|
||||
#define PIM_MASK_PIM_REG (1 << 18)
|
||||
|
||||
|
||||
/* PIM error codes */
|
||||
#define PIM_SUCCESS 0
|
||||
#define PIM_MALLOC_FAIL -1
|
||||
#define PIM_GROUP_BAD_ADDRESS -2
|
||||
#define PIM_GROUP_OVERLAP -3
|
||||
#define PIM_GROUP_PFXLIST_OVERLAP -4
|
||||
#define PIM_RP_BAD_ADDRESS -5
|
||||
#define PIM_RP_NO_PATH -6
|
||||
#define PIM_RP_NOT_FOUND -7
|
||||
#define PIM_RP_PFXLIST_IN_USE -8
|
||||
|
||||
const char *const PIM_ALL_SYSTEMS;
|
||||
const char *const PIM_ALL_ROUTERS;
|
||||
const char *const PIM_ALL_PIM_ROUTERS;
|
||||
|
Loading…
Reference in New Issue
Block a user