Skip to content

Commit b4ceac2

Browse files
committed
pimd: added support for multi-oif static mroute
Signed-off-by: e-wing <[email protected]>
1 parent 8c11cc5 commit b4ceac2

File tree

6 files changed

+119
-13
lines changed

6 files changed

+119
-13
lines changed

pimd/pim_cmd_common.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,12 @@ int pim_process_ip_gmp_proxy_cmd(struct vty *vty, bool enable)
468468
int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
469469
const char *group_str, const char *source_str)
470470
{
471-
nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, interface);
471+
/* managing list of oif regarding (iif,mcast group, mcast source)*/
472+
char xpath[XPATH_MAXLEN];
473+
474+
snprintf(xpath, sizeof(xpath), "./oif[.='%s']", interface);
475+
476+
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
472477

473478
if (!source_str) {
474479
char buf[SRCDEST2STR_BUFFER];
@@ -487,15 +492,20 @@ int pim_process_ip_mroute_cmd(struct vty *vty, const char *interface,
487492
int pim_process_no_ip_mroute_cmd(struct vty *vty, const char *interface,
488493
const char *group_str, const char *source_str)
489494
{
490-
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
495+
/* managing list of oif regarding (iif,mcast group, mcast source)*/
496+
char xpath[XPATH_MAXLEN];
497+
498+
snprintf(xpath, sizeof(xpath), "./oif[.='%s']", interface);
499+
500+
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
491501

492502
if (!source_str) {
493503
char buf[SRCDEST2STR_BUFFER];
494504

495505
inet_ntop(AF_INET6, &in6addr_any, buf, sizeof(buf));
496506
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,
497-
FRR_PIM_AF_XPATH_VAL, buf,
498-
group_str);
507+
FRR_PIM_AF_XPATH_VAL, buf,
508+
group_str);
499509
}
500510

501511
return nb_cli_apply_changes(vty, FRR_PIM_MROUTE_XPATH,

pimd/pim_nb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,13 @@ const struct frr_yang_module_info frr_pim_info = {
418418
.xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute",
419419
.cbs = {
420420
.create = lib_interface_pim_address_family_mroute_create,
421-
.destroy = lib_interface_pim_address_family_mroute_destroy,
421+
.destroy = lib_interface_pim_address_family_mroute_oif_destroy,
422422
}
423423
},
424424
{
425425
.xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif",
426426
.cbs = {
427-
.modify = lib_interface_pim_address_family_mroute_oif_modify,
427+
.create = lib_interface_pim_address_family_mroute_oif_create,
428428
.destroy = lib_interface_pim_address_family_mroute_oif_destroy,
429429
}
430430
},

pimd/pim_nb.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ int lib_interface_pim_address_family_mroute_create(
166166
struct nb_cb_create_args *args);
167167
int lib_interface_pim_address_family_mroute_destroy(
168168
struct nb_cb_destroy_args *args);
169-
int lib_interface_pim_address_family_mroute_oif_modify(
170-
struct nb_cb_modify_args *args);
169+
int lib_interface_pim_address_family_mroute_oif_create(
170+
struct nb_cb_create_args *args);
171171
int lib_interface_pim_address_family_mroute_oif_destroy(
172172
struct nb_cb_destroy_args *args);
173173

pimd/pim_nb_config.c

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,8 +2960,8 @@ int lib_interface_pim_address_family_mroute_destroy(
29602960
/*
29612961
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
29622962
*/
2963-
int lib_interface_pim_address_family_mroute_oif_modify(
2964-
struct nb_cb_modify_args *args)
2963+
int lib_interface_pim_address_family_mroute_oif_create(
2964+
struct nb_cb_create_args *args)
29652965
{
29662966
struct pim_instance *pim;
29672967
struct pim_interface *pim_iifp;
@@ -3004,7 +3004,16 @@ int lib_interface_pim_address_family_mroute_oif_modify(
30043004
case NB_EV_ABORT:
30053005
break;
30063006
case NB_EV_APPLY:
3007-
iif = nb_running_get_entry(args->dnode, NULL, true);
3007+
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
3008+
if (!if_dnode) {
3009+
snprintf(args->errmsg, args->errmsg_len,
3010+
"%% Enable PIM and/or IGMP on this interface first");
3011+
return NB_ERR_INCONSISTENCY;
3012+
}
3013+
iif = nb_running_get_entry(if_dnode, NULL, true);
3014+
if (!iif)
3015+
return NB_ERR_INCONSISTENCY;
3016+
30083017
pim_iifp = iif->info;
30093018
pim = pim_iifp->pim;
30103019

@@ -3035,11 +3044,59 @@ int lib_interface_pim_address_family_mroute_oif_modify(
30353044
int lib_interface_pim_address_family_mroute_oif_destroy(
30363045
struct nb_cb_destroy_args *args)
30373046
{
3047+
struct pim_instance *pim;
3048+
struct pim_interface *pim_iifp;
3049+
struct interface *iif;
3050+
struct interface *oif;
3051+
const char *oifname;
3052+
pim_addr source_addr;
3053+
pim_addr group_addr;
3054+
const struct lyd_node *if_dnode;
3055+
30383056
switch (args->event) {
30393057
case NB_EV_VALIDATE:
3058+
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
3059+
if (!is_pim_interface(if_dnode)) {
3060+
snprintf(args->errmsg, args->errmsg_len,
3061+
"%% Enable PIM and/or IGMP on this interface first");
3062+
return NB_ERR_VALIDATION;
3063+
}
3064+
break;
30403065
case NB_EV_PREPARE:
30413066
case NB_EV_ABORT:
3067+
break;
30423068
case NB_EV_APPLY:
3069+
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
3070+
if (!if_dnode) {
3071+
snprintf(args->errmsg, args->errmsg_len,
3072+
"%% Enable PIM and/or IGMP on this interface first");
3073+
return NB_ERR_INCONSISTENCY;
3074+
}
3075+
iif = nb_running_get_entry(if_dnode, NULL, true);
3076+
if (!iif)
3077+
return NB_ERR_INCONSISTENCY;
3078+
3079+
3080+
pim_iifp = iif->info;
3081+
pim = pim_iifp->pim;
3082+
3083+
oifname = yang_dnode_get_string(args->dnode, NULL);
3084+
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
3085+
if (!oif) {
3086+
snprintf(args->errmsg, args->errmsg_len,
3087+
"No such interface name %s",
3088+
oifname);
3089+
return NB_ERR_INCONSISTENCY;
3090+
}
3091+
3092+
yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
3093+
yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
3094+
3095+
if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
3096+
snprintf(args->errmsg, args->errmsg_len,
3097+
"Failed to del static mroute");
3098+
return NB_ERR_INCONSISTENCY;
3099+
}
30433100
break;
30443101
}
30453102

tests/topotests/pim_basic/test_pim.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,45 @@ def test_memory_leak():
247247
tgen.report_memory_leaks()
248248

249249

250+
def test_pim_static_mroute():
251+
"Test Static routes add/remove cycle"
252+
logger.info("Testing static routes")
253+
254+
tgen = get_topogen()
255+
256+
if tgen.routers_have_failure():
257+
pytest.skip(tgen.errors)
258+
259+
r1 = tgen.gears["r1"]
260+
261+
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
262+
assert "239.1.1.1" not in ip_mroute_json.keys()
263+
264+
# Add ip mroute with iif=r1-eth0 oil=r1-eth1
265+
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip mroute r1-eth1 239.1.1.1 10.0.0.1")
266+
267+
# Expect to find oil=[r1-eth1] in ip mroute command
268+
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
269+
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == ['r1-eth1']
270+
271+
# Add ip mroute with iif=r1-eth0 oil=r1-eth2
272+
r1.vtysh_cmd("conf t\ninterface r1-eth0\nip mroute r1-eth2 239.1.1.1 10.0.0.1")
273+
274+
# Expect to find oil=[r1-eth1,r1-eth2] in ip mroute command
275+
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
276+
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == ['r1-eth1', 'r1-eth2']
277+
278+
# Remove ip mroute with oil=r1-eth1
279+
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip mroute r1-eth1 239.1.1.1 10.0.0.1")
280+
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
281+
# This assert right here would break back in the day because only one oif was handled by the datamodel
282+
assert list(ip_mroute_json["239.1.1.1"]["10.0.0.1"]["oil"].keys()) == ['r1-eth2']
283+
284+
r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip mroute r1-eth2 239.1.1.1 10.0.0.1")
285+
# Expect a clean state
286+
ip_mroute_json = r1.vtysh_cmd("show ip mroute json", isjson=True)
287+
assert "239.1.1.1" not in ip_mroute_json.keys()
288+
250289
if __name__ == "__main__":
251290
args = ["-s"] + sys.argv[1:]
252291
sys.exit(pytest.main(args))

yang/frr-pim.yang

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,10 +650,10 @@ module frr-pim {
650650
description
651651
"Add multicast route.";
652652

653-
leaf oif {
653+
leaf-list oif {
654654
type frr-interface:interface-ref;
655655
description
656-
"Outgoing interface name.";
656+
"List of Outgoing interface names.";
657657
}
658658

659659
leaf source-addr {

0 commit comments

Comments
 (0)