aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2015-04-09 11:19:14 -0700
committerSasha Levin <sasha.levin@oracle.com>2015-04-27 17:13:41 -0400
commit218aa70e49b61fd49691a688309bdee22608c9bb (patch)
tree6cf9af20e9768ba36d62d4f71e6fe7016fa7d4eb
parent754a19948ec440acc781d3870d48329c802a6eb7 (diff)
downloadlinux-linaro-stable-218aa70e49b61fd49691a688309bdee22608c9bb.tar.gz
udptunnels: Call handle_offloads after inserting vlan tag.
[ Upstream commit b736a623bd099cdf5521ca9bd03559f3bc7fa31c ] handle_offloads() calls skb_reset_inner_headers() to store the layer pointers to the encapsulated packet. However, we currently push the vlag tag (if there is one) onto the packet afterwards. This changes the MAC header for the encapsulated packet but it is not reflected in skb->inner_mac_header, which breaks GSO and drivers which attempt to use this for encapsulation offloads. Fixes: 1eaa8178 ("vxlan: Add tx-vlan offload support.") Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
-rw-r--r--drivers/net/vxlan.c20
-rw-r--r--net/ipv4/geneve.c6
2 files changed, 14 insertions, 12 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 99da7cec9cf4..2826c5508762 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1578,12 +1578,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
int err;
bool udp_sum = !udp_get_no_check6_tx(vs->sock->sk);
- skb = udp_tunnel_handle_offloads(skb, udp_sum);
- if (IS_ERR(skb)) {
- err = -EINVAL;
- goto err;
- }
-
skb_scrub_packet(skb, xnet);
min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
@@ -1603,6 +1597,12 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
goto err;
}
+ skb = udp_tunnel_handle_offloads(skb, udp_sum);
+ if (IS_ERR(skb)) {
+ err = -EINVAL;
+ goto err;
+ }
+
vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = htonl(VXLAN_FLAGS);
vxh->vx_vni = vni;
@@ -1628,10 +1628,6 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
int err;
bool udp_sum = !vs->sock->sk->sk_no_check_tx;
- skb = udp_tunnel_handle_offloads(skb, udp_sum);
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
+ VXLAN_HLEN + sizeof(struct iphdr)
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
@@ -1647,6 +1643,10 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
if (WARN_ON(!skb))
return -ENOMEM;
+ skb = udp_tunnel_handle_offloads(skb, udp_sum);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = htonl(VXLAN_FLAGS);
vxh->vx_vni = vni;
diff --git a/net/ipv4/geneve.c b/net/ipv4/geneve.c
index fd0fe18e3e3e..d5423e33d32b 100644
--- a/net/ipv4/geneve.c
+++ b/net/ipv4/geneve.c
@@ -121,8 +121,6 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
int min_headroom;
int err;
- skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx);
-
min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
+ (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0);
@@ -135,6 +133,10 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
if (unlikely(!skb))
return -ENOMEM;
+ skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);