Merge pull request #23340 from yuwata/network-check-sr-iov-pf-state
network: check SR-IOV PF state
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+28
-12
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0)
|
||||
if (sd_device_new_child(&virtfn_pcidev, physfn_pcidev, de->d_name) < 0)
|
||||
continue;
|
||||
|
||||
if (streq(syspath, virtfn_pci_syspath)) {
|
||||
if (sd_device_get_syspath(virtfn_pcidev, &s) < 0)
|
||||
continue;
|
||||
|
||||
if (streq(s, syspath)) {
|
||||
char *suffix;
|
||||
|
||||
suffix = strjoin("v", n);
|
||||
|
||||
Reference in New Issue
Block a user