This commit is contained in:
Rafael Zalamena 2025-04-29 18:35:25 +00:00 committed by GitHub
commit 47f6e44086
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 228 additions and 0 deletions

View file

@ -175,6 +175,12 @@ PIMv6 Router
notifications to the kernel. This command is vrf aware, to configure for a
vrf, specify the vrf in the router pim6 block.
.. clicmd:: ssm prefix-list WORD
Specify a range of group addresses via a prefix-list that forces pim to
never do SM over. This command is vrf aware, to configure for a vrf, specify
the vrf in the router pim block.
.. clicmd:: ssmpingd [X:X::X:X]
Enable ipv6 ssmpingd configuration. A network level management tool

View file

@ -28,6 +28,8 @@
#include "pim_addr.h"
#include "pim_nht.h"
#include "pim_bsm.h"
#include "pim_ssm.h"
#include "pim_util.h"
#include "pim_iface.h"
#include "pim_zebra.h"
#include "pim_instance.h"
@ -1479,6 +1481,26 @@ DEFPY_ATTR(no_ipv6_ssmpingd,
return ret;
}
DEFPY_YANG(ipv6_pim_ssm,
ipv6_pim_ssm_cmd,
"[no] ssm prefix-list PREFIXLIST6_NAME$plist",
NO_STR
"Source Specific Multicast\n"
"Group range prefix-list filter\n"
"Name of a prefix-list\n")
{
char ssm_plist_xpath[XPATH_MAXLEN];
snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), "./ssm-prefix-list");
if (no)
nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, NULL);
else
nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_MODIFY, plist);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG_HIDDEN (interface_ipv6_mld_join,
interface_ipv6_mld_join_cmd,
"[no] ipv6 mld join X:X::X:X$grp [X:X::X:X]$src",
@ -2433,6 +2455,79 @@ DEFPY (show_ipv6_pim_bsrp,
return pim_show_group_rp_mappings_info_helper(vrf, vty, !!json);
}
DEFPY(show_ipv6_pim_ssm_range,
show_ipv6_pim_ssm_range_cmd,
"show ipv6 pim [vrf NAME$vrf_name] group-type [json$json]",
SHOW_STR
IPV6_STR
PIM_STR
VRF_CMD_HELP_STR
"PIM group type\n"
JSON_STR)
{
struct pim_instance *pim;
const char *range_str;
struct pim_ssm *ssm;
struct vrf *vrf = NULL;
if (vrf_name)
vrf = vrf_lookup_by_name(vrf_name);
if (vrf == NULL)
vrf = vrf_lookup_by_id(VRF_DEFAULT);
pim = vrf->info;
ssm = pim->ssm_info;
range_str = ssm->plist_name ? ssm->plist_name : PIM6_SSM_STANDARD_RANGE;
if (json) {
struct json_object *json_root;
json_root = json_object_new_object();
json_object_string_add(json_root, "ssmGroups", range_str);
vty_json(vty, json_root);
} else
vty_out(vty, "SSM group range : %s\n", range_str);
return CMD_SUCCESS;
}
DEFPY(show_ipv6_pim_group_type,
show_ipv6_pim_group_type_cmd,
"show ipv6 pim [vrf NAME$vrf_name] group-type X:X::X:X$group [json$json]",
SHOW_STR
IP_STR
PIM_STR
VRF_CMD_HELP_STR
"multicast group type\n"
"group address\n"
JSON_STR)
{
struct pim_instance *pim;
const char *type_str;
struct vrf *vrf = NULL;
if (vrf_name)
vrf = vrf_lookup_by_name(vrf_name);
if (vrf == NULL)
vrf = vrf_lookup_by_id(VRF_DEFAULT);
pim = vrf->info;
if (pim_is_group_ff00_8(group))
type_str = pim_is_grp_ssm(pim, group) ? "SSM" : "ASM";
else
type_str = "not-multicast";
if (json) {
struct json_object *json_root;
json_root = json_object_new_object();
json_object_string_add(json_root, "groupType", type_str);
vty_json(vty, json_root);
} else
vty_out(vty, "Group type : %s\n", type_str);
return CMD_SUCCESS;
}
DEFPY(clear_ipv6_mld_interfaces,
clear_ipv6_mld_interfaces_cmd,
"clear ipv6 mld [vrf NAME$vrf_name] interfaces",
@ -2957,6 +3052,7 @@ void pim_cmd_init(void)
install_element(PIM6_NODE, &pim6_embedded_rp_group_list_cmd);
install_element(PIM6_NODE, &pim6_embedded_rp_limit_cmd);
install_element(PIM6_NODE, &ipv6_pim_ssm_cmd);
install_element(PIM6_NODE, &pim6_ssmpingd_cmd);
install_element(PIM6_NODE, &no_pim6_ssmpingd_cmd);
install_element(PIM6_NODE, &pim6_bsr_candidate_rp_cmd);
@ -3061,6 +3157,8 @@ void pim_cmd_init(void)
install_element(VIEW_NODE, &show_ipv6_pim_bsr_cmd);
install_element(VIEW_NODE, &show_ipv6_pim_bsm_db_cmd);
install_element(VIEW_NODE, &show_ipv6_pim_bsrp_cmd);
install_element(VIEW_NODE, &show_ipv6_pim_ssm_range_cmd);
install_element(VIEW_NODE, &show_ipv6_pim_group_type_cmd);
install_element(ENABLE_NODE, &clear_ipv6_mld_interfaces_cmd);
install_element(ENABLE_NODE, &clear_ipv6_pim_statistics_cmd);
install_element(ENABLE_NODE, &clear_ipv6_mroute_cmd);

View file

@ -7,6 +7,7 @@
#define PIM_SSM_H
#define PIM_SSM_STANDARD_RANGE "232.0.0.0/8"
#define PIM6_SSM_STANDARD_RANGE "FF30::/32"
struct pim_instance;

View file

@ -129,6 +129,20 @@ int pim_is_group_224_4(struct in_addr group_addr)
return prefix_match(&group_all, &group);
}
bool pim_is_group_ff00_8(struct in6_addr group_address)
{
struct prefix group_all = { .family = AF_INET6,
.prefixlen = 8,
.u.prefix6.s6_addr = { 0xFF } };
struct prefix group;
group.family = AF_INET6;
group.u.prefix6 = group_address;
group.prefixlen = IPV6_MAX_BITLEN;
return prefix_match(&group_all, &group);
}
static bool pim_cisco_match(const struct filter *filter, const struct in_addr *source,
const struct in_addr *group)
{

View file

@ -23,6 +23,7 @@ void pim_pkt_dump(const char *label, const uint8_t *buf, int size);
int pim_is_group_224_0_0_0_24(struct in_addr group_addr);
int pim_is_group_224_4(struct in_addr group_addr);
bool pim_is_group_ff00_8(struct in6_addr group_address);
enum filter_type pim_access_list_apply(struct access_list *access, const struct in_addr *source,
const struct in_addr *group);
bool pim_is_group_filtered(struct pim_interface *pim_ifp, pim_addr *grp, pim_addr *src);

View file

@ -0,0 +1,14 @@
log commands
!
ip prefix-list pim-ssm permit 230.0.0.0/8
!
ipv6 prefix-list pim6-ssm permit ff35::/32
!
router pim
ssm prefix-list pim-ssm
exit
!
router pim6
ssm prefix-list pim6-ssm
exit
!

View file

@ -0,0 +1,94 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC
#
# test_multicast_ssm_topo1.py
# Part of NetDEF Topology Tests
#
# Copyright (c) 2025 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
"""
test_multicast_ssm_topo1.py: Test PIM SSM configuration.
"""
import os
import sys
import json
from functools import partial
import re
import pytest
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib import topotest
# Required to instantiate the topology builder class.
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
pytestmark = [pytest.mark.pimd]
def build_topo(tgen):
tgen.add_router(f"r1")
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
tgen.gears["r1"].load_frr_config(os.path.join(CWD, f"r1/frr.conf"))
tgen.start_router()
def teardown_module():
"Teardown the pytest environment"
tgen = get_topogen()
tgen.stop_topology()
def test_multicast_ssm():
"Test SSM group"
pim_test = [
{"address": "229.0.0.100", "type": "ASM"},
{"address": "230.0.0.100", "type": "SSM"}
]
pim6_test = [
{"address": "FF32::100", "type": "ASM"},
{"address": "FF35::100", "type": "SSM"}
]
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router = tgen.gears["r1"]
for test in pim_test:
output = router.vtysh_cmd(f"show ip pim group-type {test['address']} json", isjson=True)
assert test["type"] == output["groupType"], "Wrong group type"
for test in pim6_test:
output = router.vtysh_cmd(f"show ipv6 pim group-type {test['address']} json", isjson=True)
assert test["type"] == output["groupType"], "Wrong group type"
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))