Files
hpnn-proto/docs/OVS_DPDK_MIGRATION.md
ayurishchevandClaude Opus 5 5e9a035f6e Документ по переходу ноды на OVS-DPDK
Анализ текущего состояния стенда и перечень изменений для ПРОД-окружения
на выделенном сервере с OVS-DPDK.

Основной вывод инвентаризации: вся форвардинг-логика DPDK-совместима,
pipeline.sh переносится без изменений. Переделке подлежат подключение
портов (macvlan и veth -> dpdk и vhost-user), размещение узла
(контейнер -> железо) и инструментарий.

Отдельно зафиксировано, что потолок производительности сместится с PPS
на CPS: multipath и ct(commit) дают upcall на каждое новое соединение,
и они же вместе с learn блокируют hardware offload.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 21:08:07 +03:00

19 KiB
Raw Permalink Blame History

Переход на OVS-DPDK: перечень необходимых изменений

Дата: 2026-08-17 Зачем: в ПРОД-окружении нода HPNN (маршрутизатор и балансировщик) работает на выделенном физическом сервере с OVS-DPDK. Документ фиксирует, что для этого нужно изменить, что переносится как есть и где ожидаются потери. Основание: фактическое состояние стенда на 2026-08-17 (шаг 3).

1. Исходное состояние — что измерено

Параметр Значение в стенде
Сборка OVS 3.1.0, dpdk_initialized=false, dpdk_version=none
Датапас system@ovs-system — kernel datapath
datapath_type моста пусто (то есть system)
Порты моста 11: pub0 (macvlan), p2/p3 (veth в docker-бридж), hcif-p2/hcif-p3 (internal), 6 veth к контейнерам ВМ
Правил в пайплайне 105 + 1024 в таблице слотов
Действия пайплайна load 91, goto_table 52, move 36, learn 36, ct 16, IN_PORT 14, mod_dl_src 11, mod_dl_dst 10, multipath 4, dec_ttl 3
Состояние ct ~250 записей, 19 потоков датапаса с recirc

Вывод из инвентаризации: вся форвардинг-логика DPDK-совместима — все перечисленные действия поддерживает userspace-датапас (netdev). Переделке подлежит не пайплайн, а способ подключения портов, размещение узла и инструментарий. Отдельный разговор — производительность: ct, learn и multipath определяют её потолок (раздел 6).

2. Что переносится без изменений

  • lb/pipeline.sh целиком — таблицы 0/1/5/6/10/11/12/15/16/20/21/24/25, включая ARP- и ICMP-респондеры (move/load/IN_PORT), dec_ttl, multipath(symmetric_l4), ct(commit,nat) и ct(nat), действие learn, рассылку по списку портов и fail_mode=secure.
  • Логика Maglev (hc/maglev.go) и формат бандла ovs-ofctl — датапаса не касаются вовсе.
  • Детерминизм выбора члена. multipath считается в ofproto, а не в датапасе, поэтому номер слота для одного 5-tuple не зависит от типа датапаса — раскладка и дайджест при переходе не меняются. Подлежит подтверждению спайком S-DPDK-1 (раздел 8).
  • Адресная модель: VIP в правилах, шлюзы сегментов, уникальные адреса источника health-проб, PRIV_LISTENERS.

3. Изменения по слоям

3.1. Хост и ОС

Что Требование
Hugepages 1 GB страницы, объём под dpdk-socket-mem + vhost-user; default_hugepagesz=1G hugepagesz=1G hugepages=N в cmdline
Изоляция ядер isolcpus, nohz_full, rcu_nocbs для ядер PMD; PMD-ядра не отдаются планировщику
Драйвер NIC vfio-pci (с iommu=pt intel_iommu=on), NIC отвязана от ядра
NUMA PMD-ядра, hugepages и NIC — на одном сокете; проверять numactl -H и /sys/class/net/*/device/numa_node
Пакеты OVS, собранный с DPDK (--with-dpdk), версии OVS и DPDK согласованы
Модуль openvswitch не нужен — modprobe openvswitch из scripts/host-prereq.sh и lb/entrypoint.sh уходит

3.2. Конфигурация OVS

ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-mem="2048,0"
ovs-vsctl set Open_vSwitch . other_config:dpdk-lcore-mask=0x1
ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=0x3c      # ядра PMD
ovs-vsctl set Open_vSwitch . other_config:userspace-tso-enable=true
ovs-vsctl add-br br-lb -- set bridge br-lb datapath_type=netdev \
    -- set bridge br-lb fail_mode=secure \
    -- set bridge br-lb protocols=OpenFlow13,OpenFlow15

datapath_type=netdev на мосту — единственное изменение в самой сборке моста; fail_mode=secure и набор протоколов сохраняются.

3.3. Порты — главная переделка

Сейчас В ПРОД на DPDK
pub0 — macvlan поверх enp3s0, перенесённый в netns контейнера type=dpdk, options:dpdk-devargs=0000:xx:00.0; при необходимости dpdkbond для LAG
p2/p3 — veth в docker-бридж (аплинк сегмента к шлюзу Docker) физический порт или VLAN-подынтерфейс к фабрике сегмента; шлюза Docker в ПРОД нет
Порты ВМ (be1…cli3) — veth, создаваемые scripts/attach-segment.sh через nsenter type=dpdkvhostuserclient, options:vhost-server-path=/var/run/openvswitch/vhostuserN; порты создаёт гипервизор при старте ВМ
hcif-p2/hcif-p3 — type=internal с IP в ядре type=internal в netdev-мосте (реализуется как tap) либо отдельная management-NIC в ядре — см. 3.5

Предпосылка шага 3 «порт ВМ — порт OVS» на DPDK выполняется естественно: vhost-user — это и есть порт моста. scripts/attach-segment.sh и make attach в ПРОД не нужны — вместе с network_mode: none и всей docker-обвязкой.

Дополнительно потребуется задать: mtu_request (jumbo, если фабрика позволяет), options:n_rxq и other_config:pmd-rxq-affinity для распределения очередей по PMD, options:n_rxq_desc/n_txq_desc.

3.4. Размещение узла: контейнер → сервер

  • docker-compose.yml, lb/Dockerfile, privileged: true, /lib/modules:ro — уходят. Узел ставится на железо.
  • lb/entrypoint.sh разделяется на: конфигурацию OVS (systemd-юнит ovs-vswitchd с DPDK-опциями), сборку моста и портов (штатный ovsdb-конфиг, а не скрипт при старте) и запуск hcd как systemd-сервиса.
  • lb/topology.env остаётся источником правды, но описывает физические порты, PCI-адреса и пути vhost-user вместо MAC docker-интерфейсов. Опознание порта по MAC (find_dev_by_mac) заменяется на PCI-адрес и имя vhost-сокета.
  • lb/apply.sh, lb/lbctl.sh работают как есть — они общаются с OVS через ovs-vsctl/ovs-ofctl локально; из них убираются обёртки docker compose exec.

3.5. Health-check (hc/)

Демон менять почти не нужно, но одно место требует решения: пробы уходят из сетевого стека ядра (net.Dialer.LocalAddr на адресе internal-порта). В DPDK-мосте такой порт — tap-устройство, и трафик проб идёт медленным путём через ядро. Для проб (единицы пакетов в секунду на члена) это допустимо, но требует проверки задержки и того, что tap не привязан к PMD-ядру.

Варианты, которые надо сравнить на спайке:

  1. type=internal в netdev-мосте — минимум изменений, hcd остаётся как есть. Предпочтительный вариант по умолчанию.
  2. Отдельная management-NIC в ядре — пробы идут в обход датапаса; требует маршрутной достижимости сегментов бэкендов, то есть меняет топологию.
  3. Пробер поверх DPDK (собственный TCP-стек или AF_XDP) — снимает зависимость от ядра, но это отдельная разработка; вне рамок миграции.

Остальное в hc/ переносится без изменений: exec ovs-ofctl bundle, HTTP API, /metrics, Maglev, гистерезис.

3.6. Инструментарий и проверки

Файл Что делать
scripts/host-prereq.sh переписать: вместо modprobe openvswitch и macvlan-shim — hugepages, vfio-pci, проверка изоляции ядер и NUMA
scripts/attach-segment.sh удалить: порты создаёт гипервизор
scripts/verify.sh сохранить структуру проверок, заменить транспорт: docker compose exec → ssh/локальные вызовы на ВМ; добавить проверки PMD (загрузка, drops, pmd-rxq-show)
Makefile цели up/down/attach/shim заменяются на управление сервисами; flows, health, slots, fdb, trace остаются
perftest/k6_bench.js k6 через стек ядра не покажет предел DPDK: нужен генератор трафика (TRex, MoonGen, dpdk-pktgen) с профилем по новым соединениям в секунду, а не только по PPS

4. Что нужно решить до миграции — влияние на пайплайн

Ни одно из перечисленного не блокирует запуск, но каждое влияет на потолок производительности и должно быть решено осознанно.

Механизм Где Состояние на DPDK Решение
ct(commit,nat) / ct(nat) t12, t15, t24 userspace conntrack работает, включая NAT оставить на первом этапе; параллельно вести переход на stateless un-DNAT (nw_src=member, tp_src=8080 → VIP:80) — он уже стоит в заделе шага 3
learn (FDB t25, adjacency t21) t0, t1 работает, но каждый новый MAC/адрес — upcall; несовместим с полным HW offload для ВМ состав сегмента известен control plane: заменить обучение на статические записи, оставив learn только как страховку
multipath t10 считается в ofproto, работает оставить; проверить детерминизм спайком
recirculation после ct работает учесть в бюджете PMD-цикла: каждый recirc — повторный проход
IN_PORT, рассылка по списку портов t5, t25 работает при большом числе ВМ в сегменте заменить рассылку на явные группы вывода
type=internal hcif-* tap, медленный путь см. 3.5
Hardware offload (hw-offload=true, rte_flow) — несовместим с ct, learn, multipath, recirc на первом этапе не включать; рассматривать только после перехода на stateless-датапас

5. Изменения по файлам — сводка

Файл Действие
lb/pipeline.sh без изменений (кроме подстановки новых номеров портов)
hc/maglev.go, hc/main.go без изменений; открытый вопрос — источник проб (3.5)
lb/topology.env переписать порты: PCI-адреса, пути vhost-user, номера ofport
lb/entrypoint.sh разделить на systemd-юниты и конфигурацию OVS
lb/apply.sh, lb/lbctl.sh убрать обёртки docker compose exec
docker-compose.yml, lb/Dockerfile не применяются в ПРОД (остаются для стенда)
scripts/attach-segment.sh удалить
scripts/host-prereq.sh переписать под hugepages/vfio/NUMA
scripts/verify.sh адаптировать транспорт, добавить PMD-проверки
perftest/ заменить k6 на аппаратный генератор
Makefile цели жизненного цикла заменить на управление сервисами

6. Потолок производительности — что определяет предел

Главный вывод анализа: на DPDK узкое место сместится с PPS на число новых соединений в секунду (CPS).

  • multipath вычисляет слот от 5-tuple, поэтому megaflow для балансируемого трафика матчит полный 5-tuple: каждое новое соединение даёт upcall и собственную запись в датапасе. То же делает ct(commit).
  • Установленные соединения обслуживаются из кэшей (EMC → SMC → megaflow) на скорости PMD; проблема только в темпе появления новых.
  • Настройки, влияющие на это: размер EMC (emc-insert-inv-prob), число handler threads, pmd-cpu-mask, n_rxq.

Отсюда программа измерений: отдельно PPS на установленных потоках и отдельно CPS на новых. Сравнивать надо с текущим kernel-датапасом на том же профиле, иначе цифры не сопоставимы.

Второй фактор — recirculation после каждого ct: удваивает число проходов по таблицам для балансируемого трафика.

7. План миграции по этапам

Этап Содержание Критерий готовности
1 Стенд с datapath_type=netdev на том же железе, порты — dpdkvhostuser + одна физическая NIC все текущие проверки verify.sh проходят, дайджест раскладки совпадает с kernel-датапасом
2 Спайки S-DPDK-1…3 (раздел 8) детерминизм подтверждён, источник проб выбран, CPS измерен
3 Замена learn на статические записи от control plane FDB и adjacency не зависят от трафика; verify.sh зелёный
4 Stateless un-DNAT вместо ct в t15 и t24 сессии живут, dump-conntrack пуст, recirc-проходов меньше
5 Профилирование и тюнинг: n_rxq, pmd-rxq-affinity, hugepages, TSO целевые PPS и CPS достигнуты, PMD без drops
6 Оценка HW offload (только после этапа 4) измеренный выигрыш против потери гибкости

Порядок не произвольный: этапы 3 и 4 снимают именно те механизмы, которые блокируют offload и дают upcall на каждое соединение.

8. Спайки, которые надо выполнить до перевода ПРОД

  • S-DPDK-1 — детерминизм multipath. Один и тот же корпус синтетических 5-tuple через ofproto/trace на kernel- и netdev-датапасе обязан давать одинаковые reg1/reg2. Блокирующий: на нём стоит вся модель раскладки.
  • S-DPDK-2 — ct с NAT в userspace. Проверить обратную трансляцию в t15 и t24, поведение при переполнении таблицы соединений, стоимость recirc.
  • S-DPDK-3 — источник health-проб. Работает ли type=internal в netdev-мосте, какова задержка проб под нагрузкой PMD, не голодает ли tap.
  • S-DPDK-4 — CPS и PPS. Аппаратный генератор: предел по новым соединениям и по установленным потокам, с профилем, приближенным к целевому.

9. Открытые вопросы к разработке и эксплуатации

  1. Сколько ВМ в сегменте ожидается — от этого зависит, допустима ли рассылка списком портов в t25 и нужны ли группы вывода.
  2. Нужен ли dpdkbond/LACP на аплинке и VLAN-теги на портах сегментов — сейчас VLAN в пайплайне не используется вовсе.
  3. Целевые MTU и включение TSO для vhost-user.
  4. Кто создаёт vhost-user порты и заполняет topology.env — гипервизор, оркестратор или control plane HPNN (это же вопрос модели Load_Balancer → Listener → Pool → Member в OVSDB).
  5. Останется ли профиль A (default бэкенда мимо балансировщика) или в ПРОД используется профиль B — от этого зависит объём egress через узел.
  6. Где живёт узел относительно фабрики: сегменты приходят отдельными портами, VLAN'ами или туннелями.

10. Чек-лист конфигурации перед вводом в эксплуатацию

# датапас и DPDK
ovs-vsctl get Open_vSwitch . dpdk_initialized          # true
ovs-vsctl get bridge br-lb datapath_type               # netdev
ovs-appctl dpif/show                                   # netdev@ovs-netdev

# PMD и очереди
ovs-appctl dpif-netdev/pmd-rxq-show
ovs-appctl dpif-netdev/pmd-stats-show                  # drops, cycles
ovs-appctl dpif-netdev/pmd-perf-show

# хост
cat /proc/meminfo | grep Huge
lscpu | grep -i numa; numactl -H
dpdk-devbind.py --status                               # NIC на vfio-pci

# функциональность (как в стенде)
make flows && make health && make slots && make fdb
lbctl trace <src> <sport> p2