Теоретические основы и архитектура
ICMP ping и traceroute проверяют только IP-маршрутизацию: пакет может дойти по IP-пути, хотя пересылка по меткам сломана, поэтому они не доказывают исправность LSP (а P-маршрутизаторы в traceroute видны лишь при включённом propagate-ttl). Для проверки LSP стандартизованы MPLS Echo Request/Reply: LSP Ping и LSP Traceroute (RFC 8029, заменивший RFC 4379). 1. LSP Ping: эхо-запрос отправляется внутри тестируемого LSP, с тем же стеком меток, что и клиентский трафик, как UDP-пакет на порт 3503; адрес назначения - из диапазона 127.0.0.0/8 (по умолчанию 127.0.0.1), IP TTL равен 1, стоит опция Router Alert. Транзитные P-маршрутизаторы пересылают пакет по метке и в IP-заголовок не смотрят. Egress снимает метку, передаёт пакет процессу MPLS OAM, и тот сверяет Target FEC Stack со своими привязками; если FEC принадлежит ему, возвращает Return Code 3, иначе код ошибки. Ответ идёт обычным IP-путём. 2. LSP Traceroute: запросы с MPLS TTL 1, 2, 3 и далее; каждый узел отвечает Return Code 8 и TLV Downstream Mapping (следующий узел, интерфейс, MRU, исходящие метки), последний отвечает кодом 3. Оба теста проверяют один LSP для одного FEC: VPN-метку и таблицу VRF они не проверяют (для этого нужен FEC типа VPN IPv4 prefix или ping vrf).
Зачем нужен отдельный ping для LSP
Обычный ICMP ping проверяет IP-путь, а MPLS-сеть может быть сломана так, что IGP и LDP выглядят здоровыми: LDP-сессия Oper, префикс в RIB есть, а в LFIB транзитного P-маршрутизатора нет исходящей метки или аппаратная таблица запрограммирована неверно. Контрольная плоскость отвечает "всё хорошо", пакеты клиентов пропадают. LSP ping и LSP traceroute (RFC 4379, заменён RFC 8029) решают именно эту задачу: они отправляют проверочный пакет внутри тестируемого LSP, с тем же стеком меток, который получил бы клиентский трафик, и сверяют результат с таблицами конечного узла. Тест отвечает на вопрос "доходит ли пакет с меткой этого FEC до его egress-узла и признаёт ли egress, что FEC принадлежит ему".
Формат MPLS Echo Request
Эхо-запрос - это UDP-пакет с портом назначения 3503. IP-адрес назначения берётся из диапазона 127.0.0.0/8 (по умолчанию 127.0.0.1), IP TTL равен 1, в заголовке стоит опция Router Alert. Адрес 127/8 нужен как защита: если метка потеряна и пакет вышел из LSP на обычном IP-узле, он не будет маршрутизирован дальше (loopback-адреса не пересылаются), а попадёт в локальный процесс или будет отброшен. Поэтому и транзитные узлы не обращают внимания на IP-заголовок: решение принимается по метке. Диапазон 127/8 даёт и практический приём: при ECMP хеш зависит от адреса назначения, поэтому перебор 127.0.0.1-127.0.0.N заставляет эхо-запросы пройти разными равноценными путями.
Фиксированный заголовок эха занимает 32 байта: Version (1), Global Flags (бит V - "validate FEC stack"), Message Type (1 - Echo Request, 2 - Echo Reply), Reply Mode, Return Code, Return Subcode, Sender's Handle (копируется в ответ), Sequence Number, TimeStamp Sent и TimeStamp Received (по ним считается RTT). Далее идут TLV. Reply Mode: 1 - не отвечать, 2 - ответ UDP-пакетом по IP (по умолчанию), 3 - ответ UDP с Router Alert (проходит по тракту с обработкой на каждом hop), 4 - ответ по каналу приложения (VCCV для псевдопроводов). Ответ (Echo Reply) идёт на UDP-порт, с которого пришёл запрос, и по обычной IP-маршрутизации: поэтому сломанный обратный путь даёт "нет ответа" даже при исправном прямом LSP.
Target FEC Stack и ответ egress
Главный TLV (тип 1) - Target FEC Stack: перечень FEC для каждой метки стека, начиная с верхней. Примеры подтипов: LDP IPv4 prefix (1), RSVP IPv4 LSP session (3), VPN IPv4 prefix (6), FEC 128 pseudowire (10), FEC 129 pseudowire (11), BGP labeled IPv4 prefix (12), Nil FEC (16). Egress получает пакет, снимает метки, видит адрес 127.0.0.1 и передаёт запрос в процесс OAM. Тот проверяет FEC: для LDP IPv4 prefix 10.255.0.2/32 egress должен сам быть "конечной точкой" этого префикса (адрес на его loopback). Если проверка пройдена, в ответе Return Code 3 ("Replying router is an egress for the FEC at stack-depth"). Таким образом ping проверяет не только прохождение, но и соответствие метки и FEC: пакет, ошибочно доставленный другому узлу по неверной метке, получит Return Code 4 или 10, а не 3.
Return Code: как читать ответ
Код возврата - главный диагностический результат. Значения RFC 8029: 0 - без кода; 1 - искажённый запрос; 2 - непонятные TLV; 3 - узел является egress для FEC; 4 - у узла нет привязки для этого FEC на данной глубине стека; 5 - несоответствие Downstream Mapping; 8 - метка коммутируется на этой глубине стека (транзитный узел, нормальный ответ traceroute); 9 - метка есть, но MPLS-пересылки по ней нет; 10 - привязка FEC не совпадает с присланной меткой; 11 - нет записи для метки; 12 - протокол не включён на интерфейсе. Коды 4, 9, 10, 11 означают "здесь LSP сломан". Обратите внимание: в общем описании курса код 10 часто ошибочно приписывают к "label switched but no MPLS forwarding" - это код 9.
LSP traceroute: Downstream Mapping и TTL
Traceroute отправляет эхо-запросы с MPLS TTL 1, 2, 3 и так далее. На транзитном узле TTL метки истекает, пакет уходит в процесс OAM, и узел отвечает Return Code 8 вместе с TLV Downstream Mapping (DSMAP, тип 2; в современных реализациях DDMAP, тип 20, RFC 6424): адрес следующего узла, интерфейс, MRU (максимальный размер принимаемого downstream пакета) и исходящий стек меток. Ingress копирует эту информацию в следующий запрос, и очередной узел может проверить, что принимает пакет именно с той меткой, которую ему обещал предыдущий. Расхождение даёт Return Code 5 (Downstream Mapping Mismatch). Последний узел отвечает Return Code 3. Предпоследний узел при PHP сообщает исходящую метку implicit-null (3): это нормально, а не авария.
Важная особенность: LSP traceroute работает независимо от режима propagate-ttl. В обычном IP traceroute команда no mpls ip propagate-ttl скрывает P-маршрутизаторы (IP TTL не копируется в метку), тогда как LSP traceroute сам задаёт TTL метки и видит каждый hop. Поэтому сначала проверяйте им, а не IP traceroute.