mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
Merge pull request #11698 from yuwata/fix-network-route-table
network: honor specified route table
This commit is contained in:
commit
702451b038
@ -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 != NULL)
|
||||
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)
|
||||
@ -135,14 +130,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 +154,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;
|
||||
|
||||
|
@ -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) {
|
||||
@ -288,7 +293,8 @@ 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);
|
||||
|
||||
@ -300,22 +306,26 @@ static int dhcp6_lease_pd_prefix_acquired(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);
|
||||
table = link_get_dhcp_route_table(link);
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
|
@ -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,23 +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;
|
||||
|
||||
r = route_configure(route, link, ipv4ll_route_handler);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link->ipv4ll_route = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -176,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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -87,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;
|
||||
@ -105,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;
|
||||
|
@ -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, ...) \
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -141,7 +141,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)
|
||||
@ -151,7 +151,7 @@ IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool,
|
||||
IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
|
||||
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)
|
||||
|
@ -209,6 +209,7 @@ int network_load_one(Manager *manager, const char *filename) {
|
||||
.ipv6_accept_ra_use_autonomous_prefix = true,
|
||||
.ipv6_accept_ra_use_onlink_prefix = 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,
|
||||
@ -1423,16 +1424,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;
|
||||
@ -1445,12 +1448,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;
|
||||
}
|
||||
|
@ -215,6 +215,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;
|
||||
@ -311,7 +312,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);
|
||||
|
@ -501,6 +501,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);
|
||||
|
2
test/test-network/conf/25-vrf.network
Normal file
2
test/test-network/conf/25-vrf.network
Normal file
@ -0,0 +1,2 @@
|
||||
[Match]
|
||||
Name=vrf99
|
@ -13,3 +13,4 @@ UseHostname=true
|
||||
Hostname=test-hostname
|
||||
ClientIdentifier=mac
|
||||
VendorClassIdentifier=SusantVendorTest
|
||||
RouteTable=211
|
||||
|
8
test/test-network/conf/dhcp-client-vrf.network
Normal file
8
test/test-network/conf/dhcp-client-vrf.network
Normal file
@ -0,0 +1,8 @@
|
||||
[Match]
|
||||
Name=veth99
|
||||
|
||||
[Network]
|
||||
DHCP=yes
|
||||
IPv6AcceptRA=yes
|
||||
LinkLocalAddressing=yes
|
||||
VRF=vrf99
|
@ -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()
|
||||
@ -1212,10 +1210,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',
|
||||
@ -1226,6 +1227,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',
|
||||
@ -1290,16 +1292,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'))
|
||||
@ -1439,6 +1452,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))
|
||||
|
Loading…
Reference in New Issue
Block a user