diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index a8f021fa6d..e935c897df 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -11,6 +11,8 @@ #include "bond.h" #include "bridge.h" #include "bus-util.h" +#include "device-private.h" +#include "device-util.h" #include "dhcp-identifier.h" #include "dhcp-lease-internal.h" #include "env-file.h" @@ -1734,7 +1736,7 @@ static void link_detach_from_manager(Link *link) { link_unref(link); } -void link_drop(Link *link) { +static void link_drop(Link *link) { if (!link || link->state == LINK_STATE_LINGER) return; @@ -2381,7 +2383,7 @@ static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin return 1; } -int link_initialized(Link *link, sd_device *device) { +static int link_initialized(Link *link, sd_device *device) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -2421,7 +2423,7 @@ int link_initialized(Link *link, sd_device *device) { return 0; } -int link_add(Manager *m, sd_netlink_message *message, Link **ret) { +static int link_add(Manager *m, sd_netlink_message *message, Link **ret) { _cleanup_(sd_device_unrefp) sd_device *device = NULL; char ifindex_str[2 + DECIMAL_STR_MAX(int)]; Link *link; @@ -2506,6 +2508,57 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) { return 0; } +int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) { + sd_device_action_t action; + Manager *m = userdata; + Link *link = NULL; + int r, ifindex; + + assert(m); + assert(device); + + r = sd_device_get_action(device, &action); + if (r < 0) { + log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m"); + return 0; + } + + /* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents + * are "positive" events in some form, i.e. inform us about a changed or new network interface, that + * still exists — and we are interested in that. */ + if (action == SD_DEVICE_REMOVE) + return 0; + + r = sd_device_get_ifindex(device, &ifindex); + if (r < 0) { + log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m", + device_action_to_string(action)); + return 0; + } + + r = device_is_renaming(device); + if (r < 0) { + log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m", + device_action_to_string(action)); + return 0; + } + if (r > 0) { + log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed."); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0) { + if (r != -ENODEV) + log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex); + return 0; + } + + (void) link_initialized(link, device); + + return 0; +} + static int link_carrier_gained(Link *link) { int r; @@ -2619,13 +2672,14 @@ int link_carrier_reset(Link *link) { return 0; } -/* This is called every time an interface admin state changes to up; - * specifically, when IFF_UP flag changes from unset to set */ static int link_admin_state_up(Link *link) { int r; assert(link); + /* This is called every time an interface admin state changes to up; + * specifically, when IFF_UP flag changes from unset to set. */ + if (!link->network) return 0; @@ -2649,7 +2703,6 @@ static int link_admin_state_up(Link *link) { } static int link_admin_state_down(Link *link) { - assert(link); if (!link->network) @@ -2663,7 +2716,7 @@ static int link_admin_state_down(Link *link) { return 0; } -int link_update(Link *link, sd_netlink_message *m) { +static int link_update(Link *link, sd_netlink_message *m) { _cleanup_strv_free_ char **s = NULL; hw_addr_data hw_addr; const char *ifname; @@ -2807,6 +2860,93 @@ int link_update(Link *link, sd_netlink_message *m) { return 0; } +int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { + Link *link = NULL; + NetDev *netdev = NULL; + uint16_t type; + const char *name; + int r, ifindex; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) { + log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name); + if (r < 0) { + log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); + return 0; + } + + (void) link_get(m, ifindex, &link); + (void) netdev_get(m, name, &netdev); + + switch (type) { + case RTM_NEWLINK: + if (!link) { + /* link is new, so add it */ + r = link_add(m, message, &link); + if (r < 0) { + log_warning_errno(r, "Could not process new link message, ignoring: %m"); + return 0; + } + } + + if (netdev) { + /* netdev exists, so make sure the ifindex matches */ + r = netdev_set_ifindex(netdev, message); + if (r < 0) { + log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m"); + return 0; + } + } + + r = link_update(link, message); + if (r < 0) { + log_warning_errno(r, "Could not process link message, ignoring: %m"); + return 0; + } + + break; + + case RTM_DELLINK: + link_drop(link); + netdev_drop(netdev); + + break; + + default: + assert_not_reached("Received link message with invalid RTNL message type."); + } + + return 1; +} + static const char* const link_state_table[_LINK_STATE_MAX] = { [LINK_STATE_PENDING] = "pending", [LINK_STATE_INITIALIZED] = "initialized", diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 347da1c928..d3353a1c4f 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -203,19 +203,15 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref); int link_get(Manager *m, int ifindex, Link **ret); -int link_add(Manager *manager, sd_netlink_message *message, Link **ret); -void link_drop(Link *link); int link_down(Link *link, link_netlink_message_handler_t callback); void link_enter_failed(Link *link); -int link_initialized(Link *link, sd_device *device); void link_set_state(Link *link, LinkState state); void link_check_ready(Link *link); void link_update_operstate(Link *link, bool also_update_bond_master); -int link_update(Link *link, sd_netlink_message *message); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); @@ -236,6 +232,9 @@ LinkState link_state_from_string(const char *s) _pure_; int link_configure(Link *link); int link_reconfigure(Link *link, bool force); +int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata); +int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); + int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg); #define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg) #define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 86432a6dc3..bfdb1f8c96 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -17,8 +17,6 @@ #include "bus-util.h" #include "conf-parser.h" #include "def.h" -#include "device-private.h" -#include "device-util.h" #include "dns-domain.h" #include "fd-util.h" #include "fileio.h" @@ -49,7 +47,6 @@ #include "strv.h" #include "sysctl-util.h" #include "tmpfile-util.h" -#include "udev-util.h" /* use 128 MB for receive socket kernel queue. */ #define RCVBUF_SIZE (128*1024*1024) @@ -182,57 +179,6 @@ int manager_connect_bus(Manager *m) { return 0; } -static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) { - sd_device_action_t action; - Manager *m = userdata; - Link *link = NULL; - int r, ifindex; - - assert(m); - assert(device); - - r = sd_device_get_action(device, &action); - if (r < 0) { - log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m"); - return 0; - } - - /* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents - * are "positive" events in some form, i.e. inform us about a changed or new network interface, that - * still exists — and we are interested in that. */ - if (action == SD_DEVICE_REMOVE) - return 0; - - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) { - log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m", - device_action_to_string(action)); - return 0; - } - - r = device_is_renaming(device); - if (r < 0) { - log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m", - device_action_to_string(action)); - return 0; - } - if (r > 0) { - log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed."); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r < 0) { - if (r != -ENODEV) - log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex); - return 0; - } - - (void) link_initialized(link, device); - - return 0; -} - static int manager_connect_udev(Manager *m) { int r; @@ -264,93 +210,6 @@ static int manager_connect_udev(Manager *m) { return 0; } -static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { - Link *link = NULL; - NetDev *netdev = NULL; - uint16_t type; - const char *name; - int r, ifindex; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); - return 0; - } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) { - log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type); - return 0; - } - - r = sd_rtnl_message_link_get_ifindex(message, &ifindex); - if (r < 0) { - log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex); - return 0; - } - - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name); - if (r < 0) { - log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); - return 0; - } - - (void) link_get(m, ifindex, &link); - (void) netdev_get(m, name, &netdev); - - switch (type) { - case RTM_NEWLINK: - if (!link) { - /* link is new, so add it */ - r = link_add(m, message, &link); - if (r < 0) { - log_warning_errno(r, "Could not process new link message, ignoring: %m"); - return 0; - } - } - - if (netdev) { - /* netdev exists, so make sure the ifindex matches */ - r = netdev_set_ifindex(netdev, message); - if (r < 0) { - log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m"); - return 0; - } - } - - r = link_update(link, message); - if (r < 0) { - log_warning_errno(r, "Could not process link message, ignoring: %m"); - return 0; - } - - break; - - case RTM_DELLINK: - link_drop(link); - netdev_drop(netdev); - - break; - - default: - assert_not_reached("Received link message with invalid RTNL message type."); - } - - return 1; -} - static int systemd_netlink_fd(void) { int n, fd, rtnl_fd = -EINVAL;