diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2017-12-22 10:24:25 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2018-01-05 18:25:08 +0100 |
commit | da4c9e51a038279e261b896e5156308adaea4572 (patch) | |
tree | 286713127adb28f63b41cd8ef47dc4579fe1e4ed | |
parent | 686afe531ab3774cd818feda8361de74101971f5 (diff) | |
download | NetworkManager-da4c9e51a038279e261b896e5156308adaea4572.tar.gz |
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
-rw-r--r-- | clients/common/nm-meta-setting-desc.c | 8 | ||||
-rw-r--r-- | clients/common/settings-docs.c.in | 1 | ||||
-rw-r--r-- | introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml | 7 | ||||
-rw-r--r-- | libnm-core/nm-core-types-internal.h | 9 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-tunnel.c | 60 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-tunnel.h | 30 | ||||
-rw-r--r-- | libnm/libnm.ver | 3 | ||||
-rw-r--r-- | libnm/nm-device-ip-tunnel.c | 36 | ||||
-rw-r--r-- | libnm/nm-device-ip-tunnel.h | 4 | ||||
-rw-r--r-- | src/devices/nm-device-ip-tunnel.c | 43 | ||||
-rw-r--r-- | src/devices/nm-device-ip-tunnel.h | 1 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 5 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 8 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 3 | ||||
-rw-r--r-- | src/platform/tests/test-common.c | 13 | ||||
-rw-r--r-- | src/platform/tests/test-link.c | 65 |
16 files changed, 274 insertions, 22 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index b2e8b9b4a4..51e01a85ed 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -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 }; diff --git a/clients/common/settings-docs.c.in b/clients/common/settings-docs.c.in index 7725c7deaf..8f3a95763f 100644 --- a/clients/common/settings-docs.c.in +++ b/clients/common/settings-docs.c.in @@ -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.") diff --git a/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml b/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml index ef92f3a992..7c464b9478 100644 --- a/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml +++ b/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml @@ -89,6 +89,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 diff --git a/libnm-core/nm-core-types-internal.h b/libnm-core/nm-core-types-internal.h index 442a10a30f..843cf9fdf8 100644 --- a/libnm-core/nm-core-types-internal.h +++ b/libnm-core/nm-core-types-internal.h @@ -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 */ diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index fa8d4a7a24..c9cb97dfe2 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -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)); } diff --git a/libnm-core/nm-setting-ip-tunnel.h b/libnm-core/nm-setting-ip-tunnel.h index dfa6211685..efa754a8fe 100644 --- a/libnm-core/nm-setting-ip-tunnel.h +++ b/libnm-core/nm-setting-ip-tunnel.h @@ -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 diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 2014a30a52..e5ded29ac1 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -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; diff --git a/libnm/nm-device-ip-tunnel.c b/libnm/nm-device-ip-tunnel.c index e0dfc0f4e0..2f7efe9d8d 100644 --- a/libnm/nm-device-ip-tunnel.c +++ b/libnm/nm-device-ip-tunnel.c @@ -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)); } diff --git a/libnm/nm-device-ip-tunnel.h b/libnm/nm-device-ip-tunnel.h index 6d748d966b..92a83edc32 100644 --- a/libnm/nm-device-ip-tunnel.h +++ b/libnm/nm-device-ip-tunnel.h @@ -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 diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index af3cfe4c98..24ee62c3bc 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -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), diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h index 4bff6e33e8..6f1fcd756e 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/devices/nm-device-ip-tunnel.h @@ -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 diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 76285dd7d7..0aec50c9b2 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -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); diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index d1f2e0d49a..d2c0be2851 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 3266558fb0..34b1d8c0a1 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -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 { diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index df82e9163f..02c1bede01 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -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); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index ad25ea577b..bc4d848769 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -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); |