mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
geneve: Fix incorrect inner network header offset when innerprotoinherit is set
[ Upstream commit c6ae073f5903f6c6439d0ac855836a4da5c0a701 ]
When innerprotoinherit is set, the tunneled packets do not have an inner
Ethernet header.
Change 'maclen' to not always assume the header length is ETH_HLEN, as
there might not be a MAC header.
This resolves issues with drivers (e.g. mlx5, in
mlx5e_tx_tunnel_accel()) who rely on the skb inner network header offset
to be correct, and use it for TX offloads.
Fixes: d8a6213d70ac ("geneve: fix header validation in geneve[6]_xmit_skb")
Signed-off-by: Gal Pressman <gal@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
0b160b127c
commit
11f1f0c4f7
@@ -919,6 +919,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
struct geneve_dev *geneve,
|
||||
const struct ip_tunnel_info *info)
|
||||
{
|
||||
bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;
|
||||
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
|
||||
struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
|
||||
const struct ip_tunnel_key *key = &info->key;
|
||||
@@ -930,7 +931,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be16 sport;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb))
|
||||
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
return -EINVAL;
|
||||
|
||||
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
||||
@@ -1003,7 +1004,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
|
||||
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr),
|
||||
geneve->cfg.inner_proto_inherit);
|
||||
inner_proto_inherit);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
@@ -1019,6 +1020,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
struct geneve_dev *geneve,
|
||||
const struct ip_tunnel_info *info)
|
||||
{
|
||||
bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;
|
||||
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
|
||||
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
|
||||
const struct ip_tunnel_key *key = &info->key;
|
||||
@@ -1028,7 +1030,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
__be16 sport;
|
||||
int err;
|
||||
|
||||
if (!skb_vlan_inet_prepare(skb))
|
||||
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
|
||||
return -EINVAL;
|
||||
|
||||
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
|
||||
@@ -1083,7 +1085,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
ttl = ttl ? : ip6_dst_hoplimit(dst);
|
||||
}
|
||||
err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr),
|
||||
geneve->cfg.inner_proto_inherit);
|
||||
inner_proto_inherit);
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
|
||||
@@ -353,9 +353,10 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
|
||||
|
||||
/* Variant of pskb_inet_may_pull().
|
||||
*/
|
||||
static inline bool skb_vlan_inet_prepare(struct sk_buff *skb)
|
||||
static inline bool skb_vlan_inet_prepare(struct sk_buff *skb,
|
||||
bool inner_proto_inherit)
|
||||
{
|
||||
int nhlen = 0, maclen = ETH_HLEN;
|
||||
int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN;
|
||||
__be16 type = skb->protocol;
|
||||
|
||||
/* Essentially this is skb_protocol(skb, true)
|
||||
|
||||
Reference in New Issue
Block a user