Теоретические основы и архитектура

Заголовок MPLS (RFC 3032) представляет собой 32-битный «shim»-заголовок, вставляемый между заголовком канала передачи данных (L2) и сетевым заголовком (L3). Он состоит из четырёх полей: 20-битная метка (Label, значения 0-15 зарезервированы), 3-битное поле Traffic Class (TC, ранее называвшееся EXP, используется для QoS), 1-битный флаг дна стека (S, Bottom of Stack: S=1 означает последнюю метку перед заголовком данных, S=0 — наличие следующей метки в стеке) и 8-битный TTL (Time to Live, уменьшаемый на каждом LSR для петлезащиты). Каждая метка в стеке добавляет ровно 4 байта. В сложных операторских сервисах стек меток может достигать 3-5 меток (Транспортная LDP/SR + Сервисная VPN + FRR bypass + Flow label = 16-20 байт). Это создаёт критическую проблему MPLS MTU: если MTU физического интерфейса составляет стандартные 1500 байт, то маркированный пакет размером 1500 байт IP + 8 байт меток превысит MTU интерфейса: при DF=1 LSR отбросит его и вернёт ICMP Fragmentation Needed (по LSP, RFC 3032), а если превышен предел кадра на L2, пакет теряется молча. Типичный симптом: ping и BGP OPEN проходят, а крупные пакеты зависают. Поэтому на интерфейсах ядра MTU увеличивают с запасом (обычно 1530-1548 байт, Jumbo / Baby Giant).

Запись стека меток (LSE): 32 бита между L2 и L3

Одна запись стека меток (Label Stack Entry, RFC 3032) занимает ровно 4 байта и располагается между заголовком канального уровня и IP-заголовком. Поэтому MPLS иногда называют уровнем «2.5». Тип кадра в Ethernet меняется: 0x8847 для unicast и 0x8848 для multicast вместо 0x0800 у IPv4. Поля записи, считая от старшего бита:

text
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Label (20)                 | TC (3)|S|   TTL (8)   |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 bits 0-19: Label | bits 20-22: TC | bit 23: S | bits 24-31: TTL

Метка — 20 бит, то есть 1 048 576 значений, из них 16 (0-15) зарезервированы, остаётся 1 048 560 для динамического и статического выделения. Поле TC (Traffic Class, 3 бита, 8 классов) раньше называлось EXP; RFC 5462 (2009) переименовал его, потому что оно давно используется для DiffServ, а не для экспериментов. Бит S (Bottom of Stack) равен 1 только в последней записи стека; LSR всегда смотрит только на верхнюю запись, а S нужен, чтобы после её снятия понять, что дальше лежит полезная нагрузка (IP, Ethernet, и т.д.), а не ещё одна метка. TTL — 8 бит, служит той же цели, что и IP TTL: защита от петель и основа для traceroute.

Зарезервированные метки 0-15

Эти значения нельзя раздавать по LDP/RSVP/BGP как обычные. Часть из них используется на практике ежедневно, часть почти никогда.

МеткаНазваниеНазначение
0IPv4 Explicit NullМетку снять и обработать пакет как IPv4; сохраняет TC до egress при отключённом PHP.
1Router AlertДоставить пакет в control plane локального LSR; не выбирается как обычная метка пересылки.
2IPv6 Explicit NullТо же, что 0, но для IPv6.
3Implicit NullВ заголовке никогда не встречается: egress объявляет её по LDP/RSVP, чтобы penultimate-hop снял метку (PHP).
7ELI (Entropy Label Indicator, RFC 6790)Следующая запись стека — entropy label для балансировки; отдельный ELI-TTL обычно 0.
13GAL (RFC 5586)Generic Associated Channel Label, используется MPLS-TP OAM.
14OAM Alert (RFC 3429)Служебные OAM-пакеты (Y.1711); в IP/MPLS-сетях встречается редко.
15ReservedЗарезервирована под расширение пространства специальных меток.

Значения 4-6 и 8-12 не назначены. Первое «обычное» значение — 16; Cisco IOS-XE по умолчанию раздаёт LDP-метки с 16, Junos LDP — с диапазона около 300000, SR-MPLS по умолчанию использует SRGB 16000-23999. Это объясняет, почему в show mpls forwarding-table метки разных протоколов выглядят так по-разному.

Стек и цена в байтах

Каждая метка добавляет 4 байта к размеру кадра. Размер, который должен пройти по ядру, считается так: для L3-нагрузки клиентский IP MTU + 4*N, где N — число меток в стеке; для L2-нагрузки (псевдопровод, VPLS, EVPN) — размер клиентского Ethernet-кадра без FCS + 4*N + 4 байта control word (если включён). Клиентский кадр без FCS при IP MTU 1500 — 1514 байт (1518 с dot1q-тегом).

СценарийМетки в стекеНагрузкаМинимальный MTU в ядре
IP поверх LDPтранспортная (1)IP 15001504
L3VPN поверх LDP или SRтранспорт + VPN (2)IP 15001508
L3VPN + RSVP-TE, LDP over TEVPN + LDP + TE (3)IP 15001512
L3VPN, TE и активный FRR bypassVPN + TE + bypass (3-4)IP 15001512-1516
Inter-AS option CVPN + BGP-LU + IGP (3)IP 15001512
SR-TE policy из 5 SID + VPN6IP 15001524
VPWS/VPLS, Ethernet без тегатранспорт + PW + CW (4 байта)кадр 15141526
VPLS, тегированный кадрто жекадр 15181530
EVPN: транспорт, EVPN, ELI+EL4 меткикадр 15141530
EVPN BUM c ESI-меткой5 метоккадр 15141534

Отсюда типовая рекомендация: на всех ядровых и агрегационных линках задавать MTU с запасом (1600 или jumbo 9000-9216, если оборудование и стыки это поддерживают). Лабораторное значение 1524 выбрано как «клиентские 1500 + 6 меток», этого хватает для L3VPN, TE с FRR и SR-TE из пяти SID. Важно, что максимально возможная глубина стека определяется самой длинной возможной в сети комбинацией сервисов, а не обычным сценарием.

Распространение TTL: uniform и pipe

RFC 3443 описывает две модели. В uniform-модели (поведение по умолчанию на Cisco, Huawei для публичной сети и Junos) ingress LSR копирует IP TTL в поле TTL метки, каждый LSR уменьшает его на 1, а при снятии последней метки значение копируется обратно в IP TTL. Для оператора и клиента это выглядит как обычная L3-сеть, и traceroute видит каждый P-маршрутизатор. В pipe-модели LSP считается прозрачной трубой: на ingress в метку записывается 255, транзитные LSR уменьшают только метку, а IP TTL клиента не затрагивается; ядро скрыто от клиентской трассировки.

Ключевые команды: Cisco no mpls ip propagate-ttl, Junos set protocols mpls no-propagate-ttl, MikroTik /mpls/set propagate-ttl=no, Huawei undo ttl propagate public / undo ttl propagate vpn в режиме mpls. Отключение скрывает топологию ядра от клиента и защищает адреса P-маршрутизаторов; платой становится невозможность увидеть, на каком хопе ядра потеряно соединение, из клиентского traceroute. Включать/отключать нужно одинаково на всех PE, иначе значение TTL на egress будет разным в зависимости от пути.