Skip to contentSkip to conversation

openvswitch: add IPv6 tunneling support

PATCH Superseded Jiri Benc 3 participants 15 messages Sep 29, 2015 – Sep 30, 2015

Subsystems (3)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Jiri Benc

author
#0 lore raw

cover openvswitch: add IPv6 tunneling support

This builds on the previous work that added IPv6 support to lwtunnels and adds IPv6 tunneling support to ovs; it is now pretty straightforward.

To use IPv6 tunneling, there needs to be a metadata based tunnel net_device created and added to the ovs bridge. Currently, only vxlan is supported by the kernel, with geneve to follow shortly. There's no need nor intent to add a support for this into the vport-vxlan compat layer.

Jiri Benc (2):
openvswitch: add tunnel protocol to sw_flow_key
openvswitch: netlink attributes for IPv6 tunneling

 include/uapi/linux/openvswitch.h |   2 +
 net/openvswitch/flow.c           |   4 +-
 net/openvswitch/flow.h           |   1 +
 net/openvswitch/flow_netlink.c   | 125 +++++++++++++++++++++++++++------------
 net/openvswitch/flow_table.c     |   2 +-
 5 files changed, 93 insertions(+), 41 deletions(-)
Signature · 1 line
1.8.3.1
author
#1 lore raw

PATCH 1/2 openvswitch: add tunnel protocol to sw_flow_key

Store tunnel protocol (AF_INET or AF_INET6) in sw_flow_key. This field now also acts as an indicator whether the flow contains tunnel data (this was previously indicated by tun_key.u.ipv4.dst being set but with IPv6 addresses in an union with IPv4 ones this won't work anymore).

The new field was added to a hole in sw_flow_key.

---
 net/openvswitch/flow.c         | 4 ++--
 net/openvswitch/flow.h         | 1 +
 net/openvswitch/flow_netlink.c | 7 +++++--
 net/openvswitch/flow_table.c   | 2 +-
 4 files changed, 9 insertions(+), 5 deletions(-)
net/openvswitch/flow.c +2 -2
index c8db44ab2ee7..0ea128eeeab2 100644
@@ -698,8 +698,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
 {
 	/* Extract metadata from packet. */
 	if (tun_info) {
-		if (ip_tunnel_info_af(tun_info) != AF_INET)
-			return -EINVAL;
+		key->tun_proto = ip_tunnel_info_af(tun_info);
 		memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
 
 		if (tun_info->options_len) {
@@ -714,6 +713,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
 			key->tun_opts_len = 0;
 		}
 	} else  {
+		key->tun_proto = 0;
 		key->tun_opts_len = 0;
 		memset(&key->tun_key, 0, sizeof(key->tun_key));
 	}
net/openvswitch/flow.h +1 -0
index fe527d2dd4b7..5688e33e2de6 100644
@@ -63,6 +63,7 @@ struct sw_flow_key {
 		u32	skb_mark;	/* SKB mark. */
 		u16	in_port;	/* Input switch port (or DP_MAX_PORTS). */
 	} __packed phy; /* Safe when right after 'tun_key'. */
+	u8 tun_proto;			/* Protocol of encapsulating tunnel. */
 	u32 ovs_flow_hash;		/* Datapath computed hash value.  */
 	u32 recirc_id;			/* Recirculation ID.  */
 	struct {
net/openvswitch/flow_netlink.c +5 -2
index 5c030a4d7338..03ba070c3256 100644
@@ -643,6 +643,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 	}
 
 	SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
+	SW_FLOW_KEY_PUT(match, tun_proto, AF_INET, is_mask);
 
 	if (rem > 0) {
 		OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.",
@@ -1194,7 +1195,7 @@ int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
 			/* The userspace does not send tunnel attributes that
 			 * are 0, but we should not wildcard them nonetheless.
 			 */
-			if (match->key->tun_key.u.ipv4.dst)
+			if (match->key->tun_proto)
 				SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
 							 0xff, true);
 
@@ -1367,7 +1368,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
 	if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
 		goto nla_put_failure;
 
-	if ((swkey->tun_key.u.ipv4.dst || is_mask)) {
+	if ((swkey->tun_proto || is_mask)) {
 		const void *opts = NULL;
 
 		if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
@@ -1913,6 +1914,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
 
 	tun_info = &tun_dst->u.tun_info;
 	tun_info->mode = IP_TUNNEL_INFO_TX;
+	if (key.tun_proto == AF_INET6)
+		tun_info->mode |= IP_TUNNEL_INFO_IPV6;
 	tun_info->key = key.tun_key;
 
 	/* We need to store the options in the action itself since
net/openvswitch/flow_table.c +1 -1
index f2ea83ba4763..95dbcedf0bd4 100644
@@ -427,7 +427,7 @@ static u32 flow_hash(const struct sw_flow_key *key,
 
 static int flow_key_start(const struct sw_flow_key *key)
 {
-	if (key->tun_key.u.ipv4.dst)
+	if (key->tun_proto)
 		return 0;
 	else
 		return rounddown(offsetof(struct sw_flow_key, phy),
Signature · 1 line
1.8.3.1
author
#9 lore raw

PATCH 2/2 openvswitch: netlink attributes for IPv6 tunneling

In reply to Jiri Benc

Add netlink attributes for IPv6 tunnel addresses. This enables IPv6 support for tunnels.

When compat code for tunnel configuration is used, IPv6 tun_info will be rejected by ovs_tunnel_get_egress_info. As the consequence, only the new way of tunnel config supports IPv6.

---
 include/uapi/linux/openvswitch.h |   2 +
 net/openvswitch/flow_netlink.c   | 120 +++++++++++++++++++++++++++------------
 2 files changed, 85 insertions(+), 37 deletions(-)
include/uapi/linux/openvswitch.h +2 -0
index 32e07d8cbaf4..4036e1b1980f 100644
@@ -349,6 +349,8 @@ enum ovs_tunnel_key_attr {
 	OVS_TUNNEL_KEY_ATTR_TP_SRC,		/* be16 src Transport Port. */
 	OVS_TUNNEL_KEY_ATTR_TP_DST,		/* be16 dst Transport Port. */
 	OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS,		/* Nested OVS_VXLAN_EXT_* */
+	OVS_TUNNEL_KEY_ATTR_IPV6_SRC,		/* struct in6_addr src IPv6 address. */
+	OVS_TUNNEL_KEY_ATTR_IPV6_DST,		/* struct in6_addr dst IPv6 address. */
 	__OVS_TUNNEL_KEY_ATTR_MAX
 };
 
net/openvswitch/flow_netlink.c +83 -37

229 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#2 lore raw

Re: [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Jiri Benc
Quoted 15 lines · Jiri Benc

Store tunnel protocol (AF_INET or AF_INET6) in sw_flow_key. This field now also acts as an indicator whether the flow contains tunnel data (this was previously indicated by tun_key.u.ipv4.dst being set but with IPv6 addresses in an union with IPv4 ones this won't work anymore).

The new field was added to a hole in sw_flow_key.

---
 net/openvswitch/flow.c         | 4 ++--
 net/openvswitch/flow.h         | 1 +
 net/openvswitch/flow_netlink.c | 7 +++++--
 net/openvswitch/flow_table.c   | 2 +-
 4 files changed, 9 insertions(+), 5 deletions(-)

...

net/openvswitch/flow.h struct sw_flow_key { · line 66

Quoted 9 lines
net/openvswitch/flow.h +1 -0
index fe527d2dd4b7..5688e33e2de6 100644
@@ -63,6 +63,7 @@ struct sw_flow_key {
                u32     skb_mark;       /* SKB mark. */
                u16     in_port;        /* Input switch port (or DP_MAX_PORTS). */
        } __packed phy; /* Safe when right after 'tun_key'. */
+       u8 tun_proto;                   /* Protocol of encapsulating tunnel. */

We can add rather add TUNNEL_IPV6 flag to distinguish IPv4 and IPv6 tunnel keys. This can be stored in ip_tunnel_key.tun_flags. That also saves space in flow key.

#7 lore raw

Re: [ovs-dev] [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Jiri Benc

net/openvswitch/flow_netlink.c static int ipv4_tun_from_nlattr(const struct nlattr *attr, · line 646

Quoted 9 lines · Jiri Benc
net/openvswitch/flow_netlink.c +1 -0
index 5c030a4d7338..03ba070c3256 100644
@@ -643,6 +643,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
        }
 
        SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
+       SW_FLOW_KEY_PUT(match, tun_proto, AF_INET, is_mask);

I don't think this is right in the case of the mask. It will cause the the mask to be the value AF_INET - instead you want to set the mask to be 0xff.

#10 lore raw

Re: [PATCH net-next 2/2] openvswitch: netlink attributes for IPv6 tunneling

In reply to Jiri Benc
Quoted 3 lines · Jiri Benc

When compat code for tunnel configuration is used, IPv6 tun_info will be rejected by ovs_tunnel_get_egress_info. As the consequence, only the new way of tunnel config supports IPv6.

This appears to me to be a bug in the existing code. ovs_tunnel_get_egress_info() as a general mechanism is still in use and should work with both the old and new configuration methods. However, I agree that it doesn't look like it will work currently with tunnel devices. I think we need to fix this rather than making it more broken.

author
#3 lore raw

Re: [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Pravin Shelar
Quoted 2 lines · Pravin Shelar

We can add rather add TUNNEL_IPV6 flag to distinguish IPv4 and IPv6 tunnel keys. This can be stored in ip_tunnel_key.tun_flags.

Not really. This was my original approach, too, but openvswitch is not the only user of struct ip_tunnel_key, and in the lwtunnel core, tun_flags are handled in the way that makes this impractical. Most importantly, the tun_flags value is directly taken from/stored to LWTUNNEL_IP_FLAGS/LWTUNNEL_IP6_FLAGS netlink attributes in net/ipv4/ip_tunnel_core.c. This would mean complicated masking, etc.

Quoted 1 line

That also saves space in flow key.

The field was added to a 2 byte hole in the struct sw_flow_key (leaving still 1 byte free), thus there's no additional space used.

Jiri

Signature · 1 line
Jiri Benc
author
#8 lore raw

Re: [ovs-dev] [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Jesse Gross
Quoted 8 lines · Jesse Gross
Quoted 7 lines · Jiri Benc
net/openvswitch/flow_netlink.c +0 -0
index 5c030a4d7338..03ba070c3256 100644
@@ -643,6 +643,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
        }
 
Quoted 6 lines

net/openvswitch/flow_netlink.c static int ipv4_tun_from_nlattr(const struct nlattr *attr, · line 646

Quoted 2 lines
net/openvswitch/flow_netlink.c +1 -0
        SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
+       SW_FLOW_KEY_PUT(match, tun_proto, AF_INET, is_mask);

I don't think this is right in the case of the mask. It will cause the the mask to be the value AF_INET - instead you want to set the mask to be 0xff.

I think you're right, this is a special case. I'll fix it.

Thanks,

Jiri

Signature · 1 line
Jiri Benc
author
#11 lore raw

Re: [PATCH net-next 2/2] openvswitch: netlink attributes for IPv6 tunneling

In reply to Jesse Gross
Quoted 3 lines · Jesse Gross

This appears to me to be a bug in the existing code. ovs_tunnel_get_egress_info() as a general mechanism is still in use and should work with both the old and new configuration methods.

It's currently used only from the compat layer (the API that the user space that is unaware of lwtunnels use).

I don't understand what it would be good for with lwtunnel based tunnels. The metadata_dst is created in the validate_and_copy_set_tun function (net/openvswitch/flow_netlink.c) and used to specify egress encapsulation metadata. The ovs_tunnel_get_egress_info function is not needed.

Quoted 3 lines

However, I agree that it doesn't look like it will work currently with tunnel devices. I think we need to fix this rather than making it more broken.

I'm not making it more broken. We currently (i.e. right now, in the current net.git) have two APIs for tunnel specification in the ovs kernel datapath: the old one, which is translated by the compat layer to create a net_device, and the lwtunnel one, which requires user space to create a (metadata) tunnel net_device and add it to the datapath. I'm simply not adding more code to the first, legacy interface, which seems to be the correct thing to do.

Jiri

Signature · 1 line
Jiri Benc
#4 lore raw

Re: [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Jiri Benc
Quoted 11 lines · Jiri Benc
Quoted 2 lines · Pravin Shelar

We can add rather add TUNNEL_IPV6 flag to distinguish IPv4 and IPv6 tunnel keys. This can be stored in ip_tunnel_key.tun_flags.

Not really. This was my original approach, too, but openvswitch is not the only user of struct ip_tunnel_key, and in the lwtunnel core, tun_flags are handled in the way that makes this impractical. Most importantly, the tun_flags value is directly taken from/stored to LWTUNNEL_IP_FLAGS/LWTUNNEL_IP6_FLAGS netlink attributes in net/ipv4/ip_tunnel_core.c. This would mean complicated masking, etc.

How is it impractical ? Userspace can set flag for IPv6 tunnel info. That should be easy.

IPv6 bit can not be masked anyways so I do not see problem with masking this flag due to the new bit.

Since this field is exposed to userspace. TUNNEL_* flags needs to be moved to uapi header.

Quoted 9 lines
Quoted 1 line

That also saves space in flow key.

The field was added to a 2 byte hole in the struct sw_flow_key (leaving still 1 byte free), thus there's no additional space used.

Jiri

--
Jiri Benc

#12 lore raw

Re: [PATCH net-next 2/2] openvswitch: netlink attributes for IPv6 tunneling

In reply to Jiri Benc
Quoted 7 lines · Jiri Benc
Quoted 3 lines · Jesse Gross

This appears to me to be a bug in the existing code. ovs_tunnel_get_egress_info() as a general mechanism is still in use and should work with both the old and new configuration methods.

It's currently used only from the compat layer (the API that the user space that is unaware of lwtunnels use).

Yes but that is a bug. From the perspective of the intended use of this function, I don't think there is any difference between compat and non-compat users.

Quoted 5 lines

I don't understand what it would be good for with lwtunnel based tunnels. The metadata_dst is created in the validate_and_copy_set_tun function (net/openvswitch/flow_netlink.c) and used to specify egress encapsulation metadata. The ovs_tunnel_get_egress_info function is not needed.

This function is used to report back information that is the result of the encapsulation process, such as the UDP source port chosen. Take a look at net/openvswitch/actions.c:output_userspace(), particularly the OVS_USERSPACE_ATTR_EGRESS_TUN_PORT case.

#5 lore raw

Re: [ovs-dev] [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

In reply to Pravin Shelar
Quoted 12 lines · Pravin Shelar
Quoted 11 lines · Jiri Benc
Quoted 2 lines · Pravin Shelar

We can add rather add TUNNEL_IPV6 flag to distinguish IPv4 and IPv6 tunnel keys. This can be stored in ip_tunnel_key.tun_flags.

Not really. This was my original approach, too, but openvswitch is not the only user of struct ip_tunnel_key, and in the lwtunnel core, tun_flags are handled in the way that makes this impractical. Most importantly, the tun_flags value is directly taken from/stored to LWTUNNEL_IP_FLAGS/LWTUNNEL_IP6_FLAGS netlink attributes in net/ipv4/ip_tunnel_core.c. This would mean complicated masking, etc.

Quoted 5 lines

How is it impractical ? Userspace can set flag for IPv6 tunnel info. That should be easy.

IPv6 bit can not be masked anyways so I do not see problem with masking this flag due to the new bit.

I think he meant for non-OVS users.

Quoted 2 lines

Since this field is exposed to userspace. TUNNEL_* flags needs to be moved to uapi header.

This doesn't really seem all that desirable to me. It's nice to be able to change these as necessary and in the particular case of IPv6, it seems like something that the kernel can manage by itself (as is done in this patch and I think the same strategy would apply regardless of the particular representation).

author
#6 lore raw

Re: [ovs-dev] [PATCH net-next 1/2] openvswitch: add tunnel protocol to sw_flow_key

Quoted 13 lines · Jesse Gross
Quoted 12 lines · Pravin Shelar
Quoted 11 lines · Jiri Benc
Quoted 2 lines · Pravin Shelar

We can add rather add TUNNEL_IPV6 flag to distinguish IPv4 and IPv6 tunnel keys. This can be stored in ip_tunnel_key.tun_flags.

Not really. This was my original approach, too, but openvswitch is not the only user of struct ip_tunnel_key, and in the lwtunnel core, tun_flags are handled in the way that makes this impractical. Most importantly, the tun_flags value is directly taken from/stored to LWTUNNEL_IP_FLAGS/LWTUNNEL_IP6_FLAGS netlink attributes in net/ipv4/ip_tunnel_core.c. This would mean complicated masking, etc.

Quoted 7 lines
Quoted 5 lines

How is it impractical ? Userspace can set flag for IPv6 tunnel info. That should be easy.

IPv6 bit can not be masked anyways so I do not see problem with masking this flag due to the new bit.

I think he meant for non-OVS users.

Yes, I didn't mean masking in ovs, I meant that we'd need to hide the bit from other users, for example in net/ipv4/ip_tunnel_core.c. Currently, the information about ip_tunnel_key protocol is stored outside the structure. Changing this would mean quite big changes in the lwtunnel code (or, rather, IP users of lwtunnel) which doesn't seem worth it just because of ovs. Especially when ovs can store the information just fine without impact on memory footprint.

I don't see any real advantage in storing the protocol inside ip_tunnel_key, this looks like it would be just a change for the change.

Quoted 8 lines
Quoted 2 lines

Since this field is exposed to userspace. TUNNEL_* flags needs to be moved to uapi header.

This doesn't really seem all that desirable to me. It's nice to be able to change these as necessary and in the particular case of IPv6, it seems like something that the kernel can manage by itself (as is done in this patch and I think the same strategy would apply regardless of the particular representation).

User space can set and get those bits in LWTUNNEL_IP_FLAGS netlink attribute when using lwtunnel+routing rules. It would make sense to move them to uapi but that's for a different patch(set).

Jiri

Signature · 1 line
Jiri Benc
author
#13 lore raw

Re: [PATCH net-next 2/2] openvswitch: netlink attributes for IPv6 tunneling

In reply to Jesse Gross
Quoted 4 lines · Jesse Gross

This function is used to report back information that is the result of the encapsulation process, such as the UDP source port chosen. Take a look at net/openvswitch/actions.c:output_userspace(), particularly the OVS_USERSPACE_ATTR_EGRESS_TUN_PORT case.

I see. I think it should be addressed separately from this patchset, though, as the function needs to be completely rewritten even for IPv4 and IPv6 can be handled alongside it.

I'll change the patch description in v2, the current wording is not correct. I don't think that fixing the bug should be a prerequisite for this patchset, the problem is already there and this patchset doesn't change that.

Jiri

Signature · 1 line
Jiri Benc
#14 lore raw

Re: [PATCH net-next 2/2] openvswitch: netlink attributes for IPv6 tunneling

Quoted 6 lines · Jiri Benc
Quoted 4 lines · Jesse Gross

This function is used to report back information that is the result of the encapsulation process, such as the UDP source port chosen. Take a look at net/openvswitch/actions.c:output_userspace(), particularly the OVS_USERSPACE_ATTR_EGRESS_TUN_PORT case.

Quoted 8 lines

I see. I think it should be addressed separately from this patchset, though, as the function needs to be completely rewritten even for IPv4 and IPv6 can be handled alongside it.

I'll change the patch description in v2, the current wording is not correct. I don't think that fixing the bug should be a prerequisite for this patchset, the problem is already there and this patchset doesn't change that.

Can you at least update the existing code for IPv6 so that this doesn't introduce another lurking issue when the bug is fixed?