NS3-虚拟网络与物理网络的交互-2 FdNetDevice文件描述符网络设备
2 FdNetDevice文件描述符网络设备
目录
- 1. 文件描述符网络设备(File Descriptor NetDevice)
- 1.1. 模型描述
- 1.1.1. 设计
- 1.1.2. 范围与限制
- 1.2. 使用指南
- 1.2.1. 辅助类 Helpers
- 1.2.1.1. EmuFdNetDeviceHelper
- 1.2.1.2. TapFdNetDeviceHelper
- 1.2.2. 属性(Attributes)
- 1.2.3. 输出(Output)
- 1.2.4. 示例(Examples)
1. 文件描述符网络设备(File Descriptor NetDevice)
src/fd-net-device
模块提供了 FdNetDevice
类,它能够通过用户提供的 文件描述符(file descriptor) 读写网络流量。该文件描述符可关联到以下对象:
- TAP设备
- 原始套接字(raw socket)
- 生成/消费流量的用户空间进程
用户可自由定义外部流量的生成方式及如何消费NS-3仿真流量。
通过辅助类(helper classes),可为仿真与外部流量的交互提供多种机制。目前提供两种特定辅助类:
EmuFdNetDeviceHelper
:将NS-3设备与主机物理设备关联。TapFdNetDeviceHelper
:将NS-3设备与主机的TAP设备文件描述符关联。
1.1. 模型描述
本模块的源代码位于 src/fd-net-device
目录。
FdNetDevice
是一种特殊的NS-3网络设备(NetDevice),它通过文件描述符读写流量。与纯仿真网络设备(通过模拟信道收发帧)不同,FdNetDevice
将帧导向仿真外部的文件描述符。该文件描述符可关联到以下对象:
- Linux TUN/TAP设备
- 套接字(socket)
- 用户空间进程
用户需自行提供文件描述符,其类型决定了所建模的设备类型。例如:
- 若文件描述符关联到主机无线网卡的原始套接字,则建模的是无线设备。
从设备的逻辑“顶部”向下看,该设备对仿真节点表现为:
- 支持48位IEEE MAC地址
- 可桥接、支持广播
- 使用IPv4 ARP或IPv6邻居发现协议
(这些属性可根据用例调整)
1.1.1. 设计
FdNetDevice
的实现基于 FdReader
类(来自NS-3的 src/core
模块)。FdReader
管理一个独立于NS-3主线程的 读取线程,用于从文件描述符读取流量。
- 设备启动:调用
StartDevice
方法时,初始化读取线程并启动。在此之前,必须通过SetFileDescriptor
将文件描述符关联到FdNetDevice
。 - 文件描述符创建与配置:通常由辅助类完成,用户无需手动调用
SetFileDescriptor
。
流量接收流程:
- 读取线程从文件描述符收到帧后,调用
ReceiveCallback
方法。 ReceiveCallback
将帧调度为NS-3仿真事件(使用ScheduleWithContext
避免线程安全问题)。- 若待接收帧数达到
RxQueueSize
限制,新帧将被静默丢弃。 - 仿真器调用
ForwardUp
方法处理帧:剥离二层头部(根据EncapsulationMode
属性),将IP数据包传递给上层协议栈。
流量发送流程:
- 仿真生成的流量通过
Send
方法发送。 SendFrom
方法添加二层头部,将帧写入文件描述符。
TAP设备特殊处理:
- 若TAP设备未设置
IFF_NO_PI
标志,帧可能包含额外的 PI头部。 - 当
EncapsulationMode
设为DIXPI
时,PI头部会被移除。
1.1.2. 范围与限制
- 流量控制:在仿真模式下,文件描述符接口 无流量控制。若物理设备缓冲不足,可能导致本地丢包。
- 接收队列限制:
RxQueueSize
限制待处理帧数,超限时新帧被丢弃。 - MTU设置:设备MTU默认以太网II标准值(1500字节)。辅助类应根据实际接口特性设置MTU,否则需用户手动配置。
- 封装模式支持:
DIX
:以太网II帧LLC
:802.2 LLC/SNAP帧DIXPI
:含TAP PI头部的以太网II帧- 不支持 IEEE 802.1q(VLAN)标签。
- 无线设备关联:需将设备MAC地址设为真实网卡MAC地址,否则驱动会丢弃目标MAC不匹配的流量。
平台依赖与性能:
- 辅助类依赖:使用
EmuFdNetDeviceHelper
或TapFdNetDeviceHelper
需启用线程、实时仿真模式及TUN/TAP支持(NS-3配置时可见):Threading Primitives : enabled Real Time Simulator : enabled Emulated Net Device : enabled Tap Bridge : enabled
- 性能限制:在1Gb以太网链路上,TCP吞吐量上限约60Mbps(受测试设备处理能力限制)。
1.2. 使用指南
基础用法:
FdNetDeviceHelper fd;
NetDeviceContainer devices = fd.Install(nodes); // 用户手动创建并设置文件描述符
...
device->SetFileDescriptor(fd);
典型配置:
- 启用实时仿真与校验和计算:
GlobalValue::Bind("SimulatorImplementationType", StringValue("ns3::RealtimeSimulatorImpl")); GlobalValue::Bind("ChecksumEnabled", BooleanValue(true));
与Linux主机交互:
- 使用
EmuFdNetDeviceHelper
或TapFdNetDeviceHelper
时,需通过 特权程序 创建文件描述符:CreateFileDescriptor
创建本地Unix套接字并fork。- 子进程以root权限运行,创建原始套接字并通过Unix套接字返回文件描述符(使用
SCM_RIGHTS
控制消息)。
- 启用
--enable-sudo
配置选项,确保“creator”程序具有所需权限。
注意事项:
- 避免以root权限运行整个仿真,仅需通过辅助程序执行高权限操作。
- 确保文件描述符与设备MTU匹配,避免分片问题。
1.2.1. 辅助类 Helpers
1.2.1.1. EmuFdNetDeviceHelper
EmuFdNetDeviceHelper
通过 原始套接字(raw socket) 关联底层物理设备,并将套接字描述符传递给 FdNetDevice
,使得 NS-3 仿真能够通过主机的物理网卡收发帧。该辅助类允许将仿真节点透明地集成到由真实节点组成的网络中。
网络拓扑示例:
+----------------------+ +-----------------------+
| 主机 1 | | 主机 2 |
+----------------------+ +-----------------------+
| NS-3 仿真环境 | | |
+----------------------+ | Linux 网络栈 |
| NS-3 节点 | | +----------------+ |
| +----------------+ | | | TCP | |
| | NS-3 TCP | | | +----------------+ |
| +----------------+ | | | IP | |
| | NS-3 IP | | | +----------------+ |
| +----------------+ | | | | |
| | FdNetDevice | | | + 以太网设备 + |
| | 10.1.1.1 | | | | | |
| +----------------+ | | +----------------+ |
| | 原始套接字 | | | | eth0 | |
|--+----------------+--| +--------+------+-------+
| | eth0 | | | |
+-------+------+-------+ | | 10.1.1.11 10.1.1.12 | | +----------------------------+
功能与特性:
- 取代旧版
EmuNetDevice
:NS-3.17 之前版本使用EmuNetDevice
,现由EmuFdNetDeviceHelper
统一整合至FdNetDevice
框架。 - MAC 地址欺骗:通过生成虚拟 MAC 地址(默认以 OUI
00:00:00
为前缀),隔离仿真流量与主机其他流量。 - 测试环境适用性:适用于需驱动真实硬件的场景,要求:
- 物理网卡启用 混杂模式。
- 禁用硬件分段与校验和卸载。
配置步骤:
- 设置设备名称:指定主机物理网卡(如
eth0
)。 - 安装设备:关联到仿真节点。
- 分配唯一 MAC 地址:避免与真实设备冲突。
EmuFdNetDeviceHelper emu;
emu.SetDeviceName(deviceName); // 设置物理设备名称
NetDeviceContainer devices = emu.Install(node);
Ptr<NetDevice> device = devices.Get(0);
device->SetAttribute("Address", Mac48AddressValue(Mac48Address::Allocate())); // 分配唯一MAC地址
注意事项:
- 物理设备需处于 混杂模式 且已启用。
- 若多仿真环境共用网络,需手动确保全局 MAC 地址唯一性。
- 大规模仿真建议通过 OUI 分配 MAC 地址。
1.2.1.2. TapFdNetDeviceHelper
TAP 设备 是 Linux 中的虚拟网络接口:
- 内核侧:视为普通
net_device
,可配置 IP 和路由。 - 用户侧:以文件描述符形式暴露,供
FdNetDevice
使用。
用户侧的FdNetDevice,网络拓扑示例:
+-------------------------------------+
| 主机 |
+-------------------------------------+
| NS-3 仿真环境 | |
+----------------------+ |
| NS-3 节点 | |
| +----------------+ | |
| | NS-3 TCP | | |
| +----------------+ | |
| | NS-3 IP | | |
| +----------------+ | |
| | FdNetDevice | | +------+ |
|--+----------------+--+ | eth0 | |
| | TAP | +------+ |
| +------+ | |
| 192.168.0.1 | |
+------------------------------|------+ | ------------(互联网)-----
内核侧的Tap设备,网络拓扑示例:
+--------+
| Linux | +----------+
| 主机 | | 影子节点 |
| ------ | | (ghost) |
| 应用层 | | -------- |
| ------ | | IP协议栈| +----------+
| 协议栈 | | ==========| | 节点 |
| ------ | | TAP桥接 | | -------- |
| TAP设备| <----- IPC ------> | (tap) | | IP协议栈|
+--------+ | -------- | | -------- | | NS-3网络 | | NS-3网络 | | 设备 | | 设备 | +----------+ +----------+ || || +---------------------------+ | NS-3 通信信道 | +---------------------------+
关键区别:
-
TapFdNetDeviceHelper
:- TAP设备直接连接主机网络栈,仿真流量通过主机路由转发至外部网络(如互联网)。
- 依赖主机网络配置(如IP转发、NAT等)。
-
TapBridge
:- 通过 进程间通信(IPC) 将TAP设备桥接到NS-3仿真中的 影子节点(ghost node)。
- 流量通过NS-3内部的 虚拟信道 传输,完全在仿真环境中处理。
- 不依赖主机网络功能,适合隔离测试。
应用场景:
- 若需仿真节点与主机应用(如真实Web服务器)交互,使用
TapFdNetDeviceHelper
。 - 若需完全控制链路层行为(如测试自定义协议),使用
TapBridge
。
配置示例:
TapFdNetDeviceHelper helper;
helper.SetDeviceName(deviceName); // 设置 TAP 设备名称
helper.SetModePi(modePi); // 是否启用 PI 头部
helper.SetTapIpv4Address(tapIp); // 设置 IPv4 地址
helper.SetTapIpv4Mask(tapMask); // 设置子网掩码
...
helper.Install(node); // 安装到节点
1.2.2. 属性(Attributes)
FdNetDevice
提供以下关键属性:
属性 | 描述 |
---|---|
Address | 设备的 MAC 地址(需唯一) |
Start /Stop | 设备线程的启动/停止时间(默认全程活跃) |
EncapsulationMode | 链路层封装格式(如 DIX 、LLC 、DIXPI ) |
RxQueueSize | 文件描述符读取线程的缓冲区大小(默认 1000 包) |
典型配置代码:
device->SetAttribute("Address", Mac48AddressValue(Mac48Address::Allocate()));
1.2.3. 输出(Output)
支持 ASCII 日志 和 PCAP 跟踪,启用方式类似其他 NS-3 网络设备:
EmuFdNetDeviceHelper emu;
NetDeviceContainer devices = emu.Install(node);
...
emu.EnablePcap("emu-ping", device, true); // 启用 PCAP 捕获
跟踪源(Trace Sources):
MaxTx
:NS-3 向设备发送新帧时触发。MaxTxDrop
:写入文件描述符失败时触发。MaxPromiscRx
:收到任何有效 MAC 帧时触发。MaxRx
:收到目标为本设备的有效 MAC 帧时触发。Sniffer
:非混杂模式抓包(类似tcpdump
)。PromiscSniffer
:混杂模式抓包。
1.2.4. 示例(Examples)
示例文件 | 功能描述 |
---|---|
dummy-network.cc | 通过 Unix 管道连接两个节点,测试 FdNetDevice 基础功能。 |
realtime-dummy-network.cc | 同上,但启用实时仿真器。 |
fd2fd-onoff.cc | 测量纯仿真环境下 FdNetDevice 的吞吐量(通过套接字对连接两个设备)。 |
fd-emu-onoff.cc | 使用 EmuFdNetDeviceHelper 关联真实网卡,测试 TCP 饱和吞吐量。 |
fd-emu-ping.cc | 通过 EmuFdNetDeviceHelper 发送 ICMP 流量(如 ping )。 |
fd-emu-udp-echo.cc | 通过 EmuFdNetDeviceHelper 发送 UDP 流量。 |
fd-tap-ping.cc | 通过 TapFdNetDeviceHelper 发送 ICMP 流量。 |
通过上述机制,FdNetDevice
能够灵活连接仿真环境与物理网络,支持混合仿真、真实流量测试等复杂场景。
原文参考NS3官方网站:https://www.nsnam.org/docs/models/html/fd-net-device.html