Merge pull request #25192 from yuwata/wait-online-altname
wait-online: support alternative interface names
This commit is contained in:
@@ -2238,7 +2238,7 @@ static int link_update_alternative_names(Link *link, sd_netlink_message *message
|
||||
|
||||
r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &altnames);
|
||||
if (r == -ENODATA)
|
||||
/* The message does not have IFLA_PROP_LIST container attribute. It does not means the
|
||||
/* The message does not have IFLA_PROP_LIST container attribute. It does not mean the
|
||||
* interface has no alternative name. */
|
||||
return 0;
|
||||
if (r < 0)
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
#include "sd-network.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "format-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "link.h"
|
||||
#include "manager.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) {
|
||||
_cleanup_(link_freep) Link *l = NULL;
|
||||
@@ -55,15 +57,95 @@ Link *link_free(Link *l) {
|
||||
if (l->manager) {
|
||||
hashmap_remove(l->manager->links_by_index, INT_TO_PTR(l->ifindex));
|
||||
hashmap_remove(l->manager->links_by_name, l->ifname);
|
||||
|
||||
STRV_FOREACH(n, l->altnames)
|
||||
hashmap_remove(l->manager->links_by_name, *n);
|
||||
}
|
||||
|
||||
free(l->state);
|
||||
free(l->ifname);
|
||||
strv_free(l->altnames);
|
||||
return mfree(l);
|
||||
}
|
||||
}
|
||||
|
||||
static int link_update_name(Link *l, sd_netlink_message *m) {
|
||||
char ifname_from_index[IF_NAMESIZE];
|
||||
const char *ifname;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(l->manager);
|
||||
assert(m);
|
||||
|
||||
r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
|
||||
if (r == -ENODATA)
|
||||
/* Hmm? But ok. */
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq(ifname, l->ifname))
|
||||
return 0;
|
||||
|
||||
/* The kernel sometimes sends wrong ifname change. Let's confirm the received name. */
|
||||
r = format_ifname(l->ifindex, ifname_from_index);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(ifname, ifname_from_index)) {
|
||||
log_link_debug(l, "New interface name '%s' received from the kernel does not correspond "
|
||||
"with the name currently configured on the actual interface '%s'. Ignoring.",
|
||||
ifname, ifname_from_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hashmap_remove(l->manager->links_by_name, l->ifname);
|
||||
|
||||
r = free_and_strdup(&l->ifname, ifname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&l->manager->links_by_name, &string_hash_ops, l->ifname, l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_update_altnames(Link *l, sd_netlink_message *m) {
|
||||
_cleanup_strv_free_ char **altnames = NULL;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(l->manager);
|
||||
assert(m);
|
||||
|
||||
r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &altnames);
|
||||
if (r == -ENODATA)
|
||||
/* The message does not have IFLA_PROP_LIST container attribute. It does not mean the
|
||||
* interface has no alternative name. */
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (strv_equal(altnames, l->altnames))
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(n, l->altnames)
|
||||
hashmap_remove(l->manager->links_by_name, *n);
|
||||
|
||||
strv_free_and_replace(l->altnames, altnames);
|
||||
|
||||
STRV_FOREACH(n, l->altnames) {
|
||||
r = hashmap_ensure_put(&l->manager->links_by_name, &string_hash_ops, *n, l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_update_rtnl(Link *l, sd_netlink_message *m) {
|
||||
const char *ifname;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
@@ -74,24 +156,13 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
|
||||
r = link_update_name(l, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(l->ifname, ifname)) {
|
||||
char *new_ifname;
|
||||
|
||||
new_ifname = strdup(ifname);
|
||||
if (!new_ifname)
|
||||
return -ENOMEM;
|
||||
|
||||
assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l);
|
||||
free_and_replace(l->ifname, new_ifname);
|
||||
|
||||
r = hashmap_put(l->manager->links_by_name, l->ifname, l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = link_update_altnames(l, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ struct Link {
|
||||
|
||||
int ifindex;
|
||||
char *ifname;
|
||||
char **altnames;
|
||||
unsigned flags;
|
||||
|
||||
bool required_for_online;
|
||||
|
||||
@@ -12,6 +12,20 @@
|
||||
#include "time-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static bool link_in_command_line_interfaces(Link *link, Manager *m) {
|
||||
assert(link);
|
||||
assert(m);
|
||||
|
||||
if (hashmap_contains(m->command_line_interfaces_by_name, link->ifname))
|
||||
return true;
|
||||
|
||||
STRV_FOREACH(n, link->altnames)
|
||||
if (hashmap_contains(m->command_line_interfaces_by_name, *n))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool manager_ignore_link(Manager *m, Link *link) {
|
||||
assert(m);
|
||||
assert(link);
|
||||
@@ -22,14 +36,21 @@ static bool manager_ignore_link(Manager *m, Link *link) {
|
||||
|
||||
/* if interfaces are given on the command line, ignore all others */
|
||||
if (m->command_line_interfaces_by_name &&
|
||||
!hashmap_contains(m->command_line_interfaces_by_name, link->ifname))
|
||||
!link_in_command_line_interfaces(link, m))
|
||||
return true;
|
||||
|
||||
if (!link->required_for_online)
|
||||
return true;
|
||||
|
||||
/* ignore interfaces we explicitly are asked to ignore */
|
||||
return strv_fnmatch(m->ignored_interfaces, link->ifname);
|
||||
if (strv_fnmatch(m->ignored_interfaces, link->ifname))
|
||||
return true;
|
||||
|
||||
STRV_FOREACH(n, link->altnames)
|
||||
if (strv_fnmatch(m->ignored_interfaces, *n))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange s) {
|
||||
@@ -58,7 +79,7 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
|
||||
if (streq(l->state, "unmanaged")) {
|
||||
/* If the link is in unmanaged state, then ignore the interface unless the interface is
|
||||
* specified in '--interface/-i' option. */
|
||||
if (!hashmap_contains(m->command_line_interfaces_by_name, l->ifname)) {
|
||||
if (!link_in_command_line_interfaces(l, m)) {
|
||||
log_link_debug(l, "link is not managed by networkd (yet?).");
|
||||
return 0;
|
||||
}
|
||||
@@ -212,11 +233,13 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
|
||||
|
||||
case RTM_NEWLINK:
|
||||
if (!l) {
|
||||
log_debug("Found link %i", ifindex);
|
||||
log_debug("Found link %s(%i)", ifname, ifindex);
|
||||
|
||||
r = link_new(m, &l, ifindex, ifname);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create link object: %m");
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to create link object for %s(%i), ignoring: %m", ifname, ifindex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = link_update_rtnl(l, mm);
|
||||
|
||||
Reference in New Issue
Block a user