summaryrefslogtreecommitdiffstats
path: root/pimd
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-04-07 16:16:23 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-04-20 21:55:50 +0200
commitdf94f9a91dbff3e0b04928d564484dfc4bf55aed (patch)
tree1cee9cc829182d1dd28342c5a5ef25390e674eac /pimd
parentMerge pull request #379 from pguibert6WIND/frrouting_issue309_2 (diff)
downloadfrr-df94f9a91dbff3e0b04928d564484dfc4bf55aed.tar.xz
frr-df94f9a91dbff3e0b04928d564484dfc4bf55aed.zip
pimd: Add prefix list handling to spt-switchover
To the 'ip pim spt-switchover infinity-and-beyond' command add 'prefix-list <PLIST>'. To the command. Use this as the basis to deny (Not immediate switchover) or permit (Immediate switchover), based upon matching the group address and the prefix-list. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'pimd')
-rw-r--r--pimd/pim_cmd.c62
-rw-r--r--pimd/pim_ifchannel.c22
-rw-r--r--pimd/pim_memory.c1
-rw-r--r--pimd/pim_memory.h1
-rw-r--r--pimd/pim_upstream.c45
-rw-r--r--pimd/pim_upstream.h4
-rw-r--r--pimd/pim_vty.c10
-rw-r--r--pimd/pimd.c5
-rw-r--r--pimd/pimd.h5
9 files changed, 139 insertions, 16 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index de2b7cbba..f04fafdaf 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -3416,6 +3416,33 @@ pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const cha
return CMD_SUCCESS;
}
+static int
+pim_cmd_spt_switchover (enum pim_spt_switchover spt, const char *plist)
+{
+ pimg->spt.switchover = spt;
+
+ switch (pimg->spt.switchover)
+ {
+ case PIM_SPT_IMMEDIATE:
+ if (pimg->spt.plist)
+ XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+
+ pim_upstream_add_lhr_star_pimreg ();
+ break;
+ case PIM_SPT_INFINITY:
+ pim_upstream_remove_lhr_star_pimreg (plist);
+
+ if (pimg->spt.plist)
+ XFREE (MTYPE_PIM_SPT_PLIST_NAME, pimg->spt.plist);
+
+ if (plist)
+ pimg->spt.plist = XSTRDUP (MTYPE_PIM_SPT_PLIST_NAME, plist);
+ break;
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_spt_switchover_infinity,
ip_pim_spt_switchover_infinity_cmd,
"ip pim spt-switchover infinity-and-beyond",
@@ -3424,10 +3451,20 @@ DEFUN (ip_pim_spt_switchover_infinity,
"SPT-Switchover\n"
"Never switch to SPT Tree\n")
{
- pimg->spt_switchover = PIM_SPT_INFINITY;
+ return pim_cmd_spt_switchover (PIM_SPT_INFINITY, NULL);
+}
- pim_upstream_remove_lhr_star_pimreg();
- return CMD_SUCCESS;
+DEFUN (ip_pim_spt_switchover_infinity_plist,
+ ip_pim_spt_switchover_infinity_plist_cmd,
+ "ip pim spt-switchover infinity-and-beyond prefix-list WORD",
+ IP_STR
+ PIM_STR
+ "SPT-Switchover\n"
+ "Never switch to SPT Tree\n"
+ "Prefix-List to control which groups to switch\n"
+ "Prefix-List name\n")
+{
+ return pim_cmd_spt_switchover (PIM_SPT_INFINITY, argv[5]->arg);
}
DEFUN (no_ip_pim_spt_switchover_infinity,
@@ -3439,10 +3476,21 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
"SPT_Switchover\n"
"Never switch to SPT Tree\n")
{
- pimg->spt_switchover = PIM_SPT_IMMEDIATE;
+ return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
+}
- pim_upstream_add_lhr_star_pimreg();
- return CMD_SUCCESS;
+DEFUN (no_ip_pim_spt_switchover_infinity_plist,
+ no_ip_pim_spt_switchover_infinity_plist_cmd,
+ "no ip pim spt-switchover infinity-and-beyond prefix-list WORD",
+ NO_STR
+ IP_STR
+ PIM_STR
+ "SPT_Switchover\n"
+ "Never switch to SPT Tree\n"
+ "Prefix-List to control which groups to switch\n"
+ "Prefix-List name\n")
+{
+ return pim_cmd_spt_switchover (PIM_SPT_IMMEDIATE, NULL);
}
DEFUN (ip_pim_joinprune_time,
@@ -6217,7 +6265,9 @@ void pim_cmd_init()
install_element (CONFIG_NODE, &ip_pim_register_suppress_cmd);
install_element (CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
+ install_element (CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_cmd);
+ install_element (CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
install_element (CONFIG_NODE, &ip_pim_joinprune_time_cmd);
install_element (CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index ebd36f878..fc84a5c2f 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -27,6 +27,7 @@
#include "vrf.h"
#include "hash.h"
#include "jhash.h"
+#include "prefix.h"
#include "pimd.h"
#include "pim_str.h"
@@ -1006,8 +1007,25 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
}
}
- if (pimg->spt_switchover != PIM_SPT_INFINITY)
- pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+
+ if (pimg->spt.switchover == PIM_SPT_INFINITY)
+ {
+ if (pimg->spt.plist)
+ {
+ struct prefix_list *plist = prefix_list_lookup (AFI_IP, pimg->spt.plist);
+ struct prefix g;
+ g.family = AF_INET;
+ g.prefixlen = IPV4_MAX_PREFIXLEN;
+ g.u.prefix4 = up->sg.grp;
+
+ if (prefix_list_apply (plist, &g) == PREFIX_DENY)
+ {
+ pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ }
+ }
+ }
+ else
+ pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
}
return 1;
diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c
index 2acca6f49..ab92665b9 100644
--- a/pimd/pim_memory.c
+++ b/pimd/pim_memory.c
@@ -52,3 +52,4 @@ DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source")
DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state")
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")
+DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name")
diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h
index 02446de46..e366377c8 100644
--- a/pimd/pim_memory.h
+++ b/pimd/pim_memory.h
@@ -51,5 +51,6 @@ DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
DECLARE_MTYPE(PIM_PIM_INSTANCE)
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
DECLARE_MTYPE(PIM_SSM_INFO)
+DECLARE_MTYPE(PIM_SPT_PLIST_NAME);
#endif /* _QUAGGA_PIM_MEMORY_H */
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 5743dac65..167588dae 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -1695,10 +1695,41 @@ pim_upstream_add_lhr_star_pimreg (void)
}
void
-pim_upstream_remove_lhr_star_pimreg (void)
+pim_upstream_spt_prefix_list_update (struct prefix_list *pl)
+{
+ const char *pname = prefix_list_name (pl);
+
+ if (pimg->spt.plist && strcmp (pimg->spt.plist, pname) == 0)
+ {
+ pim_upstream_remove_lhr_star_pimreg (pname);
+ }
+}
+
+/*
+ * nlist -> The new prefix list
+ *
+ * Per Group Application of pimreg to the OIL
+ * If the prefix list tells us DENY then
+ * we need to Switchover to SPT immediate
+ * so add the pimreg.
+ * If the prefix list tells us to ACCEPT than
+ * we need to Never do the SPT so remove
+ * the interface
+ *
+ */
+void
+pim_upstream_remove_lhr_star_pimreg (const char *nlist)
{
struct pim_upstream *up;
struct listnode *node;
+ struct prefix_list *np;
+ struct prefix g;
+ enum prefix_list_type apply_new;
+
+ np = prefix_list_lookup (AFI_IP, nlist);
+
+ g.family = AF_INET;
+ g.prefixlen = IPV4_MAX_PREFIXLEN;
for (ALL_LIST_ELEMENTS_RO (pim_upstream_list, node, up))
{
@@ -1708,7 +1739,17 @@ pim_upstream_remove_lhr_star_pimreg (void)
if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP (up->flags))
continue;
- pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ if (!nlist)
+ {
+ pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ continue;
+ }
+ g.u.prefix4 = up->sg.grp;
+ apply_new = prefix_list_apply (np, &g);
+ if (apply_new == PREFIX_DENY)
+ pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
+ else
+ pim_channel_del_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
}
}
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index a1af4483a..ec40f3c24 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -200,5 +200,7 @@ int pim_upstream_compare (void *arg1, void *arg2);
void pim_upstream_register_reevaluate (void);
void pim_upstream_add_lhr_star_pimreg (void);
-void pim_upstream_remove_lhr_star_pimreg (void);
+void pim_upstream_remove_lhr_star_pimreg (const char *nlist);
+
+void pim_upstream_spt_prefix_list_update (struct prefix_list *pl);
#endif /* PIM_UPSTREAM_H */
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 3d52dc9c4..c8322b629 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -182,10 +182,14 @@ int pim_global_config_write(struct vty *vty)
ssm->plist_name, VTY_NEWLINE);
++writes;
}
- if (pimg->spt_switchover == PIM_SPT_INFINITY)
+ if (pimg->spt.switchover == PIM_SPT_INFINITY)
{
- vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
- VTY_NEWLINE);
+ if (pimg->spt.plist)
+ vty_out (vty, "ip pim spt-switchover infinity-and-beyond prefix-list %s%s",
+ pimg->spt.plist, VTY_NEWLINE);
+ else
+ vty_out (vty, "ip pim spt-switchover infinity-and-beyond%s",
+ VTY_NEWLINE);
++writes;
}
diff --git a/pimd/pimd.c b/pimd/pimd.c
index eaef4ff5c..a8a2a806e 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -194,6 +194,7 @@ pim_prefix_list_update (struct prefix_list *plist)
{
pim_rp_prefix_list_update (plist);
pim_ssm_prefix_list_update (plist);
+ pim_upstream_spt_prefix_list_update (plist);
}
static void
@@ -249,7 +250,9 @@ pim_instance_init (vrf_id_t vrf_id, afi_t afi)
pim->vrf_id = vrf_id;
pim->afi = afi;
- pim->spt_switchover = PIM_SPT_IMMEDIATE;
+ pim->spt.switchover = PIM_SPT_IMMEDIATE;
+ pim->spt.plist = NULL;
+
pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal);
if (PIM_DEBUG_ZEBRA)
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 6c3dcfafc..246be17d4 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -248,7 +248,10 @@ struct pim_instance
afi_t afi;
vrf_id_t vrf_id;
- enum pim_spt_switchover spt_switchover;
+ struct {
+ enum pim_spt_switchover switchover;
+ char *plist;
+ } spt;
struct hash *rpf_hash;
void *ssm_info; /* per-vrf SSM configuration */