1

在我的应用程序中,我使用以下指令打开一个原始套接字(LINUX 内核 3.8.5):

::socket( PF_PACKET, SOCK_RAW, htons((uint16_t)ETH_P_ALL));

一切正常,我能够接收它并将其发送到另一个接口。然而有一段时间

::recvfrom() 

在那个套接字上返回 1518(1504 个有效负载字节 + 14 个 ETH_HLEN)。

当我尝试发送这个 1518 字节的缓冲区时,但是指令

::send(......)

返回 EMSGSIZE(消息太长)。

请注意,在我的 NIC 接口上,MTU 为 1500,因此我预计使用 ::recvfrom 检索的最多 1514(有效负载 + ETH_HLEN)字节

ethtype 是 0x0800 所以它不是 vlan 标记的帧,因此这 4 个字节“额外”不是由于 vlan 标记

你有解释吗?

4

2 回答 2

0

更多关于此事,atm调试问题我有这个配置:

eth0(Server1)------------->eth0(Server2)-----NAT----->dummy0(Server2)

Server1 和 Server2 之间没有交换机,什么都没有,只有一根电缆,dummy0 是使用 dummy 网络模块获得的 NIC。

在 eth0(Server1)“TX 端”和 eth0(Server2)“RX 端”嗅探这就是我得到的:

TX端:

1514 bytes, sequence number  15476 
1514 bytes, sequence number  15477 
1514 bytes, sequence number  15478 
1514 bytes, sequence number  15479

在 RX 方面,我期望相同,但我得到:

1514 bytes, sequence number 15476
1518 bytes, sequence number 15477
1514 bytes, sequence number 15479

有趣的是,虽然没有收到 15478,但那 1518 个字节(序列号 15477)中的最后 4 个字节是丢失的 eth 数据包有效负载中的前 4 个字节。

已解决:这是 GRO 选项,确实感谢 ::rcv 上的该选项能够一次获得 2 个或更多以太网帧,这就是为什么例如序列号“出现”丢失(实际上它与以前的一),对于某些数据包我得到 1518 是由于在 ::rcv 传递的缓冲区的大小,传递一个更大的缓冲区确实我没有丢失任何内容。

于 2013-06-28T16:40:51.077 回答
0

我的理解是 MTU 是特定于连接的,因为它取决于从源到目标的整个路径 - 而不仅仅是您的本地接口。如果您发送到的地址与您从中欺骗数据包的地址不同,则 MTU 可能不同似乎很合理。

引用Linux 手册页

启用 PMTU 发现后,内核会自动跟踪每个目标主机的路径 MTU。当它通过 connect(2) 连接到特定对等体时,可以使用 IP_MTU 套接字选项方便地检索当前已知的路径 MTU(例如,在发生 EMSGSIZE 错误之后)。它可能会随着时间而改变。对于具有多个目标的无连接套接字,也可以使用错误队列访问给定目标的新 MTU(请参阅 IP_RECVERR)。每个传入的 MTU 更新都会排队一个新错误。

于 2013-06-27T13:47:53.100 回答