]> git.puffer.fish Git - matthieu/frr.git/commitdiff
staticd: Add v4-via-v6 nexthop support
authorChristopher Dziomba <christopher.dziomba@telekom.de>
Mon, 14 Apr 2025 17:13:45 +0000 (19:13 +0200)
committerChristopher Dziomba <christopher.dziomba@telekom.de>
Mon, 14 Apr 2025 17:22:39 +0000 (19:22 +0200)
Routing v4 over an v6 nexthop is already well supported within zebra
(and FRR). This adds support to staticd, allowing an IPv6 nexthop to
be provided to ip route statements. For this the commands are
extended and the address family is parsed from the parameter.

When receiving nht updates from zebra, both AFIs are checked because
prefixes could exist in both. Additionally when route_node is known,
family of prefix is used instead of nexthop.

Signed-off-by: Christopher Dziomba <christopher.dziomba@telekom.de>
staticd/static_vty.c
staticd/static_zebra.c

index 6fc4f067d900eb62fe550519980997cdf34d02f8..087df8efa027e980cd59b4e4f8929ec255d7ca9b 100644 (file)
@@ -86,6 +86,7 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
        uint8_t segs_stack_id = 0;
        char *orig_label = NULL, *orig_seg = NULL;
        const char *buf_gate_str;
+       struct ipaddr gate_ip;
        uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
        route_tag_t tag = 0;
        uint32_t table_id = 0;
@@ -149,22 +150,27 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
 
        if (src.prefixlen)
                prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
-       if (args->gateway)
+
+       if (args->gateway) {
                buf_gate_str = args->gateway;
-       else
+               if (str2ipaddr(args->gateway, &gate_ip) != 0) {
+                       vty_out(vty, "%% Invalid gateway address %s\n", args->gateway);
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+       } else
                buf_gate_str = "";
 
        if (args->gateway == NULL && args->interface_name == NULL)
                type = STATIC_BLACKHOLE;
        else if (args->gateway && args->interface_name) {
-               if (args->afi == AFI_IP)
+               if (gate_ip.ipa_type == IPADDR_V4)
                        type = STATIC_IPV4_GATEWAY_IFNAME;
                else
                        type = STATIC_IPV6_GATEWAY_IFNAME;
        } else if (args->interface_name)
                type = STATIC_IFNAME;
        else {
-               if (args->afi == AFI_IP)
+               if (gate_ip.ipa_type == IPADDR_V4)
                        type = STATIC_IPV4_GATEWAY;
                else
                        type = STATIC_IPV6_GATEWAY;
@@ -552,7 +558,7 @@ DEFPY_YANG(ip_route_address_interface,
       ip_route_address_interface_cmd,
       "[no] ip route\
        <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
-       A.B.C.D$gate                                   \
+       <A.B.C.D|X:X::X:X>$gate                        \
        <INTERFACE|Null0>$ifname                       \
        [{                                             \
          tag (1-4294967295)                           \
@@ -571,7 +577,8 @@ DEFPY_YANG(ip_route_address_interface,
       "IP destination prefix (e.g. 10.0.0.0/8)\n"
       "IP destination prefix\n"
       "IP destination prefix mask\n"
-      "IP gateway address\n"
+      "IPv4 gateway address\n"
+      "IPv6 gateway address\n"
       "IP gateway interface name\n"
       "Null interface\n"
       "Set tag for this route\n"
@@ -624,7 +631,7 @@ DEFPY_YANG(ip_route_address_interface_vrf,
       ip_route_address_interface_vrf_cmd,
       "[no] ip route\
        <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
-       A.B.C.D$gate                                   \
+       <A.B.C.D|X:X::X:X>$gate                        \
        <INTERFACE|Null0>$ifname                       \
        [{                                             \
          tag (1-4294967295)                           \
@@ -642,7 +649,8 @@ DEFPY_YANG(ip_route_address_interface_vrf,
       "IP destination prefix (e.g. 10.0.0.0/8)\n"
       "IP destination prefix\n"
       "IP destination prefix mask\n"
-      "IP gateway address\n"
+      "IPv4 gateway address\n"
+      "IPv6 gateway address\n"
       "IP gateway interface name\n"
       "Null interface\n"
       "Set tag for this route\n"
@@ -693,16 +701,16 @@ DEFPY_YANG(ip_route_address_interface_vrf,
 DEFPY_YANG(ip_route,
       ip_route_cmd,
       "[no] ip route\
-       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
-       <A.B.C.D$gate|<INTERFACE|Null0>$ifname>        \
-       [{                                             \
-         tag (1-4294967295)                           \
-         |(1-255)$distance                            \
-         |vrf NAME                                    \
-         |label WORD                                  \
-         |table (1-4294967295)                        \
-         |nexthop-vrf NAME                            \
-         |color (1-4294967295)                        \
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>     \
+       <<A.B.C.D|X:X::X:X>$gate|<INTERFACE|Null0>$ifname> \
+       [{                                                 \
+         tag (1-4294967295)                               \
+         |(1-255)$distance                                \
+         |vrf NAME                                        \
+         |label WORD                                      \
+         |table (1-4294967295)                            \
+         |nexthop-vrf NAME                                \
+         |color (1-4294967295)                            \
          |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
          |segments WORD \
           }]",
@@ -711,7 +719,8 @@ DEFPY_YANG(ip_route,
       "IP destination prefix (e.g. 10.0.0.0/8)\n"
       "IP destination prefix\n"
       "IP destination prefix mask\n"
-      "IP gateway address\n"
+      "IPv4 gateway address\n"
+      "IPv6 gateway address\n"
       "IP gateway interface name\n"
       "Null interface\n"
       "Set tag for this route\n"
@@ -761,15 +770,15 @@ DEFPY_YANG(ip_route,
 DEFPY_YANG(ip_route_vrf,
       ip_route_vrf_cmd,
       "[no] ip route\
-       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
-       <A.B.C.D$gate|<INTERFACE|Null0>$ifname>        \
-       [{                                             \
-         tag (1-4294967295)                           \
-         |(1-255)$distance                            \
-         |label WORD                                  \
-         |table (1-4294967295)                        \
-         |nexthop-vrf NAME                            \
-         |color (1-4294967295)                        \
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>     \
+       <<A.B.C.D|X:X::X:X>$gate|<INTERFACE|Null0>$ifname> \
+       [{                                                 \
+         tag (1-4294967295)                               \
+         |(1-255)$distance                                \
+         |label WORD                                      \
+         |table (1-4294967295)                            \
+         |nexthop-vrf NAME                                \
+         |color (1-4294967295)                            \
          |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
          |segments WORD \
           }]",
@@ -778,7 +787,8 @@ DEFPY_YANG(ip_route_vrf,
       "IP destination prefix (e.g. 10.0.0.0/8)\n"
       "IP destination prefix\n"
       "IP destination prefix mask\n"
-      "IP gateway address\n"
+      "IPv4 gateway address\n"
+      "IPv6 gateway address\n"
       "IP gateway interface name\n"
       "Null interface\n"
       "Set tag for this route\n"
index f02fe1e95c28c04fbff93c458fe3873938e1fcdd..cc09b428365fdc56e9210c21532fb751f077f289 100644 (file)
@@ -209,14 +209,10 @@ static void static_zebra_nexthop_update(struct vrf *vrf, struct prefix *matched,
                                        struct zapi_route *nhr)
 {
        struct static_nht_data *nhtd, lookup;
-       afi_t afi = AFI_IP;
 
        if (static_zclient->bfd_integration)
                bfd_nht_update(matched, nhr);
 
-       if (matched->family == AF_INET6)
-               afi = AFI_IP6;
-
        if (nhr->type == ZEBRA_ROUTE_CONNECT) {
                if (static_nexthop_is_local(vrf->vrf_id, matched,
                                            nhr->prefix.family))
@@ -233,8 +229,12 @@ static void static_zebra_nexthop_update(struct vrf *vrf, struct prefix *matched,
        if (nhtd) {
                nhtd->nh_num = nhr->nexthop_num;
 
-               static_nht_reset_start(matched, afi, nhr->safi, nhtd->nh_vrf_id);
-               static_nht_update(NULL, NULL, matched, nhr->nexthop_num, afi, nhr->safi,
+               /* The tracked nexthop might be used by IPv4 and IPv6 routes */
+               static_nht_reset_start(matched, AFI_IP, nhr->safi, nhtd->nh_vrf_id);
+               static_nht_update(NULL, NULL, matched, nhr->nexthop_num, AFI_IP, nhr->safi,
+                                 nhtd->nh_vrf_id);
+               static_nht_reset_start(matched, AFI_IP6, nhr->safi, nhtd->nh_vrf_id);
+               static_nht_update(NULL, NULL, matched, nhr->nexthop_num, AFI_IP6, nhr->safi,
                                  nhtd->nh_vrf_id);
        } else
                zlog_err("No nhtd?");
@@ -361,7 +361,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
        if (reg) {
                if (nhtd->nh_num) {
                        /* refresh with existing data */
-                       afi_t afi = prefix_afi(&lookup.nh);
+                       afi_t afi = prefix_afi(&rn->p);
 
                        if (nh->state == STATIC_NOT_INSTALLED ||
                            nh->state == STATIC_SENT_TO_ZEBRA)