Skip to content

pimd,pim6d: implement PIM join filtering #19299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/user/pim.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,22 @@ PIM Routers
never do SM over. This command is vrf aware, to configure for a vrf, specify
the vrf in the router pim block.

.. clicmd:: join-filter route-map RMAP_NAME

Specify a route-map name to use for filtering incoming PIM joins.

The following route-map match statements can be used:

* match ip multicast-group A.B.C.D

* match ip multicast-group prefix-list IPV4-PREFIX-LIST

* match ip multicast-source A.B.C.D

* match ip multicast-source prefix-list IPV4-PREFIX-LIST

* match multicast-interface INTERFACE-NAME

.. clicmd:: rpf-lookup-mode MODE [group-list PREFIX_LIST] [source-list PREFIX_LIST]

MODE sets the method used to perform RPF lookups. Supported modes:
Expand Down
18 changes: 17 additions & 1 deletion doc/user/pimv6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ PIMv6 Router
never do SM over. This command is vrf aware, to configure for a vrf, specify
the vrf in the router pim block.

.. clicmd:: join-filter route-map RMAP_NAME

Specify a route-map name to use for filtering incoming PIM joins.

The following route-map match statements can be used:

* match ipv6 multicast-group X:X::X:X

* match ipv6 multicast-group prefix-list IPV6-PREFIX-LIST

* match ipv6 multicast-source X:X::X:X

* match ipv6 multicast-source prefix-list IPV6-PREFIX-LIST

* match multicast-interface INTERFACE-NAME

.. clicmd:: ssmpingd [X:X::X:X]

Enable ipv6 ssmpingd configuration. A network level management tool
Expand Down Expand Up @@ -303,7 +319,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end.

.. clicmd:: ipv6 mld route-map ROUTE-MAP

Apply the indicated route map to filter incoming IGMP joins.
Apply the indicated route map to filter incoming MLD joins.

The following match statements can be used:

Expand Down
2 changes: 1 addition & 1 deletion lib/routemap_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(dnode,
"./rmap-match-condition/frr-pim-route-map:list-name"));
} else if (IS_MATCH_MULTICAST_INTERFACE(condition)) {
vty_out(vty, " match ipv6 multicast-interface %s\n",
vty_out(vty, " match multicast-interface %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-pim-route-map:multicast-interface"));
Expand Down
20 changes: 20 additions & 0 deletions pimd/pim6_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2943,6 +2943,24 @@ DEFPY (debug_pimv6_bsm,
return CMD_SUCCESS;
}

DEFPY_YANG(pim6_join_filter_route_map, pim6_join_filter_route_map_cmd,
"[no] join-filter route-map ![RMAP_NAME]$rmap",
NO_STR
"PIM join filter configuration\n"
"Filter PIM joins via route-map\n"
"Route-map name\n")
{
char xpath[XPATH_MAXLEN];

snprintf(xpath, sizeof(xpath), "./pim-join-route-map");
if (no)
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rmap);

return nb_cli_apply_changes(vty, NULL);
}

struct cmd_node pim6_node = {
.name = "pim6",
.node = PIM6_NODE,
Expand Down Expand Up @@ -3025,6 +3043,8 @@ void pim_cmd_init(void)
install_element(PIM6_NODE, &pim6_bsr_candidate_rp_group_cmd);
install_element(PIM6_NODE, &pim6_bsr_candidate_bsr_cmd);

install_element(PIM6_NODE, &pim6_join_filter_route_map_cmd);

install_element(CONFIG_NODE, &ipv6_mld_group_watermark_cmd);
install_element(VRF_NODE, &ipv6_mld_group_watermark_cmd);
install_element(CONFIG_NODE, &no_ipv6_mld_group_watermark_cmd);
Expand Down
19 changes: 19 additions & 0 deletions pimd/pim_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -9153,6 +9153,24 @@ DEFPY_YANG(pim_rpf_lookup_mode, pim_rpf_lookup_mode_cmd,
(grp_list ? grp_list : ""), (src_list ? src_list : ""));
}

DEFPY_YANG(pim_join_filter_route_map, pim_join_filter_route_map_cmd,
"[no] join-filter route-map ![RMAP_NAME]$rmap",
NO_STR
"PIM join filter configuration\n"
"Filter PIM joins via route-map\n"
"Route-map name\n")
{
char xpath[XPATH_MAXLEN];

snprintf(xpath, sizeof(xpath), "./pim-join-route-map");
if (no)
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, rmap);

return nb_cli_apply_changes(vty, NULL);
}

struct cmd_node pim_node = {
.name = "pim",
.node = PIM_NODE,
Expand Down Expand Up @@ -9322,6 +9340,7 @@ void pim_cmd_init(void)
install_element(PIM_NODE, &pim_dm_prefix_list_cmd);

install_element(PIM_NODE, &pim_rpf_lookup_mode_cmd);
install_element(PIM_NODE, &pim_join_filter_route_map_cmd);

install_element(INTERFACE_NODE, &interface_ip_igmp_cmd);
install_element(INTERFACE_NODE, &interface_no_ip_igmp_cmd);
Expand Down
4 changes: 4 additions & 0 deletions pimd/pim_instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);

pim_filter_ref_fini(&pim->join_filter);

pim->vrf = NULL;
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
}
Expand Down Expand Up @@ -131,6 +133,8 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim_autorp_init(pim);
#endif

pim_filter_ref_init(&pim->join_filter);

return pim;
}

Expand Down
4 changes: 4 additions & 0 deletions pimd/pim_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "pim_bsm.h"
#include "pim_vxlan_instance.h"
#include "pim_oil.h"
#include "pim_routemap.h"
#include "pim_upstream.h"
#include "pim_mroute.h"
#include "pim_autorp.h"
Expand Down Expand Up @@ -209,6 +210,9 @@ struct pim_instance {
/** Log SA event messages. */
#define PIM_MSDP_LOG_SA_EVENTS 0x02

/* Filter on received PIM joins */
struct pim_filter_ref join_filter;

bool stopping;

#if PIM_IPV == 6
Expand Down
10 changes: 10 additions & 0 deletions pimd/pim_join.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,

/* Scan joined sources */
for (source = 0; source < msg_num_joined_sources; ++source) {
struct prefix_sg psg;

addr_offset = pim_parse_addr_source(
&sg, &msg_source_flags, buf, pastend - buf);
if (addr_offset < 1) {
Expand All @@ -306,6 +308,14 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
if (group_filtered || pim_is_group_filtered(pim_ifp, &sg.grp, &sg.src))
continue;

pim_sg_to_prefix(&sg, &psg);
if (!pim_filter_match(&pim_ifp->pim->join_filter, &psg, ifp)) {
if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: SG%pPSG on interface %s filtered due to route-map",
__func__, &psg, ifp->name);
continue;
}

recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr,
&sg, msg_source_flags);

Expand Down
7 changes: 7 additions & 0 deletions pimd/pim_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,13 @@ const struct frr_yang_module_info frr_pim_info = {
.destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy,
}
},
{
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/pim-join-route-map",
.cbs = {
.modify = pim_join_route_map_modify,
.destroy = pim_join_route_map_detroy,
}
},
{
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mcast-rpf-lookup",
.cbs = {
Expand Down
2 changes: 2 additions & 0 deletions pimd/pim_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_re
struct nb_cb_modify_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
struct nb_cb_destroy_args *args);
int pim_join_route_map_modify(struct nb_cb_modify_args *args);
int pim_join_route_map_detroy(struct nb_cb_destroy_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mcast_rpf_lookup_create(
struct nb_cb_create_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mcast_rpf_lookup_destroy(
Expand Down
45 changes: 45 additions & 0 deletions pimd/pim_nb_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2012,6 +2012,51 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_re
return NB_OK;
}

/*
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/pim-join-route-map
*/
int pim_join_route_map_modify(struct nb_cb_modify_args *args)
{
struct vrf *vrf;
struct pim_instance *pim;

switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;

case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
pim_filter_ref_set_rmap(&pim->join_filter,
yang_dnode_get_string(args->dnode, NULL));
break;
}

return NB_OK;
}

int pim_join_route_map_detroy(struct nb_cb_destroy_args *args)
{
struct vrf *vrf;
struct pim_instance *pim;

switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
pim_filter_ref_set_rmap(&pim->join_filter, NULL);
break;
}

return NB_OK;
}

/*
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mcast-rpf-lookup
*/
Expand Down
5 changes: 5 additions & 0 deletions pimd/pim_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)

writes += pim_lookup_mode_write(pim, vty);

if (pim->join_filter.rmapname) {
vty_out(vty, " join-filter route-map %s\n", pim->join_filter.rmapname);
++writes;
}

return writes;
}

Expand Down
Empty file.
30 changes: 30 additions & 0 deletions tests/topotests/multicast_pim_route_map_topo1/r1/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
log commands
!
ip route 192.168.101.0/24 192.168.100.2
ip route 10.254.254.2/32 192.168.100.2
ipv6 route 2001:db8:101::/64 2001:db8:100::2
ipv6 route 2001:db8:ffff::2/128 2001:db8:100::2
!
interface r1-eth0
ip address 192.168.100.1/24
ip pim
ipv6 address 2001:db8:100::1/64
ipv6 pim
exit
!
interface r1-eth1
ip address 192.168.200.1/24
ip igmp
ip pim passive
ipv6 address 2001:db8:200::1/64
ipv6 mld
ipv6 pim passive
exit
!
router pim
rp 10.254.254.2
exit
!
router pim6
rp 2001:db8:ffff::2
exit
75 changes: 75 additions & 0 deletions tests/topotests/multicast_pim_route_map_topo1/r2/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
log commands
!
interface r2-eth0
ip address 192.168.100.2/24
ip pim
ipv6 address 2001:db8:100::2/64
ipv6 pim
exit
!
interface r2-eth1
ip address 192.168.101.2/24
ip pim
ipv6 address 2001:db8:101::2/64
ipv6 pim
exit
!
interface lo
ip address 10.254.254.2/32
ip igmp
ip pim passive
ipv6 address 2001:db8:ffff::2/128
ipv6 mld
ipv6 pim passive
!
router pim
rp 10.254.254.2
join-filter route-map pim-filter
exit
!
router pim6
rp 2001:db8:ffff::2
join-filter route-map pim6-filter
exit
!
ip prefix-list allowed-pim-groups seq 5 permit 225.0.0.1/32 le 32
ip prefix-list allowed-pim-groups seq 10 permit 225.0.0.2/32 le 32
!
route-map pim-filter permit 100
match ip multicast-group prefix-list allowed-pim-groups
exit
!
route-map pim-filter permit 110
match ip multicast-group 225.0.0.100
exit
!
route-map pim-filter permit 120
match ip multicast-group 225.0.0.200
match multicast-interface r2-eth1
exit
!
route-map pim-filter permit 130
match ip multicast-group 232.0.1.1
match ip multicast-source 192.168.101.10
exit
!
ipv6 prefix-list allowed-pim6-groups seq 5 permit ff05::100/128 le 128
ipv6 prefix-list allowed-pim6-groups seq 10 permit ff05::200/128 le 128
!
route-map pim6-filter permit 100
match ipv6 multicast-group prefix-list allowed-pim6-groups
exit
!
route-map pim6-filter permit 110
match ipv6 multicast-group ff05::1000
exit
!
route-map pim6-filter permit 120
match ipv6 multicast-group ff05::2000
match multicast-interface r2-eth1
exit
!
route-map pim6-filter permit 130
match ipv6 multicast-group ff35::100
match ipv6 multicast-source 2001:db8:101::100
exit
Loading
Loading