veth: add support to configure veth interfaces

NetworkManager is now able to configure veth interfaces throught the
NMSettingVeth. Veth interfaces only have "peer" property.

In order to support Veth interfaces in NetworkManager the design need
to pass the following requirements:

 * Veth setting only has "peer" attribute.
 * Ethernet profiles must be applicable to Veth interfaces.
 * When creating a veth interface, the peer will be managed by
   NetworkManager but will not have a profile.
 * Veth connection can reapply only if the peer has not been modified.
 * In order to modify the veth peer, NetworkManager must deactivate the
   connection and create a new one with peer modified.

In general, it should support the basis of veth interfaces but without
breaking any existing feature or use case. The users that are using veth
interfaces as ethernet should not notice anything changed unless they
specified the veth peer setting.

Creating a Veth interface in NetworkManager is useful even without the
support for namespaces for some use cases, e.g "connecting one side of
the veth to an OVS bridge and the other side to a Linux bridge" this is
done when using OVN kubernetes [1][2]. In addition, it would provide
persistent configuration and rollback support for Veth interfaces.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1885605
[2] https://bugzilla.redhat.com/show_bug.cgi?id=1894139

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
This commit is contained in:
Fernando Fernandez Mancera 2020-11-12 21:58:13 +01:00 committed by Thomas Haller
parent de1d849f17
commit cd0cf9229d
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
26 changed files with 603 additions and 43 deletions

View file

@ -969,6 +969,7 @@ libnm_core_lib_h_pub_real = \
libnm-core/nm-setting-team.h \
libnm-core/nm-setting-tun.h \
libnm-core/nm-setting-user.h \
libnm-core/nm-setting-veth.h \
libnm-core/nm-setting-vlan.h \
libnm-core/nm-setting-vpn.h \
libnm-core/nm-setting-vrf.h \
@ -1044,6 +1045,7 @@ libnm_core_lib_c_settings_real = \
libnm-core/nm-setting-team.c \
libnm-core/nm-setting-tun.c \
libnm-core/nm-setting-user.c \
libnm-core/nm-setting-veth.c \
libnm-core/nm-setting-vlan.c \
libnm-core/nm-setting-vpn.c \
libnm-core/nm-setting-vrf.c \
@ -1363,6 +1365,7 @@ libnm_lib_h_pub_real = \
libnm/nm-device-ppp.h \
libnm/nm-device-team.h \
libnm/nm-device-tun.h \
libnm/nm-device-veth.h \
libnm/nm-device-vlan.h \
libnm/nm-device-vrf.h \
libnm/nm-device-vxlan.h \
@ -1427,6 +1430,7 @@ libnm_lib_c_real = \
libnm/nm-device-ppp.c \
libnm/nm-device-team.c \
libnm/nm-device-tun.c \
libnm/nm-device-veth.c \
libnm/nm-device-vlan.c \
libnm/nm-device-vrf.c \
libnm/nm-device-vxlan.c \

View file

@ -858,30 +858,30 @@ const NmcMetaGenericInfo
/*****************************************************************************/
#define NMC_FIELDS_SETTINGS_NAMES_ALL \
NM_SETTING_CONNECTION_SETTING_NAME \
"," NM_SETTING_MATCH_SETTING_NAME "," NM_SETTING_WIRED_SETTING_NAME \
"," NM_SETTING_802_1X_SETTING_NAME "," NM_SETTING_WIRELESS_SETTING_NAME \
"," NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "," NM_SETTING_IP4_CONFIG_SETTING_NAME \
"," NM_SETTING_IP6_CONFIG_SETTING_NAME "," NM_SETTING_SERIAL_SETTING_NAME \
"," NM_SETTING_WIFI_P2P_SETTING_NAME "," NM_SETTING_PPP_SETTING_NAME \
"," NM_SETTING_PPPOE_SETTING_NAME "," NM_SETTING_ADSL_SETTING_NAME \
"," NM_SETTING_GSM_SETTING_NAME "," NM_SETTING_CDMA_SETTING_NAME \
"," NM_SETTING_BLUETOOTH_SETTING_NAME "," NM_SETTING_OLPC_MESH_SETTING_NAME \
"," NM_SETTING_VPN_SETTING_NAME "," NM_SETTING_INFINIBAND_SETTING_NAME \
"," NM_SETTING_BOND_SETTING_NAME "," NM_SETTING_VLAN_SETTING_NAME \
"," NM_SETTING_BRIDGE_SETTING_NAME "," NM_SETTING_BRIDGE_PORT_SETTING_NAME \
"," NM_SETTING_TEAM_SETTING_NAME "," NM_SETTING_TEAM_PORT_SETTING_NAME \
"," NM_SETTING_OVS_BRIDGE_SETTING_NAME "," NM_SETTING_OVS_INTERFACE_SETTING_NAME \
"," NM_SETTING_OVS_PATCH_SETTING_NAME "," NM_SETTING_OVS_PORT_SETTING_NAME \
"," 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_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 \
#define NMC_FIELDS_SETTINGS_NAMES_ALL \
NM_SETTING_CONNECTION_SETTING_NAME \
"," NM_SETTING_MATCH_SETTING_NAME "," NM_SETTING_WIRED_SETTING_NAME \
"," NM_SETTING_VETH_SETTING_NAME "," NM_SETTING_802_1X_SETTING_NAME \
"," NM_SETTING_WIRELESS_SETTING_NAME "," NM_SETTING_WIRELESS_SECURITY_SETTING_NAME \
"," NM_SETTING_IP4_CONFIG_SETTING_NAME "," NM_SETTING_IP6_CONFIG_SETTING_NAME \
"," NM_SETTING_SERIAL_SETTING_NAME "," NM_SETTING_WIFI_P2P_SETTING_NAME \
"," NM_SETTING_PPP_SETTING_NAME "," NM_SETTING_PPPOE_SETTING_NAME \
"," NM_SETTING_ADSL_SETTING_NAME "," NM_SETTING_GSM_SETTING_NAME \
"," NM_SETTING_CDMA_SETTING_NAME "," NM_SETTING_BLUETOOTH_SETTING_NAME \
"," NM_SETTING_OLPC_MESH_SETTING_NAME "," NM_SETTING_VPN_SETTING_NAME \
"," NM_SETTING_INFINIBAND_SETTING_NAME "," NM_SETTING_BOND_SETTING_NAME \
"," NM_SETTING_VLAN_SETTING_NAME "," NM_SETTING_BRIDGE_SETTING_NAME \
"," NM_SETTING_BRIDGE_PORT_SETTING_NAME "," NM_SETTING_TEAM_SETTING_NAME \
"," NM_SETTING_TEAM_PORT_SETTING_NAME "," NM_SETTING_OVS_BRIDGE_SETTING_NAME \
"," NM_SETTING_OVS_INTERFACE_SETTING_NAME "," NM_SETTING_OVS_PATCH_SETTING_NAME \
"," NM_SETTING_OVS_PORT_SETTING_NAME "," 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_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_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {

View file

@ -986,6 +986,11 @@
</setting>
<setting name="user" >
</setting>
<setting name="veth" >
<property name="peer"
alias="peer"
description="This property specifies the peer interface name of the veth. This property is mandatory." />
</setting>
<setting name="vlan" >
<property name="parent"
alias="dev"

View file

@ -7084,6 +7084,19 @@ static const NMMetaPropertyInfo *const property_infos_TUN[] = {
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VETH
static const NMMetaPropertyInfo *const property_infos_VETH[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_VETH_PEER,
.is_cli_option = TRUE,
.property_alias = "peer",
.inf_flags = NM_META_PROPERTY_INF_FLAG_REQD,
.prompt = N_("veth peer"),
.property_type = &_pt_gobject_string,
),
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VLAN
static const NMMetaPropertyInfo *const property_infos_VLAN[] = {
@ -7984,6 +7997,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
#define SETTING_PRETTY_NAME_TEAM_PORT N_("Team port")
#define SETTING_PRETTY_NAME_TUN N_("Tun device")
#define SETTING_PRETTY_NAME_USER N_("User settings")
#define SETTING_PRETTY_NAME_VETH N_("Veth connection")
#define SETTING_PRETTY_NAME_VLAN N_("VLAN connection")
#define SETTING_PRETTY_NAME_VPN N_("VPN connection")
#define SETTING_PRETTY_NAME_VRF N_("VRF connection")
@ -8224,6 +8238,14 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
.setting_init_fcn = _setting_init_fcn_tun,
),
SETTING_INFO_EMPTY (USER),
SETTING_INFO (VETH,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
NM_META_SETTING_VALID_PART_ITEM (VETH, TRUE),
NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE),
NM_META_SETTING_VALID_PART_ITEM (ETHTOOL, FALSE),
),
),
SETTING_INFO (VLAN,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),

View file

@ -374,6 +374,7 @@
#define DESCRIBE_DOC_NM_SETTING_TUN_PI N_("If TRUE the interface will prepend a 4 byte header describing the physical interface to the packets.")
#define DESCRIBE_DOC_NM_SETTING_TUN_VNET_HDR N_("If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network header.")
#define DESCRIBE_DOC_NM_SETTING_USER_DATA N_("A dictionary of key/value pairs with user data. This data is ignored by NetworkManager and can be used at the users discretion. The keys only support a strict ascii format, but the values can be arbitrary UTF8 strings up to a certain length.")
#define DESCRIBE_DOC_NM_SETTING_VETH_PEER N_("This property specifies the peer interface name of the veth. This property is mandatory.")
#define DESCRIBE_DOC_NM_SETTING_VLAN_EGRESS_PRIORITY_MAP N_("For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities. The mapping is given in the format \"from:to\" where both \"from\" and \"to\" are unsigned integers, ie \"7:3\".")
#define DESCRIBE_DOC_NM_SETTING_VLAN_FLAGS N_("One or more flags which control the behavior and features of the VLAN interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, but it used to be 0. To preserve backward compatibility, the default-value in the D-Bus API continues to be 0 and a missing property on D-Bus is still considered as 0.")
#define DESCRIBE_DOC_NM_SETTING_VLAN_ID N_("The VLAN identifier that the interface created by this connection should be assigned. The valid range is from 0 to 4094, without the reserved id 4095.")

View file

@ -350,6 +350,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-setting-team.xml"/>
<xi:include href="xml/nm-setting-tun.xml"/>
<xi:include href="xml/nm-setting-user.xml"/>
<xi:include href="xml/nm-setting-veth.xml"/>
<xi:include href="xml/nm-setting-vlan.xml"/>
<xi:include href="xml/nm-setting-vpn.xml"/>
<xi:include href="xml/nm-setting-vrf.xml"/>
@ -388,6 +389,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-device-ppp.xml"/>
<xi:include href="xml/nm-device-team.xml"/>
<xi:include href="xml/nm-device-tun.xml"/>
<xi:include href="xml/nm-device-veth.xml"/>
<xi:include href="xml/nm-device-vlan.xml"/>
<xi:include href="xml/nm-device-vrf.xml"/>
<xi:include href="xml/nm-device-vxlan.xml"/>

View file

@ -59,6 +59,7 @@ libnm_core_headers = files(
'nm-setting-team.h',
'nm-setting-tun.h',
'nm-setting-user.h',
'nm-setting-veth.h',
'nm-setting-vlan.h',
'nm-setting-vpn.h',
'nm-setting-vrf.h',
@ -161,6 +162,7 @@ libnm_core_settings_sources = files(
'nm-setting-team.c',
'nm-setting-tun.c',
'nm-setting-user.c',
'nm-setting-veth.c',
'nm-setting-vlan.c',
'nm-setting-vpn.c',
'nm-setting-vrf.c',

View file

@ -2642,6 +2642,7 @@ nm_connection_is_virtual(NMConnection *connection)
NM_SETTING_OVS_PORT_SETTING_NAME,
NM_SETTING_TEAM_SETTING_NAME,
NM_SETTING_TUN_SETTING_NAME,
NM_SETTING_VETH_SETTING_NAME,
NM_SETTING_VLAN_SETTING_NAME,
NM_SETTING_VRF_SETTING_NAME,
NM_SETTING_VXLAN_SETTING_NAME,

View file

@ -60,6 +60,7 @@
#include "nm-setting-team-port.h"
#include "nm-setting-team.h"
#include "nm-setting-tun.h"
#include "nm-setting-veth.h"
#include "nm-setting-vlan.h"
#include "nm-setting-vpn.h"
#include "nm-setting-vrf.h"

View file

@ -54,6 +54,7 @@ typedef struct _NMSettingTeam NMSettingTeam;
typedef struct _NMSettingTeamPort NMSettingTeamPort;
typedef struct _NMSettingTun NMSettingTun;
typedef struct _NMSettingUser NMSettingUser;
typedef struct _NMSettingVeth NMSettingVeth;
typedef struct _NMSettingVlan NMSettingVlan;
typedef struct _NMSettingVpn NMSettingVpn;
typedef struct _NMSettingVrf NMSettingVrf;

View file

@ -0,0 +1,194 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-setting-veth.h"
#include <stdlib.h>
#include "nm-utils.h"
#include "nm-setting-connection.h"
#include "nm-setting-private.h"
#include "nm-connection-private.h"
/**
* SECTION:nm-setting-veth
* @short_description: Describes connection properties for veth interfaces
*
* The #NMSettingVeth object is a #NMSetting subclass that describes properties
* necessary for connection to veth interfaces.
**/
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, );
typedef struct {
char *peer;
} NMSettingVethPrivate;
/**
* NMSettingVeth:
*
* Veth Settings
*/
struct _NMSettingVeth {
NMSetting parent;
NMSettingVethPrivate _priv;
};
struct _NMSettingVethClass {
NMSettingClass parent;
};
G_DEFINE_TYPE(NMSettingVeth, nm_setting_veth, NM_TYPE_SETTING)
#define NM_SETTING_VETH_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMSettingVeth, NM_IS_SETTING_VETH, NMSetting)
/*****************************************************************************/
/**
* nm_setting_veth_get_peer:
* @setting: the #NMSettingVeth
*
* Returns: the #NMSettingVeth:peer property of the setting
*
* Since: 1.30
**/
const char *
nm_setting_veth_get_peer(NMSettingVeth *setting)
{
g_return_val_if_fail(NM_IS_SETTING_VETH(setting), NULL);
return NM_SETTING_VETH_GET_PRIVATE(setting)->peer;
}
/*****************************************************************************/
static gboolean
verify(NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting);
if (!priv->peer) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_PROPERTY,
_("property is not specified"));
g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER);
return FALSE;
}
if (!nm_utils_ifname_valid(priv->peer, NMU_IFACE_KERNEL, NULL)) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("'%s' is not a valid interface name"),
priv->peer);
g_prefix_error(error, "%s.%s: ", NM_SETTING_VETH_SETTING_NAME, NM_SETTING_VETH_PEER);
return FALSE;
}
if (!_nm_connection_verify_required_interface_name(connection, error))
return FALSE;
return TRUE;
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMSettingVeth * setting = NM_SETTING_VETH(object);
NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting);
switch (prop_id) {
case PROP_PEER:
g_value_set_string(value, priv->peer);
break;
}
}
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NMSettingVeth * setting = NM_SETTING_VETH(object);
NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting);
switch (prop_id) {
case PROP_PEER:
g_free(priv->peer);
priv->peer = g_value_dup_string(value);
break;
}
}
/*****************************************************************************/
static void
nm_setting_veth_init(NMSettingVeth *setting)
{}
/**
* nm_setting_veth_new:
*
* Creates a new #NMSettingVeth object with default values.
*
* Returns: (transfer full): the new empty #NMSettingVeth object
*
* Since: 1.30
**/
NMSetting *
nm_setting_veth_new(void)
{
return g_object_new(NM_TYPE_SETTING_VETH, NULL);
}
static void
finalize(GObject *object)
{
NMSettingVeth * setting = NM_SETTING_VETH(object);
NMSettingVethPrivate *priv = NM_SETTING_VETH_GET_PRIVATE(setting);
g_free(priv->peer);
G_OBJECT_CLASS(nm_setting_veth_parent_class)->finalize(object);
}
static void
nm_setting_veth_class_init(NMSettingVethClass *klass)
{
GObjectClass * object_class = G_OBJECT_CLASS(klass);
NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
g_type_class_add_private(klass, sizeof(NMSettingVethPrivate));
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->finalize = finalize;
setting_class->verify = verify;
/**
* NMSettingVeth:peer:
*
* This property specifies the peer interface name of the veth. This
* property is mandatory.
*
* Since: 1.30
**/
obj_properties[PROP_PEER] = g_param_spec_string(NM_SETTING_VETH_PEER,
"",
"",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE
| G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_VETH);
}

View file

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#ifndef __NM_SETTING_VETH_H__
#define __NM_SETTING_VETH_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_VETH (nm_setting_veth_get_type())
#define NM_SETTING_VETH(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_VETH, NMSettingVeth))
#define NM_IS_SETTING_VETH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_VETH))
#define NM_IS_SETTING_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_VETH))
#define NM_SETTING_VETH_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_VETH, NMSettingVethClass))
#define NM_SETTING_VETH_SETTING_NAME "veth"
#define NM_SETTING_VETH_PEER "peer"
typedef struct _NMSettingVethClass NMSettingVethClass;
NM_AVAILABLE_IN_1_30
GType nm_setting_veth_get_type(void);
NM_AVAILABLE_IN_1_30
NMSetting *nm_setting_veth_new(void);
NM_AVAILABLE_IN_1_30
const char *nm_setting_veth_get_peer(NMSettingVeth *setting);
G_END_DECLS
#endif /* __NM_SETTING_VETH_H__ */

View file

@ -88,6 +88,7 @@
#include "nm-setting-team-port.h"
#include "nm-setting-tun.h"
#include "nm-setting-user.h"
#include "nm-setting-veth.h"
#include "nm-setting-vlan.h"
#include "nm-setting-vpn.h"
#include "nm-setting-vrf.h"

View file

@ -1758,6 +1758,7 @@ global:
libnm_1_30_0 {
global:
nm_device_veth_get_type;
nm_keyfile_handler_data_fail_with_error;
nm_keyfile_handler_data_get_context;
nm_keyfile_handler_data_warn_get;
@ -1778,5 +1779,8 @@ global:
nm_setting_ovs_external_ids_get_type;
nm_setting_ovs_external_ids_new;
nm_setting_ovs_external_ids_set_data;
nm_setting_veth_get_peer;
nm_setting_veth_get_type;
nm_setting_veth_new;
nm_utils_print;
} libnm_1_28_0;

View file

@ -40,6 +40,7 @@ libnm_headers = files(
'nm-device-ppp.h',
'nm-device-team.h',
'nm-device-tun.h',
'nm-device-veth.h',
'nm-device-vlan.h',
'nm-device-vrf.h',
'nm-device-vxlan.h',
@ -106,6 +107,7 @@ libnm_sources = files(
'nm-device-ppp.c',
'nm-device-team.c',
'nm-device-tun.c',
'nm-device-veth.c',
'nm-device-vlan.c',
'nm-device-vrf.c',
'nm-device-vxlan.c',

View file

@ -53,6 +53,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceOvsPort, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDevicePpp, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceTeam, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceTun, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceVeth, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceVlan, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceVxlan, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMDeviceWifi, g_object_unref)
@ -98,6 +99,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingTeam, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingTeamPort, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingTun, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingUser, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingVeth, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingVlan, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingVpn, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(NMSettingVxlan, g_object_unref)

View file

@ -12,8 +12,10 @@
#include "nm-setting-connection.h"
#include "nm-setting-wired.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-veth.h"
#include "nm-utils.h"
#include "nm-object-private.h"
#include "nm-device-veth.h"
/*****************************************************************************/
@ -173,9 +175,12 @@ connection_compatible(NMDevice *device, NMConnection *connection, GError **error
->connection_compatible(device, connection, error))
return FALSE;
if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)) {
if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)
|| nm_connection_is_type(connection, NM_SETTING_WIRED_SETTING_NAME)
|| (nm_connection_is_type(connection, NM_SETTING_VETH_SETTING_NAME)
&& NM_IS_DEVICE_VETH(device))) {
/* NOP */
} else if (!nm_connection_is_type(connection, NM_SETTING_WIRED_SETTING_NAME)) {
} else {
g_set_error_literal(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
@ -307,13 +312,6 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
}
}
/* TODO: implemented Veth. */
const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth = NML_DBUS_META_IFACE_INIT(
NM_DBUS_INTERFACE_DEVICE_VETH,
NULL,
NML_DBUS_META_INTERFACE_PRIO_NONE,
NML_DBUS_META_IFACE_DBUS_PROPERTIES(NML_DBUS_META_PROPERTY_INIT_TODO("Peer", "o"), ), );
const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_wired = NML_DBUS_META_IFACE_INIT_PROP(
NM_DBUS_INTERFACE_DEVICE_WIRED,
nm_device_ethernet_get_type,

129
libnm/nm-device-veth.c Normal file
View file

@ -0,0 +1,129 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-device-veth.h"
#include "nm-setting-connection.h"
#include "nm-setting-veth.h"
#include "nm-setting-wired.h"
#include "nm-utils.h"
#include "nm-device-ethernet.h"
#include "nm-object-private.h"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PEER, );
typedef struct {
char *peer;
} NMDeviceVethPrivate;
struct _NMDeviceVeth {
NMDeviceEthernet parent;
NMDeviceVethPrivate _priv;
};
struct _NMDeviceVethClass {
NMDeviceEthernetClass parent;
};
G_DEFINE_TYPE(NMDeviceVeth, nm_device_veth, NM_TYPE_DEVICE_ETHERNET)
#define NM_DEVICE_VETH_GET_PRIVATE(self) \
_NM_GET_PRIVATE(self, NMDeviceVeth, NM_IS_DEVICE_VETH, NMObject, NMDevice)
/*****************************************************************************/
/**
* nm_device_veth_get_peer:
* @device: a #NMDeviceVeth
*
* Returns: the device's peer name
*
* Since: 1.30
**/
const char *
nm_device_veth_get_peer(NMDeviceVeth *device)
{
g_return_val_if_fail(NM_IS_DEVICE_VETH(device), NULL);
return _nml_coerce_property_str_not_empty(NM_DEVICE_VETH_GET_PRIVATE(device)->peer);
}
static GType
get_setting_type(NMDevice *device)
{
return NM_TYPE_SETTING_VETH;
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMDeviceVeth *device = NM_DEVICE_VETH(object);
switch (prop_id) {
case PROP_PEER:
g_value_set_string(value, nm_device_veth_get_peer(device));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
nm_device_veth_init(NMDeviceVeth *device)
{}
static void
finalize(GObject *object)
{
NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE(object);
g_free(priv->peer);
G_OBJECT_CLASS(nm_device_veth_parent_class)->finalize(object);
}
const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_veth = NML_DBUS_META_IFACE_INIT_PROP(
NM_DBUS_INTERFACE_DEVICE_VETH,
nm_device_veth_get_type,
NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_20,
NML_DBUS_META_IFACE_DBUS_PROPERTIES(
NML_DBUS_META_PROPERTY_INIT_S("peer", PROP_PEER, NMDeviceVeth, _priv.peer), ), );
static void
nm_device_veth_class_init(NMDeviceVethClass *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, NMDeviceVeth);
device_class->get_setting_type = get_setting_type;
/**
* NMDeviceVeth:peer:
*
* The device's peer name.
*
* Since: 1.30
**/
obj_properties[PROP_PEER] = g_param_spec_string(NM_DEVICE_VETH_PEER,
"",
"",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
_nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_veth);
}

41
libnm/nm-device-veth.h Normal file
View file

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#ifndef __NM_DEVICE_VETH_H__
#define __NM_DEVICE_VETH_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_VETH (nm_device_veth_get_type())
#define NM_DEVICE_VETH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_VETH, NMDeviceVeth))
#define NM_DEVICE_VETH_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_VETH, NMDeviceVethClass))
#define NM_IS_DEVICE_VETH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_VETH))
#define NM_IS_DEVICE_VETH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_VETH))
#define NM_DEVICE_VETH_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_VETH, NMDeviceVethClass))
#define NM_DEVICE_VETH_PEER "peer"
/**
* NMDeviceVeth:
*/
typedef struct _NMDeviceVethClass NMDeviceVethClass;
NM_AVAILABLE_IN_1_30
GType nm_device_veth_get_type(void);
NM_AVAILABLE_IN_1_30
const char *nm_device_veth_get_peer(NMDeviceVeth *device);
G_END_DECLS
#endif /* __NM_DEVICE_VETH_H__ */

View file

@ -36,6 +36,7 @@ typedef struct _NMDeviceOvsPort NMDeviceOvsPort;
typedef struct _NMDevicePpp NMDevicePpp;
typedef struct _NMDeviceTeam NMDeviceTeam;
typedef struct _NMDeviceTun NMDeviceTun;
typedef struct _NMDeviceVeth NMDeviceVeth;
typedef struct _NMDeviceVlan NMDeviceVlan;
typedef struct _NMDeviceVrf NMDeviceVrf;
typedef struct _NMDeviceVxlan NMDeviceVxlan;

View file

@ -1002,6 +1002,7 @@
<listitem><para><literal>team</literal></para></listitem>
<listitem><para><literal>team-slave</literal> (deprecated for ethernet with master)</para></listitem>
<listitem><para><literal>tun</literal></para></listitem>
<listitem><para><literal>veth</literal></para></listitem>
<listitem><para><literal>vlan</literal></para></listitem>
<listitem><para><literal>vpn</literal></para></listitem>
<listitem><para><literal>vrf</literal></para></listitem>

View file

@ -95,6 +95,7 @@ libnm-core/nm-setting-team-port.c
libnm-core/nm-setting-team.c
libnm-core/nm-setting-tun.c
libnm-core/nm-setting-user.c
libnm-core/nm-setting-veth.c
libnm-core/nm-setting-vlan.c
libnm-core/nm-setting-vrf.c
libnm-core/nm-setting-vpn.c
@ -130,6 +131,7 @@ libnm/nm-device-ovs-interface.c
libnm/nm-device-ovs-port.c
libnm/nm-device-team.c
libnm/nm-device-tun.c
libnm/nm-device-veth.c
libnm/nm-device-vlan.c
libnm/nm-device-vrf.c
libnm/nm-device-vxlan.c
@ -165,6 +167,7 @@ src/devices/nm-device-infiniband.c
src/devices/nm-device-ip-tunnel.c
src/devices/nm-device-macvlan.c
src/devices/nm-device-tun.c
src/devices/nm-device-veth.c
src/devices/nm-device-vlan.c
src/devices/nm-device-vrf.c
src/devices/nm-device-vxlan.c

View file

@ -46,6 +46,7 @@
#include "nm-setting-team.h"
#include "nm-setting-tun.h"
#include "nm-setting-user.h"
#include "nm-setting-veth.h"
#include "nm-setting-vlan.h"
#include "nm-setting-vpn.h"
#include "nm-setting-vrf.h"
@ -419,6 +420,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_USER_SETTING_NAME,
.get_setting_gtype = nm_setting_user_get_type,
},
[NM_META_SETTING_TYPE_VETH] =
{
.meta_type = NM_META_SETTING_TYPE_VETH,
.setting_priority = NM_SETTING_PRIORITY_HW_BASE,
.setting_name = NM_SETTING_VETH_SETTING_NAME,
.get_setting_gtype = nm_setting_veth_get_type,
},
[NM_META_SETTING_TYPE_VLAN] =
{
.meta_type = NM_META_SETTING_TYPE_VLAN,

View file

@ -143,6 +143,7 @@ typedef enum {
NM_META_SETTING_TYPE_TEAM_PORT,
NM_META_SETTING_TYPE_TUN,
NM_META_SETTING_TYPE_USER,
NM_META_SETTING_TYPE_VETH,
NM_META_SETTING_TYPE_VLAN,
NM_META_SETTING_TYPE_VPN,
NM_META_SETTING_TYPE_VRF,

View file

@ -34,6 +34,7 @@
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-udev-aux/nm-udev-utils.h"
#include "nm-device-veth.h"
#define _NMLOG_DEVICE_TYPE NMDeviceEthernet
#include "nm-device-logging.h"
@ -347,7 +348,9 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError *
->check_connection_compatible(device, connection, error))
return FALSE;
if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)) {
if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)
|| (nm_connection_is_type(connection, NM_SETTING_VETH_SETTING_NAME)
&& NM_IS_DEVICE_VETH(device))) {
s_wired = nm_connection_get_setting_wired(connection);
} else {
s_wired =
@ -1360,6 +1363,9 @@ wake_on_lan_enable(NMDevice *device)
s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED);
if (NM_IS_DEVICE_VETH(device))
return FALSE;
if (s_wired) {
wol = nm_setting_wired_get_wake_on_lan(s_wired);
password = nm_setting_wired_get_wake_on_lan_password(s_wired);
@ -1493,6 +1499,12 @@ act_stage3_ip_config_start(NMDevice * device,
{
NMSettingConnection *s_con;
const char * connection_type;
int ifindex;
ifindex = nm_device_get_ifindex(device);
if (ifindex <= 0)
return NM_ACT_STAGE_RETURN_FAILURE;
if (addr_family == AF_INET) {
s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
@ -1803,7 +1815,7 @@ static void
link_changed(NMDevice *device, const NMPlatformLink *pllink)
{
NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->link_changed(device, pllink);
if (pllink->initialized)
if (!NM_IS_DEVICE_VETH(device) && pllink->initialized)
_update_s390_subchannels((NMDeviceEthernet *) device);
}

View file

@ -7,11 +7,13 @@
#include <stdlib.h>
#include "nm-core-internal.h"
#include "nm-device-veth.h"
#include "nm-device-private.h"
#include "nm-manager.h"
#include "platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-veth.h"
#define _NMLOG_DEVICE_TYPE NMDeviceVeth
#include "nm-device-logging.h"
@ -42,9 +44,10 @@ update_properties(NMDevice *device)
ifindex = nm_device_get_ifindex(device);
if (!nm_platform_link_veth_get_properties(nm_device_get_platform(device),
ifindex,
&peer_ifindex))
if (ifindex <= 0
|| !nm_platform_link_veth_get_properties(nm_device_get_platform(device),
ifindex,
&peer_ifindex))
peer_ifindex = 0;
nm_device_parent_set_ifindex(device, peer_ifindex);
@ -71,6 +74,81 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink)
update_properties(device);
}
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);
NMSettingVeth *s_veth;
int r;
s_veth = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VETH);
if (!s_veth) {
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_CREATION_FAILED,
"Profile %s (%s) is not a suitable veth profile",
nm_connection_get_id(connection),
nm_connection_get_uuid(connection));
return FALSE;
}
r = nm_platform_link_veth_add(nm_device_get_platform(device),
iface,
nm_setting_veth_get_peer(s_veth),
out_plink);
if (r < 0) {
g_set_error(error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create veth interface '%s' for '%s': %s",
iface,
nm_connection_get_id(connection),
nm_strerror(r));
return FALSE;
}
return TRUE;
}
/*****************************************************************************/
static NMDeviceCapabilities
get_generic_capabilities(NMDevice *device)
{
return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE;
}
static gboolean
complete_connection(NMDevice * device,
NMConnection * connection,
const char * specific_object,
NMConnection *const *existing_connections,
GError ** error)
{
NMSettingVeth *s_veth;
nm_utils_complete_generic(nm_device_get_platform(device),
connection,
NM_SETTING_VETH_SETTING_NAME,
existing_connections,
NULL,
_("Veth connection"),
"veth",
NULL,
TRUE);
s_veth = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VETH);
if (!s_veth) {
s_veth = (NMSettingVeth *) nm_setting_veth_new();
nm_connection_add_setting(connection, NM_SETTING(s_veth));
}
return TRUE;
}
/*****************************************************************************/
static void
@ -136,6 +214,9 @@ nm_device_veth_class_init(NMDeviceVethClass *klass)
device_class->can_unmanaged_external_down = can_unmanaged_external_down;
device_class->link_changed = link_changed;
device_class->parent_changed_notify = parent_changed_notify;
device_class->create_and_realize = create_and_realize;
device_class->complete_connection = complete_connection;
device_class->get_generic_capabilities = get_generic_capabilities;
obj_properties[PROP_PEER] = g_param_spec_string(NM_DEVICE_VETH_PEER,
"",
@ -171,8 +252,10 @@ create_device(NMDeviceFactory * factory,
NULL);
}
NM_DEVICE_FACTORY_DEFINE_INTERNAL(VETH,
Veth,
veth,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_VETH),
factory_class->create_device = create_device;);
NM_DEVICE_FACTORY_DEFINE_INTERNAL(
VETH,
Veth,
veth,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_VETH)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_VETH_SETTING_NAME),
factory_class->create_device = create_device;);