]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_routemap.c
Merge pull request #8888 from dlqs/lua-call
[mirror_frr.git] / bgpd / bgp_routemap.c
index 4d67fb66dbee812f9ffecdf9b8c3d589655e9ce9..529abcbea07b35a393c578e71be6f5448be38c73 100644 (file)
@@ -1067,6 +1067,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,
@@ -4050,6 +4115,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",
@@ -6107,6 +6314,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);
@@ -6150,6 +6359,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);