Как MTU составляет 65535 в UDP, но Ethernet не позволяет размер кадра более 1500 байт

11

Я использую быструю сеть Ethernet со скоростью 100 Мбит / с, размер кадра которой меньше 1500 байт (1472 байт для полезной нагрузки согласно моему учебнику). Таким образом, я смог отправить и получить пакет UDP размером 65507 байт, что означает, что размер пакета был 65507 + 20 (заголовок IP) + 8 (заголовок UDP) = 65535.

Если сам размер полезной нагрузки кадра составляет максимум 1472 байта (согласно моему учебнику), как размер пакета IP может быть больше, чем тот, который здесь равен 65535?

Я использовал код отправителя как

char buffer[100000];
for (int i = 1; i < 100000; i++)
{
    int len = send (socket_id, buffer, i);
    printf("%d\n", len);
}

Код получателя как

while (len = recv (socket_id, buffer, 100000))
{
     printf("%d\n". len);
}

Я заметил, что send returns -1на i > 65507и recvпечатает или получает пакет maximum of length 65507.

sysadmin1138
источник

Ответы:

11

UDP датаграммы не имеют ничего общего с размером MTU, вы можете сделать его настолько большим, насколько вам нравится, вплоть до 64K - максимум, упомянутый выше. Вы даже можете отправить один из них во всем пакете, если вы используете гигантские кадры, размер которых больше, чем большая датаграмма.

Однако большие кадры должны поддерживаться всем оборудованием, через которое будет проходить кадр, и это проблема. Для практических целей кадры Ethernet являются наиболее распространенным размером передачи, MTU для них составляет около 1500 байтов, я скажу 1500 вперед, но это не всегда. Когда вы создаете дейтаграмму UDP, превышающую базовый MTU (который, как указано, чаще всего это Ethernet), он будет незаметно разбит на несколько кадров в 1500 байт. Если вы tcpdump этот трафик, вы увидите несколько пакетов, разбитых на границе MTU, у которых будет установлен флаг больше фрагментов вместе с номером фрагмента. Первый пакет будет иметь номер фрагмента 0 и установить больше фрагментов, а последний пакет будет иметь ненулевой номер фрагмента и больше фрагментов не будет установлено.

Так зачем заботиться? Детали реализации действительно имеют значение. Фрагментация может снизить производительность в сети, теперь это не большая проблема, но об этом следует помнить. Если использовался огромный размер дейтаграммы, то в случае потери какого-либо фрагмента все дейтаграммы необходимо будет повторно отправить. В равной степени при больших объемах, и сегодня это совершенно достижимые объемы, тогда возможно неправильное объединение кадров при повторной сборке. Могут также возникнуть проблемы с получением фрагментированных пакетов UDP для прохождения через конфигурации корпоративного брандмауэра, где распределители нагрузки распределяют пакеты, если один фрагмент находится на одном брандмауэре, а другой - на другом, тогда трафик будет отброшен как неполный.

Поэтому не создавайте дейтаграммы UDP больше, чем фрагментация по размеру MTU, если только вам не нужно, и если вы должны указать, что инфраструктура, с которой осуществляется обмен данными, близка (та же подсеть близка), и в этом случае кадры-гиганты, вероятно, будут хорошим вариантом.

Мартын А
источник
Хорошая информация о «флаге больше фрагментов». Это флаг в заголовке UDP или в заголовке IP?
Иоанн Иисус
Примечание. Некоторые ОС НЕ будут передавать UDP, если данные будут фрагментированы. IE Linux док,By default, Linux UDP does path MTU (Maximum Transmission Unit) discovery. This means the kernel will keep track of the MTU to a specific target IP address and return EMSGSIZE when a UDP packet write exceeds it.
Рахли
2

Уровень IP фрагментирует ваш пакет на передающей стороне, а затем снова собирает его обратно на принимающей стороне, прежде чем передать его в UDP. На уровне UDP вы не можете сказать, что пакет был фрагментирован. Если вы используете инструмент захвата пакетов, такой как Wireshark , вы должны увидеть, что ваш компьютер получает IP-пакеты, ограниченные MTU.

Джефф
источник
1

Оказывается, что разрешение стеку TCP / IP фрагментировать пакеты по мере необходимости намного меньше затрат, чем отправка отдельных пакетов.

geekosaur
источник
1
Вы имеете в виду, что TCP / IP фрагментирует и собирает сам себя? Если да, то почему люди все время говорят, что ваш код должен позаботиться о повторной сборке на стороне получателя. Я не наблюдал фрагментации на данный момент, но видел много форумов, которые говорят это, и даже люди, принимающие это.
Для тех из нас, у кого есть проблема с моделью OSI, не могли бы вы добавить немного больше подробностей в свой ответ?
Роберт Харви
Я был немного придирчивым, потому что я не могу сказать, если это домашняя работа или нет. Это компромисс: поскольку UDP не дает никаких гарантий доставки, если какой-либо фрагмент пакета отбрасывается, весь пакет теряется. Если вам нужен надежный транспорт поверх UDP, вам нужно справиться со всем этим самостоятельно; но если вы делаете (скажем) потоковые протоколы (или NFS через UDP, который принял путь, подобный потоковому), то снижаются издержки либо просто отбросить эти пакеты, либо повторно передать больший пакет после длительной задержки, если это необходимо. Вы должны сбалансировать свои потребности с функциями протокола и накладными расходами протокола.
geekosaur
1

UDP ничего не знает о MTU. Пакеты UDP могут иметь любой размер от 8 до 65535 байтов. Уровни протокола ниже UDP либо могут отправить пакет определенного размера, либо отклонят отправку этого пакета с ошибкой, если она слишком велика.

Уровень ниже UDP обычно IP, либо IPv4, либо IPv6. И IP-пакет может иметь любой размер от 20 (IPv4) / 40 (IPv6) до 65535 байтов, это столько же, сколько UDP. Однако IP поддерживает механизм, называемый фрагментацией . Если IP-пакет больше по размеру, чем тот, который может транспортировать нижний уровень, IP может разделить один пакет на несколько пакетов, называемых фрагментами. Каждый фрагмент фактически является собственным IP-пакетом (имеет собственный IP-заголовок) и также сам отправляется в пункт назначения; Задача получателя состоит в том, чтобы собрать все фрагменты и восстановить из них полный пакет перед передачей полученных данных на следующий более высокий уровень (например, UDP).

Протокол Ethernet может передавать только кадры с полезной нагрузкой от 46 до 1500 байт (есть исключения, но это выходит за рамки этого ответа). Если данные полезной нагрузки меньше 46 байтов, они дополняются до 46 байтов. Если данные полезной нагрузки превышают 1500 байт, интерфейс откажется принять их. Если это произойдет, то теперь IP-уровень решит либо фрагментировать пакет, чтобы ни один фрагмент не был длиннее 1500 байт, либо сообщить об ошибке следующему более высокому уровню, если фрагментация была отключена или запрещена для этого конкретного соединения.

Фрагментации, как правило, следует избегать, так как

  • Это тратит впустую ресурсы на стороне отправителя.
  • это тратит впустую ресурсы на стороне получателя.
  • это увеличивает издержки протокола для того же объема данных полезной нагрузки.
  • если один фрагмент потерян, весь пакет потерян.
  • если один фрагмент поврежден, весь пакет будет поврежден.
  • в случае повторной отправки все фрагменты должны быть повторно отправлены.

Вот почему TCP разумно принимает свой размер кадра, так что пакетам никогда не требуется IP для их фрагментации. Это можно сделать, запретив IP фрагментировать пакеты, и если IP сообщает, что пакет слишком велик для отправки, TCP уменьшает размер кадра и повторяет попытку, пока больше не сообщается об ошибке.

Для UDP, однако, это будет задачей самого приложения, поскольку UDP является «тупым» протоколом, у него нет собственной логики управления, что делает его очень гибким, быстрым и простым.

Единственный размер UDP, на который можно всегда ориентироваться, - это 576 минус 8 байтов заголовка UDP и минус 20 (v4) / 40 (v6) байтов IP, поскольку стандарт IP требует, чтобы каждый хост IP мог принимать IP-пакеты с общий размер 576 байт. Реализация вашего протокола не будет соответствовать стандарту, если он не может принимать пакеты хотя бы такого размера. Обратите внимание, однако, что стандарт не говорит 576 без фрагментации, поэтому даже пакет из 576 байтов IP может быть фрагментирован между двумя хостами.

Единственный размер пакета, который вы можете использовать для переноса без фрагментации, составляет 24 байта для IPv4 и 56 байтов для IPv6, так как наименьшие заголовки IP для фрагмента составляют 20/48 байтов (v4 / v6), а фрагмент должен иметь как минимум 4/8 байт (v4 / v6) данные полезной нагрузки. Таким образом, транспортная система ниже уровня IP, которая не может транспортировать по меньшей мере пакеты этих размеров, не может использоваться для транспортировки IP-трафика.

И прежде чем кто-либо прокомментирует, что заголовок IPv6 имеет только 40 байтов: это правильно, но, в отличие от заголовка IPv4, стандартный заголовок IPv6 не имеет полей заголовка для фрагментации. Если пакет должен быть фрагментирован, то заголовок расширения фрагментации должен быть добавлен ниже базового заголовка IPv6, и этот заголовок расширения имеет длину 8 байтов. Кроме того, в отличие от IPv4, смещения фрагментации в IPv6 подсчитываются в 8 байтах, а не в 4 байтовых единицах, таким образом, фрагмент может переносить только полезную нагрузку, кратную 8 байтов в случае IPv6.

Mecki
источник
0

Чтобы ответить на ваш вопрос: «Если сам размер полезной нагрузки кадра составляет максимум 1472 байта (согласно моему учебнику), как размер пакета IP может быть больше, чем тот, который здесь равен 65535?»

Это происходит из-за функции разгрузки, называемой UFO. (UDP Fragmentation Offload). Пожалуйста, обратитесь к этой ссылке.

Вы можете проверить и отключить функции разгрузки через ethtool -k ethX и ethtool -K ethX соответственно.

Нехал Даттани
источник
0

Если вы отслеживаете исходящие кадры, возможно, ваш сетевой адаптер поддерживает разгрузку сегментации и он включен. С включенной разгрузкой сегментации сетевая карта сама обрабатывает сегментирование пакета / кадра в соответствующий размер, а не сетевой стек. Это освобождает процессор компьютера для выполнения других задач, повышая производительность. В linux ethtool -k [устройство] покажет флаги разгрузки.

Эндрю Бауэрс
источник