From e2809e618bb18cddb18efbbc1d743490db7596b6 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 20 Apr 2021 14:54:09 -0300 Subject: [PATCH] pimd: rework MSDP mesh-group code Fully utilize the northbound to hold pointers to our private data instead of searching for data structures every time we need to change a configuration. Highlights: * Support multiple mesh groups per PIM instance (instead of one) * Use DEFPY instead of DEFUN to reduce code complexity * Use northbound private pointers to store data structures * Reduce callback names size Signed-off-by: Rafael Zalamena --- pimd/pim_cmd.c | 449 ++++++++++++++++++++----------------------- pimd/pim_msdp.c | 314 ++++++++++-------------------- pimd/pim_msdp.h | 56 ++++-- pimd/pim_nb.c | 25 +-- pimd/pim_nb.h | 22 +-- pimd/pim_nb_config.c | 341 ++++++-------------------------- 6 files changed, 423 insertions(+), 784 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index f6072b177..b3d444465 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -3853,6 +3853,54 @@ static const char *pim_cli_get_vrf_name(struct vty *vty) return yang_dnode_get_string(vrf_node, "./name"); } +/** + * Compatibility function to keep the legacy mesh group CLI behavior: + * Delete group when there are no more configurations in it. + * + * NOTE: + * Don't forget to call `nb_cli_apply_changes` after this. + */ +static void pim_cli_legacy_mesh_group_behavior(struct vty *vty, + const char *gname) +{ + const char *vrfname; + char xpath_value[XPATH_MAXLEN]; + char xpath_member_value[XPATH_MAXLEN]; + const struct lyd_node *member_dnode; + + vrfname = pim_cli_get_vrf_name(vty); + if (vrfname == NULL) + return; + + /* Get mesh group base XPath. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); + /* Group must exists, otherwise just quit. */ + if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value)) + return; + + /* Group members check: */ + strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value)); + strlcat(xpath_member_value, "/members", sizeof(xpath_member_value)); + if (yang_dnode_exists(vty->candidate_config->dnode, + xpath_member_value)) { + member_dnode = yang_dnode_get(vty->candidate_config->dnode, + xpath_member_value); + if (!yang_is_last_list_dnode(member_dnode)) + return; + } + + /* Source address check: */ + strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value)); + strlcat(xpath_member_value, "/source", sizeof(xpath_member_value)); + if (yang_dnode_exists(vty->candidate_config->dnode, xpath_member_value)) + return; + + /* No configurations found: delete it. */ + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); +} + DEFUN (clear_ip_interfaces, clear_ip_interfaces_cmd, "clear ip interfaces [vrf NAME]", @@ -9685,305 +9733,199 @@ DEFUN (no_ip_msdp_peer, return nb_cli_apply_changes(vty, NULL); } -DEFUN (ip_msdp_mesh_group_member, - ip_msdp_mesh_group_member_cmd, - "ip msdp mesh-group WORD member A.B.C.D", - IP_STR - CFG_MSDP_STR - "Configure MSDP mesh-group\n" - "mesh group name\n" - "mesh group member\n" - "peer ip address\n") +DEFPY(ip_msdp_mesh_group_member, + ip_msdp_mesh_group_member_cmd, + "ip msdp mesh-group WORD$gname member A.B.C.D$maddr", + IP_STR + CFG_MSDP_STR + "Configure MSDP mesh-group\n" + "Mesh group name\n" + "Mesh group member\n" + "Peer IP address\n") { const char *vrfname; - char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; - char msdp_mesh_group_member_xpath[XPATH_MAXLEN]; + char xpath_value[XPATH_MAXLEN]; vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) return CMD_WARNING_CONFIG_FAILED; - 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)); + /* Create mesh group. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - 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); + /* Create mesh group member. */ + strlcat(xpath_value, "/members[address='", sizeof(xpath_value)); + strlcat(xpath_value, maddr_str, sizeof(xpath_value)); + strlcat(xpath_value, "']", sizeof(xpath_value)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); return nb_cli_apply_changes(vty, NULL); } -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", - NO_STR - IP_STR - CFG_MSDP_STR - "Delete MSDP mesh-group member\n" - "mesh group name\n" - "mesh group member\n" - "peer ip address\n") +DEFPY(no_ip_msdp_mesh_group_member, + no_ip_msdp_mesh_group_member_cmd, + "no ip msdp mesh-group WORD$gname member A.B.C.D$maddr", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group member\n" + "Mesh group name\n" + "Mesh group member\n" + "Peer IP address\n") { const char *vrfname; - char pim_af_xpath[XPATH_MAXLEN]; - char mesh_group_xpath[XPATH_MAXLEN + 32]; - char group_member_list_xpath[XPATH_MAXLEN + 64]; - char group_member_xpath[XPATH_MAXLEN + 128]; - char source_xpath[XPATH_MAXLEN + 64]; - char mesh_group_name_xpath[XPATH_MAXLEN + 64]; - const char *mesh_group_name; - const struct lyd_node *member_dnode; + char xpath_value[XPATH_MAXLEN]; + char xpath_member_value[XPATH_MAXLEN]; vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) return CMD_WARNING_CONFIG_FAILED; - snprintf(pim_af_xpath, sizeof(pim_af_xpath), FRR_PIM_AF_XPATH, - "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4"); + /* Get mesh group base XPath. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); - snprintf(mesh_group_xpath, sizeof(mesh_group_xpath), - "%s/msdp-mesh-group", pim_af_xpath); - - snprintf(group_member_list_xpath, sizeof(group_member_list_xpath), - "%s/msdp-mesh-group/member-ip", pim_af_xpath); - - snprintf(group_member_xpath, sizeof(group_member_xpath), "%s[.='%s']", - group_member_list_xpath, argv[6]->arg); - - snprintf(source_xpath, sizeof(source_xpath), - "%s/msdp-mesh-group/source-ip", pim_af_xpath); - - snprintf(mesh_group_name_xpath, sizeof(mesh_group_name_xpath), - "%s/msdp-mesh-group/mesh-group-name", pim_af_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, xpath_value)) { + 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)) { - 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_list_xpath, - NB_OP_DESTROY, argv[6]->arg); - return nb_cli_apply_changes(vty, NULL); - } - nb_cli_enqueue_change(vty, group_member_list_xpath, - NB_OP_DESTROY, argv[6]->arg); - return nb_cli_apply_changes(vty, NULL); + /* Remove mesh group member. */ + strlcpy(xpath_member_value, xpath_value, sizeof(xpath_member_value)); + strlcat(xpath_member_value, "/members[address='", + sizeof(xpath_member_value)); + strlcat(xpath_member_value, maddr_str, sizeof(xpath_member_value)); + strlcat(xpath_member_value, "']", sizeof(xpath_member_value)); + if (!yang_dnode_exists(vty->candidate_config->dnode, + xpath_member_value)) { + vty_out(vty, "%% mesh-group member does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; } - vty_out(vty, "%% mesh-group member does not exist\n"); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); - return CMD_SUCCESS; + /* + * If this is the last member, then we must remove the group altogether + * to not break legacy CLI behaviour. + */ + pim_cli_legacy_mesh_group_behavior(vty, gname); + + return nb_cli_apply_changes(vty, NULL); } -DEFUN (ip_msdp_mesh_group_source, - ip_msdp_mesh_group_source_cmd, - "ip msdp mesh-group WORD source A.B.C.D", - IP_STR - CFG_MSDP_STR - "Configure MSDP mesh-group\n" - "mesh group name\n" - "mesh group local address\n" - "source ip address for the TCP connection\n") +DEFPY(ip_msdp_mesh_group_source, + ip_msdp_mesh_group_source_cmd, + "ip msdp mesh-group WORD$gname source A.B.C.D$saddr", + IP_STR + CFG_MSDP_STR + "Configure MSDP mesh-group\n" + "Mesh group name\n" + "Mesh group local address\n" + "Source IP address for the TCP connection\n") { const char *vrfname; - char msdp_mesh_source_ip_xpath[XPATH_MAXLEN]; - char msdp_mesh_group_name_xpath[XPATH_MAXLEN]; + char xpath_value[XPATH_MAXLEN]; vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) return CMD_WARNING_CONFIG_FAILED; - 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_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)); + /* Create mesh group. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - 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); + /* Create mesh group member. */ + strlcat(xpath_value, "/source", sizeof(xpath_value)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, saddr_str); return nb_cli_apply_changes(vty, NULL); } -DEFUN (no_ip_msdp_mesh_group_source, - no_ip_msdp_mesh_group_source_cmd, - "no ip msdp mesh-group WORD source [A.B.C.D]", - NO_STR - IP_STR - CFG_MSDP_STR - "Delete MSDP mesh-group source\n" - "mesh group name\n" - "mesh group source\n" - "mesh group local address\n") +DEFPY(no_ip_msdp_mesh_group_source, + no_ip_msdp_mesh_group_source_cmd, + "no ip msdp mesh-group WORD$gname source [A.B.C.D]", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group source\n" + "Mesh group name\n" + "Mesh group source\n" + "Mesh group local address\n") { 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; + char xpath_value[XPATH_MAXLEN]; vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) 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)); + /* Get mesh group base XPath. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_CREATE, NULL); - 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)); + /* Create mesh group member. */ + strlcat(xpath_value, "/source", sizeof(xpath_value)); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); - 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)); + /* + * If this is the last member, then we must remove the group altogether + * to not break legacy CLI behaviour. + */ + pim_cli_legacy_mesh_group_behavior(vty, gname); - 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, - no_ip_msdp_mesh_group_cmd, - "no ip msdp mesh-group [WORD]", - NO_STR - IP_STR - CFG_MSDP_STR - "Delete MSDP mesh-group\n" - "mesh group name") +DEFPY(no_ip_msdp_mesh_group, + no_ip_msdp_mesh_group_cmd, + "no ip msdp mesh-group WORD$gname", + NO_STR + IP_STR + CFG_MSDP_STR + "Delete MSDP mesh-group\n" + "Mesh group name") { const char *vrfname; - const char *mesh_group_name; - char xpath[XPATH_MAXLEN]; - char msdp_mesh_xpath[XPATH_MAXLEN]; + char xpath_value[XPATH_MAXLEN]; vrfname = pim_cli_get_vrf_name(vty); if (vrfname == NULL) return CMD_WARNING_CONFIG_FAILED; - 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)); + /* Get mesh group base XPath. */ + snprintf(xpath_value, sizeof(xpath_value), + FRR_PIM_AF_XPATH "/msdp-mesh-groups[name='%s']", + "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4", gname); + if (!yang_dnode_exists(vty->candidate_config->dnode, xpath_value)) + return CMD_SUCCESS; - nb_cli_enqueue_change(vty, msdp_mesh_xpath, NB_OP_DESTROY, NULL); + nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, NULL); return nb_cli_apply_changes(vty, NULL); } -static void print_empty_json_obj(struct vty *vty) -{ - json_object *json; - json = json_object_new_object(); - vty_out(vty, "%s\n", - json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); -} - -static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty, - bool uj) +static void ip_msdp_show_mesh_group(struct vty *vty, struct pim_msdp_mg *mg, + struct json_object *json) { struct listnode *mbrnode; struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = pim->msdp.mg; char mbr_str[INET_ADDRSTRLEN]; char src_str[INET_ADDRSTRLEN]; char state_str[PIM_MSDP_STATE_STRLEN]; enum pim_msdp_peer_state state; - json_object *json = NULL; json_object *json_mg_row = NULL; json_object *json_members = NULL; json_object *json_row = NULL; - if (!mg) { - if (uj) - print_empty_json_obj(vty); - return; - } - pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); - if (uj) { - json = json_object_new_object(); + if (json) { /* currently there is only one mesh group but we should still * make * it a dict with mg-name as key */ @@ -10005,7 +9947,7 @@ static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty, state = PIM_MSDP_DISABLED; } pim_msdp_state_dump(state, state_str, sizeof(state_str)); - if (uj) { + if (json) { json_row = json_object_new_object(); json_object_string_add(json_row, "member", mbr_str); json_object_string_add(json_row, "state", state_str); @@ -10020,12 +9962,8 @@ static void ip_msdp_show_mesh_group(struct pim_instance *pim, struct vty *vty, } } - if (uj) { + if (json) json_object_object_add(json, mg->mesh_group_name, json_mg_row); - vty_out(vty, "%s\n", json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } } DEFUN (show_ip_msdp_mesh_group, @@ -10040,12 +9978,34 @@ DEFUN (show_ip_msdp_mesh_group, { bool uj = use_json(argc, argv); int idx = 2; + struct pim_msdp_mg *mg; struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx); + struct pim_instance *pim = vrf->info; + struct json_object *json = NULL; if (!vrf) return CMD_WARNING; - ip_msdp_show_mesh_group(vrf->info, vty, uj); + /* Quick case: list is empty. */ + if (SLIST_EMPTY(&pim->msdp.mglist)) { + if (uj) + vty_out(vty, "{}\n"); + + return CMD_SUCCESS; + } + + if (uj) + json = json_object_new_object(); + + SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry) + ip_msdp_show_mesh_group(vty, mg, json); + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } return CMD_SUCCESS; } @@ -10061,23 +10021,32 @@ DEFUN (show_ip_msdp_mesh_group_vrf_all, JSON_STR) { bool uj = use_json(argc, argv); + struct json_object *json = NULL, *vrf_json = NULL; + struct pim_instance *pim; + struct pim_msdp_mg *mg; struct vrf *vrf; - bool first = true; if (uj) - vty_out(vty, "{ "); + json = json_object_new_object(); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if (uj) { - if (!first) - vty_out(vty, ", "); - vty_out(vty, " \"%s\": ", vrf->name); - first = false; + vrf_json = json_object_new_object(); + json_object_object_add(json, vrf->name, vrf_json); } else vty_out(vty, "VRF: %s\n", vrf->name); - ip_msdp_show_mesh_group(vrf->info, vty, uj); + + pim = vrf->info; + SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry) + ip_msdp_show_mesh_group(vty, mg, vrf_json); + } + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); } - if (uj) - vty_out(vty, "}\n"); return CMD_SUCCESS; } diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 9cf73c38c..6de793ff4 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -58,8 +58,6 @@ static void pim_msdp_sa_deref(struct pim_msdp_sa *sa, enum pim_msdp_sa_flags flags); static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2); static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr); -static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, - struct pim_msdp_mg_mbr *mbr); /************************ SA cache management ******************************/ static void pim_msdp_sa_timer_expiry_log(struct pim_msdp_sa *sa, @@ -1252,27 +1250,33 @@ static int pim_msdp_peer_comp(const void *p1, const void *p2) } /************************** Mesh group management **************************/ -static void pim_msdp_mg_free(struct pim_instance *pim) +void pim_msdp_mg_free(struct pim_instance *pim, struct pim_msdp_mg **mgp) { - struct pim_msdp_mg *mg = pim->msdp.mg; + struct pim_msdp_mg_mbr *mbr; + struct listnode *n, *nn; - /* If the mesh-group has valid member or src_ip don't delete it */ - if (!mg || mg->mbr_cnt || (mg->src_ip.s_addr != INADDR_ANY)) { + if (*mgp == NULL) return; - } + + /* SIP is being removed - tear down all active peer sessions */ + for (ALL_LIST_ELEMENTS((*mgp)->mbr_list, n, nn, mbr)) + pim_msdp_mg_mbr_do_del((*mgp), mbr); if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name); + zlog_debug("MSDP mesh-group %s deleted", + (*mgp)->mesh_group_name); } - XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name); - if (mg->mbr_list) - list_delete(&mg->mbr_list); + XFREE(MTYPE_PIM_MSDP_MG_NAME, (*mgp)->mesh_group_name); + + if ((*mgp)->mbr_list) + list_delete(&(*mgp)->mbr_list); - XFREE(MTYPE_PIM_MSDP_MG, pim->msdp.mg); + XFREE(MTYPE_PIM_MSDP_MG, (*mgp)); } -static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name) +struct pim_msdp_mg *pim_msdp_mg_new(struct pim_instance *pim, + const char *mesh_group_name) { struct pim_msdp_mg *mg; @@ -1286,52 +1290,10 @@ static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name) if (PIM_DEBUG_MSDP_EVENTS) { zlog_debug("MSDP mesh-group %s created", mg->mesh_group_name); } - return mg; -} - -enum pim_msdp_err pim_msdp_mg_del(struct pim_instance *pim, - const char *mesh_group_name) -{ - struct pim_msdp_mg *mg = pim->msdp.mg; - struct pim_msdp_mg_mbr *mbr; - - if (!mg - || (mesh_group_name - && strcmp(mg->mesh_group_name, mesh_group_name))) { - return PIM_MSDP_ERR_NO_MG; - } - - /* delete all the mesh-group members */ - while (!list_isempty(mg->mbr_list)) { - mbr = listnode_head(mg->mbr_list); - pim_msdp_mg_mbr_do_del(mg, mbr); - } - - /* clear src ip */ - mg->src_ip.s_addr = INADDR_ANY; - - /* free up the mesh-group */ - pim_msdp_mg_free(pim); - return PIM_MSDP_ERR_NONE; -} - -static enum pim_msdp_err pim_msdp_mg_add(struct pim_instance *pim, - const char *mesh_group_name) -{ - if (pim->msdp.mg) { - if (!strcmp(pim->msdp.mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NONE; - } - /* currently only one mesh-group can exist at a time */ - return PIM_MSDP_ERR_MAX_MESH_GROUPS; - } - pim->msdp.mg = pim_msdp_mg_new(mesh_group_name); - if (!pim->msdp.mg) { - return PIM_MSDP_ERR_OOM; - } + SLIST_INSERT_HEAD(&pim->msdp.mglist, mg, mg_entry); - return PIM_MSDP_ERR_NONE; + return mg; } static int pim_msdp_mg_mbr_comp(const void *p1, const void *p2) @@ -1353,66 +1315,7 @@ static void pim_msdp_mg_mbr_free(struct pim_msdp_mg_mbr *mbr) XFREE(MTYPE_PIM_MSDP_MG_MBR, mbr); } -static struct pim_msdp_mg_mbr *pim_msdp_mg_mbr_find(struct pim_instance *pim, - struct in_addr mbr_ip) -{ - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - - if (!pim->msdp.mg) { - return NULL; - } - /* we can move this to a hash but considering that number of peers in - * a mesh-group that seems like bit of an overkill */ - for (ALL_LIST_ELEMENTS_RO(pim->msdp.mg->mbr_list, mbr_node, mbr)) { - if (mbr->mbr_ip.s_addr == mbr_ip.s_addr) { - return mbr; - } - } - return mbr; -} - -enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr mbr_ip) -{ - int rc; - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg; - - rc = pim_msdp_mg_add(pim, mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } - - mg = pim->msdp.mg; - mbr = pim_msdp_mg_mbr_find(pim, mbr_ip); - if (mbr) { - return PIM_MSDP_ERR_MG_MBR_EXISTS; - } - - mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); - mbr->mbr_ip = mbr_ip; - listnode_add_sort(mg->mbr_list, mbr); - - /* if valid SIP has been configured add peer session */ - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_peer_add(pim, mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } - - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", mbr->mbr_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s mbr %s created", - mg->mesh_group_name, ip_str); - } - ++mg->mbr_cnt; - return PIM_MSDP_ERR_NONE; -} - -static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, - struct pim_msdp_mg_mbr *mbr) +void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, struct pim_msdp_mg_mbr *mbr) { /* Delete active peer session if any */ if (mbr->mp) { @@ -1432,34 +1335,10 @@ static void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, } } -enum pim_msdp_err pim_msdp_mg_mbr_del(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr mbr_ip) -{ - struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = pim->msdp.mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - mbr = pim_msdp_mg_mbr_find(pim, mbr_ip); - if (!mbr) { - return PIM_MSDP_ERR_NO_MG_MBR; - } - - pim_msdp_mg_mbr_do_del(mg, mbr); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(pim); - - return PIM_MSDP_ERR_NONE; -} - -static void pim_msdp_mg_src_do_del(struct pim_instance *pim) +static void pim_msdp_mg_src_do_del(struct pim_msdp_mg *mg) { struct pim_msdp_mg_mbr *mbr; struct listnode *mbr_node; - struct pim_msdp_mg *mg = pim->msdp.mg; /* SIP is being removed - tear down all active peer sessions */ for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { @@ -1474,91 +1353,38 @@ static void pim_msdp_mg_src_do_del(struct pim_instance *pim) } } -enum pim_msdp_err pim_msdp_mg_src_del(struct pim_instance *pim, - const char *mesh_group_name) -{ - struct pim_msdp_mg *mg = pim->msdp.mg; - - if (!mg || strcmp(mg->mesh_group_name, mesh_group_name)) { - return PIM_MSDP_ERR_NO_MG; - } - - if (mg->src_ip.s_addr != INADDR_ANY) { - mg->src_ip.s_addr = INADDR_ANY; - pim_msdp_mg_src_do_del(pim); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(pim); - } - return PIM_MSDP_ERR_NONE; -} - -enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr src_ip) -{ - int rc; - struct pim_msdp_mg_mbr *mbr; - struct listnode *mbr_node; - struct pim_msdp_mg *mg; - - if (src_ip.s_addr == INADDR_ANY) { - pim_msdp_mg_src_del(pim, mesh_group_name); - return PIM_MSDP_ERR_NONE; - } - - rc = pim_msdp_mg_add(pim, mesh_group_name); - if (rc != PIM_MSDP_ERR_NONE) { - return rc; - } - - mg = pim->msdp.mg; - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_msdp_mg_src_do_del(pim); - } - mg->src_ip = src_ip; - - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) { - pim_msdp_peer_add(pim, mbr->mbr_ip, mg->src_ip, mesh_group_name, - &mbr->mp); - } - - if (PIM_DEBUG_MSDP_EVENTS) { - char ip_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", mg->src_ip, ip_str, sizeof(ip_str)); - zlog_debug("MSDP mesh-group %s src %s set", mg->mesh_group_name, - ip_str); - } - return PIM_MSDP_ERR_NONE; -} - /*********************** MSDP feature APIs *********************************/ int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty, const char *spaces) { + struct pim_msdp_mg *mg; struct listnode *mbrnode; struct pim_msdp_mg_mbr *mbr; - struct pim_msdp_mg *mg = pim->msdp.mg; char mbr_str[INET_ADDRSTRLEN]; char src_str[INET_ADDRSTRLEN]; int count = 0; - if (!mg) { + if (SLIST_EMPTY(&pim->msdp.mglist)) return count; - } - if (mg->src_ip.s_addr != INADDR_ANY) { - pim_inet4_dump("", mg->src_ip, src_str, sizeof(src_str)); - vty_out(vty, "%sip msdp mesh-group %s source %s\n", spaces, - mg->mesh_group_name, src_str); - ++count; - } + SLIST_FOREACH (mg, &pim->msdp.mglist, mg_entry) { + if (mg->src_ip.s_addr != INADDR_ANY) { + pim_inet4_dump("", mg->src_ip, src_str, + sizeof(src_str)); + vty_out(vty, "%sip msdp mesh-group %s source %s\n", + spaces, mg->mesh_group_name, src_str); + ++count; + } - for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { - pim_inet4_dump("", mbr->mbr_ip, mbr_str, sizeof(mbr_str)); - vty_out(vty, "%sip msdp mesh-group %s member %s\n", spaces, - mg->mesh_group_name, mbr_str); - ++count; + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) { + pim_inet4_dump("", mbr->mbr_ip, mbr_str, + sizeof(mbr_str)); + vty_out(vty, "%sip msdp mesh-group %s member %s\n", + spaces, mg->mesh_group_name, mbr_str); + ++count; + } } + return count; } @@ -1623,11 +1449,13 @@ void pim_msdp_init(struct pim_instance *pim, struct thread_master *master) /* counterpart to MSDP init; XXX: unused currently */ void pim_msdp_exit(struct pim_instance *pim) { - pim_msdp_sa_adv_timer_setup(pim, false); + struct pim_msdp_mg *mg; - /* XXX: stop listener and delete all peer sessions */ + pim_msdp_sa_adv_timer_setup(pim, false); - pim_msdp_mg_free(pim); + /* Stop listener and delete all peer sessions */ + while ((mg = SLIST_FIRST(&pim->msdp.mglist)) != NULL) + pim_msdp_mg_free(pim, &mg); if (pim->msdp.peer_hash) { hash_clean(pim->msdp.peer_hash, NULL); @@ -1653,3 +1481,57 @@ void pim_msdp_exit(struct pim_instance *pim) stream_free(pim->msdp.work_obuf); pim->msdp.work_obuf = NULL; } + +void pim_msdp_mg_change_source(struct pim_instance *pim, struct pim_msdp_mg *mg, + struct in_addr *ai) +{ + struct pim_msdp_mg_mbr *mbr; + struct listnode *mbr_node; + + /* Stop all connections and remove data structures. */ + pim_msdp_mg_src_do_del(mg); + + /* Set new address. */ + mg->src_ip = *ai; + + /* No new address, disable everyone. */ + if (ai->s_addr == INADDR_ANY) { + if (PIM_DEBUG_MSDP_EVENTS) + zlog_debug("MSDP mesh-group %s src unset", + mg->mesh_group_name); + return; + } + + /* Create data structures and start TCP connection. */ + for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbr_node, mbr)) + pim_msdp_peer_add(pim, mbr->mbr_ip, mg->src_ip, + mg->mesh_group_name, &mbr->mp); + + if (PIM_DEBUG_MSDP_EVENTS) + zlog_debug("MSDP mesh-group %s src %pI4 set", + mg->mesh_group_name, &mg->src_ip); +} + +struct pim_msdp_mg_mbr *pim_msdp_mg_add_peer(struct pim_instance *pim, + struct pim_msdp_mg *mg, + struct in_addr *ia) +{ + struct pim_msdp_mg_mbr *mbr; + + mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); + mbr->mbr_ip = *ia; + listnode_add_sort(mg->mbr_list, mbr); + + /* if valid SIP has been configured add peer session */ + if (mg->src_ip.s_addr != INADDR_ANY) + pim_msdp_peer_add(pim, mbr->mbr_ip, mg->src_ip, + mg->mesh_group_name, &mbr->mp); + + if (PIM_DEBUG_MSDP_EVENTS) + zlog_debug("MSDP mesh-group %s mbr %pI4 created", + mg->mesh_group_name, &mbr->mbr_ip); + + ++mg->mbr_cnt; + + return mbr; +} diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h index 4d01880fb..f4d58cd56 100644 --- a/pimd/pim_msdp.h +++ b/pimd/pim_msdp.h @@ -19,6 +19,8 @@ #ifndef PIM_MSDP_H #define PIM_MSDP_H +#include "lib/openbsd-queue.h" + enum pim_msdp_peer_state { PIM_MSDP_DISABLED, PIM_MSDP_INACTIVE, @@ -160,8 +162,13 @@ struct pim_msdp_mg { struct in_addr src_ip; uint32_t mbr_cnt; struct list *mbr_list; + + /** Belongs to PIM instance list. */ + SLIST_ENTRY(pim_msdp_mg) mg_entry; }; +SLIST_HEAD(pim_mesh_group_list, pim_msdp_mg); + enum pim_msdp_flags { PIM_MSDPF_NONE = 0, PIM_MSDPF_ENABLE = (1 << 0), @@ -196,8 +203,8 @@ struct pim_msdp { struct in_addr originator_id; - /* currently only one mesh-group is supported - so just stash it here */ - struct pim_msdp_mg *mg; + /** List of mesh groups. */ + struct pim_mesh_group_list mglist; }; #define PIM_MSDP_PEER_READ_ON(mp) \ @@ -246,17 +253,40 @@ bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); void pim_msdp_up_join_state_changed(struct pim_instance *pim, struct pim_upstream *xg_up); void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg); -enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr mbr_ip); -enum pim_msdp_err pim_msdp_mg_mbr_del(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr mbr_ip); -enum pim_msdp_err pim_msdp_mg_src_del(struct pim_instance *pim, - const char *mesh_group_name); -enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim, - const char *mesh_group_name, - struct in_addr src_ip); enum pim_msdp_err pim_msdp_mg_del(struct pim_instance *pim, const char *mesh_group_name); + +/** + * Allocates a new mesh group data structure under PIM instance. + */ +struct pim_msdp_mg *pim_msdp_mg_new(struct pim_instance *pim, + const char *mesh_group_name); +/** + * Deallocates mesh group data structure under PIM instance. + */ +void pim_msdp_mg_free(struct pim_instance *pim, struct pim_msdp_mg **mgp); + +/** + * Change the source address of a mesh group peers. It will do the following: + * - Close all peers TCP connections + * - Recreate peers data structure + * - Start TCP connections with new local address. + */ +void pim_msdp_mg_change_source(struct pim_instance *pim, struct pim_msdp_mg *mg, + struct in_addr *ai); + +/** + * Add new peer to mesh group and starts the connection if source address is + * configured. + */ +struct pim_msdp_mg_mbr *pim_msdp_mg_add_peer(struct pim_instance *pim, + struct pim_msdp_mg *mg, + struct in_addr *ia); + +/** + * Stops the connection and removes the peer data structures. + */ +void pim_msdp_mg_mbr_do_del(struct pim_msdp_mg *mg, + struct pim_msdp_mg_mbr *mbr); + #endif diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c index 37c539883..ea53f1ef1 100644 --- a/pimd/pim_nb.c +++ b/pimd/pim_nb.c @@ -118,31 +118,24 @@ const struct frr_yang_module_info frr_pim_info = { } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups", .cbs = { - .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create, - .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy, + .create = pim_msdp_mesh_group_create, + .destroy = pim_msdp_mesh_group_destroy, } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source", .cbs = { - .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify, - .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy, + .modify = pim_msdp_mesh_group_source_modify, + .destroy = pim_msdp_mesh_group_source_destroy, } }, { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/member-ip", + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members", .cbs = { - .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create, - .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy, - } - }, - { - .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip", - .cbs = { - .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify, - .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy, + .create = pim_msdp_mesh_group_members_create, + .destroy = pim_msdp_mesh_group_members_destroy, } }, { diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h index 440384e45..1959b403f 100644 --- a/pimd/pim_nb.h +++ b/pimd/pim_nb.h @@ -60,22 +60,12 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss struct nb_cb_create_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy( struct nb_cb_destroy_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create( - struct nb_cb_create_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy( - struct nb_cb_destroy_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify( - struct nb_cb_modify_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy( - struct nb_cb_destroy_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create( - struct nb_cb_create_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy( - struct nb_cb_destroy_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify( - struct nb_cb_modify_args *args); -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy( - struct nb_cb_destroy_args *args); +int pim_msdp_mesh_group_create(struct nb_cb_create_args *args); +int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args); +int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args); +int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args); +int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args); +int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create( struct nb_cb_create_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy( diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 11e8da3b8..10a83e889 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -243,147 +243,6 @@ 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, @@ -1146,29 +1005,13 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss } /* - * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups */ -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create( - struct nb_cb_create_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: - case NB_EV_APPLY: - break; - } - - return NB_OK; -} - -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy( - struct nb_cb_destroy_args *args) +int pim_msdp_mesh_group_create(struct nb_cb_create_args *args) { + struct pim_msdp_mg *mg; struct vrf *vrf; - struct pim_instance *pim; - const char *mesh_group_name; - int result; switch (args->event) { case NB_EV_VALIDATE: @@ -1177,67 +1020,29 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms break; case NB_EV_APPLY: 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_cmd_worker(pim, mesh_group_name, - args->errmsg, - args->errmsg_len); - - if (result != PIM_MSDP_ERR_NONE) - return NB_ERR_INCONSISTENCY; - + mg = pim_msdp_mg_new(vrf->info, yang_dnode_get_string( + args->dnode, "./name")); + nb_running_set_entry(args->dnode, mg); break; } return NB_OK; } -/* - * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name - */ -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify( - struct nb_cb_modify_args *args) +int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args) { - const char *mesh_group_name; - const char *mesh_group_name_old; - char xpath[XPATH_MAXLEN]; + struct pim_msdp_mg *mg; + struct vrf *vrf; 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: break; - } - - return NB_OK; -} - -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy( - struct nb_cb_destroy_args *args) -{ - switch (args->event) { - case NB_EV_VALIDATE: - case NB_EV_PREPARE: - case NB_EV_ABORT: case NB_EV_APPLY: + mg = nb_running_unset_entry(args->dnode); + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim_msdp_mg_free(vrf->info, &mg); break; } @@ -1245,16 +1050,15 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms } /* - * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/member-ip + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source */ -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create( - struct nb_cb_create_args *args) +int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args) { + const struct lyd_node *vrf_dnode; + struct pim_msdp_mg *mg; struct vrf *vrf; - struct pim_instance *pim; - const char *mesh_group_name; - struct ipaddr mbr_ip; - enum pim_msdp_err result; + struct ipaddr ip; switch (args->event) { case NB_EV_VALIDATE: @@ -1262,33 +1066,24 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_ABORT: break; case NB_EV_APPLY: - 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; + mg = nb_running_get_entry(args->dnode, NULL, true); + vrf_dnode = + yang_dnode_get_parent(args->dnode, "address-family"); + vrf = nb_running_get_entry(vrf_dnode, "../../", true); + yang_dnode_get_ip(&ip, args->dnode, NULL); + pim_msdp_mg_change_source(vrf->info, mg, &ip.ip._v4_addr); break; } - return NB_OK; } -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy( - struct nb_cb_destroy_args *args) +int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args) { + const struct lyd_node *vrf_dnode; + struct pim_msdp_mg *mg; struct vrf *vrf; - struct pim_instance *pim; - const char *mesh_group_name; - struct ipaddr mbr_ip; - enum pim_msdp_err result; + struct in_addr addr; switch (args->event) { case NB_EV_VALIDATE: @@ -1296,36 +1091,30 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_ABORT: break; case NB_EV_APPLY: - 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; + mg = nb_running_get_entry(args->dnode, NULL, true); + vrf_dnode = + yang_dnode_get_parent(args->dnode, "address-family"); + vrf = nb_running_get_entry(vrf_dnode, "../../", true); + addr.s_addr = INADDR_ANY; + pim_msdp_mg_change_source(vrf->info, mg, &addr); break; } - return NB_OK; } + /* - * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members */ -int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify( - struct nb_cb_modify_args *args) +int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args) { + const struct lyd_node *vrf_dnode; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg; struct vrf *vrf; - struct pim_instance *pim; - const char *mesh_group_name; - struct ipaddr src_ip; - enum pim_msdp_err result; + struct ipaddr ip; switch (args->event) { case NB_EV_VALIDATE: @@ -1333,31 +1122,24 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_ABORT: break; case NB_EV_APPLY: - 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; + mg = nb_running_get_entry(args->dnode, NULL, true); + vrf_dnode = + yang_dnode_get_parent(args->dnode, "address-family"); + vrf = nb_running_get_entry(vrf_dnode, "../../", true); + yang_dnode_get_ip(&ip, args->dnode, "address"); + mbr = pim_msdp_mg_add_peer(vrf->info, mg, &ip.ip._v4_addr); + nb_running_set_entry(args->dnode, mbr); 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) +int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args) { - struct vrf *vrf; - struct pim_instance *pim; - const char *mesh_group_name; - enum pim_msdp_err result; + struct pim_msdp_mg_mbr *mbr; + struct pim_msdp_mg *mg; switch (args->event) { case NB_EV_VALIDATE: @@ -1365,20 +1147,13 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms case NB_EV_ABORT: break; case NB_EV_APPLY: - 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; + mbr = nb_running_get_entry(args->dnode, NULL, true); + mg = nb_running_get_entry(args->dnode, "../", true); + pim_msdp_mg_mbr_do_del(mg, mbr); break; } + return NB_OK; } -- 2.39.5