Configurando redes lossless: guia de PFC e ECN para NVMe-oF
Aprenda a configurar Priority Flow Control (PFC) e Explicit Congestion Notification (ECN) para garantir estabilidade e baixa latência em redes NVMe over Fabrics (RoCEv2).
O NVMe over Fabrics (NVMe-oF) transformou a maneira como acessamos armazenamento remoto, entregando latências quase idênticas às de um SSD local. No entanto, essa performance depende de um pilar fundamental: a rede. Diferente do tráfego TCP padrão, que tolera perdas e retransmissões, o protocolo RoCEv2 (RDMA over Converged Ethernet) exige uma rede "lossless" (sem perdas).
Configurar uma rede Ethernet para se comportar como uma rede Fibre Channel — garantindo entrega sem descarte de pacotes — requer a implementação precisa de dois mecanismos: PFC (Priority Flow Control) e ECN (Explicit Congestion Notification). Sem eles, um simples pico de tráfego pode colapsar a performance do seu array de armazenamento All-Flash.
Resumo em 30 segundos
- O Problema: O protocolo RoCEv2 não lida bem com perda de pacotes. Um único drop força uma retransmissão lenta, matando a latência do NVMe.
- A Solução: Combinar PFC (que pausa o tráfego na Camada 2 para evitar estouro de buffer) com ECN (que avisa sobre congestionamento na Camada 3 para reduzir a velocidade antes da pausa).
- O Segredo: A configuração deve ser espelhada: o que você define na placa de rede (NIC) do servidor deve bater exatamente com a configuração das portas e buffers do switch.
Por que "Lossless" é crítico para Storage?
Em redes de dados comuns, quando um buffer de switch enche, o switch descarta os pacotes excedentes. O TCP percebe a falta do pacote e o reenvia. Para acessar uma página web, isso é imperceptível. Para um cluster de armazenamento NVMe processando milhares de IOPS, isso é catastrófico.
O RDMA (Remote Direct Memory Access) busca contornar a CPU para gravar dados diretamente na memória. Se houver perda de pacote, o hardware precisa interromper o fluxo, aguardar um timeout e solicitar retransmissão. Isso cria o fenômeno de "Incast", onde a latência salta de microssegundos para milissegundos.
Figura: Comparativo de impacto: Perda de pacote no TCP vs. Pausa dramática no fluxo RDMA.
A Dupla Dinâmica: PFC e ECN
Para evitar descartes, transformamos a Ethernet em uma rede determinística usando duas ferramentas que trabalham em camadas diferentes.
Tabela Comparativa: PFC vs. ECN
| Característica | PFC (Priority Flow Control) | ECN (Explicit Congestion Notification) |
|---|---|---|
| Camada OSI | Camada 2 (Enlace/MAC) | Camada 3 (Rede/IP) |
| Mecanismo | "Força Bruta". Envia um frame de PAUSA para o vizinho. | "Sinalização". Marca o cabeçalho IP avisando congestionamento. |
| Ação | Interrompe todo o tráfego de uma prioridade específica. | O remetente reduz a taxa de transmissão suavemente. |
| Risco | Head-of-Line Blocking (pode travar a rede se mal configurado). | Se o buffer encher antes da reação, pacotes serão descartados. |
| Função no NVMe-oF | Rede de segurança final (evita o drop físico). | Mecanismo primário de controle (evita a pausa brusca). |
Pré-requisitos de Hardware e Topologia
Para seguir este guia, assumimos o seguinte cenário típico de Enterprise Storage:
NICs: Mellanox ConnectX-5, 6 ou superior (NVIDIA).
Switches: Switches Data Center (Arista, Cisco Nexus, Dell PowerSwitch, NVIDIA Spectrum) com suporte a DCB (Data Center Bridging).
OS: Linux (RHEL, Ubuntu ou Debian) com drivers OFED ou upstream recentes.
💡 Dica Pro: Não tente fazer isso em switches de acesso "campus" ou "borda". O switch precisa de buffers profundos e suporte real a QoS/DCB em hardware.
Passo 1: Mapeamento de Prioridades no Linux
O primeiro passo é garantir que o tráfego de armazenamento saia do servidor marcado corretamente. Usaremos o DSCP (Differentiated Services Code Point) na camada 3 e o CoS (Class of Service) na camada 2.
Por padrão, o tráfego RDMA costuma usar a prioridade 3 ou 5. Vamos padronizar na prioridade 3 para este exemplo.
Configurando a Interface com mlnx_qos
Se você usa placas Mellanox, a ferramenta mlnx_qos é a maneira mais direta de configurar os buffers da placa sem se perder no tc (Traffic Control) do Linux inicialmente.
Verifique a configuração atual:
mlnx_qos -i ens785f0
Agora, vamos configurar a prioridade 3 como "lossless" (sem perdas) e mapear o valor DSCP 26 (comum para storage) para essa prioridade.
mlnx_qos -i ens785f0 --pfc 0,0,0,1,0,0,0,0
# Define o modo de confiança para DSCP (a placa confia na marcação L3)
mlnx_qos -i ens785f0 --trust dscp
⚠️ Perigo: Se você ativar o PFC no host mas não no switch, o host enviará frames de pausa que o switch ignorará (ou vice-versa), resultando em descartes de pacotes silenciosos. A configuração DEVE ser simétrica.
Passo 2: Configurando ECN no Host
O ECN permite que o host marque os pacotes para que, se eles encontrarem congestionamento no caminho, os switches saibam que devem avisar o remetente em vez de descartar o pacote.
No diretório /sys/class/infiniband, você controla os parâmetros do driver RDMA.
# Habilitar ECN para a placa mlx5_0
echo 1 > /sys/class/infiniband/mlx5_0/ports/1/sys_image_guid/cc_params/cc_algorithm_ecn
(Nota: O caminho exato no sysfs pode variar dependendo da versão do driver e do kernel. Consulte a documentação da sua distro para persistência via sysctl ou regras udev.)
Figura: Anatomia do Pacote: Onde vivem as marcas de prioridade (PCP) e congestionamento (ECN/DSCP).
Passo 3: Configuração do Switch (Conceitual)
Como cada fabricante tem uma CLI diferente, focaremos na lógica universal que você deve aplicar. Você precisa criar uma classe de tráfego para RDMA e garantir que ela tenha largura de banda garantida e tratamento lossless.
A lógica segue este fluxo:
Classificar: Identificar pacotes com DSCP 26 ou CoS 3.
Enfileirar: Jogar esses pacotes numa fila específica (ex: Queue 3).
Proteger: Ativar "Pause" (PFC) nessa fila.
Sinalizar: Ativar marcação ECN se o buffer dessa fila passar de X% de uso.
Exemplo Genérico (Estilo Cisco/Arista):
# 1. Classificação
class-map type qos match-all RDMA_CLASS
match dscp 26
match cos 3
# 2. Política de QoS (Input)
policy-map type qos RDMA_POLICY
class RDMA_CLASS
set qos-group 3
# 3. Configuração de Enfileiramento (Queuing)
policy-map type queuing RDMA_QUEUING
class type queuing c-out-q3
bandwidth percent 50
random-detect minimum-threshold 150 kbytes maximum-threshold 3000 kbytes drop-probability 0 weight 0 ecn
# 4. Aplicação na Interface
interface Ethernet1/1
priority-flow-control mode on
service-policy type qos input RDMA_POLICY
service-policy type queuing input RDMA_QUEUING
Observe a linha random-detect ... ecn. Isso configura o switch para marcar o bit ECN quando o buffer encher, em vez de descartar o pacote (WRED).
Figura: Gerenciamento de Buffer: Limiares de ativação do ECN e do PFC dentro do switch.
Passo 4: Validando a Ausência de Packet Drops
Após configurar as duas pontas, é hora de gerar carga (usando fio ou ib_write_bw) e monitorar as interfaces.
Use o ethtool para ler os contadores estendidos da placa de rede. Você está procurando por duas coisas:
Rx/Tx Pause Frames: Devem existir, mas não em excesso. Isso confirma que o PFC está ativo.
Discards/Drops: Devem ser ZERO na prioridade configurada.
# Verificando contadores de prioridade
ethtool -S ens785f0 | grep -E "prio3|pause"
Saída esperada (exemplo):
rx_prio3_packets: 5042012
tx_prio3_packets: 4012301
rx_prio3_discards: 0 <-- CRÍTICO: Deve ser zero
rx_pause_ctrl_phy: 150 <-- Indica que o switch pediu pausa (PFC funcionando)
tx_pause_ctrl_phy: 20 <-- Indica que o host pediu pausa
Se rx_prio3_discards estiver subindo, sua configuração de buffer no switch está insuficiente ou o PFC não foi negociado corretamente.
Diagnóstico: A Tempestade de PFC (PFC Storm)
O maior risco de redes lossless é o Head-of-Line Blocking. Imagine que um servidor lento peça "Pausa" ao switch. O switch, ficando sem buffer, pede "Pausa" para todos os outros servidores que estão enviando dados. De repente, toda a rede trava por causa de um nó lento.
Para mitigar isso:
Watchdogs: Configure PFC Watchdogs nos switches. Se uma fila ficar pausada por muito tempo, o switch ignora o PFC e descarta o pacote para destravar a rede.
Segregação: Nunca misture tráfego LAN geral (navegação, SSH) na mesma prioridade do tráfego NVMe-oF. Mantenha o Storage na CoS 3 e o resto na CoS 0.
Figura: O pesadelo do Head-of-Line Blocking: Como um nó lento pode parar a rede inteira.
Monitoramento Contínuo
Configurar redes lossless para NVMe-oF não é uma tarefa de "configurar e esquecer". À medida que você adiciona mais arrays de armazenamento ou nós de computação, o perfil de tráfego muda.
Recomendo fortemente a implementação de monitoramento via Telemetria (streaming telemetry) nos switches, em vez de SNMP tradicional, para capturar micro-bursts que causam ativação de PFC. Se você notar que os contadores de PFC estão subindo drasticamente, é sinal de que sua rede está subdimensionada ou que o ECN não está sendo agressivo o suficiente para frear os emissores antes da saturação física.
Por que o NVMe-oF precisa de uma rede lossless?
O protocolo RoCEv2 (RDMA over Converged Ethernet) é sensível à perda de pacotes. Diferente do TCP, que retransmite nativamente, a perda no RDMA causa pausas severas e retransmissões custosas, destruindo a performance de latência do NVMe.Qual a diferença entre PFC e ECN?
O PFC (Priority Flow Control) atua na Camada 2, pausando o tráfego para evitar estouro de buffer (força bruta). O ECN (Explicit Congestion Notification) atua na Camada 3, marcando pacotes para avisar o remetente sobre congestionamento antes que o buffer encha, permitindo uma redução suave da velocidade.Posso usar apenas ECN sem PFC?
Em ambientes puramente RoCEv2, é recomendado usar ambos. O ECN é o mecanismo primário de controle de congestionamento, enquanto o PFC atua como uma rede de segurança final para evitar o descarte de pacotes se o ECN não for rápido o suficiente.
Silvio Zimmerman
Operador de Backup & DR
"Vivo sob o lema de que backup não existe, apenas restore bem-sucedido. Minha religião é a regra 3-2-1 e meu hobby é desconfiar da integridade dos seus dados."