关于Linux内核对tcp_v4_send_check实现的变化问题

问题发现

最近使用ebpf的tc classifier对tcp数据进行处理时,发现tcp头部的校验和仅仅包含伪头部的校验和。
于是我使用ethtool的tx off关闭了硬件卸载,却发现tc classifier获得的tcp校验和仍为tcp伪头部的校验和(此时获得的udp校验和符合预期)

问题分析

排除了硬件卸载的问题(因为已经运行了ethtool -K eth0 tx off,且UDP数据包的校验和没有问题),因此看了一下linux对发送校验和的实现;发现目前tcp_v4_send_checksum的实现如下:

void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr)
{
    struct tcphdr *th = tcp_hdr(skb);

    th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0);
    skb->csum_start = skb_transport_header(skb) - skb->head;
    skb->csum_offset = offsetof(struct tcphdr, check);
}

但之前内核版本(参见https://github.com/hustcat/hustcat.github.io/blob%E4%B8%AD%E7%9A%84checksum-in-kernel.md)%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%A6%82%E4%B8%8B:

static void __tcp_v4_send_check(struct sk_buff *skb,
                __be32 saddr, __be32 daddr)
{
    struct tcphdr *th = tcp_hdr(skb);

    if (skb->ip_summed == CHECKSUM_PARTIAL) { ///HW CSUM
        th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0); ///add IPv4 pseudo header checksum
        skb->csum_start = skb_transport_header(skb) - skb->head;
        skb->csum_offset = offsetof(struct tcphdr, check);
    } else {
        th->check = tcp_v4_check(skb->len, saddr, daddr,
                     csum_partial(th,
                              th->doff << 2,
                              skb->csum)); ///ip_summed == CHECKSUM_NONE
    }
}

所以就想请教一下,是否表明新版的linux内核中在计算tcp校验和时忽略了网卡的属性而直接尝试将tcp的发送校验和放到下层(ip层或硬件)去实现?这么做的理由是是什么呢?真的合理吗?