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

У меня есть классы 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)

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

1 Ответ

0 голосов
/ 06 июня 2018

Размер очень четко определен в 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.

...