Маршрутизация на отправителе по звеньям
Введение
Ранее рассматривали маршрутизацию по адресу назначения (трад. IP).
Она хорошо годится для, например, интернета:
- интернет — совокупность непрозрачных "автономных систем" и связей между ними
- его абоненты не обязаны доверять друг другу, а узлы маршрутизации не доверяют абонентам
- качество связи принципиально best-effort (от пиров ничего потребовать нельзя)
- самих узлов-абонентов колоссальное количество, и узлы каждую минуту появляются и исчезают: записать всех в таблицу нереально
- иерархическая делегация диапазонов адресов упрощает работу маршрутизаторам, передающим трафик миллионов абонентов: у них меньше размеры таблиц
У такой принципиальной архитектуры есть ограничения.
До 2006 года маршрутизация была либо программной на CPU (и упиралась в тактовую частоту), либо дорогой. Нельзя было маршрутизировать на высоких (1Gbps+) скоростях без спецоборудования стоимостью в дом. Инженерное сообщество успело изобрести MPLS: O(1) поиск в таблице FEC вместо обхода таблицы префиксов.
Чтобы выйти за потолок качества связи, которое может предоставить best-effort-сеть, захотелось резервировать ресурсы для передачи приоритетных данных => RSVP
В массово-параллельных сетях, а также в сетях с нетривиальной связностью возникла необходимость в более замороченной политике определения пути пакетов => RSVP-TE
К 2010 году крупные операторы связи поняли, что им этого мало; с ростом к-ва абонентов, потоков, роутеров
протоколы управления балансировкой потоков и QoS для каждого потока стали медленно сходиться при отвале/появлении узлов или линков
стали требовать не только таблиц маршрутизации / меток на каждом узле, но и трекинга путей для каждого потока
таблицы маршрутизации / распределение меток тоже медленно сходятся, время до восстановления связи неудовлетворительно большое
=> Созрела архитектура звеньевой маршрутизации (Segment Routing)
Принципы
- приемлема в некоторой области (domain) достаточно доверенных соединённых узлов под общим управлением
- узлы доставляют пакеты согласно "SR Policy": списку звеньев (segments)
- SR Policy назначает первый узел в области, стоящий на пути пакета
- остальные тупо исполняют ⇒ меньше потребление ресурсов, меньше задержки
- идентификатор звена SID — bitstring, кодирует звено в пакете
- звено — инструкция, что сделать с пакетом (в т. ч. "куда доставить", но не только)
- не только сетевая маршрутизация, но, более того, "сетевое программирование": SID могут быть не только адресами узлов, а обозначать класс обслуживания, исходящий интерфейс, процесс внутри узла, особую операцию над пакетом без топологической семантики, вообще любое действие над пакетом.
- семантика инструкции может быть всеобщей в области или частной для узла
- SR supports per-flow explicit routing while maintaining per-flow state only at the ingress nodes to the SR domain.
Вообще говоря, не годится для построения интернета: не позволяйте кому попало из интернета программировать ваши узлы!
SR не навязывает конкретную платформу доставки данных (data plane).
SR не навязывает характер контроллера SR Policy или даже его наличие.
Паста из rfc8402:
A segment may be associated with a topological instruction. A topological local segment may instruct a node to forward the packet via a specific outgoing interface. A topological global segment may instruct an SR domain to forward the packet via a specific path to a destination. Different segments may exist for the same destination, each with different path objectives (e.g., which metric is minimized, what constraints are specified).
A segment may be associated with a service instruction (e.g., the packet should be processed by a container or Virtual Machine (VM) associated with the segment). A segment may be associated with a QoS treatment (e.g., shape the packets received with this segment at x Mbps).
Две data planes
IETF стандартизовала для SR две платформы доставки данных, на которые она может опираться:
SR-MPLS
- SID — одна из меток в стопке
- SR Policy — стопка меток
- Активное звено — верхняя метка
Continue — замена метки (ip -M r add X as Y $nexthop)
Next — снятие метки (ip -M r add Y $nexthop)
SR-IPv6 (часто сокращают как SRv6)
- SID — IPv6-адрес
- SR Policy — стопка (массив) IPv6-адресов в теле SRH (в порядке возрастания активности)
- Активное звено — адрес получателя в заге IPv6
- Continue — обычная IPv6-маршрутизация
- для её осуществления не нужно уметь в SRv6 или понимать/трогать SRH
Next — уменьшение поля Segments Left в SRH, адрес SRH.segs[SL] становится адресом получателя
SR-MPLS:
- В MPLS нет next header, есть только 1 бит bottom of stack.
- крайнему маршрутизатору на пути нужно заглядывать вглубь пакета и перебирать эвристики, что за пакет
- или на всём пути держать +1 вечную метку.
MPLS в ЦОД и на "последней миле": в крутых и дорогих SP-коммутаторах поддержка есть (и контрольных протоколов тоже), в хостах-серверах на Linux программная поддержка тоже есть (подумаешь, 600 строк на Си), в дешёвых ближайших к хосту access-коммутаторах не сделали. "А я не бууу"
- SR-MPLS определяет всего две функции: "направить до узла по кратчайшему пути", "направить через конкретный интерфейс"
- Если к-во MPLS меток overhead достигает 5-7, то это уже сравнимо с 128-бит метками!
SR-IPv6:
- SID 128 бит: много места
- Старшие биты: префикс-локатор (на него можно просто смаршрутизировать и без SR)
- не менее 32 бит, обычно 48
- Полный вариант SR Policy: IPv6 + SRH
Пример: IP6(DA=[2001:db8:10:a::]) / Routing(Type=4, SL=2, Last=2, Segs=([2001:db8:10:1000::], [2001:db8:10:c::], [2001:db8:10:a::]))
Next: IP6(DA=[2001:db8:10:c::]) / Routing(Type=4, SL=1, Last=2, Segs=([2001:db8:10:1000::], [2001:db8:10:c::], [2001:db8:10:a::]))
- Сжатый вариант SR Policy: CSID, они же µSID, позволяют упаковать ещё плотнее (5 или менее звеньев c одинаковым локатором — SRH не нужен)
(2001:db8:10:a::), (2001:db8:10:c::), (2001:db8:10:1000::) ⇒ IP6(DA=[2001:db8:10:a:c:1000::])
Next: IP6(DA=[2001:db8:10:c:1000::])
- IPv6 Flow Label: можно выставить в соотв. с SR Policy или ULP
Схема IPv6-SRH:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Header | Hdr Ext Len | Routing Type | Segments Left |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Last Entry | Flags | Tag |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Segment List[0] (128-bit IPv6 address) |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| |
...
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Segment List[n] (128-bit IPv6 address) |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// //
// Optional Type Length Value objects (variable) //
// //
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Зачем?
А потом оказалось:
- Конвергенция: оборудование для пакетных сетей становится лучше, есть желание даже традиционные голосовые услуги перенести на общую инфру с вычислительными сетями (пример — VoLTE).
- Отличие SP-сетей от DC. Clos topo, цитата: "вся полоса доступна по кратчайшему пути, почти не нужен TE". В SP-сетях нередко это не так
- SP control plane с целью удешевления всего (места в стойках, электроэнергии) переезжает в виртуалки, а значит, в те же DC — надо тащить SR-архитектуру в DC.
- причины тащить SR-архитектуру в metro/access?
- UE моб. связи / CPE фикс. связи может заказать для пакета QoS без дополнительных протоколов
ДЦ / Серверные приложения
TODO раскрыть лучше, сравнить ещё с geneve.
Сисадмины-недоучки без понимания сетевых технологий для соединения виртуализованного ПО (от программистов без понимания сетевых технологий) придумали VXLAN: Eth + IP + UDP/4789 + VXLAN + Eth + IP + ... SRv6 даст более короткий заголовок, особенно с CSID.
Паста от gemini в комменте-спойлере:
Ссылки
SRv6 uSID Introduction, YouTube, слайды; последние два слайда надо вынести.
Towards Fully-Controllable Packet Steering for AI Backend Networks with SRv6; вообще ушли от классической дин. маршрутизации.
- Filsfils, C. and contributors, Segment Routing
- Part I: Core fundamentals and architecture
- Part II: Traffic Engineering: end-to-end scalable network policies for WAN and data centers
TODO дополнить ещё книжками

VXLAN's innate design choices intentionally created a highly complex scenario for network interface cards (NICs) and operating systems. The protocol mechanics that make checksumming naturally problematic include several key design elements.
1. The "Zero Checksum" Default (RFC 7348) According to the original specification (RFC 7348), the outer UDP checksum SHOULD be transmitted as zero. Calculating a checksum across the entire encapsulated packet (outer IP + outer UDP + VXLAN + inner Ethernet frame) in software is computationally expensive and wastes CPU cycles. Since the inner payload (like a TCP packet) already has its own checksum, an outer checksum was deemed redundant. This led to the following problems:
2. Multi-Layered "Checksum Blindness" A standard packet has one Layer 4 checksum (e.g., TCP). A VXLAN packet contains two distinct Layer 4 checksums (the outer UDP header and the inner TCP/UDP payload).
3. The Performance/Integrity Tradeoff Because computing full inner and outer checksums in software destroys throughput, the protocol forces network operators to choose between two structural risks: 1. Turn Outer Checksums Off (Set to 0): You gain speed, but you lose error detection for the underlay network. If a bit flips inside the VXLAN header (corrupting the VXLAN Network Identifier/VNI) while crossing a physical switch, the packet will be delivered to the wrong virtual network/tenant without detection. 2. Turn Outer Checksums On: You protect data integrity, but you introduce a high risk of software driver mismatch and bugs.
Because the protocol embeds an entire packet inside another packet, operating system kernels (like Linux) and hardware vendors (Intel, NVIDIA/Mellanox, Broadcom) have had to entirely redesign their driver architectures via concepts like VXLAN Hardware Stateless Offloads or Remote Checksum Offload (RCO) to handle computing multiple layers of checksums at line-rate. When a driver, hypervisor (like VMware ESXi), and the Linux kernel don't align perfectly on who is calculating which layer of the checksum, the packet breaks.