From 675c8fdef05693a65b61e84b08809d8a341e5369 Mon Sep 17 00:00:00 2001 From: Sarita Patra Date: Fri, 23 Oct 2020 05:59:37 -0700 Subject: [PATCH] pimd: Northbound implementation for mroute, use-source, boundary_oil cmd interface_ip_pim_boundary_oil interface_no_ip_pim_boundary_oil interface_ip_mroute interface_no_ip_mroute interface_pim_use_source interface_no_pim_use_source Yang Model: augment /frr-interface:lib/frr-interface:interface: +--rw pim! +--rw address-family* [address-family] +--rw address-family identityref +--rw use-source? ietf-inet-types:ip-address +--rw multicast-boundary-oil? plist-ref +--rw mroute* [source-addr group-addr] +--rw oif? frr-interface:interface-ref +--rw source-addr ietf-inet-types:ip-address +--rw group-addr ietf-routing-types:ip-multicast-group-address Signed-off-by: Sarita Patra --- pimd/pim_cmd.c | 157 ++++++++----------------------- pimd/pim_nb_config.c | 215 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 240 insertions(+), 132 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a4111f080e..d945fe0266 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -8093,22 +8093,13 @@ DEFUN(interface_ip_pim_boundary_oil, "Filter OIL by group using prefix list\n" "Prefix list to filter OIL with\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - struct pim_interface *pim_ifp; - int idx = 0; - - argv_find(argv, argc, "WORD", &idx); - - PIM_GET_PIM_INTERFACE(pim_ifp, iif); + nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY, + argv[4]->arg); - if (pim_ifp->boundary_oil_plist) - XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']", + "frr-routing:ipv4"); - pim_ifp->boundary_oil_plist = - XSTRDUP(MTYPE_PIM_INTERFACE, argv[idx]->arg); - - /* Interface will be pruned from OIL on next Join */ - return CMD_SUCCESS; } DEFUN(interface_no_ip_pim_boundary_oil, @@ -8121,18 +8112,12 @@ DEFUN(interface_no_ip_pim_boundary_oil, "Filter OIL by group using prefix list\n" "Prefix list to filter OIL with\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - struct pim_interface *pim_ifp; - int idx = 0; - - argv_find(argv, argc, "WORD", &idx); - - PIM_GET_PIM_INTERFACE(pim_ifp, iif); + nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY, + NULL); - if (pim_ifp->boundary_oil_plist) - XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); - - return CMD_SUCCESS; + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']", + "frr-routing:ipv4"); } DEFUN (interface_ip_mroute, @@ -8144,56 +8129,21 @@ DEFUN (interface_ip_mroute, "Group address\n" "Source address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - struct pim_interface *pim_ifp; - struct pim_instance *pim; int idx_interface = 2; int idx_ipv4 = 3; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - PIM_GET_PIM_INTERFACE(pim_ifp, iif); - pim = pim_ifp->pim; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, pim->vrf_id); - if (!oif) { - vty_out(vty, "No such interface name %s\n", oifname); - return CMD_WARNING; - } + const char *source_str; - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } + if (argc == (idx_ipv4 + 1)) + source_str = "0.0.0.0"; + else + source_str = argv[idx_ipv4 + 1]->arg; - if (argc == (idx_ipv4 + 1)) { - src_addr.s_addr = INADDR_ANY; - } - else { - src_str = argv[idx_ipv4 + 1]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } - } - - if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) { - vty_out(vty, "Failed to add static mroute\n"); - return CMD_WARNING; - } + nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY, + argv[idx_interface]->arg); - return CMD_SUCCESS; + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']", + "frr-routing:ipv4", source_str, argv[idx_ipv4]->arg); } DEFUN (interface_no_ip_mroute, @@ -8206,56 +8156,19 @@ DEFUN (interface_no_ip_mroute, "Group Address\n" "Source Address\n") { - VTY_DECLVAR_CONTEXT(interface, iif); - struct pim_interface *pim_ifp; - struct pim_instance *pim; - int idx_interface = 3; int idx_ipv4 = 4; - struct interface *oif; - const char *oifname; - const char *grp_str; - struct in_addr grp_addr; - const char *src_str; - struct in_addr src_addr; - int result; - - PIM_GET_PIM_INTERFACE(pim_ifp, iif); - pim = pim_ifp->pim; - - oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname, pim->vrf_id); - if (!oif) { - vty_out(vty, "No such interface name %s\n", oifname); - return CMD_WARNING; - } + const char *source_str; - grp_str = argv[idx_ipv4]->arg; - result = inet_pton(AF_INET, grp_str, &grp_addr); - if (result <= 0) { - vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } + if (argc == (idx_ipv4 + 1)) + source_str = "0.0.0.0"; + else + source_str = argv[idx_ipv4 + 1]->arg; - if (argc == (idx_ipv4 + 1)) { - src_addr.s_addr = INADDR_ANY; - } - else { - src_str = argv[idx_ipv4 + 1]->arg; - result = inet_pton(AF_INET, src_str, &src_addr); - if (result <= 0) { - vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str, - errno, safe_strerror(errno)); - return CMD_WARNING; - } - } - - if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) { - vty_out(vty, "Failed to remove static mroute\n"); - return CMD_WARNING; - } + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - return CMD_SUCCESS; + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']", + "frr-routing:ipv4", source_str, argv[idx_ipv4]->arg); } DEFUN (interface_ip_pim_hello, @@ -8957,7 +8870,11 @@ DEFUN (interface_pim_use_source, "Configure primary IP address\n" "source ip address\n") { - return interface_pim_use_src_cmd_worker(vty, argv[3]->arg); + nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, argv[3]->arg); + + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']", + "frr-routing:ipv4"); } DEFUN (interface_no_pim_use_source, @@ -8969,7 +8886,11 @@ DEFUN (interface_no_pim_use_source, "Delete source IP address\n" "source ip address\n") { - return interface_pim_use_src_cmd_worker(vty, "0.0.0.0"); + nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, "0.0.0.0"); + + return nb_cli_apply_changes(vty, + "./frr-pim:pim/address-family[address-family='%s']", + "frr-routing:ipv4"); } DEFUN (ip_pim_bfd, diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index ef949d954a..68111dc1e3 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -24,6 +24,7 @@ #include "pim_pim.h" #include "pim_mlag.h" #include "pim_bfd.h" +#include "pim_static.h" static void pim_if_membership_clear(struct interface *ifp) { @@ -154,6 +155,36 @@ static int pim_cmd_interface_delete(struct interface *ifp) return 1; } +static int interface_pim_use_src_cmd_worker(struct interface *ifp, + struct in_addr source_addr, + char *errmsg, size_t errmsg_len) +{ + int result; + int ret = NB_OK; + + result = pim_update_source_set(ifp, source_addr); + + switch (result) { + case PIM_SUCCESS: + break; + case PIM_IFACE_NOT_FOUND: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "Pim not enabled on this interface %s", + ifp->name); + break; + case PIM_UPDATE_SOURCE_DUP: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, "Source already set"); + break; + default: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, "Source set failed"); + } + + return ret; +} + static bool is_pim_interface(const struct lyd_node *dnode) { char if_xpath[XPATH_MAXLEN]; @@ -1413,7 +1444,6 @@ int lib_interface_pim_address_family_create(struct nb_cb_create_args *args) case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -1427,7 +1457,6 @@ int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args) case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -1439,12 +1468,34 @@ int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args) */ int lib_interface_pim_address_family_use_source_modify(struct nb_cb_modify_args *args) { + struct interface *ifp; + struct ipaddr source_addr; + int result; + const struct lyd_node *if_dnode; + switch (args->event) { case NB_EV_VALIDATE: - case NB_EV_PREPARE: + if_dnode = yang_dnode_get_parent(args->dnode, "interface"); + if (!is_pim_interface(if_dnode)) { + snprintf(args->errmsg, args->errmsg_len, + "Pim not enabled on this interface"); + return NB_ERR_VALIDATION; + } + break; case NB_EV_ABORT: + case NB_EV_PREPARE: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + ifp = nb_running_get_entry(args->dnode, NULL, true); + yang_dnode_get_ip(&source_addr, args->dnode, NULL); + + result = interface_pim_use_src_cmd_worker( + ifp, source_addr.ip._v4_addr, + args->errmsg, args->errmsg_len); + + if (result != PIM_SUCCESS) + return NB_ERR_INCONSISTENCY; + break; } @@ -1453,12 +1504,33 @@ int lib_interface_pim_address_family_use_source_modify(struct nb_cb_modify_args int lib_interface_pim_address_family_use_source_destroy(struct nb_cb_destroy_args *args) { + struct interface *ifp; + struct in_addr source_addr = {INADDR_ANY}; + int result; + const struct lyd_node *if_dnode; + switch (args->event) { case NB_EV_VALIDATE: - case NB_EV_PREPARE: + if_dnode = yang_dnode_get_parent(args->dnode, "interface"); + if (!is_pim_interface(if_dnode)) { + snprintf(args->errmsg, args->errmsg_len, + "Pim not enabled on this interface"); + return NB_ERR_VALIDATION; + } + break; case NB_EV_ABORT: + case NB_EV_PREPARE: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + ifp = nb_running_get_entry(args->dnode, NULL, true); + + result = interface_pim_use_src_cmd_worker(ifp, source_addr, + args->errmsg, + args->errmsg_len); + + if (result != PIM_SUCCESS) + return NB_ERR_INCONSISTENCY; + break; } @@ -1470,12 +1542,34 @@ int lib_interface_pim_address_family_use_source_destroy(struct nb_cb_destroy_arg */ int lib_interface_pim_address_family_multicast_boundary_oil_modify(struct nb_cb_modify_args *args) { + struct interface *ifp; + struct pim_interface *pim_ifp; + const char *plist; + const struct lyd_node *if_dnode; + switch (args->event) { case NB_EV_VALIDATE: - case NB_EV_PREPARE: + if_dnode = yang_dnode_get_parent(args->dnode, "interface"); + if (!is_pim_interface(if_dnode)) { + snprintf(args->errmsg, args->errmsg_len, + "Pim not enabled on this interface"); + return NB_ERR_VALIDATION; + } + break; case NB_EV_ABORT: + case NB_EV_PREPARE: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + ifp = nb_running_get_entry(args->dnode, NULL, true); + pim_ifp = ifp->info; + plist = yang_dnode_get_string(args->dnode, NULL); + + if (pim_ifp->boundary_oil_plist) + XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); + + pim_ifp->boundary_oil_plist = + XSTRDUP(MTYPE_PIM_INTERFACE, plist); + break; } @@ -1484,12 +1578,27 @@ int lib_interface_pim_address_family_multicast_boundary_oil_modify(struct nb_cb_ int lib_interface_pim_address_family_multicast_boundary_oil_destroy(struct nb_cb_destroy_args *args) { + struct interface *ifp; + struct pim_interface *pim_ifp; + const struct lyd_node *if_dnode; + switch (args->event) { case NB_EV_VALIDATE: - case NB_EV_PREPARE: + 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_ABORT: + case NB_EV_PREPARE: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + ifp = nb_running_get_entry(args->dnode, NULL, true); + pim_ifp = ifp->info; + if (pim_ifp->boundary_oil_plist) + XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist); break; } @@ -1506,7 +1615,6 @@ int lib_interface_pim_address_family_mroute_create(struct nb_cb_create_args *arg case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -1515,12 +1623,52 @@ int lib_interface_pim_address_family_mroute_create(struct nb_cb_create_args *arg 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; + struct ipaddr source_addr; + struct ipaddr 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: - /* TODO: implement me. */ + 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_id); + + if (!oif) { + snprintf(args->errmsg, args->errmsg_len, + "No such interface name %s", + oifname); + return NB_ERR_INCONSISTENCY; + } + + yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr"); + yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr"); + + if (pim_static_del(pim, iif, oif, group_addr.ip._v4_addr, + source_addr.ip._v4_addr)) { + snprintf(args->errmsg, args->errmsg_len, + "Failed to remove static mroute"); + return NB_ERR_INCONSISTENCY; + } + break; } @@ -1532,12 +1680,52 @@ int lib_interface_pim_address_family_mroute_destroy(struct nb_cb_destroy_args *a */ int lib_interface_pim_address_family_mroute_oif_modify(struct nb_cb_modify_args *args) { + struct pim_instance *pim; + struct pim_interface *pim_iifp; + struct interface *iif; + struct interface *oif; + const char *oifname; + struct ipaddr source_addr; + struct ipaddr 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: - /* TODO: implement me. */ + iif = nb_running_get_entry(args->dnode, NULL, true); + pim_iifp = iif->info; + pim = pim_iifp->pim; + + oifname = yang_dnode_get_string(args->dnode, NULL); + oif = if_lookup_by_name(oifname, pim->vrf_id); + + if (!oif) { + snprintf(args->errmsg, args->errmsg_len, + "No such interface name %s", + oifname); + return NB_ERR_INCONSISTENCY; + } + + yang_dnode_get_ip(&source_addr, args->dnode, "../source-addr"); + yang_dnode_get_ip(&group_addr, args->dnode, "../group-addr"); + + if (pim_static_add(pim, iif, oif, group_addr.ip._v4_addr, + source_addr.ip._v4_addr)) { + snprintf(args->errmsg, args->errmsg_len, + "Failed to add static mroute"); + return NB_ERR_INCONSISTENCY; + } + break; } @@ -1551,7 +1739,6 @@ int lib_interface_pim_address_family_mroute_oif_destroy(struct nb_cb_destroy_arg case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } -- 2.39.5