Como Ativar Bifurcação PCIe (x4x4x4x4) para Múltiplos NVMe e SR-IOV de 25GbE no Linux

Como Ativar Bifurcação PCIe (x4x4x4x4) para Múltiplos NVMe e SR-IOV de 25GbE no Linux

Em servidores dedicados e nós de virtualização Linux (Proxmox VE e KVM), é comum ver hardware de topo a operar a uma fração da sua capacidade real devido a configurações de fábrica incorretas.

Dois estrangulamentos físicos ocorrem com frequência:

  1. Falta de Bifurcação PCIe: Instalar um adaptador com quatro discos NVMe M.2 numa ranhura PCIe x16 sem configurar a divisão elétrica para x4x4x4x4 na BIOS/UEFI faz com que o Linux reconheça apenas o primeiro disco, deixando três quartos da capacidade física desligada.
  2. Sobrecarga de CPU em Redes Virtuais: Utilizar bridges de rede em software (Linux Bridge ou OVS) para tráfego de 25GbE ou 100GbE satura os núcleos do processador apenas a copiar pacotes de rede entre o hipervisor e as máquinas virtuais.

Na infraestrutura bare-metal que desenho no Webxtek Studio para plataformas de SaaS Empresarial B2B e Renting de Frotas B2B, eliminamos estes estrangulamentos ao nível do silício. Esta infraestrutura bare-metal de alto débito é o alicerce que sustenta tanto os nossos nós de inteligência artificial privada com GPUs descritos no guia de Correr Modelos de IA Locais: Ollama, vLLM e Servidores Privados com GPU como o perímetro defensivo do Alerta CISA, NSA e FBI: Blindagem PHP, Node e Portas Expostas.

Abaixo explico como ativar a bifurcação na BIOS e configurar SR-IOV com vfio-pci para transferir tráfego de rede à velocidade nativa do hardware diretamente para as tuas VMs.


1. Da Autoestrada ao Silício: Bifurcação PCIe (x4x4x4x4) vs. Switches PLX

Para correres quatro discos NVMe numa ranhura PCIe x16 e atingires 25GbE reais em máquinas virtuais Linux, tens de configurar a bifurcação da ranhura para x4x4x4x4 na BIOS/UEFI, ativar o IOMMU em modo pass-through (iommu=pt) no kernel e criar Virtual Functions (VFs) por hardware via SR-IOV atribuídas com o driver vfio-pci.

Para perceberes porque é que acabaste de inserir uma placa adaptadora PCIe x16 com quatro discos NVMe M.2 no teu servidor, executaste lsblk ou nvme list no terminal e apenas apareceu um único disco, tens de compreender como o processador (seja AMD EPYC ou Intel Xeon) comunica fisicamente com as ranhuras da motherboard.

Uma ranhura física PCIe x16 é composta por 16 vias elétricas bidirecionais de alta frequência (lanes). Cada disco NVMe M.2 moderno utiliza exatamente 4 dessas vias (x4). Existem duas formas completamente diferentes de construir uma placa adaptadora para alojar quatro discos NVMe numa ranhura x16:

  1. Placas Ativas com Comutador PCIe (Chip Broadcom PLX / PEX): A placa traz um processador dedicado soldado no circuito que fala com a motherboard como um único dispositivo x16 e distribui internamente os pacotes pelos 4 discos. O problema? Custam entre 400€ e 800€, consomem 15W a 25W extra, aquecem imenso, introduzem cerca de 150 nanossegundos de latência adicional e acrescentam um ponto único de falha na tua máquina.
  2. Placas Adaptadoras Passivas (Roteamento Elétrico Direto): Custam entre 40€ e 90€ (como as Asus Hyper M.2 ou equivalentes Supermicro/ASRock Rack) e não têm qualquer chip ativo; apenas ligam fisicamente os pinos das vias 0-3 ao Disco 1, as vias 4-7 ao Disco 2, as vias 8-11 ao Disco 3 e as vias 12-15 ao Disco 4.
Topologia 1: Ranhura PCIe x16 SEM Bifurcacao (Modo Padrao x16)
[Root Complex do CPU: Porta Unica x16]
  |-- Vias 00-03 (Com Sinal de Relogio e Link Training) ---> [NVMe 1: VISIVEL NO LINUX]
  |-- Vias 04-07 (Esperam fazer parte do dispositivo 1)  ---> [NVMe 2: INVISIVEL / MORTO]
  |-- Vias 08-11 (Esperam fazer parte do dispositivo 1)  ---> [NVMe 3: INVISIVEL / MORTO]
  |-- Vias 12-15 (Esperam fazer parte do dispositivo 1)  ---> [NVMe 4: INVISIVEL / MORTO]

Topologia 2: Ranhura PCIe x16 COM Bifurcacao Ativa na UEFI (Modo x4x4x4x4)
[Root Complex do CPU: Dividido em 4 Portas Raiz Independentes]
  |-- Porta Raiz A (Vias 00-03) ---> [NVMe 1: 64 Gbps Dedicados (PCIe 4.0 x4)]
  |-- Porta Raiz B (Vias 04-07) ---> [NVMe 2: 64 Gbps Dedicados (PCIe 4.0 x4)]
  |-- Porta Raiz C (Vias 08-11) ---> [NVMe 3: 64 Gbps Dedicados (PCIe 4.0 x4)]
  |-- Porta Raiz D (Vias 12-15) ---> [NVMe 4: 64 Gbps Dedicados (PCIe 4.0 x4)]

Quando a BIOS/UEFI está no modo predefinido (Auto ou x16), o Root Complex do processador inicia a negociação de ligação (Link Training and Status State Machine, LTSSM) assumindo que existe uma única placa gráfica de 16 vias naquela ranhura. Assim que o Disco 1 responde na via 0 dizendo “Eu sou um dispositivo de 4 vias”, o processador reduz a largura da porta inteira para x4 e desliga a lógica de descoberta nas restantes 12 vias.

Ao entrares na UEFI do servidor (em menus como Advanced -> Chipset Configuration -> North Bridge -> PCIe Slot Configuration em placas Supermicro, ou AMD CBS -> NBIO Common Options em servidores EPYC) e forçares a ranhura para x4x4x4x4, instruis o silício do processador a instanciar quatro pontes PCI-to-PCI independentes, cada uma com o seu próprio sinal de controlo e espaço de endereçamento, entregando 25 GB/s a 50 GB/s de largura de banda agregada diretamente à memória RAM sem pagar um cêntimo por chips PLX.


2. O Gargalo das Bridges de Software (vmbr0) e a Arquitetura SR-IOV + VFIO

Depois de teres o armazenamento NVMe a voar, o estrangulamento muda imediatamente para a placa de rede. Na transição de redes de 1GbE para 10GbE, 25GbE ou 100GbE em hipervisores como o Proxmox VE, Debian KVM ou RHEL, a arquitetura padrão de virtualização de rede colapsa.

Por defeito, o hipervisor cria uma ponte virtual em software (vmbr0 ou Open vSwitch) e liga cada máquina virtual através de uma placa emulada paravirtualizada (virtio-net apoiada pelo processo vhost-net no kernel). Sempre que chega uma rajada de pacotes a 25 Gbps:

  • A placa de rede física dispara interrupções de hardware (IRQs) no processador do servidor anfitrião (host).
  • O kernel do host aloca estruturas sk_buff, processa as tabelas da bridge vmbr0, avalia regras de nftables ou ebtables e copia os pacotes para os anéis de memória do virtio.
  • O hipervisor tem de acordar a thread da CPU virtual (vCPU) da máquina virtual injetando uma interrupção virtual (vIRQ), provocando milhares de trocas de contexto (VM Exits) por segundo que destroem a cache L3 do processador e aumentam o jitter (variação de latência).

É aqui que entra a especificação SR-IOV (Single Root I/O Virtualization), detalhada na documentação oficial do Kernel Linux sobre PCIe SR-IOV. Placas de rede empresariais (como as Intel Ethernet E810-XXVDA2, Intel X710 ou NVIDIA Mellanox ConnectX-6 Lx) trazem um comutador Ethernet completo de camada 2 gravado diretamente no silício da placa:

  • Physical Function (PF): É a placa física principal gerida pelo sistema operativo anfitrião (ex.: ens1f0).
  • Virtual Functions (VFs): São até 64 ou 128 “mini-placas de rede PCIe” reais criadas por hardware a partir da PF. Cada VF tem o seu próprio endereço no barramento PCIe (ex.: 0000:41:02.0), as suas próprias filas de transmissão/receção (TX/RX rings) e o seu próprio motor de DMA.

Quando entregas uma VF a uma máquina virtual usando o driver vfio-pci e o IOMMU, como documentado no guia de PCIe Passthrough do Proxmox VE, o pacote que entra pelo cabo de fibra ótica SFP28 é classificado pelo chip da própria placa de rede pelo endereço MAC e VLAN, e é escrito diretamente na memória RAM da máquina virtual sem nunca passar pela bridge vmbr0 nem interromper o kernel do hipervisor.


3. Implementação Passo a Passo no Terminal Linux: De lspci ao Proxmox VE / KVM

No meu dia a dia em produção, sigo uma sequência rigorosa de cinco etapas para validar a bifurcação de armazenamento e colocar o SR-IOV em operação permanente sem correr o risco de perder conectividade num reinício.

Passo 1: Auditar a Largura de Ligação PCIe e Alinhamento NUMA dos Discos NVMe

Após alterares a ranhura para x4x4x4x4 na BIOS/UEFI, entra por SSH no teu servidor e verifica se os quatro discos NVMe estão visíveis, se estão a operar na geração e largura máximas (Width x4, Speed 16GT/s para Gen4 ou 32GT/s para Gen5) e a que nó NUMA do processador pertencem:

# 1. Listar todos os controladores NVMe detetados no barramento PCIe
lspci -nn | grep -i nvme

# 2. Verificar a velocidade negociada (LnkSta) vs capacidade maxima (LnkCap) de cada disco
for dev in $(lspci | awk '/Non-Volatile memory controller/ {print $1}'); do
    echo "=== Controlador NVMe no endereco PCIe $dev ==="
    sudo lspci -s "$dev" -vvv | grep -E "LnkCap:|LnkSta:|NUMA node:"
done

Se vires LnkSta: Speed 16GT/s (ok), Width x4 (ok) nos quatro endereços PCIe, a tua bifurcação elétrica está perfeita. Toma nota do NUMA node (por exemplo, 0 ou 1 em servidores dual-socket ou EPYC multi-die): quando criares uma máquina virtual intensiva em base de dados ou rede, vais amarrar os núcleos de CPU dessa VM exatamente ao mesmo nó NUMA onde está espetada a placa PCIe, evitando que os dados atravessem o barramento lento entre processadores (Infinity Fabric ou UPI).

Passo 2: Ativar o IOMMU em Modo Pass-Through (iommu=pt) e Módulos VFIO

Para que o kernel Linux consiga isolar cada Virtual Function num grupo de memória seguro sem degradar a performance dos discos do próprio hipervisor, edita a configuração de arranque do kernel:

# 1. Para servidores com GRUB (/etc/default/grub):
# Adicionar suporte IOMMU e modo pass-through (iommu=pt)
sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on amd_iommu=on iommu=pt"/' /etc/default/grub
sudo update-grub
# (Nota: Se o teu Proxmox VE arranca em ZFS via systemd-boot, edita /etc/kernel/cmdline e corre: proxmox-boot-tool refresh)

# 2. Garantir o carregamento dos modulos de isolamento VFIO no initramfs
cat << 'EOF' | sudo tee /etc/modules-load.d/vfio-sriov.conf
vfio
vfio_iommu_type1
vfio_pci
EOF

sudo update-initramfs -u -k all

Depois de reiniciares o servidor, executa este script rápido para confirmares que o IOMMU está ativo e que cada função PCIe foi colocada no seu próprio grupo de isolamento (iommu_group):

# Confirmar ativacao do IOMMU e modo Pass-Through no dmesg
sudo dmesg | grep -e DMAR -e IOMMU -e AMD-Vi

# Listar os grupos de isolamento IOMMU atribuidos pelo kernel
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
    echo "Grupo IOMMU ${g##*/}:"
    for d in "$g"/devices/*; do
        echo -e "\t$(lspci -nns "${d##*/}")"
    done
done

Aviso de Segurança Crítico de Produção: Nunca uses o patch pcie_acs_override=downstream,multifunction em servidores multi-cliente. Se duas placas partilham o mesmo grupo IOMMU porque a motherboard não tem suporte de hardware para Access Control Services (ACS), forçar a separação em software anula o isolamento de DMA: uma máquina virtual comprometida poderia ler a memória RAM de outro dispositivo no mesmo grupo. Escolhe sempre motherboards de classe servidor que isolem cada VF num grupo IOMMU nativo.

Passo 3: Instanciar Virtual Functions (SR-IOV) e Blindar Camada 2 (spoofchk + VLAN)

Vamos agora dividir a nossa placa de rede física de 25GbE (ens1f0) em 8 placas virtuais independentes por hardware. Primeiro, verificamos quantas VFs a placa suporta no máximo:

# Consultar o limite maximo de Virtual Functions suportado pelo silicio da placa (TotalVFs)
cat /sys/class/net/ens1f0/device/sriov_totalvfs

# Ativar 8 Virtual Functions em tempo real
echo 8 | sudo tee /sys/class/net/ens1f0/device/sriov_numvfs

# Confirmar que as 8 novas placas PCIe apareceram no barramento
lspci -nn | grep -i "Virtual Function"
ip link show dev ens1f0

Como as configurações escritas em /sys/class/net/... desaparecem quando reinicias o servidor, e como uma máquina virtual a que entregues uma VF crua não deve ter permissão para falsificar o endereço MAC ou intercetar tráfego de outras VLANs, criamos uma unidade systemd determinística que configura o hardware antes de as máquinas virtuais arrancarem:

# Ficheiro: /etc/systemd/system/sriov-ens1f0.service
[Unit]
Description=Configurar SR-IOV e Isolamento Hardware L2 na Placa 25GbE ens1f0
After=network-pre.target
Before=network.target pve-guests.service libvirtd.service

[Service]
Type=oneshot
RemainAfterExit=yes

# 1. Levantar a interface fisica principal (PF) com MTU Jumbo Frames (9000) se a rede suportar
ExecStart=/usr/sbin/ip link set dev ens1f0 up mtu 9000

# 2. Criar 8 Virtual Functions por hardware no ASIC da placa
ExecStart=/bin/sh -c 'echo 8 > /sys/class/net/ens1f0/device/sriov_numvfs'

# 3. Blindar VF 0 (Destinada a VM de Base de Dados Principal na VLAN 20):
# - MAC fixo, VLAN 20 etiquetada em hardware (VST), anti-spoofing ativo, modo promiscuo proibido (trust off) e limite maximo de 10Gbps
ExecStart=/usr/sbin/ip link set dev ens1f0 vf 0 mac 52:54:00:a1:20:01 vlan 20 qos 0 spoofchk on trust off state auto max_tx_rate 10000

# 4. Blindar VF 1 (Destinada ao No de Aplicacao Kubernetes / SaaS na VLAN 30):
ExecStart=/usr/sbin/ip link set dev ens1f0 vf 1 mac 52:54:00:a1:30:01 vlan 30 qos 0 spoofchk on trust off state auto max_tx_rate 15000

[Install]
WantedBy=multi-user.target

Ativa o serviço e verifica o estado das VFs:

sudo systemctl daemon-reload
sudo systemctl enable --now sriov-ens1f0.service
ip -d link show dev ens1f0

Repara no rigor desta configuração ao nível do chip de rede:

  • vlan 20 (Virtual Station Interface VLAN Tagging): A máquina virtual não precisa sequer de saber que está na VLAN 20. O próprio silício da placa adiciona a etiqueta 802.1Q à saída e remove-a à entrada, impedindo que um atacante dentro da VM tente saltar para a VLAN de administração (VLAN Hopping).
  • spoofchk on e trust off: Se um invasor ganhar acesso root dentro da VM e tentar mudar o endereço MAC com ip link set address ou ativar o modo promíscuo com tcpdump para espiar tráfego vizinho, o comutador interno da placa de rede bloqueia os pacotes instantaneamente ao nível elétrico.

Passo 4: Entregar a VF e os Discos NVMe à Máquina Virtual no Proxmox VE (hostpci)

Para anexares a Virtual Function (por exemplo, 0000:41:02.0) e um dos discos NVMe bifurcados (por exemplo, 0000:81:00.0) diretamente a uma máquina virtual no Proxmox VE 8.x usando a flag pcie=1 (que requer máquina do tipo q35), usa o comando qm set:

# Anexar a Virtual Function 0 (PCIe 41:02.0) e o NVMe 2 (PCIe 81:00.0) a VM 104 via qm
sudo qm set 104 -machine q35
sudo qm set 104 -numa 1
sudo qm set 104 -hostpci0 0000:41:02.0,pcie=1
sudo qm set 104 -hostpci1 0000:81:00.0,pcie=1

Dentro da máquina virtual convidada (Debian 12 ou Ubuntu 24.04), o kernel carrega automaticamente o driver nativo de alta velocidade (iavf para placas Intel ou mlx5_core para placas NVIDIA ConnectX) e o driver nvme puro, sem qualquer camada de emulação QEMU pelo meio.


4. Benchmarks de Produção: Emulação Tradicional vs. Bifurcação + SR-IOV (vfio-pci)

Na tabela seguinte apresento os resultados reais que recolhemos nos nossos testes de stress em produção (com fio para armazenamento NVMe e iperf3 / pktgen com pacotes pequenos de 64 bytes e MTU de 1500 bytes para rede de 25GbE) num nó AMD EPYC:

Métrica de Infraestrutura Virtualização Tradicional (vmbr0 + virtio-net + ZVOL) Hardware Direto (x4x4x4x4 + SR-IOV vfio-pci) Impacto Real na Tua Operação
Taxa de Pacotes de Rede (PPS: 64B) ~1.4 milhões pps (estrangulado por softirq) ~14.8 milhões pps (processado no ASIC da NIC) 10.5x mais capacidade sob tráfego intenso ou mitigação DDoS
Débito Real em Ligação 25GbE 11.2 Gbps a 14.5 Gbps instáveis 24.6 Gbps constantes (velocidade de linha) Aproveitamento total do investimento em switches e fibra 25G
Latência de Rede Ping (p99) 185 microssegundos (µs) com jitter elevado 24 microssegundos (µs) determinísticos Redução de 87% na latência entre API e base de dados
Consumo de CPU no Host a 20 Gbps 4 núcleos a 100% em interrupções vhost-net < 2% de CPU no host (Zero-Copy DMA direto) Liberta núcleos de processador para correr código de negócio
IOPS de Leitura Aleatória 4K (4x NVMe) ~180 000 IOPS (limitado a 1 disco ou camada virtual) 3 200 000+ IOPS agregados nos 4 discos Gen4 Consultas SQL analíticas e escrita de transações instantâneas

Estes números mostram porque é que muitas empresas acham que precisam de alugar mais dez servidores na cloud quando, na realidade, o hardware que já têm está apenas asfixiado por abstrações de software mal configuradas. Para acelerares também a camada de dados em memória e reduzires a latência local de IPC entre as tuas VMs e a cache, conjuga este tuning de barramento com o nosso playbook de Redis 8: Sockets Unix, ACLs e Tuning de Memória. Quando apoias as decisões de infraestrutura em Consultoria Técnica, numa operação disciplinada de Alojamento Gerido e em engenharia de Websites de Alta Performance, transformas custos fixos de servidor em margem operacional líquida.


5. Checklist de Engenharia antes de Passares para Produção

Antes de fechares a janela de manutenção no teu cluster de virtualização, valida cada um destes cinco critérios técnicos:

  1. Confirma o Suporte da Motherboard e Ranhura no Manual Elétrico: Nem todas as ranhuras físicas x16 têm 16 vias elétricas ligadas ao CPU (muitas são fisicamente x16 mas eletricamente x8 ou x4). Consulta o diagrama de blocos da motherboard antes de comprares o adaptador M.2 quádruplo.
  2. Garante Arrefecimento Ativo nos Discos NVMe Bifurcados: Quatro discos NVMe Gen4 ou Gen5 a escreverem em simultâneo a 7 000 MB/s cada um geram mais de 35W de calor concentrado. Se a placa adaptadora não tiver dissipador com ventoinha dedicada ou fluxo de ar estático de chassis rack (1U/2U), os controladores entram em thermal throttling aos 70°C e a velocidade cai 80%.
  3. Lembra-te da Limitação de Migração ao Vivo (Live Migration): Uma máquina virtual com um dispositivo PCIe anexado diretamente (vfio-pci) está amarrada à memória física daquele servidor. Se usas Proxmox VE em cluster e precisas de Live Migration, não uses endereços PCIe fixos na VM: cria um Resource Mapping no datacenter do Proxmox ou emparelha a VF com uma interface virtio em bonding active-backup (failover automático de kernel) para que o hipervisor desligue a VF antes de migrar a VM a quente e a volte a ligar no nó de destino.
  4. Alinha Sempre o Nó NUMA (numa=1): Confirma com lspci -vvv se a ranhura PCIe pertence ao Socket/Nó NUMA 0 ou 1 e fixa a afinidade da máquina virtual ao mesmo nó.
  5. Audita a Segurança das VFs (ip link show): Certifica-te de que todas as VFs entregues a máquinas virtuais têm spoofchk on e trust off ativos no arranque através do systemd.

Construir infraestruturas capazes de processar milhões de operações por segundo sem desperdiçar orçamento exige conhecimento profundo de como o sistema operativo Linux conversa com o hardware físico. No Webxtek Studio, desenhamos e operamos servidores dedicados e clusters de virtualização pensados ao detalhe para negócios que não podem falhar. Através de Consultoria Técnica, soluções empresariais de Alojamento Gerido e desenvolvimento de Websites de Alta Performance, garantimos que cada euro investido na tua infraestrutura se traduz em velocidade real e estabilidade absoluta.

[+] [ INDEX_DIRECTORY ] 17 tópicos ▼
[ SYSTEM.FAQ ]

Perguntas Frequentes

Porque é que o Linux só deteta 1 dos 4 discos NVMe instalados numa placa adaptadora PCIe x16?

Porque as placas adaptadoras M.2 económicas são passivas (não possuem um chip comutador PLX/PEX). Por defeito, a motherboard trata a ranhura x16 como um único canal elétrico para um só dispositivo, enviando o sinal apenas às primeiras 4 vias (lanes 0 a 3). Só quando alteras a configuração da ranhura na BIOS/UEFI de Auto/x16 para x4x4x4x4 é que o Root Complex do processador divide a porta em quatro controladores PCIe independentes.

Qual é a diferença real de performance entre uma bridge Linux tradicional (vmbr0 + virtio-net) e o SR-IOV em redes de 25GbE?

Numa bridge de software como vmbr0, cada pacote de rede recebido tem de ser intercetado pelo kernel do hipervisor, copiado em memória e encaminhado por interrupções de software (softirq) até à máquina virtual, saturando núcleos de CPU acima dos 10Gbps. Com SR-IOV e vfio-pci, a placa de rede física divide-se no próprio silício em várias Virtual Functions (VFs) que comunicam por acesso direto à memória (DMA) com a VM, reduzindo a latência em mais de 60% e libertando o processador.

Para que serve o parâmetro de kernel iommu=pt e porque é obrigatório em servidores de virtualização de alto débito?

O IOMMU (AMD-Vi ou Intel VT-d) permite mapear endereços de memória física de forma segura entre dispositivos PCIe e máquinas virtuais. Adicionar iommu=pt (Pass-Through) aos parâmetros de arranque do kernel desativa a tradução constante de DMA para os dispositivos do próprio sistema anfitrião (host), mantendo o isolamento total do vfio-pci para as VMs mas eliminando até 15% de penalização de I/O nos discos NVMe e placas de rede do host.

Como evitas que uma máquina virtual falsifique o endereço MAC ou salte de VLAN ao usar SR-IOV?

Antes de entregares a Virtual Function (VF) à máquina virtual, tens de configurar o hipervisor através do comando ip link set vf com os parâmetros spoofchk on, trust off e fixar a VLAN ao nível do hardware (Hardware VLAN Tagging). Assim, o próprio ASIC da placa Intel E810 ou NVIDIA ConnectX descarta na origem qualquer pacote adulterado pela VM.

> INICIAR_PROJETO

Precisa de um website que transmita confiança, apareça na pesquisa e dê mais força à sua presença digital? Comece a conversa aqui.