diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-08-05 20:18:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-05 20:18:30 +0200 |
commit | 1ab7e2b58719ffa36054483c826b9f5e53206e54 (patch) | |
tree | 02e3c2e416d6911e4da42d70c04202fd44c75531 /src | |
parent | Merge pull request #23508 from yuwata/core-device (diff) | |
parent | network: also check SR-IOV PF port and other VF ports before configuring (diff) | |
download | systemd-1ab7e2b58719ffa36054483c826b9f5e53206e54.tar.xz systemd-1ab7e2b58719ffa36054483c826b9f5e53206e54.zip |
Merge pull request #23340 from yuwata/network-check-sr-iov-pf-state
network: check SR-IOV PF state
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd/libsystemd.sym | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 23 | ||||
-rw-r--r-- | src/network/netdev/l2tp-tunnel.c | 4 | ||||
-rw-r--r-- | src/network/netdev/netdev-util.c | 2 | ||||
-rw-r--r-- | src/network/netdev/netdev.c | 40 | ||||
-rw-r--r-- | src/network/networkd-dhcp-server.c | 8 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 2 | ||||
-rw-r--r-- | src/network/networkd-dhcp6.c | 2 | ||||
-rw-r--r-- | src/network/networkd-link.c | 27 | ||||
-rw-r--r-- | src/network/networkd-link.h | 3 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 2 | ||||
-rw-r--r-- | src/network/networkd-radv.c | 2 | ||||
-rw-r--r-- | src/network/networkd-route.c | 3 | ||||
-rw-r--r-- | src/network/networkd-setlink.c | 36 | ||||
-rw-r--r-- | src/network/networkd-sriov.c | 262 | ||||
-rw-r--r-- | src/network/networkd-sriov.h | 8 | ||||
-rw-r--r-- | src/network/networkd-wiphy.c | 47 | ||||
-rw-r--r-- | src/systemd/sd-device.h | 2 | ||||
-rw-r--r-- | src/udev/udev-builtin-net_id.c | 19 |
19 files changed, 416 insertions, 78 deletions
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index fb6e6f6431..5c5446e987 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -784,6 +784,8 @@ global: sd_bus_message_read_strv_extend; sd_bus_error_setfv; + sd_device_new_child; + sd_id128_string_equal; sd_hwdb_new_from_path; diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 3e31beb1f2..1050234afe 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -861,6 +861,29 @@ _public_ int sd_device_get_syspath(sd_device *device, const char **ret) { return 0; } +_public_ int sd_device_new_child(sd_device **ret, sd_device *device, const char *suffix) { + _cleanup_free_ char *path = NULL; + const char *s; + int r; + + assert_return(ret, -EINVAL); + assert_return(device, -EINVAL); + assert_return(suffix, -EINVAL); + + if (!path_is_normalized(suffix)) + return -EINVAL; + + r = sd_device_get_syspath(device, &s); + if (r < 0) + return r; + + path = path_join(s, suffix); + if (!path) + return -ENOMEM; + + return sd_device_new_from_syspath(ret, path); +} + static int device_new_from_child(sd_device **ret, sd_device *child) { _cleanup_free_ char *path = NULL; const char *syspath; diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c index c38b9dc312..7e7d167928 100644 --- a/src/network/netdev/l2tp-tunnel.c +++ b/src/network/netdev/l2tp-tunnel.c @@ -292,7 +292,7 @@ static int l2tp_get_local_address(NetDev *netdev, union in_addr_union *ret) { if (r < 0) return r; - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return -EBUSY; } @@ -346,7 +346,7 @@ static int l2tp_get_local_address(NetDev *netdev, union in_addr_union *ret) { return link_get_l2tp_local_address(link, t, ret); HASHMAP_FOREACH(link, netdev->manager->links_by_index) { - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) continue; if (link_get_l2tp_local_address(link, t, ret) >= 0) diff --git a/src/network/netdev/netdev-util.c b/src/network/netdev/netdev-util.c index 06028855a8..23506246ce 100644 --- a/src/network/netdev/netdev-util.c +++ b/src/network/netdev/netdev-util.c @@ -51,7 +51,7 @@ int link_get_local_address( assert_not_reached(); } - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return -EBUSY; SET_FOREACH(a, link->addresses) { diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index f015168692..e9fadfddde 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -31,6 +31,7 @@ #include "networkd-manager.h" #include "networkd-queue.h" #include "networkd-setlink.h" +#include "networkd-sriov.h" #include "nlmon.h" #include "path-lookup.h" #include "siphash24.h" @@ -604,24 +605,39 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) { return 0; } +static bool link_is_ready_to_create_stacked_netdev_one(Link *link, bool allow_unmanaged) { + assert(link); + + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED)) + return false; + + if (!link->network) + return allow_unmanaged; + + if (link->set_link_messages > 0) + return false; + + /* If stacked netdevs are created before the underlying interface being activated, then + * the activation policy for the netdevs are ignored. See issue #22593. */ + if (!link->activated) + return false; + + return true; +} + +static bool link_is_ready_to_create_stacked_netdev(Link *link) { + return check_ready_for_all_sr_iov_ports(link, /* allow_unmanaged = */ false, + link_is_ready_to_create_stacked_netdev_one); +} + static int netdev_is_ready_to_create(NetDev *netdev, Link *link) { assert(netdev); if (netdev->state != NETDEV_STATE_LOADING) return false; - if (link) { - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - return false; - - if (link->set_link_messages > 0) - return false; - - /* If stacked netdevs are created before the underlying interface being activated, then - * the activation policy for the netdevs are ignored. See issue #22593. */ - if (!link->activated) - return false; - } + if (link && !link_is_ready_to_create_stacked_netdev(link)) + return false; if (NETDEV_VTABLE(netdev)->is_ready_to_create) return NETDEV_VTABLE(netdev)->is_ready_to_create(netdev, link); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 5861ecb922..076779dc0e 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -539,13 +539,7 @@ static bool dhcp_server_is_ready_to_configure(Link *link) { assert(link); - if (!link->network) - return false; - - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) - return false; - - if (link->set_flags_messages > 0) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return false; if (!link_has_carrier(link)) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index c6cbadc08b..3795fb32f3 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1557,7 +1557,7 @@ static int dhcp4_process_request(Request *req, Link *link, void *userdata) { assert(link); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return 0; r = dhcp4_configure_duid(link); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 7f9f4e12b9..4293eb6242 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -741,7 +741,7 @@ static int dhcp6_process_request(Request *req, Link *link, void *userdata) { assert(link); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return 0; r = dhcp_configure_duid(link, link_get_dhcp6_duid(link)); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 76e0690aef..20eb43eb09 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -92,19 +92,15 @@ bool link_ipv6_enabled(Link *link) { return false; } -bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) { +static bool link_is_ready_to_configure_one(Link *link, bool allow_unmanaged) { assert(link); - if (!link->network) { - if (!allow_unmanaged) - return false; - - return link_has_carrier(link); - } - - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED)) return false; + if (!link->network) + return allow_unmanaged; + if (!link->network->configure_without_carrier) { if (link->set_flags_messages > 0) return false; @@ -122,6 +118,10 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) { return true; } +bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) { + return check_ready_for_all_sr_iov_ports(link, allow_unmanaged, link_is_ready_to_configure_one); +} + void link_ntp_settings_clear(Link *link) { link->ntp = strv_free(link->ntp); } @@ -183,6 +183,7 @@ static Link *link_free(Link *link) { link_free_engines(link); + set_free(link->sr_iov_virt_port_ifindices); free(link->ifname); strv_free(link->alternative_names); free(link->kind); @@ -894,6 +895,8 @@ static Link *link_drop(Link *link) { link_free_bound_to_list(link); link_free_bound_by_list(link); + link_clear_sr_iov_ifindices(link); + link_drop_from_master(link); if (link->state_file) @@ -1393,6 +1396,8 @@ static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin } static int link_initialized(Link *link, sd_device *device) { + int r; + assert(link); assert(device); @@ -1400,6 +1405,10 @@ static int link_initialized(Link *link, sd_device *device) { * or sysattrs) may be outdated. */ device_unref_and_replace(link->dev, device); + r = link_set_sr_iov_ifindices(link); + if (r < 0) + log_link_warning_errno(link, r, "Failed to manage SR-IOV PF and VF ports, ignoring: %m"); + /* Do not ignore unamanaged state case here. If an interface is renamed after being once * configured, and the corresponding .network file has Name= in [Match] section, then the * interface may be already in unmanaged state. See #20657. */ diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 807fb44709..362f439940 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -52,6 +52,9 @@ typedef struct Link { int ifindex; int master_ifindex; int dsa_master_ifindex; + int sr_iov_phys_port_ifindex; + Set *sr_iov_virt_port_ifindices; + char *ifname; char **alternative_names; char *kind; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index dfbb7043bf..579282136f 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -1099,7 +1099,7 @@ static int ndisc_process_request(Request *req, Link *link, void *userdata) { assert(link); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return 0; r = ndisc_configure(link); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index c59ae82694..a0ce162532 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -549,7 +549,7 @@ static int radv_is_ready_to_configure(Link *link) { assert(link); assert(link->network); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false)) return false; if (in6_addr_is_null(&link->ipv6ll_address)) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 921b031b29..71e578d898 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1298,7 +1298,8 @@ static int route_is_ready_to_configure(const Route *route, Link *link) { if (r < 0) return false; if (r > 0) { - if (!link_is_ready_to_configure(l, true)) + if (!link_is_ready_to_configure(l, /* allow_unmanaged = */ true) || + !link_has_carrier(l)) return false; m->ifindex = l->ifindex; diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index e2b5acc086..4c0d3d23c3 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -14,6 +14,7 @@ #include "networkd-manager.h" #include "networkd-queue.h" #include "networkd-setlink.h" +#include "networkd-sriov.h" #include "networkd-wiphy.h" static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -797,20 +798,28 @@ int link_request_to_set_master(Link *link) { assert(link->network); if (link->network->keep_master) { + /* When KeepMaster=yes, BatmanAdvanced=, Bond=, Bridge=, and VRF= are ignored. */ link->master_set = true; return 0; - } - - link->master_set = false; - if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) + } else if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) { + link->master_set = false; return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER, link_set_master_handler, NULL); - else + + } else if (link->master_ifindex != 0) { + /* Unset master only when it is set. */ + link->master_set = false; return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER, link_unset_master_handler, NULL); + + } else { + /* Nothing we need to do. */ + link->master_set = true; + return 0; + } } int link_request_to_set_mtu(Link *link, uint32_t mtu) { @@ -999,15 +1008,28 @@ static int link_up_or_down(Link *link, bool up, Request *req) { return request_call_netlink_async(link->manager->rtnl, m, req); } -static bool link_is_ready_to_activate(Link *link, bool up) { +static bool link_is_ready_to_activate_one(Link *link, bool allow_unmanaged) { assert(link); - if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) + if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED)) return false; + if (!link->network) + return allow_unmanaged; + if (link->set_link_messages > 0) return false; + return true; +} + + static bool link_is_ready_to_activate(Link *link, bool up) { + assert(link); + + if (!check_ready_for_all_sr_iov_ports(link, /* allow_unmanaged = */ false, + link_is_ready_to_activate_one)) + return false; + if (up && link_rfkilled(link) > 0) return false; diff --git a/src/network/networkd-sriov.c b/src/network/networkd-sriov.c index 09980b4256..3d44c8fc82 100644 --- a/src/network/networkd-sriov.c +++ b/src/network/networkd-sriov.c @@ -1,6 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later * Copyright © 2020 VMware, Inc. */ +#include "device-enumerator-private.h" +#include "dirent-util.h" +#include "fd-util.h" #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-queue.h" @@ -103,3 +106,262 @@ int link_request_sr_iov_vfs(Link *link) { return 0; } + +static int find_ifindex_from_pci_dev_port(sd_device *pci_dev, const char *dev_port) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *dev; + int ifindex, r; + + assert(pci_dev); + assert(dev_port); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_parent(e, pci_dev); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "net", true); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysattr(e, "dev_port", dev_port, true); + if (r < 0) + return r; + + dev = sd_device_enumerator_get_device_first(e); + if (!dev) + return -ENODEV; /* no device found */ + + if (sd_device_enumerator_get_device_next(e)) + return -ENXIO; /* multiple devices found */ + + r = sd_device_get_ifindex(dev, &ifindex); + if (r < 0) + return r; + + assert(ifindex > 0); + return ifindex; +} + +static int manager_update_sr_iov_ifindices(Manager *manager, int phys_port_ifindex, int virt_port_ifindex) { + Link *phys_link = NULL, *virt_link = NULL; + int r; + + assert(manager); + assert(phys_port_ifindex > 0); + assert(virt_port_ifindex > 0); + + /* This sets ifindices only whenn both interfaces are already managed by us. */ + + r = link_get_by_index(manager, phys_port_ifindex, &phys_link); + if (r < 0) + return r; + + r = link_get_by_index(manager, virt_port_ifindex, &virt_link); + if (r < 0) + return r; + + /* update VF ifindex in PF */ + r = set_ensure_put(&phys_link->sr_iov_virt_port_ifindices, NULL, INT_TO_PTR(virt_port_ifindex)); + if (r < 0) + return r; + + log_link_debug(phys_link, + "Found SR-IOV VF port %s(%i).", + virt_link ? virt_link->ifname : "n/a", virt_port_ifindex); + + /* update PF ifindex in VF */ + if (virt_link->sr_iov_phys_port_ifindex > 0 && virt_link->sr_iov_phys_port_ifindex != phys_port_ifindex) { + Link *old_phys_link; + + if (link_get_by_index(manager, virt_link->sr_iov_phys_port_ifindex, &old_phys_link) >= 0) + set_remove(old_phys_link->sr_iov_virt_port_ifindices, INT_TO_PTR(virt_port_ifindex)); + } + + virt_link->sr_iov_phys_port_ifindex = phys_port_ifindex; + + log_link_debug(virt_link, + "Found SR-IOV PF port %s(%i).", + phys_link ? phys_link->ifname : "n/a", phys_port_ifindex); + + return 0; +} + +static int link_set_sr_iov_phys_port(Link *link) { + _cleanup_(sd_device_unrefp) sd_device *pci_physfn_dev = NULL; + const char *dev_port; + sd_device *pci_dev; + int r; + + assert(link); + assert(link->manager); + + if (link->sr_iov_phys_port_ifindex > 0) + return 0; + + if (!link->dev) + return -ENODEV; + + r = sd_device_get_sysattr_value(link->dev, "dev_port", &dev_port); + if (r < 0) + return r; + + r = sd_device_get_parent_with_subsystem_devtype(link->dev, "pci", NULL, &pci_dev); + if (r < 0) + return r; + + r = sd_device_new_child(&pci_physfn_dev, pci_dev, "physfn"); + if (r < 0) + return r; + + r = find_ifindex_from_pci_dev_port(pci_physfn_dev, dev_port); + if (r < 0) + return r; + + return manager_update_sr_iov_ifindices(link->manager, r, link->ifindex); +} + +static int link_set_sr_iov_virt_ports(Link *link) { + const char *dev_port, *pci_syspath; + _cleanup_closedir_ DIR *dir = NULL; + sd_device *pci_dev; + int r; + + assert(link); + assert(link->manager); + + set_clear(link->sr_iov_virt_port_ifindices); + + if (!link->dev) + return -ENODEV; + + r = sd_device_get_sysattr_value(link->dev, "dev_port", &dev_port); + if (r < 0) + return r; + + r = sd_device_get_parent_with_subsystem_devtype(link->dev, "pci", NULL, &pci_dev); + if (r < 0) + return r; + + r = sd_device_get_syspath(pci_dev, &pci_syspath); + if (r < 0) + return r; + + dir = opendir(pci_syspath); + if (!dir) + return -errno; + + FOREACH_DIRENT_ALL(de, dir, break) { + _cleanup_(sd_device_unrefp) sd_device *pci_virtfn_dev = NULL; + + if (de->d_type != DT_LNK) + continue; + + /* Accept name prefixed with "virtfn", but refuse "virtfn" itself. */ + if (isempty(startswith(de->d_name, "virtfn"))) + continue; + + if (sd_device_new_child(&pci_virtfn_dev, pci_dev, de->d_name) < 0) + continue; + + if (find_ifindex_from_pci_dev_port(pci_virtfn_dev, dev_port) < 0) + continue; + + if (manager_update_sr_iov_ifindices(link->manager, link->ifindex, r) < 0) + continue; + } + + return 0; +} + +int link_set_sr_iov_ifindices(Link *link) { + int r; + + assert(link); + + r = link_set_sr_iov_phys_port(link); + if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) + return r; + + r = link_set_sr_iov_virt_ports(link); + if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r)) + return r; + + return 0; +} + +void link_clear_sr_iov_ifindices(Link *link) { + void *v; + + assert(link); + assert(link->manager); + + if (link->sr_iov_phys_port_ifindex > 0) { + Link *phys_link; + + if (link_get_by_index(link->manager, link->sr_iov_phys_port_ifindex, &phys_link) >= 0) + set_remove(phys_link->sr_iov_virt_port_ifindices, INT_TO_PTR(link->ifindex)); + + link->sr_iov_phys_port_ifindex = 0; + } + + while ((v = set_steal_first(link->sr_iov_virt_port_ifindices))) { + Link *virt_link; + + if (link_get_by_index(link->manager, PTR_TO_INT(v), &virt_link) >= 0) + virt_link->sr_iov_phys_port_ifindex = 0; + } +} + +bool check_ready_for_all_sr_iov_ports( + Link *link, + bool allow_unmanaged, /* for the main target */ + bool (check_one)(Link *link, bool allow_unmanaged)) { + + Link *phys_link; + void *v; + + assert(link); + assert(link->manager); + assert(check_one); + + /* Some drivers make VF ports become down when their PF port becomes down, and may fail to configure + * VF ports. Also, when a VF port becomes up/down, its PF port and other VF ports may become down. + * See issue #23315. */ + + /* First, check the main target. */ + if (!check_one(link, allow_unmanaged)) + return false; + + /* If this is a VF port, then also check the PF port. */ + if (link->sr_iov_phys_port_ifindex > 0) { + if (link_get_by_index(link->manager, link->sr_iov_phys_port_ifindex, &phys_link) < 0 || + !check_one(phys_link, /* allow_unmanaged = */ true)) + return false; + } else + phys_link = link; + + /* Also check all VF ports. */ + SET_FOREACH(v, phys_link->sr_iov_virt_port_ifindices) { + int ifindex = PTR_TO_INT(v); + Link *virt_link; + + if (ifindex == link->ifindex) + continue; /* The main target link is a VF port, and its state is already checked. */ + + if (link_get_by_index(link->manager, ifindex, &virt_link) < 0) + return false; + + if (!check_one(virt_link, /* allow_unmanaged = */ true)) + return false; + } + + return true; +} diff --git a/src/network/networkd-sriov.h b/src/network/networkd-sriov.h index 539fa06099..0d4276e099 100644 --- a/src/network/networkd-sriov.h +++ b/src/network/networkd-sriov.h @@ -7,3 +7,11 @@ typedef struct Link Link; int link_request_sr_iov_vfs(Link *link); + +int link_set_sr_iov_ifindices(Link *link); +void link_clear_sr_iov_ifindices(Link *link); + +bool check_ready_for_all_sr_iov_ports( + Link *link, + bool allow_unmanaged, /* for the main target */ + bool (check_one)(Link *link, bool allow_unmanaged)); diff --git a/src/network/networkd-wiphy.c b/src/network/networkd-wiphy.c index 38d1ceeba1..63874cdf98 100644 --- a/src/network/networkd-wiphy.c +++ b/src/network/networkd-wiphy.c @@ -116,7 +116,7 @@ static int link_get_wiphy(Link *link, Wiphy **ret) { return -EOPNOTSUPP; if (!link->dev) - return -EOPNOTSUPP; + return -ENODEV; r = sd_device_get_devtype(link->dev, &s); if (r < 0) @@ -125,12 +125,7 @@ static int link_get_wiphy(Link *link, Wiphy **ret) { if (!streq_ptr(s, "wlan")) return -EOPNOTSUPP; - r = sd_device_get_syspath(link->dev, &s); - if (r < 0) - return r; - - s = strjoina(s, "/phy80211"); - r = sd_device_new_from_syspath(&phy, s); + r = sd_device_new_child(&phy, link->dev, "phy80211"); if (r < 0) return r; @@ -219,10 +214,11 @@ int link_rfkilled(Link *link) { assert(link); r = link_get_wiphy(link, &w); - if (IN_SET(r, -EOPNOTSUPP, -ENODEV)) - return false; /* Typically, non-wifi interface or running in container */ - if (r < 0) + if (r < 0) { + if (ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_DEVICE_ABSENT(r)) + return false; /* Typically, non-wifi interface or running in container */ return log_link_debug_errno(link, r, "Could not get phy: %m"); + } return wiphy_rfkilled(w); } @@ -272,11 +268,8 @@ static int wiphy_update_device(Wiphy *w) { w->dev = sd_device_unref(w->dev); r = sd_device_new_from_subsystem_sysname(&dev, "ieee80211", w->name); - if (r < 0) { - /* The corresponding syspath may not exist yet, and may appear later. */ - log_wiphy_debug_errno(w, r, "Failed to get wiphy device, ignoring: %m"); - return 0; - } + if (r < 0) + return r; if (DEBUG_LOGGING) { const char *s = NULL; @@ -321,14 +314,12 @@ static int wiphy_update_rfkill(Wiphy *w) { return r; rfkill = sd_device_enumerator_get_device_first(e); - if (!rfkill) { + if (!rfkill) /* rfkill device may not detected by the kernel yet, and may appear later. */ - log_wiphy_debug_errno(w, SYNTHETIC_ERRNO(ENODEV), "No rfkill device found, ignoring."); - return 0; - } + return -ENODEV; if (sd_device_enumerator_get_device_next(e)) - return log_wiphy_debug_errno(w, SYNTHETIC_ERRNO(EEXIST), "Multiple rfkill devices found."); + return -ENXIO; /* multiple devices found */ w->rfkill = sd_device_ref(rfkill); @@ -348,12 +339,20 @@ static int wiphy_update(Wiphy *w) { assert(w); r = wiphy_update_device(w); - if (r < 0) - return log_wiphy_debug_errno(w, r, "Failed to update wiphy device: %m"); + if (r < 0) { + if (ERRNO_IS_DEVICE_ABSENT(r)) + log_wiphy_debug_errno(w, r, "Failed to update wiphy device, ignoring: %m"); + else + return log_wiphy_warning_errno(w, r, "Failed to update wiphy device: %m"); + } r = wiphy_update_rfkill(w); - if (r < 0) - return log_wiphy_debug_errno(w, r, "Failed to update rfkill device: %m"); + if (r < 0) { + if (ERRNO_IS_DEVICE_ABSENT(r)) + log_wiphy_debug_errno(w, r, "Failed to update rfkill device, ignoring: %m"); + else + return log_wiphy_warning_errno(w, r, "Failed to update rfkill device: %m"); + } return 0; } diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index 19dd4d9eef..0b2f8f8b42 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -67,6 +67,8 @@ int sd_device_new_from_path(sd_device **ret, const char *path); int sd_device_new_from_ifname(sd_device **ret, const char *ifname); int sd_device_new_from_ifindex(sd_device **ret, int ifindex); +int sd_device_new_child(sd_device **ret, sd_device *device, const char *suffix); + int sd_device_get_parent(sd_device *child, sd_device **ret); int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret); diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 59db7641b5..45387b2bdb 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -23,7 +23,6 @@ #include <linux/pci_regs.h> #include "alloc-util.h" -#include "chase-symlinks.h" #include "device-util.h" #include "dirent-util.h" #include "fd-util.h" @@ -109,8 +108,7 @@ static int get_virtfn_info(sd_device *pcidev, sd_device **ret_physfn_pcidev, cha return r; /* Get physical function's pci device. */ - physfn_syspath = strjoina(syspath, "/physfn"); - r = sd_device_new_from_syspath(&physfn_pcidev, physfn_syspath); + r = sd_device_new_child(&physfn_pcidev, pcidev, "physfn"); if (r < 0) return r; @@ -124,21 +122,20 @@ static int get_virtfn_info(sd_device *pcidev, sd_device **ret_physfn_pcidev, cha return -errno; FOREACH_DIRENT_ALL(de, dir, break) { - _cleanup_free_ char *virtfn_link_file = NULL, *virtfn_pci_syspath = NULL; - const char *n; + _cleanup_(sd_device_unrefp) sd_device *virtfn_pcidev = NULL; + const char *n, *s; n = startswith(de->d_name, "virtfn"); - if (!n) + if (isempty(n)) continue; - virtfn_link_file = path_join(physfn_syspath, de->d_name); - if (!virtfn_link_file) - return -ENOMEM; + if (sd_device_new_child(&virtfn_pcidev, physfn_pcidev, de->d_name) < 0) + continue; - if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0) + if (sd_device_get_syspath(virtfn_pcidev, &s) < 0) continue; - if (streq(syspath, virtfn_pci_syspath)) { + if (streq(s, syspath)) { char *suffix; suffix = strjoin("v", n); |