summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2020-03-17 14:57:10 -0400
committerGitHub <noreply@github.com>2020-03-17 14:57:10 -0400
commit09c04bc49098f513ceaba6323f5c2921212b8e03 (patch)
treea15761c227cde1ba00f6021e2b16edd2ba2cde4d
parent7bffea9dff1cf23b92ff2343a1e241d718d1d5cf (diff)
parentc64d8d857780e59fd4fad6c6ffd1c712d097bca8 (diff)
Merge pull request #5849 from donaldsharp/pim_register_prefix_list
Pim register prefix list
-rw-r--r--doc/user/pim.rst8
-rw-r--r--pimd/pim_cmd.c28
-rw-r--r--pimd/pim_instance.c2
-rw-r--r--pimd/pim_instance.h3
-rw-r--r--pimd/pim_memory.c2
-rw-r--r--pimd/pim_memory.h2
-rw-r--r--pimd/pim_register.c56
-rw-r--r--pimd/pim_vty.c5
-rw-r--r--tests/topotests/pim-basic/r1/pimd.conf4
-rw-r--r--tests/topotests/pim-basic/r1/zebra.conf3
-rw-r--r--tests/topotests/pim-basic/r3/pimd.conf1
-rw-r--r--tests/topotests/pim-basic/r3/zebra.conf8
-rw-r--r--tests/topotests/pim-basic/rp/pimd.conf3
-rw-r--r--tests/topotests/pim-basic/test_pim.py13
14 files changed, 115 insertions, 23 deletions
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 36c8b44aa4..f480c6bdc4 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -66,6 +66,14 @@ Certain signals have special meanings to *pimd*.
prefix of group ranges covered. This command is vrf aware, to configure for
a vrf, enter the vrf submode.
+.. index:: ip pim register-accept-list PLIST
+.. clicmd:: ip pim register-accept-list PLIST
+
+ When pim receives a register packet the source of the packet will be compared
+ to the prefix-list specified, PLIST, and if a permit is received normal
+ processing continues. If a deny is returned for the source address of the
+ register packet a register stop message is sent to the source.
+
.. index:: ip pim spt-switchover infinity-and-beyond
.. clicmd:: ip pim spt-switchover infinity-and-beyond
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index fc8778fd8d..af25d930d1 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -6628,18 +6628,18 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
switch (pim->spt.switchover) {
case PIM_SPT_IMMEDIATE:
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
pim_upstream_add_lhr_star_pimreg(pim);
break;
case PIM_SPT_INFINITY:
pim_upstream_remove_lhr_star_pimreg(pim, plist);
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
if (plist)
pim->spt.plist =
- XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
+ XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
break;
}
@@ -6700,6 +6700,26 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
}
+DEFPY (pim_register_accept_list,
+ pim_register_accept_list_cmd,
+ "[no] ip pim register-accept-list WORD$word",
+ NO_STR
+ IP_STR
+ PIM_STR
+ "Only accept registers from a specific source prefix list\n"
+ "Prefix-List name\n")
+{
+ PIM_DECLVAR_CONTEXT(vrf, pim);
+
+ if (no)
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+ else {
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+ pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, word);
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ip_pim_joinprune_time,
ip_pim_joinprune_time_cmd,
"ip pim join-prune-interval (60-600)",
@@ -10798,6 +10818,8 @@ void pim_cmd_init(void)
install_element(CONFIG_NODE,
&no_ip_pim_spt_switchover_infinity_plist_cmd);
install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd);
+ install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
+ install_element(VRF_NODE, &pim_register_accept_list_cmd);
install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index 347b0fc284..2cda628a90 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -69,6 +69,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
pim_msdp_exit(pim);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
}
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index 7b1fd2e172..48dc2d9530 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -135,6 +135,9 @@ struct pim_instance {
char *plist;
} spt;
+ /* The name of the register-accept prefix-list */
+ char *register_plist;
+
struct hash *rpf_hash;
void *ssm_info; /* per-vrf SSM configuration */
diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c
index 2bbab67e45..6bc8062c4b 100644
--- a/pimd/pim_memory.c
+++ b/pimd/pim_memory.c
@@ -51,5 +51,5 @@ 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")
+DEFINE_MTYPE(PIMD, PIM_PLIST_NAME, "PIM Prefix List Names")
DEFINE_MTYPE(PIMD, PIM_VXLAN_SG, "PIM VxLAN mroute cache")
diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h
index e5ca57a15d..6beeb60075 100644
--- a/pimd/pim_memory.h
+++ b/pimd/pim_memory.h
@@ -50,7 +50,7 @@ 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);
+DECLARE_MTYPE(PIM_PLIST_NAME);
DECLARE_MTYPE(PIM_VXLAN_SG)
#endif /* _QUAGGA_PIM_MEMORY_H */
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 19baecb9c2..7b0af89993 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -324,14 +324,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
struct prefix_sg sg;
uint32_t *bits;
int i_am_rp = 0;
- struct pim_interface *pim_ifp = NULL;
-
- pim_ifp = ifp->info;
+ struct pim_interface *pim_ifp = ifp->info;
+ struct pim_instance *pim = pim_ifp->pim;
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
- if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) {
+ if (!pim_rp_check_is_my_ip_address(pim, dest_addr)) {
if (PIM_DEBUG_PIM_REG) {
char dest[INET_ADDRSTRLEN];
@@ -375,7 +374,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
sg.src = ip_hdr->ip_src;
sg.grp = ip_hdr->ip_dst;
- i_am_rp = I_am_RP(pim_ifp->pim, sg.grp);
+ i_am_rp = I_am_RP(pim, sg.grp);
if (PIM_DEBUG_PIM_REG) {
char src_str[INET_ADDRSTRLEN];
@@ -387,9 +386,36 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
if (i_am_rp
&& (dest_addr.s_addr
- == ((RP(pim_ifp->pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
+ == ((RP(pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
sentRegisterStop = 0;
+ if (pim->register_plist) {
+ struct prefix_list *plist;
+ struct prefix src;
+
+ plist = prefix_list_lookup(AFI_IP, pim->register_plist);
+
+ src.family = AF_INET;
+ src.prefixlen = IPV4_MAX_PREFIXLEN;
+ src.u.prefix4 = sg.src;
+
+ if (prefix_list_apply(plist, &src) == PREFIX_DENY) {
+ pim_register_stop_send(ifp, &sg, dest_addr,
+ src_addr);
+ if (PIM_DEBUG_PIM_PACKETS) {
+ char src_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<src?>", src_addr,
+ src_str,
+ sizeof(src_str));
+ zlog_debug("%s: Sending register-stop to %s for %pSG4 due to prefix-list denial, dropping packet",
+ __func__, src_str, &sg);
+ }
+
+ return 0;
+ }
+ }
+
if (*bits & PIM_REGISTER_BORDER_BIT) {
struct in_addr pimbr = pim_br_get_pmbr(&sg);
if (PIM_DEBUG_PIM_PACKETS)
@@ -411,14 +437,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
}
}
- struct pim_upstream *upstream =
- pim_upstream_find(pim_ifp->pim, &sg);
+ struct pim_upstream *upstream = pim_upstream_find(pim, &sg);
/*
* If we don't have a place to send ignore the packet
*/
if (!upstream) {
upstream = pim_upstream_add(
- pim_ifp->pim, &sg, ifp,
+ pim, &sg, ifp,
PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
NULL);
if (!upstream) {
@@ -452,9 +477,8 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || ((SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))
- && pim_upstream_inherited_olist(pim_ifp->pim, upstream)
- == 0)) {
+ || ((SwitchToSptDesiredOnRp(pim, &sg))
+ && pim_upstream_inherited_olist(pim, upstream) == 0)) {
pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
sentRegisterStop = 1;
} else {
@@ -463,15 +487,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
upstream->sptbit);
}
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
- || (SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))) {
+ || (SwitchToSptDesiredOnRp(pim, &sg))) {
if (sentRegisterStop) {
pim_upstream_keep_alive_timer_start(
- upstream,
- pim_ifp->pim->rp_keep_alive_time);
+ upstream, pim->rp_keep_alive_time);
} else {
pim_upstream_keep_alive_timer_start(
- upstream,
- pim_ifp->pim->keep_alive_time);
+ upstream, pim->keep_alive_time);
}
}
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 8a87dfbb55..72540903be 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -216,6 +216,11 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
ssm->plist_name);
++writes;
}
+ if (pim->register_plist) {
+ vty_out(vty, "%sip pim register-accept-list %s\n", spaces,
+ pim->register_plist);
+ ++writes;
+ }
if (pim->spt.switchover == PIM_SPT_INFINITY) {
if (pim->spt.plist)
vty_out(vty,
diff --git a/tests/topotests/pim-basic/r1/pimd.conf b/tests/topotests/pim-basic/r1/pimd.conf
index cec765699d..f64a46deb3 100644
--- a/tests/topotests/pim-basic/r1/pimd.conf
+++ b/tests/topotests/pim-basic/r1/pimd.conf
@@ -7,6 +7,10 @@ interface r1-eth0
interface r1-eth1
ip pim
!
+interface r1-eth2
+ ip igmp
+ ip pim
+!
interface lo
ip pim
!
diff --git a/tests/topotests/pim-basic/r1/zebra.conf b/tests/topotests/pim-basic/r1/zebra.conf
index b0a25f12aa..e43041758b 100644
--- a/tests/topotests/pim-basic/r1/zebra.conf
+++ b/tests/topotests/pim-basic/r1/zebra.conf
@@ -6,6 +6,9 @@ interface r1-eth0
interface r1-eth1
ip address 10.0.30.1/24
!
+interface r1-eth2
+ ip address 10.0.40.1/24
+!
interface lo
ip address 10.254.0.1/32
!
diff --git a/tests/topotests/pim-basic/r3/pimd.conf b/tests/topotests/pim-basic/r3/pimd.conf
new file mode 100644
index 0000000000..f94ee99930
--- /dev/null
+++ b/tests/topotests/pim-basic/r3/pimd.conf
@@ -0,0 +1 @@
+hostname r3
diff --git a/tests/topotests/pim-basic/r3/zebra.conf b/tests/topotests/pim-basic/r3/zebra.conf
new file mode 100644
index 0000000000..8e58e8c66a
--- /dev/null
+++ b/tests/topotests/pim-basic/r3/zebra.conf
@@ -0,0 +1,8 @@
+hostname r3
+!
+interface r3-eth0
+ ip address 10.0.40.4/24
+!
+interface lo
+ ip address 10.254.0.4/32
+!
diff --git a/tests/topotests/pim-basic/rp/pimd.conf b/tests/topotests/pim-basic/rp/pimd.conf
index 3f1b4d65c9..6e35c97971 100644
--- a/tests/topotests/pim-basic/rp/pimd.conf
+++ b/tests/topotests/pim-basic/rp/pimd.conf
@@ -7,3 +7,6 @@ interface lo
ip pim
!
ip pim rp 10.254.0.3
+ip pim register-accept-list ACCEPT
+
+ip prefix-list ACCEPT seq 5 permit 10.0.20.0/24 le 32
diff --git a/tests/topotests/pim-basic/test_pim.py b/tests/topotests/pim-basic/test_pim.py
index 0e0569e234..9101d7e035 100644
--- a/tests/topotests/pim-basic/test_pim.py
+++ b/tests/topotests/pim-basic/test_pim.py
@@ -46,14 +46,18 @@ class PIMTopo(Topo):
"Build function"
tgen = get_topogen(self)
- for routern in range(1, 3):
+ for routern in range(1, 4):
tgen.add_router('r{}'.format(routern))
tgen.add_router('rp')
+ # rp ------ r1 -------- r2
+ # \
+ # --------- r3
# r1 -> .1
# r2 -> .2
# rp -> .3
+ # r3 -> .4
# loopback network is 10.254.0.X/32
#
# r1 <- sw1 -> r2
@@ -70,6 +74,10 @@ class PIMTopo(Topo):
sw.add_link(tgen.gears['r1'])
sw.add_link(tgen.gears['rp'])
+ # 10.0.40.0/24
+ sw = tgen.add_switch('sw3')
+ sw.add_link(tgen.gears['r1'])
+ sw.add_link(tgen.gears['r3'])
def setup_module(mod):
"Sets up the pytest environment"
@@ -130,12 +138,15 @@ def test_pim_send_mcast_stream():
pytest.skip(tgen.errors)
rp = tgen.gears['rp']
+ r3 = tgen.gears['r3']
r2 = tgen.gears['r2']
r1 = tgen.gears['r1']
# Let's establish a S,G stream from r2 -> r1
CWD = os.path.dirname(os.path.realpath(__file__))
r2.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(CWD))
+ # And from r3 -> r1
+ r3.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(CWD))
# Let's see that it shows up and we have established some basic state
out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)