【问题标题】:UDP with gso doesn't receive the entire message带有 gso 的 UDP 没有收到整个消息
【发布时间】:2020-12-14 17:43:43
【问题描述】:

我正在尝试使用带有 GSO(通用分段卸载)的 UDP 来发送 50Kb 大小的数据包。

// sender side 
int val = 1472; // ETHERNET - udp - upv4 header
if (setsockopt(fdt, SOL_UDP, UDP_SEGMENT, &val, sizeof(val)))
    error(1, errno, "setsockopt udp segment");
int ret = sendmsg(fd, msg, flags);

关于recv大小,我愿意

// recv side 
int ret = recvmsg(fd, msg, flags);

我可以看到我发送了 50Kb 的消息,而接收方只收到了 1472 个呼叫。我听说过 GRO(通用接收卸载),但我没有在网上找到任何示例。我是否必须进行多个系统调用才能获取所有数据,是否可以设置一个 socekt 选项或进行系统调用以一次性接收重新组装的消息?如果我必须进行多个系统调用,而不是仅仅依靠 IP 分片并发送大于 MTU 的数据包,如何才能更有效?

【问题讨论】:

  • 发送过大的 UDP 数据包不是我所相信的,尤其是中间可能有多少层 NAT 和状态防火墙。您不能将传输分割成更小的块或使用 TCP 流式传输吗?
  • 作为注释 1472 (ish) 是关于您对分段数据包序列的第一个数据包的期望。
  • @tadman:我确信一个 recvmsg 只收到了分段消息序列中第一个数据包的 1472 个,我认为 UDP GRO 应该重新组装所有分段数据包并返回整个消息。
  • @tadman:此外,数据通过以太网在直接连接的 ECU 之间传输。没有重新路由,NAT 或任何东西。 1472 几乎是我们可以发送的最大安全数据包。
  • UDP 数据报理想情况下约为 576 个八位字节,并且您永远不会希望发送导致数据包大于您的路径 MTU 的数据报(您可以使用 PMTUD 发现最小的 MTU路径)。您丢失数据报,它们越小,您丢失的越少。此外,智能站点现在有防火墙丢弃数据包碎片(第一个通过,但其余的碎片被丢弃)以防止碎片攻击。

标签: c++ c networking tcp udp


【解决方案1】:

这是一个有趣的article,您可以阅读以深入了解 GSO 和 GRO。 Ethtool 可能能够在特定接口上启用/禁用 GRO。取决于版本。如果你能适应它,那就最好了。

如果不是,由于 Linux 网络堆栈非常复杂,因此很难仅通过结果来检查哪个部分导致该段失败。我认为最好使用netstat,ss,sar,tcpdump,wireshark等工具来分析每一层,然后更容易知道哪里出错了。但不要忘记检查您的硬件是否支持此功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 2018-05-31
    • 2015-09-28
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多