В разделе "Транспортный MTU" главы 2 мы описали концепцию транспортного MTU (path MTU). Это минимальный MTU в любой из сетей, по которым проходит маршрут между двумя хостами. При определении транспортного MTU в IP заголовке устанавливается бит "не фрагментировать" (DF - don't fragment), что позволяет определить, необходимо ли какому-либо маршрутизатору на текущем маршруте фрагментировать IP датаграммы, которые мы посылаем. В разделе "ICMP ошибки о недоступности" главы 11 мы показали ICMP ошибку о недоступности, генерируемую маршрутизатором, которому необходимо перенаправить IP датаграмму с установленным битом DF, когда MTU меньше чем размер датаграммы. В разделе "Определение транспортного MTU с использованием Traceroute" главы 11 мы показали версию программы traceroute, которая использует этот механизм, чтобы определить транспортный MTU к пункту назначения. В разделе "Определение транспортного MTU при использовании UDP" главы 11 мы видели, как UDP определял транспортный MTU. В этом разделе мы просмотрим, как TCP использует этот механизм. Это описано в RFC 1191 [Mogul and Deering 1990].
Из всех систем, которые используются в этой книге (см. вступление), только Solaris 2.x поддерживает определение транспортного MTU.
Алгоритм определения транспортного MTU TCP работает следующим образом. Когда соединение установлено, TCP использует минимальный MTU исходящего интерфейса или MSS, объявленный удаленным концом, в качестве исходного размера сегмента. Алгоритм определения транспортного MTU не позволяет TCP превосходить MSS, объявленный удаленным концом. Если удаленный конец не указал MSS, то он устанавливается по умолчанию в значение равное 536. Реализации могут сохранить информацию о транспортном MTU определенного канала, как мы говорили в разделе "Показатели на маршрут" главы 21.
После того как выбран исходный размер сегмента, во всех IP датаграммах, отправляемых TCP по этому соединению, установливается бит DF. Если промежуточному маршрутизатору необходимо фрагментировать датаграмму, в которой установлен бит DF, он отбрасывает датаграмму и генерирует ICMP ошибку "не могу фрагментировать" (can't fragment). Это описано в разделе "ICMP ошибки о недоступности" главы 11. Если принята такая ICMP ошибка, TCP уменьшает размер сегмента и повторяет передачу. Если маршрутизатор сгенерировал новую ICMP ошибку, размер сегмента может быть установлен в MTU следующей пересылки минус размеры IP и TCP заголовков.
Если возвратилась старая ICMP ошибка, должно быть использовано следующее меньшее значение MTU (рисунок 2.5). Когда осуществляются повторные передачи, вызванные этими ICMP ошибками, окно переполнения не должно изменяться, вместо этого должен быть использован медленный старт.
Так как маршруты могут меняться со временем, по истечении определенного времени после последнего уменьшения транспортного MTU, можно попробовать большее значение (до величины минимального MSS, объявленного удаленным концом, или MTU исходящего интерфейса). RFC 1191 рекомендует, чтобы этот временной интервал составлял примерно 10 минут. (Мы видели в разделе "Определение транспортного MTU при использовании UDP" главы 11, что Solaris 2.2 использует для этих целей 30-секундный тайм-аут.)
Используя обычное для работы в глобальных сетях значение MSS по умолчанию равное 536, алгоритм определения транспортного MTU избегает фрагментации по промежуточным каналам с MTU меньшим чем 576 (что встречается довольно редко). Также можно избежать фрагментации в локальных сетях, когда промежуточный канал (Ethernet) имеет меньший MTU, чем сеть конечного пункта назначения (Token ring). В процессе определения транспортного MTU (при работе в глобальных сетях с MTU большим чем 576), системы не должны использовать MSS по умолчанию равный 536 байт для нелокальных пунктов назначения. Предпочтительней выбирать MSS равный MTU исходящего интерфейса (естественно, минус размер IP и TCP заголовков). (В приложении Е мы увидим, что большинство реализаций позволяют системным администраторам изменить значение MSS принятое по умолчанию.)