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

标签 c networking tcp linux-kernel kernel-module

asking about the same problem之后在 Linux 论坛和一些错误测试中,我有以下似乎与我的问题相关的信息:

我正在构建一个应用程序,它将传入的数据包从内核网络 Hook 转移到用户空间中的代理,该代理从 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 钩子(Hook)上处理的 skb 是否有可能在处理后没有被释放?

我的内核版本是3.2

最佳答案

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

关于c - skb校验和计算功能可能导致系统挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54884557/

相关文章:

performance - Hadoop CDH5使用1个MapReduce TaskTracker在10个节点上的最高网络性能

go - 使用DOS和DOSBox的IPX网络(在Raspbian下)

c - Arduino 从服务器问题中得到响应

tcp - 你如何解读这句话?

c - 在 C 中使用 sin() 的 math.h 链接器错误

我可以用模块替换 Linux 内核函数吗?

android - 如何判断经纬度是否准确

在我关闭连接或退出客户端应用程序之前,golang 连接不会写入

c - 第一个函数调用分配一个变量。隐式声明?

c - msgrcv() 中的错误 :receiving data through message queue in C