skb校验和计算功能可能导致系统挂起
skb checksum computing function probably causes system hang
在 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
钩子上处理的skbs有没有可能在我处理完它们后没有被释放?
我的内核版本是3.2
因此,在我的程序运行时进行更多调试和检查内核内存使用情况后,发现它并没有随着每个数据包而增长。在我删除我添加的一个函数中的自旋锁后,它停止锁定,因为我想在系统调用之间保持我的模块函数线程安全。显然我不知道我在做什么,重负载可能导致死锁或其他什么,这很奇怪,因为我只有一把锁。谢谢,如果有人试图提供帮助,抱歉浪费您的时间。
在 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
钩子上处理的skbs有没有可能在我处理完它们后没有被释放?
我的内核版本是3.2
因此,在我的程序运行时进行更多调试和检查内核内存使用情况后,发现它并没有随着每个数据包而增长。在我删除我添加的一个函数中的自旋锁后,它停止锁定,因为我想在系统调用之间保持我的模块函数线程安全。显然我不知道我在做什么,重负载可能导致死锁或其他什么,这很奇怪,因为我只有一把锁。谢谢,如果有人试图提供帮助,抱歉浪费您的时间。