本节中的教程演示了基本的 TRex无状态用例。示例包括常见和中等高级的 TRex 概念。
在正常操作模式下,为了保持数据包的高速处理,TRex 忽略大部分 rx 流量,但计数/统计和处理延迟流除外。
模式:_
On:所有数据包都被转发到 rx 以由 Client 或 Capture 处理。
Off - 仅转发延迟数据包。在 v2.66 之前,非 TCP UDP 以软件模式转发到 rx,在 v2.66(包括)之后,仅在过滤模式下转发这些数据包以获得更大的灵活性。
Filter [bgp, no_tcp_udp, emu, transport, mdns, dhcp, all] - 在这种情况下,特定的数据包被转发到 rx。一个例子可以是 BIRD 的 BGP 数据包。它仅与软件模式有关,--software 使用过滤器模式,您将能够以高速率运行 TCP/UDP 流量,同时保持路由协议的功能。性能将与“关闭”一样好,唯一的惩罚来自需要在 rx 端处理所有数据包的软件模式。
过滤模式是v2.66版本新增的
下面说明了如何处理 rx 数据包。只有一部分被转发到 rx 处理模块,没有一部分被转发回 Python 客户端。

图1. 正常模式下的端口
在服务模式下,端口响应 ping 和 ARP 请求,并启用将数据包转发到 Python 控制平面以应用全双工协议(DCHP、IPv6 邻居等)。
下面说明了如何将数据包转发回 Python 客户端。
图 2. 服务模式下的端口
在编写用于仿真的 Python 插件(例如:IPV6 ND/DHCP)以准备设置时,服务模式可能很有用。然后您可以进入正常模式进行高速测试。
- trex>service --help
- usage: service [-h] [-p PORTS [PORTS ...] | -a] [--bgp] [--dhcp] [--mdns]
- [--emu] [--tran] [--no-tcp-udp] [--all] [--off]
-
- Configures port for service mode. In service mode ports will reply to ARP,
- PING and etc.
-
- optional arguments:
- -h, --help show this help message and exit
- -p PORTS [PORTS ...], --port PORTS [PORTS ...]
- A list of ports on which to apply the command
- -a Set this flag to apply the command on all available
- ports
-
- --bgp filter mode with bgp packets forward to rx
- --dhcp filter mode with dhcpv4/dhcpv6 packets forward to rx
- --mdns filter mode with mDNS packets forward to rx
- --emu filter mode for all emu services rx
- --tran filter mode with tcp/udp packets forward to rx
- (generated by emu)
- --no-tcp-udp filter mode with no_tcp_udp packets forward to rx
- --all Allow every filter possible
- --off Deactivates services on port(s)
-
- trex>service
-
- Enabling service mode on port(s) [0, 1]: [SUCCESS]
-
- trex(service)>service --off
-
- Disabling service mode on port(s) [0, 1]: [SUCCESS]
服务模式和普通模式切换示例:API
- client.set_service_mode(ports = [0, 1], enabled = True)
-
- client.set_service_mode(ports = [0, 1], enabled = False)
ARP/ICMP 响应
只有在服务模式下,端口才会回复 ICMP 回显请求和 ARP 请求。
在服务模式下,TRex 提供了几种方法来检查和操作 Rx 和 Tx 数据包。
数据包捕获是通过在服务器端分配一个更快的内存队列来实现的,该队列复制并存储数据包缓冲区。
每个队列都可以使用以下属性定义:
贮存
它应该捕获 Tx/Rx 上的哪些端口
应该是循环的还是固定
上述架构意味着我们可以在短时间内高速捕获。
例如,可以将 100 万个数据包的队列分配为循环队列,并以几个 MPPS 的速率处于活动状态。这有效地提供了具有给定过滤器的服务器看到的最后 100 万个数据包的样本。
BPF 过滤
在演示如何使用数据包捕获之前,回顾一下过滤是如何完成的会很有帮助。
每个数据包捕获都分配了一个过滤器(默认情况下,一个匹配任何数据包的过滤器)。可以分配任何遵循Berekely 包过滤器 (BPF)语法规则的过滤器。
BPF 过滤器被 Linux 内核、TCP 转储等广泛使用。基本上任何tcpdump过滤教程都可以用来为 TRex 定义一个过滤器。
一些使用BPF的简单示例:
所有ARP或ICMP数据包:
'arp or icmp'
所有目标端口为 53 的 UDP数据包:
'udp and dst 53'
所有数据包VLAN标记为200和TCP SYN:
'vlan 200 and tcp[tcpflags] == tcp-syn'
有关更多示例,请参阅在线提供的 BPF 和 tcpdump 示例。
BPFJIT
TRex 服务器使用BPF JIT,一个 BPF 到本地代码的编译版本,以允许非常快速的过滤。所以在TRex中高速过滤是非常可能的。
之前
以下是 XL710 的快照,配备 Intel® Xeon® CPU E5-2667 v3 @ 3.20GHz ,在应用 BPF 过滤器之前处理 15.72 mpps。
- Global Statistics
-
- connection : localhost, Port 4501 total_tx_L2 : 8.18 Gb/sec
- version : v2.28 total_tx_L1 : 10.73 Gb/sec
- cpu_util. : 3.31% @ 14 cores (7 per port) total_rx : 8.18 Gb/sec
- rx_cpu_util. : 82.0% / 15.72 Mpkt/sec 1 total_pps : 15.97 Mpkt/sec
- async_util. : 0.19% / 1.76 KB/sec drop_rate : 0.00 b/sec
- queue_full : 0 pkts
之后
用一个非命中过滤器来衡量使用 BPF 过滤器的效果:
- Global Statistics
-
- connection : localhost, Port 4501 total_tx_L2 : 8.21 Gb/sec
- version : v2.28 total_tx_L1 : 10.77 Gb/sec
- cpu_util. : 3.37% @ 14 cores (7 per port) total_rx : 8.21 Gb/sec
- rx_cpu_util. : 86.4% / 15.63 Mpkt/sec 1 total_pps : 16.03 Mpkt/sec
- async_util. : 0.21% / 1.64 KB/sec drop_rate : 0.00 b/sec
- queue_full : 0 pkts
负过滤对 CPU 利用率的影响几乎为零 (<5%)。
当然,命中过滤器会产生影响,但通常只对一小部分流量产生影响。
API 使用情况
使用 Python API 相当简单:
- # move port 1 to service mode as we want to capture traffic on it
- client.set_service_mode(ports = 1)
-
- # start a capture on port 1 Rx side with a limit, a mode and a *BPF* filter for any UDP with dst port 53
- capture = client.start_capture(rx_ports = 1, limit = 100, mode = 'fixed', bpf_filter = 'udp and dst 53')
-
- # execute your code here
-
- # save the packets to a file or to a list (see the Python API docs)
- client.stop_capture(capture['id'], '/home/mydir/port_0_rx.pcap')
-
- # exit service mode on port 1
- client.set_service_mode(ports = 1, enabled = False)
控制台使用
控制台提供了几种灵活的方式来处理数据包捕获
捕获监控
捕获记录
捕获监控
捕获监控是一种非持久性方法,用于捕获和显示来自一个或多个端口的 Tx / Rx 的数据包。
监控有 3 种模式:
低详细 - 将显示每个数据包的短行
高详细 - 每个数据包将显示完整的 Scapy 节目
Wireshark Pipe - 使用连接到正在捕获的流量的管道启动 Wireshark
前两个选项在控制台上显示数据包信息。如果正在监控中等数量的流量,这是理想的选择。但是,如果正在监控大量流量,请考虑使用Wireshark Pipe或Capture Recording方法。
- trex>service 1
-
- Enabling service mode on port(s) [0, 1, 2, 3]: [SUCCESS]
-
- trex(service)>capture monitor start --rx 3 -v 2
-
- Starting stdout capture monitor - verbose: 'high' [SUCCESS]
-
-
- *** use 'capture monitor stop' to abort capturing... ***
-
- trex(service)>arp -p 3 3
-
- Resolving destination on port(s) [3]: [SUCCESS]
-
- Port 3 - Recieved ARP reply from: 1.1.1.1, hw: 90:e2:ba:ae:88:b8 4
- 38.14 [ms]
-
- trex(service)>
-
- #1 Port: 3 -- Rx
-
- Type: ARP, Size: 60 B, TS: 16.98 [sec]
-
- ###[ Ethernet ]###
- dst = 90:e2:ba:af:13:89
- src = 90:e2:ba:ae:88:b8
- type = 0x806
- ###[ ARP ]###
- hwtype = 0x1
- ptype = 0x800
- hwlen = 6
- plen = 4
- op = is-at 5
- hwsrc = 90:e2:ba:ae:88:b8
- psrc = 1.1.1.1
- hwdst = 90:e2:ba:af:13:89
- pdst = 4.4.4.4
- ###[ Padding ]###
- load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
-
-
- trex(service)>
说明:
1、移动到服务模式以允许捕获。
2、在详细打开 的情况下激活端口3 Rx 侧的捕获监视器。
3、在端口3 上发送 ARP 请求。
4、控制台显示返回的数据包。
5、is-at ARP 响应被捕获。
使用 Wireshark 管道捕获流量的示例
- trex(service)>capture monitor start --rx 3 -f udp -p 1
-
- Starting pipe capture monitor [SUCCESS]
-
-
- Trying to locate Wireshark [SUCCESS]
-
-
- Checking permissions on '/usr/bin/dumpcap' [SUCCESS]
-
-
- Launching '/usr/bin/wireshark -k -i /tmp/tmputa4jf3c' [SUCCESS] 2
-
-
- Waiting for Wireshark pipe connection [SUCCESS] 3
-
-
- *** Capture monitoring started *** 4
-
- trex(service)>arp 5
-
- Resolving destination on port(s) [0, 1, 2, 3]: [SUCCESS]
-
- Port 0 - Recieved ARP reply from: 4.4.4.4, hw: 90:e2:ba:af:13:89
- Port 1 - Recieved ARP reply from: 3.3.3.3, hw: 90:e2:ba:af:13:88
- Port 2 - Recieved ARP reply from: 2.2.2.2, hw: 90:e2:ba:ae:88:b9
- Port 3 - Recieved ARP reply from: 1.1.1.1, hw: 90:e2:ba:ae:88:b8
说明:
1、使用 Wireshark 管道和 UDP 过滤器 (BPF) 激活监视器。
2、尝试使用与管道的连接来启动 Wireshark。
3、控制台被阻塞,直到建立连接。
4、监视器处于活动状态。
5、发送 ARP 请求。

图4. Wireshark 管道
捕获记录
除了监控之外,控制台还允许进行简单的录制。记录使您能够定义一个固定大小的队列,然后可以将其保存到 PCAP 文件中。
- trex(service)>capture record start --rx 3 --limit 200 1
-
- Starting packet capturing up to 200 packets [SUCCESS]
-
- *** Capturing ID is set to '4' *** 2
- *** Please call 'capture record stop --id 4 -o <out.pcap>' when done ***
-
- trex(service)>capture 3
-
- Active Recorders
-
- ID | Status | Packets | Bytes | TX Ports | RX Ports
- ------------------------------------------------------------------------------------------------------
- 4 | ACTIVE | [0/200] | 0 B | - | 3
-
-
-
- trex(service)>start -f stl/imix.py -m 1kpps -p 0 --force 4
-
- Removing all streams from port(s) [0]: [SUCCESS]
-
-
- Attaching 3 streams to port(s) [0]: [SUCCESS]
-
-
- Starting traffic on port(s) [0]: [SUCCESS]
-
- 20.42 [ms]
-
- trex(service)>capture 5
-
- Active Recorders
-
- ID | Status | Packets | Bytes | TX Ports | RX Ports
- ------------------------------------------------------------------------------------------------------
- 4 | ACTIVE | [200/200] | 74.62 KB | - | 3
-
-
- trex(service)>capture record stop --id 4 -o /tmp/rx_3.pcap 6
-
- Stopping packet capture 4 [SUCCESS]
-
-
- Writing 200 packets to '/tmp/rx_3.pcap' [SUCCESS]
-
-
- Removing PCAP capture 4 from server [SUCCESS]
-
- trex(service)>
说明:
1、在端口3 Rx 端 启动一个数据包记录,限制为200 个数据包。
2、使用 ID 4 创建一个新的捕获。
3、显示捕获状态 - 当前为空。
4、在连接到端口3的端口0 上启动流量。
5、显示捕获状态 - 已满。
6、将 200 个数据包保存到输出文件:/tmp/rx_3.pcap
使用捕获作为计数器
数据包捕获的另一个用途是计数。您可以简单地计算命中 BPF 过滤器的数据包,而不是获取数据包。
例如,要计算源端口为5000的任何UDP数据包,您只需使用正确的 BPF 过滤器附加一个空捕获并检查匹配的字段:
- trex(service)>capture record start --rx 3 --limit 0 -f udp and src 5000
-
- Starting packet capturing up to 0 packets [SUCCESS]
-
- *** Capturing ID is set to '14' ***
- *** Please call 'capture record stop --id 14 -o <out.pcap>' when done ***
-
- trex(service)>capture
-
- Active Recorders
-
- ID | Status | Matched | Packets | Bytes | RX Ports | BPF Filter
- -------------------------------------------------------------------------------------------------------
- 14 | ACTIVE | 0 | [0/0] | 0 B | 3 | udp and src 5000
-
- trex(service)>
Matched字段表示有多少数据包与过滤器匹配。
使用捕获端口进行更快的数据包捕获/数据包注入
由于轮询性质和 RPC 协议的开销,使用数据包捕获机制在 TRex 客户端 python 端检查数据包通常会产生大约 5000 个数据包/秒的传输速率。
为了在 TRex 服务器和 TRex 客户端之间进行更快的数据包传输,以及改进数据包的注入,可以使用捕获端口功能。它的运行速度通常比 TRex 捕获快 4 倍。
此功能使 oneTRex 服务器能够连接到已打开的 ZeroMQ 套接字,该套接字将仅用于发送/接收给定 TRex 端口的原始数据包。在此套接字上推送一些数据将转换为在 TRex 端口上发送的新数据包,而在该端口上接收到的数据包也将通过 ZeroMQ 套接字发送。
可选地,也可以指定一个 BPF 过滤器来限制从 TRex 服务器发送到 TRex 客户端的数据包。
这是一个使用示例,它将首先在 TRex 端口 0 上发送一个数据包,然后阻塞直到收到一个 IP 数据包:
- import zmq
- # Bind our ZeroMQ socket so that the TRex server can connect to it
- capture_port = "ipc:///tmp/trex_capture_port"
- zmq_context = zmq.Context()
- zmq_socket = zmq_context.socket(zmq.PAIR)
- zmq_socket.bind(capture_port)
-
- # move port 0 to service mode as we want to start capture port on it
- client.set_service_mode(ports = 0)
-
- # start a trex capture port on port 0 with *BPF* filter for any IP packets
- client.start_capture_port(port = 0, endpoint = capture_port, bpf_filter = 'ip')
-
- # Send one packet (using scapy here)
- zmq_socket.send(bytes(Ether()/IP()/IP()/UDP()))
-
- # Wait until we get an IP packet on TRex port 0 and display it parsed using Scapy
- received_packet = zmq_socket.recv()
- Ether(received_packet).show2()
-
- # Stop capture port
- client.stop_capture_port(port = 0)
-
- # exit service mode on port 0
- client.set_service_mode(ports = 0, enabled = False)
为了保持高速流量生成,TRex 在预测试阶段处理相邻协议。
需要运行相邻协议的测试应首先进入服务模式,在 Python 中执行所需的步骤,切换回正常模式,然后开始实际测试。
ARP
作为 TRex 的一部分提供的基本相邻协议是 ARP。
示例设置:

图 5. 路由器 ARP
- trex>service #1
-
- Enabling service mode on port(s) [0, 1]: [SUCCESS]
-
- trex(service)>portattr --port 0
-
- port | 0 |
- ------------------------------------------
- driver | rte_ixgbe_pmd |
- description | 82599EB 10-Gigabit |
- link status | UP |
- link speed | 10 Gb/s |
- port status | IDLE |
- promiscuous | off |
- flow ctrl | none |
- -- | |
- src IPv4 | - |
- src MAC | 00:00:00:01:00:00 |
- --- | |
- Destination | 00:00:00:01:00:00 |
- ARP Resolution | - |
- ---- | |
- PCI Address | 0000:03:00.0 |
- NUMA Node | 0 |
- ----- | |
- RX Filter Mode | hardware match |
- RX Queueing | off |
- RX sniffer | off |
- Grat ARP | off |
-
-
- trex(service)>l3 -p -s 1.1.1.1 -d 1.1.1.2 #2
-
- trex(service)>arp -p 0 1 #3
-
- Resolving destination on port(s) [0, 1]: [SUCCESS]
-
-
- Port 0 - Received ARP reply from: 1.1.1.1, hw: d0:d0:fd:a8:a1:01
- Port 1 - Received ARP reply from: 1.1.2.1, hw: d0:d0:fd:a8:a1:02
-
- trex(service)>service --off #4
说明:
1、启用服务模式。
2、设置 IPv4/默认网关。它将解析ARP。
3、重复 ARP 解析。
4、退出服务模式。
要恢复到 MAC 地址模式(无 ARP 解析):
- trex>l2 -p 0 --dst 00:00:00:01:00:00 #1
-
- trex>portattr --port 0
-
- port | 0 |
- ------------------------------------------
- driver | rte_ixgbe_pmd |
- description | 82599EB 10-Gigabit |
- link status | UP |
- link speed | 10 Gb/s |
- port status | IDLE |
- promiscuous | off |
- flow ctrl | none |
- -- | |
- src IPv4 | - |
- src MAC | 00:00:00:01:00:00 |
- --- | |
- Destination | 00:00:00:01:00:00 |
- ARP Resolution | - |
- ---- | |
- PCI Address | 0000:03:00.0 |
- NUMA Node | 0 |
- ----- | |
- RX Filter Mode | hardware match |
- RX Queueing | off |
- RX sniffer | off |
- Grat ARP | off |
说明:
1、禁用服务模式。
Python API:
- client.set_service_mode(ports = [0, 1], enabled = True) 1
-
- # configure port 0, 1 to Layer 3 mode
- client.set_l3_mode(port = 0, src_ipv4 = '1.1.1.2', dst_ipv4 = '1.1.1.2') 2
- client.set_l3_mode(port = 1, src_ipv4 = '1.1.2.2', dst_ipv4 = '1.1.2.1')
-
- # ARP resolve ports 0, 1
- c.resolve(ports = [0, 1])
-
- client.set_service_mode(ports = [0, 1], enabled = False) 3
说明:
1、启用服务模式。
2、配置 IPv4 和默认网关。
3、禁用服务模式。
ICMP
TRex 提供的另一个基本协议是 ICMP。在服务模式下,可以从控制台/API ping DUT 甚至是 TRex 端口。
- trex(service)>ping --help
- usage: ping [-h] --port PORT -d PING_IPV4 [-s PKT_SIZE] [-n COUNT]
-
- pings the server / specific IP
-
- optional arguments:
- -h, --help show this help message and exit
- --port PORT, -p PORT source port for the action
- -d PING_IPV4 which IPv4 to ping
- -s PKT_SIZE packet size to use
- -n COUNT, --count COUNT
- How many times to ping [default is 5]
-
- trex(service)>ping -p 0 -d 1.1.2.2
-
- Pinging 1.1.2.2 from port 0 with 64 bytes of data:
- Reply from 1.1.2.2: bytes=64, time=27.72ms, TTL=127
- Reply from 1.1.2.2: bytes=64, time=1.40ms, TTL=127
- Reply from 1.1.2.2: bytes=64, time=1.31ms, TTL=127
- Reply from 1.1.2.2: bytes=64, time=1.78ms, TTL=127
- Reply from 1.1.2.2: bytes=64, time=1.95ms, TTL=127
Python API
- # move to service mode
- client.set_service_mode(ports = ports, enabled = True)
-
- # configure port 0, 1 to Layer 3 mode
- client.set_l3_mode(port = 0, src_ipv4 = '1.1.1.2', dst_ipv4 = '1.1.1.1')
- client.set_l3_mode(port = 1, src_ipv4 = '1.1.2.2', dst_ipv4 = '1.1.2.1')
-
- # ping port 1 from port 0 through the router
- client.ping_ip(src_port = 0, dst_ipv4 = '1.1.2.2', pkt_size = 64) 1
-
- # disable service mode
- client.set_service_mode(enabled = False)
说明:
1、检查连通性。
IPv6 ND 客户端
当前:TRex 支持扫描网络以查找支持 IPv6 的邻居,并从控制台 ping 附近的设备。
未来阶段的计划:在 CPP 服务器上添加支持。
这些方法的优点是它们可以很容易地扩展以在自动化中模拟大量客户端。
扫描示例:

ping示例:

这些实用程序(也可从 API 获得)可以帮助用户配置下一跳。从控制台,可以设置从 scan6 结果中获取的“l2”目标 MAC:

为了设置自己的 IPv6,我们使用RFC 3513中描述的本地地址。
对于网络扫描,我们 ping 多播地址 ff02::1 并通过 NS/ND 会话建立连接。
扫描网络上的附加链接:
在自动化中使用 IPv6 方法的示例:
Linux 网络命名空间
从 v2.50 版本开始,可以将一些 Linux 网络命名空间附加到 TRex 物理接口。命名空间中的每个主机也就是模拟真实客户端的节点。使用这种方法,可以模拟具有许多 Linux 网络设备的网络,每个设备都有自己独立的网络堆栈(例如不同的 ipv4/ipv6/QinQ/Dot1Q/routing/arp 表等)

上图显示了连接到虚拟交换机(在 TRex 内部实现)的两台主机 host4 和 host5。TRex 端口本身有自己的命名空间,有自己的 IPv4 和 IPv6 配置(使用旧 API)。创建时的每个主机都有一个不同的 MAC 地址作为密钥和网络配置(IPv4、IPv6、Dot1Q、QinQ 等)。这些协议由 Linux 内核实现(超时、arp 表、ipv6、每个命名空间的路由)。
让我们以入口和出口数据包为例
DUT ARP 请求数据包来自 DUT 到 host4(whois host4 -broadcast)。此数据包到达 TRex Rx 核心(由于 STL 中的服务模式配置以及默认情况下在 ASTF 中)。Rx 核心会将其广播到所有节点(host4、host5、trex-port1) host4 将使用单播 ARP 响应进行应答 tat 将到达 DUT(通过 TRex 交换机实现)
节点生成的 IPv6 MLD/广播数据包(组播/广播数据包)将仅转发到DUT。DUT 广播/多播数据包将转发到所有节点。
创建新节点时。它不会发送免费的 arp 多播/混杂模式应该在端口级别启用,否则单播数据包不会到达节点。
API 功能是
创建一个新节点并将其关联到一个物理端口(例如端口 0)。
使用 IPv4 和/或 IPv6 配置节点。
从端口中删除节点。
获取统计信息/状态
这种方法的一个缺点是添加/删除新节点有点慢。创建一个可能需要大约 100 毫秒(由于内核交互)。但是,一旦创建了节点,TRex 将能够毫无问题地处理其中的许多节点,因为流量率不高(仅限多播/广播数据包),TRex 可以通过将此操作拆分为来处理多播突发(DUT→许多节点)很多小操作。
规模受内核内存和创建时间的限制。
因为这是一个非常缓慢的操作,所以 API 与我们今天的 API 有点不同。
差异
reset API不会删除所有节点
一旦客户端断开/连接,节点信息就不会同步
“服务模式”应该在 STL 中启用(对于 ASTF 不需要)
需要启用多播/混杂模式
添加 stack: linux_basedtrex_cfg.yaml 参见Linux Stack
- - version: 2
- interfaces: ['82:00.0', '82:00.1']
- stack: linux_based
- ...
完整的 API 可以在命名空间 API中找到
节点类型
所有节点 (node==veth) 都由唯一的 MAC 地址标识,但存在一些差异。有 3 种类型的节点:Normal、Shared Namespace和Bird 节点。
图 7. 三种类型的节点
普通节点
这些是默认类型的节点,创建 1 个命名空间和 1 个 veth 对。添加另一个新节点将创建另一个具有 1 个 veth 对的命名空间。这些节点由 ipv4 和一个默认网关配置(所有流量都转发到默认的单个 veth)
使用示例
- cmds = NSCmds()
- MAC = "00:01:02:03:04:05"
- cmds.add_node(MAC) 1
- c.set_namespace(0, method='set_ipv4', mac=MAC, ipv4="1.1.1.3", dg="1.1.1.2") 2
- ...
说明:
1、默认节点为普通节点,只指定mac地址
2、使用 ip 地址和默认网关配置 ipv4
更多示例可以在这里找到
共享命名空间节点
这些是附加到预先创建的命名空间的节点(veth)。通过这种方式,您可以创建多个附加到同一命名空间的 veth。这些节点由 ipv4 和子网掩码配置,还可以为整个命名空间设置默认网关(设置为 veth 之一) Dot1Q/QinQ 的配置是 per veth 而不是 per namespace
使用示例
- cmds = NSCmds()
- cmds.add_node(mac = "00:01:02:03:04:05", shared_ns = "my-ns") 1
- cmds.add_node(mac = "00:01:02:03:04:06", shared_ns = "my-ns") 2
- c.set_namespace(0, method='set_ipv4', mac="00:01:02:03:04:05",
- ipv4 = "1.1.1.3",
- subnet = 24,
- shared_ns = True) 3
-
- c.set_namespace(0, method='set_ipv4', mac="00:01:02:03:04:06",
- ipv4 = "1.1.2.3",
- subnet = 24,
- shared_ns = True)
说明:
1、“my-ns”是预先创建的命名空间的名称
2、在同一命名空间中创建第二个 veth 对
3、必须指定 shared_ns 参数
鸟节点
鸟节点是共享命名空间节点的一个特例。Bird 命名空间在运行带有“--bird-server”标志的 TRex 时创建,这样它们类似于共享命名空间。
要了解更多关于在 TRex 中使用 bird 的信息,请参阅:
节点类型差异总结
| 节点类型 | 节点:veth 比率 | 命名空间创建 | 子网掩码 | 默认网关 |
| 普通的 | 1:1 | 在每个节点上创建 | 未使用,使用默认网关 | 1 代表整个节点 |
| 共享命名空间 | 1:很多 | 由“add_shared_ns”命令创建,名称由 TRex 确定 | 在“set_ipv4/6”处配置 | 1 代表整个命名空间 |
| 鸟 | 1:很多 | 预先创建,名称由 TRex 确定 | 在“set_ipv4/6”处配置 | 未使用,使用子网掩码 |
注意命名空间不能相互通信,因为它们都通过 TRex 端口将数据包传递到 DUT。
使用批处理 API 添加一个节点
在此示例中,将添加一个 MAC:“00:01:02:03:04:05”和 ipv4="1.1.1.3" default_gateway ="1.1.1.2" 并启用 IPv6 的节点。API 需要一批操作。这些操作可以与其他 API(例如流量)并行工作,以验证需要调用wait_for_async_resultsAPI的响应
- c = STLClient(verbose_level = 'error')
- c.connect()
-
- my_ports=[0,1]
- c.reset(ports = my_ports) 1
-
- # move to service mode
- c.set_service_mode (ports = my_ports, enabled = True) 2
-
-
- cmds=NSCmds() 3
- MAC="00:01:02:03:04:05"
- cmds.add_node(MAC) # add namespace 4
- cmds.set_vlan(MAC,[123,123]) # add vlan + QinQ tags
- cmds.set_ipv4(MAC,"1.1.1.3","1.1.1.2") # configure ipv4 and default gateway 5
- cmds.set_ipv6(MAC,True) # enable ipv6 (auto mode, get src address from the router) 6
-
-
- # start the batch
- c.set_namespace_start( 0, cmds) 7
- # wait for the results
- res = c.wait_for_async_results(0) 8
-
- # print the results
- print(res)
说明:
1、重置 API 不会删除旧节点
2、进入服务模式
3、定义一个 NSCmds 对象,它将被异步命令填充
4、添加新节点
5、配置ipv4
6、启用 ipv6
7、为对象提供 set_namespace_start 的所有命令
8、等待操作完成
阻塞 API
- c = STLClient(verbose_level = 'error')
- c.connect()
-
- my_ports=[0,1]
- c.reset(ports = my_ports)
-
- # move to service mode
- c.set_service_mode (ports = my_ports, enabled = True)
-
- # remove all old name spaces from all the ports
- c.namespace_remove_all()
-
- # utility function
- MAC="00:01:02:03:04:05"
-
- # each function will block
- c.set_namespace(0,method='add_node',mac=MAC) 1
- c.set_namespace(0,method='set_vlan',vlans=[123,123])
- c.set_namespace(0,method='set_ipv4', mac=MAC, ipv4="1.1.1.3", dg="1.1.1.2")
- c.set_namespace(0,method='set_ipv6', mac=MAC, enable= True)
说明:
1、无需填充对象 NSCmds。使用命名空间请求的 API 调用 set_namespace API
统计查询
- c = STLClient(verbose_level = 'error')
- c.connect()
- my_ports=[0,1]
- c.reset(ports = my_ports)
-
- # get all active nodes on port 0
- r=c.set_namespace(0, method='get_nodes') 1
- c.set_namespace (0, method='get_nodes_info', macs_list=r) 2
-
- r=c.set_namespace(0, method='counters_get_meta') 3
- r=c.set_namespace(0, method='counters_get_values', zeros=True) 4
说明:
1、获取活动节点(每个节点的 mac)
2、获取每个节点的完整信息
3、获取统计计数器(名称/类型)
4、获取计数器值
Ping 到新节点
在此设置中有两个端口 1.1.1.1 (port0) <→ 1.1.1.2 (port1)
这是之前的配置:
混杂已关闭
- trex>portattr -a
- Port Status
-
- port | 0 | 1
- ----------------+----------------------+---------------------
- driver | net_vmxnet3 | net_vmxnet3
- description | VMXNET3 Ethernet C | VMXNET3 Ethernet C
- link status | UP | UP
- link speed | 10 Gb/s | 10 Gb/s
- port status | IDLE | IDLE
- promiscuous | off | off
- multicast | on | on
- flow ctrl | N/A | N/A
- vxlan fs | N/A | N/A
- -- | |
- layer mode | IPv4 | IPv4
- src IPv4 | 1.1.1.1 | 1.1.1.2
- IPv6 | off | off
- src MAC | 00:0c:29:b4:e7:e9 | 00:0c:29:b4:e7:11
- --- | |
- Destination | 1.1.1.2 | 1.1.1.1
- ARP Resolution | 00:0c:29:b4:e7:11 | 00:0c:29:b4:e7:e9
- ---- | |
- VLAN | - | -
- ----- | |
- PCI Address | 0000:0b:00.0 | 0000:0c:00.0
- NUMA Node | 0 | 0
- RX Filter Mode | hardware match | hardware match
- RX Queueing | off | off
- Grat ARP | off | off
- ------ | |
让我们确保我们处于混杂模式和服务模式
- trex>portattr --mul on
- trex>portattr --prom on
- trex>service
- trex>portattr -a
- Port Status
-
- port | 0 | 1
- ----------------+----------------------+---------------------
- driver | net_vmxnet3 | net_vmxnet3
- description | VMXNET3 Ethernet C | VMXNET3 Ethernet C
- link status | UP | UP
- link speed | 10 Gb/s | 10 Gb/s
- port status | IDLE | IDLE
- promiscuous | on | on
- multicast | on | on
- flow ctrl | N/A | N/A
- vxlan fs | N/A | N/A
- -- | |
- layer mode | IPv4 | IPv4
- src IPv4 | 1.1.1.1 | 1.1.1.2
- IPv6 | off | off
- src MAC | 00:0c:29:b4:e7:e9 | 00:0c:29:b4:e7:11
- --- | |
- Destination | 1.1.1.2 | 1.1.1.1
- ARP Resolution | 00:0c:29:b4:e7:11 | 00:0c:29:b4:e7:e9
- ---- | |
- VLAN | - | -
- ----- | |
- PCI Address | 0000:0b:00.0 | 0000:0c:00.0
- NUMA Node | 0 | 0
- RX Filter Mode | hardware match | hardware match
- RX Queueing | off | off
- Grat ARP | off | off
- ------
让我们调用这个脚本在端口 0 上添加一个新节点
- cmds=NSCmds()
- MAC="00:01:02:03:04:05"
- cmds.add_node(MAC)
- cmds.set_ipv4(MAC,"1.1.1.3","1.1.1.2")
- cmds.set_ipv6(MAC,True)
-
- res = c.set_namespace_start( 0, cmds)
- res = c.wait_for_async_results(0)
现在我们可以ping到新节点
- trex(service)>l3 -p 1 --src 1.1.1.2 --dst 1.1.1.3
- trex(service)>ping -p 1 -d 1.1.1.3
-
- Pinging 1.1.1.3 from port 1 with 64 bytes of data:
- Reply from 1.1.1.3: bytes=64, time=32.29ms, TTL=64
- Reply from 1.1.1.3: bytes=64, time=3.73ms, TTL=64
- Reply from 1.1.1.3: bytes=64, time=3.89ms, TTL=64
- Reply from 1.1.1.3: bytes=64, time=2.85ms, TTL=64
- Reply from 1.1.1.3: bytes=64, time=2.82ms, TTL=64
要从 Linux shell 调试它,你可以这样做
$sudo ip netns show
这将显示所有网络命名空间
对于端口 0,名称是trex-a-0-x,其中 X 是命名空间的编号
查看信息
- $sudo ip netns exec trex-a-0-1 ifconfig
- trex-a-0-1-L: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9280
- inet 1.1.1.3 netmask 255.255.255.255 broadcast 0.0.0.0
- inet6 fe80::201:2ff:fe03:405 prefixlen 64 scopeid 0x20<link>
- ether 00:01:02:03:04:05 txqueuelen 1000 (Ethernet)
- RX packets 1 bytes 60 (60.0 B)
- RX errors 0 dropped 1 overruns 0 frame 0
- TX packets 8 bytes 648 (648.0 B)
- TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以使用通常的捕获功能监视和捕获来自/到命名空间的流量
您将无法 ping 1.1.1.1(原始端口 ip),因为 TRex ping 有一个默认网关
控制台命令示例
控制台命令的目标是一次添加/删除一个节点的小规模操作以下示例显示
- trex(service)>ns add -p 0 --mac 00:01:02:03:04:05 --src 1.1.1.3 --dst 1.1.1.2 --ipv6
-
- trex(service)>ns show-node -p 0 --mac 00:01:02:03:04:05
-
- {'nodes': [{'ether': {'src': '00:01:02:03:04:05'},
- 'ipv4': {'dst': '1.1.1.2', 'src': '1.1.1.3'},
- 'ipv6': {'enabled': True, 'src': ''},
- 'linux-ns': 'trex-a-0-1',
- 'linux-veth-external': 'trex-a-0-1-T',
- 'linux-veth-internal': 'trex-a-0-1-L',
- 'vlan': {'tags': []}}]}
-
-
- trex(service)>ns show-nodes -p 0
-
- Setting port 0 in with namespace configuration [SUCCESS]
-
-
- wait_for_async_results [SUCCESS]
-
- ns nods
-
- node-id | mac
- -----------+------------------
- 0 | 00:01:02:03:04:05
-
-
- trex(service)>ns show-counters -p 0
-
- Setting port 0 in with namespace configuration [SUCCESS]
-
-
- wait_for_async_results [SUCCESS]
-
- ns stats
-
- name | value | help
- ---------------------+-------------------+---------------------
- rx_unicast_bytes | 60 | rx unicast bytes
- tx_multicast_bytes | 648 | tx multicast bytes
- rx_unicast_pkts | 1 | rx unicast pkts
- tx_multicast_pkts | 8 | tx multicast pkts
- rx_multicast_bytes | 480 | rx multicast bytes
- rx_multicast_pkts | 8 | rx multicast pkts