From f206085e19950fefb3cf76e1c7057aa06e827e13 Mon Sep 17 00:00:00 2001 From: Sarita Patra Date: Fri, 23 Oct 2020 06:58:51 -0700 Subject: [PATCH] pimd: Northbound implementation for ssm prefix-list, ssmpingd command ip_pim_ssm_prefix_list no_ip_pim_ssm_prefix_list no_ip_pim_ssm_prefix_list_name no_ip_ssmpingd ip_ssmpingd Yang Model: augment /frr-routing:routing/frr-routing:control-plane-protocols/frr-routing:control-plane-protocol: +--rw pim +--rw address-family* [address-family] +--rw address-family identityref +--rw ssm-prefix-list? plist-ref +--rw ssm-pingd-source-ip* ietf-inet-types:ip-address Signed-off-by: Sarita Patra --- pimd/pim_cmd.c | 205 +++++++++++++++++++++++++++++-------------- pimd/pim_nb_config.c | 102 +++++++++++++++++++-- 2 files changed, 238 insertions(+), 69 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 609521823c..aeaeefa75c 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7409,30 +7409,6 @@ DEFUN (no_ip_pim_rp_prefix_list, return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg); } -static int pim_ssm_cmd_worker(struct pim_instance *pim, struct vty *vty, - const char *plist) -{ - int result = pim_ssm_range_set(pim, pim->vrf_id, plist); - int ret = CMD_WARNING_CONFIG_FAILED; - - if (result == PIM_SSM_ERR_NONE) - return CMD_SUCCESS; - - switch (result) { - case PIM_SSM_ERR_NO_VRF: - vty_out(vty, "%% VRF doesn't exist\n"); - break; - case PIM_SSM_ERR_DUP: - vty_out(vty, "%% duplicate config\n"); - ret = CMD_WARNING; - break; - default: - vty_out(vty, "%% ssm range config failed\n"); - } - - return ret; -} - DEFUN (ip_pim_ssm_prefix_list, ip_pim_ssm_prefix_list_cmd, "ip pim ssm prefix-list WORD", @@ -7442,8 +7418,31 @@ DEFUN (ip_pim_ssm_prefix_list, "group range prefix-list filter\n" "Name of a prefix-list\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return pim_ssm_cmd_worker(pim, vty, argv[4]->arg); + const struct lyd_node *vrf_dnode; + const char *vrfname; + char ssm_plist_xpath[XPATH_MAXLEN]; + + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath)); + + nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_MODIFY, argv[4]->arg); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_pim_ssm_prefix_list, @@ -7455,8 +7454,31 @@ DEFUN (no_ip_pim_ssm_prefix_list, "Source Specific Multicast\n" "group range prefix-list filter\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return pim_ssm_cmd_worker(pim, vty, NULL); + const struct lyd_node *vrf_dnode; + const char *vrfname; + char ssm_plist_xpath[XPATH_MAXLEN]; + + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath)); + + nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_pim_ssm_prefix_list_name, @@ -7469,11 +7491,50 @@ DEFUN (no_ip_pim_ssm_prefix_list_name, "group range prefix-list filter\n" "Name of a prefix-list\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - struct pim_ssm *ssm = pim->ssm_info; + const struct lyd_node *vrf_dnode; + const char *vrfname; + const struct lyd_node *ssm_plist_dnode; + char ssm_plist_xpath[XPATH_MAXLEN]; + const char *ssm_plist_name; + + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; + + + snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath)); + ssm_plist_dnode = yang_dnode_get(vty->candidate_config->dnode, + ssm_plist_xpath); + + if (!ssm_plist_dnode) { + vty_out(vty, + "%% pim ssm prefix-list %s doesn't exist\n", + argv[5]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + ssm_plist_name = yang_dnode_get_string(ssm_plist_dnode, "."); + + if (ssm_plist_name && !strcmp(ssm_plist_name, argv[5]->arg)) { + nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, + NULL); - if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg)) - return pim_ssm_cmd_worker(pim, vty, NULL); + return nb_cli_apply_changes(vty, NULL); + } vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg); @@ -7602,27 +7663,35 @@ DEFUN (ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); int idx_ipv4 = 2; - int result; - struct in_addr source_addr; const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0"; + const struct lyd_node *vrf_dnode; + const char *vrfname; + char ssmpingd_ip_xpath[XPATH_MAXLEN]; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; - result = pim_ssmpingd_start(pim, source_addr); - if (result) { - vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip", + sizeof(ssmpingd_ip_xpath)); - return CMD_SUCCESS; + nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE, + source_str); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_ssmpingd, @@ -7633,27 +7702,35 @@ DEFUN (no_ip_ssmpingd, CONF_SSMPINGD_STR "Source address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); + const struct lyd_node *vrf_dnode; + const char *vrfname; int idx_ipv4 = 3; - int result; - struct in_addr source_addr; const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0"; + char ssmpingd_ip_xpath[XPATH_MAXLEN]; - result = inet_pton(AF_INET, source_str, &source_addr); - if (result <= 0) { - vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", - source_str, errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + if (vty->xpath_index) { + vrf_dnode = + yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (!vrf_dnode) { + vty_out(vty, + "%% Failed to get vrf dnode in candidate db\n"); + return CMD_WARNING_CONFIG_FAILED; + } + vrfname = yang_dnode_get_string(vrf_dnode, "./name"); + } else + vrfname = VRF_DEFAULT_NAME; - result = pim_ssmpingd_stop(pim, source_addr); - if (result) { - vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n", - source_str, result); - return CMD_WARNING_CONFIG_FAILED; - } + snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip", + sizeof(ssmpingd_ip_xpath)); - return CMD_SUCCESS; + nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_DESTROY, + source_str); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (ip_pim_ecmp, diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index faf492a41f..8eca915c67 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -25,6 +25,8 @@ #include "pim_mlag.h" #include "pim_bfd.h" #include "pim_static.h" +#include "pim_ssm.h" +#include "pim_ssmpingd.h" static void pim_if_membership_clear(struct interface *ifp) { @@ -210,6 +212,32 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim, return NB_OK; } +static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist, + char *errmsg, size_t errmsg_len) +{ + int result = pim_ssm_range_set(pim, pim->vrf_id, plist); + int ret = NB_ERR; + + if (result == PIM_SSM_ERR_NONE) + return NB_OK; + + switch (result) { + case PIM_SSM_ERR_NO_VRF: + snprintf(errmsg, errmsg_len, + "VRF doesn't exist"); + break; + case PIM_SSM_ERR_DUP: + snprintf(errmsg, errmsg_len, + "duplicate config"); + break; + default: + snprintf(errmsg, errmsg_len, + "ssm range config failed"); + } + + return ret; +} + static bool is_pim_interface(const struct lyd_node *dnode) { char if_xpath[XPATH_MAXLEN]; @@ -706,12 +734,26 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_sp */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(struct nb_cb_modify_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *plist_name; + int result; + switch (args->event) { case NB_EV_VALIDATE: case NB_EV_PREPARE: case NB_EV_ABORT: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + plist_name = yang_dnode_get_string(args->dnode, NULL); + result = pim_ssm_cmd_worker(pim, plist_name, args->errmsg, + args->errmsg_len); + + if (result) + return NB_ERR_INCONSISTENCY; + break; } @@ -720,12 +762,24 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(struct nb_cb_destroy_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + int result; + switch (args->event) { case NB_EV_VALIDATE: case NB_EV_PREPARE: case NB_EV_ABORT: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + result = pim_ssm_cmd_worker(pim, NULL, args->errmsg, + args->errmsg_len); + + if (result) + return NB_ERR_INCONSISTENCY; + break; } @@ -737,13 +791,31 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(struct nb_cb_create_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + int result; + struct ipaddr source_addr; + switch (args->event) { case NB_EV_VALIDATE: case NB_EV_PREPARE: case NB_EV_ABORT: - case NB_EV_APPLY: - /* TODO: implement me. */ break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&source_addr, args->dnode, NULL); + result = pim_ssmpingd_start(pim, source_addr.ip._v4_addr); + if (result) { + char source_str[INET_ADDRSTRLEN]; + + ipaddr2str(&source_addr, source_str, + sizeof(source_str)); + snprintf(args->errmsg, args->errmsg_len, + "%% Failure starting ssmpingd for source %s: %d", + source_str, result); + return NB_ERR_INCONSISTENCY; + } } return NB_OK; @@ -751,12 +823,32 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(struct nb_cb_destroy_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + int result; + struct ipaddr source_addr; + switch (args->event) { case NB_EV_VALIDATE: case NB_EV_PREPARE: case NB_EV_ABORT: + break; case NB_EV_APPLY: - /* TODO: implement me. */ + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_ip(&source_addr, args->dnode, NULL); + result = pim_ssmpingd_stop(pim, source_addr.ip._v4_addr); + if (result) { + char source_str[INET_ADDRSTRLEN]; + + ipaddr2str(&source_addr, source_str, + sizeof(source_str)); + snprintf(args->errmsg, args->errmsg_len, + "%% Failure stopping ssmpingd for source %s: %d", + source_str, result); + return NB_ERR_INCONSISTENCY; + } + break; } -- 2.39.5