Hello, IPVS (IP Virtual Server) has a sending mode to encapsulate IPv6 packet in a new IPv6 header (like ip6ip6 tunnel). As IPVS is lacking skb->encapsulation support we are trying to call iptunnel_handle_offloads() with some SKB_GSO_ value, SKB_GSO_SIT looking the only available option. IPVS works by catching packets at LOCAL_IN (GRO is possible) and injecting them via ip_local_out() and ip6_local_out() after adding new IPIP or IPV6 header. Draft patch is appended for comments. We have the following questions: - Is it correct to provide SKB_GSO_SIT to iptunnel_handle_offloads() for the case when we add IPPROTO_IPV6 header, I see (SKB_GSO_SIT|SKB_GSO_IPIP) check in ipv6_gso_segment() that may need to account network headers. Or we have to add SKB_GSO_IPV6 with same value like SKB_GSO_SIT, in case the SIT name looks confusing for ip6ip6 mode and to register it in inet6_offloads? Questions not related to IPVS: - I guess ipv6_gro_receive() does not support GRO for IPPROTO_IPV6 in IPPROTO_IPV6 because IPPROTO_IPV6 is not registered in inet6_offloads list? - is it correct ip6_tnl_xmit2() to use skb->transport_header = skb->network_header before calling skb_reset_inner_headers() ? skb->inner_transport_header will get wrong value? I guess this is bad for HW csum offload? Thanks! [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. Thanks to Alex Gartrell for reporting the problem, providing solution and for all suggestions. Reported-by: Alex Gartrell <agartrell@xxxxxx> TODO: waiting for final ack from Alex before adding Signed-off-by line Signed-off-by: Julian Anastasov <ja@xxxxxx> --- net/netfilter/ipvs/ip_vs_xmit.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 73ba1cc..8c1172c 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> @@ -862,14 +863,19 @@ 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)); + skb_clear_hash(skb); /* * Push down and install the IPIP header. @@ -900,7 +906,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 +960,10 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, old_iph = ipv6_hdr(skb); } + skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); + 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; -- 1.9.0 -- 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