Merge pull request #17521 from opensourcerouting/msdp-sa-limit

pimd: MSDP per peer SA limit
This commit is contained in:
Jafar Al-Gharaibeh 2024-12-10 11:36:50 -06:00 committed by GitHub
commit ccb57ad10f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 136 additions and 0 deletions

View File

@ -503,6 +503,10 @@ Commands available for MSDP
The filtering will only take effect starting from the command The filtering will only take effect starting from the command
application. application.
.. clicmd:: msdp peer A.B.C.D sa-limit <AMOUNT>
Configure the maximum number of SAs to learn from peer.
.. clicmd:: msdp peer A.B.C.D password WORD .. clicmd:: msdp peer A.B.C.D password WORD
Use MD5 authentication to connect with the remote peer. Use MD5 authentication to connect with the remote peer.

View File

@ -7593,6 +7593,29 @@ DEFPY(msdp_shutdown,
return nb_cli_apply_changes(vty, NULL); return nb_cli_apply_changes(vty, NULL);
} }
DEFPY(msdp_peer_sa_limit, msdp_peer_sa_limit_cmd,
"[no] msdp peer A.B.C.D$peer sa-limit ![(1-4294967294)$sa_limit]",
NO_STR
CFG_MSDP_STR
"Configure MSDP peer\n"
"MSDP peer address\n"
"Limit amount of SA\n"
"Maximum number of SA\n")
{
const struct lyd_node *peer_node;
char xpath[XPATH_MAXLEN + 24];
snprintf(xpath, sizeof(xpath), "%s/msdp-peer[peer-ip='%s']", VTY_CURR_XPATH, peer_str);
peer_node = yang_dnode_get(vty->candidate_config->dnode, xpath);
if (peer_node == NULL) {
vty_out(vty, "%% MSDP peer %s not yet configured\n", peer_str);
return CMD_SUCCESS;
}
nb_cli_enqueue_change(vty, "./sa-limit", NB_OP_MODIFY, sa_limit_str);
return nb_cli_apply_changes(vty, "%s", xpath);
}
static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg, static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg,
struct json_object *json) struct json_object *json)
{ {
@ -8988,6 +9011,7 @@ void pim_cmd_init(void)
install_element(PIM_NODE, &msdp_log_neighbor_changes_cmd); install_element(PIM_NODE, &msdp_log_neighbor_changes_cmd);
install_element(PIM_NODE, &msdp_log_sa_changes_cmd); install_element(PIM_NODE, &msdp_log_sa_changes_cmd);
install_element(PIM_NODE, &msdp_shutdown_cmd); install_element(PIM_NODE, &msdp_shutdown_cmd);
install_element(PIM_NODE, &msdp_peer_sa_limit_cmd);
install_element(PIM_NODE, &pim_bsr_candidate_rp_cmd); install_element(PIM_NODE, &pim_bsr_candidate_rp_cmd);
install_element(PIM_NODE, &pim_bsr_candidate_rp_group_cmd); install_element(PIM_NODE, &pim_bsr_candidate_rp_group_cmd);

View File

@ -359,6 +359,15 @@ void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
struct rp_info *rp_info; struct rp_info *rp_info;
struct prefix grp; struct prefix grp;
/* Check peer SA limit. */
if (mp && mp->sa_limit && mp->sa_cnt >= mp->sa_limit) {
if (pim_msdp_log_sa_events(pim))
zlog_debug("MSDP peer %pI4 reject SA (%pI4, %pI4): SA limit %u of %u",
&mp->peer, &sg->src, &sg->grp, mp->sa_cnt, mp->sa_limit);
return;
}
sa = pim_msdp_sa_add(pim, sg, rp); sa = pim_msdp_sa_add(pim, sg, rp);
if (!sa) { if (!sa) {
return; return;
@ -1316,6 +1325,9 @@ bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim)
vty_out(vty, " msdp peer %pI4 sa-filter %s out\n", vty_out(vty, " msdp peer %pI4 sa-filter %s out\n",
&mp->peer, mp->acl_out); &mp->peer, mp->acl_out);
if (mp->sa_limit)
vty_out(vty, " msdp peer %pI4 sa-limit %u\n", &mp->peer, mp->sa_limit);
written = true; written = true;
} }

View File

@ -152,6 +152,9 @@ struct pim_msdp_peer {
char *acl_in; char *acl_in;
/** SA output access list name. */ /** SA output access list name. */
char *acl_out; char *acl_out;
/** SA maximum amount. */
uint32_t sa_limit;
}; };
struct pim_msdp_mg_mbr { struct pim_msdp_mg_mbr {

View File

@ -208,6 +208,13 @@ const struct frr_yang_module_info frr_pim_info = {
.destroy = pim_msdp_peer_authentication_key_destroy, .destroy = pim_msdp_peer_authentication_key_destroy,
} }
}, },
{
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/sa-limit",
.cbs = {
.modify = pim_msdp_peer_sa_limit_modify,
.destroy = pim_msdp_peer_sa_limit_destroy,
}
},
{ {
.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag", .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag",
.cbs = { .cbs = {

View File

@ -76,6 +76,8 @@ int pim_msdp_peer_sa_filter_out_destroy(struct nb_cb_destroy_args *args);
int pim_msdp_peer_authentication_type_modify(struct nb_cb_modify_args *args); int pim_msdp_peer_authentication_type_modify(struct nb_cb_modify_args *args);
int pim_msdp_peer_authentication_key_modify(struct nb_cb_modify_args *args); int pim_msdp_peer_authentication_key_modify(struct nb_cb_modify_args *args);
int pim_msdp_peer_authentication_key_destroy(struct nb_cb_destroy_args *args); int pim_msdp_peer_authentication_key_destroy(struct nb_cb_destroy_args *args);
int pim_msdp_peer_sa_limit_modify(struct nb_cb_modify_args *args);
int pim_msdp_peer_sa_limit_destroy(struct nb_cb_destroy_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create( int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
struct nb_cb_create_args *args); struct nb_cb_create_args *args);
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy( int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(

View File

@ -1579,6 +1579,48 @@ int pim_msdp_peer_sa_filter_out_destroy(struct nb_cb_destroy_args *args)
return NB_OK; return NB_OK;
} }
/*
* XPath:
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/sa-limit
*/
int pim_msdp_peer_sa_limit_modify(struct nb_cb_modify_args *args)
{
struct pim_msdp_peer *mp;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
/* NOTHING */
break;
case NB_EV_APPLY:
mp = nb_running_get_entry(args->dnode, NULL, true);
mp->sa_limit = yang_dnode_get_uint32(args->dnode, NULL);
break;
}
return NB_OK;
}
int pim_msdp_peer_sa_limit_destroy(struct nb_cb_destroy_args *args)
{
struct pim_msdp_peer *mp;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
/* NOTHING */
break;
case NB_EV_APPLY:
mp = nb_running_get_entry(args->dnode, NULL, true);
mp->sa_limit = 0;
break;
}
return NB_OK;
}
/* /*
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
*/ */

View File

@ -511,6 +511,42 @@ def test_msdp_sa_filter():
assert val is None, "multicast route convergence failure" assert val is None, "multicast route convergence failure"
def test_msdp_sa_limit():
"Test MSDP SA limiting."
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
tgen.gears["r4"].vtysh_cmd(
"""
configure terminal
router pim
msdp log sa-events
msdp peer 192.168.2.1 sa-limit 4
msdp peer 192.168.3.1 sa-limit 4
"""
)
# Flow from r1 -> r4
for multicast_address in [
"229.1.2.10",
"229.1.2.11",
"229.1.2.12",
"229.1.2.13",
"229.1.2.14",
]:
app_helper.run("h1", [multicast_address, "h1-eth0"])
app_helper.run("h2", ["--send=0.7", multicast_address, "h2-eth0"])
def test_sa_limit_log():
r4_log = tgen.gears["r4"].net.getLog("log", "pimd")
return re.search(r"MSDP peer .+ reject SA (.+, .+): SA limit \d+ of 4", r4_log)
_, val = topotest.run_and_expect(test_sa_limit_log, None, count=30, wait=1)
assert val is None, "SA limit check failed"
def test_msdp_log_events(): def test_msdp_log_events():
"Test that the enabled logs are working as expected." "Test that the enabled logs are working as expected."

View File

@ -341,6 +341,12 @@ module frr-pim {
} }
uses msdp-authentication; uses msdp-authentication;
leaf sa-limit {
type uint32;
description
"Peer SA maximum limit.";
}
} }
container mlag { container mlag {