1. 安装
1
2
3
4
5
6
* (HEAD detached at v23.11.5)
cd ~/xx/dpdk_brige/dpdk
rm -rf build
meson setup build -Dmax_numa_nodes=1
ninja -C build
2. 环境基础配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
xm@xm:~/xx/dpdk_brige/dpdk$ cat /proc/meminfo |grep Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
xm@xm:~/xx/dpdk_brige/dpdk$ free -g
total used free shared buff/cache available
Mem: 7 0 6 0 0 6
Swap: 1 0 1
xm@xm:~/xx/dpdk_brige/dpdk$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 36 bits physical, 48 bits virtual
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 167
Model name: 11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz
Stepping: 1
CPU MHz: 2496.000
BogoMIPS: 4992.00
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 192 KiB
L1i cache: 128 KiB
L2 cache: 2 MiB
L3 cache: 16 MiB
NUMA node0 CPU(s): 0-3
Vulnerability Gather data sampling: Unknown: Dependent on hypervisor status
Vulnerability Itlb multihit: KVM: Mitigation: VMX unsupported
Vulnerability L1tf: Mitigation; PTE Inversion
Vulnerability Mds: Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
Vulnerability Meltdown: Mitigation; PTI
Vulnerability Mmio stale data: Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
Vulnerability Reg file data sampling: Not affected
Vulnerability Retbleed: Vulnerable
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass: Vulnerable
Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2: Mitigation; Retpolines; STIBP disabled; RSB filling; PBRSB-eIBRS Not affected; BHI Retpoline
Vulnerability Srbds: Not affected
Vulnerability Tsx async abort: Not affected
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc nopl xtopology nonstop_tsc cpuid tsc_kn
own_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti
fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid avx512f avx512dq rdseed adx smap clflushopt avx512cd avx512bw avx512vl xsaveopt xsavec dtherm arat pln pts
3. numa 问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
xm@xm:~/xx/dpdk_brige/dpdk$ numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 7930 MB
node 0 free: 6466 MB
node distances:
node 0
0: 10
xm@xm:~/xx/dpdk_brige/dpdk$
xm@xm:~/xx/dpdk_brige/dpdk$
xm@xm:~/xx/dpdk_brige/dpdk$ free -g
total used free shared buff/cache available
Mem: 7 0 6 0 0 6
Swap: 1 0 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
===============================
单 NUMA 节点示意图
===============================
NUMA Node 0
+-------------------------------+
| CPU Cores: 0 1 2 3 |
| |
| +-----------------------+ |
| | Hugepages (DMA mem) | | <- DPDK 分配的内存,网卡 DMA 直接访问
| +-----------------------+ |
| |
| Network Card (ens4) | <- PCIe 网卡属于本 NUMA 节点
+-------------------------------+
数据流示意:
CPU 0/1/2/3 <---> Hugepages 内存 <---> 网卡 DMA
特点:
- CPU 访问本地 NUMA 内存延迟低
- 网卡 DMA buffer 在本地 NUMA 节点,吞吐最高
- PMD 轮询线程固定绑定 CPU 核心
- RX/TX 队列绑定本地 CPU + 内存 + 网卡
===============================
多 NUMA 节点示意图
===============================
NUMA Node 0 NUMA Node 1
+---------------------+ +---------------------+
| CPU Cores: 0 1 | | CPU Cores: 2 3 |
| Hugepages mem | | Hugepages mem |
| Network Card ens4 | | Network Card ens5 |
+---------------------+ +---------------------+
最佳访问:
CPU(node0) -> Mem(node0) -> NIC(node0) // 快
CPU(node1) -> Mem(node1) -> NIC(node1) // 快
跨节点访问(CPU(node0) -> Mem(node1) 或 NIC(node1))会增加延迟
DPDK 做的事情:
- 检测 CPU 核心和 NUMA 节点
- 检测网卡所在 NUMA 节点
- 为每个 NUMA 节点分配 Hugepages 内存
- 将 PMD 线程绑定到 CPU
- 将 RX/TX 队列和内存绑定到网卡所在 NUMA 节点
4. 大页内存问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
* =====================================================
* DPDK 大页内存(Hugepages)说明
* =====================================================
*
* 1. 定义
* --------
* - Linux 默认页大小:4 KB
* - Hugepages(大页):通常 2 MB 或更大
* - 优势:
* - 减少页表条目数量
* - 降低 CPU TLB(Translation Lookaside Buffer)缺失
* - 提升内存访问效率
*
* 2. 为什么 DPDK 需要 Hugepages
* --------------------------------
* - 高性能数据平面需要零拷贝(zero-copy)DMA:
* - 网卡直接访问内存(RX/TX buffer)
* - 需要物理连续的内存页,普通 4 KB 页容易碎片化
*
* - 减少内存管理开销:
* - 高速轮询模式的 PMD 线程需要频繁访问大量 buffer
* - 使用大页减少页表查找次数和 TLB Miss
*
* - 配合 NUMA 优化:
* - 每个 NUMA 节点分配 Hugepages
* - 线程、网卡、内存本地化,避免跨节点访问
*
* 3. 配置 Hugepages 示例(单 NUMA 节点)
* ----------------------------------------
* // 查看当前 Hugepages 配置
* cat /proc/meminfo | grep Huge
*
* // 设置 2 GB 内存为 Hugepages(假设页大小 2 MB)
* sudo sysctl -w vm.nr_hugepages=1024
*
* // 为 NUMA 节点单独设置
* echo 1024 | sudo tee /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
*
* 4. DPDK 使用 Hugepages
* ----------------------
* sudo build/app/dpdk-testpmd -l 0-3 -n 1 -- --socket-mem 1024
* - -l 0-3 : 使用 CPU 核心 0-3
* - -n 1 : 内存通道数
* - --socket-mem : 每个 NUMA 节点分配的 Hugepages 内存大小(MB)
*
* DPDK 会:
* - 检测 CPU 核心和 NUMA 节点
* - 检测网卡 NUMA 节点
* - 分配 Hugepages 内存,作为 DMA buffer
* - 将 PMD 线程绑定到 CPU,队列绑定到网卡所在 NUMA 节点
*
* 5. 总结
* --------
* - Hugepages 提供物理连续内存,降低页表/TLB开销
* - 必须与 NUMA 配合保证线程、内存、网卡本地化
* - DPDK 程序初始化失败(Cannot get hugepage information)通常意味着
* Hugepages 未分配或权限不足
*
*/
5. igb_uio 问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
* igb_uio 与 DPDK 的关系
*
* 1️⃣ igb_uio 不是网卡驱动
* ----------------------------------------------------
* - 厂商内核驱动 (i40e/igb/ixgbe):
* * 负责网卡收发
* * 依赖内核协议栈 (TCP/IP)
*
* - DPDK 用户态驱动 (PMD,例如 net_i40e/net_igb):
* * 负责网卡收发
* * 完全在用户态处理,不走内核协议栈
*
* - igb_uio:
* * 不是网卡驱动
* * 只是“搬运工”,负责把 PCI 资源交给用户态
*
*
* 2️⃣ igb_uio 的作用
* ----------------------------------------------------
* - 解除网卡和内核驱动绑定 (如 i40e/igb)
* - 把 PCI 设备绑定到 igb_uio
* - 通过 /dev/uioX 暴露设备资源给用户态:
* * BAR 寄存器
* * MSI-X 中断
* * DMA 地址空间
* - 用户态 PMD 可以直接访问网卡寄存器和 DMA 内存
*
*
* 3️⃣ 为什么 igb_uio 能“适配所有网卡”?
* ----------------------------------------------------
* - 网卡硬件的寄存器/DMA 访问方式是由 PCIe 总线暴露的
* - 这些操作和驱动框架分离,属于通用行为
* - 因此:
* * igb_uio 只做通用 PCI → 用户态映射
* * 不关心网卡型号
* * 具体逻辑交给 DPDK PMD 实现
*
* 举例:
* - i40e 网卡 → DPDK 使用 net_i40e PMD
* - igb 网卡 → DPDK 使用 net_igb PMD
* - virtio 网卡 → DPDK 使用 net_virtio PMD
*
*
* 4️⃣ 总结
* ----------------------------------------------------
* - igb_uio = 通用“网关”,负责 PCI → 用户态映射
* - DPDK PMD = 针对具体网卡型号的“驱动大脑”
* - 内核驱动 (i40e/igb/ixgbe) 与 DPDK PMD 二选一:
* * 内核驱动 → 内核协议栈
* * igb_uio + PMD → 用户态高速收发
*/
6. why is dpdk?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* ============================================================
* DPDK 简要说明(C 注释版)
* ============================================================
*
* 1️⃣ DPDK 是什么?
* ------------------------------------------------------------
* - DPDK (Data Plane Development Kit)
* - 一套用户态高速网络包处理框架
* - 核心思路:绕过内核协议栈,直接用用户态驱动(PMD)收发包
*
* 传统方式(Linux 内核网络栈):
* [ 网卡 ] → [ 内核驱动 ] → [ 内核协议栈 TCP/IP ] → [ 用户应用 ]
* -> 每收一个包,要经过内核和系统调用,性能开销大
*
* DPDK 方式:
* [ 网卡 ] → [ DPDK 驱动 PMD + 用户态应用 ]
* -> 内核完全绕开,CPU 轮询方式处理,效率更高,可达到数千万 PPS
*
* 2️⃣ 为什么要用 DPDK?
* ------------------------------------------------------------
* - 极致性能:小包转发可做到线速 (10G/25G/100G)
* - 可控性强:开发者自己掌握内存管理、调度策略
* - 广泛应用:
* - 防火墙 / WAF / IDS / IPS
* - 负载均衡 / 代理(LVS、HAProxy DPDK 版)
* - 5G Core、vRAN
* - 金融交易(超低延迟收发包)
*
* 3️⃣ 业界一般如何使用 DPDK?
* ------------------------------------------------------------
* 🅰️ 直接写 DPDK 应用(硬核派)
* - 使用 DPDK API 编程:
* - 收包: rte_eth_rx_burst
* - 发包: rte_eth_tx_burst
* - 适合做定制化网络功能(DPI、防火墙、SD-WAN)
* - 性能极致,但开发成本高
*
* 🅱️ 基于 DPDK 的框架(主流派)
* - 封装了 DPDK,开发更方便:
* - OVS-DPDK → Open vSwitch DPDK 加速版
* - VPP (FD.io) → 用户态转发平面
* - Snort/Suricata with DPDK → 入侵检测系统
* - NGINX with DPDK patches → 高速代理
* - 企业常见做法:在 OVS-DPDK 或 VPP 上跑业务,不裸写 DPDK
*
* 🅾️ 用于网络性能测试(学习/验证)
* - DPDK 自带 testpmd:验证环境是否可用、网卡性能
* - DPDK 自带 pktgen-dpdk:生成流量
* - 适合学习和环境验证
*
* 4️⃣ 小结
* ------------------------------------------------------------
* - DPDK = 用户态收发包框架,绕过内核,加速网络处理
* - 业界用法:
* - 硬核型:自己写 DPDK 应用(安全厂商、金融)
* - 框架型:用 OVS-DPDK / VPP(云厂商、运营商)
* - 工具型:用 testpmd / pktgen(研发、实验室)
*
* =============================================================
* End of summary
* =============================================================
*/
7. 再聊 DPDK 应用场景
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
* ===========================================================
* DPDK 简介与使用示例(C 注释版)
* ===========================================================
*
* 1️⃣ DPDK 本质
*
* DPDK = 框架 + 用户态库 + PMD 驱动
* - 高性能网络包处理的 C 库
* - C 程序通过 #include <rte_*.h> 引用头文件
* - 编译链接 DPDK 后即可直接调用 API
* - 核心思想:绕过内核网络栈,用户态直接操作网卡 DMA 内存
* CPU 轮询收发包,性能极高
*
* -----------------------------------------------------------
*
* 2️⃣ dpdk-testpmd 与自己写的 C 程序
*
* - dpdk-testpmd 本质上是一个 C 程序二进制
* - 调用的都是 DPDK 官方提供的 API:
* - 初始化 EAL
* - 配置端口和队列
* - 创建内存池
* - 收发包循环
* - 自己写的程序与 testpmd 同类,只是功能自定义
*
* -----------------------------------------------------------
*
* 3️⃣ DPDK C 程序伪码示例
*
* #include <rte_eal.h>
* #include <rte_ethdev.h>
* #include <rte_mbuf.h>
*
* int main(int argc, char **argv) {
* // 1. 初始化 EAL(DPDK 环境)
* rte_eal_init(argc, argv);
*
* // 2. 查询可用网卡数量
* uint16_t nb_ports = rte_eth_dev_count_avail();
*
* // 3. 创建 mbuf 内存池
* struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create(
* "MBUF_POOL", 8192, 256, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
*
* // 4. 配置端口 & 队列
* for (int port_id = 0; port_id < nb_ports; port_id++) {
* rte_eth_dev_configure(port_id, 1, 1, NULL);
* rte_eth_rx_queue_setup(port_id, 0, 1024, rte_eth_dev_socket_id(port_id), NULL, mbuf_pool);
* rte_eth_tx_queue_setup(port_id, 0, 1024, rte_eth_dev_socket_id(port_id), NULL);
* rte_eth_dev_start(port_id);
* }
*
* // 5. 收发包主循环
* while (1) {
* struct rte_mbuf *pkts[32];
* int nb_rx = rte_eth_rx_burst(0, 0, pkts, 32);
* if (nb_rx > 0) {
* rte_eth_tx_burst(0, 0, pkts, nb_rx);
* }
* }
*
* // 6. 停止端口
* for (int port_id = 0; port_id < nb_ports; port_id++) {
* rte_eth_dev_stop(port_id);
* rte_eth_dev_close(port_id);
* }
*
* return 0;
* }
*
* -----------------------------------------------------------
*
* 核心 API 快览
*
* 功能 | API | 说明
* ------------------------------------------------------------
* 初始化 DPDK | rte_eal_init() | 初始化 hugepages、NUMA、CPU 绑定
* 查询网卡 | rte_eth_dev_count_avail() | 可用网卡数量
* 创建内存池 | rte_pktmbuf_pool_create() | 分配 mbuf 内存用于收发包
* 配置端口 | rte_eth_dev_configure() | 配置 RX/TX 队列数量
* 配置 RX 队列 | rte_eth_rx_queue_setup() | 设置 RX 队列参数
* 配置 TX 队列 | rte_eth_tx_queue_setup() | 设置 TX 队列参数
* 启动端口 | rte_eth_dev_start() | 激活端口开始收发
* 收包 | rte_eth_rx_burst() | 批量收包
* 发包 | rte_eth_tx_burst() | 批量发包
* 停止端口 | rte_eth_dev_stop() | 停止收发
* 关闭端口 | rte_eth_dev_close() | 释放端口资源
*
* -----------------------------------------------------------
*
* 💡 总结
*
* - DPDK = 用户态高性能网络库
* - dpdk-testpmd = 官方示例程序,调用 API 做收发测试
* - 自己写 C 程序 = 同理,也调用 API,只是功能自定义
*/
8. DPDK 预备流程 & 启动流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* ================= DPDK 启动与 testpmd 流程注释 =================
*
* 1️⃣ 预备步骤:系统 & 驱动准备
*
* Hugepages(大页内存)分配
* - DPDK PMD 需要连续大块内存(DMA buffer)来放 mbuf
* - 示例:
* echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
* - 可按 NUMA 节点分配:
* echo 512 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
* echo 512 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
*
* 网卡绑定到用户态驱动
* - 内核驱动不能同时被 DPDK 使用
* - 使用 dpdk-devbind.py 绑定:
* sudo ./usertools/dpdk-devbind.py -b igb_uio 0000:00:05.0
* - 绑定完成后 PMD 驱动才能探测到网卡
*
* CPU & NUMA 核心规划(可选,但推荐)
* - 确定哪些核心用于轮询线程、哪些核心留给系统
* - 避免跨 NUMA 节点访问,提高 DMA 速度
*
*
* 2️⃣ DPDK 应用初始化(以 testpmd 为例)
*
* // 1. 初始化 EAL(Environment Abstraction Layer)
* rte_eal_init(argc, argv);
* // 作用:
* // - 解析命令行参数(CPU掩码、NUMA节点、Hugepage目录等)
* // - 初始化 Hugepages 映射
* // - 初始化用户态 PCI 访问
* // - 绑定 PMD 驱动到网卡
*
* // 2. 探测网卡
* uint16_t nb_ports = rte_eth_dev_count_avail();
* // DPDK PMD 驱动查看绑定的网卡,记录 NUMA 节点
*
* // 3. 创建 mbuf 内存池
* struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create(
* "MBUF_POOL", 8192, 256, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
* // - 分配大页内存
* // - 按 NUMA 节点分配
*
* // 4. 配置端口和队列
* for (port_id = 0; port_id < nb_ports; port_id++) {
* rte_eth_dev_configure(port_id, nb_rx_queues, nb_tx_queues, &conf);
* rte_eth_rx_queue_setup(port_id, ... , mbuf_pool);
* rte_eth_tx_queue_setup(port_id, ...);
* rte_eth_dev_start(port_id);
* }
*
* // 5. 主循环:轮询收发包
* while (!quit) {
* // 收包
* nb_rx = rte_eth_rx_burst(port_id, queue_id, pkts, BURST_SIZE);
* // 发包
* nb_tx = rte_eth_tx_burst(port_id, queue_id, pkts, nb_rx);
* }
*
* // 6. 停止端口
* for (port_id = 0; port_id < nb_ports; port_id++) {
* rte_eth_dev_stop(port_id);
* rte_eth_dev_close(port_id);
* }
*
*
* 3️⃣ 核心点说明
*
* 环节 | 作用 | 注意事项
* ----------------|-------------------------------|---------------------------
* Hugepages | 提供连续 DMA 内存 | 必须提前分配,否则 EAL 初始化报错
* 网口绑定 | 解除内核驱动,绑定 PMD | 没绑定,PMD 无法探测网卡
* PMD 驱动 | 用户态轮询网卡收发 | 网卡型号不同,PMD 不同(i40e/igb/virtio)
* NUMA | 优化 CPU-内存-网卡访问 | 多节点需绑定线程 & 队列到网卡所在 NUMA
* Mbuf 内存池 | 存放数据包 | 分配在本地 NUMA 节点 Hugepages
* 主循环 | 收发包 | 轮询方式,没有中断,CPU 100% 工作
*
*
* ✅ 总结:
* - 执行 dpdk-testpmd 前:
* 1. 分配 Hugepages
* 2. 绑定网卡到用户态驱动
* 3. 可选:确定 CPU & NUMA 配置
* - testpmd 初始化:
* 1. EAL 初始化(Hugepages + PCI + NUMA + PMD 驱动)
* 2. 网卡探测
* 3. 内存池创建
* 4. 队列配置 & 端口启动
* - 主循环:
* 收包 → 发包 → 循环
* 使用 mbuf 内存池里的大页,避免跨 NUMA 节点访问
*/
9. 再谈大页文件系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 文件系统挂载
xm@xm-virtual-machine:~/xx_dpdk/dpdk/build/app$ mount | grep huge
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,pagesize=2M)
// 应用使用大页内存举例
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 打开文件
int fd = open("/dev/hugepages/myhugepagefile", O_CREAT | O_RDWR, 0755);
if (fd < 0) { perror("open"); return 1; }
// 映射 2MB 内存
size_t size = 2 * 1024 * 1024;
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) { perror("mmap"); return 1; }
// 使用内存
sprintf((char*)addr, "Hello hugepage!\n");
printf("%s", (char*)addr);
// 解除映射
munmap(addr, size);
close(fd);
return 0;
}
10. testpmd 自测
1
2
3
4
5
6
7
sudo ./build/app/dpdk-testpmd -l 0-1 -n 4 \
--vdev=net_pcap0,iface=lo \
--vdev=net_pcap1,iface=lo \
--no-pci \
-- -i --forward-mode=io --port-topology=chained --auto-start