我正在 Linux 平台上开发以太网驱动程序。我发现当发生TCP重传时,引用相同序号数据包的多个重传数据包的TCP负载是不同的。我不明白为什么会这样。在我的驱动程序中,我只是分配了一个没有任何特定标志的普通网络设备。顺便说一句,这些重传数据包中的 TCP 校验和字段也是错误的,但是所有其他类型的 TCP 数据包中的校验和都是正确的,例如 SYNC、ACK 和 DUP ACK。
我是用wireshark抓包的,也就是说我抓到的包不是我的驱动处理的,只是来自Linux内核的TCP栈。但是当我用其他以太网设备和驱动程序进行测试时,并没有出现这个问题。所以我的问题如下。
- TCP 堆栈是否有可能在没有相同负载的情况下重传相同的数据包?
- Linux内核中的哪些参数会导致这些问题?
- 我的驱动程序如何导致此问题?
最佳答案
感谢您的所有回复。
我找到了这个问题的原因。这是一个非常非常愚蠢的错误。
由于使所有 DMA 缓冲区(在我的驱动程序中是 skb->data)地址对齐到 4 字节,我调用了一个 memmove 函数来做到这一点。实际上,skb->data 引用的数据由内核中的所有 TCP/IP 堆栈共享。所以在这个错误的操作之后,当发生TCP重传时,TCP栈中skb->data引用的地址仍然保持原来的地址。这就是为什么基于原始数据的校验和在 wireshark 中似乎是错误的。我的驱动程序中的代码如下。
u32 skb_len = skb->len;
u32 align = check_aligned(skb);
if !align
return skb;
skb_push(skb,align);
memmove(skb->data, skb->data+align, skb_len);
skb_trim(skb, skb_len);
return skb;
我希望我的经验可以帮助其他人避免这种愚蠢的错误。
关于linux-kernel - 相同数据包的 TCP 重传,但具有不同的 TCP 负载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29658336/