From 860e636cf6855260634ef2f7f52af4635b1271c3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Feb 2019 21:25:13 +0900 Subject: [PATCH 01/11] network: minor coding style update --- src/network/networkd-dhcp4.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index d8ac4552f4c..ea5dab3858c 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -70,7 +70,7 @@ static int link_set_dhcp_routes(Link *link) { /* When the interface is part of an VRF use the VRFs routing table, unless * there is a another table specified. */ table = link->network->dhcp_route_table; - if (!link->network->dhcp_route_table_set && link->network->vrf != NULL) + if (!link->network->dhcp_route_table_set && link->network->vrf) table = VRF(link->network->vrf)->table; r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); @@ -135,14 +135,7 @@ static int link_set_dhcp_routes(Link *link) { log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); if (r >= 0 && !classless_route) { - _cleanup_(route_freep) Route *route = NULL; - _cleanup_(route_freep) Route *route_gw = NULL; - - r = route_new(&route); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate route: %m"); - - route->protocol = RTPROT_DHCP; + _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL; r = route_new(&route_gw); if (r < 0) @@ -166,9 +159,14 @@ static int link_set_dhcp_routes(Link *link) { link->dhcp4_messages++; + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + route->family = AF_INET; route->gw.in = gateway; route->prefsrc.in = address; + route->protocol = RTPROT_DHCP; route->priority = link->network->dhcp_route_metric; route->table = table; From 156ed65e3c6aa14b09a6ffd1138820569761319c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Feb 2019 21:28:13 +0900 Subject: [PATCH 02/11] network: add more debugging logs when adding, removing, updateing and configuring route --- src/network/networkd-manager.c | 22 ++++++++++++++++++++++ src/network/networkd-route.c | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index c8d369e2a0f..4b69e6afaeb 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -422,6 +422,28 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo (void) route_get(link, family, &dst, dst_prefixlen, tos, priority, table, &route); + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, + *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL; + + if (!in_addr_is_null(family, &dst)) { + (void) in_addr_to_string(family, &dst, &buf_dst); + (void) asprintf(&buf_dst_prefixlen, "/%u", dst_prefixlen); + } + if (!in_addr_is_null(family, &src)) + (void) in_addr_to_string(family, &src, &buf_src); + if (!in_addr_is_null(family, &gw)) + (void) in_addr_to_string(family, &gw, &buf_gw); + if (!in_addr_is_null(family, &prefsrc)) + (void) in_addr_to_string(family, &prefsrc, &buf_prefsrc); + + log_link_debug(link, + "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s", + type == RTM_DELROUTE ? "Removing" : route ? "Updating" : "Adding", + strna(buf_dst), strempty(buf_dst_prefixlen), + strna(buf_src), strna(buf_gw), strna(buf_prefsrc)); + } + switch (type) { case RTM_NEWROUTE: if (!route) { diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 5553a7e3bd1..5014e48753e 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -513,6 +513,24 @@ int route_configure( set_size(link->routes) >= routes_max()) return -E2BIG; + if (DEBUG_LOGGING) { + _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL; + + if (!in_addr_is_null(route->family, &route->dst)) { + (void) in_addr_to_string(route->family, &route->dst, &dst); + (void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen); + } + if (!in_addr_is_null(route->family, &route->src)) + (void) in_addr_to_string(route->family, &route->src, &src); + if (!in_addr_is_null(route->family, &route->gw)) + (void) in_addr_to_string(route->family, &route->gw, &gw); + if (!in_addr_is_null(route->family, &route->prefsrc)) + (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc); + + log_link_debug(link, "Configuring route: dst: %s%s, src: %s, gw: %s, prefsrc: %s", + strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc)); + } + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, RTM_NEWROUTE, route->family, route->protocol); From d5fa3339601d83514c1a160fe5bd1f674f9668d2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 12:42:10 +0900 Subject: [PATCH 03/11] network: introduce Network::ipv6_accept_ra_route_table_set flag It will be used in later commit. --- src/network/networkd-network-gperf.gperf | 4 +-- src/network/networkd-network.c | 34 +++++++++++++++--------- src/network/networkd-network.h | 3 ++- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5d8aede5930..45343f43479 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -140,7 +140,7 @@ DHCP.UserClass, config_parse_dhcp_user_class, DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) -DHCP.RouteTable, config_parse_dhcp_route_table, 0, 0 +DHCP.RouteTable, config_parse_section_route_table, 0, 0 DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.IAID, config_parse_iaid, 0, 0 DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) @@ -148,7 +148,7 @@ DHCP.RapidCommit, config_parse_bool, DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) -IPv6AcceptRA.RouteTable, config_parse_uint32, 0, offsetof(Network, ipv6_accept_ra_route_table) +IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0 DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 12344ec695b..097eb0adeaf 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -207,6 +207,7 @@ int network_load_one(Manager *manager, const char *filename) { .allmulticast = -1, .ipv6_accept_ra_use_dns = true, .ipv6_accept_ra_route_table = RT_TABLE_MAIN, + .ipv6_accept_ra_route_table_set = false, }; r = config_parse_many(filename, network_dirs, dropin_dirname, @@ -1422,16 +1423,18 @@ int config_parse_dhcp_user_class( return 0; } -int config_parse_dhcp_route_table(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_section_route_table( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = data; uint32_t rt; int r; @@ -1444,12 +1447,17 @@ int config_parse_dhcp_route_table(const char *unit, r = safe_atou32(rvalue, &rt); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, - "Unable to read RouteTable, ignoring assignment: %s", rvalue); + "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue); return 0; } - network->dhcp_route_table = rt; - network->dhcp_route_table_set = true; + if (streq_ptr(section, "DHCP")) { + network->dhcp_route_table = rt; + network->dhcp_route_table_set = true; + } else { /* section is IPv6AcceptRA */ + network->ipv6_accept_ra_route_table = rt; + network->ipv6_accept_ra_route_table_set = true; + } return 0; } diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index f6e62cdd799..37c2b355fd1 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -213,6 +213,7 @@ struct Network { bool primary_slave; DHCPUseDomains ipv6_accept_ra_use_domains; uint32_t ipv6_accept_ra_route_table; + bool ipv6_accept_ra_route_table_set; union in_addr_union ipv6_token; IPv6PrivacyExtensions ipv6_privacy_extensions; @@ -308,7 +309,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode); -CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_table); +CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class); CONFIG_PARSER_PROTOTYPE(config_parse_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_iaid); From bdb9f580868906383d200bed1bb827647cb65a37 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 12:49:45 +0900 Subject: [PATCH 04/11] network: honor VRF table or explicitly specified route table --- src/network/networkd-dhcp4.c | 7 +------ src/network/networkd-dhcp6.c | 5 ++++- src/network/networkd-ipv4ll.c | 1 + src/network/networkd-link.c | 19 +++++++++++++++++++ src/network/networkd-link.h | 4 ++++ src/network/networkd-ndisc.c | 6 +++--- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index ea5dab3858c..ace8b254d14 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -6,7 +6,6 @@ #include "alloc-util.h" #include "hostname-util.h" #include "parse-util.h" -#include "netdev/vrf.h" #include "network-internal.h" #include "networkd-link.h" #include "networkd-manager.h" @@ -67,11 +66,7 @@ static int link_set_dhcp_routes(Link *link) { if (!link->network->dhcp_use_routes) return 0; - /* When the interface is part of an VRF use the VRFs routing table, unless - * there is a another table specified. */ - table = link->network->dhcp_route_table; - if (!link->network->dhcp_route_table_set && link->network->vrf) - table = VRF(link->network->vrf)->table; + table = link_get_dhcp_route_table(link); r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r < 0) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index c1fba03f9fe..183b3fa97fd 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -289,6 +289,7 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { if (pd_prefix_len < 64) { Route *route = NULL; + uint32_t table; (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf); @@ -300,8 +301,10 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { continue; } + table = link_get_dhcp_route_table(link); + route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, - 0, 0, 0, &route); + 0, 0, table, &route); route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE); diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 3562e90535d..56a4ff8b853 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -134,6 +134,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { route->scope = RT_SCOPE_LINK; route->protocol = RTPROT_STATIC; route->priority = IPV4LL_ROUTE_METRIC; + route->table = link_get_vrf_table(link); r = route_configure(route, link, ipv4ll_route_handler); if (r < 0) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 22392d70bc4..24946b1df82 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -14,6 +14,7 @@ #include "fd-util.h" #include "fileio.h" #include "missing_network.h" +#include "netdev/vrf.h" #include "netlink-util.h" #include "network-internal.h" #include "networkd-ipv6-proxy-ndp.h" @@ -32,6 +33,24 @@ #include "util.h" #include "virt.h" +uint32_t link_get_vrf_table(Link *link) { + return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN; +} + +uint32_t link_get_dhcp_route_table(Link *link) { + /* When the interface is part of an VRF use the VRFs routing table, unless + * another table is explicitly specified. */ + if (link->network->dhcp_route_table_set) + return link->network->dhcp_route_table; + return link_get_vrf_table(link); +} + +uint32_t link_get_ipv6_accept_ra_route_table(Link *link) { + if (link->network->ipv6_accept_ra_route_table_set) + return link->network->ipv6_accept_ra_route_table; + return link_get_vrf_table(link); +} + DUID* link_get_duid(Link *link) { if (link->network->duid.type != _DUID_TYPE_INVALID) return &link->network->duid; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index dcb1ea68dd9..344873f303f 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -185,6 +185,10 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int link_send_changed(Link *link, const char *property, ...) _sentinel_; +uint32_t link_get_vrf_table(Link *link); +uint32_t link_get_dhcp_route_table(Link *link); +uint32_t link_get_ipv6_accept_ra_route_table(Link *link); + /* Macros which append INTERFACE= to the message */ #define log_link_full(link, level, error, ...) \ diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index e5b8d115551..8fcb4851c44 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -103,7 +103,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; + route->table = link_get_ipv6_accept_ra_route_table(link); route->priority = link->network->dhcp_route_metric; route->protocol = RTPROT_RA; route->pref = preference; @@ -238,7 +238,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; + route->table = link_get_ipv6_accept_ra_route_table(link); route->priority = link->network->dhcp_route_metric; route->protocol = RTPROT_RA; route->flags = RTM_F_PREFIX; @@ -299,7 +299,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { return log_link_error_errno(link, r, "Could not allocate route: %m"); route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; + route->table = link_get_ipv6_accept_ra_route_table(link); route->protocol = RTPROT_RA; route->pref = preference; route->gw.in6 = gateway; From 793167508756f99e357a7a7c2a3a8d13a90c94c6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 13:00:25 +0900 Subject: [PATCH 05/11] network: configure ipv4ll route after address is set --- src/network/networkd-ipv4ll.c | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 56a4ff8b853..829dc48a0a1 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -65,12 +65,28 @@ static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *l link->ipv4ll_route = true; - if (link->ipv4ll_address == true) - link_check_ready(link); + link_check_ready(link); return 1; } +static int ipv4ll_route_configure(Link *link) { + _cleanup_(route_freep) Route *route = NULL; + int r; + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET; + route->scope = RT_SCOPE_LINK; + route->protocol = RTPROT_STATIC; + route->priority = IPV4LL_ROUTE_METRIC; + route->table = link_get_vrf_table(link); + + return route_configure(route, link, ipv4ll_route_handler); +} + static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -86,21 +102,26 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link link->ipv4ll_address = true; - if (link->ipv4ll_route) - link_check_ready(link); + r = ipv4ll_route_configure(link); + if (r < 0) { + log_link_error_errno(link, r, "Failed to configure ipv4ll route: %m"); + link_enter_failed(link); + } return 1; } static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { _cleanup_(address_freep) Address *ll_addr = NULL; - _cleanup_(route_freep) Route *route = NULL; struct in_addr address; int r; assert(ll); assert(link); + link->ipv4ll_address = false; + link->ipv4ll_route = false; + r = sd_ipv4ll_get_address(ll, &address); if (r == -ENOENT) return 0; @@ -124,24 +145,6 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { if (r < 0) return r; - link->ipv4ll_address = false; - - r = route_new(&route); - if (r < 0) - return r; - - route->family = AF_INET; - route->scope = RT_SCOPE_LINK; - route->protocol = RTPROT_STATIC; - route->priority = IPV4LL_ROUTE_METRIC; - route->table = link_get_vrf_table(link); - - r = route_configure(route, link, ipv4ll_route_handler); - if (r < 0) - return r; - - link->ipv4ll_route = false; - return 0; } @@ -177,6 +180,7 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) { case SD_IPV4LL_EVENT_BIND: r = ipv4ll_address_claimed(ll, link); if (r < 0) { + log_link_error(link, "Failed to configure ipv4ll address: %m"); link_enter_failed(link); return; } From 966ab36b102a098905de78b193e15f41cf70730a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 13:02:38 +0900 Subject: [PATCH 06/11] network: use _cleanup_ attribute at one more place --- src/network/networkd-dhcp6.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 183b3fa97fd..a95cd55b2c9 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -288,7 +288,7 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { } if (pd_prefix_len < 64) { - Route *route = NULL; + _cleanup_(route_freep) Route *route = NULL; uint32_t table; (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf); @@ -313,12 +313,9 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { log_link_warning_errno(link, r, "Cannot configure unreachable route for delegated subnet %s/%u: %m", strnull(buf), pd_prefix_len); - route_free(route); continue; } - route_free(route); - log_link_debug(link, "Configuring unreachable route for %s/%u", strnull(buf), pd_prefix_len); From 57445b53fb01e2ddd65530496b650131d7e437fb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 13:03:57 +0900 Subject: [PATCH 07/11] network: add missing error check --- src/network/networkd-dhcp6.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index a95cd55b2c9..90361c9f4a3 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -142,10 +142,15 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) { continue; } - route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, - 0, 0, 0, &route); - route_update(route, NULL, 0, NULL, NULL, 0, 0, - RTN_UNREACHABLE); + r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, 0, &route); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to add unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m", + strnull(buf), + pd_prefix_len); + continue; + } + + route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE); r = route_remove(route, link, dhcp6_route_remove_handler); if (r < 0) { @@ -303,10 +308,15 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { table = link_get_dhcp_route_table(link); - route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, - 0, 0, table, &route); - route_update(route, NULL, 0, NULL, NULL, 0, 0, - RTN_UNREACHABLE); + r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, 0, 0, table, &route); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to add unreachable route for DHCPv6 delegated subnet %s/%u: %m", + strnull(buf), + pd_prefix_len); + continue; + } + + route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE); r = route_configure(route, link, dhcp6_route_handler); if (r < 0) { From 89b9a975739889541839bb56c1e78bebeeb77709 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 17 Feb 2019 01:15:19 +0900 Subject: [PATCH 08/11] network: disable link local addressing on vrf See the commment in vrf_link_scope_lookup() in drivers/net/vrf.c of Linux kernel. --- src/network/networkd-link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 24946b1df82..e9c814ade54 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -106,7 +106,7 @@ static bool link_ipv4ll_enabled(Link *link) { if (!link->network) return false; - if (streq_ptr(link->kind, "wireguard")) + if (STRPTR_IN_SET(link->kind, "vrf", "wireguard")) return false; return link->network->link_local & ADDRESS_FAMILY_IPV4; @@ -124,7 +124,7 @@ static bool link_ipv6ll_enabled(Link *link) { if (!link->network) return false; - if (streq_ptr(link->kind, "wireguard")) + if (STRPTR_IN_SET(link->kind, "vrf", "wireguard")) return false; return link->network->link_local & ADDRESS_FAMILY_IPV6; From 3b51bbe135b1143347367057415edf163b99b249 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Feb 2019 21:29:00 +0900 Subject: [PATCH 09/11] test-network: drop unused variable --- test/test-network/systemd-networkd-tests.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 1fc7094d281..143fba20fba 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -86,8 +86,6 @@ def tearDownModule(): subprocess.check_call('systemctl start systemd-networkd.service', shell=True) class Utilities(): - dhcp_server_data = [] - def read_link_attr(self, link, dev, attribute): with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f: return f.readline().strip() From 0ae7a66d1a561c2ff1c8314abcdcaeba4f4d0b8b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Feb 2019 21:38:54 +0900 Subject: [PATCH 10/11] test-network: add tests for DHCP.RouteTable= --- .../conf/dhcp-client-ipv4-dhcp-settings.network | 1 + test/test-network/systemd-networkd-tests.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network index 5c4ca22ab7b..ebe3b7c0dd1 100644 --- a/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network +++ b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network @@ -13,3 +13,4 @@ UseHostname=true Hostname=test-hostname ClientIdentifier=mac VendorClassIdentifier=SusantVendorTest +RouteTable=211 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 143fba20fba..64a3d25bd41 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1182,16 +1182,27 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): self.start_dnsmasq() + print('## ip address show dev veth99') output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8') print(output) self.assertRegex(output, '12:34:56:78:9a:bc') self.assertRegex(output, '192.168.5') self.assertRegex(output, '1492') - output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8') + # issue #8726 + print('## ip route show table main dev veth99') + output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8') print(output) - self.assertRegex(output, 'default.*dev veth99 proto dhcp') + self.assertNotRegex(output, 'proto dhcp') + print('## ip route show table 211 dev veth99') + output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'default via 192.168.5.1 proto dhcp') + self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp') + self.assertRegex(output, '192.168.5.1 proto dhcp scope link') + + print('## dnsmasq log') self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True)) self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc')) self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname')) From 18c613dc3610ba4fcacf5697664e4b70ffdb712f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 12 Feb 2019 14:42:12 +0900 Subject: [PATCH 11/11] test-network: add tests for VRF= --- test/test-network/conf/25-vrf.network | 2 + .../test-network/conf/dhcp-client-vrf.network | 8 +++ test/test-network/systemd-networkd-tests.py | 58 ++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/test-network/conf/25-vrf.network create mode 100644 test/test-network/conf/dhcp-client-vrf.network diff --git a/test/test-network/conf/25-vrf.network b/test/test-network/conf/25-vrf.network new file mode 100644 index 00000000000..42ce5b19252 --- /dev/null +++ b/test/test-network/conf/25-vrf.network @@ -0,0 +1,2 @@ +[Match] +Name=vrf99 diff --git a/test/test-network/conf/dhcp-client-vrf.network b/test/test-network/conf/dhcp-client-vrf.network new file mode 100644 index 00000000000..bb1d2e09c5e --- /dev/null +++ b/test/test-network/conf/dhcp-client-vrf.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes +IPv6AcceptRA=yes +LinkLocalAddressing=yes +VRF=vrf99 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 64a3d25bd41..d1d4f4c3daa 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1104,10 +1104,13 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities): class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): links = [ 'dummy98', - 'veth99'] + 'veth99', + 'vrf99'] units = [ '25-veth.netdev', + '25-vrf.netdev', + '25-vrf.network', 'dhcp-client-anonymize.network', 'dhcp-client-critical-connection.network', 'dhcp-client-ipv4-dhcp-settings.network', @@ -1118,6 +1121,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): 'dhcp-client-listen-port.network', 'dhcp-client-route-metric.network', 'dhcp-client-route-table.network', + 'dhcp-client-vrf.network', 'dhcp-client.network', 'dhcp-server-veth-peer.network', 'dhcp-v4-server-veth-peer.network', @@ -1342,6 +1346,58 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): self.assertRegex(output, '2600::') self.assertRegex(output, 'valid_lft forever preferred_lft forever') + @expectedFailureIfModuleIsNotAvailable('vrf') + def test_dhcp_client_vrf(self): + self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network', + '25-vrf.netdev', '25-vrf.network') + self.start_networkd() + + self.assertTrue(self.link_exits('veth99')) + self.assertTrue(self.link_exits('vrf99')) + + self.start_dnsmasq() + + print('## ip -d link show dev vrf99') + output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'vrf table 42') + + print('## ip address show vrf vrf99') + output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8') + print(output_ip_vrf) + + print('## ip address show dev veth99') + output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8') + print(output) + self.assertEqual(output, output_ip_vrf) + self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute') + self.assertRegex(output, 'inet6 .* scope link') + + print('## ip route show vrf vrf99') + output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.') + self.assertRegex(output, 'default dev veth99 proto static scope link') + self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254') + self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5') + self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp') + self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5') + + print('## ip route show table main dev veth99') + output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8') + print(output) + self.assertEqual(output, '') + + output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'State: carrier \(configured\)') + + output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'State: routable \(configured\)') + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=3))