Merge branch NetworkManager:main into kk-l10n-add

This commit is contained in:
Baurzhan Muftakhidinov 2026-02-24 17:03:24 +00:00
commit b01a611efd
59 changed files with 1999 additions and 42 deletions

1
NEWS
View file

@ -47,6 +47,7 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
* WIFI connections using wpa-psk respect the setting connection.auth-retry
and only prompt for new secrets during the last authentication attempt before
failing.
* Add support for GENEVE interface.
=============================================
NetworkManager-1.56

View file

@ -183,6 +183,7 @@
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Bridge.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Dummy.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Generic.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Geneve.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Hsr.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml"/>
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml"/>

View file

@ -317,6 +317,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-setting-dummy.xml"/>
<xi:include href="xml/nm-setting-ethtool.xml"/>
<xi:include href="xml/nm-setting-generic.xml"/>
<xi:include href="xml/nm-setting-geneve.xml"/>
<xi:include href="xml/nm-setting-gsm.xml"/>
<xi:include href="xml/nm-setting-hostname.xml"/>
<xi:include href="xml/nm-setting-hsr.xml"/>
@ -377,6 +378,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-device-dummy.xml"/>
<xi:include href="xml/nm-device-ethernet.xml"/>
<xi:include href="xml/nm-device-generic.xml"/>
<xi:include href="xml/nm-device-geneve.xml"/>
<xi:include href="xml/nm-device-hsr.xml"/>
<xi:include href="xml/nm-device-infiniband.xml"/>
<xi:include href="xml/nm-device-ip-tunnel.xml"/>

View file

@ -15,6 +15,7 @@ ifaces = [
'org.freedesktop.NetworkManager.Device.Bridge',
'org.freedesktop.NetworkManager.Device.Dummy',
'org.freedesktop.NetworkManager.Device.Generic',
'org.freedesktop.NetworkManager.Device.Geneve',
'org.freedesktop.NetworkManager.Device.Hsr',
'org.freedesktop.NetworkManager.Device.IPTunnel',
'org.freedesktop.NetworkManager.Device.Infiniband',

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.Device.Geneve:
@short_description: GENEVE Device.
-->
<interface name="org.freedesktop.NetworkManager.Device.Geneve">
<!--
Id:
@since: 1.58
The GENEVE Virtual Network Identifier (VNI).
-->
<property name="Id" type="u" access="read"/>
<!--
Remote:
@since: 1.58
The IP (v4 or v6) address of the remote endpoint to which GENEVE packets
are sent.
-->
<property name="Remote" type="s" access="read"/>
<!--
Tos:
@since: 1.58
The value to use in the IP ToS field for GENEVE packets sent to the remote
endpoint.
-->
<property name="Tos" type="y" access="read"/>
<!--
Ttl:
@since: 1.58
The value to use in the IP TTL field for GENEVE packets sent to the remote
endpoint.
-->
<property name="Ttl" type="i" access="read"/>
<!--
Df:
@since: 1.58
The Don't Fragment (DF) flag setting for GENEVE packets. 0 means unset,
1 means set, 2 means inherit from the underlying interface.
-->
<property name="Df" type="y" access="read"/>
<!--
DstPort:
@since: 1.58
Destination port for outgoing GENEVE packets.
-->
<property name="DstPort" type="q" access="read"/>
</interface>
</node>

View file

@ -62,7 +62,7 @@
<!--
GetSecrets:
@setting_name: Name of the setting to return secrets for. If empty, all secrets will be returned.
@setting_name: Name of the setting to return secrets for (mandatory).
@secrets: Nested settings maps containing secrets.
Get the secrets belonging to this network configuration. Only secrets from

View file

@ -1852,9 +1852,9 @@
connections with an option of restoring the network configuration to a
known good state in case of an error.</para>
<para>If the a list of interface names is specified, the checkpoint is
taken, the checkpoint is takes only on the specified devices. Otherwise
a checkpoint is taken for all devices.</para>
<para>If a list of interface names is specified, the checkpoint is
taken only on the specified devices. Otherwise a checkpoint is taken for
all devices.</para>
<para>Currently the timeout defaults to 15 seconds. This may change in
a future version.</para>

View file

@ -5,7 +5,7 @@ project(
# NOTE: When incrementing version also add corresponding
# NM_VERSION_x_y_z macros in
# "src/libnm-core-public/nm-version-macros.h.in"
version: '1.57.2-dev',
version: '1.57.3-dev',
license: 'GPL2+',
default_options: [
'buildtype=debugoptimized',

View file

@ -11,6 +11,7 @@ src/core/devices/nm-device-bridge.c
src/core/devices/nm-device-dummy.c
src/core/devices/nm-device-ethernet-utils.c
src/core/devices/nm-device-ethernet.c
src/core/devices/nm-device-geneve.c
src/core/devices/nm-device-infiniband.c
src/core/devices/nm-device-ip-tunnel.c
src/core/devices/nm-device-loopback.c
@ -46,6 +47,7 @@ src/libnm-client-impl/nm-device-bt.c
src/libnm-client-impl/nm-device-dummy.c
src/libnm-client-impl/nm-device-ethernet.c
src/libnm-client-impl/nm-device-generic.c
src/libnm-client-impl/nm-device-geneve.c
src/libnm-client-impl/nm-device-hsr.c
src/libnm-client-impl/nm-device-infiniband.c
src/libnm-client-impl/nm-device-ip-tunnel.c
@ -90,6 +92,7 @@ src/libnm-core-impl/nm-setting-connection.c
src/libnm-core-impl/nm-setting-dcb.c
src/libnm-core-impl/nm-setting-ethtool.c
src/libnm-core-impl/nm-setting-generic.c
src/libnm-core-impl/nm-setting-geneve.c
src/libnm-core-impl/nm-setting-gsm.c
src/libnm-core-impl/nm-setting-hsr.c
src/libnm-core-impl/nm-setting-infiniband.c

View file

@ -412,6 +412,7 @@ nm_device_factory_manager_load_factories(NMDeviceFactoryManagerFactoryFunc callb
_ADD_INTERNAL(nm_dummy_device_factory_get_type);
_ADD_INTERNAL(nm_ethernet_device_factory_get_type);
_ADD_INTERNAL(nm_generic_device_factory_get_type);
_ADD_INTERNAL(nm_geneve_device_factory_get_type);
_ADD_INTERNAL(nm_hsr_device_factory_get_type);
_ADD_INTERNAL(nm_infiniband_device_factory_get_type);
_ADD_INTERNAL(nm_ip_tunnel_device_factory_get_type);

View file

@ -0,0 +1,487 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2026 Red Hat, Inc.
*/
#include "src/core/nm-default-daemon.h"
#include "nm-manager.h"
#include "nm-device-geneve.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-act-request.h"
#include "nm-device-private.h"
#include "nm-setting-geneve.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#define _NMLOG_DEVICE_TYPE NMDeviceGeneve
#include "nm-device-logging.h"
NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceGeneve,
PROP_ID,
PROP_REMOTE,
PROP_TOS,
PROP_TTL,
PROP_DF,
PROP_DST_PORT, );
typedef struct {
NMPlatformLnkGeneve props;
} NMDeviceGenevePrivate;
struct _NMDeviceGeneve {
NMDevice parent;
NMDeviceGenevePrivate _priv;
};
struct _NMDeviceGeneveClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE(NMDeviceGeneve, nm_device_geneve, NM_TYPE_DEVICE)
#define NM_DEVICE_GENEVE_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMDeviceGeneve, NM_IS_DEVICE_GENEVE, NMDevice)
/*****************************************************************************/
static NMDeviceCapabilities
get_generic_capabilities(NMDevice *dev)
{
return NM_DEVICE_CAP_IS_SOFTWARE;
}
static void
update_properties(NMDevice *device)
{
NMDeviceGeneve *self;
NMDeviceGenevePrivate *priv;
const NMPlatformLink *plink;
const NMPlatformLnkGeneve *props;
int ifindex;
g_return_if_fail(NM_IS_DEVICE_GENEVE(device));
self = NM_DEVICE_GENEVE(device);
priv = NM_DEVICE_GENEVE_GET_PRIVATE(self);
ifindex = nm_device_get_ifindex(device);
g_return_if_fail(ifindex > 0);
props = nm_platform_link_get_lnk_geneve(nm_device_get_platform(device), ifindex, &plink);
if (!props) {
_LOGW(LOGD_PLATFORM, "could not get GENEVE properties");
return;
}
g_object_freeze_notify((GObject *) device);
#define CHECK_PROPERTY_CHANGED(field, prop) \
G_STMT_START \
{ \
if (priv->props.field != props->field) { \
priv->props.field = props->field; \
_notify(self, prop); \
} \
} \
G_STMT_END
#define CHECK_PROPERTY_CHANGED_IN6ADDR(field, prop) \
G_STMT_START \
{ \
if (memcmp(&priv->props.field, &props->field, sizeof(props->field)) != 0) { \
priv->props.field = props->field; \
_notify(self, prop); \
} \
} \
G_STMT_END
CHECK_PROPERTY_CHANGED(id, PROP_ID);
CHECK_PROPERTY_CHANGED(remote, PROP_REMOTE);
CHECK_PROPERTY_CHANGED_IN6ADDR(remote6, PROP_REMOTE);
CHECK_PROPERTY_CHANGED(tos, PROP_TOS);
CHECK_PROPERTY_CHANGED(ttl, PROP_TTL);
CHECK_PROPERTY_CHANGED(df, PROP_DF);
CHECK_PROPERTY_CHANGED(dst_port, PROP_DST_PORT);
g_object_thaw_notify((GObject *) device);
}
static void
link_changed(NMDevice *device, const NMPlatformLink *pllink)
{
NM_DEVICE_CLASS(nm_device_geneve_parent_class)->link_changed(device, pllink);
update_properties(device);
}
static void
unrealize_notify(NMDevice *device)
{
NMDeviceGeneve *self = NM_DEVICE_GENEVE(device);
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(self);
guint i;
NM_DEVICE_CLASS(nm_device_geneve_parent_class)->unrealize_notify(device);
memset(&priv->props, 0, sizeof(NMPlatformLnkGeneve));
for (i = 1; i < _PROPERTY_ENUMS_LAST; i++)
g_object_notify_by_pspec(G_OBJECT(self), obj_properties[i]);
}
static gboolean
create_and_realize(NMDevice *device,
NMConnection *connection,
NMDevice *parent,
const NMPlatformLink **out_plink,
GError **error)
{
const char *iface = nm_device_get_iface(device);
NMPlatformLnkGeneve props = {};
NMSettingGeneve *s_geneve;
const char *str;
int r;
s_geneve = nm_connection_get_setting_geneve(connection);
g_return_val_if_fail(s_geneve, FALSE);
props.id = nm_setting_geneve_get_id(s_geneve);
str = nm_setting_geneve_get_remote(s_geneve);
if (!nm_inet_parse_bin(AF_INET, str, NULL, &props.remote)
&& !nm_inet_parse_bin(AF_INET6, str, NULL, &props.remote6)) {
return nm_assert_unreachable_val(FALSE);
}
props.tos = nm_setting_geneve_get_tos(s_geneve);
props.ttl = nm_setting_geneve_get_ttl(s_geneve);
props.df = nm_setting_geneve_get_df(s_geneve);
props.dst_port = nm_setting_geneve_get_destination_port(s_geneve);
r = nm_platform_link_geneve_add(nm_device_get_platform(device), iface, &props, out_plink);
if (r < 0) {
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create geneve interface '%s' for '%s': %s",
iface,
nm_connection_get_id(connection),
nm_strerror(r));
return FALSE;
}
return TRUE;
}
static gboolean
address_matches(const char *candidate, in_addr_t addr4, struct in6_addr *addr6)
{
NMIPAddr candidate_addr;
int addr_family;
if (!candidate)
return addr4 == 0u && IN6_IS_ADDR_UNSPECIFIED(addr6);
if (!nm_inet_parse_bin(AF_UNSPEC, candidate, &addr_family, &candidate_addr))
return FALSE;
if (!nm_ip_addr_equal(addr_family,
&candidate_addr,
NM_IS_IPv4(addr_family) ? (gpointer) &addr4 : addr6))
return FALSE;
if (NM_IS_IPv4(addr_family))
return IN6_IS_ADDR_UNSPECIFIED(addr6);
else
return addr4 == 0u;
}
static gboolean
check_connection_compatible(NMDevice *device,
NMConnection *connection,
gboolean check_properties,
GError **error)
{
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(device);
NMSettingGeneve *s_geneve;
if (!NM_DEVICE_CLASS(nm_device_geneve_parent_class)
->check_connection_compatible(device, connection, check_properties, error))
return FALSE;
if (check_properties && nm_device_is_real(device)) {
s_geneve = nm_connection_get_setting_geneve(connection);
if (priv->props.id != nm_setting_geneve_get_id(s_geneve)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve id mismatches");
return FALSE;
}
if (!address_matches(nm_setting_geneve_get_remote(s_geneve),
priv->props.remote,
&priv->props.remote6)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve remote address mismatches");
return FALSE;
}
if (priv->props.dst_port != nm_setting_geneve_get_destination_port(s_geneve)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve destination port mismatches");
return FALSE;
}
if (priv->props.tos != nm_setting_geneve_get_tos(s_geneve)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve TOS mismatches");
return FALSE;
}
if (priv->props.ttl != nm_setting_geneve_get_ttl(s_geneve)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve TTL mismatches");
return FALSE;
}
if (priv->props.df != nm_setting_geneve_get_df(s_geneve)) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
"geneve DF mismatches");
return FALSE;
}
}
return TRUE;
}
static gboolean
complete_connection(NMDevice *device,
NMConnection *connection,
const char *specific_object,
NMConnection *const *existing_connections,
GError **error)
{
NMSettingGeneve *s_geneve;
nm_utils_complete_generic(nm_device_get_platform(device),
connection,
NM_SETTING_GENEVE_SETTING_NAME,
existing_connections,
NULL,
_("Geneve connection"),
NULL,
NULL);
s_geneve = nm_connection_get_setting_geneve(connection);
if (!s_geneve) {
g_set_error_literal(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_CONNECTION,
"A 'geneve' setting is required.");
return FALSE;
}
return TRUE;
}
static void
update_connection(NMDevice *device, NMConnection *connection)
{
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(device);
NMSettingGeneve *s_geneve = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_GENEVE);
char sbuf[NM_INET_ADDRSTRLEN];
if (priv->props.id != nm_setting_geneve_get_id(s_geneve))
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_ID, priv->props.id, NULL);
/* Handle remote (IPv4 or IPv6) */
if (priv->props.remote) {
g_object_set(s_geneve,
NM_SETTING_GENEVE_REMOTE,
nm_inet4_ntop(priv->props.remote, sbuf),
NULL);
} else if (memcmp(&priv->props.remote6, &in6addr_any, sizeof(in6addr_any))) {
g_object_set(s_geneve,
NM_SETTING_GENEVE_REMOTE,
nm_inet6_ntop(&priv->props.remote6, sbuf),
NULL);
}
if (priv->props.dst_port != nm_setting_geneve_get_destination_port(s_geneve))
g_object_set(G_OBJECT(s_geneve),
NM_SETTING_GENEVE_DESTINATION_PORT,
priv->props.dst_port,
NULL);
if (priv->props.tos != nm_setting_geneve_get_tos(s_geneve))
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_TOS, priv->props.tos, NULL);
if (priv->props.ttl != nm_setting_geneve_get_ttl(s_geneve))
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_TTL, priv->props.ttl, NULL);
if (priv->props.df != nm_setting_geneve_get_df(s_geneve))
g_object_set(G_OBJECT(s_geneve), NM_SETTING_GENEVE_DF, priv->props.df, NULL);
}
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(object);
switch (prop_id) {
case PROP_ID:
g_value_set_uint(value, priv->props.id);
break;
case PROP_REMOTE:
if (priv->props.remote)
g_value_take_string(value, nm_inet4_ntop_dup(priv->props.remote));
else if (!IN6_IS_ADDR_UNSPECIFIED(&priv->props.remote6))
g_value_take_string(value, nm_inet6_ntop_dup(&priv->props.remote6));
break;
case PROP_TOS:
g_value_set_uchar(value, priv->props.tos);
break;
case PROP_TTL:
g_value_set_uchar(value, priv->props.ttl);
break;
case PROP_DF:
g_value_set_uint(value, priv->props.df);
break;
case PROP_DST_PORT:
g_value_set_uint(value, priv->props.dst_port);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_device_geneve_init(NMDeviceGeneve *self)
{}
static const NMDBusInterfaceInfoExtended interface_info_device_geneve = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
NM_DBUS_INTERFACE_DEVICE_GENEVE,
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Id", "u", NM_DEVICE_GENEVE_ID),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Remote", "s", NM_DEVICE_GENEVE_REMOTE),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Tos", "y", NM_DEVICE_GENEVE_TOS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Ttl", "y", NM_DEVICE_GENEVE_TTL),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Df", "u", NM_DEVICE_GENEVE_DF),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DstPort",
"q",
NM_DEVICE_GENEVE_DST_PORT), ), ),
};
static void
nm_device_geneve_class_init(NMDeviceGeneveClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS(klass);
object_class->get_property = get_property;
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_geneve);
device_class->connection_type_supported = NM_SETTING_GENEVE_SETTING_NAME;
device_class->connection_type_check_compatible = NM_SETTING_GENEVE_SETTING_NAME;
device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_GENEVE);
device_class->link_changed = link_changed;
device_class->unrealize_notify = unrealize_notify;
device_class->create_and_realize = create_and_realize;
device_class->check_connection_compatible = check_connection_compatible;
device_class->complete_connection = complete_connection;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->update_connection = update_connection;
obj_properties[PROP_ID] = g_param_spec_uint(NM_DEVICE_GENEVE_ID,
"",
"",
0,
G_MAXUINT32,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_REMOTE] = g_param_spec_string(NM_DEVICE_GENEVE_REMOTE,
"",
"",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_TOS] = g_param_spec_uchar(NM_DEVICE_GENEVE_TOS,
"",
"",
0,
255,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_TTL] = g_param_spec_uchar(NM_DEVICE_GENEVE_TTL,
"",
"",
0,
255,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_DF] = g_param_spec_uint(NM_DEVICE_GENEVE_DF,
"",
"",
0,
2,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_DST_PORT] = g_param_spec_uint(NM_DEVICE_GENEVE_DST_PORT,
"",
"",
0,
65535,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}
/*****************************************************************************/
#define NM_TYPE_GENEVE_DEVICE_FACTORY (nm_geneve_device_factory_get_type())
#define NM_GENEVE_DEVICE_FACTORY(obj) \
(_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_GENEVE_DEVICE_FACTORY, NMGeneveDeviceFactory))
static NMDevice *
create_device(NMDeviceFactory *factory,
const char *iface,
const NMPlatformLink *plink,
NMConnection *connection,
gboolean *out_ignore)
{
return g_object_new(NM_TYPE_DEVICE_GENEVE,
NM_DEVICE_IFACE,
iface,
NM_DEVICE_TYPE_DESC,
"Geneve",
NM_DEVICE_DEVICE_TYPE,
NM_DEVICE_TYPE_GENEVE,
NM_DEVICE_LINK_TYPE,
NM_LINK_TYPE_GENEVE,
NULL);
}
NM_DEVICE_FACTORY_DEFINE_INTERNAL(
GENEVE,
Geneve,
geneve,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_GENEVE)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_GENEVE_SETTING_NAME),
factory_class->create_device = create_device;);

View file

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2026 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_DEVICE_GENEVE_H__
#define __NETWORKMANAGER_DEVICE_GENEVE_H__
#include "nm-device.h"
#define NM_TYPE_DEVICE_GENEVE (nm_device_geneve_get_type())
#define NM_DEVICE_GENEVE(obj) \
(_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneve))
#define NM_DEVICE_GENEVE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
#define NM_IS_DEVICE_GENEVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_GENEVE))
#define NM_IS_DEVICE_GENEVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_GENEVE))
#define NM_DEVICE_GENEVE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
#define NM_DEVICE_GENEVE_ID "id"
#define NM_DEVICE_GENEVE_REMOTE "remote"
#define NM_DEVICE_GENEVE_TOS "tos"
#define NM_DEVICE_GENEVE_TTL "ttl"
#define NM_DEVICE_GENEVE_DF "df"
#define NM_DEVICE_GENEVE_DST_PORT "dst-port"
typedef struct _NMDeviceGeneve NMDeviceGeneve;
typedef struct _NMDeviceGeneveClass NMDeviceGeneveClass;
GType nm_device_geneve_get_type(void);
#endif /* __NETWORKMANAGER_DEVICE_GENEVE_H__ */

View file

@ -5962,7 +5962,6 @@ nm_device_get_route_metric_default(NMDeviceType device_type)
* in some aspects a VPN. */
case NM_DEVICE_TYPE_WIREGUARD:
return NM_VPN_ROUTE_METRIC_DEFAULT;
case NM_DEVICE_TYPE_ETHERNET:
case NM_DEVICE_TYPE_VETH:
return 100;
@ -5996,6 +5995,8 @@ nm_device_get_route_metric_default(NMDeviceType device_type)
return 470;
case NM_DEVICE_TYPE_VXLAN:
return 500;
case NM_DEVICE_TYPE_GENEVE:
return 525;
case NM_DEVICE_TYPE_DUMMY:
return 550;
case NM_DEVICE_TYPE_WIFI:
@ -19567,7 +19568,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
nm_assert(priv->type == NM_DEVICE_TYPE_UNKNOWN);
priv->type = g_value_get_uint(value);
nm_assert(priv->type > NM_DEVICE_TYPE_UNKNOWN);
nm_assert(priv->type <= NM_DEVICE_TYPE_IPVLAN);
nm_assert(priv->type <= NM_DEVICE_TYPE_GENEVE);
break;
case PROP_LINK_TYPE:
/* construct-only */

View file

@ -111,6 +111,7 @@ libNetworkManager = static_library(
'devices/nm-device-ethernet-utils.c',
'devices/nm-device-factory.c',
'devices/nm-device-generic.c',
'devices/nm-device-geneve.c',
'devices/nm-device-hsr.c',
'devices/nm-device-infiniband.c',
'devices/nm-device-ip-tunnel.c',

View file

@ -56,7 +56,7 @@ G_DEFINE_ABSTRACT_TYPE(NMIPConfig, nm_ip_config, NM_TYPE_DBUS_OBJECT)
/*****************************************************************************/
static void _handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init);
static void _handle_platform_change(NMIPConfig *self, guint64 obj_type_flags, gboolean is_init);
static void _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd);
/*****************************************************************************/
@ -77,7 +77,7 @@ static void
_notify_platform_handle(NMIPConfig *self, gint64 now_msec)
{
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
guint32 obj_type_flags;
guint64 obj_type_flags;
nm_clear_g_source_inst(&priv->notify_platform_timeout_source);
@ -98,7 +98,7 @@ _notify_platform_cb(gpointer user_data)
}
static void
_notify_platform(NMIPConfig *self, guint32 obj_type_flags)
_notify_platform(NMIPConfig *self, guint64 obj_type_flags)
{
const int addr_family = nm_ip_config_get_addr_family(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
@ -953,7 +953,7 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
}
static void
_handle_platform_change(NMIPConfig *self, guint32 obj_type_flags, gboolean is_init)
_handle_platform_change(NMIPConfig *self, guint64 obj_type_flags, gboolean is_init)
{
const int addr_family = nm_ip_config_get_addr_family(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);

View file

@ -35,7 +35,7 @@ struct _NMIPConfigPrivate {
GSource *notify_platform_timeout_source;
gint64 notify_platform_rlimited_until_msec;
gulong l3cfg_notify_id;
guint32 notify_platform_obj_type_flags;
guint64 notify_platform_obj_type_flags;
};
struct _NMIPConfig {

View file

@ -657,7 +657,7 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data,
case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
nm_strbuf_append(&s,
&l,
", obj-type-flags=0x%x",
", obj-type-flags=0x%" G_GINT64_MODIFIER "x",
notify_data->platform_change_on_idle.obj_type_flags);
break;
case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT:
@ -1604,7 +1604,7 @@ _load_link(NML3Cfg *self, gboolean initial)
/*****************************************************************************/
void
_nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags)
_nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint64 obj_type_flags)
{
NML3ConfigNotifyData notify_data;

View file

@ -178,7 +178,7 @@ typedef struct {
} platform_change;
struct {
guint32 obj_type_flags;
guint64 obj_type_flags;
} platform_change_on_idle;
struct {
@ -207,7 +207,7 @@ struct _NML3Cfg {
* NML3Cfg instance. We track some per-l3cfg-data that is only
* relevant to NMNetns here. */
struct {
guint32 signal_pending_obj_type_flags;
guint64 signal_pending_obj_type_flags;
CList signal_pending_lst;
CList ecmp_track_ifindex_lst_head;
} internal_netns;
@ -223,7 +223,7 @@ NML3Cfg *nm_l3cfg_new(NMNetns *netns, int ifindex);
gboolean nm_l3cfg_is_ready(NML3Cfg *self);
void _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags);
void _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint64 obj_type_flags);
void _nm_l3cfg_notify_platform_change(NML3Cfg *self,
NMPlatformSignalChangeType change_type,

View file

@ -1230,7 +1230,7 @@ out:
}
gboolean
nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert)
nmtstp_check_platform_full(NMPlatform *platform, guint64 obj_type_flags, gboolean do_assert)
{
static const NMPObjectType obj_types[] = {
NMP_OBJECT_TYPE_IP4_ADDRESS,
@ -1265,7 +1265,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea
for (i_obj_types = 0; i_obj_types < (int) G_N_ELEMENTS(obj_types); i_obj_types++) {
const NMPObjectType obj_type = obj_types[i_obj_types];
const guint32 i_obj_type_flags = nmp_object_type_to_flags(obj_type);
const guint64 i_obj_type_flags = nmp_object_type_to_flags(obj_type);
gs_unref_ptrarray GPtrArray *arr1 = NULL;
gs_unref_ptrarray GPtrArray *arr2 = NULL;
NMPLookup lookup;
@ -1408,7 +1408,7 @@ nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolea
}
void
nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags)
nmtstp_check_platform(NMPlatform *platform, guint64 obj_type_flags)
{
if (!nmtstp_check_platform_full(platform, obj_type_flags, FALSE)) {
/* It's unclear why this failure sometimes happens. It happens
@ -2393,6 +2393,61 @@ nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *na
return pllink;
}
const NMPlatformLink *
nmtstp_link_geneve_add(NMPlatform *platform,
int external_command,
const char *name,
const NMPlatformLnkGeneve *lnk)
{
const NMPlatformLink *pllink = NULL;
int success;
g_assert(nm_utils_ifname_valid_kernel(name, NULL));
g_assert(lnk->remote || !IN6_IS_ADDR_UNSPECIFIED(&lnk->remote6));
external_command = nmtstp_run_command_check_external(external_command);
_init_platform(&platform, external_command);
if (external_command) {
char remote[NM_INET_ADDRSTRLEN];
char remote6[NM_INET_ADDRSTRLEN];
char str_ttl[30];
if (lnk->remote)
nm_inet4_ntop(lnk->remote, remote);
else
remote[0] = '\0';
if (memcmp(&lnk->remote6, &in6addr_any, sizeof(in6addr_any)))
nm_inet6_ntop(&lnk->remote6, remote6);
else
remote6[0] = '\0';
success = !nmtstp_run_command(
"ip link add %s type geneve id %u remote %s %s tos %02x dstport %u%s",
name,
lnk->id,
remote[0] ? remote : remote6,
lnk->ttl > 0 ? nm_sprintf_buf(str_ttl, "ttl %u", lnk->ttl & 0xff)
: lnk->ttl == 0 ? "ttl auto"
: "ttl inherit",
lnk->tos,
lnk->dst_port,
lnk->df == 1 ? " df set "
: lnk->df == 2 ? " df inherit "
: "");
if (success)
pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_GENEVE, 100);
} else
success = NMTST_NM_ERR_SUCCESS(nm_platform_link_geneve_add(platform, name, lnk, &pllink));
_assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_GENEVE);
return pllink;
}
const NMPlatformLink *
nmtstp_link_gre_add(NMPlatform *platform,
int external_command,
@ -3024,8 +3079,6 @@ nmtstp_link_vxlan_add(NMPlatform *platform,
return pllink;
}
/*****************************************************************************/
const NMPlatformLink *
nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type)
{

View file

@ -140,9 +140,9 @@ int nmtstp_run_command(const char *format, ...) _nm_printf(1, 2);
/*****************************************************************************/
gboolean
nmtstp_check_platform_full(NMPlatform *platform, guint32 obj_type_flags, gboolean do_assert);
nmtstp_check_platform_full(NMPlatform *platform, guint64 obj_type_flags, gboolean do_assert);
void nmtstp_check_platform(NMPlatform *platform, guint32 obj_type_flags);
void nmtstp_check_platform(NMPlatform *platform, guint64 obj_type_flags);
/*****************************************************************************/
@ -474,6 +474,10 @@ const NMPlatformLink *nmtstp_link_veth_add(NMPlatform *platform,
const char *peer);
const NMPlatformLink *
nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *name);
const NMPlatformLink *nmtstp_link_geneve_add(NMPlatform *platform,
int external_command,
const char *name,
const NMPlatformLnkGeneve *lnk);
const NMPlatformLink *nmtstp_link_gre_add(NMPlatform *platform,
int external_command,
const char *name,

View file

@ -1388,10 +1388,11 @@ test_software_detect(gconstpointer user_data)
const gboolean ext = test_data->external_command;
NMPlatformLnkBridge lnk_bridge = {};
NMPlatformLnkTun lnk_tun;
NMPlatformLnkGre lnk_gre = {};
NMPlatformLnkVti lnk_vti = {};
NMPlatformLnkVti6 lnk_vti6 = {};
nm_auto_close int tun_fd = -1;
NMPlatformLnkGeneve lnk_geneve = {};
NMPlatformLnkGre lnk_gre = {};
NMPlatformLnkVti lnk_vti = {};
NMPlatformLnkVti6 lnk_vti6 = {};
nm_auto_close int tun_fd = -1;
gboolean module_loaded;
nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
@ -1434,6 +1435,31 @@ test_software_detect(gconstpointer user_data)
g_error("Failed adding Bridge interface");
break;
case NM_LINK_TYPE_GENEVE:
{
switch (test_data->test_mode) {
case 0:
lnk_geneve.id = 42;
lnk_geneve.remote = nmtst_inet4_from_string("192.168.1.100");
lnk_geneve.ttl = 64;
lnk_geneve.tos = 0;
lnk_geneve.dst_port = 6081;
lnk_geneve.df = 0;
break;
case 1:
lnk_geneve.id = 12345;
lnk_geneve.remote6 = nmtst_inet6_from_string("2001:db8::1");
lnk_geneve.ttl = 128;
lnk_geneve.tos = 16;
lnk_geneve.dst_port = 6082;
lnk_geneve.df = 1;
break;
}
g_assert(nmtstp_link_geneve_add(NULL, ext, DEVICE_NAME, &lnk_geneve));
break;
}
case NM_LINK_TYPE_GRE:
module_loaded = nmtstp_ensure_module("ip_gre");
@ -2208,6 +2234,34 @@ test_software_detect(gconstpointer user_data)
}
break;
}
case NM_LINK_TYPE_GENEVE:
{
const NMPlatformLnkGeneve *plnk = &lnk->lnk_geneve;
g_assert(plnk == nm_platform_link_get_lnk_geneve(NM_PLATFORM_GET, ifindex, NULL));
switch (test_data->test_mode) {
case 0:
g_assert_cmpint(plnk->id, ==, 42);
nmtst_assert_ip4_address(plnk->remote, "192.168.1.100");
nmtst_assert_ip6_address(&plnk->remote6, "::");
g_assert_cmpint(plnk->ttl, ==, 64);
g_assert_cmpint(plnk->tos, ==, 0);
g_assert_cmpint(plnk->dst_port, ==, 6081);
g_assert_cmpint(plnk->df, ==, 0);
break;
case 1:
g_assert_cmpint(plnk->id, ==, 12345);
nmtst_assert_ip4_address(plnk->remote, "0.0.0.0");
nmtst_assert_ip6_address(&plnk->remote6, "2001:db8::1");
g_assert_cmpint(plnk->ttl, ==, 128);
g_assert_cmpint(plnk->tos, ==, 16);
g_assert_cmpint(plnk->dst_port, ==, 6082);
g_assert_cmpint(plnk->df, ==, 1);
break;
}
break;
}
case NM_LINK_TYPE_WIREGUARD:
{
const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard;
@ -4143,6 +4197,8 @@ _nmtstp_setup_tests(void)
g_test_add_func("/link/external", test_external);
test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0);
test_software_detect_add("/link/software/detect/geneve/0", NM_LINK_TYPE_GENEVE, 0);
test_software_detect_add("/link/software/detect/geneve/1", NM_LINK_TYPE_GENEVE, 1);
test_software_detect_add("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
test_software_detect_add("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
test_software_detect_add("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);

View file

@ -2106,8 +2106,25 @@ global:
libnm_1_58_0 {
global:
nm_connection_get_setting_geneve;
nm_device_geneve_get_df;
nm_device_geneve_get_dst_port;
nm_device_geneve_get_id;
nm_device_geneve_get_remote;
nm_device_geneve_get_tos;
nm_device_geneve_get_ttl;
nm_device_geneve_get_type;
nm_ip_config_get_clat_address;
nm_ip_config_get_clat_pref64;
nm_setting_geneve_df_get_type;
nm_setting_geneve_get_destination_port;
nm_setting_geneve_get_df;
nm_setting_geneve_get_id;
nm_setting_geneve_get_remote;
nm_setting_geneve_get_tos;
nm_setting_geneve_get_ttl;
nm_setting_geneve_get_type;
nm_setting_geneve_new;
nm_setting_ip4_config_clat_get_type;
nm_setting_ip4_config_get_clat;
nm_utils_wifi_6ghz_freqs;

View file

@ -16,6 +16,7 @@ libnm_client_impl_sources = files(
'nm-device-bt.c',
'nm-device-dummy.c',
'nm-device-ethernet.c',
'nm-device-geneve.c',
'nm-device-generic.c',
'nm-device-hsr.c',
'nm-device-infiniband.c',

View file

@ -29,6 +29,7 @@
#include "nm-device-dummy.h"
#include "nm-device-ethernet.h"
#include "nm-device-generic.h"
#include "nm-device-geneve.h"
#include "nm-device-hsr.h"
#include "nm-device-infiniband.h"
#include "nm-device-ip-tunnel.h"

View file

@ -0,0 +1,344 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2026 Red Hat, Inc.
*/
#include "libnm-client-impl/nm-default-libnm.h"
#include "nm-device-geneve.h"
#include "nm-setting-connection.h"
#include "nm-setting-geneve.h"
#include "nm-utils.h"
#include "nm-object-private.h"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_ID,
PROP_REMOTE,
PROP_TOS,
PROP_TTL,
PROP_DST_PORT,
PROP_DF, );
typedef struct {
char *remote;
guint32 id;
gint32 ttl;
guint16 dst_port;
guint8 df;
guint8 tos;
} NMDeviceGenevePrivate;
struct _NMDeviceGeneve {
NMDevice parent;
NMDeviceGenevePrivate _priv;
};
struct _NMDeviceGeneveClass {
NMDeviceClass parent;
};
G_DEFINE_TYPE(NMDeviceGeneve, nm_device_geneve, NM_TYPE_DEVICE)
#define NM_DEVICE_GENEVE_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMDeviceGeneve, NM_IS_DEVICE_GENEVE, NMObject, NMDevice)
/*****************************************************************************/
/**
* nm_device_geneve_get_id:
* @device: a #NMDeviceGeneve
*
* Returns: the device's GENEVE ID.
*
* Since: 1.58
**/
guint
nm_device_geneve_get_id(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), 0);
return NM_DEVICE_GENEVE_GET_PRIVATE(device)->id;
}
/**
* nm_device_geneve_get_remote:
* @device: a #NMDeviceGeneve
*
* Returns: the IP address of the remote tunnel endpoint
*
* Since: 1.58
**/
const char *
nm_device_geneve_get_remote(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), NULL);
return _nml_coerce_property_str_not_empty(NM_DEVICE_GENEVE_GET_PRIVATE(device)->remote);
}
/**
* nm_device_geneve_get_dst_port:
* @device: a #NMDeviceGeneve
*
* Returns: the UDP destination port
*
* Since: 1.58
**/
guint
nm_device_geneve_get_dst_port(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), 0);
return NM_DEVICE_GENEVE_GET_PRIVATE(device)->dst_port;
}
/**
* nm_device_geneve_get_tos:
* @device: a #NMDeviceGeneve
*
* Returns: the TOS value to use in outgoing packets
*
* Since: 1.58
**/
guint
nm_device_geneve_get_tos(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), 0);
return NM_DEVICE_GENEVE_GET_PRIVATE(device)->tos;
}
/**
* nm_device_geneve_get_ttl:
* @device: a #NMDeviceGeneve
*
* Returns: the time-to-live value to use in outgoing packets
*
* Since: 1.58
**/
guint
nm_device_geneve_get_ttl(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), 0);
return NM_DEVICE_GENEVE_GET_PRIVATE(device)->ttl;
}
/**
* nm_device_geneve_get_df:
* @device: a #NMDeviceGeneve
*
* Returns: the Don't Fragment (DF) bit to set in outgoing packets
*
* Since: 1.58
**/
guint
nm_device_geneve_get_df(NMDeviceGeneve *device)
{
g_return_val_if_fail(NM_IS_DEVICE_GENEVE(device), 0);
return NM_DEVICE_GENEVE_GET_PRIVATE(device)->df;
}
static gboolean
connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
{
NMSettingGeneve *s_geneve;
if (!NM_DEVICE_CLASS(nm_device_geneve_parent_class)
->connection_compatible(device, connection, error))
return FALSE;
if (!nm_connection_is_type(connection, NM_SETTING_GENEVE_SETTING_NAME)) {
g_set_error_literal(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
_("The connection was not a GENEVE connection."));
return FALSE;
}
s_geneve = nm_connection_get_setting_geneve(connection);
if (nm_setting_geneve_get_id(s_geneve) != nm_device_geneve_get_id(NM_DEVICE_GENEVE(device))) {
g_set_error_literal(
error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
_("The GENEVE identifiers of the device and the connection didn't match."));
return FALSE;
}
return TRUE;
}
static GType
get_setting_type(NMDevice *device)
{
return NM_TYPE_SETTING_GENEVE;
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMDeviceGeneve *device = NM_DEVICE_GENEVE(object);
switch (prop_id) {
case PROP_ID:
g_value_set_uint(value, nm_device_geneve_get_id(device));
break;
case PROP_REMOTE:
g_value_set_string(value, nm_device_geneve_get_remote(device));
break;
case PROP_TOS:
g_value_set_uint(value, nm_device_geneve_get_tos(device));
break;
case PROP_TTL:
g_value_set_int(value, nm_device_geneve_get_ttl(device));
break;
case PROP_DST_PORT:
g_value_set_uint(value, nm_device_geneve_get_dst_port(device));
break;
case PROP_DF:
g_value_set_uint(value, nm_device_geneve_get_df(device));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
nm_device_geneve_init(NMDeviceGeneve *device)
{}
static void
finalize(GObject *object)
{
NMDeviceGenevePrivate *priv = NM_DEVICE_GENEVE_GET_PRIVATE(object);
g_free(priv->remote);
G_OBJECT_CLASS(nm_device_geneve_parent_class)->finalize(object);
}
const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_geneve = NML_DBUS_META_IFACE_INIT_PROP(
NM_DBUS_INTERFACE_DEVICE_GENEVE,
nm_device_geneve_get_type,
NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30,
NML_DBUS_META_IFACE_DBUS_PROPERTIES(
NML_DBUS_META_PROPERTY_INIT_Y("Df", PROP_DF, NMDeviceGeneve, _priv.df),
NML_DBUS_META_PROPERTY_INIT_Q("DstPort", PROP_DST_PORT, NMDeviceGeneve, _priv.dst_port),
NML_DBUS_META_PROPERTY_INIT_U("Id", PROP_ID, NMDeviceGeneve, _priv.id),
NML_DBUS_META_PROPERTY_INIT_S("Remote", PROP_REMOTE, NMDeviceGeneve, _priv.remote),
NML_DBUS_META_PROPERTY_INIT_Y("Tos", PROP_TOS, NMDeviceGeneve, _priv.tos),
NML_DBUS_META_PROPERTY_INIT_I("Ttl", PROP_TTL, NMDeviceGeneve, _priv.ttl), ), );
static void
nm_device_geneve_class_init(NMDeviceGeneveClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
NMObjectClass *nm_object_class = NM_OBJECT_CLASS(klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS(klass);
object_class->get_property = get_property;
object_class->finalize = finalize;
_NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceGeneve);
device_class->connection_compatible = connection_compatible;
device_class->get_setting_type = get_setting_type;
/**
* NMDeviceGeneve:id:
*
* The device's GENEVE ID.
*
* Since: 1.58
**/
obj_properties[PROP_ID] = g_param_spec_uint(NM_DEVICE_GENEVE_ID,
"",
"",
0,
(1 << 24) - 1,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMDeviceGeneve:remote:
*
* The IP address of the remote tunnel endpoint.
*
* Since: 1.58
*/
obj_properties[PROP_REMOTE] = g_param_spec_string(NM_DEVICE_GENEVE_REMOTE,
"",
"",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMDeviceGeneve:tos:
*
* The TOS value to use in outgoing packets.
*
* Since: 1.58
*/
obj_properties[PROP_TOS] = g_param_spec_uchar(NM_DEVICE_GENEVE_TOS,
"",
"",
0,
255,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMDeviceGeneve:ttl:
*
* The time-to-live value to use in outgoing packets.
*
* Since: 1.58
*/
obj_properties[PROP_TTL] = g_param_spec_int(NM_DEVICE_GENEVE_TTL,
"",
"",
-1,
255,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMDeviceGeneve:dst-port:
*
* The UDP destination port used to communicate with the remote GENEVE tunnel
* endpoint.
*
* Since: 1.58
*/
obj_properties[PROP_DST_PORT] = g_param_spec_uint(NM_DEVICE_GENEVE_DST_PORT,
"",
"",
0,
65535,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMDeviceGeneve:df:
*
* The Don't Fragment (DF) bit to set in outgoing packets.
*
* Since: 1.58
*/
obj_properties[PROP_DF] = g_param_spec_uchar(NM_DEVICE_GENEVE_DF,
"",
"",
0,
2,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
_nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_geneve);
}

View file

@ -302,6 +302,7 @@ coerce_type(NMDeviceType type)
case NM_DEVICE_TYPE_TUN:
case NM_DEVICE_TYPE_VETH:
case NM_DEVICE_TYPE_GENERIC:
case NM_DEVICE_TYPE_GENEVE:
case NM_DEVICE_TYPE_UNUSED1:
case NM_DEVICE_TYPE_UNUSED2:
case NM_DEVICE_TYPE_UNKNOWN:
@ -1792,6 +1793,8 @@ get_type_name(NMDevice *device)
return _("MACVLAN");
case NM_DEVICE_TYPE_VXLAN:
return _("VXLAN");
case NM_DEVICE_TYPE_GENEVE:
return _("GENEVE");
case NM_DEVICE_TYPE_IP_TUNNEL:
return _("IPTunnel");
case NM_DEVICE_TYPE_TUN:

View file

@ -789,6 +789,7 @@ const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = {
&_nml_dbus_meta_iface_nm_device_bridge,
&_nml_dbus_meta_iface_nm_device_dummy,
&_nml_dbus_meta_iface_nm_device_generic,
&_nml_dbus_meta_iface_nm_device_geneve,
&_nml_dbus_meta_iface_nm_device_hsr,
&_nml_dbus_meta_iface_nm_device_iptunnel,
&_nml_dbus_meta_iface_nm_device_infiniband,

View file

@ -579,7 +579,7 @@ struct _NMLDBusMetaIface {
NML_DBUS_META_IFACE_OBJ_PROPERTIES(), \
##__VA_ARGS__)
extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[47];
extern const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[48];
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_accesspoint;
@ -593,6 +593,7 @@ extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bond;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bridge;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_dummy;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_generic;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_geneve;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_hsr;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_infiniband;
extern const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_iptunnel;

View file

@ -37,6 +37,7 @@
#include "nm-setting-dummy.h"
#include "nm-setting-ethtool.h"
#include "nm-setting-generic.h"
#include "nm-setting-geneve.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-hsr.h"
@ -114,6 +115,7 @@
#include "nm-device-dummy.h"
#include "nm-device-ethernet.h"
#include "nm-device-generic.h"
#include "nm-device-geneve.h"
#include "nm-device-hsr.h"
#include "nm-device-infiniband.h"
#include "nm-device-ip-tunnel.h"

View file

@ -18,6 +18,7 @@ libnm_client_headers = files(
'nm-device-dummy.h',
'nm-device-ethernet.h',
'nm-device-generic.h',
'nm-device-geneve.h',
'nm-device-hsr.h',
'nm-device-infiniband.h',
'nm-device-ip-tunnel.h',

View file

@ -41,6 +41,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceBt, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceDummy, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceEthernet, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceGeneric, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceGeneve, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceHsr, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceIPTunnel, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceInfiniband, g_object_unref)
@ -80,6 +81,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingDcb, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingDummy, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingEthtool, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingGeneric, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingGeneve, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingGsm, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingHostname, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingHsr, g_object_unref)

View file

@ -0,0 +1,60 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2015 Red Hat, Inc.
*/
#ifndef __NM_DEVICE_GENEVE_H__
#define __NM_DEVICE_GENEVE_H__
#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include "nm-device.h"
G_BEGIN_DECLS
#define NM_TYPE_DEVICE_GENEVE (nm_device_geneve_get_type())
#define NM_DEVICE_GENEVE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneve))
#define NM_DEVICE_GENEVE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
#define NM_IS_DEVICE_GENEVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_GENEVE))
#define NM_IS_DEVICE_GENEVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_GENEVE))
#define NM_DEVICE_GENEVE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_GENEVE, NMDeviceGeneveClass))
#define NM_DEVICE_GENEVE_ID "id"
#define NM_DEVICE_GENEVE_REMOTE "remote"
#define NM_DEVICE_GENEVE_TOS "tos"
#define NM_DEVICE_GENEVE_TTL "ttl"
#define NM_DEVICE_GENEVE_DST_PORT "dst-port"
#define NM_DEVICE_GENEVE_DF "df"
/**
* NMDeviceGeneve:
*
* Since: 1.58
*/
typedef struct _NMDeviceGeneve NMDeviceGeneve;
typedef struct _NMDeviceGeneveClass NMDeviceGeneveClass;
NM_AVAILABLE_IN_1_58
GType nm_device_geneve_get_type(void);
NM_AVAILABLE_IN_1_58
guint nm_device_geneve_get_id(NMDeviceGeneve *device);
NM_AVAILABLE_IN_1_58
const char *nm_device_geneve_get_remote(NMDeviceGeneve *device);
NM_AVAILABLE_IN_1_58
guint nm_device_geneve_get_dst_port(NMDeviceGeneve *device);
NM_AVAILABLE_IN_1_58
guint nm_device_geneve_get_tos(NMDeviceGeneve *device);
NM_AVAILABLE_IN_1_58
guint nm_device_geneve_get_ttl(NMDeviceGeneve *device);
NM_AVAILABLE_IN_1_58
guint nm_device_geneve_get_df(NMDeviceGeneve *device);
G_END_DECLS
#endif /* __NM_DEVICE_GENEVE_H__ */

View file

@ -1378,6 +1378,34 @@
gprop-type="gchararray"
/>
</setting>
<setting name="geneve"
gtype="NMSettingGeneve"
>
<property name="destination-port"
dbus-type="u"
gprop-type="guint"
/>
<property name="df"
dbus-type="i"
gprop-type="gint"
/>
<property name="id"
dbus-type="u"
gprop-type="guint"
/>
<property name="remote"
dbus-type="s"
gprop-type="gchararray"
/>
<property name="tos"
dbus-type="u"
gprop-type="guint"
/>
<property name="ttl"
dbus-type="i"
gprop-type="gint"
/>
</setting>
<setting name="gsm"
gtype="NMSettingGsm"
>

View file

@ -17,6 +17,7 @@ libnm_core_settings_sources = files(
'nm-setting-dummy.c',
'nm-setting-ethtool.c',
'nm-setting-generic.c',
'nm-setting-geneve.c',
'nm-setting-gsm.c',
'nm-setting-hostname.c',
'nm-setting-hsr.c',

View file

@ -3272,6 +3272,7 @@ nm_connection_is_virtual(NMConnection *connection)
NM_SETTING_BOND_SETTING_NAME,
NM_SETTING_BRIDGE_SETTING_NAME,
NM_SETTING_DUMMY_SETTING_NAME,
NM_SETTING_GENEVE_SETTING_NAME,
NM_SETTING_HSR_SETTING_NAME,
NM_SETTING_IP_TUNNEL_SETTING_NAME,
NM_SETTING_IPVLAN_SETTING_NAME,
@ -3526,6 +3527,22 @@ nm_connection_get_setting_generic(NMConnection *connection)
return _nm_connection_get_setting_by_metatype(connection, NM_META_SETTING_TYPE_GENERIC);
}
/**
* nm_connection_get_setting_geneve:
* @connection: the #NMConnection
*
* A shortcut to return any #NMSettingGeneve the connection might contain.
*
* Returns: (transfer none): an #NMSettingGeneve if the connection contains one, otherwise NULL
*
* Since: 1.58
**/
NMSettingGeneve *
nm_connection_get_setting_geneve(NMConnection *connection)
{
return _nm_connection_get_setting_by_metatype(connection, NM_META_SETTING_TYPE_GENEVE);
}
/**
* nm_connection_get_setting_gsm:
* @connection: the #NMConnection

View file

@ -27,6 +27,7 @@
#include "nm-setting-dummy.h"
#include "nm-setting-ethtool.h"
#include "nm-setting-generic.h"
#include "nm-setting-geneve.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-hsr.h"
@ -324,6 +325,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_GENERIC_SETTING_NAME,
.get_setting_gtype = nm_setting_generic_get_type,
},
[NM_META_SETTING_TYPE_GENEVE] =
{
.meta_type = NM_META_SETTING_TYPE_GENEVE,
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
.setting_name = NM_SETTING_GENEVE_SETTING_NAME,
.get_setting_gtype = nm_setting_geneve_get_type,
},
[NM_META_SETTING_TYPE_GSM] =
{
.meta_type = NM_META_SETTING_TYPE_GSM,
@ -655,6 +663,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_CDMA,
NM_META_SETTING_TYPE_DUMMY,
NM_META_SETTING_TYPE_GENERIC,
NM_META_SETTING_TYPE_GENEVE,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_HSR,
NM_META_SETTING_TYPE_INFINIBAND,

View file

@ -0,0 +1,354 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2026 Red Hat, Inc.
*/
#include "libnm-core-impl/nm-default-libnm-core.h"
#include "nm-setting-geneve.h"
#include <stdlib.h>
#include "nm-utils.h"
#include "nm-setting-private.h"
/**
* SECTION:nm-setting-geneve
* @short_description: Describes connection properties for GENEVE interfaces
*
* The #NMSettingGeneve object is a #NMSetting subclass that describes properties
* necessary for connection to GENEVE interfaces.
**/
#define DST_PORT_DEFAULT 6081
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_ID,
PROP_REMOTE,
PROP_DESTINATION_PORT,
PROP_TOS,
PROP_TTL,
PROP_DF, );
typedef struct {
char *remote;
guint32 id;
guint32 destination_port;
guint32 tos;
gint32 ttl;
int df;
} NMSettingGenevePrivate;
/**
* NMSettingGeneve:
*
* GENEVE Settings
*/
struct _NMSettingGeneve {
NMSetting parent;
NMSettingGenevePrivate _priv;
};
struct _NMSettingGeneveClass {
NMSettingClass parent;
};
G_DEFINE_TYPE(NMSettingGeneve, nm_setting_geneve, NM_TYPE_SETTING)
#define NM_SETTING_GENEVE_GET_PRIVATE(o) \
_NM_GET_PRIVATE(o, NMSettingGeneve, NM_IS_SETTING_GENEVE, NMSetting)
/*****************************************************************************/
/**
* nm_setting_geneve_get_id:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:id property of the setting
*
* Since: 1.58
**/
guint
nm_setting_geneve_get_id(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), 0);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->id;
}
/**
* nm_setting_geneve_get_remote:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:remote property of the setting
*
* Since: 1.58
**/
const char *
nm_setting_geneve_get_remote(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), NULL);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->remote;
}
/**
* nm_setting_geneve_get_destination_port:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:destination-port property of the setting
*
* Since: 1.58
**/
guint
nm_setting_geneve_get_destination_port(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), DST_PORT_DEFAULT);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->destination_port;
}
/**
* nm_setting_geneve_get_tos:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:tos property of the setting
*
* Since: 1.58
**/
guint
nm_setting_geneve_get_tos(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), 0);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->tos;
}
/**
* nm_setting_geneve_get_ttl:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:ttl property of the setting
*
* Since: 1.58
**/
guint
nm_setting_geneve_get_ttl(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), 0);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->ttl;
}
/**
* nm_setting_geneve_get_df:
* @setting: the #NMSettingGeneve
*
* Returns: the #NMSettingGeneve:df property of the setting
*
* Since: 1.58
**/
NMSettingGeneveDf
nm_setting_geneve_get_df(NMSettingGeneve *setting)
{
g_return_val_if_fail(NM_IS_SETTING_GENEVE(setting), NM_SETTING_GENEVE_DF_UNSET);
return NM_SETTING_GENEVE_GET_PRIVATE(setting)->df;
}
/*****************************************************************************/
static gboolean
verify(NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingGenevePrivate *priv = NM_SETTING_GENEVE_GET_PRIVATE(setting);
if (priv->id == 0) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_PROPERTY,
_("property is required"));
g_prefix_error(error, "%s.%s: ", NM_SETTING_GENEVE_SETTING_NAME, NM_SETTING_GENEVE_ID);
return FALSE;
}
if (!priv->remote) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_PROPERTY,
_("property is required"));
g_prefix_error(error, "%s.%s: ", NM_SETTING_GENEVE_SETTING_NAME, NM_SETTING_GENEVE_REMOTE);
return FALSE;
}
if (!nm_inet_parse_bin(AF_UNSPEC, priv->remote, NULL, NULL)) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' is not a valid IP address"),
priv->remote);
g_prefix_error(error, "%s.%s: ", NM_SETTING_GENEVE_SETTING_NAME, NM_SETTING_GENEVE_REMOTE);
return FALSE;
}
return TRUE;
}
/*****************************************************************************/
static void
nm_setting_geneve_init(NMSettingGeneve *self)
{}
/**
* nm_setting_geneve_new:
*
* Creates a new #NMSettingGeneve object with default values.
*
* Returns: (transfer full): the new empty #NMSettingGeneve object
*
* Since: 1.58
**/
NMSetting *
nm_setting_geneve_new(void)
{
return g_object_new(NM_TYPE_SETTING_GENEVE, NULL);
}
static void
nm_setting_geneve_class_init(NMSettingGeneveClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
GArray *properties_override = _nm_sett_info_property_override_create_array();
object_class->get_property = _nm_setting_property_get_property_direct;
object_class->set_property = _nm_setting_property_set_property_direct;
setting_class->verify = verify;
/**
* NMSettingGeneve:id:
*
* Specifies the GENEVE Network Identifier (or GENEVE Segment Identifier) to
* use.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_GENEVE_ID,
PROP_ID,
0,
(1 << 24) - 1,
0,
NM_SETTING_PARAM_INFERRABLE,
NMSettingGenevePrivate,
id);
/**
* NMSettingGeneve:remote:
*
* Specifies the unicast destination IP address to use in outgoing packets
* when communicating with the remote GENEVE tunnel endpoint.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_string(properties_override,
obj_properties,
NM_SETTING_GENEVE_REMOTE,
PROP_REMOTE,
NM_SETTING_PARAM_REQUIRED,
NMSettingGenevePrivate,
remote,
.direct_set_string_ip_address_addr_family =
AF_UNSPEC + 1,
.direct_string_allow_empty = TRUE);
/**
* NMSettingGeneve:destination-port:
*
* Specifies the UDP destination port to communicate to the remote GENEVE
* tunnel endpoint.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_GENEVE_DESTINATION_PORT,
PROP_DESTINATION_PORT,
0,
G_MAXUINT16,
DST_PORT_DEFAULT,
NM_SETTING_PARAM_INFERRABLE,
NMSettingGenevePrivate,
destination_port);
/**
* NMSettingGeneve:tos:
*
* Specifies the TOS value to use in outgoing packets.
* The special value "inherit" (1) means inherit from outer packet.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_uint32(properties_override,
obj_properties,
NM_SETTING_GENEVE_TOS,
PROP_TOS,
0,
255,
0,
NM_SETTING_PARAM_INFERRABLE,
NMSettingGenevePrivate,
tos);
/**
* NMSettingGeneve:ttl:
*
* Specifies the time-to-live value to use in outgoing packets.
* The special value "inherit" (-1) means inherit from outer packet, 0 means auto, 1-255 are fixed values.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_int32(properties_override,
obj_properties,
NM_SETTING_GENEVE_TTL,
PROP_TTL,
-1,
255,
0,
NM_SETTING_PARAM_INFERRABLE,
NMSettingGenevePrivate,
ttl);
/**
* NMSettingGeneve:df:
*
* Specifies how the Don't Fragment (DF) flag should be handled in the outer IP
* header of GENEVE tunnel packets.
*
* %NM_SETTING_GENEVE_DF_UNSET (0): Don't set the DF flag, packets may be fragmented.
* %NM_SETTING_GENEVE_DF_SET (1): Always set the DF flag, packets will not be fragmented.
* %NM_SETTING_GENEVE_DF_INHERIT (2): Inherit the DF flag from the inner IP header.
*
* Since: 1.58
**/
_nm_setting_property_define_direct_enum(properties_override,
obj_properties,
NM_SETTING_GENEVE_DF,
PROP_DF,
NM_TYPE_SETTING_GENEVE_DF,
NM_SETTING_GENEVE_DF_UNSET,
NM_SETTING_PARAM_INFERRABLE,
NULL,
NMSettingGenevePrivate,
df);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit(setting_class,
NM_META_SETTING_TYPE_GENEVE,
NULL,
properties_override,
G_STRUCT_OFFSET(NMSettingGeneve, _priv));
}

View file

@ -37,6 +37,7 @@
#include "nm-setting-dcb.h"
#include "nm-setting-dummy.h"
#include "nm-setting-generic.h"
#include "nm-setting-geneve.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hsr.h"
#include "nm-setting-hostname.h"

View file

@ -121,6 +121,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_DUMMY,
NM_META_SETTING_TYPE_ETHTOOL,
NM_META_SETTING_TYPE_GENERIC,
NM_META_SETTING_TYPE_GENEVE,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_HOSTNAME,
NM_META_SETTING_TYPE_HSR,

View file

@ -22,6 +22,7 @@ libnm_core_headers = files(
'nm-setting-dummy.h',
'nm-setting-ethtool.h',
'nm-setting-generic.h',
'nm-setting-geneve.h',
'nm-setting-gsm.h',
'nm-setting-hsr.h',
'nm-setting-hostname.h',

View file

@ -206,8 +206,10 @@ NMSettingCdma *nm_connection_get_setting_cdma(NMConnection *connection);
NMSettingConnection *nm_connection_get_setting_connection(NMConnection *connection);
NMSettingDcb *nm_connection_get_setting_dcb(NMConnection *connection);
NM_AVAILABLE_IN_1_8
NMSettingDummy *nm_connection_get_setting_dummy(NMConnection *connection);
NMSettingGeneric *nm_connection_get_setting_generic(NMConnection *connection);
NMSettingDummy *nm_connection_get_setting_dummy(NMConnection *connection);
NMSettingGeneric *nm_connection_get_setting_generic(NMConnection *connection);
NM_AVAILABLE_IN_1_58
NMSettingGeneve *nm_connection_get_setting_geneve(NMConnection *connection);
NMSettingGsm *nm_connection_get_setting_gsm(NMConnection *connection);
NMSettingInfiniband *nm_connection_get_setting_infiniband(NMConnection *connection);
NM_AVAILABLE_IN_1_2

View file

@ -27,6 +27,7 @@ typedef struct _NMSettingConnection NMSettingConnection;
typedef struct _NMSettingDcb NMSettingDcb;
typedef struct _NMSettingDummy NMSettingDummy;
typedef struct _NMSettingEthtool NMSettingEthtool;
typedef struct _NMSettingGeneve NMSettingGeneve;
typedef struct _NMSettingGeneric NMSettingGeneric;
typedef struct _NMSettingGsm NMSettingGsm;
typedef struct _NMSettingHostname NMSettingHostname;

View file

@ -36,6 +36,7 @@
#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge"
#define NM_DBUS_INTERFACE_DEVICE_DUMMY NM_DBUS_INTERFACE_DEVICE ".Dummy"
#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic"
#define NM_DBUS_INTERFACE_DEVICE_GENEVE NM_DBUS_INTERFACE_DEVICE ".Geneve"
#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
#define NM_DBUS_INTERFACE_DEVICE_HSR NM_DBUS_INTERFACE_DEVICE ".Hsr"
#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband"
@ -250,6 +251,7 @@ typedef enum {
* @NM_DEVICE_TYPE_LOOPBACK: a loopback interface. Since: 1.42.
* @NM_DEVICE_TYPE_HSR: A HSR/PRP device. Since: 1.46.
* @NM_DEVICE_TYPE_IPVLAN: A IPVLAN device. Since: 1.52.
* @NM_DEVICE_TYPE_GENEVE: A GENEVE device. Since: 1.58.
*
* #NMDeviceType values indicate the type of hardware represented by a
* device object.
@ -290,6 +292,7 @@ typedef enum {
NM_DEVICE_TYPE_LOOPBACK = 32,
NM_DEVICE_TYPE_HSR = 33,
NM_DEVICE_TYPE_IPVLAN = 34,
NM_DEVICE_TYPE_GENEVE = 35,
} NMDeviceType;
/**

View file

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2026 Red Hat, Inc.
*/
#ifndef __NM_SETTING_GENEVE_H__
#define __NM_SETTING_GENEVE_H__
#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include "nm-setting.h"
G_BEGIN_DECLS
#define NM_TYPE_SETTING_GENEVE (nm_setting_geneve_get_type())
#define NM_SETTING_GENEVE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_GENEVE, NMSettingGeneve))
#define NM_SETTING_GENEVE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_GENEVE, NMSettingGeneveClass))
#define NM_IS_SETTING_GENEVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_GENEVE))
#define NM_IS_SETTING_GENEVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_GENEVE))
#define NM_SETTING_GENEVE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_GENEVE, NMSettingGeneveClass))
#define NM_SETTING_GENEVE_SETTING_NAME "geneve"
#define NM_SETTING_GENEVE_ID "id"
#define NM_SETTING_GENEVE_REMOTE "remote"
#define NM_SETTING_GENEVE_DESTINATION_PORT "destination-port"
#define NM_SETTING_GENEVE_TOS "tos"
#define NM_SETTING_GENEVE_TTL "ttl"
#define NM_SETTING_GENEVE_DF "df"
/**
* NMSettingGeneveDf:
* @NM_SETTING_GENEVE_DF_UNSET: Don't set the DF flag, packets may be fragmented.
* @NM_SETTING_GENEVE_DF_SET: Always set the DF flag, packets will not be fragmented.
* @NM_SETTING_GENEVE_DF_INHERIT: Inherit the DF flag from the inner IP header.
*
* #NMSettingGeneveDf values indicate how the Don't Fragment (DF) flag should be handled
* in the outer IP header of GENEVE tunnel packets.
*
* Since: 1.58
*/
typedef enum {
NM_SETTING_GENEVE_DF_UNSET = 0,
NM_SETTING_GENEVE_DF_SET = 1,
NM_SETTING_GENEVE_DF_INHERIT = 2,
} NMSettingGeneveDf;
typedef struct _NMSettingGeneveClass NMSettingGeneveClass;
NM_AVAILABLE_IN_1_58
GType nm_setting_geneve_get_type(void);
NM_AVAILABLE_IN_1_58
NMSetting *nm_setting_geneve_new(void);
NM_AVAILABLE_IN_1_58
guint nm_setting_geneve_get_id(NMSettingGeneve *setting);
NM_AVAILABLE_IN_1_58
const char *nm_setting_geneve_get_remote(NMSettingGeneve *setting);
NM_AVAILABLE_IN_1_58
guint nm_setting_geneve_get_destination_port(NMSettingGeneve *setting);
NM_AVAILABLE_IN_1_58
guint nm_setting_geneve_get_tos(NMSettingGeneve *setting);
NM_AVAILABLE_IN_1_58
guint nm_setting_geneve_get_ttl(NMSettingGeneve *setting);
NM_AVAILABLE_IN_1_58
NMSettingGeneveDf nm_setting_geneve_get_df(NMSettingGeneve *setting);
G_END_DECLS
#endif /* __NM_SETTING_GENEVE_H__ */

View file

@ -130,6 +130,7 @@ typedef enum {
#define _NM_LINK_TYPE_SW_FIRST NM_LINK_TYPE_BNEP
NM_LINK_TYPE_BNEP, /* Bluetooth Ethernet emulation */
NM_LINK_TYPE_DUMMY,
NM_LINK_TYPE_GENEVE,
NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IFB,

View file

@ -862,6 +862,7 @@ static const LinkDesc link_descs[] = {
[NM_LINK_TYPE_BNEP] = {"bluetooth", NULL, "bluetooth"},
[NM_LINK_TYPE_DUMMY] = {"dummy", "dummy", NULL},
[NM_LINK_TYPE_GENEVE] = {"geneve", "geneve", "geneve"},
[NM_LINK_TYPE_GRE] = {"gre", "gre", NULL},
[NM_LINK_TYPE_GRETAP] = {"gretap", "gretap", NULL},
[NM_LINK_TYPE_IFB] = {"ifb", "ifb", NULL},
@ -909,6 +910,7 @@ _link_type_from_rtnl_type(const char *name)
NM_LINK_TYPE_BOND, /* "bond" */
NM_LINK_TYPE_BRIDGE, /* "bridge" */
NM_LINK_TYPE_DUMMY, /* "dummy" */
NM_LINK_TYPE_GENEVE, /* "geneve" */
NM_LINK_TYPE_GRE, /* "gre" */
NM_LINK_TYPE_GRETAP, /* "gretap" */
NM_LINK_TYPE_HSR, /* "hsr" */
@ -987,6 +989,7 @@ _link_type_from_devtype(const char *name)
NM_LINK_TYPE_BNEP, /* "bluetooth" */
NM_LINK_TYPE_BOND, /* "bond" */
NM_LINK_TYPE_BRIDGE, /* "bridge" */
NM_LINK_TYPE_GENEVE, /* "geneve" */
NM_LINK_TYPE_HSR, /* "hsr" */
NM_LINK_TYPE_PPP, /* "ppp" */
NM_LINK_TYPE_VLAN, /* "vlan" */
@ -1856,6 +1859,57 @@ _parse_lnk_gre(const char *kind, struct nlattr *info_data)
/*****************************************************************************/
static NMPObject *
_parse_lnk_geneve(const char *kind, struct nlattr *info_data)
{
static const struct nla_policy policy[] = {
[IFLA_GENEVE_ID] = {.type = NLA_U32},
[IFLA_GENEVE_REMOTE] = {.type = NLA_U32},
[IFLA_GENEVE_REMOTE6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)},
[IFLA_GENEVE_TTL] = {.type = NLA_U8},
[IFLA_GENEVE_TOS] = {.type = NLA_U8},
[IFLA_GENEVE_TTL_INHERIT] = {.type = NLA_U8},
[IFLA_GENEVE_PORT] = {.type = NLA_U16},
[IFLA_GENEVE_DF] = {.type = NLA_U8},
};
struct nlattr *tb[G_N_ELEMENTS(policy)];
NMPObject *obj;
NMPlatformLnkGeneve *props;
if (!info_data || !nm_streq0(kind, "geneve"))
return NULL;
if (nla_parse_nested_arr(tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_GENEVE, NULL);
props = &obj->lnk_geneve;
if (tb[IFLA_GENEVE_ID])
props->id = nla_get_u32(tb[IFLA_GENEVE_ID]);
if (tb[IFLA_GENEVE_REMOTE])
props->remote = nla_get_u32(tb[IFLA_GENEVE_REMOTE]);
if (tb[IFLA_GENEVE_REMOTE6])
props->remote6 = *nla_data_as(struct in6_addr, tb[IFLA_GENEVE_REMOTE6]);
if (tb[IFLA_GENEVE_TTL_INHERIT] && nla_get_u8(tb[IFLA_GENEVE_TTL_INHERIT]))
props->ttl = -1;
else if (tb[IFLA_GENEVE_TTL])
props->ttl = nla_get_u8(tb[IFLA_GENEVE_TTL]);
if (tb[IFLA_GENEVE_TOS])
props->tos = nla_get_u8(tb[IFLA_GENEVE_TOS]);
if (tb[IFLA_GENEVE_PORT])
props->dst_port = ntohs(nla_get_u16(tb[IFLA_GENEVE_PORT]));
if (tb[IFLA_GENEVE_DF])
props->df = nla_get_u8(tb[IFLA_GENEVE_DF]);
return obj;
}
/*****************************************************************************/
static NMPObject *
_parse_lnk_hsr(const char *kind, struct nlattr *info_data)
{
@ -3694,6 +3748,9 @@ _new_from_nl_link(NMPlatform *platform,
case NM_LINK_TYPE_BOND:
lnk_data = _parse_lnk_bond(nl_info_kind, nl_info_data);
break;
case NM_LINK_TYPE_GENEVE:
lnk_data = _parse_lnk_geneve(nl_info_kind, nl_info_data);
break;
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data);
@ -5182,6 +5239,35 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo
nla_nest_end(msg, info_peer);
break;
}
case NM_LINK_TYPE_GENEVE:
{
const NMPlatformLnkGeneve *props = extra_data;
nm_assert(props);
if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
goto nla_put_failure;
NLA_PUT_U32(msg, IFLA_GENEVE_ID, props->id);
if (props->remote) {
NLA_PUT_U32(msg, IFLA_GENEVE_REMOTE, props->remote);
} else if (!IN6_IS_ADDR_UNSPECIFIED(&props->remote6)) {
NLA_PUT(msg, IFLA_GENEVE_REMOTE6, sizeof(props->remote6), &props->remote6);
}
NLA_PUT_U16(msg, IFLA_GENEVE_PORT, htons(props->dst_port));
if (props->ttl == -1) {
NLA_PUT_U8(msg, IFLA_GENEVE_TTL_INHERIT, 1);
} else {
/* When you want to specify a TTL value,
* don't add TTL_INHERIT to the message */
NLA_PUT_U8(msg, IFLA_GENEVE_TTL, props->ttl & 0xff);
}
NLA_PUT_U8(msg, IFLA_GENEVE_TOS, props->tos);
NLA_PUT_U8(msg, IFLA_GENEVE_DF, props->df);
break;
}
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
{

View file

@ -1388,6 +1388,12 @@ nm_platform_link_add(NMPlatform *self,
case NM_LINK_TYPE_VETH:
nm_sprintf_buf(buf, ", veth-peer \"%s\"", (const char *) extra_data);
break;
case NM_LINK_TYPE_GENEVE:
nm_strbuf_append_str(&buf_p, &buf_len, ", ");
nm_platform_lnk_geneve_to_string((const NMPlatformLnkGeneve *) extra_data,
buf_p,
buf_len);
break;
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
nm_strbuf_append_str(&buf_p, &buf_len, ", ");
@ -2565,6 +2571,12 @@ nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformL
return _link_get_lnk(self, ifindex, NM_LINK_TYPE_BRIDGE, out_link);
}
const NMPlatformLnkGeneve *
nm_platform_link_get_lnk_geneve(NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GENEVE, out_link);
}
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
@ -6494,6 +6506,52 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le
return buf;
}
const char *
nm_platform_lnk_geneve_to_string(const NMPlatformLnkGeneve *lnk, char *buf, gsize len)
{
char str_remote[NM_INET_ADDRSTRLEN];
char str_remote1[30 + NM_INET_ADDRSTRLEN];
char str_remote6[NM_INET_ADDRSTRLEN];
char str_remote6_1[30 + NM_INET_ADDRSTRLEN];
char str_ttl[30];
char str_tos[30];
char str_id[30];
char str_dstport[30];
if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len))
return buf;
g_snprintf(
buf,
len,
"geneve"
"%s" /* id */
"%s" /* remote */
"%s" /* remote6 */
"%s" /* dst_port */
"%s" /* ttl */
"%s" /* tos */
"%s" /* df */
"",
lnk->id ? nm_sprintf_buf(str_id, " id %u", lnk->id) : "",
lnk->remote
? nm_sprintf_buf(str_remote, " remote %s", nm_inet4_ntop(lnk->remote, str_remote1))
: "",
!IN6_IS_ADDR_UNSPECIFIED(&lnk->remote6)
? nm_sprintf_buf(str_remote6, " remote %s", nm_inet6_ntop(&lnk->remote6, str_remote6_1))
: "",
lnk->dst_port ? nm_sprintf_buf(str_dstport, " dstport %u", lnk->dst_port) : "",
lnk->ttl > 0 ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl & 0xff)
: lnk->ttl == 0 ? "ttl auto"
: "ttl inherit",
lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos))
: "",
lnk->df == 1 ? " df set "
: lnk->df == 2 ? " df inherit "
: "");
return buf;
}
const char *
nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len)
{
@ -8491,6 +8549,27 @@ nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b)
return 0;
}
void
nm_platform_lnk_geneve_hash_update(const NMPlatformLnkGeneve *obj, NMHashState *h)
{
nm_hash_update_vals(h, obj->id, obj->remote, obj->dst_port, obj->ttl, obj->tos, obj->df);
nm_hash_update_mem(h, &obj->remote6, sizeof(obj->remote6));
}
int
nm_platform_lnk_geneve_cmp(const NMPlatformLnkGeneve *a, const NMPlatformLnkGeneve *b)
{
NM_CMP_SELF(a, b);
NM_CMP_FIELD(a, b, id);
NM_CMP_FIELD(a, b, remote);
NM_CMP_FIELD_MEMCMP(a, b, remote6);
NM_CMP_FIELD(a, b, ttl);
NM_CMP_FIELD(a, b, tos);
NM_CMP_FIELD(a, b, dst_port);
NM_CMP_FIELD(a, b, df);
return 0;
}
void
nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h)
{

View file

@ -835,6 +835,16 @@ typedef struct {
bool use_carrier : 1;
} _nm_alignas(NMPlatformObject) NMPlatformLnkBond;
typedef struct {
struct in6_addr remote6;
in_addr_t remote;
guint32 id;
gint32 ttl;
guint16 dst_port;
guint8 tos;
guint8 df;
} _nm_alignas(NMPlatformObject) NMPlatformLnkGeneve;
typedef struct {
int parent_ifindex;
in_addr_t local;
@ -1858,6 +1868,15 @@ nm_platform_link_vxlan_add(NMPlatform *self,
return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, 0, props, out_link);
}
static inline int
nm_platform_link_geneve_add(NMPlatform *self,
const char *name,
const NMPlatformLnkGeneve *props,
const NMPlatformLink **out_link)
{
return nm_platform_link_add(self, NM_LINK_TYPE_GENEVE, name, 0, NULL, 0, 0, props, out_link);
}
static inline int
nm_platform_link_6lowpan_add(NMPlatform *self,
const char *name,
@ -2143,6 +2162,8 @@ const NMPlatformLnkBond *
nm_platform_link_get_lnk_bond(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkBridge *
nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGeneve *
nm_platform_link_get_lnk_geneve(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGre *
@ -2482,6 +2503,7 @@ gboolean nm_platform_tc_sync(NMPlatform *self,
const char *nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len);
const char *nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize len);
const char *nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len);
const char *nm_platform_lnk_geneve_to_string(const NMPlatformLnkGeneve *lnk, char *buf, gsize len);
const char *nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len);
const char *nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len);
const char *
@ -2537,6 +2559,7 @@ nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *bu
int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b);
int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b);
int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b);
int nm_platform_lnk_geneve_cmp(const NMPlatformLnkGeneve *a, const NMPlatformLnkGeneve *b);
int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b);
int nm_platform_lnk_hsr_cmp(const NMPlatformLnkHsr *a, const NMPlatformLnkHsr *b);
int nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a,
@ -2612,6 +2635,7 @@ void nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj,
NMHashState *h);
void nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h);
void nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h);
void nm_platform_lnk_geneve_hash_update(const NMPlatformLnkGeneve *obj, NMHashState *h);
void nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h);
void nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h);
void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h);

View file

@ -166,6 +166,7 @@ typedef enum _nm_packed {
NMP_OBJECT_TYPE_TFILTER,
NMP_OBJECT_TYPE_LNK_BRIDGE,
NMP_OBJECT_TYPE_LNK_GENEVE,
NMP_OBJECT_TYPE_LNK_GRE,
NMP_OBJECT_TYPE_LNK_GRETAP,
NMP_OBJECT_TYPE_LNK_HSR,
@ -194,15 +195,15 @@ typedef enum _nm_packed {
NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1,
} NMPObjectType;
static inline guint32
static inline guint64
nmp_object_type_to_flags(NMPObjectType obj_type)
{
G_STATIC_ASSERT_EXPR(NMP_OBJECT_TYPE_MAX < 32);
G_STATIC_ASSERT_EXPR(NMP_OBJECT_TYPE_MAX < 64);
nm_assert(_NM_INT_NOT_NEGATIVE(obj_type));
nm_assert(obj_type < NMP_OBJECT_TYPE_MAX);
return ((guint32) 1u) << obj_type;
return ((guint64) 1u) << obj_type;
}
/*****************************************************************************/

View file

@ -3469,6 +3469,18 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_bridge_hash_update,
.cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_bridge_cmp,
},
[NMP_OBJECT_TYPE_LNK_GENEVE - 1] =
{
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_GENEVE,
.sizeof_data = sizeof(NMPObjectLnkGeneve),
.sizeof_public = sizeof(NMPlatformLnkGeneve),
.obj_type_name = "geneve",
.lnk_link_type = NM_LINK_TYPE_GENEVE,
.cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_geneve_to_string,
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_geneve_hash_update,
.cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_geneve_cmp,
},
[NMP_OBJECT_TYPE_LNK_GRE - 1] =
{
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),

View file

@ -250,6 +250,10 @@ typedef struct {
NMPlatformLnkBond _public;
} NMPObjectLnkBond;
typedef struct {
NMPlatformLnkGeneve _public;
} NMPObjectLnkGeneve;
typedef struct {
NMPlatformLnkGre _public;
} NMPObjectLnkGre;
@ -383,6 +387,9 @@ struct _NMPObject {
NMPlatformLnkBond lnk_bond;
NMPObjectLnkBond _lnk_bond;
NMPlatformLnkGeneve lnk_geneve;
NMPObjectLnkGeneve _lnk_geneve;
NMPlatformLnkGre lnk_gre;
NMPObjectLnkGre _lnk_gre;
@ -543,6 +550,7 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type)
case NMP_OBJECT_TYPE_LNK_BRIDGE:
case NMP_OBJECT_TYPE_LNK_BOND:
case NMP_OBJECT_TYPE_LNK_GENEVE:
case NMP_OBJECT_TYPE_LNK_GRE:
case NMP_OBJECT_TYPE_LNK_GRETAP:
case NMP_OBJECT_TYPE_LNK_HSR:

View file

@ -19,6 +19,7 @@ G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectIP6Route))
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLink));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkBond));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkBridge));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkGeneve));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkGre));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkInfiniband));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkIp6Tnl));
@ -49,6 +50,7 @@ G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformIPXRoute)
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLink));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkBond));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkBridge));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkGeneve));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkGre));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkInfiniband));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkIp6Tnl));

View file

@ -27,6 +27,7 @@
#include "nm-setting-dummy.h"
#include "nm-setting-ethtool.h"
#include "nm-setting-generic.h"
#include "nm-setting-geneve.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-hsr.h"
@ -324,6 +325,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_GENERIC_SETTING_NAME,
.get_setting_gtype = nm_setting_generic_get_type,
},
[NM_META_SETTING_TYPE_GENEVE] =
{
.meta_type = NM_META_SETTING_TYPE_GENEVE,
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
.setting_name = NM_SETTING_GENEVE_SETTING_NAME,
.get_setting_gtype = nm_setting_geneve_get_type,
},
[NM_META_SETTING_TYPE_GSM] =
{
.meta_type = NM_META_SETTING_TYPE_GSM,
@ -655,6 +663,7 @@ const NMMetaSettingType nm_meta_setting_types_by_priority[] = {
NM_META_SETTING_TYPE_CDMA,
NM_META_SETTING_TYPE_DUMMY,
NM_META_SETTING_TYPE_GENERIC,
NM_META_SETTING_TYPE_GENEVE,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_HSR,
NM_META_SETTING_TYPE_INFINIBAND,

View file

@ -121,6 +121,7 @@ typedef enum _nm_packed {
NM_META_SETTING_TYPE_DUMMY,
NM_META_SETTING_TYPE_ETHTOOL,
NM_META_SETTING_TYPE_GENERIC,
NM_META_SETTING_TYPE_GENEVE,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_HOSTNAME,
NM_META_SETTING_TYPE_HSR,

View file

@ -6112,6 +6112,57 @@ static const NMMetaPropertyInfo *const property_infos_GENERIC[] = {
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GENEVE
static const NMMetaPropertyInfo *const property_infos_GENEVE[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_ID,
.is_cli_option = TRUE,
.property_alias = "id",
.inf_flags = NM_META_PROPERTY_INF_FLAG_REQD,
.prompt = N_("GENEVE ID"),
.property_type = &_pt_gobject_int,
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_REMOTE,
.is_cli_option = TRUE,
.property_alias = "remote",
.inf_flags = NM_META_PROPERTY_INF_FLAG_REQD,
.prompt = N_("Remote"),
.property_type = &_pt_gobject_string,
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_DESTINATION_PORT,
.is_cli_option = TRUE,
.property_alias = "destination-port",
.prompt = N_("Destination port"),
.property_type = &_pt_gobject_int,
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_TOS,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
.value_infos = INT_VALUE_INFOS (
{
.value.u64 = 1,
.nick = "inherit",
},
),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_TTL,
.property_type = &_pt_gobject_int,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int,
.value_infos = INT_VALUE_INFOS (
{
.value.i64 = -1,
.nick = "inherit",
},
),
),
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_GENEVE_DF,
.property_type = &_pt_gobject_enum,
),
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GSM
static const NMMetaPropertyInfo *const property_infos_GSM[] = {
@ -9018,6 +9069,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
#define SETTING_PRETTY_NAME_DUMMY N_("Dummy settings")
#define SETTING_PRETTY_NAME_ETHTOOL N_("Ethtool settings")
#define SETTING_PRETTY_NAME_GENERIC N_("Generic settings")
#define SETTING_PRETTY_NAME_GENEVE N_("Geneve settings")
#define SETTING_PRETTY_NAME_GSM N_("GSM mobile broadband connection")
#define SETTING_PRETTY_NAME_HOSTNAME N_("Hostname settings")
#define SETTING_PRETTY_NAME_HSR N_("HSR settings")
@ -9156,6 +9208,14 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
NM_META_SETTING_VALID_PART_ITEM (GENERIC, TRUE),
),
),
SETTING_INFO (GENEVE,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
NM_META_SETTING_VALID_PART_ITEM (GENEVE, TRUE),
NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE),
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
),
),
SETTING_INFO (GSM,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),

View file

@ -499,6 +499,12 @@
#define DESCRIBE_DOC_NM_SETTING_WPAN_SHORT_ADDRESS N_("Short IEEE 802.15.4 address to be used within a restricted environment.")
#define DESCRIBE_DOC_NM_SETTING_BOND_PORT_PRIO N_("The port priority for bond active port re-selection during failover. A higher number means a higher priority in selection. The primary port has the highest priority. This option is only compatible with active-backup, balance-tlb and balance-alb modes.")
#define DESCRIBE_DOC_NM_SETTING_BOND_PORT_QUEUE_ID N_("The queue ID of this bond port. The maximum value of queue ID is the number of TX queues currently active in device.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_DESTINATION_PORT N_("Specifies the UDP destination port to communicate to the remote GENEVE tunnel endpoint.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_DF N_("Specifies how the Don't Fragment (DF) flag should be handled in the outer IP header of GENEVE tunnel packets. \"unset\" (0) (0): Don't set the DF flag, packets may be fragmented. \"set\" (1) (1): Always set the DF flag, packets will not be fragmented. \"inherit\" (2) (2): Inherit the DF flag from the inner IP header.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_ID N_("Specifies the GENEVE Network Identifier (or GENEVE Segment Identifier) to use.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_REMOTE N_("Specifies the unicast destination IP address to use in outgoing packets when communicating with the remote GENEVE tunnel endpoint.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_TOS N_("Specifies the TOS value to use in outgoing packets. The special value \"inherit\" (1) means inherit from outer packet.")
#define DESCRIBE_DOC_NM_SETTING_GENEVE_TTL N_("Specifies the time-to-live value to use in outgoing packets. The special value \"inherit\" (-1) means inherit from outer packet, 0 means auto, 1-255 are fixed values.")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DHCP N_("Whether the system hostname can be determined from DHCP on this connection. When set to \"default\" (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be \"true\" (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP N_("Whether the system hostname can be determined from reverse DNS lookup of addresses on this device. When set to \"default\" (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be \"true\" (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT N_("If set to \"true\" (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to \"false\" (0), the hostname can be set from this device even if it doesn't have the default route. When set to \"default\" (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be \"false\" (0).")

View file

@ -4,6 +4,7 @@
*/
#include "libnm-client-aux-extern/nm-default-client.h"
#include "nmcli.h"
#include "connections.h"
@ -1070,13 +1071,13 @@ const NmcMetaGenericInfo
"," NM_SETTING_DCB_SETTING_NAME "," NM_SETTING_TUN_SETTING_NAME \
"," NM_SETTING_IP_TUNNEL_SETTING_NAME "," NM_SETTING_MACSEC_SETTING_NAME \
"," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME \
"," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME \
"," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME \
"," NM_SETTING_LINK_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME \
"," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME \
"," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME \
"," NM_SETTING_HOSTNAME_SETTING_NAME "," NM_SETTING_HSR_SETTING_NAME \
"," NM_SETTING_IPVLAN_SETTING_NAME
"," NM_SETTING_GENEVE_SETTING_NAME "," NM_SETTING_VRF_SETTING_NAME \
"," NM_SETTING_WPAN_SETTING_NAME "," NM_SETTING_6LOWPAN_SETTING_NAME \
"," NM_SETTING_WIREGUARD_SETTING_NAME "," NM_SETTING_LINK_SETTING_NAME \
"," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME \
"," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME \
"," NM_SETTING_OVS_DPDK_SETTING_NAME "," NM_SETTING_HOSTNAME_SETTING_NAME \
"," NM_SETTING_HSR_SETTING_NAME "," NM_SETTING_IPVLAN_SETTING_NAME
/* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
@ -1306,6 +1307,9 @@ usage_connection_add(void)
" [source-port-min <0-65535>]\n"
" [source-port-max <0-65535>]\n"
" [destination-port <0-65535>]\n\n"
" geneve: id <GENEVE ID>\n"
" remote <IP address>\n"
" [destination-port <0-65535>]\n\n"
" wpan: [short-addr <0x0000-0xffff>]\n"
" [pan-id <0x0000-0xffff>]\n"
" [page <default|0-31>]\n"

View file

@ -629,7 +629,7 @@
alias="type"
nmcli-description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, &quot;802-3-ethernet&quot; or &quot;802-11-wireless&quot; or &quot;bluetooth&quot;, etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, &quot;vpn&quot; or &quot;bridge&quot;, etc)."
format="string"
values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-interface, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
values="6lowpan, 802-11-olpc-mesh, 802-11-wireless, 802-3-ethernet, adsl, bluetooth, bond, bridge, cdma, dummy, generic, geneve, gsm, hsr, infiniband, ip-tunnel, ipvlan, loopback, macsec, macvlan, ovs-bridge, ovs-interface, ovs-port, pppoe, team, tun, veth, vlan, vpn, vrf, vxlan, wifi-p2p, wimax, wireguard, wpan" />
<property name="interface-name"
alias="ifname"
nmcli-description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface."
@ -1110,6 +1110,36 @@
nmcli-description="Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and &apos;-&apos;, &apos;_&apos;, &apos;.&apos;. It cannot start with &apos;.&apos;. See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler. By setting this property the generic connection becomes &quot;virtual&quot;, meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler."
format="string" />
</setting>
<setting name="geneve" >
<property name="id"
alias="id"
nmcli-description="Specifies the GENEVE Network Identifier (or GENEVE Segment Identifier) to use."
format="integer"
values="0 - 16777215" />
<property name="remote"
alias="remote"
nmcli-description="Specifies the unicast destination IP address to use in outgoing packets when communicating with the remote GENEVE tunnel endpoint."
format="string" />
<property name="destination-port"
alias="destination-port"
nmcli-description="Specifies the UDP destination port to communicate to the remote GENEVE tunnel endpoint."
format="integer"
values="0 - 65535" />
<property name="tos"
nmcli-description="Specifies the TOS value to use in outgoing packets. The special value &quot;inherit&quot; (1) means inherit from outer packet."
format="integer"
values="0 - 255"
special-values="inherit (1)" />
<property name="ttl"
nmcli-description="Specifies the time-to-live value to use in outgoing packets. The special value &quot;inherit&quot; (-1) means inherit from outer packet, 0 means auto, 1-255 are fixed values."
format="integer"
values="-1 - 255"
special-values="inherit (-1)" />
<property name="df"
nmcli-description="Specifies how the Don&apos;t Fragment (DF) flag should be handled in the outer IP header of GENEVE tunnel packets. &quot;unset&quot; (0) (0): Don&apos;t set the DF flag, packets may be fragmented. &quot;set&quot; (1) (1): Always set the DF flag, packets will not be fragmented. &quot;inherit&quot; (2) (2): Inherit the DF flag from the inner IP header."
format="choice (NMSettingGeneveDf)"
values="unset (0), set (1), inherit (2)" />
</setting>
<setting name="gsm" >
<property name="auto-config"
nmcli-description="When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database."

View file

@ -29,6 +29,7 @@ SETTING_DNS_OPTION_* parent="NM.SettingDnsOption" name="SETTIN
SETTING_DUMMY_* parent="NM.SettingDummy" name="SETTING_DUMMY_(.+)"
SETTING_ETHTOOL_* parent="NM.SettingEthtool" name="SETTING_ETHTOOL_(.+)"
SETTING_GENERIC_* parent="NM.SettingGeneric" name="SETTING_GENERIC_(.+)"
SETTING_GENEVE_* parent="NM.SettingGeneve" name="SETTING_GENEVE_(.+)"
SETTING_GSM_* parent="NM.SettingGsm" name="SETTING_GSM_(.+)"
SETTING_HOSTNAME_* parent="NM.SettingHostname" name="SETTING_HOSTNAME_(.+)"
SETTING_HSR_* parent="NM.SettingHsr" name="SETTING_HSR_(.+)"
@ -114,6 +115,7 @@ DEVICE_BT_* parent="NM.DeviceBt" name="DEVICE
DEVICE_DUMMY_* parent="NM.DeviceDummy" name="DEVICE_DUMMY_(.+)"
DEVICE_ETHERNET_* parent="NM.DeviceEthernet" name="DEVICE_ETHERNET_(.+)"
DEVICE_GENERIC_* parent="NM.DeviceGeneric" name="DEVICE_GENERIC_(.+)"
DEVICE_GENEVE_* parent="NM.DeviceGeneve" name="DEVICE_GENEVE_(.+)"
DEVICE_HSR_* parent="NM.DeviceHsr" name="DEVICE_HSR_(.+)"
DEVICE_INFINIBAND_* parent="NM.DeviceInfiniband" name="DEVICE_INFINIBAND_(.+)"
DEVICE_IP_TUNNEL_* parent="NM.DeviceIPTunnel" name="DEVICE_IP_TUNNEL_(.+)"