From 8fc41e81f0881d4f35564b57d54f92ca410b8de6 Mon Sep 17 00:00:00 2001 From: Christopher Dziomba Date: Mon, 14 Apr 2025 19:13:45 +0200 Subject: [PATCH] staticd: Add v4-via-v6 nexthop support 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 --- staticd/static_vty.c | 68 ++++++++++++++++++++++++------------------ staticd/static_zebra.c | 14 ++++----- 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 6fc4f067d9..087df8efa0 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -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$gate \ + $gate \ $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$gate \ + $gate \ $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\ - \ - $ifname> \ - [{ \ - tag (1-4294967295) \ - |(1-255)$distance \ - |vrf NAME \ - |label WORD \ - |table (1-4294967295) \ - |nexthop-vrf NAME \ - |color (1-4294967295) \ + \ + <$gate|$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\ - \ - $ifname> \ - [{ \ - tag (1-4294967295) \ - |(1-255)$distance \ - |label WORD \ - |table (1-4294967295) \ - |nexthop-vrf NAME \ - |color (1-4294967295) \ + \ + <$gate|$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" diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index f02fe1e95c..cc09b42836 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -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) -- 2.39.5