Анализ текущего состояния стенда и перечень изменений для ПРОД-окружения на выделенном сервере с 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>
19 KiB
Переход на 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-ядру.
Варианты, которые надо сравнить на спайке:
type=internalв netdev-мосте — минимум изменений,hcdостаётся как есть. Предпочтительный вариант по умолчанию.- Отдельная management-NIC в ядре — пробы идут в обход датапаса; требует маршрутной достижимости сегментов бэкендов, то есть меняет топологию.
- Пробер поверх 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. Открытые вопросы к разработке и эксплуатации
- Сколько ВМ в сегменте ожидается — от этого зависит, допустима ли рассылка списком портов в t25 и нужны ли группы вывода.
- Нужен ли
dpdkbond/LACP на аплинке и VLAN-теги на портах сегментов — сейчас VLAN в пайплайне не используется вовсе. - Целевые MTU и включение TSO для vhost-user.
- Кто создаёт vhost-user порты и заполняет
topology.env— гипервизор, оркестратор или control plane HPNN (это же вопрос моделиLoad_Balancer → Listener → Pool → Memberв OVSDB). - Останется ли профиль A (default бэкенда мимо балансировщика) или в ПРОД используется профиль B — от этого зависит объём egress через узел.
- Где живёт узел относительно фабрики: сегменты приходят отдельными портами, 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