summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd-network/network-internal.c4
-rw-r--r--src/libsystemd-network/network-internal.h2
-rw-r--r--src/network/networkd-link.c253
-rw-r--r--src/network/networkd-manager.c184
-rw-r--r--src/network/networkd-netdev.c72
-rw-r--r--src/network/networkd-network.c30
-rw-r--r--src/network/networkd.c2
-rw-r--r--src/network/networkd.h14
-rw-r--r--src/network/test-network.c14
-rw-r--r--src/udev/net/link-config.c2
10 files changed, 270 insertions, 307 deletions
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 3686267b07..52e614c4ea 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -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)))
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 65cd0d72a0..836472a776 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -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,
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index f179af332c..319f2904c0 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -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",
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index d903d0d60e..4c1987daa8 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -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 = sd_rtnl_message_link_get_ifindex(message, &ifindex);
+ if (r < 0 || ifindex <= 0) {
+ log_warning("rtnl: received link message without valid ifindex");
+ return 0;
+ }
+
+ 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 = udev_enumerate_add_match_subsystem(e, "net");
+ r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
if (r < 0)
- return r;
+ log_warning("rtnl: received link message without valid ifname");
+ else {
+ NetDev *netdev;
- /* 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 = 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 = udev_enumerate_scan_devices(e);
+ 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;
+
+ r = sd_rtnl_message_request_dump(req, true);
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_call(m->rtnl, req, 0, &reply);
+ if (r < 0)
+ return r;
- d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
- if (!d)
- return -ENOMEM;
+ 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_process_link(m, d);
+ 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;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 92548d96f0..b7fc48db94 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -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");
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index bdf71e854e..048017e229 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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;
}
diff --git a/src/network/networkd.c b/src/network/networkd.c
index f0e6ad5201..6b3bf12a4c 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -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;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 36902e3c51..4a62fb8396 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -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_;
diff --git a/src/network/test-network.c b/src/network/test-network.c
index 9c372c7798..38d57cc6a6 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -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);
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 0c563b2db5..8215c40d5d 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -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"),