summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Bahr <nbahr@atcorp.com>2024-11-01 20:11:14 +0100
committerNathan Bahr <nbahr@atcorp.com>2024-11-19 23:33:11 +0100
commita060c72530b96181ca736e8c42257b558e1b8dd3 (patch)
treeaa0866ae2c5b4e9cabade7cb6e1e8ddf4f60fd21
parentpimd,yang: Add PIMD northbound/yang for AutoRP mapping agent (diff)
downloadfrr-a060c72530b96181ca736e8c42257b558e1b8dd3.tar.xz
frr-a060c72530b96181ca736e8c42257b558e1b8dd3.zip
pimd: Implement autorp mapping agent CLI
Also exposes BSR cand_addrsel methods for use in AutoRP. Signed-off-by: Nathan Bahr <nbahr@atcorp.com>
-rw-r--r--pimd/pim_bsm.c4
-rw-r--r--pimd/pim_bsm.h5
-rw-r--r--pimd/pim_cmd.c114
-rw-r--r--pimd/pim_cmd_common.c185
-rw-r--r--pimd/pim_cmd_common.h16
5 files changed, 149 insertions, 175 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index a44e4e08f..75104141a 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -1769,14 +1769,14 @@ static inline pim_addr if_highest_addr(pim_addr cur, struct interface *ifp)
return cur;
}
-static void cand_addrsel_clear(struct cand_addrsel *asel)
+void cand_addrsel_clear(struct cand_addrsel *asel)
{
asel->run = false;
asel->run_addr = PIMADDR_ANY;
}
/* returns whether address or active changed */
-static bool cand_addrsel_update(struct cand_addrsel *asel, struct vrf *vrf)
+bool cand_addrsel_update(struct cand_addrsel *asel, struct vrf *vrf)
{
bool is_any = false, prev_run = asel->run;
struct interface *ifp = NULL;
diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h
index 1eacc1be5..b1582d0df 100644
--- a/pimd/pim_bsm.h
+++ b/pimd/pim_bsm.h
@@ -64,7 +64,7 @@ enum cand_addr {
CAND_ADDR_EXPLICIT,
};
-/* used separately for Cand-RP and Cand-BSR */
+/* used separately for Cand-RP, Cand-BSR, and AutoRP mapping agent */
struct cand_addrsel {
bool cfg_enable;
enum cand_addr cfg_mode : 8;
@@ -369,6 +369,9 @@ void pim_cand_rp_trigger(struct bsm_scope *scope);
void pim_cand_rp_grp_add(struct bsm_scope *scope, const prefix_pim *p);
void pim_cand_rp_grp_del(struct bsm_scope *scope, const prefix_pim *p);
+void cand_addrsel_clear(struct cand_addrsel *asel);
+bool cand_addrsel_update(struct cand_addrsel *asel, struct vrf *vrf);
+
void pim_cand_addrs_changed(void);
int pim_crp_process(struct interface *ifp, pim_sgaddr *src_dst, uint8_t *buf,
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 934da2d53..732dd2971 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -2822,65 +2822,49 @@ DEFPY (show_ip_pim_rp_vrf_all,
DEFPY (show_ip_pim_autorp,
show_ip_pim_autorp_cmd,
- "show ip pim [vrf NAME] autorp [json$json]",
+ "show ip pim [vrf <NAME|all>] autorp [discovery|candidate|mapping-agent]$component [json$json]",
SHOW_STR
IP_STR
PIM_STR
VRF_CMD_HELP_STR
+ "All VRF's\n"
"PIM AutoRP information\n"
+ "RP Discovery details\n"
+ "Candidate RP details\n"
+ "Mapping Agent details\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;
- }
+ struct vrf *v;
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 (vrf && strmatch(vrf, "all")) {
+ json_object *json_vrf = NULL;
- if (json)
- json_parent = json_object_new_object();
+ RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
+ if (!v || !v->info)
+ continue;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- if (vrf->info) {
- if (!json)
- vty_out(vty, "VRF: %s\n", vrf->name);
- else
+ if (json)
json_vrf = json_object_new_object();
+ else
+ vty_out(vty, "VRF: %s\n", v->name);
- pim_autorp_show_autorp(vty, vrf->info, json_vrf);
+ pim_autorp_show_autorp(vty, v->info, component, json_vrf);
if (json)
- json_object_object_add(json_parent, vrf->name,
- json_vrf);
+ json_object_object_add(json_parent, v->name, json_vrf);
+ }
+ } else {
+ 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;
}
+ pim_autorp_show_autorp(vty, v->info, component, json_parent);
}
if (json)
@@ -4609,13 +4593,17 @@ DEFPY (pim_autorp_announce_rp,
"Prefix list\n"
"List name\n")
{
- return pim_process_autorp_candidate_rp_cmd(vty, no, rpaddr_str, (grp_str ? grp : NULL),
- plist);
+ if (grp_str && (!pim_addr_is_multicast(grp->prefix) || grp->prefixlen < 4)) {
+ vty_out(vty, "%% group prefix %pFX is not a valid multicast range\n", grp);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return pim_process_autorp_candidate_rp_cmd(vty, no, rpaddr_str, grp_str, 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] autorp announce {scope (1-255) | interval (1-65535) | holdtime (0-65535)}",
NO_STR
"AutoRP\n"
"AutoRP Candidate RP announcement\n"
@@ -4626,11 +4614,44 @@ DEFPY (pim_autorp_announce_scope_int,
"Announcement holdtime\n"
"Time in seconds\n")
{
- return pim_process_autorp_announce_scope_int_cmd(vty, no, scope_str,
- interval_str,
+ return pim_process_autorp_announce_scope_int_cmd(vty, no, scope_str, interval_str,
holdtime_str);
}
+DEFPY (pim_autorp_send_rp_discovery,
+ pim_autorp_send_rp_discovery_cmd,
+ "[no] autorp send-rp-discovery [source <address A.B.C.D | interface IFNAME | loopback$loopback | any$any>]",
+ NO_STR
+ "AutoRP\n"
+ "Enable AutoRP mapping agent\n"
+ "Specify AutoRP discovery source\n"
+ "Local address\n"
+ IP_ADDR_STR
+ "Local Interface (uses highest address)\n"
+ IFNAME_STR
+ "Highest loopback address (default)\n"
+ "Highest address of any interface\n")
+{
+ return pim_process_autorp_send_rp_discovery_cmd(vty, no, any, loopback, ifname, address_str);
+}
+
+DEFPY (pim_autorp_send_rp_discovery_scope_int,
+ pim_autorp_send_rp_discovery_scope_int_cmd,
+ "[no] autorp send-rp-discovery {scope (0-255) | interval (1-65535) | holdtime (0-65535)}",
+ NO_STR
+ "AutoRP\n"
+ "Enable AutoRP mapping agent\n"
+ "Packet scope (TTL)\n"
+ "TTL value\n"
+ "Discovery TX interval\n"
+ "Time in seconds\n"
+ "Announcement holdtime\n"
+ "Time in seconds\n")
+{
+ return pim_process_autorp_send_rp_discovery_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 <address A.B.C.D|interface IFNAME|loopback$loopback|any$any>}]",
@@ -8855,6 +8876,8 @@ void pim_cmd_init(void)
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, &pim_autorp_send_rp_discovery_cmd);
+ install_element(PIM_NODE, &pim_autorp_send_rp_discovery_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);
@@ -9010,7 +9033,6 @@ void pim_cmd_init(void)
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);
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index 02ddea825..1476845a5 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -630,139 +630,88 @@ int pim_process_no_autorp_cmd(struct vty *vty)
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)
+int pim_process_autorp_candidate_rp_cmd(struct vty *vty, bool no, const char *rpaddr_str,
+ const char *grp, const char *plist)
{
- char xpath[XPATH_MAXLEN];
- char grpstr[64];
-
if (no) {
- if ((grp && !is_default_prefix((const struct prefix *)grp)) || plist) {
+ if (grp || plist) {
/* If any single values are set, only destroy those */
- if (grp && !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 {
+ if (grp)
+ nb_cli_enqueue_change(vty, "./group", NB_OP_DESTROY, NULL);
+ if (plist)
+ nb_cli_enqueue_change(vty, "./prefix-list", 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);
- }
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
} else {
- if ((grp && !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 (grp && !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;
- }
+ nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+ if (grp)
+ nb_cli_enqueue_change(vty, "./group", NB_OP_MODIFY, grp);
+ if (plist)
+ nb_cli_enqueue_change(vty, "./prefix-list", NB_OP_MODIFY, plist);
}
- return nb_cli_apply_changes(vty, NULL);
+ return nb_cli_apply_changes(vty, "%s/candidate-rp-list[rp-address='%s']",
+ FRR_PIM_AUTORP_XPATH, rpaddr_str);
}
-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_autorp_announce_scope_int_cmd(struct vty *vty, bool no, const char *scope,
+ const char *interval, const char *holdtime)
{
- char xpath[XPATH_MAXLEN];
+ /* At least one value is required, so set/delete anything defined */
+ enum nb_operation op = (no ? NB_OP_DESTROY : NB_OP_MODIFY);
+
+ if (scope)
+ nb_cli_enqueue_change(vty, "./announce-scope", op, scope);
+ if (interval)
+ nb_cli_enqueue_change(vty, "./announce-interval", op, interval);
+ if (holdtime)
+ nb_cli_enqueue_change(vty, "./announce-holdtime", op, holdtime);
+ return nb_cli_apply_changes(vty, "%s", FRR_PIM_AUTORP_XPATH);
+}
+
+int pim_process_autorp_send_rp_discovery_cmd(struct vty *vty, bool no, bool any, bool loopback,
+ const char *ifname, const char *addr)
+{
+ /* Just take any "no" version of this command as disable the mapping agent */
+ nb_cli_enqueue_change(vty, "./send-rp-discovery", NB_OP_MODIFY, (no ? "false" : "true"));
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);
- }
+ nb_cli_enqueue_change(vty, "./if-any", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./interface", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./address", NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, "./if-loopback", 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;
- }
+ /* Enabling mapping agent. Loopback is default, so any non-no for of the command will
+ * enable the mapping agent.
+ */
+ if (any)
+ nb_cli_enqueue_change(vty, "./if-any", NB_OP_CREATE, NULL);
+ else if (ifname)
+ nb_cli_enqueue_change(vty, "./interface", NB_OP_MODIFY, ifname);
+ else if (addr)
+ nb_cli_enqueue_change(vty, "./address", NB_OP_MODIFY, addr);
+ else
+ nb_cli_enqueue_change(vty, "./if-loopback", NB_OP_CREATE, NULL);
}
- return nb_cli_apply_changes(vty, NULL);
+ return nb_cli_apply_changes(vty, "%s/%s", FRR_PIM_AUTORP_XPATH, "mapping-agent");
+}
+
+int pim_process_autorp_send_rp_discovery_scope_int_cmd(struct vty *vty, bool no, const char *scope,
+ const char *interval, const char *holdtime)
+{
+ /* At least one value is required, so only set/delete the values specified */
+ enum nb_operation op = (no ? NB_OP_DESTROY : NB_OP_MODIFY);
+
+ if (scope)
+ nb_cli_enqueue_change(vty, "./discovery-scope", op, scope);
+ if (interval)
+ nb_cli_enqueue_change(vty, "./discovery-interval", op, interval);
+ if (holdtime)
+ nb_cli_enqueue_change(vty, "./discovery-holdtime", op, holdtime);
+
+ return nb_cli_apply_changes(vty, "%s/%s", FRR_PIM_AUTORP_XPATH, "mapping-agent");
}
bool pim_sgaddr_match(pim_sgaddr item, pim_sgaddr match)
diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h
index d7c97e31d..a06764711 100644
--- a/pimd/pim_cmd_common.h
+++ b/pimd/pim_cmd_common.h
@@ -37,14 +37,14 @@ 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_autorp_candidate_rp_cmd(struct vty *vty, bool no, const char *rpaddr_str,
+ const char *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_autorp_send_rp_discovery_cmd(struct vty *vty, bool no, bool any, bool loopback,
+ const char *ifname, const char *addr);
+int pim_process_autorp_send_rp_discovery_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);