summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_routemap.c213
-rw-r--r--bgpd/bgp_routemap_nb.c14
-rw-r--r--bgpd/bgp_routemap_nb.h8
-rw-r--r--bgpd/bgp_routemap_nb_config.c104
-rw-r--r--lib/routemap.h4
-rw-r--r--lib/routemap_cli.c10
-rw-r--r--yang/frr-bgp-route-map.yang32
7 files changed, 385 insertions, 0 deletions
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 921a3e0dd9..ca1407b86a 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1084,6 +1084,71 @@ static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
route_match_rd_free
};
+static enum route_map_cmd_result_t
+route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
+{
+ struct ipaddr *gw_ip = rule;
+ struct bgp_path_info *path;
+ struct prefix_evpn *evp;
+
+ if (prefix->family != AF_EVPN)
+ return RMAP_OKAY;
+
+ evp = (struct prefix_evpn *)prefix;
+ if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
+ return RMAP_OKAY;
+
+ if ((is_evpn_prefix_ipaddr_v4(evp) && IPADDRSZ(gw_ip) != 4)
+ || (is_evpn_prefix_ipaddr_v6(evp) && IPADDRSZ(gw_ip) != 16))
+ return RMAP_OKAY;
+
+ path = object;
+
+ /* Set gateway-ip value. */
+ path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
+ memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
+ IPADDRSZ(gw_ip));
+
+ return RMAP_OKAY;
+}
+
+/*
+ * Route map `evpn gateway-ip' compile function.
+ * Given string is converted to struct ipaddr structure
+ */
+static void *route_set_evpn_gateway_ip_compile(const char *arg)
+{
+ struct ipaddr *gw_ip = NULL;
+ int ret;
+
+ gw_ip = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct ipaddr));
+
+ ret = str2ipaddr(arg, gw_ip);
+ if (ret < 0) {
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
+ return NULL;
+ }
+ return gw_ip;
+}
+
+/* Free route map's compiled `evpn gateway_ip' value. */
+static void route_set_evpn_gateway_ip_free(void *rule)
+{
+ struct ipaddr *gw_ip = rule;
+
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
+}
+
+/* Route map commands for set evpn gateway-ip ipv4. */
+struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv4_cmd = {
+ "evpn gateway-ip ipv4", route_set_evpn_gateway_ip,
+ route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
+
+/* Route map commands for set evpn gateway-ip ipv6. */
+struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv6_cmd = {
+ "evpn gateway-ip ipv6", route_set_evpn_gateway_ip,
+ route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
+
/* Route map commands for VRF route leak with source vrf matching */
static enum route_map_cmd_result_t
route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
@@ -4066,6 +4131,148 @@ DEFUN_YANG (no_match_evpn_rd,
return nb_cli_apply_changes(vty, NULL);
}
+DEFUN_YANG (set_evpn_gw_ip_ipv4,
+ set_evpn_gw_ip_ipv4_cmd,
+ "set evpn gateway-ip ipv4 A.B.C.D",
+ SET_STR
+ EVPN_HELP_STR
+ "Set gateway IP for prefix advertisement route\n"
+ "IPv4 address\n"
+ "Gateway IP address in IPv4 format\n")
+{
+ int ret;
+ union sockunion su;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
+ char xpath_value[XPATH_MAXLEN];
+
+ ret = str2sockunion(argv[4]->arg, &su);
+ if (ret < 0) {
+ vty_out(vty, "%% Malformed gateway IP\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (su.sin.sin_addr.s_addr == 0
+ || IPV4_CLASS_DE(ntohl(su.sin.sin_addr.s_addr))) {
+ vty_out(vty,
+ "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
+ xpath);
+
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
+ no_set_evpn_gw_ip_ipv4_cmd,
+ "no set evpn gateway-ip ipv4 A.B.C.D",
+ NO_STR
+ SET_STR
+ EVPN_HELP_STR
+ "Set gateway IP for prefix advertisement route\n"
+ "IPv4 address\n"
+ "Gateway IP address in IPv4 format\n")
+{
+ int ret;
+ union sockunion su;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
+
+ ret = str2sockunion(argv[5]->arg, &su);
+ if (ret < 0) {
+ vty_out(vty, "%% Malformed gateway IP\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (su.sin.sin_addr.s_addr == 0
+ || IPV4_CLASS_DE(ntohl(su.sin.sin_addr.s_addr))) {
+ vty_out(vty,
+ "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (set_evpn_gw_ip_ipv6,
+ set_evpn_gw_ip_ipv6_cmd,
+ "set evpn gateway-ip ipv6 X:X::X:X",
+ SET_STR
+ EVPN_HELP_STR
+ "Set gateway IP for prefix advertisement route\n"
+ "IPv6 address\n"
+ "Gateway IP address in IPv6 format\n")
+{
+ int ret;
+ union sockunion su;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
+ char xpath_value[XPATH_MAXLEN];
+
+ ret = str2sockunion(argv[4]->arg, &su);
+ if (ret < 0) {
+ vty_out(vty, "%% Malformed gateway IP\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
+ || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
+ vty_out(vty,
+ "%% Gateway IP cannot be a linklocal or multicast address\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
+ xpath);
+
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
+ no_set_evpn_gw_ip_ipv6_cmd,
+ "no set evpn gateway-ip ipv6 X:X::X:X",
+ NO_STR
+ SET_STR
+ EVPN_HELP_STR
+ "Set gateway IP for prefix advertisement route\n"
+ "IPv4 address\n"
+ "Gateway IP address in IPv4 format\n")
+{
+ int ret;
+ union sockunion su;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
+
+ ret = str2sockunion(argv[5]->arg, &su);
+ if (ret < 0) {
+ vty_out(vty, "%% Malformed gateway IP\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
+ || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
+ vty_out(vty,
+ "%% Gateway IP cannot be a linklocal or multicast address\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFPY_YANG(match_vrl_source_vrf,
match_vrl_source_vrf_cmd,
"match source-vrf NAME$vrf_name",
@@ -6123,6 +6330,8 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_evpn_default_route_cmd);
route_map_install_match(&route_match_vrl_source_vrf_cmd);
+ route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
+ route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
route_map_install_set(&route_set_table_id_cmd);
route_map_install_set(&route_set_srte_color_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd);
@@ -6166,6 +6375,10 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
install_element(RMAP_NODE, &match_evpn_default_route_cmd);
install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
+ install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
+ install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
+ install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
+ install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index b165c5d0ee..1254591b87 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -372,6 +372,20 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_modify,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_modify,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy,
+ }
+ },
+ {
.xpath = NULL,
},
}
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index a15f521513..f0e492eb61 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -130,6 +130,14 @@ int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_mod
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_bandwidth_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_specific_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
+ struct nb_cb_destroy_args *args);
#ifdef __cplusplus
}
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index ff08c16a82..e541d117be 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -2637,3 +2637,107 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_two_octet_as_spec
{
return lib_route_map_entry_set_destroy(args);
}
+
+/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4
+ */
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *type;
+ int rv;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ type = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = generic_set_delete;
+ rhc->rhc_rule = "evpn gateway-ip ipv4";
+ rhc->rhc_event = RMAP_EVENT_SET_DELETED;
+
+ rv = generic_set_add(rhc->rhc_rmi, "evpn gateway-ip ipv4", type,
+ args->errmsg, args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv4_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6
+ */
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *type;
+ int rv;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ type = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = generic_set_delete;
+ rhc->rhc_rule = "evpn gateway-ip ipv6";
+ rhc->rhc_event = RMAP_EVENT_SET_DELETED;
+
+ rv = generic_set_add(rhc->rhc_rmi, "evpn gateway-ip ipv6", type,
+ args->errmsg, args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
diff --git a/lib/routemap.h b/lib/routemap.h
index 5b6b64eaeb..4d76ae1536 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -366,6 +366,10 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(A, "frr-bgp-route-map:ipv4-vpn-address"))
#define IS_SET_BGP_IPV4_NH(A) \
(strmatch(A, "frr-bgp-route-map:set-ipv4-nexthop"))
+#define IS_SET_BGP_EVPN_GATEWAY_IP_IPV4(A) \
+ (strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv4"))
+#define IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(A) \
+ (strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv6"))
/* Prototypes. */
extern void route_map_init(void);
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index e11b9eea74..bf982cfa2b 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -1248,6 +1248,16 @@ void route_map_action_show(struct vty *vty, struct lyd_node *dnode,
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:ipv4-nexthop"));
+ } else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV4(action)) {
+ vty_out(vty, " set evpn gateway-ip ipv4 %s\n",
+ yang_dnode_get_string(
+ dnode,
+ "./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4"));
+ } else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(action)) {
+ vty_out(vty, " set evpn gateway-ip ipv6 %s\n",
+ yang_dnode_get_string(
+ dnode,
+ "./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
}
}
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index ca60c8f7b6..1c990b5ed9 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -300,6 +300,18 @@ module frr-bgp-route-map {
"Set BGP large community list (for deletion)";
}
+ identity set-evpn-gateway-ip-ipv4 {
+ base frr-route-map:rmap-set-type;
+ description
+ "Set EVPN gateway IP overlay index IPv4";
+ }
+
+ identity set-evpn-gateway-ip-ipv6 {
+ base frr-route-map:rmap-set-type;
+ description
+ "Set EVPN gateway IP overlay index IPv6";
+ }
+
grouping extcommunity-non-transitive-types {
leaf two-octet-as-specific {
type boolean;
@@ -816,5 +828,25 @@ module frr-bgp-route-map {
type bgp-filter:bgp-list-name;
}
}
+ case evpn-gateway-ip-ipv4 {
+ when
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
+ 'frr-bgp-route-map:set-evpn-gateway-ip-ipv4')";
+ description
+ "Set EVPN gateway IP overlay index IPv4";
+ leaf evpn-gateway-ip-ipv4 {
+ type inet:ipv4-address;
+ }
+ }
+ case evpn-gateway-ip-ipv6 {
+ when
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
+ 'frr-bgp-route-map:set-evpn-gateway-ip-ipv6')";
+ description
+ "Set EVPN gateway IP overlay index IPv6";
+ leaf evpn-gateway-ip-ipv6 {
+ type inet:ipv6-address;
+ }
+ }
}
}