mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-12 14:27:36 +00:00
Merge pull request #5849 from donaldsharp/pim_register_prefix_list
Pim register prefix list
This commit is contained in:
commit
09c04bc490
@ -66,6 +66,14 @@ Certain signals have special meanings to *pimd*.
|
|||||||
prefix of group ranges covered. This command is vrf aware, to configure for
|
prefix of group ranges covered. This command is vrf aware, to configure for
|
||||||
a vrf, enter the vrf submode.
|
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
|
.. index:: ip pim spt-switchover infinity-and-beyond
|
||||||
.. clicmd:: ip pim spt-switchover infinity-and-beyond
|
.. clicmd:: ip pim spt-switchover infinity-and-beyond
|
||||||
|
|
||||||
|
@ -6628,18 +6628,18 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
|
|||||||
|
|
||||||
switch (pim->spt.switchover) {
|
switch (pim->spt.switchover) {
|
||||||
case PIM_SPT_IMMEDIATE:
|
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);
|
pim_upstream_add_lhr_star_pimreg(pim);
|
||||||
break;
|
break;
|
||||||
case PIM_SPT_INFINITY:
|
case PIM_SPT_INFINITY:
|
||||||
pim_upstream_remove_lhr_star_pimreg(pim, plist);
|
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)
|
if (plist)
|
||||||
pim->spt.plist =
|
pim->spt.plist =
|
||||||
XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist);
|
XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6700,6 +6700,26 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
|
|||||||
return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
|
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,
|
DEFUN (ip_pim_joinprune_time,
|
||||||
ip_pim_joinprune_time_cmd,
|
ip_pim_joinprune_time_cmd,
|
||||||
"ip pim join-prune-interval (60-600)",
|
"ip pim join-prune-interval (60-600)",
|
||||||
@ -10798,6 +10818,8 @@ void pim_cmd_init(void)
|
|||||||
install_element(CONFIG_NODE,
|
install_element(CONFIG_NODE,
|
||||||
&no_ip_pim_spt_switchover_infinity_plist_cmd);
|
&no_ip_pim_spt_switchover_infinity_plist_cmd);
|
||||||
install_element(VRF_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(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
|
||||||
install_element(VRF_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);
|
install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
|
||||||
|
@ -69,6 +69,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
|
|||||||
|
|
||||||
pim_msdp_exit(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);
|
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,9 @@ struct pim_instance {
|
|||||||
char *plist;
|
char *plist;
|
||||||
} spt;
|
} spt;
|
||||||
|
|
||||||
|
/* The name of the register-accept prefix-list */
|
||||||
|
char *register_plist;
|
||||||
|
|
||||||
struct hash *rpf_hash;
|
struct hash *rpf_hash;
|
||||||
|
|
||||||
void *ssm_info; /* per-vrf SSM configuration */
|
void *ssm_info; /* per-vrf SSM configuration */
|
||||||
|
@ -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_PIM_INSTANCE, "PIM global state")
|
||||||
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
|
DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state")
|
||||||
DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration")
|
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")
|
DEFINE_MTYPE(PIMD, PIM_VXLAN_SG, "PIM VxLAN mroute cache")
|
||||||
|
@ -50,7 +50,7 @@ DECLARE_MTYPE(PIM_JP_AGG_SOURCE)
|
|||||||
DECLARE_MTYPE(PIM_PIM_INSTANCE)
|
DECLARE_MTYPE(PIM_PIM_INSTANCE)
|
||||||
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
|
DECLARE_MTYPE(PIM_NEXTHOP_CACHE)
|
||||||
DECLARE_MTYPE(PIM_SSM_INFO)
|
DECLARE_MTYPE(PIM_SSM_INFO)
|
||||||
DECLARE_MTYPE(PIM_SPT_PLIST_NAME);
|
DECLARE_MTYPE(PIM_PLIST_NAME);
|
||||||
DECLARE_MTYPE(PIM_VXLAN_SG)
|
DECLARE_MTYPE(PIM_VXLAN_SG)
|
||||||
|
|
||||||
#endif /* _QUAGGA_PIM_MEMORY_H */
|
#endif /* _QUAGGA_PIM_MEMORY_H */
|
||||||
|
@ -324,14 +324,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
|
|||||||
struct prefix_sg sg;
|
struct prefix_sg sg;
|
||||||
uint32_t *bits;
|
uint32_t *bits;
|
||||||
int i_am_rp = 0;
|
int i_am_rp = 0;
|
||||||
struct pim_interface *pim_ifp = NULL;
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
|
struct pim_instance *pim = pim_ifp->pim;
|
||||||
pim_ifp = ifp->info;
|
|
||||||
|
|
||||||
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
|
#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
|
||||||
ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
|
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) {
|
if (PIM_DEBUG_PIM_REG) {
|
||||||
char dest[INET_ADDRSTRLEN];
|
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.src = ip_hdr->ip_src;
|
||||||
sg.grp = ip_hdr->ip_dst;
|
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) {
|
if (PIM_DEBUG_PIM_REG) {
|
||||||
char src_str[INET_ADDRSTRLEN];
|
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
|
if (i_am_rp
|
||||||
&& (dest_addr.s_addr
|
&& (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;
|
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) {
|
if (*bits & PIM_REGISTER_BORDER_BIT) {
|
||||||
struct in_addr pimbr = pim_br_get_pmbr(&sg);
|
struct in_addr pimbr = pim_br_get_pmbr(&sg);
|
||||||
if (PIM_DEBUG_PIM_PACKETS)
|
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 =
|
struct pim_upstream *upstream = pim_upstream_find(pim, &sg);
|
||||||
pim_upstream_find(pim_ifp->pim, &sg);
|
|
||||||
/*
|
/*
|
||||||
* If we don't have a place to send ignore the packet
|
* If we don't have a place to send ignore the packet
|
||||||
*/
|
*/
|
||||||
if (!upstream) {
|
if (!upstream) {
|
||||||
upstream = pim_upstream_add(
|
upstream = pim_upstream_add(
|
||||||
pim_ifp->pim, &sg, ifp,
|
pim, &sg, ifp,
|
||||||
PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
|
PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__,
|
||||||
NULL);
|
NULL);
|
||||||
if (!upstream) {
|
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)
|
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||||
|| ((SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))
|
|| ((SwitchToSptDesiredOnRp(pim, &sg))
|
||||||
&& pim_upstream_inherited_olist(pim_ifp->pim, upstream)
|
&& pim_upstream_inherited_olist(pim, upstream) == 0)) {
|
||||||
== 0)) {
|
|
||||||
pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
|
pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
|
||||||
sentRegisterStop = 1;
|
sentRegisterStop = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -463,15 +487,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
|
|||||||
upstream->sptbit);
|
upstream->sptbit);
|
||||||
}
|
}
|
||||||
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
|
||||||
|| (SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))) {
|
|| (SwitchToSptDesiredOnRp(pim, &sg))) {
|
||||||
if (sentRegisterStop) {
|
if (sentRegisterStop) {
|
||||||
pim_upstream_keep_alive_timer_start(
|
pim_upstream_keep_alive_timer_start(
|
||||||
upstream,
|
upstream, pim->rp_keep_alive_time);
|
||||||
pim_ifp->pim->rp_keep_alive_time);
|
|
||||||
} else {
|
} else {
|
||||||
pim_upstream_keep_alive_timer_start(
|
pim_upstream_keep_alive_timer_start(
|
||||||
upstream,
|
upstream, pim->keep_alive_time);
|
||||||
pim_ifp->pim->keep_alive_time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +216,11 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
|
|||||||
ssm->plist_name);
|
ssm->plist_name);
|
||||||
++writes;
|
++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.switchover == PIM_SPT_INFINITY) {
|
||||||
if (pim->spt.plist)
|
if (pim->spt.plist)
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
|
@ -7,6 +7,10 @@ interface r1-eth0
|
|||||||
interface r1-eth1
|
interface r1-eth1
|
||||||
ip pim
|
ip pim
|
||||||
!
|
!
|
||||||
|
interface r1-eth2
|
||||||
|
ip igmp
|
||||||
|
ip pim
|
||||||
|
!
|
||||||
interface lo
|
interface lo
|
||||||
ip pim
|
ip pim
|
||||||
!
|
!
|
||||||
|
@ -6,6 +6,9 @@ interface r1-eth0
|
|||||||
interface r1-eth1
|
interface r1-eth1
|
||||||
ip address 10.0.30.1/24
|
ip address 10.0.30.1/24
|
||||||
!
|
!
|
||||||
|
interface r1-eth2
|
||||||
|
ip address 10.0.40.1/24
|
||||||
|
!
|
||||||
interface lo
|
interface lo
|
||||||
ip address 10.254.0.1/32
|
ip address 10.254.0.1/32
|
||||||
!
|
!
|
||||||
|
1
tests/topotests/pim-basic/r3/pimd.conf
Normal file
1
tests/topotests/pim-basic/r3/pimd.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
hostname r3
|
8
tests/topotests/pim-basic/r3/zebra.conf
Normal file
8
tests/topotests/pim-basic/r3/zebra.conf
Normal file
@ -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
|
||||||
|
!
|
@ -7,3 +7,6 @@ interface lo
|
|||||||
ip pim
|
ip pim
|
||||||
!
|
!
|
||||||
ip pim rp 10.254.0.3
|
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
|
||||||
|
@ -46,14 +46,18 @@ class PIMTopo(Topo):
|
|||||||
"Build function"
|
"Build function"
|
||||||
tgen = get_topogen(self)
|
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('r{}'.format(routern))
|
||||||
|
|
||||||
tgen.add_router('rp')
|
tgen.add_router('rp')
|
||||||
|
|
||||||
|
# rp ------ r1 -------- r2
|
||||||
|
# \
|
||||||
|
# --------- r3
|
||||||
# r1 -> .1
|
# r1 -> .1
|
||||||
# r2 -> .2
|
# r2 -> .2
|
||||||
# rp -> .3
|
# rp -> .3
|
||||||
|
# r3 -> .4
|
||||||
# loopback network is 10.254.0.X/32
|
# loopback network is 10.254.0.X/32
|
||||||
#
|
#
|
||||||
# r1 <- sw1 -> r2
|
# r1 <- sw1 -> r2
|
||||||
@ -70,6 +74,10 @@ class PIMTopo(Topo):
|
|||||||
sw.add_link(tgen.gears['r1'])
|
sw.add_link(tgen.gears['r1'])
|
||||||
sw.add_link(tgen.gears['rp'])
|
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):
|
def setup_module(mod):
|
||||||
"Sets up the pytest environment"
|
"Sets up the pytest environment"
|
||||||
@ -130,12 +138,15 @@ def test_pim_send_mcast_stream():
|
|||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
rp = tgen.gears['rp']
|
rp = tgen.gears['rp']
|
||||||
|
r3 = tgen.gears['r3']
|
||||||
r2 = tgen.gears['r2']
|
r2 = tgen.gears['r2']
|
||||||
r1 = tgen.gears['r1']
|
r1 = tgen.gears['r1']
|
||||||
|
|
||||||
# Let's establish a S,G stream from r2 -> r1
|
# Let's establish a S,G stream from r2 -> r1
|
||||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
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))
|
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
|
# 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)
|
out = r1.vtysh_cmd("show ip pim upstream json", isjson=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user