network: also check SR-IOV PF port and other VF ports before configuring
When a PF port becomes down (this can happens e.g. the PF port is joining a bond interface), some drivers make its VF ports also become down, and may cause failures in configuring VF ports. Similary, when a VF port become down, some drivers make its PF port and other VF ports down. Let's configure SR-IOV ports (both PF and VFs) after all link-layer settings of all ports being applied. Fixes #23315.
This commit is contained in:
@@ -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,12 +605,15 @@ static int stacked_netdev_create(NetDev *netdev, Link *link, Request *req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool link_is_ready_to_create_stacked_netdev(Link *link) {
|
||||
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))
|
||||
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;
|
||||
|
||||
@@ -621,6 +625,11 @@ static bool link_is_ready_to_create_stacked_netdev(Link *link) {
|
||||
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);
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ 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 (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
|
||||
@@ -118,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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -1007,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;
|
||||
|
||||
|
||||
@@ -319,3 +319,49 @@ void link_clear_sr_iov_ifindices(Link *link) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -10,3 +10,8 @@ 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));
|
||||
|
||||
Reference in New Issue
Block a user