DPDK (Data Plane Development Kit) es un conjunto de bibliotecas y drivers que permite a una aplicación leer y enviar paquetes directamente desde la tarjeta de red, sin pasar por la pila de red del kernel. En lugar de interrupciones y llamadas al sistema por paquete, un núcleo de CPU sondea la tarjeta en bucle, lo que permite procesar millones de paquetes por segundo por núcleo. En este tutorial instalarás DPDK desde los repositorios de Ubuntu 24.04, prepararás huge pages e IOMMU, vincularás una tarjeta de red al driver vfio-pci, la probarás con dpdk-testpmd y compilarás una aplicación mínima.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, preferiblemente un servidor dedicado, y un usuario no root con privilegios sudo.
  • Una tarjeta de red dedicada a DPDK, distinta de la que usas para SSH. Cuando vinculas un puerto a DPDK desaparece del sistema operativo: si es el único, perderás la conexión con el servidor.
  • Una NIC soportada por DPDK. La lista está en la documentación de drivers de DPDK; Intel (ixgbe, i40e, ice), Mellanox/NVIDIA (mlx5) y Broadcom (bnxt) son las más habituales.
  • Al menos 4 núcleos de CPU y 4 GB de RAM libres.
  • Acceso a la consola del servidor (IPMI/KVM) por si un cambio de red o de arranque te deja sin SSH.

Paso 1: Comprobar el hardware

Lista las tarjetas de red con su dirección PCI y el identificador de fabricante:

lspci -nn | grep -i ethernet
03:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ [8086:1572] (rev 02)
03:00.1 Ethernet controller [0200]: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ [8086:1572] (rev 02)

Identifica qué interfaz del sistema corresponde a cada dirección PCI y cuál tiene la IP por la que te conectas:

ls -l /sys/class/net/ | grep pci
ip -br addr

En el resto de la guía se usa el puerto 0000:03:00.1 (interfaz enp3s0f1), que no tiene IP ni se usa para SSH. Sustitúyelo por el tuyo.

Paso 2: Instalar DPDK

Ubuntu 24.04 incluye DPDK 23.11 LTS en sus repositorios. Instala las herramientas, las bibliotecas de desarrollo y lo necesario para compilar:

sudo apt update
sudo apt install dpdk libdpdk-dev build-essential pkg-config

Comprueba la versión instalada:

pkg-config --modversion libdpdk
23.11.1

El paquete dpdk instala en /usr/bin las utilidades que usarás a continuación: dpdk-devbind.py, dpdk-hugepages.py y dpdk-testpmd.

Paso 3: Reservar huge pages

DPDK coloca los buffers de paquetes en huge pages para evitar fallos de TLB y garantizar memoria física contigua. Reserva 2 GB en páginas de 2 MB con la utilidad de DPDK:

sudo dpdk-hugepages.py --setup 2G

Comprueba la reserva:

dpdk-hugepages.py --show
Node Pages Size Total
0    1024  2Mb  2Gb

Hugepages mounted on /dev/hugepages

Ubuntu ya monta hugetlbfs en /dev/hugepages al arrancar, pero la reserva de páginas se pierde con cada reinicio. Para hacerla permanente, crea un archivo de sysctl:

sudo nano /etc/sysctl.d/60-dpdk-hugepages.conf

Añade esta línea:

vm.nr_hugepages = 1024

En servidores con varios sockets, cada nodo NUMA necesita páginas propias para la NIC que tiene conectada. dpdk-hugepages.py --show muestra el reparto por nodo.

Paso 4: Activar la IOMMU

El driver vfio-pci usa la IOMMU para que la tarjeta solo pueda escribir en la memoria asignada a la aplicación DPDK. Es el driver recomendado porque no necesita desactivar protecciones del kernel.

Comprueba si la IOMMU ya está activa:

ls /sys/kernel/iommu_groups/ | wc -l

Si el resultado es 0, activa la IOMMU en los parámetros de arranque. Asegúrate también de que VT-d (Intel) o AMD-Vi/IOMMU (AMD) están habilitados en la BIOS.

sudo nano /etc/default/grub

En un procesador Intel, añade estos parámetros a GRUB_CMDLINE_LINUX_DEFAULT, conservando los que ya hubiera:

GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt"

En AMD la IOMMU se activa por defecto si está habilitada en la BIOS, así que basta con iommu=pt. Este parámetro (passthrough) evita traducir las direcciones de los dispositivos que sigue gestionando el kernel, para que no pierdan rendimiento.

Aplica el cambio y reinicia:

sudo update-grub
sudo reboot

Tras el reinicio, el número de grupos IOMMU debe ser mayor que cero:

ls /sys/kernel/iommu_groups/ | wc -l
58

Paso 5: Cargar el módulo vfio-pci

Carga el módulo y configúralo para que se cargue en cada arranque:

sudo modprobe vfio-pci
echo vfio-pci | sudo tee /etc/modules-load.d/vfio-pci.conf

Verifica que está cargado:

lsmod | grep vfio_pci
vfio_pci               16384  0
vfio_pci_core          94208  1 vfio_pci

Paso 6: Vincular la tarjeta de red a vfio-pci

Consulta el estado de las tarjetas de red desde el punto de vista de DPDK:

dpdk-devbind.py --status-dev net
Network devices using kernel driver
===================================
0000:03:00.0 'Ethernet Controller X710 for 10GbE SFP+ 1572' if=enp3s0f0 drv=i40e unused=vfio-pci *Active*
0000:03:00.1 'Ethernet Controller X710 for 10GbE SFP+ 1572' if=enp3s0f1 drv=i40e unused=vfio-pci

*Active* marca las interfaces con rutas o IP configuradas; nunca vincules esas. Apaga la interfaz que vas a usar y vincúlala a vfio-pci:

sudo ip link set enp3s0f1 down
sudo dpdk-devbind.py --bind=vfio-pci 0000:03:00.1

Vuelve a consultar el estado:

dpdk-devbind.py --status-dev net
Network devices using DPDK-compatible driver
============================================
0000:03:00.1 'Ethernet Controller X710 for 10GbE SFP+ 1572' drv=vfio-pci unused=i40e

Network devices using kernel driver
===================================
0000:03:00.0 'Ethernet Controller X710 for 10GbE SFP+ 1572' if=enp3s0f0 drv=i40e unused=vfio-pci *Active*

La interfaz enp3s0f1 ya no aparece en ip link: ahora la controla DPDK.

La vinculación se pierde al reiniciar. Para hacerla permanente, instala driverctl, que guarda un override del driver para esa dirección PCI:

sudo apt install driverctl
sudo driverctl set-override 0000:03:00.1 vfio-pci

Comprueba que el override está registrado:

driverctl list-overrides
0000:03:00.1 vfio-pci

Paso 7: Probar el puerto con dpdk-testpmd

dpdk-testpmd es la aplicación de pruebas de DPDK: inicializa los puertos, reenvía o recibe tráfico y muestra estadísticas. Lánzala en modo interactivo usando los núcleos 2 y 3 y solo el puerto vinculado:

sudo dpdk-testpmd -l 2-3 -a 0000:03:00.1 -- -i --port-topology=loop

Los argumentos antes de -- son del entorno de DPDK (EAL): -l 2-3 indica los núcleos (el primero se usa como núcleo principal y el resto para reenviar paquetes) y -a limita DPDK al puerto indicado. Los que van después son de testpmd: -i abre el modo interactivo y --port-topology=loop hace que un único puerto reenvíe lo que recibe por él mismo.

Si todo está bien, verás la inicialización y el prompt de testpmd:

EAL: Detected CPU lcores: 16
EAL: Detected NUMA nodes: 1
EAL: Selected IOVA mode 'VA'
EAL: VFIO support initialized
EAL: Using IOMMU type 1 (Type 1)
Configuring Port 0 (socket 0)
Port 0: 3C:FD:FE:XX:XX:XX
Checking link statuses...
Done
testpmd>

Consulta la información del puerto, incluido el estado del enlace:

testpmd> show port info 0

Pon el puerto en modo de solo recepción, arranca y revisa las estadísticas mientras llega tráfico al puerto (desde otra máquina o un generador de tráfico):

testpmd> set fwd rxonly
testpmd> start
testpmd> show port stats 0
  ######################## NIC statistics for port 0  ########################
  RX-packets: 18342751   RX-missed: 0          RX-bytes:  1100565060
  RX-errors: 0
  RX-nombuf:  0
  TX-packets: 0          TX-errors: 0          TX-bytes:  0

  Throughput (since last show)
  Rx-pps:     14880952          Rx-bps:   7142857000
  Tx-pps:            0          Tx-bps:            0
  ############################################################################

RX-missed cuenta los paquetes que la tarjeta descartó porque la aplicación no los recogió a tiempo; si crece, necesitas más núcleos o colas. Para reenviar el tráfico de vuelta usa set fwd io o set fwd macswap. Detén la prueba y sal:

testpmd> stop
testpmd> quit

Paso 8: Compilar una aplicación DPDK mínima

Las aplicaciones DPDK se compilan contra libdpdk usando pkg-config, que aporta las opciones de compilación y enlazado correctas. Crea un directorio de trabajo y un programa que inicialice el entorno y cuente los puertos disponibles:

mkdir -p ~/dpdk-hola
nano ~/dpdk-hola/main.c
#include <stdio.h>
#include <stdlib.h>
#include <rte_eal.h>
#include <rte_debug.h>
#include <rte_ethdev.h>

int main(int argc, char **argv)
{
    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "No se pudo inicializar el EAL\n");

    printf("Puertos DPDK disponibles: %u\n", rte_eth_dev_count_avail());

    rte_eal_cleanup();
    return 0;
}

Compílalo:

cd ~/dpdk-hola
gcc -O2 main.c -o hola $(pkg-config --cflags --libs libdpdk)

Ejecútalo con los mismos argumentos de EAL que usaste con testpmd:

sudo ./hola -l 2 -a 0000:03:00.1
EAL: Detected CPU lcores: 16
EAL: Detected NUMA nodes: 1
EAL: VFIO support initialized
Puertos DPDK disponibles: 1

Para un bucle completo de recepción y envío, el punto de partida recomendado es el ejemplo skeleton (basicfwd.c) del código fuente de DPDK, disponible en examples/skeleton del repositorio oficial. Usa la rama o etiqueta de la misma versión que muestra pkg-config --modversion libdpdk y compílalo con make desde su directorio.

Paso 9: Devolver la tarjeta al kernel

Cuando termines las pruebas, puedes devolver la tarjeta a su driver original (el que aparecía como unused= en el paso 6). Si usaste driverctl, elimina primero el override:

sudo driverctl unset-override 0000:03:00.1

Si no lo usaste, vincúlala a mano:

sudo dpdk-devbind.py --bind=i40e 0000:03:00.1

Comprueba que la interfaz vuelve a aparecer en el sistema:

ip -br link show enp3s0f1

Solución de problemas

  • EAL: No free 2048 kB hugepages reported. No hay huge pages reservadas o están todas en uso por otro proceso DPDK. Repite el paso 3 y comprueba con dpdk-hugepages.py --show.
  • vfio-pci: probe of 0000:03:00.1 failed with error -22 o EAL: VFIO group is not viable. La IOMMU no está activa o la tarjeta comparte grupo IOMMU con otro dispositivo que sigue en uso por el kernel. Revisa el paso 4 y el grupo con ls /sys/bus/pci/devices/0000:03:00.1/iommu_group/devices/.
  • testpmd no encuentra ningún puerto. La dirección PCI de -a no coincide con la vinculada, o la tarjeta no está soportada por los drivers de DPDK de tu versión. Comprueba dpdk-devbind.py --status-dev net.
  • RX-missed crece. La aplicación no da abasto: añade núcleos con -l, usa varias colas (--rxq y --txq en testpmd) y fija los núcleos de DPDK en el mismo nodo NUMA que la tarjeta.
  • Has perdido el acceso SSH. Vinculaste la interfaz de gestión. Entra por la consola del servidor y devuélvela al kernel como en el paso 9.

Conclusión

Tienes DPDK 23.11 instalado en Ubuntu 24.04, con huge pages, IOMMU y una tarjeta vinculada a vfio-pci de forma permanente, has comprobado el puerto con dpdk-testpmd y has compilado una aplicación contra libdpdk. Como siguientes pasos, aísla los núcleos que usa DPDK del planificador del kernel para evitar interrupciones, estudia el ejemplo l2fwd del código fuente para un reenvío entre puertos completo y mide el rendimiento con un generador de tráfico como TRex o pktgen-dpdk.