networkd: tie links to rtnl rather than udev

This essentially swaps the roles of rtnl and udev in networkd. After this
change libudev is only used for waiting for udev to initialize devices and
to get udev-specific information needed for some [Match] attributes.

This in particular simplifies the code in containers where udev is not really
useful, but also simplifies things and reduces round-trips in the non-container
case.
This commit is contained in:
Tom Gundersen 2014-04-15 14:21:44 +02:00
parent d1ca51b153
commit 505f8da732
10 changed files with 273 additions and 310 deletions

View File

@ -79,7 +79,7 @@ bool net_match_config(const struct ether_addr *match_mac,
Condition *match_virt,
Condition *match_kernel,
Condition *match_arch,
const char *dev_mac,
const struct ether_addr *dev_mac,
const char *dev_path,
const char *dev_parent_driver,
const char *dev_driver,
@ -98,7 +98,7 @@ bool net_match_config(const struct ether_addr *match_mac,
if (match_arch && !condition_test_architecture(match_arch))
return 0;
if (match_mac && (!dev_mac || memcmp(match_mac, ether_aton(dev_mac), ETH_ALEN)))
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
return 0;
if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0)))

View File

@ -37,7 +37,7 @@ bool net_match_config(const struct ether_addr *match_mac,
Condition *match_virt,
Condition *match_kernel,
Condition *match_arch,
const char *dev_mac,
const struct ether_addr *dev_mac,
const char *dev_path,
const char *dev_parent_driver,
const char *dev_driver,

View File

@ -24,7 +24,9 @@
#include "networkd.h"
#include "libudev-private.h"
#include "udev-util.h"
#include "util.h"
#include "virt.h"
#include "bus-util.h"
#include "network-internal.h"
@ -33,41 +35,53 @@
static int ipv4ll_address_update(Link *link, bool deprecate);
static bool ipv4ll_is_bound(sd_ipv4ll *ll);
int link_new(Manager *manager, struct udev_device *device, Link **ret) {
static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
_cleanup_link_free_ Link *link = NULL;
const char *ifname;
int r;
uint16_t type;
char *ifname;
int r, ifindex;
assert(manager);
assert(manager->links);
assert(device);
assert(message);
assert(ret);
r = sd_rtnl_message_get_type(message, &type);
if (r < 0)
return r;
else if (type != RTM_NEWLINK)
return -EINVAL;
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0)
return r;
else if (ifindex <= 0)
return -EINVAL;
r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
if (r < 0)
return r;
link = new0(Link, 1);
if (!link)
return -ENOMEM;
link->manager = manager;
link->state = _LINK_STATE_INVALID;
link->ifindex = udev_device_get_ifindex(device);
if (link->ifindex <= 0)
return -EINVAL;
link->state = LINK_STATE_INITIALIZING;
link->ifindex = ifindex;
link->ifname = strdup(ifname);
if (!link->ifname)
return -ENOMEM;
r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
link->ifindex);
if (r < 0)
return -ENOMEM;
ifname = udev_device_get_sysname(device);
link->ifname = strdup(ifname);
r = hashmap_put(manager->links, &link->ifindex, link);
if (r < 0)
return r;
link->udev_device = udev_device_ref(device);
*ret = link;
link = NULL;
@ -1036,7 +1050,6 @@ static int link_update_flags(Link *link, unsigned flags) {
int r;
assert(link);
assert(link->network);
if (link->state == LINK_STATE_FAILED)
return 0;
@ -1060,13 +1073,12 @@ static int link_update_flags(Link *link, unsigned flags) {
link->flags = flags;
if (flags_added & generic_flags)
log_debug_link(link, "link flags gained: %#.8x",
flags_added & generic_flags);
if (flags_removed & generic_flags)
log_debug_link(link, "link flags lost: %#.8x",
flags_removed & generic_flags);
if (!link->network)
/* not currently managing this link
we track state changes, but don't log them
they will be logged if and when a network is
applied */
return 0;
if (flags_added & IFF_UP)
log_info_link(link, "link is up");
@ -1083,6 +1095,14 @@ static int link_update_flags(Link *link, unsigned flags) {
else if (flags_removed & IFF_RUNNING)
log_debug_link(link, "link is not running");
if (flags_added & generic_flags)
log_debug_link(link, "ignored link flags gained: %#.8x",
flags_added & generic_flags);
if (flags_removed & generic_flags)
log_debug_link(link, "ignored link flags lost: %#.8x",
flags_removed & generic_flags);
if (carrier_gained) {
log_info_link(link, "gained carrier");
@ -1180,10 +1200,12 @@ static int link_enslaved(Link *link) {
assert(link->state == LINK_STATE_ENSLAVING);
assert(link->network);
r = link_up(link);
if (r < 0) {
link_enter_failed(link);
return r;
if (!(link->flags & IFF_UP)) {
r = link_up(link);
if (r < 0) {
link_enter_failed(link);
return r;
}
}
if (!link->network->dhcp && !link->network->ipv4ll)
@ -1231,7 +1253,7 @@ static int link_enter_enslave(Link *link) {
assert(link);
assert(link->network);
assert(link->state == _LINK_STATE_INVALID);
assert(link->state == LINK_STATE_INITIALIZING);
link->state = LINK_STATE_ENSLAVING;
@ -1323,95 +1345,11 @@ static int link_enter_enslave(Link *link) {
return 0;
}
static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
void *userdata) {
Link *link = userdata;
int r;
assert(link);
assert(link->ifname);
if (link->state == LINK_STATE_FAILED)
return 1;
r = sd_rtnl_message_get_errno(m);
if (r < 0) {
log_struct_link(LOG_ERR, link,
"MESSAGE=%s: could not get state: %s",
link->ifname, strerror(-r),
"ERRNO=%d", -r,
NULL);
link_enter_failed(link);
return 1;
}
link_update(link, m);
return 1;
}
static int link_getlink(Link *link) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
int r;
assert(link);
assert(link->manager);
assert(link->manager->rtnl);
log_debug_link(link, "requesting link status");
r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
RTM_GETLINK, link->ifindex);
if (r < 0) {
log_error_link(link, "Could not allocate RTM_GETLINK message");
return r;
}
r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
link, 0, NULL);
if (r < 0) {
log_error_link(link,
"Could not send rtnetlink message: %s", strerror(-r));
return r;
}
return 0;
}
static int link_configure(Link *link) {
int r;
assert(link);
assert(link->state == _LINK_STATE_INVALID);
r = link_getlink(link);
if (r < 0)
return r;
return link_enter_enslave(link);
}
int link_add(Manager *m, struct udev_device *device, Link **ret) {
Link *link = NULL;
Network *network;
int r;
assert(m);
assert(device);
r = link_new(m, device, &link);
if (r < 0)
return r;
*ret = link;
r = network_get(m, device, &network);
if (r < 0)
return r == -ENOENT ? 0 : r;
r = network_apply(m, network, link);
if (r < 0)
return r;
assert(link->state == LINK_STATE_INITIALIZING);
if (link->network->ipv4ll) {
uint8_t seed[8];
@ -1419,11 +1357,13 @@ int link_add(Manager *m, struct udev_device *device, Link **ret) {
if (r < 0)
return r;
r = net_get_unique_predictable_data(link->udev_device, seed);
if (r >= 0) {
r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
if (r < 0)
return r;
if (link->udev_device) {
r = net_get_unique_predictable_data(link->udev_device, seed);
if (r >= 0) {
r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
if (r < 0)
return r;
}
}
r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
@ -1463,10 +1403,84 @@ int link_add(Manager *m, struct udev_device *device, Link **ret) {
}
}
return link_enter_enslave(link);
}
int link_initialized(Link *link, struct udev_device *device) {
Network *network;
unsigned flags;
int r;
assert(link);
assert(link->ifname);
assert(link->manager);
if (link->state != LINK_STATE_INITIALIZING)
return 0;
if (device)
link->udev_device = udev_device_ref(device);
log_debug_link(link, "link initialized");
r = network_get(link->manager, device, link->ifname, &link->mac, &network);
if (r < 0)
return r == -ENOENT ? 0 : r;
r = network_apply(link->manager, network, link);
if (r < 0)
return r;
r = link_configure(link);
if (r < 0)
return r;
/* re-trigger all state updates */
flags = link->flags;
link->flags = 0;
r = link_update_flags(link, flags);
if (r < 0)
return r;
return 0;
}
int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
int r;
assert(m);
assert(message);
assert(ret);
r = link_new(m, message, ret);
if (r < 0)
return r;
link = *ret;
log_info_link(link, "link added");
if (detect_container(NULL) <= 0) {
/* not in a container, udev will be around */
sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
device = udev_device_new_from_device_id(m->udev, ifindex_str);
if (!device) {
log_warning_link(link, "could not find udev device");
return -errno;
}
if (udev_device_get_is_initialized(device) <= 0)
/* not yet ready */
return 0;
}
r = link_initialized(link, device);
if (r < 0)
return r;
return 0;
}
@ -1476,14 +1490,12 @@ int link_update(Link *link, sd_rtnl_message *m) {
int r;
assert(link);
assert(link->network);
assert(m);
if (link->state == LINK_STATE_FAILED)
return 0;
if (link->network->dhcp && link->network->dhcp_mtu &&
!link->original_mtu) {
if (!link->original_mtu) {
r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
if (r >= 0)
log_debug_link(link, "saved original MTU: %"
@ -1591,6 +1603,7 @@ finish:
}
static const char* const link_state_table[_LINK_STATE_MAX] = {
[LINK_STATE_INITIALIZING] = "configuring",
[LINK_STATE_ENSLAVING] = "configuring",
[LINK_STATE_SETTING_ADDRESSES] = "configuring",
[LINK_STATE_SETTING_ROUTES] = "configuring",

View File

@ -29,6 +29,8 @@
#include "mkdir.h"
#include "virt.h"
#include "sd-rtnl.h"
const char* const network_dirs[] = {
"/etc/systemd/network",
"/run/systemd/network",
@ -96,18 +98,14 @@ int manager_new(Manager **ret) {
if (r < 0)
return r;
m->udev = udev_new();
if (!m->udev)
return -ENOMEM;
/* udev does not initialize devices inside containers,
* so we rely on them being already initialized before
* entering the container */
if (detect_container(NULL) > 0) {
m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "kernel");
if (!m->udev_monitor)
if (detect_container(NULL) <= 0) {
m->udev = udev_new();
if (!m->udev)
return -ENOMEM;
} else {
m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_monitor)
return -ENOMEM;
@ -182,15 +180,30 @@ bool manager_should_reload(Manager *m) {
return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
}
static int manager_process_link(Manager *m, struct udev_device *device) {
static int manager_udev_process_link(Manager *m, struct udev_device *device) {
Link *link = NULL;
int r;
assert(m);
assert(device);
link_get(m, udev_device_get_ifindex(device), &link);
if (!streq_ptr(udev_device_get_action(device), "add"))
return 0;
r = link_get(m, udev_device_get_ifindex(device), &link);
if (r < 0)
return r;
if (!link)
return 0;
r = link_initialized(link, device);
if (r < 0)
return r;
return 0;
}
/*
if (streq_ptr(udev_device_get_action(device), "remove")) {
log_debug("%s: link removed", udev_device_get_sysname(device));
@ -215,45 +228,87 @@ static int manager_process_link(Manager *m, struct udev_device *device) {
return 0;
}
*/
static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
char *name;
int r, ifindex;
int manager_udev_enumerate_links(Manager *m) {
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
assert(rtnl);
assert(message);
assert(m);
e = udev_enumerate_new(m->udev);
if (!e)
return -ENOMEM;
r = udev_enumerate_add_match_subsystem(e, "net");
if (r < 0)
return r;
/* udev does not initialize devices inside containers,
* so we rely on them being already initialized before
* entering the container */
if (detect_container(NULL) <= 0) {
r = udev_enumerate_add_match_is_initialized(e);
if (r < 0)
return r;
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0 || ifindex <= 0) {
log_warning("rtnl: received link message without valid ifindex");
return 0;
}
r = udev_enumerate_scan_devices(e);
link_get(m, ifindex, &link);
if (!link) {
/* link is new, so add it */
r = link_add(m, message, &link);
if (r < 0) {
log_debug("could not add new link");
return 0;
}
}
r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
if (r < 0)
log_warning("rtnl: received link message without valid ifname");
else {
NetDev *netdev;
r = netdev_get(m, name, &netdev);
if (r >= 0) {
r = netdev_set_ifindex(netdev, message);
if (r < 0) {
log_debug("could not set ifindex on netdev");
return 0;
}
}
}
r = link_update(link, message);
if (r < 0)
return 0;
return 1;
}
int manager_rtnl_enumerate_links(Manager *m) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
sd_rtnl_message *link;
int r, k;
assert(m);
assert(m->rtnl);
r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
if (r < 0)
return r;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
int k;
r = sd_rtnl_message_request_dump(req, true);
if (r < 0)
return r;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
if (!d)
return -ENOMEM;
r = sd_rtnl_call(m->rtnl, req, 0, &reply);
if (r < 0)
return r;
k = manager_process_link(m, d);
for (link = reply; link; link = sd_rtnl_message_next(link)) {
uint16_t type;
k = sd_rtnl_message_get_type(link, &type);
if (k < 0)
return k;
if (type != RTM_NEWLINK)
continue;
k = manager_rtnl_process_link(m->rtnl, link, m);
if (k < 0)
r = k;
}
@ -270,13 +325,18 @@ static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t
if (!device)
return -ENOMEM;
manager_process_link(m, device);
manager_udev_process_link(m, device);
return 0;
}
int manager_udev_listen(Manager *m) {
int r;
if (detect_container(NULL) > 0)
return 0;
assert(m->udev_monitor);
r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
if (r < 0) {
log_error("Could not add udev monitor filter: %s", strerror(-r));
@ -300,56 +360,6 @@ int manager_udev_listen(Manager *m) {
return 0;
}
static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
Manager *m = userdata;
Link *link;
char *name;
int r, ifindex;
assert(rtnl);
assert(message);
assert(m);
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0 || ifindex <= 0) {
log_warning("received RTM_NEWLINK message without valid ifindex");
return 0;
}
r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
if (r < 0)
log_warning("received RTM_NEWLINK message without valid ifname");
else {
NetDev *netdev;
r = netdev_get(m, name, &netdev);
if (r >= 0) {
netdev_set_ifindex(netdev, message);
r = sd_rtnl_message_rewind(message);
if (r < 0) {
log_debug("could not rewind rtnl message");
return 0;
}
}
}
r = link_get(m, ifindex, &link);
if (r < 0) {
log_debug("received RTM_NEWLINK message for untracked ifindex %d", ifindex);
return 0;
}
/* only track the status of links we want to manage */
if (link->network) {
r = link_update(link, message);
if (r < 0)
return 0;
} else
log_debug("%s: received RTM_NEWLINK message for unmanaged link", link->ifname);
return 1;
}
int manager_rtnl_listen(Manager *m) {
int r;

View File

@ -161,67 +161,6 @@ static int netdev_enter_ready(NetDev *netdev) {
return 0;
}
static int netdev_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
void *userdata) {
NetDev *netdev = userdata;
int r;
assert(netdev);
if (netdev->state == NETDEV_STATE_FAILED)
return 1;
r = sd_rtnl_message_get_errno(m);
if (r < 0) {
log_struct_netdev(LOG_ERR, netdev,
"MESSAGE=%s: could not get link: %s",
netdev->name, strerror(-r),
"ERRNO=%d", -r,
NULL);
return 1;
}
netdev_set_ifindex(netdev, m);
return 1;
}
static int netdev_getlink(NetDev *netdev) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
int r;
assert(netdev->manager);
assert(netdev->manager->rtnl);
assert(netdev->name);
log_debug_netdev(netdev, "requesting netdev status");
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
RTM_GETLINK, 0);
if (r < 0) {
log_error_netdev(netdev, "Could not allocate RTM_GETLINK message");
return r;
}
r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->name);
if (r < 0) {
log_error_netdev(netdev, "Colud not append ifname to message: %s",
strerror(-r));
return r;
}
r = sd_rtnl_call_async(netdev->manager->rtnl, req, netdev_getlink_handler,
netdev, 0, NULL);
if (r < 0) {
log_error_netdev(netdev,
"Could not send rtnetlink message: %s", strerror(-r));
return r;
}
return 0;
}
static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
NetDev *netdev = userdata;
int r;
@ -230,9 +169,8 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
r = sd_rtnl_message_get_errno(m);
if (r == -EEXIST)
r = netdev_getlink(netdev);
if (r < 0) {
log_debug_netdev(netdev, "netdev exists, using existing");
else if (r < 0) {
log_warning_netdev(netdev, "netdev failed: %s", strerror(-r));
netdev_enter_failed(netdev);
@ -410,6 +348,12 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
return r;
}
r = sd_rtnl_message_exit_container(message);
if (r < 0) {
log_error_netdev(netdev, "Could not exit container");
return r;
}
kind = netdev_kind_to_string(netdev->kind);
if (!kind) {
log_error_netdev(netdev, "Could not get kind");

View File

@ -184,28 +184,28 @@ void network_free(Network *network) {
free(network);
}
int network_get(Manager *manager, struct udev_device *device, Network **ret) {
int network_get(Manager *manager, struct udev_device *device,
const char *ifname, const struct ether_addr *address,
Network **ret) {
Network *network;
assert(manager);
assert(device);
assert(ret);
LIST_FOREACH(networks, network, manager->networks) {
if (net_match_config(network->match_mac, network->match_path,
network->match_driver, network->match_type,
network->match_name, network->match_host,
network->match_virt, network->match_kernel,
network->match_arch,
udev_device_get_sysattr_value(device, "address"),
udev_device_get_property_value(device, "ID_PATH"),
udev_device_get_driver(udev_device_get_parent(device)),
udev_device_get_property_value(device, "ID_NET_DRIVER"),
udev_device_get_devtype(device),
udev_device_get_sysname(device))) {
log_debug("%s: found matching network '%s'",
udev_device_get_sysname(device),
network->filename);
network->match_driver, network->match_type,
network->match_name, network->match_host,
network->match_virt, network->match_kernel,
network->match_arch,
address,
udev_device_get_property_value(device, "ID_PATH"),
udev_device_get_driver(udev_device_get_parent(device)),
udev_device_get_property_value(device, "ID_NET_DRIVER"),
udev_device_get_devtype(device),
ifname)) {
log_debug("%s: found matching network '%s'", ifname,
network->filename);
*ret = network;
return 0;
}

View File

@ -87,7 +87,7 @@ int main(int argc, char *argv[]) {
goto out;
}
r = manager_udev_enumerate_links(m);
r = manager_rtnl_enumerate_links(m);
if (r < 0) {
log_error("Could not enumerate links: %s", strerror(-r));
goto out;

View File

@ -185,6 +185,7 @@ struct Route {
};
typedef enum LinkState {
LINK_STATE_INITIALIZING,
LINK_STATE_ENSLAVING,
LINK_STATE_SETTING_ADDRESSES,
LINK_STATE_SETTING_ROUTES,
@ -246,10 +247,10 @@ void manager_free(Manager *m);
int manager_load_config(Manager *m);
bool manager_should_reload(Manager *m);
int manager_udev_enumerate_links(Manager *m);
int manager_udev_listen(Manager *m);
int manager_rtnl_enumerate_links(Manager *m);
int manager_rtnl_listen(Manager *m);
int manager_udev_listen(Manager *m);
int manager_bus_listen(Manager *m);
int manager_update_resolv_conf(Manager *m);
@ -292,7 +293,9 @@ void network_free(Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
#define _cleanup_network_free_ _cleanup_(network_freep)
int network_get(Manager *manager, struct udev_device *device, Network **ret);
int network_get(Manager *manager, struct udev_device *device,
const char *ifname, const struct ether_addr *mac,
Network **ret);
int network_apply(Manager *manager, Network *network, Link *link);
int config_parse_bridge(const char *unit, const char *filename, unsigned line,
@ -362,13 +365,14 @@ int config_parse_label(const char *unit, const char *filename, unsigned line,
/* Link */
int link_new(Manager *manager, struct udev_device *device, Link **ret);
void link_free(Link *link);
int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, struct udev_device *device, Link **ret);
int link_add(Manager *manager, sd_rtnl_message *message, Link **ret);
int link_update(Link *link, sd_rtnl_message *message);
int link_initialized(Link *link, struct udev_device *device);
int link_save(Link *link);
const char* link_state_to_string(LinkState s) _const_;

View File

@ -21,13 +21,6 @@
#include "networkd.h"
static void test_link(Manager *manager, struct udev_device *loopback) {
Link *link = NULL;
assert_se(link_new(manager, loopback, &link) >= 0);
assert_se(link);
}
static void test_load_config(Manager *manager) {
/* TODO: should_reload, is false if the config dirs do not exist, so
* so we can't do this test here, move it to a test for paths_check_timestamps
@ -41,10 +34,11 @@ static void test_load_config(Manager *manager) {
static void test_network_get(Manager *manager, struct udev_device *loopback) {
Network *network;
const struct ether_addr mac = {};
/* let's assume that the test machine does not have a .network file
that applies to the loopback device... */
assert_se(network_get(manager, loopback, &network) == -ENOENT);
assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT);
assert_se(!network);
}
@ -66,11 +60,9 @@ int main(void) {
test_network_get(manager, loopback);
test_link(manager, loopback);
assert_se(manager_udev_listen(manager) >= 0);
assert_se(manager_udev_enumerate_links(manager) >= 0);
assert_se(manager_rtnl_listen(manager) >= 0);
assert_se(manager_rtnl_enumerate_links(manager) >= 0);
udev_device_unref(loopback);
udev_unref(udev);

View File

@ -238,7 +238,7 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_confi
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
link->match_type, NULL, link->match_host,
link->match_virt, link->match_kernel, link->match_arch,
udev_device_get_sysattr_value(device, "address"),
ether_aton(udev_device_get_sysattr_value(device, "address")),
udev_device_get_property_value(device, "ID_PATH"),
udev_device_get_driver(udev_device_get_parent(device)),
udev_device_get_property_value(device, "ID_NET_DRIVER"),