Hi Jason,

On 08/12/2018 11:13 AM, Jason A. Donenfeld wrote:

Thanks a lot for this patch and for the nice write-up. I'm still not
sure, though, that I totally understand the checksumming semantics
properly.
Neither do I :) But skbuff.h gives quite clear instructions about
CHECKSUM_PARTIAL semantics and handling for outgoing packets, namely:

...the driver MUST ensure that the checksum is set correctly. A driver can either offload the checksum calculation to the device, or call skb_checksum_help (in the case that the device does not support offload for a particular checksum).

So the usage of skb_checksum_help is mandatory, because Wireguard device itself doesn't have any HW offload capabilities, obviously. But anyway, WG device must advertise NETIF_F_HW_CSUM capability, otherwise networking stack will not feed GSO super packets to it, that's what I have understood while analyzing the root cause of this checksum bug.

As expected, the bug can also be fixed by removing NETIF_F_HW_CSUM bit from dev features, but it disables GSO, so not good.


Your paranoid proposal at the end of your description would be
something like this?

if (skb->ip_summed == CHECKSUM_PARTIAL || !skb_checksum_setup(skb, true)) {
    if (skb_checksum_help(skb))
        return false;
}

And the bug you're pointing out is that skb_checksum_setup returns
-EPROTO in the case of GRE and such, because a child function,
skb_checksum_setup_ip, only works for UDP/TCP?

Yes and yes.

Do you know why there exist these two separate functions in the first
place, and what the preferred use cases are for each one?
If you are referring to skb_checksum_help and skb_checksum_setup, then they serve different purposes. skb_checksum_help being a supper widely used function to finalize partial checksum calculation in case there is no HW offload caps (exactly WG case, as it's a virtual device), whereas skb_checksum_setup is a function which basically re-calculates checksum offset inside skb based on known protocols (only TCP/UDP!) and optionally re-calculates the checksum of pseudo-headers which _is_ somewhat costly operation and original code does request it by calling skb_checksum_setup(skb, true).

So for me it doesn't make sense to call this heavy "setup" function for an skb which came directly from the networking stack and we known it's been properly setup.

Also, do you
know about the relative performance of them and how your patch or the
paranoid variant above would impact that?
My patch should only increase the performance, because it eliminates unnecessary re-initialization of partial checksum and pseudo-header summation.

I've just realized that paranoid version could even violate the rules. Imagine, there is an skb with ip_summed _not_ equal to CHECKSUM_PARTIAL, in this case we would try to forcibly setup partial checksum for this packet and finalize it, which doesn't sound right to me, because other ip_summed values don't require the driver to tinker with checksum.

_____
BR, Andrey
_______________________________________________
WireGuard mailing list
WireGuard@lists.zx2c4.com
https://lists.zx2c4.com/mailman/listinfo/wireguard

Reply via email to