Сколько данных я могу отправить в одном UDP-пакете и при этом избежать фрагментации?

У меня есть классы C ++, которые обрабатывают отправку и получение пакетов UDP. Пока я использовал их для отправки сигналы (PING, WAKEUP, …) другими словами, очень маленькие пакеты и никогда не было проблем.

Теперь я хотел бы отправить большие блоки данных (т.е. 0,5 МБ), но чтобы оптимизировать возможность потери пакетов, я хочу иметь возможность выполнять свою собственную фрагментацию. Сначала я написал функцию, которая дает мне размер MTU:

int udp_server::get_mtu_size() const
{
if(f_mtu_size == 0)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
if(ioctl(f_socket, SIOCGIFMTU, &ifr) == 0)
{
f_mtu_size = ifr.ifr_mtu;
}
else
{
f_mtu_size = -1;
}
}

return f_mtu_size;
}

Примечание: я знаю о PMTUD, который эта функция игнорирует. Как упомянуто ниже, это должно работать в контролируемой сети, поэтому путь MTU не только изменится для нас.

Эта функция может вернуть 1500 под Linux.

Что на самом деле неясно и кажется противоречивым во многих ответах, так это то, что размер в 1500 байт будет не только моей полезной нагрузкой. Возможно, он будет включать в себя некоторые заголовки, которые я не контролирую (например, заголовок Ethernet + нижний колонтитул, заголовок IPv4, заголовок UDP).

Из некоторых других вопросов и ответов кажется, что я могу послать 1500 байт данных без фрагментации, при условии, что все мои MTU 1500.

Итак … Что это правда?

  1. Мой буфер данных может иметь размер, равный MTU

  2. Мой буфер данных должен быть MTU - sizeof(various-headers/footers)

Постскриптум Сеть является локальной сетью, которую мы контролируем на 100%. Пакеты будут передаваться с одного главного компьютера на набор подчиненных компьютеров с использованием многоадресной рассылки UDP. Между ними есть только один коммутатор 1 Гбит / с. Ничего более.

-1

Решение

Размер очень четко определен в RFC-8085: Правила использования UDP.

https://tools.ietf.org/html/rfc8085#section-3.2

Есть соответствующий бит о расчете размера для полезной нагрузки.

Чтобы определить подходящий размер полезной нагрузки UDP, приложения ДОЛЖНЫ вычесть размер заголовка IP (который включает в себя любые необязательные заголовки IPv4 или дополнительные заголовки IPv6), а также длину заголовка UDP (8 байтов) из размера PMTU. Этот размер, известный как максимальный размер сегмента (MSS), может быть получен из стека TCP / IP [RFC1122].

Таким образом, в C / C ++ это становится:

#include <netinet/ip.h> // for iphdr
#include <netinet/udp.h> // for udphdr

int mss(udp.get_mtu_size());
mss -= sizeof(iphdr);
mss -= sizeof(udphdr);

ПРЕДУПРЕЖДЕНИЕ: Размер IP-заголовка зависит от параметров. Если вы используете параметры, которые увеличивают размер, ваши вычисления MSS должны учитывать это.

Размер заголовка и нижнего колонтитула Ethernet здесь не учитывается, поскольку они прозрачны для пакета UDP.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]