计算最大UDP有效载荷大小,以避免在以太网局域网上分裂

发布于 2025-02-10 20:35:23 字数 2100 浏览 2 评论 0原文

我有一个计划,该程序旨在通过千兆以太网LAN发送/接收UDP数据包(注意:不是一般互联网),为了最大化吞吐量,我想让它使其成为数据包尽可能大,而不会引起任何碎裂。

我知道以太网的MTU大小为1500个字节。但是,这些1500个字节不仅由我的应用程序的有效载荷数据,而且由数据包的IP和UDP标头使用,这意味着我需要将有效载荷尺寸降低到这些标头的尺寸,以便适合MTU大小的所有内容并避免分裂。

鉴于这一点,我使用下面显示的代码来计算我应该传递给sendto()的最大有效载荷大小。下面的程序在运行时给出了此输出:

Recommended maximum payload size for an IPv4 packet is 1404 bytes.
Recommended maximum payload size for an IPv6 packet is 1388 bytes.

我的问题是:我的计算是否正确,还是错过了一些重要的细节?

#include <stdio.h>

/** The total maximum size of a UDP packet (including all the headers and payload data) that can be sent
 *  over a network without causing packet fragmentation.  1500 is appropriate for standard Ethernet LANs(?)
 */
const int RAW_MTU_SIZE_BYTES = 1500;

const int POTENTIAL_EXTRA_HEADERS_SIZE_BYTES = 64; /**< Extra room, just in case some router or VLAN headers need to be added to the packet also */

const int IPV4_HEADER_SIZE_BYTES = 24;  /**< Number of bytes in an IPv4 packet header: assumes worst-case scenario (i.e. that the options field is included) */
const int IPV6_HEADER_SIZE_BYTES = 40;  /**< Number of bytes in an IPv6 packet header: assuming no additional header chunks, of course */

const int UDP_HEADER_SIZE_BYTES  = (4*sizeof(short));  /**< Number of additional bytes in a UDP sub-header (sourceport, destport, length, checksum) */

/** Returns the number of application-payload bytes that we can fit into a UDP packet without causing packet fragmentation. */
const int GetRecommendedUDPPayloadSizeBytes(bool isForIPv6)
{
   const int ipHeaderSizeBytes = isForIPv6 ? IPV6_HEADER_SIZE_BYTES : IPV4_HEADER_SIZE_BYTES;
   return RAW_MTU_SIZE_BYTES - (ipHeaderSizeBytes+UDP_HEADER_SIZE_BYTES+POTENTIAL_EXTRA_HEADERS_SIZE_BYTES);
}

int main(int, char **)
{
   printf("Recommended maximum payload size for an IPv4 packet is %i bytes.\n", GetRecommendedUDPPayloadSizeBytes(false));
   printf("Recommended maximum payload size for an IPv6 packet is %i bytes.\n", GetRecommendedUDPPayloadSizeBytes(true));
   return 0;
}

I've got a program that is designed to send/receive UDP packets across a Gigabit Ethernet LAN (note: not the general Internet), and to maximize throughput, I would like to have it make the packets as large as possible without causing any fragmentation.

I understand that the MTU size for Ethernet is 1500 bytes; however those 1500 bytes are used not only by my application's payload data but also by the packet's IP and UDP headers, which means that I need to reduce my payload size by the size of those headers in order to fit everything in under the MTU-size and avoid fragmentation.

Given that, I use the code shown below to calculate the maximum payload size I should pass to sendto(). The program below gives this output when I run it:

Recommended maximum payload size for an IPv4 packet is 1404 bytes.
Recommended maximum payload size for an IPv6 packet is 1388 bytes.

My question is: are my calculations correct, or have I missed some important detail?

#include <stdio.h>

/** The total maximum size of a UDP packet (including all the headers and payload data) that can be sent
 *  over a network without causing packet fragmentation.  1500 is appropriate for standard Ethernet LANs(?)
 */
const int RAW_MTU_SIZE_BYTES = 1500;

const int POTENTIAL_EXTRA_HEADERS_SIZE_BYTES = 64; /**< Extra room, just in case some router or VLAN headers need to be added to the packet also */

const int IPV4_HEADER_SIZE_BYTES = 24;  /**< Number of bytes in an IPv4 packet header: assumes worst-case scenario (i.e. that the options field is included) */
const int IPV6_HEADER_SIZE_BYTES = 40;  /**< Number of bytes in an IPv6 packet header: assuming no additional header chunks, of course */

const int UDP_HEADER_SIZE_BYTES  = (4*sizeof(short));  /**< Number of additional bytes in a UDP sub-header (sourceport, destport, length, checksum) */

/** Returns the number of application-payload bytes that we can fit into a UDP packet without causing packet fragmentation. */
const int GetRecommendedUDPPayloadSizeBytes(bool isForIPv6)
{
   const int ipHeaderSizeBytes = isForIPv6 ? IPV6_HEADER_SIZE_BYTES : IPV4_HEADER_SIZE_BYTES;
   return RAW_MTU_SIZE_BYTES - (ipHeaderSizeBytes+UDP_HEADER_SIZE_BYTES+POTENTIAL_EXTRA_HEADERS_SIZE_BYTES);
}

int main(int, char **)
{
   printf("Recommended maximum payload size for an IPv4 packet is %i bytes.\n", GetRecommendedUDPPayloadSizeBytes(false));
   printf("Recommended maximum payload size for an IPv6 packet is %i bytes.\n", GetRecommendedUDPPayloadSizeBytes(true));
   return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一人独醉 2025-02-17 20:35:23

由于接口的MTU可能与1500不同,因此假设MTU值不是一个好主意。

通常,有一种方法可以从OS(Linux中的SIOCSIFMTU IOCTL)询问网络接口的MTU。

如果数据包路径中有几个链接,则路径MTU可能小于接口的MTU。为了避免路径中的碎片化,您可以使用 path-mtu discovery

正如Ikegami已经评论的那样,IPv4和IPv6数据包可能具有可选的标题内容,以便更难计算最佳有效负载尺寸。

Because MTU of an interface can be different than 1500, it is not good idea to assume value of MTU.

Usually there is a way to ask MTU of a network interface from OS (SIOCSIFMTU ioctl in Linux).

If there are several links in the path of packets, the path MTU can be smaller than the MTU of the interface. For avoiding fragmentation in the path, you could utilize PATH-MTU discovery.

As ikegami already commented, IPv4 and IPv6 packets may have optional header stuff for making calculation of the optimal payload size even harder.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文