zrunningz 2022-02-13 02:01
浏览 50
已结题

关于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层或硬件)去实现?这么做的理由是是什么呢?真的合理吗?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 2月21日
    • 创建了问题 2月13日

    悬赏问题

    • ¥60 求一个简单的网页(标签-安全|关键词-上传)
    • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
    • ¥15 基于卷积神经网络的声纹识别
    • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
    • ¥100 为什么这个恒流源电路不能恒流?
    • ¥15 有偿求跨组件数据流路径图
    • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
    • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
    • ¥15 一直显示正在等待HID—ISP
    • ¥15 Python turtle 画图