ipgre: fix lwtunnel support
Subsystems (3)
cover ipgre: fix lwtunnel support
lwtunnels currently work only with gretap. This patchset fixes the bugs in ipgre metadata mode implementation.
As an example, in this setup:
ip a a 192.168.1.1/24 dev eth0
ip l a gre1 type gre external
ip l s gre1 up
ip a a 192.168.99.1/24 dev gre1
ip r a 192.168.99.2/32 encap ip dst 192.168.1.2 ttl 10 dev gre1 ping 192.168.99.2
the traffic does not go through before this patchset and does as expected with it applied.
Jiri Benc (3):
gre: do not assign header_ops in collect metadata mode
gre: build header correctly for collect metadata tunnels
gre: receive also TEB packets for lwtunnels
include/net/ip_tunnels.h | 1 + net/ipv4/ip_gre.c | 48 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 15 deletions(-)
Signature · 1 line
1.8.3.1
PATCH 1/3 gre: do not assign header_ops in collect metadata mode
In ipgre mode (i.e. not gretap) with collect metadata flag set, the tunnel is incorrectly assumed to be mGRE in NBMA mode (see commit 6a5f44d7a048c). This is not the case, we're controlling the encapsulation addresses by lwtunnel metadata. And anyway, assigning dev->header_ops in collect metadata mode does not make sense.
--- net/ipv4/ip_gre.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
net/ipv4/ip_gre.c +3 -2
@@ -893,7 +893,7 @@ static int ipgre_tunnel_init(struct net_device *dev)netif_keep_dst (dev); dev->addr_len =4 ; -if (iph->daddr) { +if (iph->daddr && !tunnel->collect_md) {#ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast (iph->daddr)) {if (!iph->saddr)
@@ -902,8 +902,9 @@ static int ipgre_tunnel_init(struct net_device *dev) dev->header_ops = &ipgre_header_ops; }#endif - }else + }else if (!tunnel->collect_md) { dev->header_ops = &ipgre_header_ops; + }return ip_tunnel_init (dev); }
Signature · 1 line
1.8.3.1
PATCH 2/3 gre: build header correctly for collect metadata tunnels
In reply to Jiri BencIn ipgre (i.e. not gretap) + collect metadata mode, the skb was assumed to contain Ethernet header and was encapsulated as ETH_P_TEB. This is not the case, the interface is ARPHRD_IPGRE and the protocol to be used for encapsulation is skb->protocol.
--- net/ipv4/ip_gre.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
net/ipv4/ip_gre.c +5 -4
@@ -523,7 +523,8 @@ static struct rtable *gre_get_rt(struct sk_buff *skb,return ip_route_output_key (net, fl); } -static void gre_fb_xmit (struct sk_buff *skb,struct net_device *dev) +static void gre_fb_xmit (struct sk_buff *skb,struct net_device *dev, +__be16 proto) {struct ip_tunnel_info *tun_info;const struct ip_tunnel_key *key;
@@ -575,7 +576,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) } flags = tun_info->key.tun_flags & (TUNNEL_CSUM |TUNNEL_KEY ); -build_header (skb, tunnel_hlen, flags,htons (ETH_P_TEB ), +build_header (skb, tunnel_hlen, flags, proto,tunnel_id_to_key (tun_info->key.tun_id),0 ); df = key->tun_flags &TUNNEL_DONT_FRAGMENT ?htons (IP_DF ) :0 ;
@@ -616,7 +617,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,const struct iphdr *tnl_params;if (tunnel->collect_md) { -gre_fb_xmit (skb, dev); +gre_fb_xmit (skb, dev, skb->protocol);return NETDEV_TX_OK ; }
@@ -660,7 +661,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,struct ip_tunnel *tunnel =netdev_priv (dev);if (tunnel->collect_md) { -gre_fb_xmit (skb, dev); +gre_fb_xmit (skb, dev,htons (ETH_P_TEB ));return NETDEV_TX_OK ; }
Signature · 1 line
1.8.3.1
PATCH 3/3 gre: receive also TEB packets for lwtunnels
In reply to Jiri BencFor ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers.
--- include/net/ip_tunnels.h | 1 + net/ipv4/ip_gre.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-)
include/net/ip_tunnels.h +1 -0
@@ -161,6 +161,7 @@ struct tnl_ptk_info {#define PACKET_RCVD 0#define PACKET_REJECT 1 +#define PACKET_NEXT 2#define IP_TNL_HASH_BITS 7#define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS)
net/ipv4/ip_gre.c +25 -9
@@ -379,19 +379,13 @@ static __be32 tunnel_id_to_key(__be64 x)#endif } -static int ipgre_rcv (struct sk_buff *skb,const struct tnl_ptk_info *tpi) +static int __ipgre_rcv (struct sk_buff *skb,const struct tnl_ptk_info *tpi, +struct ip_tunnel_net *itn) { -struct net *net =dev_net (skb->dev);struct metadata_dst *tun_dst =NULL ; -struct ip_tunnel_net *itn;const struct iphdr *iph;struct ip_tunnel *tunnel; -if (tpi->proto ==htons (ETH_P_TEB )) - itn =net_generic (net, gre_tap_net_id); -else - itn =net_generic (net, ipgre_net_id); - iph =ip_hdr (skb); tunnel =ip_tunnel_lookup (itn, skb->dev->ifindex, tpi->flags, iph->saddr, iph->daddr, tpi->key);
@@ -412,7 +406,29 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)ip_tunnel_rcv (tunnel, skb, tpi, tun_dst, log_ecn_error);return PACKET_RCVD ; } -return PACKET_REJECT ; +return PACKET_NEXT ; +} + +static int ipgre_rcv (struct sk_buff *skb,const struct tnl_ptk_info *tpi) +{ +struct net *net =dev_net (skb->dev); +struct ip_tunnel_net *itn; +int res; + +if (tpi->proto ==htons (ETH_P_TEB )) + itn =net_generic (net, gre_tap_net_id); +else + itn =net_generic (net, ipgre_net_id); + + res =__ipgre_rcv (skb, tpi, itn); +if (res ==PACKET_NEXT && tpi->proto ==htons (ETH_P_TEB )) { +/* ipgre tunnels in collect metadata mode should receive +* also ETH_P_TEB traffic +*/ + itn =net_generic (net, ipgre_net_id); + res =__ipgre_rcv (skb, tpi, itn); + } +return res; }static int gre_rcv (struct sk_buff *skb)
Signature · 1 line
1.8.3.1
Re: [PATCH net 1/3] gre: do not assign header_ops in collect metadata mode
In reply to Jiri BencQuoted 26 lines · Jiri Benc
In ipgre mode (i.e. not gretap) with collect metadata flag set, the tunnel is incorrectly assumed to be mGRE in NBMA mode (see commit
6a5f44d7a048c). This is not the case, we're controlling the encapsulation addresses by lwtunnel metadata. And anyway, assigningdev->header_opsin collect metadata mode does not make sense.Fixes 2e15ea390e6f4 ("ip_gre: Add support to collect tunnel metadata.")Signed-off-by Jiri Benc <[email protected]>--- net/ipv4/ip_gre.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)net/ipv4/ip_gre.c +1
-1@@ -893,7 +893,7 @@ static int ipgre_tunnel_init(struct net_device *dev)netif_keep_dst (dev); dev->addr_len =4 ; -if (iph->daddr) { +if (iph->daddr && !tunnel->collect_md) {#ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast (iph->daddr)) {if (!iph->saddr)
net/ipv4/ip_gre.c static int ipgre_tunnel_init(struct net_device *dev) · line 904
Quoted 3 lines
net/ipv4/ip_gre.c +0
-0@@ -902,8 +902,9 @@ static int ipgre_tunnel_init(struct net_device *dev) dev->header_ops = &ipgre_header_ops; }#endif
I think we should we return error in case of such configuration rather than silently ignoring it.
Re: [PATCH net 2/3] gre: build header correctly for collect metadata tunnels
In reply to Jiri BencQuoted 7 lines · Jiri Benc
In ipgre (i.e. not gretap) + collect metadata mode, the skb was assumed to contain Ethernet header and was encapsulated as
ETH_P_TEB. This is not the case, the interface isARPHRD_IPGREand the protocol to be used for encapsulation isskb->protocol.Fixes 2e15ea390e6f4 ("ip_gre: Add support to collect tunnel metadata.")Signed-off-by Jiri Benc <[email protected]>
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Jiri BencQuoted 5 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
How user is suppose to sort out the type of packet? whether it is L2 or L3.
Quoted 9 lines
To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers.
Signed-off-by Jiri Benc <[email protected]>--- include/net/ip_tunnels.h | 1 + net/ipv4/ip_gre.c | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-)
...
Quoted 9 lines
net/ipv4/ip_gre.c +9
-0+ +static int ipgre_rcv (struct sk_buff *skb,const struct tnl_ptk_info *tpi) +{ +struct net *net =dev_net (skb->dev); +struct ip_tunnel_net *itn; +int res; + +if (tpi->proto ==htons (ETH_P_TEB )) + itn =net_generic (net, gre_tap_net_id);
net/ipv4/ip_gre.c static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
Quoted 10 lines
net/ipv4/ip_gre.c +10
-0+else + itn =net_generic (net, ipgre_net_id); + + res =__ipgre_rcv (skb, tpi, itn); +if (res ==PACKET_NEXT && tpi->proto ==htons (ETH_P_TEB )) { +/* ipgre tunnels in collect metadata mode should receive +* also ETH_P_TEB traffic +*/ + itn =net_generic (net, ipgre_net_id); + res =__ipgre_rcv (skb, tpi, int);
Is it fine to receive L2 packet over L3 device?
At least ip_tunnel_rcv() is not ready to handle such packet.
Re: [PATCH net 1/3] gre: do not assign header_ops in collect metadata mode
In reply to pravin shelarQuoted 2 lines · pravin shelar
I think we should we return error in case of such configuration rather than silently ignoring it.
I thought about it and I'm not sure. We're not returning an error currently, starting returning it now might be perceived as uAPI breakage.
But given it doesn't work at all currently, there are apparently no users yet. I'll wait for more feedback.
Jiri
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to pravin shelarQuoted 7 lines · pravin shelar
Quoted 5 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
How user is suppose to sort out the type of packet? whether it is L2 or L3.
By skb->protocol, of course. Will be ETH_P_TEB if the inner packet was Ethernet. There's no problem with this, for lwtunnels used with encap routes, such packets are just discarded (which is the expected behavior), as there's no protocol handler for ETH_P_TEB. More clever lwtunnel users (such as openvswitch) can process the packets. This is important in order to have a single tunnel interface for everything.
Quoted 2 lines
Is it fine to receive L2 packet over L3 device?
At leastip_tunnel_rcv()is not ready to handle such packet.
I don't see why. Could you please elaborate? Seems safe to me. The desired result is skb->protocol == htons(ETH_P_TEB), network header(!) pointing to the start of the Ethernet frame (because we're tunneling Ethernet via ARPHRD_IPGRE interface, there's no L2 header to have), mac header not being set.
Jiri
Simon Horman
Reviewed-byRe: [PATCH net 2/3] gre: build header correctly for collect metadata tunnels
In reply to pravin shelarQuoted 10 lines · pravin shelar
Quoted 7 lines · Jiri Benc
In ipgre (i.e. not gretap) + collect metadata mode, the skb was assumed to contain Ethernet header and was encapsulated as
ETH_P_TEB. This is not the case, the interface isARPHRD_IPGREand the protocol to be used for encapsulation isskb->protocol.Fixes 2e15ea390e6f4 ("ip_gre: Add support to collect tunnel metadata.")Signed-off-by Jiri Benc <[email protected]>Acked-by Pravin B Shelar <[email protected]>
Re: [PATCH net 1/3] gre: do not assign header_ops in collect metadata mode
In reply to Jiri BencQuoted 10 lines · Jiri Benc
Quoted 2 lines · pravin shelar
I think we should we return error in case of such configuration rather than silently ignoring it.
I thought about it and I'm not sure. We're not returning an error currently, starting returning it now might be perceived as uAPI breakage.
But given it doesn't work at all currently, there are apparently no users yet. I'll wait for more feedback.
As a user, I would probably favour receiving an error for a configuration that can't possibly work and was not working before.
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Jiri BencQuoted 7 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers.
I may be missing some context. Is anyone using this already or is this preparing the stage for another user? It's not clear to me from the commit message.
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Jiri BencQuoted 7 lines · Jiri Benc
Quoted 6 lines · pravin shelar
Quoted 5 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
Quoted 9 lines
Quoted 1 line
How user is suppose to sort out the type of packet? whether it is L2 or L3.
By
skb->protocol, of course. Will beETH_P_TEBif the inner packet was Ethernet. There's no problem with this, for lwtunnels used with encap routes, such packets are just discarded (which is the expected behavior), as there's no protocol handler forETH_P_TEB. More clever lwtunnel users (such as openvswitch) can process the packets. This is important in order to have a single tunnel interface for everything.
But skb->protocol is not set to ETH_P_TEB anywhere in ip-gre module. Am I missing something?
Quoted 9 lines
Quoted 2 lines
Is it fine to receive L2 packet over L3 device?
At leastip_tunnel_rcv()is not ready to handle such packet.I don't see why. Could you please elaborate? Seems safe to me. The desired result is
skb->protocol==htons(ETH_P_TEB), network header(!) pointing to the start of the Ethernet frame (because we're tunneling Ethernet viaARPHRD_IPGREinterface, there's no L2 header to have), mac header not being set.
ip_tunnel_rcv() checks device type (tunnel->dev->type) to perform ethernet specific processing on packet. I think that should be changed to check packet type.
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Thomas GrafQuoted 6 lines · Thomas Graf
Quoted 5 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
Quoted 6 lines
Quoted 2 lines
To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers.
I may be missing some context. Is anyone using this already or is this preparing the stage for another user? It's not clear to me from the commit message.
Hi Thomas,
I'm not sure what use Jiri may have in mind but I plan to use this to allow OvS to support packets without an Ethernet header to be received from and sent to a GRE tunnel.
I am reasonably sure there are no existing users.
Re: [PATCH net 1/3] gre: do not assign header_ops in collect metadata mode
In reply to Thomas GrafQuoted 9 lines · Thomas Graf
Quoted 8 lines · Jiri Benc
Quoted 2 lines · pravin shelar
I think we should we return error in case of such configuration rather than silently ignoring it.
I thought about it and I'm not sure. We're not returning an error currently, starting returning it now might be perceived as uAPI breakage.
Quoted 5 lines
Quoted 2 lines
But given it doesn't work at all currently, there are apparently no users yet. I'll wait for more feedback.
As a user, I would probably favour receiving an error for a configuration that can't possibly work and was not working before.
Okay, I'll change this in v2. Thanks, Pravin and Thomas.
Jiri
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Simon HormanQuoted 5 lines · Simon Horman
Quoted 3 lines · Thomas Graf
I may be missing some context. Is anyone using this already or is this preparing the stage for another user? It's not clear to me from the commit message.
Quoted 7 lines
Hi Thomas,
I'm not sure what use Jiri may have in mind but I plan to use this to allow OvS to support packets without an Ethernet header to be received from and sent to a GRE tunnel.
I am reasonably sure there are no existing users.
Yes, that's the main use case as far as I can see. Sorry for not being clear.
The intention is to support tunnels that can have mixed L2+L3 traffic over a single lwtunnel interface. VXLAN-GPE already does this, this patch makes GRE behave identically, while preserving all current GRE users.
The reason I sent this for net and not net-next is that I wanted to prevent the situation when we have a kernel released that supports ipgre lwtunnels but incompletely - i.e., ETH_P_TEB frames are discarded. But thinking about it more, it's probably non-issue. I'll retarget this patch for net-next and resend the first two for net.
Thanks,
Jiri
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to pravin shelarQuoted 2 lines · pravin shelar
But
skb->protocolis not set toETH_P_TEBanywhere in ip-gre module. Am I missing something?
Ah, I see your point. It needs to be solved a bit differently, though, we need to call __iptunnel_pull_header instead of iptunnel_pull_header for these packets. I'll rework the patch.
Quoted 3 lines
ip_tunnel_rcv()checks device type (tunnel->dev->type) to perform ethernet specific processing on packet. I think that should be changed to check packet type.
The current behavior is correct. The Ethernet processing depends on the interface type, ARPHRD_IPGRE interfaces can't treat Ethernet headers as L2 headers, that wouldn't match the interface type.
Jiri
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
In reply to Jiri BencQuoted 7 lines · Jiri Benc
For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface.
To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers.
Hi Jiri,
I have had some success wiring up Open vSwitch to use this patch for transmit. However, I am wondering if something more is needed to allow differentiation between packets with and without an L2 header present on receive.
I had luck getting receive working with the following:
From: Simon Horman <[email protected]>
Date: Mon, 18 Apr 2016 17:48:47 +1000
Subject: [PATCH] gre: mark presense of l2 when recieving TEB packets for lwtunnels
There seems to be some way for receivers to differentiate between packets recieved with and without an l2 header. The approach taken here is to use a new mode bit in struct ip_tunnel_key.
Another approach might be to store tpi->proto in tunnel metadata, though that would consume 16 bits somewhere and seems like overkill at this point.
--- include/net/ip_tunnels.h | 6 ++++++ net/ipv4/ip_gre.c | 3 +++ 2 files changed, 9 insertions(+)
include/net/ip_tunnels.h +6 -0
@@ -58,6 +58,12 @@ struct ip_tunnel_key {/* Flags for ip_tunnel_info mode. */ #define IP_TUNNEL_INFO_TX 0x01/* represents tx tunnel parameters */ #define IP_TUNNEL_INFO_IPV6 0x02/* key contains IPv6 addresses */ +#define IP_TUNNEL_INFO_L2_PRESENT 0x04/* Set on receive by tunnels that +* may receive packets both with +* and without an L2 header present +* when a packet is received with +* L2 header present. +*/ /* Maximum tunnel options length. */ #define IP_TUNNEL_OPTS_MAX \
net/ipv4/ip_gre.c +3 -0
@@ -401,6 +401,9 @@ static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, tun_dst =ip_tun_rx_dst (skb, flags, tun_id,0 );if (!tun_dst)return PACKET_REJECT ; +if (tpi->proto ==htons (ETH_P_TEB )) + tun_dst->u.tun_info.mode |= +IP_TUNNEL_INFO_L2_PRESENT ; }ip_tunnel_rcv (tunnel, skb, tpi, tun_dst, log_ecn_error);
Signature · 1 line
2.7.0.rc3.207.g0ac5344
Re: [PATCH net 3/3] gre: receive also TEB packets for lwtunnels
Quoted 4 lines · Simon Horman
I have had some success wiring up Open vSwitch to use this patch for transmit. However, I am wondering if something more is needed to allow differentiation between packets with and without an L2 header present on receive.
The problem, as Pravin pointed out, is the patch does not correctly set skb->protocol to ETH_P_TEB because of special handling of ETH_P_TEB in iptunnel_pull_header. This will be fixed in v2 of the patch.
No flag will be needed then, just use skb->protocol.
Jiri