From 403b545ac6cf9ee6afd34280e677525ccb0dfd01 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 27 Jun 2018 14:38:11 +0200 Subject: [PATCH 01/11] core: fix wrong check of gretap hardware length GRETAP have an Ethernet-like hardware address. Fixes: e2270040c0a25bee1549dda9054cca482b896819 --- src/nm-core-utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 50e107ecd..a659fea56 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -3008,7 +3008,6 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, out_iid->id_u8[0] |= 0x02; return TRUE; case NM_LINK_TYPE_GRE: - case NM_LINK_TYPE_GRETAP: /* Hardware address is the network-endian IPv4 address */ g_return_val_if_fail (hwaddr_len == 4, FALSE); addr = * (guint32 *) hwaddr; From 052d76cf824bc86b870338a80e08d87eb9f75f35 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 27 Jun 2018 17:16:11 +0200 Subject: [PATCH 02/11] platform: fix attribute size in link_gre_add() Input and output flags are 16 bit. Fixes: 91bf0efaa7dbfed84954192a449f6770d20105c1 --- src/platform/nm-linux-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index f8f68550d..721501555 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -5368,8 +5368,8 @@ link_gre_add (NMPlatform *platform, NLA_PUT_U8 (nlmsg, IFLA_GRE_PMTUDISC, !!props->path_mtu_discovery); NLA_PUT_U32 (nlmsg, IFLA_GRE_IKEY, htonl (props->input_key)); NLA_PUT_U32 (nlmsg, IFLA_GRE_OKEY, htonl (props->output_key)); - NLA_PUT_U32 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); - NLA_PUT_U32 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); + NLA_PUT_U16 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); + NLA_PUT_U16 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); nla_nest_end (nlmsg, data); nla_nest_end (nlmsg, info); From 2ac5860a064e99587751e6cffb0b30e60e0566db Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 28 May 2018 17:42:56 +0200 Subject: [PATCH 03/11] platform: avoid double log messages Certain platform operations are logged both in nm-platform.c and nm-linux-platform.c, resulting in duplicate messages. Drop log prints from the latter. --- src/platform/nm-linux-platform.c | 87 -------------------------------- src/platform/nm-platform.c | 12 +++-- 2 files changed, 9 insertions(+), 90 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 721501555..1da6c68a3 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -233,8 +233,6 @@ G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1)); } \ } G_STMT_END -#define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s" - /****************************************************************** * Forward declarations and enums ******************************************************************/ @@ -4906,8 +4904,6 @@ link_set_netns (NMPlatform *platform, { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - _LOGD ("link: move link %d to network namespace with fd %d", ifindex, netns_fd); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, @@ -5107,10 +5103,6 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size if (!address || !length) g_return_val_if_reached (NM_PLATFORM_ERROR_BUG); - _LOGD ("link: change %d: address: %s (%lu bytes)", ifindex, - (mac = nm_utils_hwaddr_ntoa (address, length)), - (unsigned long) length); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, @@ -5132,8 +5124,6 @@ link_set_name (NMPlatform *platform, int ifindex, const char *name) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - _LOGD ("link: change %d: name: %s", ifindex, name); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, @@ -5169,8 +5159,6 @@ link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; - _LOGD ("link: change %d: mtu: %u", ifindex, (unsigned) mtu); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, @@ -5294,10 +5282,6 @@ vlan_add (NMPlatform *platform, G_STATIC_ASSERT (NM_VLAN_FLAG_MVRP == (guint32) VLAN_FLAG_MVRP); vlan_flags &= (guint32) NM_VLAN_FLAGS_ALL; - - _LOGD ("link: add vlan '%s', parent %d, vlan id %d, flags %X", - name, parent, vlan_id, (unsigned) vlan_flags); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5333,14 +5317,6 @@ link_gre_add (NMPlatform *platform, nm_auto_nlmsg struct nl_msg *nlmsg = NULL; struct nlattr *info; struct nlattr *data; - char buffer[INET_ADDRSTRLEN]; - - _LOGD (LOG_FMT_IP_TUNNEL, - "gre", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, @@ -5388,16 +5364,8 @@ link_ip6tnl_add (NMPlatform *platform, nm_auto_nlmsg struct nl_msg *nlmsg = NULL; struct nlattr *info; struct nlattr *data; - char buffer[INET_ADDRSTRLEN]; guint32 flowinfo; - _LOGD (LOG_FMT_IP_TUNNEL, - "ip6tnl", - name, - props->parent_ifindex, - nm_utils_inet6_ntop (&props->local, NULL), - nm_utils_inet6_ntop (&props->remote, buffer)); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5450,14 +5418,6 @@ link_ipip_add (NMPlatform *platform, nm_auto_nlmsg struct nl_msg *nlmsg = NULL; struct nlattr *info; struct nlattr *data; - char buffer[INET_ADDRSTRLEN]; - - _LOGD (LOG_FMT_IP_TUNNEL, - "ipip", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, @@ -5503,11 +5463,6 @@ link_macsec_add (NMPlatform *platform, struct nlattr *info; struct nlattr *data; - _LOGD ("adding macsec '%s' parent %u sci %llx", - name, - parent, - (unsigned long long) props->sci); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5565,12 +5520,6 @@ link_macvlan_add (NMPlatform *platform, struct nlattr *info; struct nlattr *data; - _LOGD ("adding %s '%s' parent %u mode %u", - props->tap ? "macvtap" : "macvlan", - name, - parent, - props->mode); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5612,14 +5561,6 @@ link_sit_add (NMPlatform *platform, nm_auto_nlmsg struct nl_msg *nlmsg = NULL; struct nlattr *info; struct nlattr *data; - char buffer[INET_ADDRSTRLEN]; - - _LOGD (LOG_FMT_IP_TUNNEL, - "sit", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, @@ -5723,9 +5664,6 @@ link_vxlan_add (NMPlatform *platform, g_return_val_if_fail (props, FALSE); - _LOGD ("link: add vxlan '%s', parent %d, vxlan id %d", - name, props->parent_ifindex, props->id); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5912,9 +5850,6 @@ link_vlan_change (NMPlatform *platform, guint new_n_egress_map = 0; gs_free NMVlanQosMapping *new_ingress_map = NULL; gs_free NMVlanQosMapping *new_egress_map = NULL; - char s_flags[64]; - char s_ingress[256]; - char s_egress[256]; obj_cache = nmp_cache_lookup_link (nm_platform_get_cache (platform), ifindex); if ( !obj_cache @@ -5945,26 +5880,6 @@ link_vlan_change (NMPlatform *platform, &new_egress_map, &new_n_egress_map); - _LOGD ("link: change %d: vlan:%s%s%s", - ifindex, - flags_mask - ? nm_sprintf_buf (s_flags, " flags 0x%x/0x%x", (unsigned) flags_set, (unsigned) flags_mask) - : "", - new_n_ingress_map - ? nm_platform_vlan_qos_mapping_to_string (" ingress-qos-map", - new_ingress_map, - new_n_ingress_map, - s_ingress, - sizeof (s_ingress)) - : "", - new_n_egress_map - ? nm_platform_vlan_qos_mapping_to_string (" egress-qos-map", - new_egress_map, - new_n_egress_map, - s_egress, - sizeof (s_egress)) - : ""); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, @@ -5991,8 +5906,6 @@ link_enslave (NMPlatform *platform, int master, int slave) nm_auto_nlmsg struct nl_msg *nlmsg = NULL; int ifindex = slave; - _LOGD ("link: change %d: enslave: master %d", slave, master); - nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 1fcb4d79c..f78a77eec 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -986,7 +986,7 @@ nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd) if (!pllink) return FALSE; - _LOGD ("link: ifindex %d changing network namespace to %d", ifindex, netns_fd); + _LOGD ("link: move link %d to network namespace with fd %d", ifindex, netns_fd); return klass->link_set_netns (self, ifindex, netns_fd); } @@ -1355,15 +1355,18 @@ nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolea NMPlatformError nm_platform_link_set_address (NMPlatform *self, int ifindex, gconstpointer address, size_t length) { + gs_free char *mac = NULL; + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (ifindex > 0, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (address, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (length > 0, NM_PLATFORM_ERROR_BUG); - _LOGD ("link: setting %s (%d) hardware address", + _LOGD ("link: setting %s (%d) hardware address to %s", nm_strquote_a (20, nm_platform_link_get_name (self, ifindex)), - ifindex); + ifindex, + (mac = nm_utils_hwaddr_ntoa (address, length))); return klass->link_set_address (self, ifindex, address, length); } @@ -2437,6 +2440,9 @@ _infiniband_add_add_or_delete (NMPlatform *self, if (!klass->infiniband_partition_add (self, parent, p_key, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; } else { + _LOGD ("link: deleting infiniband partition %s for parent '%s' (%d), key %d", + name, parent_link->name, parent, p_key); + if (!klass->infiniband_partition_delete (self, parent, p_key)) return NM_PLATFORM_ERROR_UNSPECIFIED; } From 0d5e712f73d9d791e6239d51e26c6a6204c244be Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 27 Jun 2018 13:57:13 +0200 Subject: [PATCH 04/11] platform: fix linux-platform link_*_add() functions signature They should return a gboolean, not an int. --- src/platform/nm-linux-platform.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 1da6c68a3..42c1601fb 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -5266,7 +5266,7 @@ link_get_dev_id (NMPlatform *platform, int ifindex) 16, 0, G_MAXUINT16, 0); } -static int +static gboolean vlan_add (NMPlatform *platform, const char *name, int parent, @@ -5308,7 +5308,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_gre_add (NMPlatform *platform, const char *name, const NMPlatformLnkGre *props, @@ -5355,7 +5355,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_ip6tnl_add (NMPlatform *platform, const char *name, const NMPlatformLnkIp6Tnl *props, @@ -5409,7 +5409,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_ipip_add (NMPlatform *platform, const char *name, const NMPlatformLnkIpIp *props, @@ -5452,7 +5452,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_macsec_add (NMPlatform *platform, const char *name, int parent, @@ -5509,7 +5509,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_macvlan_add (NMPlatform *platform, const char *name, int parent, @@ -5552,7 +5552,7 @@ nla_put_failure: g_return_val_if_reached (FALSE); } -static int +static gboolean link_sit_add (NMPlatform *platform, const char *name, const NMPlatformLnkSit *props, From 4b46c74af71044712fb384df92ea05ae3b4a5dbf Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 27 Jun 2018 14:06:11 +0200 Subject: [PATCH 05/11] platform: fix printing macvtap links --- src/platform/nm-platform.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index f78a77eec..57de3368d 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -5236,7 +5236,8 @@ nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, char *buf, g return buf; g_snprintf (buf, len, - "macvlan mode %u %s", + "%s mode %u %s", + lnk->tap ? "macvtap" : "macvlan", lnk->mode, lnk->no_promisc ? "not-promisc" : "promisc"); return buf; From cdad8c6df926fc60e7e500009f43b3d6638f15ff Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 27 Jun 2018 14:22:30 +0200 Subject: [PATCH 06/11] platform: uniform logging for link-add functions Print all the platform-lnk attributes in a consistent manner. --- src/platform/nm-platform.c | 66 ++++++++++++-------------------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 57de3368d..f580f167e 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -74,8 +74,6 @@ G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OF } \ } G_STMT_END -#define LOG_FMT_IP_TUNNEL "adding %s '%s' parent %u local %s remote %s" - /*****************************************************************************/ static guint signals[_NM_PLATFORM_SIGNAL_ID_LAST] = { 0 }; @@ -902,7 +900,7 @@ nm_platform_link_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("link: adding link '%s' of type '%s' (%d)" + _LOGD ("link: adding link '%s': %s (%d)" "%s%s" /* address */ "%s%s" /* veth peer */ "", @@ -2000,8 +1998,9 @@ nm_platform_link_vlan_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("link: adding vlan '%s' parent %d vlanid %d vlanflags %x", + _LOGD ("link: adding link '%s': vlan parent %d vlanid %d vlanflags %x", name, parent, vlanid, vlanflags); + if (!klass->vlan_add (self, name, parent, vlanid, vlanflags, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; @@ -2032,8 +2031,9 @@ nm_platform_link_vxlan_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("link: adding vxlan '%s' parent %d id %d", - name, props->parent_ifindex, props->id); + _LOGD ("link: adding link '%s': %s", + name, nm_platform_lnk_vxlan_to_string (props, NULL, 0)); + if (!klass->link_vxlan_add (self, name, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; @@ -2084,8 +2084,9 @@ nm_platform_link_tun_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("link: adding tun '%s' %s", + _LOGD ("link: adding link '%s': %s", name, nm_platform_lnk_tun_to_string (props, b, sizeof (b))); + if (!klass->link_tun_add (self, name, props, out_link, out_fd)) return NM_PLATFORM_ERROR_UNSPECIFIED; return NM_PLATFORM_ERROR_SUCCESS; @@ -2116,7 +2117,7 @@ nm_platform_link_6lowpan_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("adding 6lowpan '%s' parent %u", name, parent); + _LOGD ("adding link '%s': 6lowpan parent %u", name, parent); if (!klass->link_6lowpan_add (self, name, parent, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2378,7 +2379,6 @@ nm_platform_link_gre_add (NMPlatform *self, const NMPlatformLink **out_link) { NMPlatformError plerr; - char buffer[INET_ADDRSTRLEN]; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); @@ -2389,12 +2389,8 @@ nm_platform_link_gre_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD (LOG_FMT_IP_TUNNEL, - "gre", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_gre_to_string (props, NULL, 0)); if (!klass->link_gre_add (self, name, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2543,7 +2539,6 @@ nm_platform_link_ip6tnl_add (NMPlatform *self, const NMPlatformLink **out_link) { NMPlatformError plerr; - char buffer[INET6_ADDRSTRLEN]; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); @@ -2554,12 +2549,8 @@ nm_platform_link_ip6tnl_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD (LOG_FMT_IP_TUNNEL, - "ip6tnl", - name, - props->parent_ifindex, - nm_utils_inet6_ntop (&props->local, NULL), - nm_utils_inet6_ntop (&props->remote, buffer)); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_ip6tnl_to_string (props, NULL, 0)); if (!klass->link_ip6tnl_add (self, name, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2582,7 +2573,6 @@ nm_platform_link_ipip_add (NMPlatform *self, const NMPlatformLink **out_link) { NMPlatformError plerr; - char buffer[INET_ADDRSTRLEN]; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); @@ -2593,12 +2583,8 @@ nm_platform_link_ipip_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD (LOG_FMT_IP_TUNNEL, - "ipip", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_ipip_to_string (props, NULL, 0)); if (!klass->link_ipip_add (self, name, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2633,10 +2619,8 @@ nm_platform_link_macsec_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("adding macsec '%s' parent %u sci %llx", - name, - parent, - (unsigned long long) props->sci); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_macsec_to_string (props, NULL, 0)); if (!klass->link_macsec_add (self, name, parent, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2673,11 +2657,8 @@ nm_platform_link_macvlan_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD ("adding %s '%s' parent %u mode %u", - props->tap ? "macvtap" : "macvlan", - name, - parent, - props->mode); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_macvlan_to_string (props, NULL, 0)); if (!klass->link_macvlan_add (self, name, parent, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; @@ -2700,7 +2681,6 @@ nm_platform_link_sit_add (NMPlatform *self, const NMPlatformLink **out_link) { NMPlatformError plerr; - char buffer[INET_ADDRSTRLEN]; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); @@ -2711,12 +2691,8 @@ nm_platform_link_sit_add (NMPlatform *self, if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; - _LOGD (LOG_FMT_IP_TUNNEL, - "sit", - name, - props->parent_ifindex, - nm_utils_inet4_ntop (props->local, NULL), - nm_utils_inet4_ntop (props->remote, buffer)); + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_sit_to_string (props, NULL, 0)); if (!klass->link_sit_add (self, name, props, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; From 4c2862b9589ceee651a69709681a546c09eb9607 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 Jun 2018 10:45:35 +0200 Subject: [PATCH 07/11] platform: add gretap tunnels support Add platform support for GRETAP tunnels (Virtual L2 tunnel interface GRE over IPv4) partially reusing the existing GRE code. --- src/nm-types.h | 1 + src/platform/nm-linux-platform.c | 21 +++++++++++--- src/platform/nm-platform.c | 14 ++++++++-- src/platform/nm-platform.h | 2 ++ src/platform/nmp-object.c | 11 ++++++++ src/platform/tests/test-common.c | 14 ++++++++-- src/platform/tests/test-link.c | 47 ++++++++++++++++++++++++-------- 7 files changed, 89 insertions(+), 21 deletions(-) diff --git a/src/nm-types.h b/src/nm-types.h index a441a7a32..e84e4826b 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -194,6 +194,7 @@ typedef enum { NMP_OBJECT_TYPE_TFILTER, NMP_OBJECT_TYPE_LNK_GRE, + NMP_OBJECT_TYPE_LNK_GRETAP, NMP_OBJECT_TYPE_LNK_INFINIBAND, NMP_OBJECT_TYPE_LNK_IP6TNL, NMP_OBJECT_TYPE_LNK_IPIP, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 42c1601fb..81712a451 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1072,15 +1072,23 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data) int err; NMPObject *obj; NMPlatformLnkGre *props; + gboolean is_tap; - if (!info_data || g_strcmp0 (kind, "gre")) + if (!info_data || !kind) + return NULL; + + if (nm_streq (kind, "gretap")) + is_tap = TRUE; + else if (nm_streq (kind, "gre")) + is_tap = FALSE; + else return NULL; err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, policy); if (err < 0) return NULL; - obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_GRE, NULL); + obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL); props = &obj->lnk_gre; props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32 (tb[IFLA_GRE_LINK]) : 0; @@ -1093,6 +1101,7 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data) props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8 (tb[IFLA_GRE_TOS]) : 0; props->ttl = tb[IFLA_GRE_TTL] ? nla_get_u8 (tb[IFLA_GRE_TTL]) : 0; props->path_mtu_discovery = !tb[IFLA_GRE_PMTUDISC] || !!nla_get_u8 (tb[IFLA_GRE_PMTUDISC]); + props->is_tap = is_tap; return obj; } @@ -1852,6 +1861,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr switch (obj->link.type) { case NM_LINK_TYPE_GRE: + case NM_LINK_TYPE_GRETAP: lnk_data = _parse_lnk_gre (nl_info_kind, nl_info_data); break; case NM_LINK_TYPE_INFINIBAND: @@ -3995,6 +4005,7 @@ cache_on_change (NMPlatform *platform, if ( !obj_new->_link.netlink.lnk && NM_IN_SET (obj_new->link.type, NM_LINK_TYPE_GRE, + NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IP6TNL, NM_LINK_TYPE_INFINIBAND, NM_LINK_TYPE_MACVLAN, @@ -5330,7 +5341,7 @@ link_gre_add (NMPlatform *platform, if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) goto nla_put_failure; - NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "gre"); + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->is_tap ? "gretap" : "gre"); if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) goto nla_put_failure; @@ -5350,7 +5361,9 @@ link_gre_add (NMPlatform *platform, nla_nest_end (nlmsg, data); nla_nest_end (nlmsg, info); - return do_add_link_with_lookup (platform, NM_LINK_TYPE_GRE, name, nlmsg, out_link); + return do_add_link_with_lookup (platform, + props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, + name, nlmsg, out_link); nla_put_failure: g_return_val_if_reached (FALSE); } diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index f580f167e..8fec85d94 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1854,6 +1854,12 @@ nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLin return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link); } +const NMPlatformLnkGre * +nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRETAP, out_link); +} + const NMPlatformLnkInfiniband * nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -2385,7 +2391,7 @@ nm_platform_link_gre_add (NMPlatform *self, g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); - plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_GRE, out_link); + plerr = _link_add_check_existing (self, name, props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) return plerr; @@ -5055,7 +5061,7 @@ nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len return buf; g_snprintf (buf, len, - "gre" + lnk->is_tap ? "gretap" : "gre" "%s" /* remote */ "%s" /* local */ "%s" /* parent_ifindex */ @@ -5942,7 +5948,8 @@ nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h) obj->output_key, obj->ttl, obj->tos, - (bool) obj->path_mtu_discovery); + (bool) obj->path_mtu_discovery, + (bool) obj->is_tap); } int @@ -5959,6 +5966,7 @@ nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b) NM_CMP_FIELD (a, b, ttl); NM_CMP_FIELD (a, b, tos); NM_CMP_FIELD_BOOL (a, b, path_mtu_discovery); + NM_CMP_FIELD_BOOL (a, b, is_tap); return 0; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 986df9b63..fcb561996 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -618,6 +618,7 @@ typedef struct { guint8 ttl; guint8 tos; bool path_mtu_discovery:1; + bool is_tap:1; } NMPlatformLnkGre; typedef struct { @@ -1198,6 +1199,7 @@ char *nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link); const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkGre *nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 0ffebc9ad..8e07923a7 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2712,6 +2712,17 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, }, + [NMP_OBJECT_TYPE_LNK_GRETAP - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_GRETAP, + .sizeof_data = sizeof (NMPObjectLnkGre), + .sizeof_public = sizeof (NMPlatformLnkGre), + .obj_type_name = "gretap", + .lnk_link_type = NM_LINK_TYPE_GRETAP, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string, + .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, + }, [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), .obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND, diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 42569d5b1..4e708f208 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1243,21 +1243,29 @@ nmtstp_link_gre_add (NMPlatform *platform, const NMPlatformLink *pllink = NULL; gboolean success; char buffer[INET_ADDRSTRLEN]; + NMLinkType link_type; g_assert (nm_utils_is_valid_iface_name (name, NULL)); external_command = nmtstp_run_command_check_external (external_command); + link_type = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE; _init_platform (&platform, external_command); if (external_command) { gs_free char *dev = NULL; + char *obj, *type; if (lnk->parent_ifindex) dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); - success = !nmtstp_run_command ("ip tunnel add %s mode gre %s local %s remote %s ttl %u tos %02x %s", + obj = lnk->is_tap ? "link" : "tunnel"; + type = lnk->is_tap ? "type gretap" : "mode gre"; + + success = !nmtstp_run_command ("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s", + obj, name, + type, dev ?: "", nm_utils_inet4_ntop (lnk->local, NULL), nm_utils_inet4_ntop (lnk->remote, buffer), @@ -1265,11 +1273,11 @@ nmtstp_link_gre_add (NMPlatform *platform, lnk->tos, lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc"); if (success) - pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_GRE, 100); + pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100); } else success = nm_platform_link_gre_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; - _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_GRE); + _assert_pllink (platform, success, pllink, name, link_type); return pllink; } diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index cd5880e34..e99d5d1fe 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -699,6 +699,7 @@ test_software_detect (gconstpointer user_data) guint i_step; const gboolean ext = test_data->external_command; NMPlatformLnkTun lnk_tun; + NMPlatformLnkGre lnk_gre = { }; nm_auto_close int tun_fd = -1; nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME); @@ -706,7 +707,6 @@ test_software_detect (gconstpointer user_data) switch (test_data->link_type) { case NM_LINK_TYPE_GRE: { - NMPlatformLnkGre lnk_gre = { }; gboolean gracefully_skip = FALSE; lnk_gre.local = nmtst_inet4_from_string ("192.168.233.204"); @@ -730,6 +730,31 @@ test_software_detect (gconstpointer user_data) } break; } + case NM_LINK_TYPE_GRETAP: { + gboolean gracefully_skip = FALSE; + + lnk_gre.local = nmtst_inet4_from_string ("192.168.1.133"); + lnk_gre.remote = nmtst_inet4_from_string ("172.168.101.2"); + lnk_gre.parent_ifindex = ifindex_parent; + lnk_gre.ttl = 39; + lnk_gre.tos = 12; + lnk_gre.path_mtu_discovery = FALSE; + lnk_gre.is_tap = TRUE; + + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "gretap0")) { + /* Seems that the ip_gre module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0; + } + + if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) { + if (gracefully_skip) { + g_test_skip ("Cannot create gretap tunnel because of missing ip_gre module (modprobe ip_gre)"); + goto out_delete_parent; + } + g_error ("Failed adding GRETAP tunnel"); + } + break; + } case NM_LINK_TYPE_IPIP: { NMPlatformLnkIpIp lnk_ipip = { }; gboolean gracefully_skip = FALSE; @@ -970,16 +995,15 @@ test_software_detect (gconstpointer user_data) const NMPlatformLnkGre *plnk = &lnk->lnk_gre; g_assert (plnk == nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); - g_assert_cmpint (plnk->input_flags, ==, 0); - g_assert_cmpint (plnk->output_flags, ==, 0); - g_assert_cmpint (plnk->input_key, ==, 0); - g_assert_cmpint (plnk->output_key, ==, 0); - nmtst_assert_ip4_address (plnk->local, "192.168.233.204"); - nmtst_assert_ip4_address (plnk->remote, "172.168.10.25"); - g_assert_cmpint (plnk->ttl, ==, 174); - g_assert_cmpint (plnk->tos, ==, 37); - g_assert_cmpint (plnk->path_mtu_discovery, ==, TRUE); + g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0); + + break; + } + case NM_LINK_TYPE_GRETAP: { + const NMPlatformLnkGre *plnk = &lnk->lnk_gre; + + g_assert (plnk == nm_platform_link_get_lnk_gretap (NM_PLATFORM_GET, ifindex, NULL)); + g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0); break; } case NM_LINK_TYPE_IP6TNL: { @@ -2641,6 +2665,7 @@ _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/gretap", NM_LINK_TYPE_GRETAP, 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); From 09a868a24e8ca22ef66650e58e7d2b9eeb73aed7 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 Jun 2018 12:06:43 +0200 Subject: [PATCH 08/11] platform: add ip6gre/ip6gretap tunnels support Add platform support for IP6GRE and IP6GRETAP tunnels. The former is a virtual tunnel interface for GRE over IPv6 and the latter is the L2 variant. The platform code internally reuses and extends the same structure used by IPv6 tunnels. --- src/nm-types.h | 4 + src/platform/nm-linux-platform.c | 146 +++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 76 +++++++++++++++- src/platform/nm-platform.h | 18 ++++ src/platform/nmp-object.c | 22 +++++ src/platform/tests/test-common.c | 51 +++++++++++ src/platform/tests/test-common.h | 4 + src/platform/tests/test-link.c | 81 +++++++++++++++++ 8 files changed, 400 insertions(+), 2 deletions(-) diff --git a/src/nm-types.h b/src/nm-types.h index e84e4826b..efdce5911 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -160,6 +160,8 @@ typedef enum { NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IFB, NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE, + NM_LINK_TYPE_IP6GRETAP, NM_LINK_TYPE_IPIP, NM_LINK_TYPE_LOOPBACK, NM_LINK_TYPE_MACSEC, @@ -197,6 +199,8 @@ typedef enum { NMP_OBJECT_TYPE_LNK_GRETAP, NMP_OBJECT_TYPE_LNK_INFINIBAND, NMP_OBJECT_TYPE_LNK_IP6TNL, + NMP_OBJECT_TYPE_LNK_IP6GRE, + NMP_OBJECT_TYPE_LNK_IP6GRETAP, NMP_OBJECT_TYPE_LNK_IPIP, NMP_OBJECT_TYPE_LNK_MACSEC, NMP_OBJECT_TYPE_LNK_MACVLAN, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 81712a451..9acd7ac52 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -549,6 +549,8 @@ static const LinkDesc linktypes[] = { { NM_LINK_TYPE_GRETAP, "gretap", "gretap", NULL }, { NM_LINK_TYPE_IFB, "ifb", "ifb", NULL }, { NM_LINK_TYPE_IP6TNL, "ip6tnl", "ip6tnl", NULL }, + { NM_LINK_TYPE_IP6GRE, "ip6gre", "ip6gre", NULL }, + { NM_LINK_TYPE_IP6GRETAP, "ip6gretap", "ip6gretap", NULL }, { NM_LINK_TYPE_IPIP, "ipip", "ipip", NULL }, { NM_LINK_TYPE_LOOPBACK, "loopback", NULL, NULL }, { NM_LINK_TYPE_MACSEC, "macsec", "macsec", NULL }, @@ -1222,6 +1224,79 @@ _parse_lnk_ip6tnl (const char *kind, struct nlattr *info_data) return obj; } +static NMPObject * +_parse_lnk_ip6gre (const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[IFLA_GRE_MAX + 1] = { + [IFLA_GRE_LINK] = { .type = NLA_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, + [IFLA_GRE_IKEY] = { .type = NLA_U32 }, + [IFLA_GRE_OKEY] = { .type = NLA_U32 }, + [IFLA_GRE_LOCAL] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr)}, + [IFLA_GRE_REMOTE] = { .type = NLA_UNSPEC, + .minlen = sizeof (struct in6_addr)}, + [IFLA_GRE_TTL] = { .type = NLA_U8 }, + [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, + [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, + }; + struct nlattr *tb[IFLA_GRE_MAX + 1]; + int err; + NMPObject *obj; + NMPlatformLnkIp6Tnl *props; + guint32 flowinfo; + gboolean is_tap; + + if (!info_data || !kind) + return NULL; + + if (nm_streq (kind, "ip6gre")) + is_tap = FALSE; + else if (nm_streq (kind, "ip6gretap")) + is_tap = TRUE; + else + return NULL; + + err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, policy); + if (err < 0) + return NULL; + + obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_IP6GRETAP : NMP_OBJECT_TYPE_LNK_IP6GRE, NULL); + props = &obj->lnk_ip6tnl; + props->is_gre = TRUE; + props->is_tap = is_tap; + + if (tb[IFLA_GRE_LINK]) + props->parent_ifindex = nla_get_u32 (tb[IFLA_GRE_LINK]); + if (tb[IFLA_GRE_IFLAGS]) + props->input_flags = ntohs (nla_get_u16 (tb[IFLA_GRE_IFLAGS])); + if (tb[IFLA_GRE_OFLAGS]) + props->output_flags = ntohs (nla_get_u16 (tb[IFLA_GRE_OFLAGS])); + if (tb[IFLA_GRE_IKEY]) + props->input_key = ntohl (nla_get_u32 (tb[IFLA_GRE_IKEY])); + if (tb[IFLA_GRE_OKEY]) + props->output_key = ntohl (nla_get_u32 (tb[IFLA_GRE_OKEY])); + if (tb[IFLA_GRE_LOCAL]) + memcpy (&props->local, nla_data (tb[IFLA_GRE_LOCAL]), sizeof (props->local)); + if (tb[IFLA_GRE_REMOTE]) + memcpy (&props->remote, nla_data (tb[IFLA_GRE_REMOTE]), sizeof (props->remote)); + if (tb[IFLA_GRE_TTL]) + props->ttl = nla_get_u8 (tb[IFLA_GRE_TTL]); + if (tb[IFLA_GRE_ENCAP_LIMIT]) + props->encap_limit = nla_get_u8 (tb[IFLA_GRE_ENCAP_LIMIT]); + if (tb[IFLA_GRE_FLOWINFO]) { + flowinfo = ntohl (nla_get_u32 (tb[IFLA_GRE_FLOWINFO])); + props->flow_label = flowinfo & IP6_FLOWINFO_FLOWLABEL_MASK; + props->tclass = (flowinfo & IP6_FLOWINFO_TCLASS_MASK) >> IP6_FLOWINFO_TCLASS_SHIFT; + } + if (tb[IFLA_GRE_FLAGS]) + props->flags = nla_get_u32 (tb[IFLA_GRE_FLAGS]); + + return obj; +} + /*****************************************************************************/ static NMPObject * @@ -1870,6 +1945,10 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_IP6TNL: lnk_data = _parse_lnk_ip6tnl (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_IP6GRE: + case NM_LINK_TYPE_IP6GRETAP: + lnk_data = _parse_lnk_ip6gre (nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_IPIP: lnk_data = _parse_lnk_ipip (nl_info_kind, nl_info_data); break; @@ -4007,6 +4086,8 @@ cache_on_change (NMPlatform *platform, && NM_IN_SET (obj_new->link.type, NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE, + NM_LINK_TYPE_IP6GRETAP, NM_LINK_TYPE_INFINIBAND, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVLAN, @@ -5379,6 +5460,8 @@ link_ip6tnl_add (NMPlatform *platform, struct nlattr *data; guint32 flowinfo; + g_return_val_if_fail (!props->is_gre, FALSE); + nlmsg = _nl_msg_new_link (RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL, 0, @@ -5422,6 +5505,68 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static gboolean +link_ip6gre_add (NMPlatform *platform, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + guint32 flowinfo; + + g_return_val_if_fail (props->is_gre, FALSE); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE | NLM_F_EXCL, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->is_tap ? "ip6gretap" : "ip6gre"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (props->parent_ifindex) + NLA_PUT_U32 (nlmsg, IFLA_GRE_LINK, props->parent_ifindex); + + NLA_PUT_U32 (nlmsg, IFLA_GRE_IKEY, htonl (props->input_key)); + NLA_PUT_U32 (nlmsg, IFLA_GRE_OKEY, htonl (props->output_key)); + NLA_PUT_U16 (nlmsg, IFLA_GRE_IFLAGS, htons (props->input_flags)); + NLA_PUT_U16 (nlmsg, IFLA_GRE_OFLAGS, htons (props->output_flags)); + + if (memcmp (&props->local, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_GRE_LOCAL, sizeof (props->local), &props->local); + if (memcmp (&props->remote, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_GRE_REMOTE, sizeof (props->remote), &props->remote); + + NLA_PUT_U8 (nlmsg, IFLA_GRE_TTL, props->ttl); + NLA_PUT_U8 (nlmsg, IFLA_GRE_ENCAP_LIMIT, props->encap_limit); + + flowinfo = props->flow_label & IP6_FLOWINFO_FLOWLABEL_MASK; + flowinfo |= (props->tclass << IP6_FLOWINFO_TCLASS_SHIFT) + & IP6_FLOWINFO_TCLASS_MASK; + NLA_PUT_U32 (nlmsg, IFLA_GRE_FLOWINFO, htonl (flowinfo)); + NLA_PUT_U32 (nlmsg, IFLA_GRE_FLAGS, props->flags); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, + props->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, + name, nlmsg, out_link); +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static gboolean link_ipip_add (NMPlatform *platform, const char *name, @@ -7314,6 +7459,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_gre_add = link_gre_add; platform_class->link_ip6tnl_add = link_ip6tnl_add; + platform_class->link_ip6gre_add = link_ip6gre_add; platform_class->link_macsec_add = link_macsec_add; platform_class->link_macvlan_add = link_macvlan_add; platform_class->link_ipip_add = link_ipip_add; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 8fec85d94..99dd8490d 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1872,6 +1872,18 @@ nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatform return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6TNL, out_link); } +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6GRE, out_link); +} + +const NMPlatformLnkIp6Tnl * +nm_platform_link_get_lnk_ip6gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_IP6GRETAP, out_link); +} + const NMPlatformLnkIpIp * nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -2550,6 +2562,7 @@ nm_platform_link_ip6tnl_add (NMPlatform *self, g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (!props->is_gre, NM_PLATFORM_ERROR_BUG); plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_IP6TNL, out_link); if (plerr != NM_PLATFORM_ERROR_SUCCESS) @@ -2563,6 +2576,46 @@ nm_platform_link_ip6tnl_add (NMPlatform *self, return NM_PLATFORM_ERROR_SUCCESS; } +/** + * nm_platform_ip6gre_add: + * @self: platform instance + * @name: name of the new interface + * @props: interface properties + * @out_link: on success, the link object + * + * Create an IPv6 GRE/GRETAP tunnel. + */ +NMPlatformError +nm_platform_link_ip6gre_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link) +{ + NMPlatformError plerr; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (props->is_gre, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, + name, + props->is_tap + ? NM_LINK_TYPE_IP6GRETAP + : NM_LINK_TYPE_IP6GRE, + out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("adding link '%s': %s", + name, nm_platform_lnk_ip6tnl_to_string (props, NULL, 0)); + + if (!klass->link_ip6gre_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + /** * nm_platform_ipip_add: * @self: platform instance @@ -5118,12 +5171,18 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi char str_encap[30]; char str_proto[30]; char str_parent_ifindex[30]; + char *str_type; if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) return buf; + if (lnk->is_gre) + str_type = lnk->is_tap ? "ip6gretap" : "ip6gre"; + else + str_type = "ip6tnl"; + g_snprintf (buf, len, - "ip6tnl" + "%s" /* type */ "%s" /* remote */ "%s" /* local */ "%s" /* parent_ifindex */ @@ -5134,6 +5193,7 @@ nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsi "%s" /* proto */ " flags 0x%x" "", + str_type, 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)), lnk->parent_ifindex ? nm_sprintf_buf (str_parent_ifindex, " dev %d", lnk->parent_ifindex) : "", @@ -5998,7 +6058,13 @@ nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState obj->encap_limit, obj->proto, obj->flow_label, - obj->flags); + obj->flags, + obj->input_flags, + obj->output_flags, + obj->input_key, + obj->output_key, + (bool) obj->is_gre, + (bool) obj->is_tap); } int @@ -6014,6 +6080,12 @@ nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6 NM_CMP_FIELD (a, b, flow_label); NM_CMP_FIELD (a, b, proto); NM_CMP_FIELD (a, b, flags); + NM_CMP_FIELD (a, b, input_flags); + NM_CMP_FIELD (a, b, output_flags); + NM_CMP_FIELD (a, b, input_key); + NM_CMP_FIELD (a, b, output_key); + NM_CMP_FIELD_BOOL (a, b, is_gre); + NM_CMP_FIELD_BOOL (a, b, is_tap); return 0; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index fcb561996..567c93ef3 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -636,6 +636,14 @@ typedef struct { guint8 proto; guint flow_label; guint32 flags; + + /* IP6GRE only */ + guint32 input_key; + guint32 output_key; + guint16 input_flags; + guint16 output_flags; + bool is_tap:1; + bool is_gre:1; } NMPlatformLnkIp6Tnl; typedef struct { @@ -830,6 +838,10 @@ typedef struct { const char *name, const NMPlatformLnkIp6Tnl *props, const NMPlatformLink **out_link); + gboolean (*link_ip6gre_add) (NMPlatform *, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link); gboolean (*link_ipip_add) (NMPlatform *, const char *name, const NMPlatformLnkIpIp *props, @@ -1201,6 +1213,8 @@ const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLink const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkGre *nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); +const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -1285,6 +1299,10 @@ NMPlatformError nm_platform_link_ip6tnl_add (NMPlatform *self, const char *name, const NMPlatformLnkIp6Tnl *props, const NMPlatformLink **out_link); +NMPlatformError nm_platform_link_ip6gre_add (NMPlatform *self, + const char *name, + const NMPlatformLnkIp6Tnl *props, + const NMPlatformLink **out_link); NMPlatformError nm_platform_link_ipip_add (NMPlatform *self, const char *name, const NMPlatformLnkIpIp *props, diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 8e07923a7..666a1d1dd 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2745,6 +2745,28 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, }, + [NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRE, + .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6gre", + .lnk_link_type = NM_LINK_TYPE_IP6GRE, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, + }, + [NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRETAP, + .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), + .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), + .obj_type_name = "ip6gretap", + .lnk_link_type = NM_LINK_TYPE_IP6GRETAP, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string, + .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, + }, [NMP_OBJECT_TYPE_LNK_IPIP - 1] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 4e708f208..3dedbd103 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1297,6 +1297,7 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform, gboolean tclass_inherit; g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (!lnk->is_gre); external_command = nmtstp_run_command_check_external (external_command); @@ -1343,6 +1344,56 @@ nmtstp_link_ip6tnl_add (NMPlatform *platform, return pllink; } +const NMPlatformLink * +nmtstp_link_ip6gre_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkIp6Tnl *lnk) +{ + const NMPlatformLink *pllink = NULL; + gboolean success; + char buffer[INET6_ADDRSTRLEN]; + char tclass[20]; + gboolean tclass_inherit; + + g_assert (nm_utils_is_valid_iface_name (name, NULL)); + g_assert (lnk->is_gre); + + external_command = nmtstp_run_command_check_external (external_command); + + _init_platform (&platform, external_command); + + if (external_command) { + gs_free char *dev = NULL; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex)); + + tclass_inherit = NM_FLAGS_HAS (lnk->flags, IP6_TNL_F_USE_ORIG_TCLASS); + + success = !nmtstp_run_command ("ip link add %s type %s %s local %s remote %s ttl %u tclass %s flowlabel %x", + name, + lnk->is_tap ? "ip6gretap" : "ip6gre", + dev, + nm_utils_inet6_ntop (&lnk->local, NULL), + nm_utils_inet6_ntop (&lnk->remote, buffer), + lnk->ttl, + tclass_inherit ? "inherit" : nm_sprintf_buf (tclass, "%02x", lnk->tclass), + lnk->flow_label); + if (success) { + pllink = nmtstp_assert_wait_for_link (platform, + name, + lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE, + 100); + } + } else + success = nm_platform_link_ip6gre_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + + _assert_pllink (platform, success, pllink, name, lnk->is_tap ? NM_LINK_TYPE_IP6GRETAP : NM_LINK_TYPE_IP6GRE); + + return pllink; +} + const NMPlatformLink * nmtstp_link_ipip_add (NMPlatform *platform, gboolean external_command, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index bd02b0d7d..ed6e5791a 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -297,6 +297,10 @@ const NMPlatformLink *nmtstp_link_ip6tnl_add (NMPlatform *platform, gboolean external_command, const char *name, const NMPlatformLnkIp6Tnl *lnk); +const NMPlatformLink *nmtstp_link_ip6gre_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkIp6Tnl *lnk); const NMPlatformLink *nmtstp_link_ipip_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index e99d5d1fe..ce0bb49e4 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -819,6 +819,58 @@ test_software_detect (gconstpointer user_data) } break; } + case NM_LINK_TYPE_IP6GRE: { + NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "ip6gre0")) { + /* Seems that the ip6_tunnel module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_gre", NULL) != 0; + } + + lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::42"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::aaaa"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.tclass = 21; + lnk_ip6tnl.flow_label = 1338; + lnk_ip6tnl.is_gre = TRUE; + + if (!nmtstp_link_ip6gre_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { + if (gracefully_skip) { + g_test_skip ("Cannot create ip6gre tunnel because of missing ip6_gre module (modprobe ip6_gre)"); + goto out_delete_parent; + } + g_error ("Failed adding IP6GRE tunnel"); + } + break; + } + case NM_LINK_TYPE_IP6GRETAP: { + NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; + gboolean gracefully_skip = FALSE; + + if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "ip6gre0")) { + /* Seems that the ip6_tunnel module is not loaded... try to load it. */ + gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_gre", NULL) != 0; + } + + lnk_ip6tnl.local = *nmtst_inet6_from_string ("fe80::abcd"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fc01::bbbb"); + lnk_ip6tnl.parent_ifindex = ifindex_parent; + lnk_ip6tnl.ttl = 10; + lnk_ip6tnl.tclass = 22; + lnk_ip6tnl.flow_label = 1339; + lnk_ip6tnl.is_gre = TRUE; + lnk_ip6tnl.is_tap = TRUE; + + if (!nmtstp_link_ip6gre_add (NULL, ext, DEVICE_NAME, &lnk_ip6tnl)) { + if (gracefully_skip) { + g_test_skip ("Cannot create ip6gretap tunnel because of missing ip6_gre module (modprobe ip6_gre)"); + goto out_delete_parent; + } + g_error ("Failed adding IP6GRETAP tunnel"); + } + break; + } case NM_LINK_TYPE_MACVLAN: { NMPlatformLnkMacvlan lnk_macvlan = { }; const NMPlatformLink *dummy; @@ -1036,6 +1088,33 @@ test_software_detect (gconstpointer user_data) } break; } + case NM_LINK_TYPE_IP6GRE: { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + g_assert (plnk == nm_platform_link_get_lnk_ip6gre (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address (&plnk->local, "fd01::42"); + nmtst_assert_ip6_address (&plnk->remote, "fd01::aaaa"); + g_assert_cmpint (plnk->tclass, ==, 21); + g_assert_cmpint (plnk->flow_label, ==, 1338); + g_assert_cmpint (plnk->is_gre, ==, TRUE); + g_assert_cmpint (plnk->is_tap, ==, FALSE); + break; + } + case NM_LINK_TYPE_IP6GRETAP: { + const NMPlatformLnkIp6Tnl *plnk = &lnk->lnk_ip6tnl; + + g_assert (plnk == nm_platform_link_get_lnk_ip6gretap (NM_PLATFORM_GET, ifindex, NULL)); + g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent); + nmtst_assert_ip6_address (&plnk->local, "fe80::abcd"); + nmtst_assert_ip6_address (&plnk->remote, "fc01::bbbb"); + g_assert_cmpint (plnk->ttl, ==, 10); + g_assert_cmpint (plnk->tclass, ==, 22); + g_assert_cmpint (plnk->flow_label, ==, 1339); + g_assert_cmpint (plnk->is_gre, ==, TRUE); + g_assert_cmpint (plnk->is_tap, ==, TRUE); + break; + } case NM_LINK_TYPE_IPIP: { const NMPlatformLnkIpIp *plnk = &lnk->lnk_ipip; @@ -2668,6 +2747,8 @@ _nmtstp_setup_tests (void) test_software_detect_add ("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0); test_software_detect_add ("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0); test_software_detect_add ("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1); + test_software_detect_add ("/link/software/detect/ip6gre", NM_LINK_TYPE_IP6GRE, 0); + test_software_detect_add ("/link/software/detect/ip6gretap", NM_LINK_TYPE_IP6GRETAP, 0); 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); From f9199c7fb564f368b1de940cb0a8dab0180e3147 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 Jun 2018 10:47:36 +0200 Subject: [PATCH 09/11] ip-tunnel: add support for gretap tunnel connections --- libnm-core/nm-dbus-interface.h | 2 ++ libnm-core/nm-setting-ip-tunnel.c | 7 +++++-- src/devices/nm-device-ip-tunnel.c | 22 ++++++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 8e0882ff1..05d3cd189 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -819,6 +819,7 @@ typedef enum /*< flags >*/ { * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel * * The tunneling mode. * @@ -835,6 +836,7 @@ typedef enum { NM_IP_TUNNEL_MODE_IPIP6 = 7, NM_IP_TUNNEL_MODE_IP6GRE = 8, NM_IP_TUNNEL_MODE_VTI6 = 9, + NM_IP_TUNNEL_MODE_GRETAP = 10, } NMIPTunnelMode; /** diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 3673d9287..8d2541aa0 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -319,6 +319,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) case NM_IP_TUNNEL_MODE_ISATAP: case NM_IP_TUNNEL_MODE_GRE: case NM_IP_TUNNEL_MODE_VTI: + case NM_IP_TUNNEL_MODE_GRETAP: family = AF_INET; break; case NM_IP_TUNNEL_MODE_IP6IP6: @@ -387,8 +388,10 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if ( (priv->input_key && priv->input_key[0]) || (priv->output_key && priv->output_key[0])) { - if ( priv->mode != NM_IP_TUNNEL_MODE_GRE - && priv->mode != NM_IP_TUNNEL_MODE_IP6GRE) { + if (!NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_GRE, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRE)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 2e266bb90..db63458a3 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -179,10 +179,13 @@ clear: goto out; } - if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { + if (NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_GRETAP)) { const NMPlatformLnkGre *lnk; - lnk = nm_platform_link_get_lnk_gre (nm_device_get_platform (device), ifindex, NULL); + if (priv->mode == NM_IP_TUNNEL_MODE_GRE) + lnk = nm_platform_link_get_lnk_gre (nm_device_get_platform (device), ifindex, NULL); + else + lnk = nm_platform_link_get_lnk_gretap (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "gre"); goto clear; @@ -456,7 +459,10 @@ update_connection (NMDevice *device, NMConnection *connection) NULL); } - if (priv->mode == NM_IP_TUNNEL_MODE_GRE || priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) { + if (NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_GRE, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRE)) { if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_INPUT_KEY, @@ -535,6 +541,8 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link) switch (link->type) { case NM_LINK_TYPE_GRE: return NM_IP_TUNNEL_MODE_GRE; + case NM_LINK_TYPE_GRETAP: + return NM_IP_TUNNEL_MODE_GRETAP; case NM_LINK_TYPE_IP6TNL: lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, link->ifindex, NULL); if (lnk) { @@ -559,6 +567,8 @@ tunnel_mode_to_link_type (NMIPTunnelMode tunnel_mode) switch (tunnel_mode) { case NM_IP_TUNNEL_MODE_GRE: return NM_LINK_TYPE_GRE; + case NM_IP_TUNNEL_MODE_GRETAP: + return NM_LINK_TYPE_GRETAP; case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6IP6: return NM_LINK_TYPE_IP6TNL; @@ -600,6 +610,9 @@ create_and_realize (NMDevice *device, g_assert (s_ip_tunnel); switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) { + case NM_IP_TUNNEL_MODE_GRETAP: + lnk_gre.is_tap = TRUE; + /* fall-through */ case NM_IP_TUNNEL_MODE_GRE: if (parent) lnk_gre.parent_ifindex = nm_device_get_ifindex (parent); @@ -938,6 +951,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_LINK_TYPE_GRE, + NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IP6TNL, NM_LINK_TYPE_IPIP, NM_LINK_TYPE_SIT); @@ -1084,7 +1098,7 @@ get_connection_iface (NMDeviceFactory *factory, } NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_class->create_device = create_device; factory_class->get_connection_parent = get_connection_parent; From 3f9f9f7fa228615967efd6000804f30011f33576 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 Jun 2018 15:05:15 +0200 Subject: [PATCH 10/11] ip-tunnel: add support for ip6gre and ip6gretap tunnel connections --- libnm-core/nm-dbus-interface.h | 24 +++--- libnm-core/nm-setting-ip-tunnel.c | 4 +- src/devices/nm-device-ip-tunnel.c | 122 +++++++++++++++++++++++++++--- 3 files changed, 126 insertions(+), 24 deletions(-) diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 05d3cd189..94b4c28d7 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -809,17 +809,18 @@ typedef enum /*< flags >*/ { /** * NMIPTunnelMode: - * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode - * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel - * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel - * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel - * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel - * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel - * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel - * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel - * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel - * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel + * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode + * @NM_IP_TUNNEL_MODE_IPIP: IP in IP tunnel + * @NM_IP_TUNNEL_MODE_GRE: GRE tunnel + * @NM_IP_TUNNEL_MODE_SIT: SIT tunnel + * @NM_IP_TUNNEL_MODE_ISATAP: ISATAP tunnel + * @NM_IP_TUNNEL_MODE_VTI: VTI tunnel + * @NM_IP_TUNNEL_MODE_IP6IP6: IPv6 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IPIP6: IPv4 in IPv6 tunnel + * @NM_IP_TUNNEL_MODE_IP6GRE: IPv6 GRE tunnel + * @NM_IP_TUNNEL_MODE_VTI6: IPv6 VTI tunnel + * @NM_IP_TUNNEL_MODE_GRETAP: GRETAP tunnel + * @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel * * The tunneling mode. * @@ -837,6 +838,7 @@ typedef enum { NM_IP_TUNNEL_MODE_IP6GRE = 8, NM_IP_TUNNEL_MODE_VTI6 = 9, NM_IP_TUNNEL_MODE_GRETAP = 10, + NM_IP_TUNNEL_MODE_IP6GRETAP = 11, } NMIPTunnelMode; /** diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 8d2541aa0..880d6d05f 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -326,6 +326,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6GRE: case NM_IP_TUNNEL_MODE_VTI6: + case NM_IP_TUNNEL_MODE_IP6GRETAP: family = AF_INET6; break; case NM_IP_TUNNEL_MODE_UNKNOWN: @@ -391,7 +392,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) if (!NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_GRETAP, - NM_IP_TUNNEL_MODE_IP6GRE)) { + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index db63458a3..a497461cc 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -257,11 +257,21 @@ clear: ttl = lnk->ttl; tos = lnk->tos; pmtud = lnk->path_mtu_discovery; - } else if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 - || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) { + } else if (NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_IPIP6, + NM_IP_TUNNEL_MODE_IP6IP6, + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { const NMPlatformLnkIp6Tnl *lnk; + NMPlatform *plat = nm_device_get_platform (device); + + if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) + lnk = nm_platform_link_get_lnk_ip6gre (plat, ifindex, NULL); + else if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRETAP) + lnk = nm_platform_link_get_lnk_ip6gretap (plat, ifindex, NULL); + else + lnk = nm_platform_link_get_lnk_ip6tnl (plat, ifindex, NULL); - lnk = nm_platform_link_get_lnk_ip6tnl (nm_device_get_platform (device), ifindex, NULL); if (!lnk) { _LOGW (LOGD_PLATFORM, "could not read %s properties", "ip6tnl"); goto clear; @@ -275,6 +285,40 @@ clear: encap_limit = lnk->encap_limit; flow_label = lnk->flow_label; flags = ip6tnl_flags_plat_to_setting (lnk->flags); + + if (NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + if (NM_FLAGS_HAS (lnk->input_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->input_key); + if (g_strcmp0 (priv->input_key, key)) { + g_free (priv->input_key); + priv->input_key = key; + _notify (self, PROP_INPUT_KEY); + } else + g_free (key); + } else { + if (priv->input_key) { + g_clear_pointer (&priv->input_key, g_free); + _notify (self, PROP_INPUT_KEY); + } + } + + if (NM_FLAGS_HAS (lnk->output_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->output_key); + if (g_strcmp0 (priv->output_key, key)) { + g_free (priv->output_key); + priv->output_key = key; + _notify (self, PROP_OUTPUT_KEY); + } else + g_free (key); + } else { + if (priv->output_key) { + g_clear_pointer (&priv->output_key, g_free); + _notify (self, PROP_OUTPUT_KEY); + } + } + } } else g_return_if_reached (); @@ -462,7 +506,8 @@ update_connection (NMDevice *device, NMConnection *connection) if (NM_IN_SET (priv->mode, NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_GRETAP, - NM_IP_TUNNEL_MODE_IP6GRE)) { + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_INPUT_KEY, @@ -552,6 +597,10 @@ platform_link_to_tunnel_mode (const NMPlatformLink *link) return NM_IP_TUNNEL_MODE_IP6IP6; } return NM_IP_TUNNEL_MODE_UNKNOWN; + case NM_LINK_TYPE_IP6GRE: + return NM_IP_TUNNEL_MODE_IP6GRE; + case NM_LINK_TYPE_IP6GRETAP: + return NM_IP_TUNNEL_MODE_IP6GRETAP; case NM_LINK_TYPE_IPIP: return NM_IP_TUNNEL_MODE_IPIP; case NM_LINK_TYPE_SIT: @@ -572,12 +621,15 @@ tunnel_mode_to_link_type (NMIPTunnelMode tunnel_mode) case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6IP6: return NM_LINK_TYPE_IP6TNL; + case NM_IP_TUNNEL_MODE_IP6GRE: + return NM_LINK_TYPE_IP6GRE; + case NM_IP_TUNNEL_MODE_IP6GRETAP: + return NM_LINK_TYPE_IP6GRETAP; case NM_IP_TUNNEL_MODE_IPIP: return NM_LINK_TYPE_IPIP; case NM_IP_TUNNEL_MODE_SIT: return NM_LINK_TYPE_SIT; case NM_IP_TUNNEL_MODE_VTI: - case NM_IP_TUNNEL_MODE_IP6GRE: case NM_IP_TUNNEL_MODE_VTI6: case NM_IP_TUNNEL_MODE_ISATAP: return NM_LINK_TYPE_UNKNOWN; @@ -605,11 +657,13 @@ create_and_realize (NMDevice *device, NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; const char *str; gint64 val; + NMIPTunnelMode mode; s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); g_assert (s_ip_tunnel); - switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) { + mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + switch (mode) { case NM_IP_TUNNEL_MODE_GRETAP: lnk_gre.is_tap = TRUE; /* fall-through */ @@ -713,6 +767,8 @@ create_and_realize (NMDevice *device, break; case NM_IP_TUNNEL_MODE_IPIP6: case NM_IP_TUNNEL_MODE_IP6IP6: + case NM_IP_TUNNEL_MODE_IP6GRE: + case NM_IP_TUNNEL_MODE_IP6GRETAP: if (parent) lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex (parent); @@ -728,13 +784,44 @@ create_and_realize (NMDevice *device, lnk_ip6tnl.tclass = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); 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 (NM_IN_SET (mode, NM_IP_TUNNEL_MODE_IP6GRE, NM_IP_TUNNEL_MODE_IP6GRETAP)) { + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_ip6tnl.input_key = val; + lnk_ip6tnl.input_flags = NM_GRE_KEY; + } + + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_ip6tnl.output_key = val; + lnk_ip6tnl.output_flags = NM_GRE_KEY; + } + + lnk_ip6tnl.is_gre = TRUE; + lnk_ip6tnl.is_tap = (mode == NM_IP_TUNNEL_MODE_IP6GRETAP); + + plerr = nm_platform_link_ip6gre_add (nm_device_get_platform (device), + iface, &lnk_ip6tnl, out_plink); + } else { + lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 + ? IPPROTO_IPIP + : IPPROTO_IPV6; + plerr = nm_platform_link_ip6tnl_add (nm_device_get_platform (device), + iface, &lnk_ip6tnl, out_plink); + } if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create IPIP interface '%s' for '%s': %s", + "Failed to create IPv6 tunnel interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string_a (plerr)); @@ -877,8 +964,11 @@ constructed (GObject *object) { NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE ((NMDeviceIPTunnel *) object); - if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 - || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) + if (NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_IPIP6, + NM_IP_TUNNEL_MODE_IP6IP6, + NM_IP_TUNNEL_MODE_IP6GRE, + NM_IP_TUNNEL_MODE_IP6GRETAP)) priv->addr_family = AF_INET6; else priv->addr_family = AF_INET; @@ -953,6 +1043,8 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE, + NM_LINK_TYPE_IP6GRETAP, NM_LINK_TYPE_IPIP, NM_LINK_TYPE_SIT); @@ -1098,7 +1190,13 @@ get_connection_iface (NMDeviceFactory *factory, } NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP) + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, + NM_LINK_TYPE_GRETAP, + NM_LINK_TYPE_SIT, + NM_LINK_TYPE_IPIP, + NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IP6GRE, + NM_LINK_TYPE_IP6GRETAP) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), factory_class->create_device = create_device; factory_class->get_connection_parent = get_connection_parent; From fc99aad3780946bd036fad9a82845f6735f3c719 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 26 Jun 2018 10:48:03 +0200 Subject: [PATCH 11/11] ip-tunnel: allow wired setting for some tunnel modes gretap and ip6gretap ip-tunnel interfaces encapsulate L2 packets over IP. Allow adding a wired setting for such connections so that users can change the interface MAC. --- clients/common/nm-meta-setting-desc.c | 1 + libnm-core/nm-connection.c | 21 +++++++++++++++++++++ libnm-core/nm-setting-ip-tunnel.c | 14 ++++++++++++++ src/devices/nm-device-ip-tunnel.c | 16 ++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 649cbf4ef..34c9d8e59 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -7778,6 +7778,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { .valid_parts = NM_META_SETTING_VALID_PARTS ( NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), NM_META_SETTING_VALID_PART_ITEM (IP_TUNNEL, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), ), ), SETTING_INFO (MACSEC, diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 8a66afc61..07b72c169 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1157,6 +1157,26 @@ _normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters) return modified; } +static gboolean +_normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters) +{ + NMSettingIPTunnel *s_ip_tunnel; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (self); + if (!s_ip_tunnel) + return FALSE; + + if ( nm_connection_get_setting_wired (self) + && !NM_IN_SET (nm_setting_ip_tunnel_get_mode (s_ip_tunnel), + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + nm_connection_remove_setting (self, NM_TYPE_SETTING_WIRED); + return TRUE; + } + + return FALSE; +} + static gboolean _normalize_required_settings (NMConnection *self, GHashTable *parameters) { @@ -1502,6 +1522,7 @@ nm_connection_normalize (NMConnection *connection, was_modified |= _normalize_team_port_config (connection, parameters); was_modified |= _normalize_bluetooth_type (connection, parameters); was_modified |= _normalize_ovs_interface_type (connection, parameters); + was_modified |= _normalize_ip_tunnel_wired_setting (connection, parameters); /* Verify anew. */ success = _nm_connection_verify (connection, error); diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c index 880d6d05f..12ccd6a94 100644 --- a/libnm-core/nm-setting-ip-tunnel.c +++ b/libnm-core/nm-setting-ip-tunnel.c @@ -458,6 +458,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if ( nm_connection_get_setting_wired (connection) + && !NM_IN_SET (priv->mode, + NM_IP_TUNNEL_MODE_GRETAP, + NM_IP_TUNNEL_MODE_IP6GRETAP)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("wired setting not allowed for mode %s"), + nm_utils_enum_to_str (nm_ip_tunnel_mode_get_type (), priv->mode)); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_SETTING_IP_TUNNEL_MODE); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + return TRUE; } diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index a497461cc..35c9b0b6f 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -952,6 +952,21 @@ set_property (GObject *object, guint prop_id, } } +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMActStageReturn ret; + + ret = NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->act_stage1_prepare (device, out_failure_reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE)) + return NM_ACT_STAGE_RETURN_FAILURE; + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + /*****************************************************************************/ static void @@ -1028,6 +1043,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_ip_tunnel); + device_class->act_stage1_prepare = act_stage1_prepare; device_class->link_changed = link_changed; device_class->can_reapply_change = can_reapply_change; device_class->complete_connection = complete_connection;