Hello,
On Thu, 24 Jul 2014, Alex Gartrell wrote:
> So I've found a patch that addresses the problem in what I suspect is the
> right way.
>
> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
> index 6f70bdd..ea7ef5e 100644
> --- a/net/netfilter/ipvs/ip_vs_xmit.c
> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
> @@ -486,6 +486,7 @@ static inline int ip_vs_tunnel_xmit_prepare(struct
> sk_buff *skb,
> if (ret == NF_ACCEPT) {
> nf_reset(skb);
> skb_forward_csum(skb);
> + skb->encapsulation = 1;
> }
> return ret;
> }
>
> Empirically, this solves my problem :) I believe it solves the problem more
> generally as well.
>
> Digging deeper into the v6 case (FB <3's v6)
>
> ip_vs_tunnel_xmit_v6
> -> ip6_local_out
> -> __ip6_local_out
> -> dst_output
> -> dst_output_sk
> -> skb_dst(skb)->output (= ip6_output)
> -> ip6_finish_output
> -> ip6->finish_output2
> -> neigh_direct_output
> -> dev_queue_xmit
> -> __dev_queue_xmit
> -> dev_hard_start
>
> And then we run into this:
>
> /* If encapsulation offload request, verify we are testing
> * hardware encapsulation features instead of standard
> * features for the netdev
> */
> if (skb->encapsulation)
> features &= dev->hw_enc_features;
>
> This essentially strips out NETIF_F_ALL_CSUM, so we end up invoking
> skb_checksum_help below.
For the case with missing NETIF_F_ALL_CSUM bits
skb_checksum_help() does not care for skb->encapsulation,
it works only by checking skb->csum_* fields. The
skb_set_inner_transport_header() and skb_set_transport_header()
calls simply update the header pointers for the drivers
that have NETIF_F_ALL_CSUM bits set.
What is your driver? I have to check why do you
have problem when NETIF_F_ALL_CSUM is not set. Is it
missing the NETIF_F_IP_CSUM (v4) and NETIF_F_IPV6_CSUM (v6) bits?
Also, can you clarify again which test has
the problem with broken csums? All 3 tests? Or it
depends on enabled HW csums?
> /* If packet is not checksummed and device does not
> * support checksumming for this protocol, complete
> * checksumming here.
> */
> if (skb->ip_summed == CHECKSUM_PARTIAL) {
> if (skb->encapsulation)
> skb_set_inner_transport_header(skb,
> skb_checksum_start_offset(skb));
> else
> skb_set_transport_header(skb,
> skb_checksum_start_offset(skb));
> if (!(features & NETIF_F_ALL_CSUM) &&
> skb_checksum_help(skb))
> goto out_kfree_skb;
> }
>
> Does this seem like a reasonable approach to you, Julian?
Exactly, I was referring to this place. For IPv4
we do the same as your change in ip_vs_tunnel_xmit_prepare,
only that it is via iptunnel_handle_offloads() which in
addition to setting skb->encapsulation adds SKB_GSO_IPIP bit
for GSO purposes but skb_checksum_help() is called again
in dev_hard_start_xmit().
Don't forget that the devices with NETIF_F_ALL_CSUM set
need skb_reset_inner_headers() call, they use the
skb->inner_* fields. What I have done in the patch is
just to copy the handling from ip*_tunnel*.c. When
NETIF_F_ALL_CSUM is not set we call skb_checksum_help() and
then the device driver detects CHECKSUM_NONE, not
CHECKSUM_PARTIAL.
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
|