netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP
@ 2022-07-11  9:17 Matthias May
  2022-07-11  9:17 ` [PATCH 1/4 v3 net-next] ip_tunnel: allow " Matthias May
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Matthias May @ 2022-07-11  9:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel,
	Matthias May

Currently IPv4 and IPv6 tunnels are able to inherit IP header fields
like TOS, TTL or the DF from their payload, when the payload is IPv4
or IPv6. Some types of tunnels, like GRETAP or VXLAN are able to carry
VLANs. The visible skb->protocol shows in this case as protocol
ETH_P_8021Q or ETH_P_8021AD. However all the relevant structures for IP
payload are correct and just need to be used.

Patch 1 allows tunnels with IPv4 as outer header to inherit from VLAN
encapsulated payload.
Patch 2 fixes a bug, where the DSCP for tunnels with IPv6 as outer header
is never set.
Patch 3 allows tunnels with IPv6 as outer header to inherit the TTL from
VLAN encapsulated payload.
Patch 4 allows IP6GRETAP tunnels with IPv6 as outer header to inherit the
TOS from VLAN encapsulated payload.

Matthias May (4):
  ip_tunnel: allow to inherit from VLAN encapsulated IP
  ip6_gre: set DSCP for non-IP
  ip6_gre: use actual protocol to select xmit
  ip6_tunnel: allow to inherit from VLAN encapsulated IP

 net/ipv4/ip_tunnel.c  | 17 +++++++++--------
 net/ipv6/ip6_gre.c    | 43 +++++++++++++++++++++++++++++++++++--------
 net/ipv6/ip6_tunnel.c | 11 +++++++----
 3 files changed, 51 insertions(+), 20 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4 v3 net-next] ip_tunnel: allow to inherit from VLAN encapsulated IP
  2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
@ 2022-07-11  9:17 ` Matthias May
  2022-07-11  9:17 ` [PATCH 2/4 net-next] ip6_gre: set DSCP for non-IP Matthias May
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Matthias May @ 2022-07-11  9:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel,
	Matthias May

The current code allows to inherit the TOS, TTL, DF from the payload
when skb->protocol is ETH_P_IP or ETH_P_IPV6.
However when the payload is VLAN encapsulated (e.g because the tunnel
is of type GRETAP), then this inheriting does not work, because the
visible skb->protocol is of type ETH_P_8021Q or ETH_P_8021AD.

Instead of skb->protocol, use skb_protocol().

Signed-off-by: Matthias May <matthias.may@westermo.com>
---
v2 -> v3:
 - Instead of manual parsing, use skb_protocol() as suggested by Eyal Birger
v1 -> v2:
 - Add support for ETH_P_8021AD as suggested by Jakub Kicinski.
---
 net/ipv4/ip_tunnel.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 94017a8c3994..dbe18c16b9f6 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -641,6 +641,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	const struct iphdr *inner_iph;
 	unsigned int max_headroom;	/* The extra header space needed */
 	struct rtable *rt = NULL;		/* Route to the other host */
+	__be16 payload_protocol;
 	bool use_cache = false;
 	struct flowi4 fl4;
 	bool md = false;
@@ -651,6 +652,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
 	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
 	connected = (tunnel->parms.iph.daddr != 0);
+	payload_protocol = skb_protocol(skb, true);
 
 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
 
@@ -670,13 +672,12 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 			dst = tun_info->key.u.ipv4.dst;
 			md = true;
 			connected = true;
-		}
-		else if (skb->protocol == htons(ETH_P_IP)) {
+		} else if (payload_protocol == htons(ETH_P_IP)) {
 			rt = skb_rtable(skb);
 			dst = rt_nexthop(rt, inner_iph->daddr);
 		}
 #if IS_ENABLED(CONFIG_IPV6)
-		else if (skb->protocol == htons(ETH_P_IPV6)) {
+		else if (payload_protocol == htons(ETH_P_IPV6)) {
 			const struct in6_addr *addr6;
 			struct neighbour *neigh;
 			bool do_tx_error_icmp;
@@ -716,10 +717,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	tos = tnl_params->tos;
 	if (tos & 0x1) {
 		tos &= ~0x1;
-		if (skb->protocol == htons(ETH_P_IP)) {
+		if (payload_protocol == htons(ETH_P_IP)) {
 			tos = inner_iph->tos;
 			connected = false;
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		} else if (payload_protocol == htons(ETH_P_IPV6)) {
 			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
 			connected = false;
 		}
@@ -765,7 +766,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	}
 
 	df = tnl_params->frag_off;
-	if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
+	if (payload_protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
 		df |= (inner_iph->frag_off & htons(IP_DF));
 
 	if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
@@ -786,10 +787,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 	tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
 	ttl = tnl_params->ttl;
 	if (ttl == 0) {
-		if (skb->protocol == htons(ETH_P_IP))
+		if (payload_protocol == htons(ETH_P_IP))
 			ttl = inner_iph->ttl;
 #if IS_ENABLED(CONFIG_IPV6)
-		else if (skb->protocol == htons(ETH_P_IPV6))
+		else if (payload_protocol == htons(ETH_P_IPV6))
 			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
 #endif
 		else
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4 net-next] ip6_gre: set DSCP for non-IP
  2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
  2022-07-11  9:17 ` [PATCH 1/4 v3 net-next] ip_tunnel: allow " Matthias May
@ 2022-07-11  9:17 ` Matthias May
  2022-07-11  9:17 ` [PATCH 3/4 net-next] ip6_gre: use actual protocol to select xmit Matthias May
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Matthias May @ 2022-07-11  9:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel,
	Matthias May

The current code always forces a dscp of 0 for all non-IP frames.
However when setting a specific TOS with the command

ip link add name tep0 type ip6gretap local fdd1:ced0:5d88:3fce::1
remote fdd1:ced0:5d88:3fce::2 tos 0xa0

one would expect all GRE encapsulated frames to have a TOS of 0xA0.
and not only when the payload is IPv4/IPv6.

Signed-off-by: Matthias May <matthias.may@westermo.com>
---
 net/ipv6/ip6_gre.c | 39 ++++++++++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index a9051df0625d..5fe0db88bea8 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -701,6 +701,33 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb,
 	return 0;
 }
 
+static int prepare_ip6gre_xmit_other(struct sk_buff *skb,
+				     struct net_device *dev,
+				     struct flowi6 *fl6, __u8 *dsfield,
+				     int *encap_limit)
+{
+	struct ip6_tnl *t = netdev_priv(dev);
+
+	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+		*encap_limit = t->parms.encap_limit;
+
+	memcpy(fl6, &t->fl.u.ip6, sizeof(*fl6));
+
+	if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
+		*dsfield = 0;
+	else
+		*dsfield = ip6_tclass(t->parms.flowinfo);
+
+	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
+		fl6->flowi6_mark = skb->mark;
+	else
+		fl6->flowi6_mark = t->parms.fwmark;
+
+	fl6->flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
+	return 0;
+}
+
 static struct ip_tunnel_info *skb_tunnel_info_txcheck(struct sk_buff *skb)
 {
 	struct ip_tunnel_info *tun_info;
@@ -868,20 +895,18 @@ static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev)
 	struct ip6_tnl *t = netdev_priv(dev);
 	int encap_limit = -1;
 	struct flowi6 fl6;
+	__u8 dsfield = 0;
 	__u32 mtu;
 	int err;
 
-	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
-		encap_limit = t->parms.encap_limit;
-
-	if (!t->parms.collect_md)
-		memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
+	if (!t->parms.collect_md &&
+	    prepare_ip6gre_xmit_other(skb, dev, &fl6, &dsfield, &encap_limit))
+		return -1;
 
 	err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM));
 	if (err)
 		return err;
-
-	err = __gre6_xmit(skb, dev, 0, &fl6, encap_limit, &mtu, skb->protocol);
+	err = __gre6_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, skb->protocol);
 
 	return err;
 }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4 net-next] ip6_gre: use actual protocol to select xmit
  2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
  2022-07-11  9:17 ` [PATCH 1/4 v3 net-next] ip_tunnel: allow " Matthias May
  2022-07-11  9:17 ` [PATCH 2/4 net-next] ip6_gre: set DSCP for non-IP Matthias May
@ 2022-07-11  9:17 ` Matthias May
  2022-07-11  9:17 ` [PATCH 4/4 net-next] ip6_tunnel: allow to inherit from VLAN encapsulated IP Matthias May
  2022-07-13 11:20 ` [PATCH 0/4 net-next] Allow " patchwork-bot+netdevbpf
  4 siblings, 0 replies; 6+ messages in thread
From: Matthias May @ 2022-07-11  9:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel,
	Matthias May

When the payload is a VLAN encapsulated IPv6/IPv6 frame, we can
skip the 802.1q/802.1ad ethertypes and jump to the actual protocol.
This way we treat IPv4/IPv6 frames as IP instead of as "other".

Signed-off-by: Matthias May <matthias.may@westermo.com>
---
 net/ipv6/ip6_gre.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 5fe0db88bea8..cd0202016da0 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -916,6 +916,7 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct net_device_stats *stats = &t->dev->stats;
+	__be16 payload_protocol;
 	int ret;
 
 	if (!pskb_inet_may_pull(skb))
@@ -924,7 +925,8 @@ static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb,
 	if (!ip6_tnl_xmit_ctl(t, &t->parms.laddr, &t->parms.raddr))
 		goto tx_err;
 
-	switch (skb->protocol) {
+	payload_protocol = skb_protocol(skb, true);
+	switch (payload_protocol) {
 	case htons(ETH_P_IP):
 		ret = ip6gre_xmit_ipv4(skb, dev);
 		break;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4 net-next] ip6_tunnel: allow to inherit from VLAN encapsulated IP
  2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
                   ` (2 preceding siblings ...)
  2022-07-11  9:17 ` [PATCH 3/4 net-next] ip6_gre: use actual protocol to select xmit Matthias May
@ 2022-07-11  9:17 ` Matthias May
  2022-07-13 11:20 ` [PATCH 0/4 net-next] Allow " patchwork-bot+netdevbpf
  4 siblings, 0 replies; 6+ messages in thread
From: Matthias May @ 2022-07-11  9:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel,
	Matthias May

The current code allows to inherit the TTL (hop_limit) from the
payload when skb->protocol is ETH_P_IP or ETH_P_IPV6.
However when the payload is VLAN encapsulated (e.g because the tunnel
is of type GRETAP), then this inheriting does not work, because the
visible skb->protocol is of type ETH_P_8021Q or ETH_P_8021AD.

Instead of skb->protocol, use skb_protocol().

Signed-off-by: Matthias May <matthias.may@westermo.com>
---
 net/ipv6/ip6_tunnel.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 19325b7600bb..4244a66eb859 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1085,10 +1085,13 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	unsigned int eth_hlen = t->dev->type == ARPHRD_ETHER ? ETH_HLEN : 0;
 	unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;
 	unsigned int max_headroom = psh_hlen;
+	__be16 payload_protocol;
 	bool use_cache = false;
 	u8 hop_limit;
 	int err = -1;
 
+	payload_protocol = skb_protocol(skb, true);
+
 	if (t->parms.collect_md) {
 		hop_limit = skb_tunnel_info(skb)->key.ttl;
 		goto route_lookup;
@@ -1098,7 +1101,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 
 	/* NBMA tunnel */
 	if (ipv6_addr_any(&t->parms.raddr)) {
-		if (skb->protocol == htons(ETH_P_IPV6)) {
+		if (payload_protocol == htons(ETH_P_IPV6)) {
 			struct in6_addr *addr6;
 			struct neighbour *neigh;
 			int addr_type;
@@ -1119,7 +1122,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 
 			memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
 			neigh_release(neigh);
-		} else if (skb->protocol == htons(ETH_P_IP)) {
+		} else if (payload_protocol == htons(ETH_P_IP)) {
 			const struct rtable *rt = skb_rtable(skb);
 
 			if (!rt)
@@ -1230,9 +1233,9 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	skb_dst_set(skb, dst);
 
 	if (hop_limit == 0) {
-		if (skb->protocol == htons(ETH_P_IP))
+		if (payload_protocol == htons(ETH_P_IP))
 			hop_limit = ip_hdr(skb)->ttl;
-		else if (skb->protocol == htons(ETH_P_IPV6))
+		else if (payload_protocol == htons(ETH_P_IPV6))
 			hop_limit = ipv6_hdr(skb)->hop_limit;
 		else
 			hop_limit = ip6_dst_hoplimit(dst);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP
  2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
                   ` (3 preceding siblings ...)
  2022-07-11  9:17 ` [PATCH 4/4 net-next] ip6_tunnel: allow to inherit from VLAN encapsulated IP Matthias May
@ 2022-07-13 11:20 ` patchwork-bot+netdevbpf
  4 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-07-13 11:20 UTC (permalink / raw)
  To: Matthias May
  Cc: netdev, davem, yoshfuji, dsahern, edumazet, kuba, pabeni, linux-kernel

Hello:

This series was applied to netdev/net-next.git (master)
by David S. Miller <davem@davemloft.net>:

On Mon, 11 Jul 2022 11:17:18 +0200 you wrote:
> Currently IPv4 and IPv6 tunnels are able to inherit IP header fields
> like TOS, TTL or the DF from their payload, when the payload is IPv4
> or IPv6. Some types of tunnels, like GRETAP or VXLAN are able to carry
> VLANs. The visible skb->protocol shows in this case as protocol
> ETH_P_8021Q or ETH_P_8021AD. However all the relevant structures for IP
> payload are correct and just need to be used.
> 
> [...]

Here is the summary with links:
  - [1/4,v3,net-next] ip_tunnel: allow to inherit from VLAN encapsulated IP
    https://git.kernel.org/netdev/net-next/c/7ae29fd1be43
  - [2/4,net-next] ip6_gre: set DSCP for non-IP
    https://git.kernel.org/netdev/net-next/c/41337f52b967
  - [3/4,net-next] ip6_gre: use actual protocol to select xmit
    https://git.kernel.org/netdev/net-next/c/3f8a8447fd0b
  - [4/4,net-next] ip6_tunnel: allow to inherit from VLAN encapsulated IP
    https://git.kernel.org/netdev/net-next/c/b09ab9c92e50

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-07-13 11:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-11  9:17 [PATCH 0/4 net-next] Allow to inherit from VLAN encapsulated IP Matthias May
2022-07-11  9:17 ` [PATCH 1/4 v3 net-next] ip_tunnel: allow " Matthias May
2022-07-11  9:17 ` [PATCH 2/4 net-next] ip6_gre: set DSCP for non-IP Matthias May
2022-07-11  9:17 ` [PATCH 3/4 net-next] ip6_gre: use actual protocol to select xmit Matthias May
2022-07-11  9:17 ` [PATCH 4/4 net-next] ip6_tunnel: allow to inherit from VLAN encapsulated IP Matthias May
2022-07-13 11:20 ` [PATCH 0/4 net-next] Allow " patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).