PMTUD: а был ли он? Ответы на вопросы.

Некоторое время назад я публиковал статью PMTUD: а был ли он? Кейс из практики. Возможно, вы помните несколько вопросов в конце статьи, которые я задавал для тренировки. Итак, я готов дать свои ответы.

Сразу хочу сказать, что это мое мнение, у вас могут быть свои варианты, которые я с удовольствием выслушаю (кстати, с английской версией статьи так и случилось, и один из моих хорошо знакомых аналитиков Christian Reusch поправил меня по поводу одного из вопросов. Спасибо!)

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

Общий вопрос 1.  Почему первое, что я сделал – это захватил второй дамп на стороне сервера (накопителя)?

Ответ: было две причины.

Первая: я хотел проверить, доходят ли мои как клиента пакеты до NAS неизменными. Много разных устройств на пути теоретически могут манипулировать полями пролетающих пакетов (например, менять поле MSS на лету). Такой фактор влияния необходимо было сразу исключить.

На рисунке отображена не вся сеть из задачи, только основной смысл.

Вторая причина: мне нужно было быть абсолютно уверенным, что процесс PMTUD действительно происходит. Если же мы будем производить захват только на стороне клиента, PMTUD пройдет мимо нас (ну, то есть, не дойдет до нас), потому что он происходит на промежутке “сервер <–> какой-то из роутеров на пути”. Вот если бы мы отправляли большие пакеты, PMTUD был бы и на нашей стороне, однако оба эти процесса совершенно независимы друг от друга.

В моем конкретном случае  действительно PMTUD не происходил со стороны сервера (накопителя с адресом 192.168.1.115).

Вопросы по PCAP.

Вопрос 1. Посмотрите на пакеты 120-124. Почему они отмечены как “out of order” (не “retransmissions”, не “spurious retransmissions”, не “fast retransmissions”)?

Ответ:

Все эти обозначения – это результат работы логики Wireshark, а конкретнее – диссектора ТСР. Который руководствуется RFC (но не только). Почему бы нам тогда не посмотреть на исходный код и RFC заодно, и не прояснить этот механизм? Так и сделаем: Wireshark.org – Develop – Browse the Code – Epan – Dissectors – packet-tcp.c. Будем работать методом исключения.

“Spurious retransmission” (трудно это перевести, наверное, что-то типа “излишние переотправки”, то есть те, которые были не нужны). Из исходного кода диссектора ТСР:

“If the current seq + segment length is less than or equal to the receiver’s lastack, the packet contains duplicate data and may be considered spurious.” (“Если SEQ + длина сегмента меньше, чем последний АСК получателя, пакет содержит дублированные данные, и его можно считать излишним”).

Итак, spurious retransmission – это перепосылка тех данных, прием которых получатель уже подтвердил своим ACK. В нашем случае мы не видим никаких АСК для больших пакетов, потому что большие пакеты были с успехом дропнуты роутером. Нельзя обойти стороной интересный факт, что у нас гораздо больше шансов заметить пакеты типа spurious retransmission, если мы захватываем трафик на стороне клиента. Почему? Рисунок ниже прояснит этот момент.

Давайте сравним такой расклад с абсолютно той же ситуацией (найдите 10 отличий! Подсказка: ничего не поменялось кроме положения точки захвата).

Попробуйте-ка расположить пакеты АСК и data, чтобы увидеть spurious retransmission на нижнем рисунке. Не так уж просто, правда? Если сервер уже увидел ACK 201 – он не станет посылать DATA SEQ 101, уже незачем. Ну разве что у него проблемка с логикой, или мимо вас пролетел АСК с поврежденной контрольной суммой, который дропнется на сетевой карте, или мимо вас АСК уже пролетел и как раз подымается по стеку ТСР на сервере, и там же он встретился с DATA SEQ 101 (заметьте, этот момент времени, мягко говоря, не очень продолжителен, и так же мал шанс попасть на такую ситуацию).

“Fast retransmission”. Ну, это легче всего. Fast retransmission должен быть обязательно вызван  тремя DUP ACKs. Тут заглянем в  RFC 2581:

“The fast retransmit algorithm uses the arrival of 3 duplicate ACKs (4 identical ACKs without the arrival of any other intervening packets) as an indication that a segment has been lost.  After receiving 3 duplicate ACKs, TCP performs a retransmission of what appears to be the missing segment, without waiting for the retransmission timer to expire.”

В общих словах, потеряли на пути сегмент – выдаем одинаковый ACK в ответ на все последующие сегменты. Когда сервер увидел четвертый одинаковый АСК – переотправляет сегмент.

Из исходного кода:

“If there were >=2 duplicate ACKs in the reverse direction (there might be duplicate acks missing from the trace) and if this sequence number matches those ACKs and if the packet occurs within 20ms of the last duplicate ack then this is a fast retransmission”

Примерно тоже, только ещё ввели 20мс. (Заметьте, их нет в RFC 2581).

Вывод прост: нет DUP ACKs -> никаких “Fast retransmission”!

Битва “Retransmission” против “Out-of order”.

Сложный случай. В коде диссектора:

“If the segment came relatively close since the segment with the highest seen sequence number and it doesn’t look like a retransmission then it is an OUT-OF-ORDER segment”.

“Если сегмент пришел достаточно быстро после предыдущего, имеющего наивысший sequence number и он не выглядит (не выглядит?? Карл..) как retransmission , то это OUT-OF-ORDER”

Как по мне объяснение туманное. Можно, конечно,  кроме комментариев в коде разобрать саму логику и математику, но я, признаюсь, в этом не силен. Предполагаю, что дело во временнОм зазоре между приходящими пакетами. В нашем случае пакет 120 пришел всего через 1,3 миллисекунды после пакета 118, SEQ у него был меньше. В этом вся логика. Вряд ли retransmission timer может принимать такие значения (при дефолтном 200 миллисекунд.)

Вопрос 2. Почему пакеты (L2-фреймы) ICMP Type 3 / Code 4 от 192.168.1.1 (IP роутера) все размером по 590 Байт?

Ответ:

а) Что ограничивает размер  ICMP Type 3 / Code 4  снизу? Согласно с RFC 792 пакеты ICMP Type 3  должны иметь такую структуру:

Мы видим, что минимальный размер такой: 20 Байт (IP header пакета ICMP) + 8 Байт (ICMP header) + 20 Байт (IP header оригинального пакета) + 8 Байт (64 бита оригинального пакета / 8 ) = 56 Байт.

б) Что определяет максимальный размер того же пакета? Это защита от Black Hole-роутера на пути. Наш роутер, отправляющий ICMP Type 3 / Code 4, должен быть уверен, что они дойдут до получателя. А путей до получателя может быть несколько. Вдруг наш  ICMP Type 3 / Code 4 полетит не по тому пути, по которому к нам уже прополз большой data-пакет (который, собственно, и вызвал наш ICMP Type 3 / Code 4)? Поэтому верхняя граница – это размер гарантированной нефрагментированной доставки (576 Байт для L3).

И теперь самый сложный вопрос. А почему именно 576 Байт (кадр L2 590 Байт)? Почему роутер уперся в максимальный безопасный размер, а не, например, взял себе спокойно 120 Байт. Признаюсь, я не знал ответ на этот вопрос и потому просто предположил, что это оставлено на усмотрение роутера. Могу 576 Байт – отправлю 576, по максимуму. Именно здесь меня поправил Christian Reusch, он подсказал просмотреть RFC1812 Section 4.3.2.3. Как оказалось, вышло дополнение к RFC 792, которое гласит среди прочего следующее:

“…Therefore, the ICMP datagram SHOULD contain as much of the original datagram as possible without the length of the ICMP datagram exceeding 576 bytes….”

“…Таким образом, ICMP-датаграмма должна содержать как можно большую часть оригинальной датаграммы, но не превышая при этом 576 Байт…”

Вот и настоящий ответ. Кстати, на последнем SharkFest’17 я на этом же вопросе во время беседы поймал инженера с dual CCIE, он тоже видел это первый раз. Если вы ещё учитесь – задайте его преподавателю, проверьте скилл 🙂

Вопрос 3. Почему пакет 130 НЕ считается “Dup ACK” несмотря на то, что его ACK number = 6469 (относительный), такой же, какой УЖЕ был в пакете 128? А потом снова пакет 132 с тем же ACK number 6469 СНОВА считается Dup ACK.

Ответ: Ничего особо сложного, но заглянуть в  RFC 5681 всё же придется:

“An acknowledgement is considered a “duplicate” in the following algorithms when (a) the receiver of the ACK has outstanding data, (b) the incoming acknowledgement carries no data, (c) the SYN and FIN bits are both off, (d) the acknowledgement number is equal to the greatest acknowledgement received on the given connection (TCP.UNA from [RFC793]) and (e) the advertised window in the incoming acknowledgement equals the advertised window in the last incoming acknowledgement.”

То есть, для того, чтобы ACK посчитался как Dup ACK нужно выполнить некоторые условия (кратко):

  1. получатель АСК ещё должен иметь свои данные “в полете” (отправлены, но не подтверждены);
  2. входящий АСК не может содержать данных;
  3. SYN и FIN не должны быть включены….

Стоп, стоп. Уже достаточно. В нашем случае пакет содержит данные (130 Байт). Мы не выполнили условие (b), поэтому и не можем обозвать этот пакет Dup ACK. Просто!

Вопрос 4. Как вы думаете, пакет 133 добрался до получателя или потерялся где-то по пути?

Ответ: да, добрался. Он не был замечен переотправленным; он подтвердился пакетом АСК под номером 147. Вопрос несложный, но есть фокус: мы можем это доказать ещё раньше, перед тем, как увидели пакет 147. Давайте сравним пакеты 132 и 135. Они оба – типа SACK (Selective  Aknowledgement). Они оба почти одинаковы, НО! Давайте посмотрим на поле SRE (Right Edge, правая граница). У пакета 132 SRE = 10849. А вот у пакета 135 SRE = 12159. Диапазон успешно принятых SEQ изменился с “10699…10849-1” на “10699…12159-1”.

Ситуация на получателе в момент, когда он отправил пакет 132:

И после того, как он отправил пакет 135:

Обратили внимание на все эти “-1” на рисунках? Да, они там специально 🙂 Как ни странно, Left Edge и Right edge обозначают чуточку разные вещи:

Left Edge of Block – первый SEQ этого (полученного) блока.

Right Edge of Block – это первый SEQ, который не входит в блок (то есть, с которого мы хотим продолжить)

Общий итог: data-пакет номер 133 с SEQ = 10849 прилетел к получателю и заполнил собой одну из пробоин в полученном потоке. Но эта пробоина была не единственной, поэтому в следующем DUP (S)ACK номер 135 получатель не стал увеличивать ACK – пришедший пакет заполнил пробоину не первую по порядку.

Вопрос 5. Давайте предположим, что мы захватываем трафик на стороне сервера. Сервер только что начал передачу большого файла. PMTUD уже произошел успешно, размер PMTU определился. Как вы думаете, есть ли у нас шанс увидеть этот процесс (PMTUD) снова в том же ТСР-соединении?

Ответ: Если отправитель уже успешно определил PMTU, например, в 1350 Байт, он будет использовать именно такой размер для текущего TCP-соединения, и мы уже больше не увидим процесс PMTUD. Правильно? Нет, неправильно! Правильный ответ – когда как… От чего же это зависит?

Случай (а). Мы не можем гарантировать, что маршрут все соединение будет один и тот же. Чаще всего это именно так, и одно TCP-соединение проходит по одному маршруту, но в любой момент теоретически путь может измениться – где-то выключили (или сам выключился) какой-то роутер, экскаватор выдернул провода… и маршрут динамически проложился через другую ветку с меньшим PMTU, например, в 1300 Байт. Ловите  ICMP Type 3 / Code 4 и давайте делать PMTUD еще разок!

Случай (б). А давайте заглянем в  RFC 1191:

“…Hosts using PMTU Discovery MUST detect decreases in Path MTU as fast as possible.  Hosts MAY detect increases in Path MTU, but because doing so requires sending datagrams larger than the current estimated PMTU, and because the likelihood is that the PMTU will not have increased, this MUST be done at infrequent intervals…”

“Хост, использующий PMTU Discovery, должен обнаруживать уменьшение Path MTU как можно более быстро. Хост может также обнаруживать увеличение Path MTU, но т.к. это предполагает отправку датаграмм, больших текущего PMTU, и так как велика вероятность, что PMTU не изменялся в большую сторону, этот процесс должен производиться нечасто” (слегка вольная трактовка с сохранением смысла). Также устанавливается нижняя граница по времени для таких проб в 5 минут, рекомендовано 10 минут.

Итак, в полном соответствии с RFC 1191 хост может время от времени увеличивать MTU для теста текущего пути. Если захочет. Это значит, что в самом деле мы имеем шанс (и далеко не нулевой, кстати) увидеть PMTU Discovery в том же соединении опять.

Я провел некоторые тесты по этому поводу, в результате составив небольшую табличку поведения разных ОС по вопросу PMTU Discovery:

Подробнее по таблице:

  • EnablePMTUD default – включен ли механизм PMTUD по умолчанию;
  • EnablePMTUBHdetect default – включен ли по умолчанию механизм обнаружения PMTU Black Hole (ключ добавляется в реестр Windows);
  • Reaction to ICMP black hole (WITH “PMTUBHdetect =1”  Key) – реакция ОС при попадании на PMTU Black Hole с выключенным/включенным механизмом обнаружения;
  • Reaction to small MTU (1350 Bytes L3) – реакция ОС на заданный PMTU в 1350 Байт (это значение, которое передается в пакетах ICMP Type 3 / Code 4);
  • PMTU ramp up – периодическая проба маршрута на повышение PMTU.

Большинство ОС действительно поднимали PMTU каждые 10 минут. Кроме одной – Mac OS.v.10.ххх “El Capitan” этого не сделал ни разу. Также в табличке я отметил поведение ОС при наталкивании на “ICMP Black Hole” – то есть, устройство, которое не отправляет назад ICMP-пакеты (не блокируйте весь ICMP на роутерах без разбора!)

Некоторые интересные особенности:

  • Windows 2000 уменьшает L3 PMTU до 1330 Байт, несмотря на то, что в ICMP Packet too Big указано 1350 Байт (это Microsoft, они так видят…)
  • Только в Windows XP Pro SP3 (из всех версий Windows, которые я тестировал) PMTU Black Hole Detection включен по умолчанию.
  • Большинство ОС со временем подымали PMTU до 1492 Байт, а не 1500. Почему так? Потому что в RFC1191 есть рекомендация насчет этого: “A better approach is to periodically increase the PMTU estimate to the next-highest value in the plateau table (or the first-hop MTU, if that is smaller)” (Section 7.1).” (“Более оптимальным подходом подходом является периодическое увеличение PMTU до следующего плато в таблице, или до first-hop MTU, если оно меньше.“) Там же, в разделе 7.1 есть и таблица значений “плато MTU”.

Надеюсь, статья была интересна и вы узнали что-то новое для себя! Комментарии приветствуются.

Автор: Владимир Герасимов

packetrrain.net

Поделиться
  •  
  •  
  • 1
  •