为什么Linux原始套接字的RX环限制为4GB?

时间:2018-04-16 14:33:02

标签: linux linux-kernel network-programming raw-sockets

背景

我正在尝试在{strong> 64位 Linux应用程序中mmap()原始套接字的RX环形缓冲区。我的戒指由4096块大小为1MB的块组成,总共4GB。 (注意,每个1MB块中可以有很多帧。See this doc for background if you're curious.

问题

不幸的是,使用带有选项setsockopt()的{​​{1}}配置时,RX环缓冲区的大小似乎有4GB的限制。对我来说,这意味着我不能再增加我的块大小或我的戒指尺寸。我的申请将受益于增加。

此限制至少在Linux内核的现代版本中强制执行。 See the source here.

(请注意,PACKET_RX_RING没有大于4GB的问题。我最初偶然发现this question。)

问题

为什么RX环形缓冲区的限制为4GB?如果从32位迁移内核的这部分内容时出现错误,那将很酷并且可能很容易进行修补。但是,如果有更根本的原因,我很想知道那可能是什么。

2 个答案:

答案 0 :(得分:1)

这是部分答案。让我们来看看如何分配PACKET_MMAP环形缓冲区结构及其缓冲区。这是通过致电alloc_pg_vecline 4270完成的。结构本身只是一个指针数组,使用kcalloc分配,它的上限为131,072字节。如果每个指针的大小为8字节,则最多可以有131,072/8 = 16,384 = 2 14 块。每个块使用alloc_one_pg_vec_page分配。请注意,每个块在内存中必须是连续的,其大小必须是页面大小的倍数(4096字节)。传递给order的{​​{1}}参数表示每个缓冲区要分配为2的幂的页数。 mmzone.h中定义的顺序有限制,alloc_pg_vec = 11.因此,最大块大小为4096 * 2 11 = 2 23 < / sup> = 8 MiB。 这意味着整体环限制为2 37 字节或128 GiB

我不知道检查MAX_ORDER的原因。可能是因为早期版本的Linux支持较少数量的缓冲区和缓冲区大小(在Linux 2.4中req->tp_block_size > UINT_MAX / req->tp_block_nr为10)。但也许通过删除检查,您可以分配最大128 GiB的环。

答案 1 :(得分:1)

这是一个错误。我提交了一个补丁来解决此问题(现已合并): https://github.com/torvalds/linux/commit/fc62814d690cf62189854464f4bd07457d5e9e50