ip-tunnel: add support for tunnel flags

Implement support for IP tunnel flags. Currently only some IPv6 tunnel
flags are supported. Example:

 # nmcli connection add type ip-tunnel mode ip6ip6 \
   ip-tunnel.flags ip6-ign-encap-limit,ip6-use-orig-tclass \
   ifname abc ip-tunnel.parent ens8 ipv4.method disabled \
   ipv6.method manual ipv6.address ::8888 remote ::42

 # ip -d l
  61: abc@ens8: <NOARP,UP,LOWER_UP> mtu 1460 qdisc noqueue ...
    link/tunnel6 :: brd ::42 promiscuity 0
    ip6tnl ip6ip6 remote ::42 local :: dev ens8 encaplimit none
    hoplimit 0 tclass inherit ...

https://bugzilla.gnome.org/show_bug.cgi?id=791846
This commit is contained in:
Beniamino Galvani 2017-12-22 10:24:25 +01:00
parent 686afe531a
commit da4c9e51a0
16 changed files with 274 additions and 22 deletions

View file

@ -6149,6 +6149,14 @@ static const NMMetaPropertyInfo *const property_infos_IP_TUNNEL[] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_MTU,
.property_type = &_pt_gobject_mtu,
),
PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_FLAGS,
.property_type = &_pt_gobject_enum,
.property_typ_data = DEFINE_PROPERTY_TYP_DATA (
PROPERTY_TYP_DATA_SUBTYPE (gobject_enum,
.get_gtype = nm_ip_tunnel_flags_get_type,
),
),
),
NULL
};

View file

@ -194,6 +194,7 @@
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_PARENT N_("The interface name of the parent device of this device. Normally NULL, but if the \"p_key\" property is set, then you must specify the base device by setting either this property or \"mac-address\".")
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_TRANSPORT_MODE N_("The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\".")
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT N_("How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels.")
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLAGS N_("Tunnel flags. Currently the following values are supported: NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS (0x2), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV (0x8), NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only for IPv6 tunnels.")
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_FLOW_LABEL N_("The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.")
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_INPUT_KEY N_("The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.")
#define DESCRIBE_DOC_NM_SETTING_IP_TUNNEL_LOCAL N_("The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.")

View file

@ -88,6 +88,13 @@
-->
<property name="FlowLabel" type="u" access="read"/>
<!--
Flags:
Tunnel flags.
-->
<property name="Flags" type="u" access="read"/>
<!--
PropertiesChanged:
@properties: A dictionary mapping property names to variant boxed values

View file

@ -27,4 +27,13 @@ typedef struct {
guint32 to;
} NMVlanQosMapping;
#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \
( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL \
| NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV \
| NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY \
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK \
)
#endif /* NM_CORE_TYPES_INTERNAL_H */

View file

@ -49,6 +49,7 @@ typedef struct {
guint encapsulation_limit;
guint flow_label;
guint mtu;
guint32 flags;
} NMSettingIPTunnelPrivate;
enum {
@ -65,6 +66,7 @@ enum {
PROP_ENCAPSULATION_LIMIT,
PROP_FLOW_LABEL,
PROP_MTU,
PROP_FLAGS,
LAST_PROP
};
@ -285,6 +287,24 @@ nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting)
return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->mtu;
}
/*
* nm_setting_ip_tunnel_get_flags:
* @setting: the #NMSettingIPTunnel
*
* Returns the #NMSettingIPTunnel:flags property of the setting.
*
* Returns: the tunnel flags
*
* Since: 1.12
**/
NMIPTunnelFlags
nm_setting_ip_tunnel_get_flags (NMSettingIPTunnel *setting)
{
g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NM_IP_TUNNEL_FLAG_NONE);
return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->flags;
}
/*****************************************************************************/
static gboolean
@ -292,6 +312,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting);
int family = AF_UNSPEC;
guint32 flags;
switch (priv->mode) {
case NM_IP_TUNNEL_MODE_IPIP:
@ -419,6 +440,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
flags = priv->flags;
if (NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_IPIP6, NM_IP_TUNNEL_MODE_IP6IP6))
flags &= (guint32) (~_NM_IP_TUNNEL_FLAG_ALL_IP6TNL);
if (flags) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("some flags are invalid for the select mode: %s"),
nm_utils_enum_to_str (nm_ip_tunnel_flags_get_type (), flags));
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
NM_SETTING_IP_TUNNEL_FLAGS);
return FALSE;
}
return TRUE;
}
@ -491,6 +526,9 @@ set_property (GObject *object, guint prop_id,
case PROP_MTU:
priv->mtu = g_value_get_uint (value);
break;
case PROP_FLAGS:
priv->flags = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -541,6 +579,9 @@ get_property (GObject *object, guint prop_id,
case PROP_MTU:
g_value_set_uint (value, priv->mtu);
break;
case PROP_FLAGS:
g_value_set_uint (value, priv->flags);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -773,4 +814,23 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class)
G_PARAM_CONSTRUCT |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingIPTunnel:flags:
*
* Tunnel flags. Currently the following values are supported:
* %NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS,
* %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL, %NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV,
* %NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY, %NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK.
* They are valid only for IPv6 tunnels.
*
* Since: 1.12
**/
g_object_class_install_property
(object_class, PROP_FLAGS,
g_param_spec_uint (NM_SETTING_IP_TUNNEL_FLAGS, "", "",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
}

View file

@ -50,6 +50,7 @@ G_BEGIN_DECLS
#define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit"
#define NM_SETTING_IP_TUNNEL_FLOW_LABEL "flow-label"
#define NM_SETTING_IP_TUNNEL_MTU "mtu"
#define NM_SETTING_IP_TUNNEL_FLAGS "flags"
/**
* NMSettingIPTunnel:
@ -67,6 +68,33 @@ typedef struct {
gpointer padding[4];
} NMSettingIPTunnelClass;
/*
* NMIPTunnelFlags:
* @NM_IP_TUNNEL_FLAG_NONE: no flag
* @NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT: don't add encapsulation limit
* if one isn't present in inner packet
* @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS: copy the traffic class field
* from the inner packet
* @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL: copy the flowlabel from the
* inner packet
* @NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV: used for Mobile IPv6
* @NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY: copy DSCP from the outer packet
* @NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK: copy fwmark from inner packet
*
* IP tunnel flags.
*
* Since: 1.12
*/
typedef enum { /*< flags, prefix=NM_IP_TUNNEL_FLAG >*/
NM_IP_TUNNEL_FLAG_NONE = 0x0,
NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT = 0x1,
NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS = 0x2,
NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL = 0x4,
NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV = 0x8,
NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY = 0x10,
NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK = 0x20,
} NMIPTunnelFlags;
NM_AVAILABLE_IN_1_2
GType nm_setting_ip_tunnel_get_type (void);
@ -97,6 +125,8 @@ NM_AVAILABLE_IN_1_2
guint nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting);
NM_AVAILABLE_IN_1_2
guint nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting);
NM_AVAILABLE_IN_1_12
NMIPTunnelFlags nm_setting_ip_tunnel_get_flags (NMSettingIPTunnel *setting);
G_END_DECLS

View file

@ -1345,6 +1345,9 @@ global:
nm_client_checkpoint_rollback_async;
nm_client_checkpoint_rollback_finish;
nm_client_get_checkpoints;
nm_device_ip_tunnel_get_flags;
nm_ip_tunnel_flags_get_type;
nm_setting_ip_tunnel_get_flags;
nm_setting_vpn_get_data_keys;
nm_setting_vpn_get_secret_keys;
} libnm_1_10_0;

View file

@ -46,6 +46,7 @@ typedef struct {
char *output_key;
guint8 encap_limit;
guint32 flow_label;
guint32 flags;
} NMDeviceIPTunnelPrivate;
enum {
@ -61,6 +62,7 @@ enum {
PROP_OUTPUT_KEY,
PROP_ENCAPSULATION_LIMIT,
PROP_FLOW_LABEL,
PROP_FLAGS,
LAST_PROP
};
@ -242,6 +244,22 @@ nm_device_ip_tunnel_get_flow_label (NMDeviceIPTunnel *device)
return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->flow_label;
}
/**
* nm_device_ip_tunnel_get_flags:
* @device: a #NMDeviceIPTunnel
*
* Returns: the tunnel flags
*
* Since: 1.12
**/
NMIPTunnelFlags
nm_device_ip_tunnel_get_flags (NMDeviceIPTunnel *device)
{
g_return_val_if_fail (NM_IS_DEVICE_IP_TUNNEL (device), NM_IP_TUNNEL_FLAG_NONE);
return NM_DEVICE_IP_TUNNEL_GET_PRIVATE (device)->flags;
}
static gboolean
connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
{
@ -286,6 +304,7 @@ init_dbus (NMObject *object)
{ NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, &priv->output_key },
{ NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, &priv->encap_limit },
{ NM_DEVICE_IP_TUNNEL_FLOW_LABEL, &priv->flow_label },
{ NM_DEVICE_IP_TUNNEL_FLAGS, &priv->flags },
{ NULL },
};
@ -352,6 +371,9 @@ get_property (GObject *object,
case PROP_FLOW_LABEL:
g_value_set_uint (value, nm_device_ip_tunnel_get_flow_label (device));
break;
case PROP_FLAGS:
g_value_set_uint (value, nm_device_ip_tunnel_get_flags (device));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -536,4 +558,18 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *bond_class)
0, (1 << 20) - 1, 0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDeviceIPTunnel:flags:
*
* Tunnel flags.
*
* Since: 1.12
**/
g_object_class_install_property
(object_class, PROP_FLAGS,
g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLAGS, "", "",
0, G_MAXUINT32, 0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}

View file

@ -26,6 +26,7 @@
#endif
#include "nm-device.h"
#include "nm-setting-ip-tunnel.h"
G_BEGIN_DECLS
@ -47,6 +48,7 @@ G_BEGIN_DECLS
#define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key"
#define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit"
#define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label"
#define NM_DEVICE_IP_TUNNEL_FLAGS "flags"
/**
* NMDeviceIPTunnel:
@ -87,6 +89,8 @@ NM_AVAILABLE_IN_1_2
guint8 nm_device_ip_tunnel_get_encapsulation_limit (NMDeviceIPTunnel *device);
NM_AVAILABLE_IN_1_2
guint nm_device_ip_tunnel_get_flow_label (NMDeviceIPTunnel *device);
NM_AVAILABLE_IN_1_12
NMIPTunnelFlags nm_device_ip_tunnel_get_flags (NMDeviceIPTunnel *device);
G_END_DECLS

View file

@ -55,6 +55,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceIPTunnel,
PROP_OUTPUT_KEY,
PROP_ENCAPSULATION_LIMIT,
PROP_FLOW_LABEL,
PROP_FLAGS,
);
typedef struct {
@ -69,6 +70,7 @@ typedef struct {
char *output_key;
guint8 encap_limit;
guint32 flow_label;
NMIPTunnelFlags flags;
} NMDeviceIPTunnelPrivate;
struct _NMDeviceIPTunnel {
@ -86,6 +88,30 @@ G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE)
/*****************************************************************************/
static guint32
ip6tnl_flags_setting_to_plat (NMIPTunnelFlags flags)
{
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT == IP6_TNL_F_IGN_ENCAP_LIMIT);
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS == IP6_TNL_F_USE_ORIG_TCLASS);
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL == IP6_TNL_F_USE_ORIG_FLOWLABEL);
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV == IP6_TNL_F_MIP6_DEV);
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY == IP6_TNL_F_RCV_DSCP_COPY);
G_STATIC_ASSERT (NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK == IP6_TNL_F_USE_ORIG_FWMARK);
/* XXX: "accidentally", the numeric values correspond.
* For flags added in the future, that might no longer
* be the case. */
return flags & _NM_IP_TUNNEL_FLAG_ALL_IP6TNL;
}
static NMIPTunnelFlags
ip6tnl_flags_plat_to_setting (guint32 flags)
{
return flags & ((guint32) _NM_IP_TUNNEL_FLAG_ALL_IP6TNL);
}
/*****************************************************************************/
static gboolean
address_equal_pp (int family, const char *a, const char *b)
{
@ -129,6 +155,7 @@ update_properties_from_ifindex (NMDevice *device, int ifindex)
guint8 ttl = 0, tos = 0, encap_limit = 0;
gboolean pmtud = FALSE;
guint32 flow_label = 0;
NMIPTunnelFlags flags = NM_IP_TUNNEL_FLAG_NONE;
char *key;
if (ifindex <= 0) {
@ -246,6 +273,7 @@ clear:
tos = lnk->tclass;
encap_limit = lnk->encap_limit;
flow_label = lnk->flow_label;
flags = ip6tnl_flags_plat_to_setting (lnk->flags);
} else
g_return_if_reached ();
@ -307,6 +335,11 @@ out:
priv->flow_label = flow_label;
_notify (self, PROP_FLOW_LABEL);
}
if (priv->flags != flags) {
priv->flags = flags;
_notify (self, PROP_FLAGS);
}
}
static void
@ -685,6 +718,7 @@ create_and_realize (NMDevice *device,
lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel);
lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel);
lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6;
lnk_ip6tnl.flags = ip6tnl_flags_setting_to_plat (nm_setting_ip_tunnel_get_flags (s_ip_tunnel));
plerr = nm_platform_link_ip6tnl_add (nm_device_get_platform (device), iface, &lnk_ip6tnl, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
@ -814,6 +848,9 @@ get_property (GObject *object, guint prop_id,
case PROP_FLOW_LABEL:
g_value_set_uint (value, priv->flow_label);
break;
case PROP_FLAGS:
g_value_set_uint (value, priv->flags);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -959,6 +996,12 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_FLAGS] =
g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLAGS, "", "",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),

View file

@ -41,6 +41,7 @@
#define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key"
#define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit"
#define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label"
#define NM_DEVICE_IP_TUNNEL_FLAGS "flags"
/* defined in the parent class, but exposed on D-Bus by the subclass. */
#define NM_DEVICE_IP_TUNNEL_PARENT NM_DEVICE_PARENT

View file

@ -36,6 +36,7 @@
#include <linux/if_link.h>
#include <linux/if_tun.h>
#include <linux/if_tunnel.h>
#include <linux/ip6_tunnel.h>
#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <libudev.h>
@ -1292,6 +1293,7 @@ _parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data)
[IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
[IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
[IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
[IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
};
struct nlattr *tb[IFLA_IPTUN_MAX + 1];
int err;
@ -1326,6 +1328,8 @@ _parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data)
}
if (tb[IFLA_IPTUN_PROTO])
props->proto = nla_get_u8 (tb[IFLA_IPTUN_PROTO]);
if (tb[IFLA_IPTUN_FLAGS])
props->flags = nla_get_u32 (tb[IFLA_IPTUN_FLAGS]);
return obj;
}
@ -5386,6 +5390,7 @@ link_ip6tnl_add (NMPlatform *platform,
& IP6_FLOWINFO_TCLASS_MASK;
NLA_PUT_U32 (nlmsg, IFLA_IPTUN_FLOWINFO, htonl (flowinfo));
NLA_PUT_U8 (nlmsg, IFLA_IPTUN_PROTO, props->proto);
NLA_PUT_U32 (nlmsg, IFLA_IPTUN_FLAGS, props->flags);
nla_nest_end (nlmsg, data);
nla_nest_end (nlmsg, info);

View file

@ -4751,6 +4751,7 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi
"%s" /* encap limit */
"%s" /* flow label */
"%s" /* proto */
" flags 0x%x"
"",
nm_sprintf_buf (str_remote, " remote %s", nm_utils_inet6_ntop (&lnk->remote, str_remote1)),
nm_sprintf_buf (str_local, " local %s", nm_utils_inet6_ntop (&lnk->local, str_local1)),
@ -4759,7 +4760,8 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi
lnk->tclass == 1 ? " tclass inherit" : nm_sprintf_buf (str_tclass, " tclass 0x%x", lnk->tclass),
nm_sprintf_buf (str_encap, " encap-limit %u", lnk->encap_limit),
nm_sprintf_buf (str_flow, " flow-label 0x05%x", lnk->flow_label),
nm_sprintf_buf (str_proto, " proto %u", lnk->proto));
nm_sprintf_buf (str_proto, " proto %u", lnk->proto),
(guint) lnk->flags);
return buf;
}
@ -5575,7 +5577,8 @@ nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState
obj->tclass,
obj->encap_limit,
obj->proto,
obj->flow_label);
obj->flow_label,
obj->flags);
}
int
@ -5590,6 +5593,7 @@ nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6
NM_CMP_FIELD (a, b, encap_limit);
NM_CMP_FIELD (a, b, flow_label);
NM_CMP_FIELD (a, b, proto);
NM_CMP_FIELD (a, b, flags);
return 0;
}

View file

@ -25,6 +25,7 @@
#include <linux/if.h>
#include <linux/if_addr.h>
#include <linux/if_link.h>
#include <linux/ip6_tunnel.h>
#include "nm-dbus-interface.h"
#include "nm-core-types-internal.h"
@ -32,6 +33,7 @@
#include "nm-core-utils.h"
#include "nm-setting-vlan.h"
#include "nm-setting-wired.h"
#include "nm-setting-ip-tunnel.h"
#define NM_TYPE_PLATFORM (nm_platform_get_type ())
#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
@ -606,6 +608,7 @@ typedef struct {
guint8 encap_limit;
guint8 proto;
guint flow_label;
guint32 flags;
} NMPlatformLnkIp6Tnl;
typedef struct {

View file

@ -1283,6 +1283,10 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform,
const NMPlatformLink *pllink = NULL;
gboolean success;
char buffer[INET6_ADDRSTRLEN];
char encap[20];
char tclass[20];
gboolean encap_ignore;
gboolean tclass_inherit;
g_assert (nm_utils_is_valid_iface_name (name, NULL));
@ -1308,15 +1312,18 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform,
g_assert_not_reached ();
}
success = !nmtstp_run_command ("ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %02x encaplimit %u flowlabel %x",
encap_ignore = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_IGN_ENCAP_LIMIT);
tclass_inherit = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS);
success = !nmtstp_run_command ("ip -6 tunnel add %s mode %s %s local %s remote %s ttl %u tclass %s encaplimit %s flowlabel %x",
name,
mode,
dev,
nm_utils_inet6_ntop (&lnk->local, NULL),
nm_utils_inet6_ntop (&lnk->remote, buffer),
lnk->ttl,
lnk->tclass,
lnk->encap_limit,
tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass),
encap_ignore ? "none" : nm_sprintf_buf (encap, "%u", lnk->encap_limit),
lnk->flow_label);
if (success)
pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_IP6TNL, 100);

View file

@ -760,13 +760,27 @@ test_software_detect (gconstpointer user_data)
gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_tunnel", NULL) != 0;
}
lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::15");
lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::16");
lnk_ip6tnl.parent_ifindex = ifindex_parent;
lnk_ip6tnl.tclass = 20;
lnk_ip6tnl.encap_limit = 6;
lnk_ip6tnl.flow_label = 1337;
lnk_ip6tnl.proto = IPPROTO_IPV6;
switch (test_data->test_mode) {
case 0:
lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::15");
lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::16");
lnk_ip6tnl.parent_ifindex = ifindex_parent;
lnk_ip6tnl.tclass = 20;
lnk_ip6tnl.encap_limit = 6;
lnk_ip6tnl.flow_label = 1337;
lnk_ip6tnl.proto = IPPROTO_IPV6;
break;
case 1:
lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::17");
lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::18");
lnk_ip6tnl.parent_ifindex = ifindex_parent;
lnk_ip6tnl.tclass = 0;
lnk_ip6tnl.encap_limit = 0;
lnk_ip6tnl.flow_label = 1338;
lnk_ip6tnl.proto = IPPROTO_IPV6;
lnk_ip6tnl.flags = IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS;
break;
}
if (!nmtstp_link_ip6tnl_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) {
if (gracefully_skip) {
@ -930,15 +944,31 @@ test_software_detect (gconstpointer user_data)
case NM_LINK_TYPE_IP6TNL: {
const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl;
g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent);
nmtst_assert_ip6_address (&plnk->local, "fd01::15");
nmtst_assert_ip6_address (&plnk->remote, "fd01::16");
g_assert_cmpint (plnk->ttl, ==, 0);
g_assert_cmpint (plnk->tclass, ==, 20);
g_assert_cmpint (plnk->encap_limit, ==, 6);
g_assert_cmpint (plnk->flow_label, ==, 1337);
g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6);
switch (test_data->test_mode) {
case 0:
g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent);
nmtst_assert_ip6_address (&plnk->local, "fd01::15");
nmtst_assert_ip6_address (&plnk->remote, "fd01::16");
g_assert_cmpint (plnk->ttl, ==, 0);
g_assert_cmpint (plnk->tclass, ==, 20);
g_assert_cmpint (plnk->encap_limit, ==, 6);
g_assert_cmpint (plnk->flow_label, ==, 1337);
g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6);
break;
case 1:
g_assert (plnk == nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent);
nmtst_assert_ip6_address (&plnk->local, "fd01::17");
nmtst_assert_ip6_address (&plnk->remote, "fd01::18");
g_assert_cmpint (plnk->ttl, ==, 0);
g_assert_cmpint (plnk->flow_label, ==, 1338);
g_assert_cmpint (plnk->proto, ==, IPPROTO_IPV6);
g_assert_cmpint (plnk->flags & 0xFFFF, /* ignore kernel internal flags */
==,
IP6_TNL_F_IGN_ENCAP_LIMIT | IP6_TNL_F_USE_ORIG_TCLASS);
break;
}
break;
}
case NM_LINK_TYPE_IPIP: {
@ -2528,7 +2558,8 @@ _nmtstp_setup_tests (void)
g_test_add_func ("/link/external", test_external);
test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
test_software_detect_add ("/link/software/detect/ip6tnl", NM_LINK_TYPE_IP6TNL, 0);
test_software_detect_add ("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
test_software_detect_add ("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1);
test_software_detect_add ("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0);
test_software_detect_add ("/link/software/detect/macvlan", NM_LINK_TYPE_MACVLAN, 0);
test_software_detect_add ("/link/software/detect/macvtap", NM_LINK_TYPE_MACVTAP, 0);