mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
ipvs: properly declare tunnel encapsulation
The tunneling method should properly use tunnel encapsulation. Fixes problem with CHECKSUM_PARTIAL packets when TCP/UDP csum offload is supported. Thanks to Alex Gartrell for reporting the problem, providing solution and for all suggestions. Reported-by: Alex Gartrell <agartrell@fb.com> Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Alex Gartrell <agartrell@fb.com> Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
parent
d1c85c2ebe
commit
ea1d5d7755
1 changed files with 16 additions and 4 deletions
|
@ -38,6 +38,7 @@
|
|||
#include <net/route.h> /* for ip_route_output */
|
||||
#include <net/ipv6.h>
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ip_tunnels.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
|
@ -862,11 +863,15 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
old_iph = ip_hdr(skb);
|
||||
}
|
||||
|
||||
skb->transport_header = skb->network_header;
|
||||
|
||||
/* fix old IP header checksum */
|
||||
ip_send_check(old_iph);
|
||||
|
||||
skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP);
|
||||
if (IS_ERR(skb))
|
||||
goto tx_error;
|
||||
|
||||
skb->transport_header = skb->network_header;
|
||||
|
||||
skb_push(skb, sizeof(struct iphdr));
|
||||
skb_reset_network_header(skb);
|
||||
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
||||
|
@ -900,7 +905,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
return NF_STOLEN;
|
||||
|
||||
tx_error:
|
||||
kfree_skb(skb);
|
||||
if (!IS_ERR(skb))
|
||||
kfree_skb(skb);
|
||||
rcu_read_unlock();
|
||||
LeaveFunction(10);
|
||||
return NF_STOLEN;
|
||||
|
@ -953,6 +959,11 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
old_iph = ipv6_hdr(skb);
|
||||
}
|
||||
|
||||
/* GSO: we need to provide proper SKB_GSO_ value for IPv6 */
|
||||
skb = iptunnel_handle_offloads(skb, false, 0); /* SKB_GSO_SIT/IPV6 */
|
||||
if (IS_ERR(skb))
|
||||
goto tx_error;
|
||||
|
||||
skb->transport_header = skb->network_header;
|
||||
|
||||
skb_push(skb, sizeof(struct ipv6hdr));
|
||||
|
@ -988,7 +999,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
return NF_STOLEN;
|
||||
|
||||
tx_error:
|
||||
kfree_skb(skb);
|
||||
if (!IS_ERR(skb))
|
||||
kfree_skb(skb);
|
||||
rcu_read_unlock();
|
||||
LeaveFunction(10);
|
||||
return NF_STOLEN;
|
||||
|
|
Loading…
Reference in a new issue