1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

network/netdev: replace old NetDev object with newer one on reload

Then, when a .netdev file of a stacked netdev is modified, the netdev
can be reconfigured with the updated setting by something like the
following way:
```
ip link del vlan99
networkctl reload
```

Note, removing the vlan interface in the above example may not be necessary,
e.g. when only VLAN flags, egress mapping, or ingress mapping are updated.
But, it is necessary when VLAN ID is updated.

Closes #9627.
Closes #27177.
Closes #34907.
Replaces #22557.
This commit is contained in:
Yu Watanabe 2024-10-27 16:38:24 +09:00
parent 890bd7225a
commit b3ae4e8622
3 changed files with 80 additions and 2 deletions

View File

@ -242,6 +242,7 @@ static NetDev* netdev_free(NetDev *netdev) {
condition_free_list(netdev->conditions);
free(netdev->filename);
strv_free(netdev->dropins);
hashmap_free(netdev->stats_by_path);
free(netdev->description);
free(netdev->ifname);
@ -1003,7 +1004,7 @@ int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) {
config_item_perf_lookup, network_netdev_gperf_lookup,
CONFIG_PARSE_WARN,
netdev,
NULL,
&netdev->stats_by_path,
&netdev->dropins);
if (r < 0)
return r; /* config_parse_many() logs internally. */
@ -1053,6 +1054,81 @@ int netdev_load(Manager *manager) {
return 0;
}
int netdev_reload(Manager *manager) {
_cleanup_hashmap_free_ Hashmap *new_netdevs = NULL;
_cleanup_strv_free_ char **files = NULL;
int r;
assert(manager);
r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS);
if (r < 0)
return log_error_errno(r, "Failed to enumerate netdev files: %m");
STRV_FOREACH(f, files) {
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
NetDev *old;
if (netdev_load_one(manager, *f, &netdev) < 0)
continue;
if (netdev_get(manager, netdev->ifname, &old) < 0) {
log_netdev_debug(netdev, "Found new .netdev file: %s", netdev->filename);
if (netdev_attach_name_full(netdev, netdev->ifname, &new_netdevs) >= 0)
TAKE_PTR(netdev);
continue;
}
if (!stats_by_path_equal(netdev->stats_by_path, old->stats_by_path)) {
log_netdev_debug(netdev, "Found updated .netdev file: %s", netdev->filename);
/* Copy ifindex. */
netdev->ifindex = old->ifindex;
if (netdev_attach_name_full(netdev, netdev->ifname, &new_netdevs) >= 0)
TAKE_PTR(netdev);
continue;
}
/* Keep the original object, and drop the new one. */
if (netdev_attach_name_full(old, old->ifname, &new_netdevs) >= 0)
netdev_ref(old);
}
/* Detach old NetDev objects from Manager.
* Note, the same object may be registered with multiple names, and netdev_detach() may drop multiple
* entries. Hence, hashmap_free_with_destructor() cannot be used. */
for (NetDev *n; (n = hashmap_first(manager->netdevs)); )
netdev_detach(n);
/* Attach new NetDev objects to Manager. */
for (;;) {
_cleanup_(netdev_unrefp) NetDev *netdev = hashmap_steal_first(new_netdevs);
if (!netdev)
break;
netdev->manager = manager;
if (netdev_attach(netdev) < 0)
continue;
/* Create a new netdev or update existing netdev, */
if (netdev_request_to_create(netdev) < 0)
continue;
TAKE_PTR(netdev);
}
/* Reassign NetDev objects to Link object. */
Link *link;
HASHMAP_FOREACH(link, manager->links_by_index)
link_assign_netdev(link);
return 0;
}
int config_parse_netdev_kind(
const char *unit,
const char *filename,

View File

@ -118,6 +118,7 @@ typedef struct NetDev {
char *filename;
char **dropins;
Hashmap *stats_by_path;
LIST_HEAD(Condition, conditions);
@ -218,6 +219,7 @@ void netdev_detach(NetDev *netdev);
int netdev_set_ifindex_internal(NetDev *netdev, int ifindex);
int netdev_load(Manager *manager);
int netdev_reload(Manager *manager);
int netdev_load_one(Manager *manager, const char *filename, NetDev **ret);
void netdev_drop(NetDev *netdev);
void netdev_enter_failed(NetDev *netdev);

View File

@ -1188,7 +1188,7 @@ int manager_reload(Manager *m, sd_bus_message *message) {
(void) notify_reloading();
r = netdev_load(m);
r = netdev_reload(m);
if (r < 0)
goto finish;