NS3-虚拟网络与物理网络的交互-3Netmap和DPDK网络设备
目录
- 1. Netmap NetDevice
- 1.1 概述
- 1.2 设计
- 1.2.1 设计思路
- 1.2.2 初始化阶段
- 1.2.3 线程功能
- 1.2.4 读写方法实现
- 1.2.5 队列控制与流量管理
- 1.2.6 性能优化
- 2. DPDK NetDevice
- 2.1 模型描述
- 2.1.1 设计
- 1. 初始化
- 2. 数据包传输
- 3. 终止
- 2.2 DPDK 安装
- 1. 检查 NIC 支持性
- 2. 替代方案:虚拟机配置
- 3. 安装方式
- 方式一:Ubuntu 包安装
- 方式二:源码编译
- 4. 加载 DPDK 驱动
- 5. 配置大页内存
- 2.3 使用指南
- 1. 验证 DPDK 支持
- 2. 配置示例
- 3. 核心属性
- 4. 示例程序
- 2.5 限制与扩展方向
1. Netmap NetDevice
fd-net-device 模块提供了 NetmapNetDevice
类,该类派生自 FdNetDevice
,能够使用 netmap 文件描述符读写流量。此 netmap 文件描述符必须与主机中的真实以太网设备关联。NetmapNetDeviceHelper 类支持对 NetmapNetDevice 的配置。
1.1 概述
Netmap 是一种快速数据包处理功能,它绕过了 Host 网络堆栈并获得对网络设备的直接访问。 netmap 由 Luigi Rizzo [Rizzo2012] 开发,并维护为 GitHub 上的 https://github.com/luigirizzo/netmap 上的开源项目。
用于 ns-3 [Imputato2019] 由 Pasquale Imputato 在 2017-19 年开发。使用 NetmapNetDevice
需要 Host System 支持 NetMap(为了获得最佳性能,驱动程序 必须支持 NetMap,并且必须使用支持 NetMap 的设备驱动程序)。用户 可以预期使用 Netmap 的仿真比使用 FdNetDevice
和原始套接字(将 通过 Linux 网络内核)的仿真,将支持更高的数据包 。
1.2 设计
1.2.1 设计思路
- 继承与扩展:
- 基于
FdNetDevice
实现NetmapNetDevice
,利用文件描述符(FD)机制与真实设备交互。 - 需定制专用于 netmap 的操作:初始化(切换 NIC 至 netmap 模式)和 读写方法(通过 netmap API 协调数据包与环的交互)。
- 基于
1.2.2 初始化阶段
- 模式切换:
- 将网络设备切换至 netmap 模式,使 ns-3 可通过 netmap 环直接读写真实设备的收发数据。
- 线程启动:
- 读线程:独立运行,监视 netmap 接收环中的新数据包,触发接收事件。
- 同步线程(Sync Thread):专用于周期同步 netmap 环状态,支持流量控制与 BQL 通知。
1.2.3 线程功能
- 读线程:
- 从 netmap 接收环提取新数据包,传递至 ns-3 协议栈处理。
- 读取完成后,同步接收环以释放已处理数据包的槽位。
- 同步线程:
- 周期同步:通过
TXSYNC
ioctl 请求,将 netmap 发送环中的待发数据包传输至:- 原生模式:直接推送至 NIC 发送环。
- 通用模式:提交至已安装的 qdisc(队列规则)。
- 队列管理:
- 若发送环空间不足导致队列暂停,当空闲槽位超过阈值时,重启队列并唤醒 ns-3 qdisc。
- BQL 支持:向字节队列限制(BQL)库通知已传输至 NIC 的字节量。
- 周期同步:通过
1.2.4 读写方法实现
- 写方法:
- 将上层(ns-3 流量控制层)下发的数据包写入 netmap 发送环的空闲槽位。
- 空间检查:若发送环剩余空间不足,立即暂停队列,阻止 ns-3 继续下发数据包。
- 读方法:
- 由读线程调用,负责提取接收环数据包并触发协议栈处理。
1.2.5 队列控制与流量管理
- 队列暂停与重启:
- 暂停条件:发送环空间不足时主动暂停队列。
- 重启条件:同步线程检测到发送环空闲槽位恢复至阈值以上时,自动重启队列。
- BQL 集成:
- 写方法:通知 BQL 已写入发送环的字节量。
- 同步线程:通知 BQL 已从发送环移除并传输至 NIC 的字节量。
1.2.6 性能优化
- 减少系统调用:通过同步线程周期批量处理 netmap 环同步,避免频繁系统调用开销。
- 零拷贝机制:直接操作 netmap 环的槽位,减少数据包在内核与用户空间间的复制。
通过上述设计,NetmapNetDevice
实现了高效、低延迟的物理网络设备模拟,同时兼容 ns-3 流量控制与 Linux 内核特性(如 BQL)。
2. DPDK NetDevice
数据平面开发套件(DPDK) 是由 Linux 基金会托管的库,旨在加速数据包处理任务(官网链接)。
DpdkNetDevice
类实现了基于 DPDK 的网络设备,绕过内核直接使用 DPDK 的高速数据包处理能力。该类位于 src/fd-net-device
模块中,继承自 FdNetDevice
,并重写了 ns-3 与 DPDK 环境交互所需的函数。
2.1 模型描述
DpdkNetDevice
提供网络仿真能力,允许模拟节点与真实主机交互。其核心功能是通过 DPDK 的 环境抽象层(EAL) 实现高速数据包处理。EAL 隐藏设备细节,为应用提供与网卡(NIC)直接交互的接口,使 ns-3 可绕过内核直接收发数据包。
2.1.1 设计
DpdkNetDevice
作为 ns-3 与 DPDK 的桥梁,生命周期分为三个阶段:
1. 初始化
- 责任方:
DpdkNetDeviceHelper
模型。 - 步骤:
- 初始化 EAL。
- 分配内存池(mempool)。
- 获取并初始化网卡端口。
- 设置端口的接收(Rx)和发送(Tx)队列。
- 调用
LaunchCore
启动HandleRx
方法,批量读取数据包。
2. 数据包传输
- 数据格式转换:
- DPDK 使用
mbuf
结构体,ns-3 使用原始缓冲区。
- DPDK 使用
- 读操作:
HandleRx
从 NIC 的 Rx 环批量读取mbuf
,转换为 ns-3 缓冲区后传递至协议栈。
- 写操作:
- 将 ns-3 缓冲区转换为
mbuf
存入 Tx 缓冲区。 - 批量发送:当 Tx 缓冲区满时,将数据包传输至 NIC 的 Tx 环。
- 超时刷新:若 Tx 缓冲区未满,默认 2ms 后手动刷新残留
mbuf
。
- 将 ns-3 缓冲区转换为
3. 终止
- 停止 Rx 轮询。
- 释放分配的
mbuf
和内存池。 - 关闭网卡端口。
2.2 DPDK 安装
1. 检查 NIC 支持性
- 查看 DPDK 支持的设备列表。
2. 替代方案:虚拟机配置
- 环境:Oracle VM VirtualBox + Ubuntu。
- 网卡配置:
- 桥接模式(Bridged Adapter)。
- 适配器类型:支持 DPDK 的 NIC(如 Intel PRO/1000 MT Server)。
- 混杂模式:允许所有。
3. 安装方式
方式一:Ubuntu 包安装
apt-get install dpdk dpdk-dev libdpdk-dev dpdk-igb-uio-dkms
- 版本要求:Ubuntu 20.04(默认 DPDK v19.11 LTS)。
方式二:源码编译
- 下载源码:从 DPDK 下载页 获取 v19.11 LTS。
- 配置为共享库:编辑
config/common_base
,设置:CONFIG_RTE_BUILD_SHARED_LIB=y
- 编译安装:
make install T=x86_64-native-linuxapp-gcc DESTDIR=install
- 设置环境变量:
export RTE_SDK=/path/to/dpdk-source export RTE_TARGET=x86_64-native-linuxapp-gcc
4. 加载 DPDK 驱动
sudo modprobe uio_pci_generic uio vfio-pci
sudo modprobe igb_uio # Ubuntu 包安装
sudo insmod $RTE_SDK/$RTE_TARGET/kmod/igb_uio.ko # 源码编译
5. 配置大页内存
- 运行时分配:
echo 256 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
- 启动时分配:编辑
/etc/default/grub
,添加:hugepages=256
- 挂载大页文件系统:
sudo mkdir /mnt/huge sudo mount -t hugetlbfs nodev /mnt/huge
2.3 使用指南
1. 验证 DPDK 支持
运行 ./ns3 configure
,若输出包含 DPDK NetDevice : enabled
表示支持。
DPDK网络拓扑示例:
2. 配置示例
DpdkNetDeviceHelper* dpdk = new DpdkNetDeviceHelper();
dpdk->SetPmdLibrary("librte_pmd_e1000.so"); // 设置 PMD 驱动库
dpdk->SetDpdkDriver("igb_uio"); // 设置 DPDK 驱动类型
3. 核心属性
属性名 | 描述 | 默认值 | 适用场景 |
---|---|---|---|
TxTimeout | Tx 缓冲区刷新超时(微秒) | 2000 | 低流量场景可调低 |
MaxRxBurst | Rx 批量大小 | 64 | 高流量可增大 |
MaxTxBurst | Tx 批量大小 | 64 | 高流量可增大 |
MempoolCacheSize | 内存池缓存大小 | 256 | 高流量可增大 |
NbRxDesc | Rx 描述符数量 | 1024 | 高流量可增大 |
NbTxDesc | Tx 描述符数量 | 1024 | 高流量可增大 |
4. 示例程序
fd-emu-ping.cc
:通过 DPDK 发送 ICMP 流量,绕过内核。fd-emu-onoff.cc
:利用 DPDK 高速处理能力,测量 TCP/UDP 吞吐量。
2.5 限制与扩展方向
- 当前限制:
- 仅支持单 NIC 单 Rx/Tx 队列。
- 不支持巨型帧(Jumbo Frames)。
- 无流量控制或 qdisc 支持。
- 未来扩展:
- 多 NIC 与多队列支持。
- 添加卸载(Offloading)和调度功能。