Messages in this thread Patch in this message | | | From | Matthias May <> | Subject | [PATCH net-next v2] ip_tunnel: allow to inherit from VLAN encapsulated IP frames | Date | Wed, 6 Jul 2022 18:00:22 +0200 |
| |
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.
Add a check on ETH_P_8021Q and subsequently check the payload protocol.
Signed-off-by: Matthias May <matthias.may@westermo.com> --- v1 -> v2: - Add support for ETH_P_8021AD as suggested by Jakub Kicinski. --- net/ipv4/ip_tunnel.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 94017a8c3994..bdcc0f1e83c8 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -648,6 +648,13 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 tos, ttl; __be32 dst; __be16 df; + __be16 *payload_protocol; + + if (skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)) + payload_protocol = (__be16 *)(skb->head + skb->network_header - 2); + else + payload_protocol = &skb->protocol; inner_iph = (const struct iphdr *)skb_inner_network_header(skb); connected = (tunnel->parms.iph.daddr != 0); @@ -670,13 +677,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 +722,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 +771,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 +792,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
| |