mirror of
https://github.com/FRRouting/frr.git
synced 2026-01-16 23:14:01 +00:00
Merge pull request #19765 from ThalesGroup/bugfix/ip_static_mroute
pimd : Added support for multi-oif static mroute
This commit is contained in:
commit
02a31e281c
6 changed files with 112 additions and 73 deletions
|
|
@ -468,7 +468,12 @@ int pim_process_ip_gmp_proxy_cmd(struct vty *vty, bool enable)
|
|||
int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
|
||||
const char *group_str, const char *source_str)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
|
||||
/* managing list of oif regarding (iif,mcast group, mcast source)*/
|
||||
char xpath[XPATH_MAXLEN];
|
||||
|
||||
snprintf(xpath, sizeof(xpath), "./oif[.='%s']", interface);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
|
||||
|
||||
if (!source_str) {
|
||||
char buf[SRCDEST2STR_BUFFER];
|
||||
|
|
@ -487,7 +492,12 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
|
|||
int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
|
||||
const char *group_str, const char *source_str)
|
||||
{
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
/* managing list of oif regarding (iif,mcast group, mcast source)*/
|
||||
char xpath[XPATH_MAXLEN];
|
||||
|
||||
snprintf(xpath, sizeof(xpath), "./oif[.='%s']", interface);
|
||||
|
||||
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
|
||||
|
||||
if (!source_str) {
|
||||
char buf[SRCDEST2STR_BUFFER];
|
||||
|
|
|
|||
|
|
@ -418,13 +418,13 @@ const struct frr_yang_module_info frr_pim_info = {
|
|||
.xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute",
|
||||
.cbs = {
|
||||
.create = lib_interface_pim_address_family_mroute_create,
|
||||
.destroy = lib_interface_pim_address_family_mroute_destroy,
|
||||
.destroy = lib_interface_pim_address_family_mroute_oif_destroy,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif",
|
||||
.cbs = {
|
||||
.modify = lib_interface_pim_address_family_mroute_oif_modify,
|
||||
.create = lib_interface_pim_address_family_mroute_oif_create,
|
||||
.destroy = lib_interface_pim_address_family_mroute_oif_destroy,
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -164,10 +164,7 @@ int lib_interface_pim_address_family_multicast_boundary_acl_modify(struct nb_cb_
|
|||
int lib_interface_pim_address_family_multicast_boundary_acl_destroy(struct nb_cb_destroy_args *args);
|
||||
int lib_interface_pim_address_family_mroute_create(
|
||||
struct nb_cb_create_args *args);
|
||||
int lib_interface_pim_address_family_mroute_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
int lib_interface_pim_address_family_mroute_oif_modify(
|
||||
struct nb_cb_modify_args *args);
|
||||
int lib_interface_pim_address_family_mroute_oif_create(struct nb_cb_create_args *args);
|
||||
int lib_interface_pim_address_family_mroute_oif_destroy(
|
||||
struct nb_cb_destroy_args *args);
|
||||
|
||||
|
|
|
|||
|
|
@ -2903,65 +2903,10 @@ int lib_interface_pim_address_family_mroute_create(
|
|||
return NB_OK;
|
||||
}
|
||||
|
||||
int lib_interface_pim_address_family_mroute_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct pim_instance *pim;
|
||||
struct pim_interface *pim_iifp;
|
||||
struct interface *iif;
|
||||
struct interface *oif;
|
||||
const char *oifname;
|
||||
pim_addr source_addr;
|
||||
pim_addr group_addr;
|
||||
const struct lyd_node *if_dnode;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
||||
if (!is_pim_interface(if_dnode)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"%% Enable PIM and/or IGMP on this interface first");
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
iif = nb_running_get_entry(args->dnode, NULL, true);
|
||||
pim_iifp = iif->info;
|
||||
pim = pim_iifp->pim;
|
||||
|
||||
oifname = yang_dnode_get_string(args->dnode, "oif");
|
||||
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
||||
|
||||
if (!oif) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"No such interface name %s",
|
||||
oifname);
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
|
||||
yang_dnode_get_pimaddr(&source_addr, args->dnode, "source-addr");
|
||||
yang_dnode_get_pimaddr(&group_addr, args->dnode, "group-addr");
|
||||
|
||||
if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"Failed to remove static mroute");
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
|
||||
*/
|
||||
int lib_interface_pim_address_family_mroute_oif_modify(
|
||||
struct nb_cb_modify_args *args)
|
||||
int lib_interface_pim_address_family_mroute_oif_create(struct nb_cb_create_args *args)
|
||||
{
|
||||
struct pim_instance *pim;
|
||||
struct pim_interface *pim_iifp;
|
||||
|
|
@ -3004,15 +2949,19 @@ int lib_interface_pim_address_family_mroute_oif_modify(
|
|||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
iif = nb_running_get_entry(args->dnode, NULL, true);
|
||||
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
||||
|
||||
iif = nb_running_get_entry(if_dnode, NULL, true);
|
||||
if (!iif)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
pim_iifp = iif->info;
|
||||
pim = pim_iifp->pim;
|
||||
|
||||
oifname = yang_dnode_get_string(args->dnode, NULL);
|
||||
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
||||
if (!oif) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"No such interface name %s",
|
||||
snprintf(args->errmsg, args->errmsg_len, "No such interface name %s",
|
||||
oifname);
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
|
|
@ -3021,8 +2970,7 @@ int lib_interface_pim_address_family_mroute_oif_modify(
|
|||
yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
|
||||
|
||||
if (pim_static_add(pim, iif, oif, group_addr, source_addr)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"Failed to add static mroute");
|
||||
snprintf(args->errmsg, args->errmsg_len, "Failed to add static mroute");
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
|
||||
|
|
@ -3032,14 +2980,55 @@ int lib_interface_pim_address_family_mroute_oif_modify(
|
|||
return NB_OK;
|
||||
}
|
||||
|
||||
int lib_interface_pim_address_family_mroute_oif_destroy(
|
||||
struct nb_cb_destroy_args *args)
|
||||
int lib_interface_pim_address_family_mroute_oif_destroy(struct nb_cb_destroy_args *args)
|
||||
{
|
||||
struct pim_instance *pim;
|
||||
struct pim_interface *pim_iifp;
|
||||
struct interface *iif;
|
||||
struct interface *oif;
|
||||
const char *oifname;
|
||||
pim_addr source_addr;
|
||||
pim_addr group_addr;
|
||||
const struct lyd_node *if_dnode;
|
||||
|
||||
switch (args->event) {
|
||||
case NB_EV_VALIDATE:
|
||||
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
||||
if (!is_pim_interface(if_dnode)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"%% Enable PIM and/or IGMP on this interface first");
|
||||
return NB_ERR_VALIDATION;
|
||||
}
|
||||
break;
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
||||
|
||||
iif = nb_running_get_entry(if_dnode, NULL, true);
|
||||
if (!iif)
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
|
||||
|
||||
pim_iifp = iif->info;
|
||||
pim = pim_iifp->pim;
|
||||
|
||||
oifname = yang_dnode_get_string(args->dnode, NULL);
|
||||
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
||||
if (!oif) {
|
||||
snprintf(args->errmsg, args->errmsg_len, "No such interface name %s",
|
||||
oifname);
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
|
||||
yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
|
||||
yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
|
||||
|
||||
if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
|
||||
snprintf(args->errmsg, args->errmsg_len, "Failed to del static mroute");
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,6 +247,49 @@ def test_memory_leak():
|
|||
tgen.report_memory_leaks()
|
||||
|
||||
|
||||
def test_pim_static_mroute():
|
||||
"Test Static routes add/remove cycle"
|
||||
logger.info("Testing static routes")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
r1 = tgen.gears["r1"]
|
||||
|
||||
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
|
||||
assert "239.1.1.1" not in ip_mroute_json.keys()
|
||||
|
||||
# Add ip mroute with iif=r1-eth0 oil=r1-eth1
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip mroute r1-eth1 239.1.1.1 10.0.0.1")
|
||||
|
||||
# Expect to find oil=[r1-eth1] in ip mroute command
|
||||
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
|
||||
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == ["r1-eth1"]
|
||||
|
||||
# Add ip mroute with iif=r1-eth0 oil=r1-eth2
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip mroute r1-eth2 239.1.1.1 10.0.0.1")
|
||||
|
||||
# Expect to find oil=[r1-eth1,r1-eth2] in ip mroute command
|
||||
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
|
||||
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == [
|
||||
"r1-eth1",
|
||||
"r1-eth2",
|
||||
]
|
||||
|
||||
# Remove ip mroute with oil=r1-eth1
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip mroute r1-eth1 239.1.1.1 10.0.0.1")
|
||||
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
|
||||
# This assert right here would break back in the day because only one oif was handled by the datamodel
|
||||
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == ["r1-eth2"]
|
||||
|
||||
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip mroute r1-eth2 239.1.1.1 10.0.0.1")
|
||||
# Expect a clean state
|
||||
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
|
||||
assert "239.1.1.1" not in ip_mroute_json.keys()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
||||
|
|
|
|||
|
|
@ -650,10 +650,10 @@ module frr-pim {
|
|||
description
|
||||
"Add multicast route.";
|
||||
|
||||
leaf oif {
|
||||
leaf-list oif {
|
||||
type frr-interface:interface-ref;
|
||||
description
|
||||
"Outgoing interface name.";
|
||||
"List of Outgoing interface names.";
|
||||
}
|
||||
|
||||
leaf source-addr {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue