Merge pull request #34331 from yuwata/network-netdev-cleanups

network/netdev: several cleanups for attaching/detaching netdev, and setting/getting ifindex from netdev
This commit is contained in:
Yu Watanabe
2024-09-10 22:05:55 +09:00
committed by GitHub
13 changed files with 610 additions and 124 deletions

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <netinet/in.h>
#include <linux/if_arp.h>
#include <linux/l2tp.h>
#include <linux/genetlink.h>
@@ -752,28 +753,40 @@ static void l2tp_tunnel_init(NetDev *netdev) {
t->udp6_csum_tx = true;
}
static int l2tp_session_verify(L2tpSession *session) {
NetDev *netdev;
#define log_session(session, fmt, ...) \
({ \
const L2tpSession *_session = (session); \
log_section_warning_errno( \
_session ? _session->section : NULL, \
SYNTHETIC_ERRNO(EINVAL), \
fmt " Ignoring [L2TPSession] section.", \
##__VA_ARGS__); \
})
static int l2tp_session_verify(L2tpSession *session, Set **names) {
int r;
assert(session);
assert(session->tunnel);
netdev = NETDEV(session->tunnel);
assert(names);
if (section_is_invalid(session->section))
return -EINVAL;
if (!session->name)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP session without name configured. "
"Ignoring [L2TPSession] section from line %u",
session->section->filename, session->section->line);
return log_session(session, "L2TP session without name configured.");
if (session->session_id == 0 || session->peer_session_id == 0)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP session without session IDs configured. "
"Ignoring [L2TPSession] section from line %u",
session->section->filename, session->section->line);
return log_session(session, "L2TP session without session IDs configured.");
if (streq(session->name, NETDEV(session->tunnel)->ifname))
return log_session(session, "L2TP session name %s cannot be the same as the netdev name.", session->name);
r = set_ensure_put(names, &string_hash_ops, session->name);
if (r < 0)
return log_oom();
if (r == 0)
return log_session(session, "L2TP session name %s is duplicated.", session->name);
return 0;
}
@@ -785,27 +798,100 @@ static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) {
L2tpSession *session;
if (!IN_SET(t->family, AF_INET, AF_INET6))
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel with invalid address family configured. Ignoring",
filename);
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel with invalid address family configured. Ignoring",
filename);
if (!in_addr_is_set(t->family, &t->remote))
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel without a remote address configured. Ignoring",
filename);
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel without a remote address configured. Ignoring",
filename);
if (t->tunnel_id == 0 || t->peer_tunnel_id == 0)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel without tunnel IDs configured. Ignoring",
filename);
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: L2TP tunnel without tunnel IDs configured. Ignoring",
filename);
_cleanup_set_free_ Set *names = NULL;
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
if (l2tp_session_verify(session) < 0)
if (l2tp_session_verify(session, &names) < 0)
l2tp_session_free(session);
return 0;
}
static int netdev_l2tp_tunnel_attach(NetDev *netdev) {
L2tpTunnel *t = L2TP(netdev);
L2tpSession *session;
int r;
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) {
assert(session->name);
r = netdev_attach_name(netdev, session->name);
if (r < 0)
return r;
}
return 0;
}
static void netdev_l2tp_tunnel_detach(NetDev *netdev) {
L2tpTunnel *t = L2TP(netdev);
L2tpSession *session;
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
netdev_detach_name(netdev, session->name);
}
static int netdev_l2tp_tunnel_set_ifindex(NetDev *netdev, const char *name, int ifindex) {
L2tpTunnel *t = L2TP(netdev);
L2tpSession *session;
bool found = false;
assert(name);
assert(ifindex > 0);
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
if (streq(session->name, name)) {
if (session->ifindex == ifindex)
return 0; /* already set. */
if (session->ifindex > 0 && session->ifindex != ifindex)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST),
"Could not set ifindex %i for session %s, already set to %i.",
ifindex, session->name, session->ifindex);
session->ifindex = ifindex;
log_netdev_debug(netdev, "Session %s gained ifindex %i.", session->name, session->ifindex);
found = true;
break;
}
if (!found)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Received netlink message with unexpected interface name %s (ifindex=%i).",
name, ifindex);
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
if (session->ifindex <= 0)
return 0; /* This session is not ready yet. */
return netdev_enter_ready(netdev);
}
static int netdev_l2tp_tunnel_get_ifindex(NetDev *netdev, const char *name) {
L2tpTunnel *t = L2TP(netdev);
L2tpSession *session;
assert(name);
ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section)
if (streq(session->name, name))
return session->ifindex;
return -ENODEV;
}
static void l2tp_tunnel_done(NetDev *netdev) {
L2tpTunnel *t = L2TP(netdev);
@@ -822,4 +908,10 @@ const NetDevVTable l2tptnl_vtable = {
.create_type = NETDEV_CREATE_INDEPENDENT,
.is_ready_to_create = netdev_l2tp_is_ready_to_create,
.config_verify = netdev_l2tp_tunnel_verify,
.attach = netdev_l2tp_tunnel_attach,
.detach = netdev_l2tp_tunnel_detach,
.set_ifindex = netdev_l2tp_tunnel_set_ifindex,
.get_ifindex = netdev_l2tp_tunnel_get_ifindex,
.iftype = ARPHRD_ETHER,
.skip_netdev_kind_check = true,
};

View File

@@ -37,6 +37,7 @@ typedef struct L2tpSession {
ConfigSection *section;
char *name;
int ifindex;
uint32_t session_id;
uint32_t peer_session_id;

View File

@@ -191,14 +191,40 @@ static bool netdev_is_stacked(NetDev *netdev) {
return true;
}
static void netdev_detach_from_manager(NetDev *netdev) {
if (netdev->ifname && netdev->manager)
hashmap_remove(netdev->manager->netdevs, netdev->ifname);
NetDev* netdev_detach_name(NetDev *netdev, const char *name) {
assert(netdev);
if (!netdev->manager || !name)
return NULL; /* Already detached or not attached yet. */
return hashmap_remove_value(netdev->manager->netdevs, name, netdev);
}
static NetDev *netdev_free(NetDev *netdev) {
static NetDev* netdev_detach_impl(NetDev *netdev) {
assert(netdev);
if (netdev->state != _NETDEV_STATE_INVALID &&
NETDEV_VTABLE(netdev) &&
NETDEV_VTABLE(netdev)->detach)
NETDEV_VTABLE(netdev)->detach(netdev);
NetDev *n = netdev_detach_name(netdev, netdev->ifname);
netdev->manager = NULL;
return n; /* Return NULL when it is not attached yet, or already detached. */
}
void netdev_detach(NetDev *netdev) {
assert(netdev);
netdev_unref(netdev_detach_impl(netdev));
}
static NetDev* netdev_free(NetDev *netdev) {
assert(netdev);
netdev_detach_impl(netdev);
/* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that
* because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure
* allocation, with no room for per-kind fields), and once to read the kind's properties (with a full,
@@ -211,8 +237,6 @@ static NetDev *netdev_free(NetDev *netdev) {
NETDEV_VTABLE(netdev)->done)
NETDEV_VTABLE(netdev)->done(netdev);
netdev_detach_from_manager(netdev);
condition_free_list(netdev->conditions);
free(netdev->filename);
strv_free(netdev->dropins);
@@ -245,9 +269,52 @@ void netdev_drop(NetDev *netdev) {
log_netdev_debug(netdev, "netdev removed");
netdev_detach_from_manager(netdev);
netdev_unref(netdev);
return;
netdev_detach(netdev);
}
int netdev_attach_name(NetDev *netdev, const char *name) {
int r;
assert(netdev);
assert(netdev->manager);
assert(name);
r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, name, netdev);
if (r == -ENOMEM)
return log_oom();
if (r == -EEXIST) {
NetDev *n = hashmap_get(netdev->manager->netdevs, name);
assert(n);
if (!streq(netdev->filename, n->filename))
log_netdev_warning_errno(netdev, r,
"Device \"%s\" was already configured by \"%s\", ignoring %s.",
name, n->filename, netdev->filename);
return -EEXIST;
}
assert(r > 0);
return 0;
}
static int netdev_attach(NetDev *netdev) {
int r;
assert(netdev);
assert(netdev->ifname);
r = netdev_attach_name(netdev, netdev->ifname);
if (r < 0)
return r;
if (NETDEV_VTABLE(netdev)->attach) {
r = NETDEV_VTABLE(netdev)->attach(netdev);
if (r < 0)
return r;
}
return 0;
}
int netdev_get(Manager *manager, const char *name, NetDev **ret) {
@@ -266,11 +333,51 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) {
return 0;
}
void link_assign_netdev(Link *link) {
_unused_ _cleanup_(netdev_unrefp) NetDev *old = NULL;
NetDev *netdev;
assert(link);
assert(link->manager);
assert(link->ifname);
old = TAKE_PTR(link->netdev);
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return;
int ifindex = NETDEV_VTABLE(netdev)->get_ifindex ?
NETDEV_VTABLE(netdev)->get_ifindex(netdev, link->ifname) :
netdev->ifindex;
if (ifindex != link->ifindex)
return;
if (NETDEV_VTABLE(netdev)->iftype != link->iftype)
return;
if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) {
const char *kind;
if (netdev->kind == NETDEV_KIND_TAP)
kind = "tun"; /* the kernel does not distinguish between tun and tap */
else
kind = netdev_kind_to_string(netdev->kind);
if (!streq_ptr(kind, link->kind))
return;
}
link->netdev = netdev_ref(netdev);
if (netdev != old)
log_link_debug(link, "Found matching .netdev file: %s", netdev->filename);
}
void netdev_enter_failed(NetDev *netdev) {
netdev->state = NETDEV_STATE_FAILED;
}
static int netdev_enter_ready(NetDev *netdev) {
int netdev_enter_ready(NetDev *netdev) {
assert(netdev);
assert(netdev->ifname);
@@ -309,96 +416,108 @@ static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev
return 1;
}
int netdev_set_ifindex_internal(NetDev *netdev, int ifindex) {
assert(netdev);
assert(ifindex > 0);
if (netdev->ifindex == ifindex)
return 0; /* Already set. */
if (netdev->ifindex > 0 && netdev->ifindex != ifindex)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST),
"Could not set ifindex to %i, already set to %i.",
ifindex, netdev->ifindex);
netdev->ifindex = ifindex;
log_netdev_debug(netdev, "Gained index %i.", ifindex);
return 1; /* set new ifindex. */
}
static int netdev_set_ifindex_impl(NetDev *netdev, const char *name, int ifindex) {
int r;
assert(netdev);
assert(name);
assert(ifindex > 0);
if (NETDEV_VTABLE(netdev)->set_ifindex)
return NETDEV_VTABLE(netdev)->set_ifindex(netdev, name, ifindex);
if (!streq(netdev->ifname, name))
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Received netlink message with unexpected interface name %s (ifindex=%i).",
name, ifindex);
r = netdev_set_ifindex_internal(netdev, ifindex);
if (r <= 0)
return r;
return netdev_enter_ready(netdev);
}
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) {
uint16_t type;
const char *kind;
const char *received_kind;
const char *received_name;
int r, ifindex;
int r, ifindex, family;
assert(netdev);
assert(message);
r = sd_netlink_message_get_type(message, &type);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m");
return log_netdev_warning_errno(netdev, r, "Could not get rtnl message type: %m");
if (type != RTM_NEWLINK)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type.");
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type.");
r = sd_rtnl_message_get_family(message, &family);
if (r < 0)
return log_netdev_warning_errno(netdev, r, "Failed to get family from received rtnl message: %m");
if (family != AF_UNSPEC)
return 0; /* IFLA_LINKINFO is only contained in the message with AF_UNSPEC. */
r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
if (r < 0) {
log_netdev_error_errno(netdev, r, "Could not get ifindex: %m");
netdev_enter_failed(netdev);
return r;
} else if (ifindex <= 0) {
log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex);
netdev_enter_failed(netdev);
return -EINVAL;
}
if (netdev->ifindex > 0) {
if (netdev->ifindex != ifindex) {
log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d",
ifindex, netdev->ifindex);
netdev_enter_failed(netdev);
return -EEXIST;
} else
/* ifindex already set to the same for this netdev */
return 0;
}
if (r < 0)
return log_netdev_warning_errno(netdev, r, "Could not get ifindex: %m");
if (ifindex <= 0)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Got invalid ifindex: %d", ifindex);
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m");
if (!streq(netdev->ifname, received_name)) {
log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name);
netdev_enter_failed(netdev);
return -EINVAL;
}
return log_netdev_warning_errno(netdev, r, "Could not get IFNAME: %m");
if (!NETDEV_VTABLE(netdev)->skip_netdev_kind_check) {
r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m");
return log_netdev_warning_errno(netdev, r, "Could not get LINKINFO: %m");
r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not get KIND: %m");
return log_netdev_warning_errno(netdev, r, "Could not get KIND: %m");
r = sd_netlink_message_exit_container(message);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not exit container: %m");
return log_netdev_warning_errno(netdev, r, "Could not exit container: %m");
if (netdev->kind == NETDEV_KIND_TAP)
/* the kernel does not distinguish between tun and tap */
kind = "tun";
else {
else
kind = netdev_kind_to_string(netdev->kind);
if (!kind) {
log_netdev_error(netdev, "Could not get kind");
netdev_enter_failed(netdev);
return -EINVAL;
}
}
if (!kind)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Could not get netdev kind.");
if (!streq(kind, received_kind)) {
log_netdev_error(netdev, "Received newlink with wrong KIND %s, expected %s",
received_kind, kind);
netdev_enter_failed(netdev);
return -EINVAL;
}
if (!streq(kind, received_kind))
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Received newlink with wrong KIND %s, expected %s",
received_kind, kind);
}
netdev->ifindex = ifindex;
log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex);
netdev_enter_ready(netdev);
return 0;
return netdev_set_ifindex_impl(netdev, received_name, ifindex);
}
#define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
@@ -850,24 +969,9 @@ int netdev_load_one(Manager *manager, const char *filename) {
if (!netdev->filename)
return log_oom();
r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, netdev->ifname, netdev);
if (r == -ENOMEM)
return log_oom();
if (r == -EEXIST) {
NetDev *n = hashmap_get(netdev->manager->netdevs, netdev->ifname);
assert(n);
if (!streq(netdev->filename, n->filename))
log_netdev_warning_errno(netdev, r,
"Device was already configured by \"%s\", ignoring %s.",
n->filename, netdev->filename);
/* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
* removed from the hashmap 'manager->netdevs'. */
netdev->ifname = mfree(netdev->ifname);
return -EEXIST;
}
assert(r > 0);
r = netdev_attach(netdev);
if (r < 0)
return r;
log_netdev_debug(netdev, "loaded \"%s\"", netdev_kind_to_string(netdev->kind));

View File

@@ -5,6 +5,7 @@
#include "conf-parser.h"
#include "ether-addr-util.h"
#include "hash-funcs.h"
#include "list.h"
#include "log-link.h"
#include "networkd-link.h"
@@ -168,6 +169,16 @@ typedef struct NetDevVTable {
/* verify that compulsory configuration options were specified */
int (*config_verify)(NetDev *netdev, const char *filename);
/* attach/detach additional interfaces, e.g. veth peer or L2TP sessions. */
int (*attach)(NetDev *netdev);
void (*detach)(NetDev *netdev);
/* set ifindex of the created interface. */
int (*set_ifindex)(NetDev *netdev, const char *name, int ifindex);
/* get ifindex of the netdev. */
int (*get_ifindex)(NetDev *netdev, const char *name);
/* expected iftype, e.g. ARPHRD_ETHER. */
uint16_t iftype;
@@ -195,10 +206,16 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
/* For casting the various netdev kinds into a netdev */
#define NETDEV(n) (&(n)->meta)
int netdev_attach_name(NetDev *netdev, const char *name);
NetDev* netdev_detach_name(NetDev *netdev, const char *name);
void netdev_detach(NetDev *netdev);
int netdev_set_ifindex_internal(NetDev *netdev, int ifindex);
int netdev_load(Manager *manager, bool reload);
int netdev_load_one(Manager *manager, const char *filename);
void netdev_drop(NetDev *netdev);
void netdev_enter_failed(NetDev *netdev);
int netdev_enter_ready(NetDev *netdev);
NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev);
@@ -207,6 +224,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
bool netdev_is_managed(NetDev *netdev);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
void link_assign_netdev(Link *link);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_generate_hw_addr(NetDev *netdev, Link *link, const char *name,
const struct hw_addr_data *hw_addr, struct hw_addr_data *ret);

View File

@@ -62,9 +62,75 @@ static int netdev_veth_verify(NetDev *netdev, const char *filename) {
"Veth NetDev without peer name configured in %s. Ignoring",
filename);
if (streq(v->ifname_peer, netdev->ifname))
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Veth peer name cannot be the same as the main interface name.");
return 0;
}
static int netdev_veth_attach(NetDev *netdev) {
Veth *v = VETH(netdev);
assert(v->ifname_peer);
return netdev_attach_name(netdev, v->ifname_peer);
}
static void netdev_veth_detach(NetDev *netdev) {
Veth *v = VETH(netdev);
netdev_detach_name(netdev, v->ifname_peer);
}
static int netdev_veth_set_ifindex(NetDev *netdev, const char *name, int ifindex) {
Veth *v = VETH(netdev);
int r;
assert(name);
assert(ifindex > 0);
if (streq(netdev->ifname, name)) {
r = netdev_set_ifindex_internal(netdev, ifindex);
if (r <= 0)
return r;
} else if (streq(v->ifname_peer, name)) {
if (v->ifindex_peer == ifindex)
return 0; /* already set. */
if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST),
"Could not set ifindex %i for peer %s, already set to %i.",
ifindex, v->ifname_peer, v->ifindex_peer);
v->ifindex_peer = ifindex;
log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex);
} else
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Received netlink message with unexpected interface name %s (index=%i).",
name, ifindex);
if (netdev->ifindex > 0 && v->ifindex_peer > 0)
return netdev_enter_ready(netdev);
return 0;
}
static int netdev_veth_get_ifindex(NetDev *netdev, const char *name) {
Veth *v = VETH(netdev);
assert(name);
if (streq(netdev->ifname, name))
return netdev->ifindex;
if (streq(v->ifname_peer, name))
return v->ifindex_peer;
return -ENODEV;
}
static void veth_done(NetDev *netdev) {
Veth *v = VETH(netdev);
@@ -78,6 +144,10 @@ const NetDevVTable veth_vtable = {
.fill_message_create = netdev_veth_fill_message_create,
.create_type = NETDEV_CREATE_INDEPENDENT,
.config_verify = netdev_veth_verify,
.attach = netdev_veth_attach,
.detach = netdev_veth_detach,
.set_ifindex = netdev_veth_set_ifindex,
.get_ifindex = netdev_veth_get_ifindex,
.iftype = ARPHRD_ETHER,
.generate_mac = true,
};

View File

@@ -10,6 +10,7 @@ struct Veth {
char *ifname_peer;
struct hw_addr_data hw_addr_peer;
int ifindex_peer;
};
DEFINE_NETDEV_CAST(VETH, Veth);

View File

@@ -38,9 +38,74 @@ static int netdev_vxcan_verify(NetDev *netdev, const char *filename) {
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"VxCan NetDev without peer name configured in %s. Ignoring", filename);
if (streq(v->ifname_peer, netdev->ifname))
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"VxCan peer name cannot be the same as the main interface name.");
return 0;
}
static int netdev_vxcan_attach(NetDev *netdev) {
VxCan *v = VXCAN(netdev);
assert(v->ifname_peer);
return netdev_attach_name(netdev, v->ifname_peer);
}
static void netdev_vxcan_detach(NetDev *netdev) {
VxCan *v = VXCAN(netdev);
netdev_detach_name(netdev, v->ifname_peer);
}
static int netdev_vxcan_set_ifindex(NetDev *netdev, const char *name, int ifindex) {
VxCan *v = VXCAN(netdev);
int r;
assert(name);
assert(ifindex > 0);
if (streq(netdev->ifname, name)) {
r = netdev_set_ifindex_internal(netdev, ifindex);
if (r <= 0)
return r;
} else if (streq(v->ifname_peer, name)) {
if (v->ifindex_peer == ifindex)
return 0; /* already set */
if (v->ifindex_peer > 0 && v->ifindex_peer != ifindex)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EEXIST),
"Could not set ifindex %i for peer %s, already set to %i.",
ifindex, v->ifname_peer, v->ifindex_peer);
v->ifindex_peer = ifindex;
log_netdev_debug(netdev, "Peer interface %s gained index %i.", v->ifname_peer, ifindex);
} else
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"Received netlink message with unexpected interface name %s (ifindex=%i).",
name, ifindex);
if (netdev->ifindex > 0 && v->ifindex_peer > 0)
return netdev_enter_ready(netdev);
return 0;
}
static int netdev_vxcan_get_ifindex(NetDev *netdev, const char *name) {
VxCan *v = VXCAN(netdev);
assert(name);
if (streq(netdev->ifname, name))
return netdev->ifindex;
if (streq(v->ifname_peer, name))
return v->ifindex_peer;
return -ENODEV;
}
static void vxcan_done(NetDev *netdev) {
VxCan *v = VXCAN(netdev);
@@ -54,5 +119,9 @@ const NetDevVTable vxcan_vtable = {
.fill_message_create = netdev_vxcan_fill_message_create,
.create_type = NETDEV_CREATE_INDEPENDENT,
.config_verify = netdev_vxcan_verify,
.attach = netdev_vxcan_attach,
.detach = netdev_vxcan_detach,
.set_ifindex = netdev_vxcan_set_ifindex,
.get_ifindex = netdev_vxcan_get_ifindex,
.iftype = ARPHRD_CAN,
};

View File

@@ -9,6 +9,7 @@ struct VxCan {
NetDev meta;
char *ifname_peer;
int ifindex_peer;
};
DEFINE_NETDEV_CAST(VXCAN, VxCan);

View File

@@ -1307,18 +1307,15 @@ static int link_get_network(Link *link, Network **ret) {
int link_reconfigure_impl(Link *link, bool force) {
Network *network = NULL;
NetDev *netdev = NULL;
int r;
assert(link);
link_assign_netdev(link);
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
return 0;
r = netdev_get(link->manager, link->ifname, &netdev);
if (r < 0 && r != -ENOENT)
return r;
r = link_get_network(link, &network);
if (r < 0 && r != -ENOENT)
return r;
@@ -1383,9 +1380,6 @@ int link_reconfigure_impl(Link *link, bool force) {
link_free_engines(link);
link->network = network_unref(link->network);
netdev_unref(link->netdev);
link->netdev = netdev_ref(netdev);
if (!network) {
link_set_state(link, LINK_STATE_UNMANAGED);
return 0;
@@ -2810,6 +2804,7 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man
r = netdev_set_ifindex(netdev, message);
if (r < 0) {
log_netdev_warning_errno(netdev, r, "Could not process new link message for netdev, ignoring: %m");
netdev_enter_failed(netdev);
return 0;
}
}

View File

@@ -633,7 +633,11 @@ Manager* manager_free(Manager *m) {
m->dhcp_pd_subnet_ids = set_free(m->dhcp_pd_subnet_ids);
m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
/* 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(m->netdevs)); )
netdev_detach(n);
m->netdevs = hashmap_free(m->netdevs);
m->tuntap_fds_by_name = hashmap_free(m->tuntap_fds_by_name);

View File

@@ -1008,19 +1008,15 @@ static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Request
}
static int link_request_wireguard_routes(Link *link, bool only_ipv4) {
NetDev *netdev;
Route *route;
int r;
assert(link);
if (!streq_ptr(link->kind, "wireguard"))
if (!link->netdev || link->netdev->kind != NETDEV_KIND_WIREGUARD)
return 0;
if (netdev_get(link->manager, link->ifname, &netdev) < 0)
return 0;
Wireguard *w = WIREGUARD(netdev);
Wireguard *w = WIREGUARD(link->netdev);
SET_FOREACH(route, w->routes) {
if (only_ipv4 && route->family != AF_INET)

View File

@@ -623,6 +623,12 @@ static int link_save(Link *link) {
"IPV6_ADDRESS_STATE=%s\n",
admin_state, oper_state, carrier_state, address_state, ipv4_address_state, ipv6_address_state);
if (link->netdev) {
r = serialize_config_files(f, "NETDEV", link->netdev->filename, link->netdev->dropins);
if (r < 0)
return r;
}
if (link->network) {
const char *online_state, *captive_portal;
bool space = false;
@@ -650,12 +656,6 @@ static int link_save(Link *link) {
if (r < 0)
return r;
if (link->netdev) {
r = serialize_config_files(f, "NETDEV", link->netdev->filename, link->netdev->dropins);
if (r < 0)
return r;
}
/************************************************************/
fputs("DNS=", f);

View File

@@ -1240,6 +1240,20 @@ class Utilities():
else:
self.fail(f'"{contents}" not found in journal.')
def networkctl_check_unit(self, ifname, netdev_file=None, network_file=None, link_file=None):
output = networkctl_status(ifname)
print(output)
if netdev_file:
self.assertRegex(output, rf'NetDev File: .*/{netdev_file}\.netdev')
else:
self.assertNotIn('NetDev File:', output)
if network_file:
self.assertRegex(output, rf'Network File: .*/{network_file}\.network')
else:
self.assertIn('Network File: n/a', output)
if link_file:
self.assertRegex(output, rf'Link File: .*/{link_file}\.link')
class NetworkctlTests(unittest.TestCase, Utilities):
def setUp(self):
@@ -1551,6 +1565,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('bareudp99:degraded')
self.networkctl_check_unit('bareudp99', '25-bareudp', '26-netdev-link-local-addressing-yes')
output = check_output('ip -d link show bareudp99')
print(output)
@@ -1564,6 +1579,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('batadv99:degraded')
self.networkctl_check_unit('batadv99', '25-batadv', '26-netdev-link-local-addressing-yes')
output = check_output('ip -d link show batadv99')
print(output)
@@ -1574,6 +1590,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('bridge99:no-carrier')
self.networkctl_check_unit('bridge99', '25-bridge', '25-bridge-configure-without-carrier')
tick = os.sysconf('SC_CLK_TCK')
self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
@@ -1607,6 +1624,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('bond99:off', 'bond98:off', 'bond97:off', setup_state='unmanaged')
self.networkctl_check_unit('bond99', '25-bond')
self.networkctl_check_unit('bond98', '25-bond-balanced-tlb')
self.networkctl_check_unit('bond97', '25-bond-property')
self.check_link_attr('bond99', 'bonding', 'mode', '802.3ad 4')
self.check_link_attr('bond99', 'bonding', 'xmit_hash_policy', 'layer3+4 1')
@@ -1646,6 +1666,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('test1:degraded', 'vlan99:routable')
self.networkctl_check_unit('vlan99', '21-vlan', '21-vlan')
self.networkctl_check_unit('test1', '11-dummy', '21-vlan-test1')
output = check_output('ip -d link show test1')
print(output)
@@ -1680,6 +1702,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('bond99:off')
self.wait_operstate('vlan99', operstate='off', setup_state='configuring', setup_timeout=10)
self.networkctl_check_unit('vlan99', '21-vlan-on-bond', '21-vlan-on-bond')
self.networkctl_check_unit('bond99', '21-bond-802.3ad', '21-bond-802.3ad')
self.check_networkd_log('vlan99: Could not bring up interface, ignoring: Network is down')
@@ -1705,6 +1729,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('macvtap99:degraded',
'test1:carrier' if mode == 'passthru' else 'test1:degraded')
self.networkctl_check_unit('macvtap99', '21-macvtap', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('test1', '11-dummy', '25-macvtap')
output = check_output('ip -d link show macvtap99')
print(output)
@@ -1729,6 +1755,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('macvlan99:degraded',
'test1:carrier' if mode == 'passthru' else 'test1:degraded')
self.networkctl_check_unit('macvlan99', '21-macvlan', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('test1', '11-dummy', '25-macvlan')
output = check_output('ip -d link show test1')
print(output)
@@ -1776,6 +1804,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('ipvlan99:degraded', 'test1:degraded')
self.networkctl_check_unit('ipvlan99', '25-ipvlan', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('test1', '11-dummy', '25-ipvlan')
output = check_output('ip -d link show ipvlan99')
print(output)
@@ -1799,6 +1829,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('ipvtap99:degraded', 'test1:degraded')
self.networkctl_check_unit('ipvtap99', '25-ipvtap', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('test1', '11-dummy', '25-ipvtap')
output = check_output('ip -d link show ipvtap99')
print(output)
@@ -1810,6 +1842,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded')
self.networkctl_check_unit('veth99', '25-veth', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('veth-peer', '25-veth', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('veth-mtu', '25-veth-mtu', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('veth-mtu-peer', '25-veth-mtu', '26-netdev-link-local-addressing-yes')
output = check_output('ip -d link show veth99')
print(output)
@@ -1881,12 +1917,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
copy_network_unit('25-tun.netdev', '25-tap.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online('testtun99:degraded', 'testtap99:degraded')
self.networkctl_check_unit('testtap99', '25-tap', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('testtun99', '25-tun', '26-netdev-link-local-addressing-yes')
self.check_tuntap(True)
remove_network_unit('26-netdev-link-local-addressing-yes.network')
restart_networkd()
self.wait_online('testtun99:degraded', 'testtap99:degraded', setup_state='unmanaged')
self.networkctl_check_unit('testtap99', '25-tap')
self.networkctl_check_unit('testtun99', '25-tun')
self.check_tuntap(True)
@@ -1894,6 +1934,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
unmanage_existing_links()
restart_networkd()
self.wait_online('testtun99:off', 'testtap99:off', setup_state='unmanaged')
self.networkctl_check_unit('testtap99')
self.networkctl_check_unit('testtun99')
self.check_tuntap(False)
@@ -1903,6 +1945,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('vrf99:carrier')
self.networkctl_check_unit('vrf99', '25-vrf', '26-netdev-link-local-addressing-yes')
@expectedFailureIfModuleIsNotAvailable('vcan')
def test_vcan(self):
@@ -1913,6 +1956,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('vcan99:carrier', 'vcan98:carrier')
# For can devices, 'carrier' is the default required operational state.
self.wait_online('vcan99', 'vcan98')
self.networkctl_check_unit('vcan99', '25-vcan', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('vcan98', '25-vcan98', '25-vcan98')
# https://github.com/systemd/systemd/issues/30140
output = check_output('ip -d link show vcan99')
@@ -1931,6 +1976,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('vxcan99:carrier', 'vxcan-peer:carrier')
# For can devices, 'carrier' is the default required operational state.
self.wait_online('vxcan99', 'vxcan-peer')
self.networkctl_check_unit('vxcan99', '25-vxcan', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('vxcan-peer', '25-vxcan', '26-netdev-link-local-addressing-yes')
@expectedFailureIfModuleIsNotAvailable('wireguard')
def test_wireguard(self):
@@ -1944,6 +1991,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
start_networkd()
self.wait_online('wg99:routable', 'wg98:routable', 'wg97:carrier')
self.networkctl_check_unit('wg99', '25-wireguard', '25-wireguard')
self.networkctl_check_unit('wg98', '25-wireguard-23-peers', '25-wireguard-23-peers')
self.networkctl_check_unit('wg97', '25-wireguard-no-peer', '25-wireguard-no-peer')
output = check_output('ip -4 address show dev wg99')
print(output)
@@ -2065,6 +2115,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('geneve99:degraded')
self.networkctl_check_unit('geneve99', '25-geneve', '26-netdev-link-local-addressing-yes')
output = check_output('ip -d link show geneve99')
print(output)
@@ -2103,6 +2154,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online('gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded')
self.networkctl_check_unit('gretun99', '25-gre-tunnel', '25-tunnel')
self.networkctl_check_unit('gretun98', '25-gre-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('gretun97', '25-gre-tunnel-remote-any', '25-tunnel-remote-any')
self.networkctl_check_unit('gretun96', '25-gre-tunnel-any-any', '25-tunnel-any-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-gretun')
output = check_output('ip -d link show gretun99')
print(output)
@@ -2164,6 +2220,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online('gretap99:routable', 'gretap98:routable', 'dummy98:degraded')
self.networkctl_check_unit('gretap99', '25-gretap-tunnel', '25-tunnel')
self.networkctl_check_unit('gretap98', '25-gretap-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-gretap')
output = check_output('ip -d link show gretap99')
print(output)
@@ -2188,6 +2247,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online('ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded')
self.networkctl_check_unit('ip6gretap99', '25-ip6gretap-tunnel', '25-tunnel')
self.networkctl_check_unit('ip6gretap98', '25-ip6gretap-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-ip6gretap')
output = check_output('ip -d link show ip6gretap99')
print(output)
@@ -2204,6 +2266,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online('vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded')
self.networkctl_check_unit('vtitun99', '25-vti-tunnel', '25-tunnel')
self.networkctl_check_unit('vtitun98', '25-vti-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('vtitun97', '25-vti-tunnel-remote-any', '25-tunnel-remote-any')
self.networkctl_check_unit('vtitun96', '25-vti-tunnel-any-any', '25-tunnel-any-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-vti')
output = check_output('ip -d link show vtitun99')
print(output)
@@ -2225,6 +2292,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
start_networkd()
self.wait_online('vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded')
self.networkctl_check_unit('vti6tun99', '25-vti6-tunnel', '25-tunnel')
self.networkctl_check_unit('vti6tun98', '25-vti6-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('vti6tun97', '25-vti6-tunnel-remote-any', '25-tunnel-remote-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-vti6')
output = check_output('ip -d link show vti6tun99')
print(output)
@@ -2248,6 +2319,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable',
'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded',
'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded')
self.networkctl_check_unit('ip6tnl99', '25-ip6tnl-tunnel', '25-tunnel')
self.networkctl_check_unit('ip6tnl98', '25-ip6tnl-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('ip6tnl97', '25-ip6tnl-tunnel-remote-any', '25-tunnel-remote-any')
self.networkctl_check_unit('ip6tnl-slaac', '25-ip6tnl-tunnel-local-slaac', '25-ip6tnl-tunnel-local-slaac')
self.networkctl_check_unit('ip6tnl-external', '25-ip6tnl-tunnel-external', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('dummy98', '12-dummy', '25-ip6tnl')
self.networkctl_check_unit('veth99', '25-veth', '25-ip6tnl-slaac')
self.networkctl_check_unit('veth-peer', '25-veth', '25-ipv6-prefix')
output = check_output('ip -d link show ip6tnl99')
print(output)
@@ -2282,6 +2361,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
start_networkd()
self.wait_online('sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded')
self.networkctl_check_unit('sittun99', '25-sit-tunnel', '25-tunnel')
self.networkctl_check_unit('sittun98', '25-sit-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('sittun97', '25-sit-tunnel-remote-any', '25-tunnel-remote-any')
self.networkctl_check_unit('sittun96', '25-sit-tunnel-any-any', '25-tunnel-any-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-sit')
output = check_output('ip -d link show sittun99')
print(output)
@@ -2301,6 +2385,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-isatap-tunnel.netdev', '25-tunnel.network')
start_networkd()
self.wait_online('isataptun99:routable', 'dummy98:degraded')
self.networkctl_check_unit('isataptun99', '25-isatap-tunnel', '25-tunnel')
self.networkctl_check_unit('dummy98', '12-dummy', '25-isatap')
output = check_output('ip -d link show isataptun99')
print(output)
@@ -2311,6 +2397,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-6rd-tunnel.netdev', '25-tunnel.network')
start_networkd()
self.wait_online('sittun99:routable', 'dummy98:degraded')
self.networkctl_check_unit('sittun99', '25-6rd-tunnel', '25-tunnel')
self.networkctl_check_unit('dummy98', '12-dummy', '25-6rd')
output = check_output('ip -d link show sittun99')
print(output)
@@ -2323,6 +2411,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded')
self.networkctl_check_unit('erspan99', '25-erspan0-tunnel', '25-tunnel')
self.networkctl_check_unit('erspan98', '25-erspan0-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan')
output = check_output('ip -d link show erspan99')
print(output)
@@ -2351,6 +2442,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded')
self.networkctl_check_unit('erspan99', '25-erspan1-tunnel', '25-tunnel')
self.networkctl_check_unit('erspan98', '25-erspan1-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan')
output = check_output('ip -d link show erspan99')
print(output)
@@ -2382,6 +2476,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network')
start_networkd()
self.wait_online('erspan99:routable', 'erspan98:routable', 'dummy98:degraded')
self.networkctl_check_unit('erspan99', '25-erspan2-tunnel', '25-tunnel')
self.networkctl_check_unit('erspan98', '25-erspan2-tunnel-local-any', '25-tunnel-local-any')
self.networkctl_check_unit('dummy98', '12-dummy', '25-erspan')
output = check_output('ip -d link show erspan99')
print(output)
@@ -2411,12 +2508,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('ipiptun99:carrier')
self.networkctl_check_unit('ipiptun99', '25-ipip-tunnel-independent', '26-netdev-link-local-addressing-yes')
def test_tunnel_independent_loopback(self):
copy_network_unit('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network')
start_networkd()
self.wait_online('ipiptun99:carrier')
self.networkctl_check_unit('ipiptun99', '25-ipip-tunnel-independent-loopback', '26-netdev-link-local-addressing-yes')
@expectedFailureIfModuleIsNotAvailable('xfrm_interface')
def test_xfrm(self):
@@ -2426,6 +2525,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded')
self.networkctl_check_unit('dummy98', '12-dummy', '25-xfrm')
self.networkctl_check_unit('xfrm98', '25-xfrm', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('xfrm99', '25-xfrm-independent', '26-netdev-link-local-addressing-yes')
output = check_output('ip -d link show dev xfrm98')
print(output)
@@ -2449,6 +2551,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off', setup_state='unmanaged')
self.networkctl_check_unit('ipiptun96', '25-fou-ipip')
self.networkctl_check_unit('sittun96', '25-fou-sit')
self.networkctl_check_unit('gretun96', '25-fou-gre')
self.networkctl_check_unit('gretap96', '25-fou-gretap')
output = check_output('ip fou show')
print(output)
@@ -2479,6 +2585,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.wait_online('test1:degraded', 'veth99:routable', 'veth-peer:degraded',
'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded')
self.networkctl_check_unit('test1', '11-dummy', '25-vxlan-test1')
self.networkctl_check_unit('veth99', '25-veth', '25-vxlan-veth99')
self.networkctl_check_unit('veth-peer', '25-veth', '25-ipv6-prefix')
self.networkctl_check_unit('vxlan99', '25-vxlan', '25-vxlan')
self.networkctl_check_unit('vxlan98', '25-vxlan-independent', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('vxlan97', '25-vxlan-ipv6', '25-vxlan-ipv6')
self.networkctl_check_unit('vxlan-slaac', '25-vxlan-local-slaac', '25-vxlan-local-slaac')
output = check_output('ip -d -d link show vxlan99')
print(output)
@@ -2530,6 +2643,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:degraded', 'macsec99:routable')
self.networkctl_check_unit('dummy98', '12-dummy', '26-macsec')
self.networkctl_check_unit('macsec99', '25-macsec', '25-macsec')
output = check_output('ip -d link show macsec99')
print(output)
@@ -2557,6 +2672,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('nlmon99:carrier')
self.networkctl_check_unit('nlmon99', '25-nlmon', '26-netdev-link-local-addressing-yes')
@expectedFailureIfModuleIsNotAvailable('ifb')
def test_ifb(self):
@@ -2564,6 +2680,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('ifb99:degraded')
self.networkctl_check_unit('ifb99', '25-ifb', '26-netdev-link-local-addressing-yes')
@unittest.skipUnless(os.cpu_count() >= 2, reason="CPU count should be >= 2 to pass this test")
def test_rps_cpu_1(self):
@@ -2571,6 +2688,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:carrier')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-1')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
@@ -2582,6 +2700,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:carrier')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-1')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
@@ -2593,6 +2712,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:carrier')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-multi')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
@@ -2605,10 +2725,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('dummy98:carrier')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy')
# 0
copy_network_unit('25-rps-cpu-0.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(int(output.replace(',', ''), base=16), 1)
@@ -2617,6 +2739,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# all
copy_network_unit('25-rps-cpu-all.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-all')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}')
@@ -2625,6 +2748,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# disable
copy_network_unit('24-rps-cpu-disable.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-disable')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(int(output.replace(',', ''), base=16), 0)
@@ -2633,6 +2757,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# set all again
copy_network_unit('25-rps-cpu-all.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-all')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}')
@@ -2641,6 +2766,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# empty -> unchanged
copy_network_unit('24-rps-cpu-empty.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-empty')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}')
@@ -2649,6 +2775,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# 0, then empty -> unchanged
copy_network_unit('25-rps-cpu-0-empty.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-empty')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(f"{int(output.replace(',', ''), base=16):x}", f'{(1 << cpu_count) - 1:x}')
@@ -2657,6 +2784,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# 0, then invalid -> 0
copy_network_unit('25-rps-cpu-0-invalid.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '25-rps-cpu-0-invalid')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(int(output.replace(',', ''), base=16), 1)
@@ -2665,6 +2793,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
# invalid -> unchanged
copy_network_unit('24-rps-cpu-invalid.link')
udevadm_trigger('/sys/class/net/dummy98')
self.networkctl_check_unit('dummy98', '12-dummy', '12-dummy', '24-rps-cpu-invalid')
output = check_output('cat /sys/class/net/dummy98/queues/rx-0/rps_cpus')
print(output)
self.assertEqual(int(output.replace(',', ''), base=16), 1)
@@ -2685,6 +2814,9 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded')
self.networkctl_check_unit('test1', '11-dummy', '25-l2tp-dummy')
self.networkctl_check_unit('l2tp-ses1', '25-l2tp-udp', '25-l2tp')
self.networkctl_check_unit('l2tp-ses2', '25-l2tp-udp', '25-l2tp')
output = check_output('ip l2tp show tunnel tunnel_id 10')
print(output)
@@ -2713,6 +2845,9 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
start_networkd()
self.wait_online('test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded')
self.networkctl_check_unit('test1', '11-dummy', '25-l2tp-dummy')
self.networkctl_check_unit('l2tp-ses3', '25-l2tp-ip', '25-l2tp')
self.networkctl_check_unit('l2tp-ses4', '25-l2tp-ip', '25-l2tp')
output = check_output('ip l2tp show tunnel tunnel_id 10')
print(output)