diff --git a/docs/api/network-manager-docs.xml b/docs/api/network-manager-docs.xml index caff6fa4fc..9916427399 100644 --- a/docs/api/network-manager-docs.xml +++ b/docs/api/network-manager-docs.xml @@ -183,6 +183,7 @@ + diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml index a957f469c8..719d8998a1 100644 --- a/docs/libnm/libnm-docs.xml +++ b/docs/libnm/libnm-docs.xml @@ -378,6 +378,7 @@ print ("NetworkManager version " + client.get_version())]]> + diff --git a/introspection/meson.build b/introspection/meson.build index 16bb5ed423..7703b46983 100644 --- a/introspection/meson.build +++ b/introspection/meson.build @@ -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', diff --git a/introspection/org.freedesktop.NetworkManager.Device.Geneve.xml b/introspection/org.freedesktop.NetworkManager.Device.Geneve.xml new file mode 100644 index 0000000000..8d24c5a578 --- /dev/null +++ b/introspection/org.freedesktop.NetworkManager.Device.Geneve.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/po/POTFILES.in b/po/POTFILES.in index 0bf3ca1c25..b66ca45263 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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 diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index 1585836281..24755a5f00 100644 --- a/src/core/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -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); diff --git a/src/core/devices/nm-device-geneve.c b/src/core/devices/nm-device-geneve.c new file mode 100644 index 0000000000..0968a2fb9b --- /dev/null +++ b/src/core/devices/nm-device-geneve.c @@ -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;); diff --git a/src/core/devices/nm-device-geneve.h b/src/core/devices/nm-device-geneve.h new file mode 100644 index 0000000000..d0a44e9dbb --- /dev/null +++ b/src/core/devices/nm-device-geneve.h @@ -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__ */ diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 434683d6b4..f3f09db18c 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -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 */ diff --git a/src/core/meson.build b/src/core/meson.build index 26d27f96e2..4a3dfd8e11 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -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', diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index 3d2bc79304..e9850ea6e5 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -2107,6 +2107,13 @@ 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; diff --git a/src/libnm-client-impl/meson.build b/src/libnm-client-impl/meson.build index b49366292f..3352ebfee0 100644 --- a/src/libnm-client-impl/meson.build +++ b/src/libnm-client-impl/meson.build @@ -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', diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c index b81ac6e506..f13835269e 100644 --- a/src/libnm-client-impl/nm-client.c +++ b/src/libnm-client-impl/nm-client.c @@ -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" diff --git a/src/libnm-client-impl/nm-device-geneve.c b/src/libnm-client-impl/nm-device-geneve.c new file mode 100644 index 0000000000..415e978d16 --- /dev/null +++ b/src/libnm-client-impl/nm-device-geneve.c @@ -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); +} diff --git a/src/libnm-client-impl/nm-device.c b/src/libnm-client-impl/nm-device.c index 1712efa5bb..9203fd6f13 100644 --- a/src/libnm-client-impl/nm-device.c +++ b/src/libnm-client-impl/nm-device.c @@ -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: diff --git a/src/libnm-client-impl/nm-libnm-utils.c b/src/libnm-client-impl/nm-libnm-utils.c index c2fa2addef..9f1b515c2e 100644 --- a/src/libnm-client-impl/nm-libnm-utils.c +++ b/src/libnm-client-impl/nm-libnm-utils.c @@ -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, diff --git a/src/libnm-client-impl/nm-libnm-utils.h b/src/libnm-client-impl/nm-libnm-utils.h index 7dcf8c18dc..27b77b6009 100644 --- a/src/libnm-client-impl/nm-libnm-utils.h +++ b/src/libnm-client-impl/nm-libnm-utils.h @@ -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; diff --git a/src/libnm-client-public/NetworkManager.h b/src/libnm-client-public/NetworkManager.h index 2d1c56521e..880bac6ed7 100644 --- a/src/libnm-client-public/NetworkManager.h +++ b/src/libnm-client-public/NetworkManager.h @@ -115,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" diff --git a/src/libnm-client-public/meson.build b/src/libnm-client-public/meson.build index b8ae9cce07..5aa6de2518 100644 --- a/src/libnm-client-public/meson.build +++ b/src/libnm-client-public/meson.build @@ -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', diff --git a/src/libnm-client-public/nm-autoptr.h b/src/libnm-client-public/nm-autoptr.h index f21f2970c8..12379fe1aa 100644 --- a/src/libnm-client-public/nm-autoptr.h +++ b/src/libnm-client-public/nm-autoptr.h @@ -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) diff --git a/src/libnm-client-public/nm-device-geneve.h b/src/libnm-client-public/nm-device-geneve.h new file mode 100644 index 0000000000..5f7c92b30b --- /dev/null +++ b/src/libnm-client-public/nm-device-geneve.h @@ -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 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__ */ diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c index d7e19627df..9ce72b4145 100644 --- a/src/libnm-core-impl/nm-connection.c +++ b/src/libnm-core-impl/nm-connection.c @@ -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, diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h index 42bff04ae0..8d34066f0e 100644 --- a/src/libnm-core-public/nm-dbus-interface.h +++ b/src/libnm-core-public/nm-dbus-interface.h @@ -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; /** diff --git a/vapi/NM-1.0.metadata b/vapi/NM-1.0.metadata index 6f1720ad7a..3084b7c289 100644 --- a/vapi/NM-1.0.metadata +++ b/vapi/NM-1.0.metadata @@ -115,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_(.+)"