No traffic emerges in DPDK RX/TX Callbacks Sample Application
我是 DPDK 领域的大一新生。我从 DPDK 主页给出的示例应用程序开始。我被困在示例中 --- DPDK RX/TX 回调示例应用程序。条件是长时间没有流量出现(但输出)。我猜原因是我无法将流量发送到 DPDK 端口。
我首先一步一步地展示我的设置。开头的网卡信息
然后,我拒绝
1 2 | sudo ifconfig eth2 down sudo ifconfig eth3 down |
接下来,我使用
所有准备工作都已完成。我开始构建示例应用程序。使用以下命令
1 2 3 4 | export RTE_SDK=~/dpdk/dpdk-18.08 export RTE_TARGET=i686-native-linuxapp-gcc cd examples/rxtx_callbacks/ make |
一切正常,输出编译信息:
1 2 3 4 5 | mininet@mininet-vm:~/dpdk/dpdk-18.08/examples/rxtx_callbacks$ make CC main.o LD rxtx_callbacks INSTALL-APP rxtx_callbacks INSTALL-MAP rxtx_callbacks.map |
然后,我开始使用以下命令运行示例应用程序:
1 | sudo ./build/rxtx_callbacks -l1 -n4 |
执行日志为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | mininet@mininet-vm:~/dpdk/dpdk-18.08/examples/rxtx_callbacks$ sudo ./build/rxtx_callbacks -l1 -n4 EAL: Detected 2 lcore(s) EAL: Detected 1 NUMA nodes EAL: Multi-process socket /var/run/dpdk/rte/mp_socket EAL: Probing VFIO support... EAL: PCI device 0000:00:08.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:09.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:0a.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:11.0 on NUMA socket 0 EAL: probe driver: 8086:100f net_e1000_em Port 0 MAC: 08 00 27 9d f9 5a Port 1 MAC: 08 00 27 7f e8 8a |
随着时间的流逝,什么也没有发生。但是,我发现执行结果应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | root@ubuntu:/home/chang/dpdk/examples/rxtx_callbacks/build# ./rxtx_callbacks -l 1 -n 4 EAL: Detected 8 lcore(s) EAL: No free hugepages reported in hugepages-1048576kB EAL: Multi-process socket /var/run/.rte_unix EAL: Probing VFIO support... EAL: PCI device 0000:02:01.0 on NUMA socket -1 EAL: Invalid NUMA socket, default to 0 EAL: probe driver: 8086:100f net_e1000_em EAL: PCI device 0000:02:02.0 on NUMA socket -1 EAL: Invalid NUMA socket, default to 0 EAL: probe driver: 8086:100f net_e1000_em EAL: PCI device 0000:02:03.0 on NUMA socket -1 EAL: Invalid NUMA socket, default to 0 EAL: probe driver: 8086:100f net_e1000_em EAL: PCI device 0000:02:04.0 on NUMA socket -1 EAL: Invalid NUMA socket, default to 0 EAL: probe driver: 8086:100f net_e1000_em Port 0 MAC: 00 0c 29 f7 4d 25 Port 1 MAC: 00 0c 29 f7 4d 2f Core 1 forwarding packets. [Ctrl+C to quit] Latency = 629 cycles Latency = 787 cycles ^C |
我试图找到结果,我在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | for (;;) { RTE_ETH_FOREACH_DEV(port) { struct rte_mbuf *bufs[BURST_SIZE]; /* printf("receive a packet\ "); */ const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE); if (unlikely(nb_rx == 0)) continue; printf("send a packet\ "); const uint16_t nb_tx = rte_eth_tx_burst(port ^ 1, 0, bufs, nb_rx); if (unlikely(nb_tx < nb_rx)) { uint16_t buf; for (buf = nb_tx; buf < nb_rx; buf++) rte_pktmbuf_free(bufs[buf]); } } } |
我发现没有收到任何数据包,因为它应该通过检查 ---
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 | #!/bin/sh modprobe pktgen function pgset() { local result echo $1 > $PGDEV result=`cat $PGDEV | fgrep"Result: OK:"` if ["$result" ="" ]; then cat $PGDEV | fgrep Result: fi } function pg() { echo inject > $PGDEV cat $PGDEV } # Config Start Here ----------------------------------------------------------- # thread config # Each CPU has own thread. Two CPU example. We add eth1. PGDEV=/proc/net/pktgen/kpktgend_0 echo"Removing all devices" pgset"rem_device_all" echo"Adding eth1" pgset"add_device eth1" echo"Setting max_before_softirq 10000" pgset"max_before_softirq 10000" # device config # delay 0 means maximum speed. CLONE_SKB="clone_skb 1000000" # NIC adds 4 bytes CRC PKT_SIZE="pkt_size 60" # COUNT 0 means forever #COUNT="count 0" COUNT="count 10000000" DELAY="delay 0" PGDEV=/proc/net/pktgen/eth1 echo"Configuring $PGDEV" pgset"$COUNT" pgset"$CLONE_SKB" pgset"$PKT_SIZE" pgset"$DELAY" pgset"dst 127.0.0.1" # here! the mac address given by the sample application pgset"dst_mac 08:00:27:9d:f9:5a" # Time to run PGDEV=/proc/net/pktgen/pgctrl echo"Running... ctrl^C to stop" pgset"start" echo"Done" # Result can be vieved in /proc/net/pktgen/eth1 |
不过,什么也没发生。也许,发送数据包到 dpdk 端口的方式是错误的。由于 dpdk 端口位于第 2 层,因此第 3 层工具(如
最好的祝愿。
EDIT1:
@Amedeo 的回复成功了,但是,我只能向 RX/TX 回调应用程序发送一些数据包(几个数据包不是流量)。我试过使用Linux提供的
首先,所有准备工作同上。但是,我使用命令
运行示例应用程序
1 | sudo ./build/rxtx_callbacks -l1 -n4 --vdev=net_tap0 |
而不是
1 | sudo ./build/rxtx_callbacks -l1 -n4 |
运行示例应用程序后,我可以在
哦,我需要提一下,我已经拒绝了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | EAL: Detected 2 lcore(s) EAL: Detected 1 NUMA nodes EAL: Multi-process socket /var/run/dpdk/rte/mp_socket EAL: Probing VFIO support... EAL: PCI device 0000:00:08.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:09.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:0a.0 on NUMA socket 0 EAL: probe driver: 8086:100e net_e1000_em EAL: PCI device 0000:00:11.0 on NUMA socket 0 EAL: probe driver: 8086:100f net_e1000_em rte_pmd_tap_probe(): Initializing pmd_tap for net_tap0 as dtap0 Port 0 MAC: 08 00 27 93 2b 19 Port 1 MAC: 08 00 27 9d f9 5a Port 2 MAC: 08 00 27 7f e8 8a Port 3 MAC: fe 02 cf 5a 23 ee Core 1 forwarding packets. [Ctrl+C to quit] |
带有
我首先给交互
1 | sudo dhclient dtap0 |
并得到:
1 2 3 4 5 6 7 | dtap0 Link encap:Ethernet HWaddr fe:02:cf:5a:23:ee inet addr:10.0.2.16 Bcast:10.0.2.255 Mask:255.255.255.0 UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:73 errors:0 dropped:0 overruns:0 frame:0 TX packets:92 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:500 RX bytes:6651 (6.6 KB) TX bytes:7808 (7.8 KB) |
然后,我编写了一个 shell 脚本来生成从
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 | #!/bin/sh #modprobe pktgen modprobe pktgen function pgset() { local result echo $1 > $PGDEV result=`cat $PGDEV | fgrep"Result: OK:"` if ["$result" ="" ]; then cat $PGDEV | fgrep Result: fi } function pg() { echo inject > $PGDEV cat $PGDEV } # Config Start Here ----------------------------------------------------------- # thread config # Each CPU has own thread. Two CPU exammple. We add eth1, eth2 respectivly. PGDEV=/proc/net/pktgen/kpktgend_0 echo"Removing all devices" pgset"rem_device_all" echo"Adding eth0" pgset"add_device eth0" echo"Setting max_before_softirq 10000" pgset"max_before_softirq 10000" # device config # delay 0 means maximum speed. CLONE_SKB="clone_skb 1000000" # NIC adds 4 bytes CRC PKT_SIZE="pkt_size 60" # COUNT 0 means forever #COUNT="count 0" COUNT="count 10000000" DELAY="delay 0" PGDEV=/proc/net/pktgen/eth0 echo"Configuring $PGDEV" pgset"$COUNT" pgset"$CLONE_SKB" pgset"$PKT_SIZE" pgset"$DELAY" # ip address of interface dtap0 pgset"dst 10.0.2.16" # the mac address of interface dtap0 pgset"dst_mac fe:02:cf:5a:23:ee" # Time to run PGDEV=/proc/net/pktgen/pgctrl echo"Running... ctrl^C to stop" pgset"start" echo"Done" |
运行这个脚本,我真的发现接口
感谢您就我的问题分享任何想法。
EDIT2:
感谢@Amedeo 的分享。我已经弄清楚如何使用 Linux 提供的
运行
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 | #!/bin/sh #modprobe pktgen modprobe pktgen function pgset() { local result echo $1 > $PGDEV result=`cat $PGDEV | fgrep"Result: OK:"` if ["$result" ="" ]; then cat $PGDEV | fgrep Result: fi } function pg() { echo inject > $PGDEV cat $PGDEV } # Config Start Here ----------------------------------------------------------- # thread config # Each CPU has own thread. Two CPU exammple. We add dtap0 PGDEV=/proc/net/pktgen/kpktgend_1 # echo"Removing all devices" # pgset"rem_device_all" echo"Adding dtap0" pgset"add_device dtap0" echo"Setting max_before_softirq 10000" pgset"max_before_softirq 10000" # device config # delay 0 means maximum speed. CLONE_SKB="clone_skb 1000000" # NIC adds 4 bytes CRC PKT_SIZE="pkt_size 60" # COUNT 0 means forever #COUNT="count 0" COUNT="count 10000000" DELAY="delay 0" PGDEV=/proc/net/pktgen/dtap0 echo"Configuring $PGDEV" pgset"$COUNT" pgset"$CLONE_SKB" pgset"$PKT_SIZE" pgset"$DELAY" # pgset"dst 192.168.211.101" # whatever mac address pgset"dst_mac ce:2a:23:42:ce:ff" # Time to run PGDEV=/proc/net/pktgen/pgctrl echo"Running... ctrl^C to stop" pgset"start" echo"Done" |
我需要做的只是从 dtap0 发送数据包!和
1 | dtap0 --- dpdk port --- rxtx_callbacks |
一切顺利。
预计您看不到流量。 RX/TX 回调示例是 L2FWD 示例的概括。此代码从一个端口接收流量并将其转发到另一个端口。
如果没有传入流量,则应用程序将永远轮询,尝试接收某些内容并且不会转发任何内容。
由于 2 个端口使用的是 DPDK 驱动程序,因此它们对内核不可见。由于这个原因,通常的工具(ifconfig、tcpdump、pktgen 等)看不到这些接口。
您可以只绑定到 dpdk 一个物理接口,并使用一个 tap 接口作为第二个接口。 Tap 接口绑定到内核,因此您可以轻松地在其中注入流量(例如使用 tcpreplay)。
使用点击界面只需要添加参数
1 | sudo ./build/rxtx_callbacks -l1 -n4 --vdev=net_tap0 |
这将创建一个从 ifconfig 可见的接口
来源:https://doc.dpdk.org/guides/nics/tap.html
端到端实验
您还可以删除所有 dpdk 物理端口并仅使用 2 个 TAP 端口。
这样你就可以拥有:
1 | dtap0 --- dpdk port --- rxtx_callbacks --- dpdk port --- dtap1 |
两个TAP可以通过rxtx_callbacks应用互相ping通。
重现这个的步骤是:
1) 解除所有物理接口与 DPDK
的绑定
2) 使用 2 个 TAP 运行 rxtx_callbacks:
1 | sudo ./rxtx_callbacks -l1 -n4 --vdev=net_tap0 --vdev=net_tap1 |
3) 现在您有 2 个 TAP 接口:dtap0 和 dtap1。将 dtap1 移动到不同的网络命名空间并将 IP 分配给 dtap0 和 dtap1:
1 2 3 4 | sudo ip netns add ns1 sudo ip link set dtap1 netns ns1 sudo ip netns exec ns1 ifconfig dtap1 11.0.0.2/24 sudo ifconfig dtap0 11.0.0.1/24 |
4) 您可以从 dtap0 ping dtap1(反之亦然):
1 2 | sudo ping 11.0.0.2 sudo ip netns exec ns1 ping 11.0.0.1 |
5) 清理:将 dtap1 移动到默认命名空间并删除命名空间。
1 2 | sudo ip netns exec ns1 ip link set dtap1 netns 1 sudo ip netns del ns1 |
最简单的开始时效果很好的解决方案是使用一台主机作为 DPDK 目标,另一台主机作为数据包生成器。快速数据包生成器占用大量 CPU 资源,因此在 DPDK 目标上运行它肯定会降低 DPDK 性能。
虽然有时另一台主机不可用,所以第二种最简单的解决方案是在同一台主机上连接背靠背的物理以太网设备。在您的情况下,DPDK 端口
在这种情况下,如果您只配置一个带有 IP 地址的
1 2 3 4 5 6 7 | # ifconfig eth2 down # for DPDK # ifconfig eth3 down # for DPDK # ifconfig eth0 172.16.0.1/24 up # for pktgen with an IP (TX) # ifconfig eth1 up # for pktgen without IP (RX) # arp -s 172.16.0.2 00:0c:29:f7:4d:25 # MAC of the connected DPDK port |
那么普通的
要查看数据包在
1 | # tcpdump -eni eth1 |
应该显示从 DPDK 返回的数据包。一旦你测试过了,你可以移动到
@Amedeo 描述的