diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 0b503b8293..aa7fc0d81f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2820,6 +2820,75 @@ DEFPY (show_ip_pim_rp_vrf_all, (struct prefix *)group, !!json); } +DEFPY (show_ip_pim_autorp, + show_ip_pim_autorp_cmd, + "show ip pim [vrf NAME] autorp [json$json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM AutoRP information\n" + JSON_STR) +{ + struct vrf *v; + json_object *json_parent = NULL; + + v = vrf_lookup_by_name(vrf ? vrf : VRF_DEFAULT_NAME); + if (!v || !v->info) { + if (!json) + vty_out(vty, "%% Unable to find pim instance\n"); + return CMD_WARNING; + } + + if (json) + json_parent = json_object_new_object(); + + pim_autorp_show_autorp(vty, v->info, json_parent); + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + +DEFPY (show_ip_pim_autorp_vrf_all, + show_ip_pim_autorp_vrf_all_cmd, + "show ip pim vrf all autorp [json$json]", + SHOW_STR + IP_STR + PIM_STR + VRF_CMD_HELP_STR + "PIM AutoRP information\n" + JSON_STR) +{ + struct vrf *vrf; + json_object *json_parent = NULL; + json_object *json_vrf = NULL; + + if (json) + json_parent = json_object_new_object(); + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + if (vrf->info) { + if (!json) + vty_out(vty, "VRF: %s\n", vrf->name); + else + json_vrf = json_object_new_object(); + + pim_autorp_show_autorp(vty, vrf->info, json_vrf); + + if (json) + json_object_object_add(json_parent, vrf->name, + json_vrf); + } + } + + if (json) + vty_json(vty, json_parent); + + return CMD_SUCCESS; +} + DEFPY (show_ip_pim_rpf, show_ip_pim_rpf_cmd, "show ip pim [vrf NAME] rpf [json$json]", @@ -4516,6 +4585,52 @@ DEFPY_ATTR(no_ip_pim_rp_prefix_list, return ret; } +DEFPY (pim_autorp_discovery, + pim_autorp_discovery_cmd, + "[no] autorp discovery", + NO_STR + "AutoRP\n" + "Enable AutoRP discovery\n") +{ + if (no) + return pim_process_no_autorp_cmd(vty); + else + return pim_process_autorp_cmd(vty); +} + +DEFPY (pim_autorp_announce_rp, + pim_autorp_announce_rp_cmd, + "[no] autorp announce A.B.C.D$rpaddr ![A.B.C.D/M$grp|group-list PREFIX_LIST$plist]", + NO_STR + "AutoRP\n" + "AutoRP Candidate RP announcement\n" + "AutoRP Candidate RP address\n" + "Group prefix\n" + "Prefix list\n" + "List name\n") +{ + return pim_process_autorp_candidate_rp_cmd(vty, no, rpaddr_str, grp, + plist); +} + +DEFPY (pim_autorp_announce_scope_int, + pim_autorp_announce_scope_int_cmd, + "[no] autorp announce ![{scope (1-255) | interval (1-65535) | holdtime (0-65535)}]", + NO_STR + "AutoRP\n" + "AutoRP Candidate RP announcement\n" + "Packet scope (TTL)\n" + "TTL value\n" + "Announcement interval\n" + "Time in seconds\n" + "Announcement holdtime\n" + "Time in seconds\n") +{ + return pim_process_autorp_announce_scope_int_cmd(vty, no, scope_str, + interval_str, + holdtime_str); +} + DEFPY (pim_bsr_candidate_bsr, pim_bsr_candidate_bsr_cmd, "[no] bsr candidate-bsr [{priority (0-255)|source
}]", @@ -6377,6 +6492,29 @@ DEFUN (no_debug_bsm, return CMD_SUCCESS; } +DEFUN (debug_autorp, + debug_autorp_cmd, + "debug pim autorp", + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_AUTORP_STR) +{ + PIM_DO_DEBUG_AUTORP; + return CMD_SUCCESS; +} + +DEFUN (no_debug_autorp, + no_debug_autorp_cmd, + "no debug pim autorp", + NO_STR + DEBUG_STR + DEBUG_PIM_STR + DEBUG_PIM_AUTORP_STR) +{ + PIM_DONT_DEBUG_AUTORP; + return CMD_SUCCESS; +} + DEFUN_NOSH (show_debugging_pim, show_debugging_pim_cmd, @@ -8714,6 +8852,9 @@ void pim_cmd_init(void) install_element(PIM_NODE, &no_pim_rp_cmd); install_element(PIM_NODE, &pim_rp_prefix_list_cmd); install_element(PIM_NODE, &no_pim_rp_prefix_list_cmd); + install_element(PIM_NODE, &pim_autorp_discovery_cmd); + install_element(PIM_NODE, &pim_autorp_announce_rp_cmd); + install_element(PIM_NODE, &pim_autorp_announce_scope_int_cmd); install_element(PIM_NODE, &no_pim_ssm_prefix_list_cmd); install_element(PIM_NODE, &no_pim_ssm_prefix_list_name_cmd); install_element(PIM_NODE, &pim_ssm_prefix_list_cmd); @@ -8868,6 +9009,8 @@ void pim_cmd_init(void) install_element(VIEW_NODE, &show_ip_pim_upstream_rpf_cmd); install_element(VIEW_NODE, &show_ip_pim_rp_cmd); install_element(VIEW_NODE, &show_ip_pim_rp_vrf_all_cmd); + install_element(VIEW_NODE, &show_ip_pim_autorp_cmd); + install_element(VIEW_NODE, &show_ip_pim_autorp_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_pim_bsr_cmd); install_element(VIEW_NODE, &show_ip_multicast_cmd); install_element(VIEW_NODE, &show_ip_multicast_vrf_all_cmd); @@ -8975,6 +9118,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &debug_pim_trace_detail_cmd); install_element(ENABLE_NODE, &debug_ssmpingd_cmd); install_element(CONFIG_NODE, &debug_ssmpingd_cmd); + install_element(ENABLE_NODE, &debug_autorp_cmd); + install_element(ENABLE_NODE, &no_debug_autorp_cmd); install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd); install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd); install_element(ENABLE_NODE, &debug_pim_zebra_cmd); @@ -9007,6 +9152,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &debug_bsm_cmd); install_element(ENABLE_NODE, &no_debug_bsm_cmd); install_element(CONFIG_NODE, &no_debug_bsm_cmd); + install_element(CONFIG_NODE, &debug_autorp_cmd); + install_element(CONFIG_NODE, &no_debug_autorp_cmd); install_element(CONFIG_NODE, &ip_igmp_group_watermark_cmd); install_element(VRF_NODE, &ip_igmp_group_watermark_cmd); diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h index d39d77cd2f..17cf4bb362 100644 --- a/pimd/pim_cmd.h +++ b/pimd/pim_cmd.h @@ -56,6 +56,7 @@ #define DEBUG_MSDP_PACKETS_STR "MSDP protocol packets\n" #define DEBUG_MTRACE_STR "Mtrace protocol activity\n" #define DEBUG_PIM_BSM_STR "BSR message processing activity\n" +#define DEBUG_PIM_AUTORP_STR "AutoRP message processing activity\n" void pim_cmd_init(void); diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index 7337bacc84..be7460d0fb 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -606,6 +606,165 @@ int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str, return nb_cli_apply_changes(vty, NULL); } +int pim_process_autorp_cmd(struct vty *vty) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), "%s/%s", FRR_PIM_AUTORP_XPATH, + "discovery-enabled"); + + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +int pim_process_no_autorp_cmd(struct vty *vty) +{ + char xpath[XPATH_MAXLEN]; + + snprintf(xpath, sizeof(xpath), "%s/%s", FRR_PIM_AUTORP_XPATH, + "discovery-enabled"); + + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +int pim_process_autorp_candidate_rp_cmd(struct vty *vty, bool no, + const char *rpaddr_str, + const struct prefix_ipv4 *grp, + const char *plist) +{ + char xpath[XPATH_MAXLEN]; + char grpstr[64]; + + if (no) { + if (!is_default_prefix((const struct prefix *)grp) || plist) { + /* If any single values are set, only destroy those */ + if (!is_default_prefix((const struct prefix *)grp)) { + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']/group", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, + NULL); + } + if (plist) { + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']/prefix-list", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, + NULL); + } + } else { + /* No values set, remove the entire RP */ + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + } + } else { + if (!is_default_prefix((const struct prefix *)grp) || plist) { + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + if (!is_default_prefix((const struct prefix *)grp)) { + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']/group", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + prefix2str(grp, grpstr, + sizeof(grpstr))); + } + if (plist) { + snprintfrr(xpath, sizeof(xpath), + "%s/candidate-rp-list[rp-address='%s']/prefix-list", + FRR_PIM_AUTORP_XPATH, rpaddr_str); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + plist); + } + } else { + return CMD_WARNING_CONFIG_FAILED; + } + } + + return nb_cli_apply_changes(vty, NULL); +} + +int pim_process_autorp_announce_scope_int_cmd(struct vty *vty, bool no, + const char *scope, + const char *interval, + const char *holdtime) +{ + char xpath[XPATH_MAXLEN]; + + if (no) { + if (scope || interval || holdtime) { + /* If any single values are set, only destroy those */ + if (scope) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-scope"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, + NULL); + } + if (interval) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-interval"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, + NULL); + } + if (holdtime) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-holdtime"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, + NULL); + } + } else { + /* No values set, remove all */ + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, "announce-scope"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, "announce-interval"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, "announce-holdtime"); + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + } + } else { + if (scope || interval || holdtime) { + if (scope) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-scope"); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + scope); + } + if (interval) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-interval"); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + interval); + } + if (holdtime) { + snprintfrr(xpath, sizeof(xpath), "%s/%s", + FRR_PIM_AUTORP_XPATH, + "announce-holdtime"); + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, + holdtime); + } + } else { + return CMD_WARNING_CONFIG_FAILED; + } + } + + return nb_cli_apply_changes(vty, NULL); +} + bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match) { return (pim_addr_is_any(match.grp) || diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h index 7ded9b246a..d7c97e31d4 100644 --- a/pimd/pim_cmd_common.h +++ b/pimd/pim_cmd_common.h @@ -35,7 +35,16 @@ int pim_process_rp_plist_cmd(struct vty *vty, const char *rp_str, const char *prefix_list); int pim_process_no_rp_plist_cmd(struct vty *vty, const char *rp_str, const char *prefix_list); - +int pim_process_autorp_cmd(struct vty *vty); +int pim_process_no_autorp_cmd(struct vty *vty); +int pim_process_autorp_candidate_rp_cmd(struct vty *vty, bool no, + const char *rpaddr_str, + const struct prefix_ipv4 *grp, + const char *plist); +int pim_process_autorp_announce_scope_int_cmd(struct vty *vty, bool no, + const char *scope, + const char *interval, + const char *holdtime); int pim_process_ip_pim_cmd(struct vty *vty); int pim_process_no_ip_pim_cmd(struct vty *vty); int pim_process_ip_pim_passive_cmd(struct vty *vty, bool enable); diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c index 3c36512a3d..66001d1463 100644 --- a/pimd/pim_nb.c +++ b/pimd/pim_nb.c @@ -379,6 +379,55 @@ const struct frr_yang_module_info frr_pim_rp_info = { .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy, } }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/discovery-enabled", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-scope", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-interval", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-holdtime", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list", + .cbs = { + .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/group", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy, + } + }, + { + .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/prefix-list", + .cbs = { + .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify, + .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy, + } + }, { .xpath = NULL, }, diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h index dfab582968..befad4efe4 100644 --- a/pimd/pim_nb.h +++ b/pimd/pim_nb.h @@ -159,6 +159,34 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp struct nb_cb_modify_args *args); int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy( struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create( + struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy( + struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify( + struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy( + struct nb_cb_destroy_args *args); /* frr-cand-bsr */ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_create( @@ -258,6 +286,7 @@ int routing_control_plane_protocols_name_validate( "mroute[source-addr='%s'][group-addr='%s']" #define FRR_PIM_STATIC_RP_XPATH \ "frr-pim-rp:rp/static-rp/rp-list[rp-address='%s']" +#define FRR_PIM_AUTORP_XPATH "./frr-pim-rp:rp/auto-rp" #define FRR_GMP_INTERFACE_XPATH \ "./frr-gmp:gmp/address-family[address-family='%s']" #define FRR_GMP_ENABLE_XPATH \ diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c index 0366d8a857..2b78b8671f 100644 --- a/pimd/pim_nb_config.c +++ b/pimd/pim_nb_config.c @@ -26,6 +26,7 @@ #include "lib_errors.h" #include "pim_util.h" #include "pim6_mld.h" +#include "pim_autorp.h" #include "pim_igmp.h" #if PIM_IPV == 6 @@ -147,6 +148,11 @@ static int pim_cmd_interface_add(struct interface *ifp) pim_if_membership_refresh(ifp); pim_if_create_pimreg(pim_ifp->pim); + +#if PIM_IPV == 4 + pim_autorp_add_ifp(ifp); +#endif + return 1; } @@ -2680,6 +2686,365 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp return NB_OK; } +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/discovery-enabled + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + bool enabled; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + enabled = yang_dnode_get_bool(args->dnode, NULL); + if (enabled) + pim_autorp_start_discovery(pim); + else + pim_autorp_stop_discovery(pim); + break; + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + bool enabled; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + enabled = yang_dnode_get_bool(args->dnode, NULL); + /* Run AutoRP discovery by default */ + if (!enabled) + pim_autorp_start_discovery(pim); + break; + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-scope + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + uint8_t scope; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + scope = yang_dnode_get_uint8(args->dnode, NULL); + pim_autorp_announce_scope(pim, scope); + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + pim_autorp_announce_scope(pim, 0); + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-interval + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + uint16_t interval; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + interval = yang_dnode_get_uint16(args->dnode, NULL); + pim_autorp_announce_interval(pim, interval); + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + pim_autorp_announce_interval(pim, 0); + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-holdtime + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + uint16_t holdtime; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + holdtime = yang_dnode_get_uint16(args->dnode, NULL); + pim_autorp_announce_holdtime(pim, holdtime); + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + /* 0 is a valid value, so -1 indicates deleting (go back to default) */ + pim_autorp_announce_holdtime(pim, -1); + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create( + struct nb_cb_create_args *args) +{ +#if PIM_IPV == 4 + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + pim_addr rp_addr; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_pimaddr(&rp_addr, args->dnode, "rp-address"); + if (!pim_autorp_rm_candidate_rp(pim, rp_addr)) + return NB_ERR_INCONSISTENCY; + break; + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/group + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + pim_addr rp_addr; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address"); + yang_dnode_get_prefix(&group, args->dnode, NULL); + apply_mask(&group); + pim_autorp_add_candidate_rp_group(pim, rp_addr, group); + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + struct prefix group; + pim_addr rp_addr; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address"); + yang_dnode_get_prefix(&group, args->dnode, NULL); + apply_mask(&group); + if (!pim_autorp_rm_candidate_rp_group(pim, rp_addr, group)) + return NB_ERR_INCONSISTENCY; + } +#endif + + return NB_OK; +} + +/* + * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/prefix-list + */ +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify( + struct nb_cb_modify_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + pim_addr rp_addr; + const char *plist; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + plist = yang_dnode_get_string(args->dnode, NULL); + yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address"); + pim_autorp_add_candidate_rp_plist(pim, rp_addr, plist); + } +#endif + + return NB_OK; +} +int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy( + struct nb_cb_destroy_args *args) +{ +#if PIM_IPV == 4 + struct vrf *vrf; + struct pim_instance *pim; + pim_addr rp_addr; + const char *plist; + + switch (args->event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + case NB_EV_ABORT: + break; + case NB_EV_APPLY: + vrf = nb_running_get_entry(args->dnode, NULL, true); + pim = vrf->info; + yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address"); + plist = yang_dnode_get_string(args->dnode, NULL); + if (!pim_autorp_rm_candidate_rp_plist(pim, rp_addr, plist)) + return NB_ERR_INCONSISTENCY; + break; + } +#endif + + return NB_OK; +} + static void yang_addrsel(struct cand_addrsel *addrsel, const struct lyd_node *node) { diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index d5d6fb54d5..b633e81d55 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -165,6 +165,11 @@ int pim_debug_config_write(struct vty *vty) ++writes; } + if (PIM_DEBUG_AUTORP) { + vty_out(vty, "debug pim autorp\n"); + ++writes; + } + return writes; } @@ -182,6 +187,9 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) } writes += pim_rp_config_write(pim, vty); +#if PIM_IPV == 4 + writes += pim_autorp_config_write(pim, vty); +#endif writes += pim_cand_config_write(pim, vty); if (pim->vrf->vrf_id == VRF_DEFAULT) { diff --git a/yang/frr-pim-rp.yang b/yang/frr-pim-rp.yang index 4cc214135d..dbd5513ee5 100644 --- a/yang/frr-pim-rp.yang +++ b/yang/frr-pim-rp.yang @@ -111,6 +111,70 @@ module frr-pim-rp { } // static-rp } // static-rp-container + grouping auto-rp-container { + description + "Grouping of AutoRP container."; + + container auto-rp { + description + "Containing AutoRP attributes."; + + leaf discovery-enabled { + type boolean; + description + "Flag indicating if Auto RP discovery is enabled."; + } + + leaf announce-scope { + type uint8; + description + "The TTL of the C-RP Announcement packet."; + } + + leaf announce-interval { + type uint16; + description + "The time between sending C-RP announcement packets."; + } + + leaf announce-holdtime { + type uint16; + description + "The hold time in seconds advertised in the announcement packet."; + } + + list candidate-rp-list { + key "rp-address"; + description + "A list of Candidate RP addresses."; + + leaf rp-address { + type inet:ip-address; + description + "Specifies a candidate RP address."; + } + + choice group-or-prefix-list { + description "Use group or prefix-list"; + case group { + leaf group { + type frr-route-types:ip-multicast-group-prefix; + description + "Multicast group prefix."; + } + } + case prefix-list { + leaf prefix-list { + type plist-ref; + description + "Group prefix-list filter"; + } + } + } + } // candidate-rp-list + } // auto-rp + } // auto-rp-container + /* * Configuration data nodes */ @@ -123,6 +187,13 @@ module frr-pim-rp { description "PIM RP configuration data."; uses static-rp-container; + + uses auto-rp-container { + when "../frr-pim:address-family = 'frr-rt:ipv4'" { + description + "Only applicable to IPv4 address family."; + } + } } // rp } // augment }