diff --git a/lib/yang.c b/lib/yang.c index 5bf7758e18..b4902aef22 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -790,8 +790,7 @@ const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode, return NULL; } -/* API to check if the given node is last node in the list */ -static bool yang_is_last_list_dnode(const struct lyd_node *dnode) +bool yang_is_last_list_dnode(const struct lyd_node *dnode) { return (((dnode->next == NULL) || (dnode->next @@ -803,8 +802,7 @@ static bool yang_is_last_list_dnode(const struct lyd_node *dnode) != 0))); } -/* API to check if the given node is last node in the data tree level */ -static bool yang_is_last_level_dnode(const struct lyd_node *dnode) +bool yang_is_last_level_dnode(const struct lyd_node *dnode) { const struct lyd_node *parent; const struct lys_node_list *snode; diff --git a/lib/yang.h b/lib/yang.h index 867ade9676..6e593883b9 100644 --- a/lib/yang.h +++ b/lib/yang.h @@ -605,6 +605,11 @@ extern uint32_t yang_get_list_elements_count(const struct lyd_node *node); /* To get the immediate child of a dnode */ const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode); +/* API to check if the given node is last node in the list */ +bool yang_is_last_list_dnode(const struct lyd_node *dnode); + +/* API to check if the given node is last node in the data tree level */ +bool yang_is_last_level_dnode(const struct lyd_node *dnode); #ifdef __cplusplus } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index aeaeefa75c..941bfbc81f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -9553,53 +9553,6 @@ ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd, "Desired min transmit interval\n") #endif /* !HAVE_BFDD */ -static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, - const char *peer, const char *local) -{ - enum pim_msdp_err result; - struct in_addr peer_addr; - struct in_addr local_addr; - int ret = CMD_SUCCESS; - - result = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = inet_pton(AF_INET, local, &local_addr); - if (result <= 0) { - vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default", - NULL /* mp_p */); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_PEER_EXISTS: - ret = CMD_WARNING; - vty_out(vty, "%% Peer exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% peer add failed\n"); - } - - return ret; -} - DEFUN (ip_msdp_peer, ip_msdp_peer_cmd, "ip msdp peer A.B.C.D source A.B.C.D", @@ -9610,35 +9563,37 @@ DEFUN (ip_msdp_peer, "Source address for TCP connection\n" "local ip address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg); -} + const struct lyd_node *vrf_dnode; + const char *vrfname; + char temp_xpath[XPATH_MAXLEN]; + char msdp_peer_source_xpath[XPATH_MAXLEN]; -static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, - const char *peer) -{ - enum pim_msdp_err result; - struct in_addr peer_addr; + 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 = inet_pton(AF_INET, peer, &peer_addr); - if (result <= 0) { - vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + snprintf(temp_xpath, sizeof(temp_xpath), + "/msdp-peer[peer-ip='%s']/source-ip", + argv[3]->arg); + strlcat(msdp_peer_source_xpath, temp_xpath, + sizeof(msdp_peer_source_xpath)); - result = pim_msdp_peer_del(pim, peer_addr); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_PEER: - vty_out(vty, "%% Peer does not exist\n"); - break; - default: - vty_out(vty, "%% peer del failed\n"); - } + nb_cli_enqueue_change(vty, msdp_peer_source_xpath, NB_OP_MODIFY, + argv[5]->arg); - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_msdp_peer, @@ -9650,47 +9605,36 @@ DEFUN (no_ip_msdp_peer, "Delete MSDP peer\n" "peer ip address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg); -} + const struct lyd_node *vrf_dnode; + const char *vrfname; + char msdp_peer_xpath[XPATH_MAXLEN]; + char temp_xpath[XPATH_MAXLEN]; -static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, - struct vty *vty, const char *mg, - const char *mbr) -{ - enum pim_msdp_err result; - struct in_addr mbr_ip; - int ret = CMD_SUCCESS; + 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 = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } + snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + snprintf(temp_xpath, sizeof(temp_xpath), + "/msdp-peer[peer-ip='%s']", + argv[4]->arg); - result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MG_MBR_EXISTS: - ret = CMD_WARNING; - vty_out(vty, "%% mesh-group member exists\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - ret = CMD_WARNING_CONFIG_FAILED; - vty_out(vty, "%% member add failed\n"); - } + strlcat(msdp_peer_xpath, temp_xpath, sizeof(msdp_peer_xpath)); - return ret; + nb_cli_enqueue_change(vty, msdp_peer_xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); } DEFUN (ip_msdp_mesh_group_member, @@ -9703,42 +9647,44 @@ DEFUN (ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg, - argv[5]->arg); + const struct lyd_node *vrf_dnode; + const char *vrfname; + char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; + char msdp_mesh_group_member_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(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name", + sizeof(msdp_mesh_group_name_xpath)); + snprintf(msdp_mesh_group_member_xpath, + sizeof(msdp_mesh_group_member_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_group_member_xpath, "/msdp-mesh-group/member-ip", + sizeof(msdp_mesh_group_member_xpath)); + + nb_cli_enqueue_change(vty, msdp_mesh_group_name_xpath, NB_OP_MODIFY, + argv[3]->arg); + nb_cli_enqueue_change(vty, msdp_mesh_group_member_xpath, NB_OP_CREATE, + argv[5]->arg); + + return nb_cli_apply_changes(vty, NULL); } -static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, - struct vty *vty, - const char *mg, - const char *mbr) -{ - enum pim_msdp_err result; - struct in_addr mbr_ip; - - result = inet_pton(AF_INET, mbr, &mbr_ip); - if (result <= 0) { - vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; - } - - result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out(vty, "%% mesh-group does not exist\n"); - break; - case PIM_MSDP_ERR_NO_MG_MBR: - vty_out(vty, "%% mesh-group member does not exist\n"); - break; - default: - vty_out(vty, "%% mesh-group member del failed\n"); - } - - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; -} DEFUN (no_ip_msdp_mesh_group_member, no_ip_msdp_mesh_group_member_cmd, "no ip msdp mesh-group WORD member A.B.C.D", @@ -9750,42 +9696,89 @@ DEFUN (no_ip_msdp_mesh_group_member, "mesh group member\n" "peer ip address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg, - argv[6]->arg); -} + const struct lyd_node *vrf_dnode; + const char *vrfname; + char temp_xpath[XPATH_MAXLEN]; + char mesh_group_xpath[XPATH_MAXLEN]; + char group_member_xpath[XPATH_MAXLEN]; + char source_xpath[XPATH_MAXLEN]; + char mesh_group_name_xpath[XPATH_MAXLEN]; + const char *mesh_group_name; + const struct lyd_node *member_dnode; -static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim, - struct vty *vty, const char *mg, - const char *src) -{ - enum pim_msdp_err result; - struct in_addr src_ip; + 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 = inet_pton(AF_INET, src, &src_ip); - if (result <= 0) { - vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src, - errno, safe_strerror(errno)); - return CMD_WARNING_CONFIG_FAILED; + snprintf(mesh_group_xpath, sizeof(mesh_group_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(mesh_group_xpath, "/msdp-mesh-group", sizeof(mesh_group_xpath)); + + snprintf(group_member_xpath, sizeof(group_member_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + snprintf(temp_xpath, sizeof(temp_xpath), + "/msdp-mesh-group/member-ip[.='%s']", argv[6]->arg); + strlcat(group_member_xpath, temp_xpath, sizeof(group_member_xpath)); + + snprintf(source_xpath, sizeof(source_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + snprintf(temp_xpath, sizeof(temp_xpath), + "/msdp-mesh-group/source-ip"); + strlcat(source_xpath, temp_xpath, sizeof(source_xpath)); + + snprintf(mesh_group_name_xpath, sizeof(mesh_group_name_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name", + sizeof(mesh_group_name_xpath)); + + if (yang_dnode_exists(running_config->dnode, mesh_group_name_xpath) + == true) { + mesh_group_name = yang_dnode_get_string(running_config->dnode, + mesh_group_name_xpath); + if (strcmp(mesh_group_name, argv[4]->arg)) { + vty_out(vty, "%% mesh-group does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - result = pim_msdp_mg_src_add(pim, mg, src_ip); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_OOM: - vty_out(vty, "%% Out of memory\n"); - break; - case PIM_MSDP_ERR_MAX_MESH_GROUPS: - vty_out(vty, "%% Only one mesh-group allowed currently\n"); - break; - default: - vty_out(vty, "%% source add failed\n"); + if (yang_dnode_exists(vty->candidate_config->dnode, + group_member_xpath)) { + if (!yang_dnode_exists(vty->candidate_config->dnode, + source_xpath)) { + member_dnode = yang_dnode_get( + vty->candidate_config->dnode, + group_member_xpath); + if (yang_is_last_list_dnode(member_dnode)) { + nb_cli_enqueue_change(vty, mesh_group_xpath, + NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + nb_cli_enqueue_change(vty, group_member_xpath, + NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); + } + nb_cli_enqueue_change(vty, group_member_xpath, + NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; -} + vty_out(vty, "%% mesh-group member does not exist\n"); + return CMD_SUCCESS; +} DEFUN (ip_msdp_mesh_group_source, ip_msdp_mesh_group_source_cmd, @@ -9797,48 +9790,42 @@ DEFUN (ip_msdp_mesh_group_source, "mesh group local address\n" "source ip address for the TCP connection\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); - return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg, - argv[5]->arg); -} + const struct lyd_node *vrf_dnode; + const char *vrfname; + char msdp_mesh_source_ip_xpath[XPATH_MAXLEN]; + char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; -static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim, - struct vty *vty, - const char *mg) -{ - enum pim_msdp_err result; + 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_msdp_mg_src_del(pim, mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out(vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out(vty, "%% mesh-group source del failed\n"); - } + snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name", + sizeof(msdp_mesh_group_name_xpath)); - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; -} + snprintf(msdp_mesh_source_ip_xpath, sizeof(msdp_mesh_source_ip_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_source_ip_xpath, "/msdp-mesh-group/source-ip", + sizeof(msdp_mesh_source_ip_xpath)); -static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim, - struct vty *vty, const char *mg) -{ - enum pim_msdp_err result; + nb_cli_enqueue_change(vty, msdp_mesh_group_name_xpath, NB_OP_MODIFY, + argv[3]->arg); + nb_cli_enqueue_change(vty, msdp_mesh_source_ip_xpath, NB_OP_MODIFY, + argv[5]->arg); - result = pim_msdp_mg_del(pim, mg); - switch (result) { - case PIM_MSDP_ERR_NONE: - break; - case PIM_MSDP_ERR_NO_MG: - vty_out(vty, "%% mesh-group does not exist\n"); - break; - default: - vty_out(vty, "%% mesh-group source del failed\n"); - } - - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_msdp_mesh_group_source, @@ -9852,9 +9839,69 @@ DEFUN (no_ip_msdp_mesh_group_source, "mesh group source\n" "mesh group local address\n") { - PIM_DECLVAR_CONTEXT(vrf, pim); + const struct lyd_node *vrf_dnode; + const char *vrfname; + char msdp_mesh_xpath[XPATH_MAXLEN]; + char source_xpath[XPATH_MAXLEN]; + char group_member_xpath[XPATH_MAXLEN]; + char mesh_group_name_xpath[XPATH_MAXLEN]; + const char *mesh_group_name; - return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty, argv[4]->arg); + 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(msdp_mesh_xpath, sizeof(msdp_mesh_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_xpath, "/msdp-mesh-group", sizeof(msdp_mesh_xpath)); + + snprintf(source_xpath, sizeof(source_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(source_xpath, "/msdp-mesh-group/source-ip", + sizeof(source_xpath)); + + snprintf(group_member_xpath, + sizeof(group_member_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(group_member_xpath, "/msdp-mesh-group/member-ip", + sizeof(group_member_xpath)); + + snprintf(mesh_group_name_xpath, sizeof(mesh_group_name_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name", + sizeof(mesh_group_name_xpath)); + + if (yang_dnode_exists(running_config->dnode, mesh_group_name_xpath) + == true) { + mesh_group_name = yang_dnode_get_string(running_config->dnode, + mesh_group_name_xpath); + if (strcmp(mesh_group_name, argv[4]->arg)) { + vty_out(vty, "%% mesh-group does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if (!yang_dnode_exists(vty->candidate_config->dnode, + group_member_xpath)) { + nb_cli_enqueue_change(vty, msdp_mesh_xpath, NB_OP_DESTROY, + NULL); + return nb_cli_apply_changes(vty, NULL); + } + nb_cli_enqueue_change(vty, source_xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); } DEFUN (no_ip_msdp_mesh_group, @@ -9866,12 +9913,50 @@ DEFUN (no_ip_msdp_mesh_group, "Delete MSDP mesh-group\n" "mesh group name") { - PIM_DECLVAR_CONTEXT(vrf, pim); + const struct lyd_node *vrf_dnode; + const char *vrfname; + const char *mesh_group_name; + char xpath[XPATH_MAXLEN]; + char msdp_mesh_xpath[XPATH_MAXLEN]; - if (argc == 5) - return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[4]->arg); - else - return ip_no_msdp_mesh_group_cmd_worker(pim, vty, NULL); + 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; + + if (argc == 5) { + snprintf(xpath, sizeof(xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd", + "pim", vrfname, "frr-routing:ipv4"); + strlcat(xpath, "/msdp-mesh-group/mesh-group-name", + sizeof(xpath)); + + if (yang_dnode_exists(running_config->dnode, xpath) == true) { + mesh_group_name = + yang_dnode_get_string(running_config->dnode, + xpath); + + if (strcmp(mesh_group_name, argv[4]->arg)) { + vty_out(vty, "%% mesh-group does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + + snprintf(msdp_mesh_xpath, sizeof(msdp_mesh_xpath), + FRR_PIM_AF_XPATH, + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + strlcat(msdp_mesh_xpath, "/msdp-mesh-group", sizeof(msdp_mesh_xpath)); + + nb_cli_enqueue_change(vty, msdp_mesh_xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); } static void print_empty_json_obj(struct vty *vty) diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 8eca915c67..3b36be5e5e 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -238,6 +238,207 @@ static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist, return ret; } +static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim, + const char *mg, + char *errmsg, size_t errmsg_len) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_del(pim, mg); + + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + snprintf(errmsg, errmsg_len, + "%% mesh-group does not exist"); + break; + default: + snprintf(errmsg, errmsg_len, + "mesh-group source del failed"); + } + + return result ? NB_ERR : NB_OK; +} + +static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, + const char *mg, + struct in_addr mbr_ip, + char *errmsg, size_t errmsg_len) +{ + enum pim_msdp_err result; + int ret = NB_OK; + + result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip); + + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% Out of memory"); + break; + case PIM_MSDP_ERR_MG_MBR_EXISTS: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% mesh-group member exists"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% Only one mesh-group allowed currently"); + break; + default: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% member add failed"); + } + + return ret; +} + +static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, + const char *mg, + struct in_addr mbr_ip, + char *errmsg, + size_t errmsg_len) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip); + + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + snprintf(errmsg, errmsg_len, + "%% mesh-group does not exist"); + break; + case PIM_MSDP_ERR_NO_MG_MBR: + snprintf(errmsg, errmsg_len, + "%% mesh-group member does not exist"); + break; + default: + snprintf(errmsg, errmsg_len, + "%% mesh-group member del failed"); + } + + return result ? NB_ERR : NB_OK; +} + +static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim, + const char *mg, + struct in_addr src_ip, + char *errmsg, size_t errmsg_len) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_src_add(pim, mg, src_ip); + + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + snprintf(errmsg, errmsg_len, + "%% Out of memory"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + snprintf(errmsg, errmsg_len, + "%% Only one mesh-group allowed currently"); + break; + default: + snprintf(errmsg, errmsg_len, + "%% source add failed"); + } + + return result ? NB_ERR : NB_OK; +} + +static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim, + const char *mg, + char *errmsg, + size_t errmsg_len) +{ + enum pim_msdp_err result; + + result = pim_msdp_mg_src_del(pim, mg); + + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_MG: + snprintf(errmsg, errmsg_len, + "%% mesh-group does not exist"); + break; + default: + snprintf(errmsg, errmsg_len, + "%% mesh-group source del failed"); + } + + return result ? NB_ERR : NB_OK; +} + +static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, + struct in_addr peer_addr, + struct in_addr local_addr, + char *errmsg, size_t errmsg_len) +{ + enum pim_msdp_err result; + int ret = NB_OK; + + result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default", + NULL /* mp_p */); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_OOM: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% Out of memory"); + break; + case PIM_MSDP_ERR_PEER_EXISTS: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% Peer exists"); + break; + case PIM_MSDP_ERR_MAX_MESH_GROUPS: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% Only one mesh-group allowed currently"); + break; + default: + ret = NB_ERR; + snprintf(errmsg, errmsg_len, + "%% peer add failed"); + } + + return ret; +} + +static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, + struct in_addr peer_addr, + char *errmsg, size_t errmsg_len) +{ + enum pim_msdp_err result; + + result = pim_msdp_peer_del(pim, peer_addr); + switch (result) { + case PIM_MSDP_ERR_NONE: + break; + case PIM_MSDP_ERR_NO_PEER: + snprintf(errmsg, errmsg_len, + "%% Peer does not exist"); + break; + default: + snprintf(errmsg, errmsg_len, + "%% peer del failed"); + } + + return result ? NB_ERR : NB_OK; +} + + static bool is_pim_interface(const struct lyd_node *dnode) { char if_xpath[XPATH_MAXLEN]; @@ -865,7 +1066,6 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -874,12 +1074,28 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *mesh_group_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; + mesh_group_name = yang_dnode_get_string(args->dnode, "."); + + result = ip_no_msdp_mesh_group_cmd_worker(pim, mesh_group_name, + args->errmsg, + args->errmsg_len); + + if (result != PIM_MSDP_ERR_NONE) + return NB_ERR_INCONSISTENCY; + break; } @@ -891,12 +1107,30 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify(struct nb_cb_modify_args *args) { + const char *mesh_group_name; + const char *mesh_group_name_old; + char xpath[XPATH_MAXLEN]; + switch (args->event) { case NB_EV_VALIDATE: + mesh_group_name = yang_dnode_get_string(args->dnode, "."); + yang_dnode_get_path(args->dnode, xpath, sizeof(xpath)); + + if (yang_dnode_exists(running_config->dnode, xpath) == false) + break; + + mesh_group_name_old = yang_dnode_get_string(running_config->dnode, + xpath); + if (strcmp(mesh_group_name, mesh_group_name_old)) { + /* currently only one mesh-group can exist at a time */ + snprintf(args->errmsg, args->errmsg_len, + "Only one mesh-group allowed currently"); + return NB_ERR_VALIDATION; + } + break; case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -910,7 +1144,6 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -922,12 +1155,31 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create(struct nb_cb_create_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *mesh_group_name; + struct ipaddr mbr_ip; + enum pim_msdp_err 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; + mesh_group_name = yang_dnode_get_string(args->dnode, + "../mesh-group-name"); + yang_dnode_get_ip(&mbr_ip, args->dnode, NULL); + + result = ip_msdp_mesh_group_member_cmd_worker( + pim, mesh_group_name, mbr_ip.ip._v4_addr, + args->errmsg, args->errmsg_len); + + if (result != PIM_MSDP_ERR_NONE) + return NB_ERR_INCONSISTENCY; + break; } @@ -936,12 +1188,31 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy(struct nb_cb_destroy_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *mesh_group_name; + struct ipaddr mbr_ip; + enum pim_msdp_err 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; + mesh_group_name = yang_dnode_get_string(args->dnode, + "../mesh-group-name"); + yang_dnode_get_ip(&mbr_ip, args->dnode, NULL); + + result = ip_no_msdp_mesh_group_member_cmd_worker( + pim, mesh_group_name, mbr_ip.ip._v4_addr, + args->errmsg, args->errmsg_len); + + if (result != PIM_MSDP_ERR_NONE) + return NB_ERR_INCONSISTENCY; + break; } @@ -953,29 +1224,62 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify(struct nb_cb_modify_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *mesh_group_name; + struct ipaddr src_ip; + enum pim_msdp_err 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; + mesh_group_name = yang_dnode_get_string(args->dnode, + "../mesh-group-name"); + yang_dnode_get_ip(&src_ip, args->dnode, NULL); + + result = ip_msdp_mesh_group_source_cmd_worker( + pim, mesh_group_name, src_ip.ip._v4_addr, + args->errmsg, args->errmsg_len); + + if (result != PIM_MSDP_ERR_NONE) + return NB_ERR_INCONSISTENCY; + break; } - return NB_OK; } int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy(struct nb_cb_destroy_args *args) { + struct vrf *vrf; + struct pim_instance *pim; + const char *mesh_group_name; + enum pim_msdp_err 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; + mesh_group_name = yang_dnode_get_string(args->dnode, + "../mesh-group-name"); + + result = ip_no_msdp_mesh_group_source_cmd_worker( + pim, mesh_group_name, args->errmsg, args->errmsg_len); + + if (result != PIM_MSDP_ERR_NONE) + return NB_ERR_INCONSISTENCY; + break; } - return NB_OK; } @@ -989,7 +1293,6 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; } @@ -998,12 +1301,27 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(struct nb_cb_destroy_args *args) { + int result; + struct pim_instance *pim; + struct ipaddr peer_ip; + struct vrf *vrf; + 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(&peer_ip, args->dnode, "./peer-ip"); + result = ip_no_msdp_peer_cmd_worker(pim, peer_ip.ip._v4_addr, + args->errmsg, + args->errmsg_len); + + if (result) + return NB_ERR_INCONSISTENCY; + break; } @@ -1015,12 +1333,48 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(struct nb_cb_modify_args *args) { + int result; + struct vrf *vrf; + struct pim_instance *pim; + struct ipaddr peer_ip; + struct ipaddr source_ip; + const struct lyd_node *mesh_group_name_dnode; + const char *mesh_group_name; + switch (args->event) { case NB_EV_VALIDATE: + mesh_group_name_dnode = + yang_dnode_get(args->dnode, + "../../msdp-mesh-group/mesh-group-name"); + if (mesh_group_name_dnode) { + mesh_group_name = + yang_dnode_get_string(mesh_group_name_dnode, + "."); + if (strcmp(mesh_group_name, "default")) { + /* currently only one mesh-group can exist at a time */ + snprintf(args->errmsg, args->errmsg_len, + "%% Only one mesh-group allowed currently"); + return NB_ERR_VALIDATION; + } + } + break; 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(&peer_ip, args->dnode, "../peer-ip"); + yang_dnode_get_ip(&source_ip, args->dnode, NULL); + + result = ip_msdp_peer_cmd_worker(pim, peer_ip.ip._v4_addr, + source_ip.ip._v4_addr, + args->errmsg, + args->errmsg_len); + + if (result) + return NB_ERR_INCONSISTENCY; + break; } @@ -1034,7 +1388,6 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_PREPARE: case NB_EV_ABORT: case NB_EV_APPLY: - /* TODO: implement me. */ break; }