Hello, On Wed, 23 Jul 2014, Alex Gartrell wrote: > Three tests: > * From a remote server: CHECKSUM_UNNECESSARY > * From the local server with hardware checksum offload enabled: > CHECKSUM_PARTIAL > * From the local server with hardware checksum offload disabled: > CHECKSUM_PARTIAL > > I was mildly surprised by the last one. In general I think that ip_summed > is a better way to figure out whether or not we should checksum though. > > > > In any event, given that the skb_checksum_helper function is way more > likely to "just work," I'll put out a patch that adds this invocation > instead. There is skb_checksum_help() call in dev_hard_start_xmit(), it is used when TCP/UDP offload is not supported. After checking the code I see only the CHECKSUM_PARTIAL + Enabled TCP/UDP CSum as a problem because the drivers use the skb->encapsulation flag to know where the TCP/UDP header resides. As tunnels prepend tunnel header they should set skb->encapsulation=1 together with calling skb_reset_inner_headers() before the header is inserted. Following is a patch for the net tree that needs testing because I don't have setup to fully test it. I hope you can try it on your setup for the 3 tests. It should have effect only on your 2nd test. Do you have problems with tests 1 and 3? [PATCH net] 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 and skb->encapsulation is not set to 1. Signed-off-by: Julian Anastasov <ja@xxxxxx> --- net/netfilter/ipvs/ip_vs_xmit.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 73ba1cc..46b43ec 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -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> @@ -483,10 +484,8 @@ static inline int ip_vs_tunnel_xmit_prepare(struct sk_buff *skb, skb->ipvs_property = 1; if (unlikely(cp->flags & IP_VS_CONN_F_NFCT)) ret = ip_vs_confirm_conntrack(skb); - if (ret == NF_ACCEPT) { + if (ret == NF_ACCEPT) nf_reset(skb); - skb_forward_csum(skb); - } return ret; } @@ -867,9 +866,14 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, /* 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_unlock; + skb_push(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + skb_clear_hash(skb); /* * Push down and install the IPIP header. @@ -901,6 +905,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, tx_error: kfree_skb(skb); + +tx_error_unlock: rcu_read_unlock(); LeaveFunction(10); return NF_STOLEN; @@ -955,6 +961,12 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, skb->transport_header = skb->network_header; + if (!skb->encapsulation) { + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } + skb_forward_csum(skb); + skb_push(skb, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); -- 1.9.0 Regards -- Julian Anastasov <ja@xxxxxx> -- To unsubscribe from this list: send the line "unsubscribe lvs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html