Files
hpnn-proto/docs/STEP1_SUMMARY.md
T

7.8 KiB
Raw Blame History

Шаг 1 — итоги: прототип окружения hpnn_v2

Дата: 2026-08-16 Статус: выполнено, стенд поднят и проверен (30 из 30 проверок) План: STEP1_IMPLEMENTATION_PLAN.md

Что сделано

Собрано контейнерное окружение из трёх сетей и трёх контейнеров, на котором работают обе подсистемы — маршрутизация и балансировка нагрузки. Всё форвардинг-решение принимается в OpenFlow: сетевой стек ядра контейнера транзитный трафик не обрабатывает.

  • Контейнер 1 (hpnn-lb) — Open vSwitch с kernel datapath в собственном netns, мост br-lb с тремя портами. Пайплайн из 42 правил и группы балансировки рендерится скриптом из topology.env и заливается атомарным бандлом.
  • Контейнеры 2 и 3 (hpnn-be1, hpnn-be2) — идентичный web-сервис на Go, каждый в своём приватном сегменте; отдаёт имя хоста, дату, время и адрес клиента.
  • Сети — публичный сегмент через macvlan поверх enp3s0 (настоящий L2 клиентской сети) и два приватных bridge-сегмента.
  • Инструментарий — make up/down/flows/verify, lbctl для осмотра датапаса, scripts/host-prereq.sh для подготовки хоста.

Результаты проверок

Проверка Результат
Kernel datapath OVS в netns контейнера system@ovs-system, поддержка recirculation, ct_state_nat, ct_zone
macvlan-интерфейс как порт OVS работает, pub0 — ofport 1
selection_method=hash, fields(ip_src,tcp_src) принят OVS 3.1
Балансировка 20 запросов с клиента be1/be2 ≈ 10/10, счётчики обоих бакетов растут
Сохранение IP клиента бэкенд видит 192.168.5.13 — DNAT без SNAT подтверждён
ARP- и ICMP-респондеры OVS ping до узла и до VIP проходит
Маршрутизация между приватными сегментами be1 → be2 через таблицы 20/21
Профиль A (§3.2 дизайна v1) egress бэкенда наружу работает и на порту p2 не появляется
ofproto/trace пути клиент → VIP DNAT, dec_ttl, перепись MAC, выход в порт 2

Отличия от плана

  1. Публичная сеть объявлена с подсетью 192.168.55.0/24, а не 192.168.5.0/24. Docker отказывается регистрировать пул, пересекающийся с уже существующей macvlan-сетью соседнего стенда router-functest (Pool overlaps with other one on this address space). Объявленная подсеть нужна только Docker IPAM: адреса узла и VIP живут исключительно в правилах OpenFlow, а macvlan включён в enp3s0 и работает на реальном L2.

  2. Обратный путь занял таблицы 15 и 16 вместо 30 и 31. goto_table в OpenFlow разрешает переход только вперёд, поэтому таблицы обратного пути обязаны стоять до общей маршрутизации (20).

  3. DNAT вынесен из бакетов группы в отдельную таблицу 11. Бакет только кладёт номер члена пула в reg2 и делает resubmit. Так вся логика трансляции лежит в одном месте и не зависит от того, какие действия допустимы внутри бакета.

  4. Обучение MAC клиентов сужено до трафика, адресованного стенду (VIP, адрес узла, приватные сегменты). В первой редакции learn срабатывал на любой IP-пакет с macvlan-порта и заносил в таблицу 21 весь широковещательный шум сегмента — DHCP, mDNS, SSDP всех соседей по LAN.

  5. Проверка профиля A добавлена в verify.sh — в плане она была только ручной.

Известные ограничения

Осознанные упрощения шага 1, каждое — задача следующих шагов:

  • Датапас stateful. Обратную трансляцию выполняет ct(nat), а не stateless un-DNAT из §2 дизайна v1. Следствие: прямой и обратный трафик сессии обязаны проходить через один узел, то есть Active/Active ECMP в такой схеме работать не будет.
  • ICMP-ошибки не генерируются. У чисто-OpenFlow узла нет стека, который бы формировал TTL exceeded и fragmentation needed; PMTUD через стенд не работает, traceroute не показывает узел.
  • Фрагменты IP не обрабатываются — правила матчат L4-заголовок, которого во втором и последующих фрагментах нет.
  • Один узел LB. Ни BGP, ни BFD, ни ECMP-набора: FRR в стенде нет, место под него (internal-порты с IP) на шаге 1 не занято, поскольку маршрутизация выполняется целиком в OpenFlow.
  • Нет health-check. Бэкенды считаются живыми всегда; отказ бэкенда не выводит его из группы. У приложения есть /healthz как задел.
  • Пул и листенер статические — заданы в topology.env, control plane и OVSDB-схемы из §6 дизайна v1 нет.
  • MAC бэкендов прописаны статически. ARP-резолвер next-hop отсутствует; MAC зафиксированы в docker-compose.yml.
  • Только TCP и только IPv4. UDP- и L3-листенеров нет.

Задел на шаг 2

  1. Заменить ct(nat) на stateless DNAT/un-DNAT с таблицей слотов и multipath(symmetric_l4) — это спайк S0 из §12 дизайна v1 и предпосылка для Active/Active.
  2. Проверить детерминизм выбора бэкенда: один и тот же 5-tuple должен давать один и тот же слот на разных узлах и между перезапусками (ofproto/trace по корпусу синтетических кортежей).
  3. Подсистема health-check: пробы с уникального адреса узла, вывод члена из пула, перерасчёт таблицы слотов.
  4. Control plane: модель Load_Balancer → Listener → Pool → Member в OVSDB вместо topology.env, агент-рендерер пайплайна.
  5. ICMP-транслятор в userspace (packet-in) — для PMTUD и корректных ICMP-ошибок от имени VIP.