$npx -y skills add mohitmishra786/low-level-dev-skills --skill dpdkDPDK skill for userspace packet I/O. Use when initializing EAL, configuring PMD drivers, using mbuf pools and rte_ring, setting up huge pages, RSS, or testpmd validation. Activates on queries about DPDK, EAL, rte_eth_rx_burst, hugepages, PMD, or testpmd.
| 1 | # DPDK |
| 2 | |
| 3 | ## Purpose |
| 4 | |
| 5 | Guide agents through DPDK (Data Plane Development Kit): EAL initialization, poll-mode driver (PMD) concepts, `rte_eth_rx_burst`/`tx_burst`, mbuf mempools, `rte_ring` queues, huge page setup, RSS configuration, testpmd validation, QEMU virtio testing, and pipeline vs run-to-completion models. |
| 6 | |
| 7 | ## When to Use |
| 8 | |
| 9 | - Building a userspace packet forwarder bypassing the kernel network stack |
| 10 | - Achieving line-rate on 10/25/100 GbE NICs |
| 11 | - Prototyping NFV/vSwitch data plane components |
| 12 | - Testing NIC configuration with testpmd before custom code |
| 13 | - Comparing DPDK throughput with kernel networking or AF_XDP |
| 14 | - Running DPDK in VMs with virtio for development |
| 15 | |
| 16 | ## Workflow |
| 17 | |
| 18 | ### 1. Huge pages setup |
| 19 | |
| 20 | ```bash |
| 21 | # 2MB hugepages (common) |
| 22 | echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages |
| 23 | |
| 24 | # 1GB hugepages (better TLB perf on large memory) |
| 25 | echo 4 | sudo tee /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages |
| 26 | |
| 27 | # Mount hugetlbfs |
| 28 | sudo mkdir -p /mnt/huge |
| 29 | sudo mount -t hugetlbfs nodev /mnt/huge |
| 30 | |
| 31 | # Verify |
| 32 | grep Huge /proc/meminfo |
| 33 | ``` |
| 34 | |
| 35 | DPDK EAL maps hugepages at startup — insufficient pages cause init failure. |
| 36 | |
| 37 | ### 2. EAL initialization |
| 38 | |
| 39 | ```c |
| 40 | #include <rte_eal.h> |
| 41 | #include <rte_ethdev.h> |
| 42 | |
| 43 | int main(int argc, char **argv) { |
| 44 | int ret = rte_eal_init(argc, argv); |
| 45 | if (ret < 0) |
| 46 | rte_exit(EXIT_FAILURE, "EAL init failed\n"); |
| 47 | // argc/argv adjusted — remaining args for app |
| 48 | return run_dataplane(argc - ret, argv + ret); |
| 49 | } |
| 50 | ``` |
| 51 | |
| 52 | ```bash |
| 53 | # Typical EAL args |
| 54 | ./dpdk_app -l 0-3 -n 4 --huge-dir=/mnt/huge -- -p 0x3 |
| 55 | |
| 56 | # Flags: |
| 57 | # -l 0-3 — cores for DPDK (lcore mask) |
| 58 | # -n 4 — memory channels |
| 59 | # --proc-type=primary |
| 60 | # --file-prefix=myapp — multi-instance |
| 61 | ``` |
| 62 | |
| 63 | ### 3. Port configuration and PMD |
| 64 | |
| 65 | ```c |
| 66 | #include <rte_ethdev.h> |
| 67 | |
| 68 | #define RX_RING_SIZE 1024 |
| 69 | #define TX_RING_SIZE 1024 |
| 70 | #define NUM_MBUFS 8191 |
| 71 | #define MBUF_CACHE 250 |
| 72 | #define BURST_SIZE 32 |
| 73 | |
| 74 | static const struct rte_eth_conf port_conf = { |
| 75 | .rxmode = { .max_lro_pkt_size = RTE_ETHER_MAX_LEN }, |
| 76 | }; |
| 77 | |
| 78 | struct rte_mempool *mbuf_pool; |
| 79 | |
| 80 | int port_init(uint16_t port) { |
| 81 | mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS, |
| 82 | MBUF_CACHE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); |
| 83 | |
| 84 | struct rte_eth_rxconf rxq_conf = dev_info.default_rxconf; |
| 85 | ret = rte_eth_rx_queue_setup(port, 0, RX_RING_SIZE, |
| 86 | rte_eth_dev_socket_id(port), &rxq_conf, mbuf_pool); |
| 87 | // ... tx queue setup ... |
| 88 | ret = rte_eth_dev_start(port); |
| 89 | rte_eth_promiscuous_enable(port); |
| 90 | return 0; |
| 91 | } |
| 92 | ``` |
| 93 | |
| 94 | ```bash |
| 95 | # List available PMDs |
| 96 | dpdk-devbind.py --status |
| 97 | |
| 98 | # Bind NIC to vfio-pci (required for physical NICs) |
| 99 | sudo modprobe vfio-pci |
| 100 | sudo dpdk-devbind.py --bind=vfio-pci 0000:03:00.0 |
| 101 | ``` |
| 102 | |
| 103 | ### 4. RX/TX burst loop |
| 104 | |
| 105 | ```c |
| 106 | static inline void lcore_main(void) { |
| 107 | const uint16_t port = 0; |
| 108 | struct rte_mbuf *bufs[BURST_SIZE]; |
| 109 | |
| 110 | while (1) { |
| 111 | uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); |
| 112 | if (nb_rx == 0) |
| 113 | continue; |
| 114 | |
| 115 | uint16_t nb_tx = rte_eth_tx_burst(port, 0, bufs, nb_rx); |
| 116 | // Free unsent mbufs |
| 117 | if (nb_tx < nb_rx) { |
| 118 | for (uint16_t i = nb_tx; i < nb_rx; i++) |
| 119 | rte_pktmbuf_free(bufs[i]); |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | ``` |
| 124 | |
| 125 | Poll-mode: no interrupts — cores spin for packets. Assign one core per queue for scaling. |
| 126 | |
| 127 | ### 5. rte_ring for inter-core queues |
| 128 | |
| 129 | ```c |
| 130 | #include <rte_ring.h> |
| 131 | |
| 132 | struct rte_ring *ring = rte_ring_create("RX_RING", 1024, |
| 133 | rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); |
| 134 | |
| 135 | // Producer (RX core) |
| 136 | rte_ring_enqueue_bulk(ring, (void **)bufs, nb_rx, NULL); |
| 137 | |
| 138 | // Consumer (worker core) |
| 139 | uint16_t nb_deq = rte_ring_dequeue_bulk(ring, (void **)bufs, BURST_SIZE, NULL); |
| 140 | ``` |
| 141 | |
| 142 | ### 6. RSS configuration |
| 143 | |
| 144 | ```c |
| 145 | static const struct rte_eth_rss_conf rss_conf = { |
| 146 | .rss_key = NULL, |
| 147 | .rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP, |
| 148 | }; |
| 149 | |
| 150 | struct rte_eth_conf port_conf = { |
| 151 | .rxmode = { .mq_mode = RTE_ETH_MQ_RX_RSS }, |
| 152 | .rx_adv_conf = { .rss_conf = rss_conf }, |
| 153 | }; |
| 154 | ``` |
| 155 | |
| 156 | Distributes flows across RX queues — map queues to cores for parallelism. |
| 157 | |
| 158 | ### 7. testpmd validation |
| 159 | |
| 160 | ```bash |
| 161 | # Build testpmd |
| 162 | cd dpdk/build |
| 163 | ninja -C build dpdk-testpmd |
| 164 | |
| 165 | # Forward mode test |
| 166 | sudo ./build/app/dpdk-testpmd -l 0-3 -n 4 -- -i --forward-mode=io |
| 167 | |
| 168 | testpmd> show port stats all |
| 169 | testpmd> start tx_first |
| 170 | testpmd> show port stats all |
| 171 | ``` |
| 172 | |
| 173 | Forward modes: `io`, `mac`, `macswap`, `flowgen` for throughput testing. |
| 174 | |
| 175 | ### 8. QEMU virtio testing |
| 176 | |
| 177 | ```bash |
| 178 | qemu-system-x86_64 \ |
| 179 | -cpu host -m 4096 -smp 4 \ |
| 180 | -netdev user,id=net0 \ |
| 181 | -device virtio-net-pci,netdev=net0,mq=on,vectors=10 \ |
| 182 | -object memory-backend-file,id=mem,size=2G,mem-path=/dev/hugepages,share=on \ |
| 183 | -numa node,memdev=mem \ |
| 184 | ... |
| 185 | ``` |
| 186 | |
| 187 | Inside VM: bind virtio PCI to `vfio-pci` or |