mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
Merge pull request #25143 from yuwata/network-reconfigure-interface-when-renamed
network: reconfigure interface when renamed
This commit is contained in:
@@ -1185,7 +1185,7 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
|
||||
assert(link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
|
||||
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = netdev_get(link->manager, link->ifname, &netdev);
|
||||
@@ -1367,21 +1367,18 @@ static int link_initialized_and_synced(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This may get called either from the asynchronous netlink callback,
|
||||
* or directly from link_check_initialized() if running in a container. */
|
||||
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
|
||||
return 0;
|
||||
if (link->state == LINK_STATE_PENDING) {
|
||||
log_link_debug(link, "Link state is up-to-date");
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
|
||||
log_link_debug(link, "Link state is up-to-date");
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
r = link_new_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_new_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return link_reconfigure_impl(link, /* force = */ false);
|
||||
}
|
||||
@@ -1426,14 +1423,10 @@ static int link_initialized(Link *link, sd_device *device) {
|
||||
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. */
|
||||
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED))
|
||||
return 0;
|
||||
if (link->state != LINK_STATE_PENDING)
|
||||
return link_reconfigure(link, /* force = */ false);
|
||||
|
||||
log_link_debug(link, "udev initialized link");
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
|
||||
/* udev has initialized the link, but we don't know if we have yet
|
||||
* processed the NEWLINK messages with the latest state. Do a GETLINK,
|
||||
@@ -1549,15 +1542,12 @@ static int link_carrier_gained(Link *link) {
|
||||
force_reconfigure = link->previous_ssid && !streq_ptr(link->previous_ssid, link->ssid);
|
||||
link->previous_ssid = mfree(link->previous_ssid);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence,
|
||||
* it is not necessary to call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or
|
||||
* NL80211_CMD_GET_STATION commands, and simply call link_reconfigure_impl().
|
||||
* Note, link_reconfigure_impl() returns 1 when the link is reconfigured. */
|
||||
r = link_reconfigure_impl(link, force_reconfigure);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence, it is not necessary to
|
||||
* call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or NL80211_CMD_GET_STATION commands, and simply call
|
||||
* link_reconfigure_impl(). Note, link_reconfigure_impl() returns 1 when the link is reconfigured. */
|
||||
r = link_reconfigure_impl(link, force_reconfigure);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = link_handle_bound_by_list(link);
|
||||
if (r < 0)
|
||||
@@ -2043,15 +2033,17 @@ static int link_update_driver(Link *link, sd_netlink_message *message) {
|
||||
assert(message);
|
||||
|
||||
/* Driver is already read. Assuming the driver is never changed. */
|
||||
if (link->driver)
|
||||
if (link->ethtool_driver_read)
|
||||
return 0;
|
||||
|
||||
/* When udevd is running, read the driver after the interface is initialized by udevd.
|
||||
* Otherwise, ethtool may not work correctly. See issue #22538.
|
||||
* When udevd is not running, read the value when the interface is detected. */
|
||||
if (link->state != (udev_available() ? LINK_STATE_INITIALIZED : LINK_STATE_PENDING))
|
||||
if (udev_available() && !link->dev)
|
||||
return 0;
|
||||
|
||||
link->ethtool_driver_read = true;
|
||||
|
||||
r = ethtool_get_driver(&link->manager->ethtool_fd, link->ifname, &link->driver);
|
||||
if (r < 0) {
|
||||
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
|
||||
@@ -2076,6 +2068,38 @@ static int link_update_driver(Link *link, sd_netlink_message *message) {
|
||||
link->dsa_master_ifindex = (int) dsa_master_ifindex;
|
||||
}
|
||||
|
||||
return 1; /* needs reconfigure */
|
||||
}
|
||||
|
||||
static int link_update_permanent_hardware_address_from_ethtool(Link *link, sd_netlink_message *message) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(message);
|
||||
|
||||
if (link->ethtool_permanent_hw_addr_read)
|
||||
return 0;
|
||||
|
||||
/* When udevd is running, read the permanent hardware address after the interface is
|
||||
* initialized by udevd. Otherwise, ethtool may not work correctly. See issue #22538.
|
||||
* When udevd is not running, read the value when the interface is detected. */
|
||||
if (udev_available() && !link->dev)
|
||||
return 0;
|
||||
|
||||
/* If the interface does not have a hardware address, then it will not have a permanent address either. */
|
||||
r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, NULL);
|
||||
if (r == -ENODATA)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to read IFLA_ADDRESS attribute: %m");
|
||||
|
||||
link->ethtool_permanent_hw_addr_read = true;
|
||||
|
||||
r = ethtool_get_permanent_hw_addr(&link->manager->ethtool_fd, link->ifname, &link->permanent_hw_addr);
|
||||
if (r < 0)
|
||||
log_link_debug_errno(link, r, "Permanent hardware address not found, continuing without: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2089,29 +2113,21 @@ static int link_update_permanent_hardware_address(Link *link, sd_netlink_message
|
||||
if (link->permanent_hw_addr.length > 0)
|
||||
return 0;
|
||||
|
||||
/* When udevd is running, read the permanent hardware address after the interface is
|
||||
* initialized by udevd. Otherwise, ethtool may not work correctly. See issue #22538.
|
||||
* When udevd is not running, read the value when the interface is detected. */
|
||||
if (link->state != (udev_available() ? LINK_STATE_INITIALIZED : LINK_STATE_PENDING))
|
||||
return 0;
|
||||
|
||||
r = netlink_message_read_hw_addr(message, IFLA_PERM_ADDRESS, &link->permanent_hw_addr);
|
||||
if (r < 0) {
|
||||
if (r != -ENODATA)
|
||||
return log_link_debug_errno(link, r, "Failed to read IFLA_PERM_ADDRESS attribute: %m");
|
||||
|
||||
if (netlink_message_read_hw_addr(message, IFLA_ADDRESS, NULL) >= 0) {
|
||||
/* Fallback to ethtool, if the link has a hardware address. */
|
||||
r = ethtool_get_permanent_hw_addr(&link->manager->ethtool_fd, link->ifname, &link->permanent_hw_addr);
|
||||
if (r < 0)
|
||||
log_link_debug_errno(link, r, "Permanent hardware address not found, continuing without: %m");
|
||||
}
|
||||
/* Fallback to ethtool for older kernels. */
|
||||
r = link_update_permanent_hardware_address_from_ethtool(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->permanent_hw_addr.length > 0)
|
||||
log_link_debug(link, "Saved permanent hardware address: %s", HW_ADDR_TO_STR(&link->permanent_hw_addr));
|
||||
|
||||
return 0;
|
||||
return 1; /* needs reconfigure */
|
||||
}
|
||||
|
||||
static int link_update_hardware_address(Link *link, sd_netlink_message *message) {
|
||||
@@ -2194,7 +2210,7 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message)
|
||||
return log_link_debug_errno(link, r, "Could not update MAC address for LLDP Tx: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1; /* needs reconfigure */
|
||||
}
|
||||
|
||||
static int link_update_mtu(Link *link, sd_netlink_message *message) {
|
||||
@@ -2286,7 +2302,7 @@ static int link_update_alternative_names(Link *link, sd_netlink_message *message
|
||||
return log_link_debug_errno(link, r, "Failed to manage link by its new alternative names: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1; /* needs reconfigure */
|
||||
}
|
||||
|
||||
static int link_update_name(Link *link, sd_netlink_message *message) {
|
||||
@@ -2382,10 +2398,11 @@ static int link_update_name(Link *link, sd_netlink_message *message) {
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to update interface name in IPv4ACD client: %m");
|
||||
|
||||
return 0;
|
||||
return 1; /* needs reconfigure */
|
||||
}
|
||||
|
||||
static int link_update(Link *link, sd_netlink_message *message) {
|
||||
bool needs_reconfigure = false;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@@ -2394,10 +2411,12 @@ static int link_update(Link *link, sd_netlink_message *message) {
|
||||
r = link_update_name(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
needs_reconfigure = needs_reconfigure || r > 0;
|
||||
|
||||
r = link_update_alternative_names(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
needs_reconfigure = needs_reconfigure || r > 0;
|
||||
|
||||
r = link_update_mtu(link, message);
|
||||
if (r < 0)
|
||||
@@ -2406,14 +2425,17 @@ static int link_update(Link *link, sd_netlink_message *message) {
|
||||
r = link_update_driver(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
needs_reconfigure = needs_reconfigure || r > 0;
|
||||
|
||||
r = link_update_permanent_hardware_address(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
needs_reconfigure = needs_reconfigure || r > 0;
|
||||
|
||||
r = link_update_hardware_address(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
needs_reconfigure = needs_reconfigure || r > 0;
|
||||
|
||||
r = link_update_master(link, message);
|
||||
if (r < 0)
|
||||
@@ -2423,7 +2445,11 @@ static int link_update(Link *link, sd_netlink_message *message) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return link_update_flags(link, message);
|
||||
r = link_update_flags(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return needs_reconfigure;
|
||||
}
|
||||
|
||||
static Link *link_drop_or_unref(Link *link) {
|
||||
@@ -2612,6 +2638,14 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
if (r > 0) {
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ typedef struct Link {
|
||||
sd_device *dev;
|
||||
char *driver;
|
||||
|
||||
/* to prevent multiple ethtool calls */
|
||||
bool ethtool_driver_read;
|
||||
bool ethtool_permanent_hw_addr_read;
|
||||
|
||||
/* link-local addressing */
|
||||
IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode;
|
||||
|
||||
|
||||
7
test/test-network/conf/12-dummy-altname.link
Normal file
7
test/test-network/conf/12-dummy-altname.link
Normal file
@@ -0,0 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
OriginalName=dummy98-2
|
||||
Driver=dummy
|
||||
|
||||
[Link]
|
||||
AlternativeName=dummy98-2-altname
|
||||
5
test/test-network/conf/12-dummy-mac.netdev
Normal file
5
test/test-network/conf/12-dummy-mac.netdev
Normal file
@@ -0,0 +1,5 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[NetDev]
|
||||
Name=dummy98
|
||||
Kind=dummy
|
||||
MACAddress=12:34:56:78:9a:01
|
||||
9
test/test-network/conf/12-dummy-match-altname.network
Normal file
9
test/test-network/conf/12-dummy-match-altname.network
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy98-2-altname
|
||||
Driver=dummy
|
||||
MACAddress=12:34:56:78:9a:02
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.2.2/16
|
||||
9
test/test-network/conf/12-dummy-match-mac-01.network
Normal file
9
test/test-network/conf/12-dummy-match-mac-01.network
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy98
|
||||
Driver=dummy
|
||||
MACAddress=12:34:56:78:9a:01
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.1/16
|
||||
9
test/test-network/conf/12-dummy-match-mac-02.network
Normal file
9
test/test-network/conf/12-dummy-match-mac-02.network
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy98
|
||||
Driver=dummy
|
||||
MACAddress=12:34:56:78:9a:02
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.0.2/16
|
||||
9
test/test-network/conf/12-dummy-match-renamed.network
Normal file
9
test/test-network/conf/12-dummy-match-renamed.network
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Match]
|
||||
Name=dummy98-1
|
||||
Driver=dummy
|
||||
MACAddress=12:34:56:78:9a:02
|
||||
|
||||
[Network]
|
||||
IPv6AcceptRA=no
|
||||
Address=10.0.1.2/16
|
||||
@@ -1090,6 +1090,54 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
||||
self.check_link_exists('veth99', expected=False)
|
||||
self.check_link_exists('veth-peer', expected=False)
|
||||
|
||||
class NetworkdMatchTests(unittest.TestCase, Utilities):
|
||||
|
||||
def setUp(self):
|
||||
setup_common()
|
||||
|
||||
def tearDown(self):
|
||||
tear_down_common()
|
||||
|
||||
def test_match(self):
|
||||
copy_network_unit('12-dummy-mac.netdev',
|
||||
'12-dummy-match-mac-01.network',
|
||||
'12-dummy-match-mac-02.network',
|
||||
'12-dummy-match-renamed.network',
|
||||
'12-dummy-match-altname.network',
|
||||
'12-dummy-altname.link')
|
||||
start_networkd()
|
||||
|
||||
self.wait_online(['dummy98:routable'])
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
|
||||
self.assertIn('Network File: /run/systemd/network/12-dummy-match-mac-01.network', output)
|
||||
output = check_output('ip -4 address show dev dummy98')
|
||||
self.assertIn('10.0.0.1/16', output)
|
||||
|
||||
check_output('ip link set dev dummy98 down')
|
||||
check_output('ip link set dev dummy98 address 12:34:56:78:9a:02')
|
||||
|
||||
self.wait_address('dummy98', '10.0.0.2/16', ipv='-4', timeout_sec=10)
|
||||
self.wait_online(['dummy98:routable'])
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
|
||||
self.assertIn('Network File: /run/systemd/network/12-dummy-match-mac-02.network', output)
|
||||
|
||||
check_output('ip link set dev dummy98 down')
|
||||
check_output('ip link set dev dummy98 name dummy98-1')
|
||||
|
||||
self.wait_address('dummy98-1', '10.0.1.2/16', ipv='-4', timeout_sec=10)
|
||||
self.wait_online(['dummy98-1:routable'])
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98-1', env=env)
|
||||
self.assertIn('Network File: /run/systemd/network/12-dummy-match-renamed.network', output)
|
||||
|
||||
check_output('ip link set dev dummy98-1 down')
|
||||
check_output('ip link set dev dummy98-1 name dummy98-2')
|
||||
check_output(*udevadm_cmd, 'trigger', '--action=add', '/sys/class/net/dummy98-2')
|
||||
|
||||
self.wait_address('dummy98-2', '10.0.2.2/16', ipv='-4', timeout_sec=10)
|
||||
self.wait_online(['dummy98-2:routable'])
|
||||
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98-2', env=env)
|
||||
self.assertIn('Network File: /run/systemd/network/12-dummy-match-altname.network', output)
|
||||
|
||||
class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user