Ключевые слова:network, mtu, ping, packet, (найти похожие документы)
From: Daniel Ginsburg <http://dbg.livejournal.com>
Date: Sun, 18 Sep 2007 17:02:14 +0000 (UTC)
Subject: PMTUD (Path MTU Discovery) и проблема фрагментации пакетов
Оригинал: http://dbg.livejournal.com/58171.html?nc=1&style=minenetchпоказал небезынтересный тред в f.r.u.b.
Собственно, обсуждение от конкретной ситуации там быстро перешло к
фрагментации и PMTUD вообще. Это далеко не единственное обсуждение
PMTUD, благо проблема реальная, вредная и до сих пор без
удовлетворительного решения. Пожалуй, попробую изложить, что я по
этому поводу думаю.
Итак, у нас есть пакетная сеть, как обычно, состоящая из узлов и
линков между ними. Разные линки могут поддерживать разный максимальный
размер пакета, который можно по этому линку передать. Это называется
Hop MTU, или просто MTU. Часто MTU имеет некоторый гарантированное
минимальное значение, например для IPv4 сетей - это 68 байт
(распространенное заблуждение: 576 байт, но это неправильно. 576 байт
- это минимальный reassembly buffer, т.е. это гарантии для end host'а,
а не для сети), для IPv6 - 1280 байт. Минимальное значение Hop MTU на
пути от узла A к узлу B называется Path MTU.
Если мы хотим, чтобы узлы A и B могли говорить друг с другом у нас
есть следующие варианты:
1) посылать только пакеты не более чем минимального гарантированного
размера
2) посылать пакеты побольше и позволить сети их фрагментировать, если
потребуется
3) каким-то образом понять, каков Path MTU между общающимися узлами и
использовать пакеты не более такого размера
Понятно, что вариант 1 - это ну очень неэффективно. В IPv6 с этим чуть
полегче, но все равно недостаточно хорошо.
Вариант 2 тоже не очень хорош по нескольким причинам.
Во-первых, фрагментация в IPv4 сломана. По этому поводу есть "IPv4
Reassembly Errors at High Data Rates" (в предыдущих редакциях этот
драфт назывался "Fragmentation Considered Very Harmful"). Очень
советую прочитать.
Во-вторых, фрагментация неэффективна. Неэффективное использование
полосы и увеличение packet rate, проблемы при потере фрагмента,
трудности обратной сборки - это все описано в классической статье
Kent & Mogul.
В упомянутой дискусси netchзаметил: На самом деле
здесь самая тяжёлая диверсия - то, что needfrag является ICMP.:(( Даже
если ICMP не режется, часто ставится предельная субполоса на него
(например до 5% канала). Если кто-то один вдруг начинает гнать мусор
типа ping flood, страдают все.
Это верно, но не до конца. Проблема не столько в том, что это ICMP, а
сколько в том, что обработка пакетов, непролезающих в следующий линк -
дорогое удовольстивие, что с фрагментацией, что с генерацией
"fragmentation needed and DF set", и эта операция реализуется в slow
path. Поэтому, нередко ставятся rate limits на эту операцию.
Соотвественно, можно как самому налететь на такой rate limit и
получить существенную потерю пакетов, так и нарваться на намеренное и
злоумышленное исчерпание этого лимита.
И, наконец, вариант 3. Всем бы он был хорош, если б работал. Проблемы
классического PMTUD многократно перетерты и подробно расписывать их я
не стану: [DEL: обезьяна с гранатой :DEL] МСЭ, сбрасывающие все ICMP
без разбору, упомянутые выше rate limits на генерацию ICMP,
органичения по полосе на ICMP - это все широко известно.
Попробуем порассуждать, как вообще можно было бы подойти к проблеме
фрагментации и Path MTU.
Можно было бы заставить протокол маршрутизации распространять
информацию о Path MTU к разным сетям. Такое уже делалось. Например
IGRP и EIGRP в составе метрики приносят значение Path MTU к той или
иной сети (правда, это никогда и никак не использовалось, насколько я
помню). В принципе, ничто не мешало сделать такое и в BGP, и других
IGP (одним только BGP обойтись нельзя из-за того, что iBGP соседи
могут не быть соединены напрямую). Никакой особой хитрости тут нету.
Добавляем атрибут MTU, при первичной генерации BGP-маршрута берем либо
статически сконфигурированное значение, либо, если у нас
редистрибуция, то берем значение оттуда, откуда редистрибутим. При
дальнейшем анонсировании выбираем min(route MTU, MTU to next-hop). У
агрегированного маршрута - min(MTU всех агрегируемых маршрутов).
Как это можно было бы использовать? Можно было бы заставить first hop
router либо фрагментировать пакеты, либо отбиваться needfrag'ом. Как
было б хорошо: first hop router разобрался с фрагментацией и понеслись
пакеты по привольному интернету быстренько и гладенько. И ничего
страшного, если FHR напряжется - это все-таки network edge, там
положено напрягаться.
Сработало бы такое? Нет.
First hop router в подавляющем большинстве случаев сидит с одним
единственным маршрутом, касающимся интернета, - с default route. А это
значит, что с этим default route ассоциирован либо минимальный из всех
MTU во всем интернете, если этот default - BGP-derived (поскольку
порождение дефолта - это по сути дела экстремальная агрегация), либо
MTU, взятый с потолка, если маршрут сконфигурен статически.
Соответственно, либо совершенно ненужное понижение MTU для для всех
пакетов, идущих через этот FHR, либо разборки с фрагментацией сдвинуты
на первый в пути роутер с полной таблицей. Первое плохо - это не
только неэффективно, но и просто опасно: кто-нибудь очень умный
санонсировал маршрут с атрибутом MTU=100 и привет, 90% пакетов в
интернете стали не длиннее сотни байт и интернет кончился. Второе тоже
плохо: DFZ-роутеров не так уж много, получают они высокоскоростной
агрегированный трафик, поэтому концентрировать еа них нагрузку по
разборкам с фрагментацией - совершенно неправильно.
Т.е. идея это гиблая.
Значит, нам ничего не остается, кроме как заставить хосты заниматься
"разведкой" Path MTU. Как это можно организовать?
Во-первых, классический PMTUD, основанный на ICMP needfrag. Во-вторых,
PMTUD, основанный на потерях больших пакетов.
С первым мы уже разобрались, почему он работает через раз.
Второй действует довольно просто, я процитирую: "The proposed new
method does not rely on ICMP or other messages from the network. It
finds the proper MTU by starting a connection using relatively small
packets (e.g. TCP segments) and searching upwards by probing with
progressively larger test packets (containing application data). If a
probe packet is successfully delivered, then the path MTU is raised.
The isolated loss of a probe packet (with or without an ICMP can't
fragment message) is treated as an indication of a MTU limit, and not
a сongestion indicator."
Что можно сказать про второй метод, чем он хорош, и чем он нехорош?
Хорош он, очевидно, тем, что от сети не надо никакого интеллекта,
кроме умения сбрасывать пакеты, которые не лезут в следующий линк. Чем
нехорош? Специфицирован он только для TCP и SCTP, но ничто не мешает
поступить похожим образом для любого протокола с двунаправленным
потоком между общающимися хостами. Однако, если поток
однонаправленный, т.е. никаких подтверждений с той стороны не
предусмотренно, то такой метод работать не будет. А вот классический
PMTUD мог бы с такой ситуацией справиться.
Можно нафантазировать еще один метод. Метод Кровавого Обрезания. Пусть
есть пакет, который не лезет в следующий линк. Вместо того чтобы его
фрагментировать, берем и [DEL: отрезаем ему половину жопы :DEL]
передаем от этого пакета сколько пролезает и устанавливаем ему в
заголовке соотвественный битик. Получатель видит обрезанный пакет и
сигнализирует передатчику "давай-ка помельче пакетики". Как
сигнализирует? Лучше всего piggyback на протоколе повыше уровнем в
рамках того же соединения - заведомо не дропнут файрволом, не зажмут
полосу и т.п. Недостаток у этого метода тот же - работает только для
двунаправленных протоколов. Достоинства: 1) Кровавое Обрезание легко
реализуется в ASIC'е 2) нет нужды строить предположения из-за чего
потерялся пакет: из-за MTU, из-за congestion, или из-за банальной
битовой ошибки в канале. Но такой метод требует поддержки на всех
хостах, так что вряд ли мы увидим его в реальной жизни.
Итого. Все плохо. По крайней мере сейчас. Завтра появятся реализации
draft-ietf-pmtud-method и какую-то часть проблем это решит. Что же
делать сегодня? Неформально стандартизоваться на гарантированном MTU
1500. В принципе, оно так и есть сейчас. А тех операторов сетей,
которые не понимают, что это established industry practice и
умудряются поломать MTU на транзите, надо [DEL: расстреливать :DEL]
учить.