network/route: also use RouteNextHop for managing gateway
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 12 Jan 2024 06:23:17 +0000 (15:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 15 Jan 2024 01:28:25 +0000 (10:28 +0900)
No functional change, just refactoring.

src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp4.c
src/network/networkd-json.c
src/network/networkd-ndisc.c
src/network/networkd-route-nexthop.c
src/network/networkd-route-util.c
src/network/networkd-route.c
src/network/networkd-route.h

index 168b45349eb3609584f9f27b582d4ca744cd5ec1..b30527e99fcca89406cb7b2ad0637f7f25ac7fd2 100644 (file)
@@ -782,8 +782,8 @@ static int dhcp4_pd_request_default_gateway_on_6rd_tunnel(Link *link, const stru
 
         route->source = NETWORK_CONFIG_SOURCE_DHCP_PD;
         route->family = AF_INET6;
-        route->gw_family = AF_INET6;
-        route->gw.in6.s6_addr32[3] = br_address->s_addr;
+        route->nexthop.family = AF_INET6;
+        route->nexthop.gw.in6.s6_addr32[3] = br_address->s_addr;
         route->scope = RT_SCOPE_UNIVERSE;
         route->protocol = RTPROT_DHCP;
         route->priority = IP6_RT_PRIO_USER;
index 44ed272387ddd7e128a4a927913395531b05607a..b56106867bd529b65b9983ae4a61f65fc744ac14 100644 (file)
@@ -482,8 +482,8 @@ static int dhcp4_request_route_auto(
                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
 
                 route->scope = RT_SCOPE_HOST;
-                route->gw_family = AF_UNSPEC;
-                route->gw = IN_ADDR_NULL;
+                route->nexthop.family = AF_UNSPEC;
+                route->nexthop.gw = IN_ADDR_NULL;
                 route->prefsrc = IN_ADDR_NULL;
 
         } else if (in4_addr_equal(&route->dst.in, &address)) {
@@ -493,8 +493,8 @@ static int dhcp4_request_route_auto(
                                        IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
 
                 route->scope = RT_SCOPE_HOST;
-                route->gw_family = AF_UNSPEC;
-                route->gw = IN_ADDR_NULL;
+                route->nexthop.family = AF_UNSPEC;
+                route->nexthop.gw = IN_ADDR_NULL;
                 route->prefsrc.in = address;
 
         } else if (in4_addr_is_null(gw)) {
@@ -516,8 +516,8 @@ static int dhcp4_request_route_auto(
                 }
 
                 route->scope = RT_SCOPE_LINK;
-                route->gw_family = AF_UNSPEC;
-                route->gw = IN_ADDR_NULL;
+                route->nexthop.family = AF_UNSPEC;
+                route->nexthop.gw = IN_ADDR_NULL;
                 route->prefsrc.in = address;
 
         } else {
@@ -526,8 +526,8 @@ static int dhcp4_request_route_auto(
                         return r;
 
                 route->scope = RT_SCOPE_UNIVERSE;
-                route->gw_family = AF_INET;
-                route->gw.in = *gw;
+                route->nexthop.family = AF_INET;
+                route->nexthop.gw.in = *gw;
                 route->prefsrc.in = address;
         }
 
@@ -619,8 +619,8 @@ static int dhcp4_request_default_gateway(Link *link) {
                 return r;
 
         /* Next, add a default gateway. */
-        route->gw_family = AF_INET;
-        route->gw.in = router;
+        route->nexthop.family = AF_INET;
+        route->nexthop.gw.in = router;
         route->prefsrc.in = address;
 
         return dhcp4_request_route(TAKE_PTR(route), link);
@@ -641,7 +641,7 @@ static int dhcp4_request_semi_static_routes(Link *link) {
                 if (!rt->gateway_from_dhcp_or_ra)
                         continue;
 
-                if (rt->gw_family != AF_INET)
+                if (rt->nexthop.family != AF_INET)
                         continue;
 
                 assert(rt->family == AF_INET);
@@ -663,7 +663,7 @@ static int dhcp4_request_semi_static_routes(Link *link) {
                 if (r < 0)
                         return r;
 
-                route->gw.in = gw;
+                route->nexthop.gw.in = gw;
 
                 r = dhcp4_request_route(TAKE_PTR(route), link);
                 if (r < 0)
index e62e57b7652d4587a8119f132f1d2bddef7312a0..9ca54db5ed5408b59bf00a50a25c8611dcc9897e 100644 (file)
@@ -237,7 +237,7 @@ static int route_append_json(Route *route, JsonVariant **array) {
                                 JSON_BUILD_PAIR_INTEGER("Family", route->family),
                                 JSON_BUILD_PAIR_IN_ADDR("Destination", &route->dst, route->family),
                                 JSON_BUILD_PAIR_UNSIGNED("DestinationPrefixLength", route->dst_prefixlen),
-                                JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->gw, route->gw_family),
+                                JSON_BUILD_PAIR_IN_ADDR_NON_NULL("Gateway", &route->nexthop.gw, route->nexthop.family),
                                 JSON_BUILD_PAIR_CONDITION(route->src_prefixlen > 0,
                                                           "Source", JSON_BUILD_IN_ADDR(&route->src, route->family)),
                                 JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("SourcePrefixLength", route->src_prefixlen),
index 7cfb9824034ef0e347810380acf1fc6d2b076804..33d11509d3715c5e91228dcd3334e30b69c88146 100644 (file)
@@ -321,8 +321,8 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
 
                 route->family = AF_INET6;
                 route->pref = preference;
-                route->gw_family = AF_INET6;
-                route->gw.in6 = gateway;
+                route->nexthop.family = AF_INET6;
+                route->nexthop.gw.in6 = gateway;
                 route->lifetime_usec = lifetime_usec;
 
                 r = ndisc_request_route(TAKE_PTR(route), link, rt);
@@ -337,14 +337,14 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
                 if (!route_gw->gateway_from_dhcp_or_ra)
                         continue;
 
-                if (route_gw->gw_family != AF_INET6)
+                if (route_gw->nexthop.family != AF_INET6)
                         continue;
 
                 r = route_dup(route_gw, &route);
                 if (r < 0)
                         return r;
 
-                route->gw.in6 = gateway;
+                route->nexthop.gw.in6 = gateway;
                 if (!route->pref_set)
                         route->pref = preference;
                 route->lifetime_usec = lifetime_usec;
@@ -626,8 +626,8 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
 
         route->family = AF_INET6;
         route->pref = preference;
-        route->gw.in6 = gateway;
-        route->gw_family = AF_INET6;
+        route->nexthop.gw.in6 = gateway;
+        route->nexthop.family = AF_INET6;
         route->dst.in6 = dst;
         route->dst_prefixlen = prefixlen;
         route->lifetime_usec = lifetime_usec;
index 2a213f94a6015ed13eea9ae94636f568b5cd4983..028504537c225334203237e9e6752228e019c123 100644 (file)
@@ -31,6 +31,7 @@ RouteNextHop* route_nexthop_free(RouteNextHop *nh) {
 void route_nexthops_done(Route *route) {
         assert(route);
 
+        route_nexthop_done(&route->nexthop);
         ordered_set_free(route->nexthops);
 }
 
@@ -157,7 +158,7 @@ int route_nexthops_is_ready_to_configure(const Route *route, Link *link) {
                 return true;
 
         if (ordered_set_isempty(route->nexthops))
-                return gateway_is_ready(link, FLAGS_SET(route->flags, RTNH_F_ONLINK), route->gw_family, &route->gw);
+                return route_nexthop_is_ready_to_configure(&route->nexthop, link, FLAGS_SET(route->flags, RTNH_F_ONLINK));
 
         RouteNextHop *nh;
         ORDERED_SET_FOREACH(nh, route->nexthops)
@@ -192,12 +193,12 @@ int route_nexthops_to_string(const Route *route, char **ret) {
         }
 
         if (ordered_set_isempty(route->nexthops)) {
-                if (in_addr_is_set(route->gw_family, &route->gw))
-                        buf = strjoin("gw: ", IN_ADDR_TO_STRING(route->gw_family, &route->gw));
+                if (in_addr_is_set(route->nexthop.family, &route->nexthop.gw))
+                        buf = strjoin("gw: ", IN_ADDR_TO_STRING(route->nexthop.family, &route->nexthop.gw));
                 else if (route->gateway_from_dhcp_or_ra) {
-                        if (route->gw_family == AF_INET)
+                        if (route->nexthop.family == AF_INET)
                                 buf = strdup("gw: _dhcp4");
-                        else if (route->gw_family == AF_INET6)
+                        else if (route->nexthop.family == AF_INET6)
                                 buf = strdup("gw: _ipv6ra");
                         else
                                 buf = strdup("gw: _dhcp");
@@ -349,15 +350,15 @@ int route_nexthops_set_netlink_message(Link *link, const Route *route, sd_netlin
 
         if (ordered_set_isempty(route->nexthops)) {
 
-                if (in_addr_is_set(route->gw_family, &route->gw)) {
-                        if (route->gw_family == route->family)
-                                r = netlink_message_append_in_addr_union(message, RTA_GATEWAY, route->gw_family, &route->gw);
+                if (in_addr_is_set(route->nexthop.family, &route->nexthop.gw)) {
+                        if (route->nexthop.family == route->family)
+                                r = netlink_message_append_in_addr_union(message, RTA_GATEWAY, route->nexthop.family, &route->nexthop.gw);
                         else {
                                 assert(route->family == AF_INET);
                                 r = sd_netlink_message_append_data(message, RTA_VIA,
                                                                    &(const RouteVia) {
-                                                                           .family = route->gw_family,
-                                                                           .address = route->gw,
+                                                                           .family = route->nexthop.family,
+                                                                           .address = route->nexthop.gw,
                                                                    }, sizeof(RouteVia));
                         }
                         if (r < 0)
@@ -479,9 +480,9 @@ int route_nexthops_read_netlink_message(Route *route, sd_netlink_message *messag
                 return log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m");
 
         if (ifindex > 0) {
-                r = netlink_message_read_in_addr_union(message, RTA_GATEWAY, route->family, &route->gw);
+                r = netlink_message_read_in_addr_union(message, RTA_GATEWAY, route->family, &route->nexthop.gw);
                 if (r >= 0) {
-                        route->gw_family = route->family;
+                        route->nexthop.family = route->family;
                         return 0;
                 }
                 if (r != -ENODATA)
@@ -493,8 +494,8 @@ int route_nexthops_read_netlink_message(Route *route, sd_netlink_message *messag
                 RouteVia via;
                 r = sd_netlink_message_read(message, RTA_VIA, sizeof(via), &via);
                 if (r >= 0) {
-                        route->gw_family = via.family;
-                        route->gw = via.address;
+                        route->nexthop.family = via.family;
+                        route->nexthop.gw = via.address;
                         return 0;
                 }
                 if (r != -ENODATA)
@@ -525,7 +526,7 @@ int route_section_verify_nexthops(Route *route) {
         if (route->gateway_from_dhcp_or_ra) {
                 assert(route->network);
 
-                if (route->gw_family == AF_UNSPEC)
+                if (route->nexthop.family == AF_UNSPEC)
                         /* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
                         switch (route->family) {
                         case AF_UNSPEC:
@@ -533,7 +534,7 @@ int route_section_verify_nexthops(Route *route) {
                                             "Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
                                             route->section->filename, route->section->line);
 
-                                route->gw_family = route->family = AF_INET;
+                                route->nexthop.family = route->family = AF_INET;
                                 break;
                         case AF_INET:
                         case AF_INET6:
@@ -541,7 +542,7 @@ int route_section_verify_nexthops(Route *route) {
                                             "Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
                                             route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
 
-                                route->gw_family = route->family;
+                                route->nexthop.family = route->family;
                                 break;
                         default:
                                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
@@ -549,13 +550,13 @@ int route_section_verify_nexthops(Route *route) {
                                                          route->section->filename, route->section->line);
                         }
 
-                if (route->gw_family == AF_INET && !FLAGS_SET(route->network->dhcp, ADDRESS_FAMILY_IPV4))
+                if (route->nexthop.family == AF_INET && !FLAGS_SET(route->network->dhcp, ADDRESS_FAMILY_IPV4))
                         return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                                  "%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
                                                  "Ignoring [Route] section from line %u.",
                                                  route->section->filename, route->section->line);
 
-                if (route->gw_family == AF_INET6 && !route->network->ipv6_accept_ra)
+                if (route->nexthop.family == AF_INET6 && !route->network->ipv6_accept_ra)
                         return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                                  "%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
                                                  "Ignoring [Route] section from line %u.",
@@ -564,7 +565,7 @@ int route_section_verify_nexthops(Route *route) {
 
         /* When only Gateway= is specified, assume the route family based on the Gateway address. */
         if (route->family == AF_UNSPEC)
-                route->family = route->gw_family;
+                route->family = route->nexthop.family;
 
         if (route->family == AF_UNSPEC) {
                 assert(route->section);
@@ -576,7 +577,7 @@ int route_section_verify_nexthops(Route *route) {
                                          route->section->filename, route->section->line);
         }
 
-        if (route->gateway_onlink < 0 && in_addr_is_set(route->gw_family, &route->gw) &&
+        if (route->gateway_onlink < 0 && in_addr_is_set(route->nexthop.family, &route->nexthop.gw) &&
             route->network && ordered_hashmap_isempty(route->network->addresses_by_section)) {
                 /* If no address is configured, in most cases the gateway cannot be reachable.
                  * TODO: we may need to improve the condition above. */
@@ -590,7 +591,7 @@ int route_section_verify_nexthops(Route *route) {
                 SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink);
 
         if (route->family == AF_INET6) {
-                if (route->gw_family == AF_INET)
+                if (route->nexthop.family == AF_INET)
                         return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                                  "%s: IPv4 gateway is configured for IPv6 route. "
                                                  "Ignoring [Route] section from line %u.",
@@ -607,7 +608,7 @@ int route_section_verify_nexthops(Route *route) {
 
         if (route->nexthop_id != 0 &&
             (route->gateway_from_dhcp_or_ra ||
-             in_addr_is_set(route->gw_family, &route->gw) ||
+             in_addr_is_set(route->nexthop.family, &route->nexthop.gw) ||
              !ordered_set_isempty(route->nexthops)))
                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                          "%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
@@ -616,7 +617,7 @@ int route_section_verify_nexthops(Route *route) {
 
         if (route_type_is_reject(route) &&
             (route->gateway_from_dhcp_or_ra ||
-             in_addr_is_set(route->gw_family, &route->gw) ||
+             in_addr_is_set(route->nexthop.family, &route->nexthop.gw) ||
              !ordered_set_isempty(route->nexthops)))
                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                          "%s: reject type route cannot be specified with Gateway= or MultiPathRoute=. "
@@ -624,7 +625,7 @@ int route_section_verify_nexthops(Route *route) {
                                          route->section->filename, route->section->line);
 
         if ((route->gateway_from_dhcp_or_ra ||
-             in_addr_is_set(route->gw_family, &route->gw)) &&
+             in_addr_is_set(route->nexthop.family, &route->nexthop.gw)) &&
             !ordered_set_isempty(route->nexthops))
                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
                                          "%s: Gateway= cannot be specified with MultiPathRoute=. "
@@ -678,38 +679,38 @@ int config_parse_gateway(
 
                 if (isempty(rvalue)) {
                         route->gateway_from_dhcp_or_ra = false;
-                        route->gw_family = AF_UNSPEC;
-                        route->gw = IN_ADDR_NULL;
+                        route->nexthop.family = AF_UNSPEC;
+                        route->nexthop.gw = IN_ADDR_NULL;
                         TAKE_PTR(route);
                         return 0;
                 }
 
                 if (streq(rvalue, "_dhcp")) {
                         route->gateway_from_dhcp_or_ra = true;
-                        route->gw_family = AF_UNSPEC;
-                        route->gw = IN_ADDR_NULL;
+                        route->nexthop.family = AF_UNSPEC;
+                        route->nexthop.gw = IN_ADDR_NULL;
                         TAKE_PTR(route);
                         return 0;
                 }
 
                 if (streq(rvalue, "_dhcp4")) {
                         route->gateway_from_dhcp_or_ra = true;
-                        route->gw_family = AF_INET;
-                        route->gw = IN_ADDR_NULL;
+                        route->nexthop.family = AF_INET;
+                        route->nexthop.gw = IN_ADDR_NULL;
                         TAKE_PTR(route);
                         return 0;
                 }
 
                 if (streq(rvalue, "_ipv6ra")) {
                         route->gateway_from_dhcp_or_ra = true;
-                        route->gw_family = AF_INET6;
-                        route->gw = IN_ADDR_NULL;
+                        route->nexthop.family = AF_INET6;
+                        route->nexthop.gw = IN_ADDR_NULL;
                         TAKE_PTR(route);
                         return 0;
                 }
         }
 
-        r = in_addr_from_string_auto(rvalue, &route->gw_family, &route->gw);
+        r = in_addr_from_string_auto(rvalue, &route->nexthop.family, &route->nexthop.gw);
         if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
index 00c267e6924e1213854cf3298b8bbd277661976f..fde7dfa5d42e52c8b1bd03f130836de10a805547 100644 (file)
@@ -74,7 +74,7 @@ bool link_find_default_gateway(Link *link, int family, Route **gw) {
                         continue;
                 if (route->scope != RT_SCOPE_UNIVERSE)
                         continue;
-                if (!in_addr_is_set(route->gw_family, &route->gw))
+                if (!in_addr_is_set(route->nexthop.family, &route->nexthop.gw))
                         continue;
 
                 /* Found a default gateway. */
@@ -83,7 +83,7 @@ bool link_find_default_gateway(Link *link, int family, Route **gw) {
 
                 /* If we have already found another gw, then let's compare their weight and priority. */
                 if (*gw) {
-                        if (route->gw_weight > (*gw)->gw_weight)
+                        if (route->nexthop.weight > (*gw)->nexthop.weight)
                                 continue;
                         if (route->priority >= (*gw)->priority)
                                 continue;
index 70a83c9d205f6b2f358e4255908a54d196f4b9f1..d9974041722337fd03c18657fc98cb0c075dacb0 100644 (file)
@@ -124,10 +124,10 @@ static void route_hash_func(const Route *route, struct siphash *state) {
                 siphash24_compress_typesafe(route->src_prefixlen, state);
                 in_addr_hash_func(&route->src, route->family, state);
 
-                siphash24_compress_typesafe(route->gw_family, state);
-                if (IN_SET(route->gw_family, AF_INET, AF_INET6)) {
-                        in_addr_hash_func(&route->gw, route->gw_family, state);
-                        siphash24_compress_typesafe(route->gw_weight, state);
+                siphash24_compress_typesafe(route->nexthop.family, state);
+                if (IN_SET(route->nexthop.family, AF_INET, AF_INET6)) {
+                        in_addr_hash_func(&route->nexthop.gw, route->nexthop.family, state);
+                        siphash24_compress_typesafe(route->nexthop.weight, state);
                 }
 
                 in_addr_hash_func(&route->prefsrc, route->family, state);
@@ -174,16 +174,16 @@ static int route_compare_func(const Route *a, const Route *b) {
                 if (r != 0)
                         return r;
 
-                r = CMP(a->gw_family, b->gw_family);
+                r = CMP(a->nexthop.family, b->nexthop.family);
                 if (r != 0)
                         return r;
 
-                if (IN_SET(a->gw_family, AF_INET, AF_INET6)) {
-                        r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family));
+                if (IN_SET(a->nexthop.family, AF_INET, AF_INET6)) {
+                        r = memcmp(&a->nexthop.gw, &b->nexthop.gw, FAMILY_ADDRESS_SIZE(a->family));
                         if (r != 0)
                                 return r;
 
-                        r = CMP(a->gw_weight, b->gw_weight);
+                        r = CMP(a->nexthop.weight, b->nexthop.weight);
                         if (r != 0)
                                 return r;
                 }
@@ -329,11 +329,11 @@ static void route_apply_nexthop(Route *route, const NextHop *nh, uint8_t nh_weig
         assert(nh);
         assert(hashmap_isempty(nh->group));
 
-        route->gw_family = nh->family;
-        route->gw = nh->gw;
+        route->nexthop.family = nh->family;
+        route->nexthop.gw = nh->gw;
 
         if (nh_weight != UINT8_MAX)
-                route->gw_weight = nh_weight;
+                route->nexthop.weight = nh_weight;
 
         if (nh->blackhole)
                 route->type = RTN_BLACKHOLE;
@@ -343,9 +343,9 @@ static void route_apply_route_nexthop(Route *route, const RouteNextHop *nh) {
         assert(route);
         assert(nh);
 
-        route->gw_family = nh->family;
-        route->gw = nh->gw;
-        route->gw_weight = nh->weight;
+        route->nexthop.family = nh->family;
+        route->nexthop.gw = nh->gw;
+        route->nexthop.weight = nh->weight;
 }
 
 typedef struct ConvertedRoutes {
@@ -2036,7 +2036,7 @@ int route_section_verify(Route *route) {
                         route->scope = RT_SCOPE_LINK;
                 else if (IN_SET(route->type, RTN_UNICAST, RTN_UNSPEC) &&
                          !route->gateway_from_dhcp_or_ra &&
-                         !in_addr_is_set(route->gw_family, &route->gw) &&
+                         !in_addr_is_set(route->nexthop.family, &route->nexthop.gw) &&
                          ordered_set_isempty(route->nexthops) &&
                          route->nexthop_id == 0)
                         route->scope = RT_SCOPE_LINK;
index 1c020f68423df5961270e142540e70a8bf801c9b..47406dd6350caec9cdc39d0c0addc840619b1a3a 100644 (file)
@@ -37,8 +37,6 @@ struct Route {
         union in_addr_union provider; /* DHCP server or router address */
 
         int family;
-        int gw_family;
-        uint32_t gw_weight;
 
         unsigned char dst_prefixlen;
         unsigned char src_prefixlen;
@@ -51,10 +49,11 @@ struct Route {
         unsigned char pref;
         unsigned flags;
         int gateway_onlink; /* Only used in conf parser and route_section_verify(). */
-        uint32_t nexthop_id;
 
         /* nexthops */
+        RouteNextHop nexthop; /* RTA_OIF, and RTA_GATEWAY or RTA_VIA (IPv4 only) */
         OrderedSet *nexthops; /* RTA_MULTIPATH */
+        uint32_t nexthop_id; /* RTA_NH_ID */
 
         /* metrics (RTA_METRICS) */
         RouteMetric metric;
@@ -74,7 +73,6 @@ struct Route {
         bool pref_set:1;
         bool gateway_from_dhcp_or_ra:1;
 
-        union in_addr_union gw;
         union in_addr_union dst;
         union in_addr_union src;
         union in_addr_union prefsrc;