skb校验和计算功能可能导致系统挂起

时间:2019-02-26 11:31:26

标签: c networking tcp linux-kernel kernel-module

在Linux论坛上的asking about the same problem和一些错误测试之后,我获得了以下与我的问题有关的信息:

我正在构建一个应用程序,该应用程序将内核网络挂钩的传入数据包转移到用户空间中的代理,该应用程序从tcp套接字读取数据,然后将其发送到其原始目的地。当数据包进入时,我将skb目标地址更改为我的代理tcp服务器的地址,当数据包离开时,我更改了源地址,以便通信可以透明地进行。

我遇到了以下问题:

当输入大量数据时,它们可以毫无问题地到达代理服务器。

但是,当将数据发送到原始目的地时,如果我发送了足够多的数据,则系统将挂起。 Caveman调试显示skb仅在离开代理时是非线性的,并且没有调用skb_linearize时,校验和无法成功计算。

当数据退出并且我自己的代码中似乎没有内存错误时,我自己没有在内核中分配任何数据,因此我得出结论,问题很可能出在我的用法skb_linearize上函数,或者我通常如何计算校验和:

void fixChecksum(struct sk_buff *skb)
{
    if(skb_is_nonlinear(skb))
    {
        skb_linearize(skb);
    }
    struct iphdr *ip_header = ip_hdr(skb);
    struct tcphdr *tcp_header = (struct tcphdr*)(skb_network_header(skb) + ip_hdrlen(skb));
    int tcplen = (skb->len - ((ip_header->ihl )<< 2));
    tcp_header->check=0;
    tcp_header->check = tcp_v4_check(tcplen, ip_header->saddr, ip_header->daddr,csum_partial((char*)tcp_header, tcplen,0));
    skb->ip_summed = CHECKSUM_NONE; //stop offloading
    ip_header->check = 0;
    ip_header->check = ip_fast_csum((u8 *)ip_header, ip_header->ihl);
}

我怀疑我以某种方式传输的数据保留在内核中,并且在足够多的数量之后内核耗尽并且系统挂起。 但是我看不出这里有什么问题。 我还尝试将skb_linearize更改为skb_linearize_cow,但无济于事。

在处理之后,在LOCAL_OUT钩上处理的skb是否有可能没有被释放?

我的内核版本为3.2

1 个答案:

答案 0 :(得分:0)

因此,在我的程序运行时进行了更多的调试和检查内核内存使用情况后,结果发现它并没有随每个数据包一起增长。在删除我添加的功能之一中的自旋锁后,它停止了锁定,因为我想让模块函数在系统调用之间保持线程安全。显然我不知道自己在做什么,繁重的工作可能会导致死锁或其他原因,这很奇怪,因为我只有一把锁。谢谢任何人尝试提供帮助,对于浪费您的时间表示抱歉。