Hello,
On Thu, 24 Jul 2014, Julian Anastasov wrote:
> 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?
I just saw that changing skb->transport_header
before skb_reset_inner_headers() and iptunnel_handle_offloads()
can cause problems. Not sure if skb->transport_header
is used later when skb->encapsulation = 1, the strange thing
is that ip6_tnl_xmit2() changes it before skb_reset_inner_headers(),
this can lead to wrong skb->inner_transport_header.
[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 | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 73ba1cc..e093580 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;
}
@@ -862,14 +861,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_unlock;
+
+ 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.
@@ -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;
@@ -953,6 +959,12 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct
ip_vs_conn *cp,
old_iph = ipv6_hdr(skb);
}
+ if (!skb->encapsulation) {
+ skb_reset_inner_headers(skb);
+ skb->encapsulation = 1;
+ }
+ skb_forward_csum(skb);
+
skb->transport_header = skb->network_header;
skb_push(skb, sizeof(struct ipv6hdr));
--
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
|