我试图计算正在发送的skb上的TCP / UDP标头校验和。
基本上,有两个功能可以完成所有工作 (也在this stackoverflow question和this one too中提及):
csum_tcpudp_magic
csum_partial
例如,对于TCP:
tcph->check = 0;
tcph->check = csum_tcpudp_magic(iph->saddr,
iph->daddr,
tcp_packet_len,
IPPROTO_TCP,
csum_partial((unsigned char *)tcph,
tcp_packet_len,
0));
这很好用 - 我能够传输TCP / UDP数据包并在接收端使用wireshark验证校验和。但是,我无法找到有关碎片化SKB的任何信息。
这两个魔法会不会出现? TCP / UDP有效负载碎片时的函数句柄?
此外,TCP / UDP标头可能位于SKB的非线性部分(也是碎片)。
这些功能是否也会处理?
我确实理解我可以尝试使用更大的数据包,这会导致它们碎片化,但现在错误处理的代价是内核oops,我无法将系统关闭。< / p>
答案 0 :(得分:4)
csum_tcpudp_magic
和csum_partial
无法使用碎片skb。
如果要使用它们来计算TCP / UDP校验和,我需要使所有数据包有效负载驻留在skb的线性部分。
幸运的是,Linux中有一个实用功能就是这样做 - skb_linearize
。
基本上,流程是:
if (unlikely(skb_linearize(skb) != 0))
... goto drop - no memory...;
... do whatever you want with data ...
tcph->check = 0;
tcph->check = csum_tcpudp_magic(iph->saddr,
iph->daddr,
tcp_packet_len,
IPPROTO_TCP,
csum_partial((unsigned char *)tcph,
tcp_packet_len,
0));
如果无法进行线性化(性能,内存或其他原因),则需要手动计算校验和。
答案 1 :(得分:0)
此代码运行时,数据包已重新组装。