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:
Yu Watanabe
2022-08-05 21:49:27 +09:00
parent b0ff6dea38
commit e33232d405
5 changed files with 83 additions and 5 deletions
+11 -2
View File
@@ -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);
+5 -1
View File
@@ -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);
}
+16 -2
View File
@@ -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;
+46
View File
@@ -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;
}
+5
View File
@@ -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));