在DPDK RX / TX回调示例应用程序中没有流量出现

时间:2018-09-11 13:46:29

标签: dpdk

我是DPDK领域的新生。我从DPDK主页给出的示例应用程序开始。我陷入了示例--- DPDK RX/TX Callbacks Sample Application。条件是很长一段时间内没有流量出现(但仍为输出)。我想原因是我无法将流量发送到DPDK端口。

我首先逐步展示我的设置。开头的网卡信息

NIC info at startup

然后,我用{p>拒绝eth2eth3

sudo ifconfig eth2 down
sudo ifconfig eth3 down

接下来,使用usertools/dpdk-setup.sh构建DPDK源(i686-native-linuxapp-gcc),插入IGB UIO模块,为非NUMA系统设置大页面映射,将设备绑定到IGB UIO模块。这是我的设备设置和大页面列表: device uio bind hugepage info

所有准备工作都已完成。我开始构建示例应用程序。使用以下命令

export RTE_SDK=~/dpdk/dpdk-18.08
export RTE_TARGET=i686-native-linuxapp-gcc
cd examples/rxtx_callbacks/
make

一切都很好,并输出编译信息:

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

然后,我开始使用以下命令运行示例应用程序:

sudo ./build/rxtx_callbacks -l1 -n4

执行日志为:

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

随着时间的流逝,什么也没有发生。但是,我发现执行结果应该是这样的:

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

我尝试查找结果,我在printf函数中添加了lcore_main(),如下所示:

for (;;) {
        RTE_ETH_FOREACH_DEV(port) {
                struct rte_mbuf *bufs[BURST_SIZE];
                /* printf("receive a packet\n"); */
                const uint16_t nb_rx = rte_eth_rx_burst(port, 0,
                                bufs, BURST_SIZE);
                if (unlikely(nb_rx == 0))
                        continue;
                printf("send a packet\n");
                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]);
                }
        }
}

我发现没有收到数据包,因为它应该通过了检查--- if (unlikely(nb_rx == 0))。因此,我尝试使用 Linux (NOT DPDK)提供的pktgen自己发送数据包。但是失败。我将展示自己的足迹。

#!/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层工具(如ping)是无用的。该示例应用程序一直都处于停滞状态,我感到绝望。您能分享一些解决我问题的想法吗?

最良好的祝愿。

EDIT1:

@Amedeo的答复是可行的,但是,我只能够向RX / TX回调应用程序发送一些数据包(几个数据包不是流量)。我尝试使用 Linux 提供的pktgen,但是接口dtap0 无法接收pktgen生成的流量。以下是我的实验课程。

首先,所有准备工作均与上述相同。但是,我使用命令运行示例应用程序

 sudo ./build/rxtx_callbacks -l1 -n4 --vdev=net_tap0

而不是

 sudo ./build/rxtx_callbacks -l1 -n4

运行示例应用程序后,我可以在ifconfig中看到一个新的nic项目。 enter image description here

哦,我需要指出的是,我已经拒绝了eth1,因此eth1eth2eth3供DPDK使用。执行输出如下:

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]

带有fe 02 cf 5a 23 ee端口3 恰好是dtap0中的ifconfig网卡。现在,我尝试将流量注入dtap0界面。但是,我尝试使用 Linux 提供的pktgen,但仍然失败。

我首先使用以下命令为接口dtap0提供一个IP地址:

sudo dhclient dtap0

并获得:

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脚本以生成从eth0dtap0的流量负载(我希望如此)。这是脚本。

#!/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"

运行此脚本,我真的发现接口eth0正在产生输出数据包(使用nloadifconfig)。但是,接口dtap0没有传入流量。我也尝试使用iperf发送流量,但是dtap0无法处理TCP连接或UDP ACK。 iperfping都不可用。

感谢您分享有关我的问题的任何想法。

EDIT2:

感谢@Amedeo的分享。我已经弄清楚了如何使用 Linux 提供的pktgen将数据包发送到RX/TX Callback示例应用程序。

用于运行RX/TX Callback示例应用程序的所有内容均与 EDIT1 相同。我将pktgen的脚本更改如下:

#!/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中发送出去!还有

dtap0 --- dpdk port --- rxtx_callbacks 

一切正常。

1 个答案:

答案 0 :(得分:2)

预计您不会看到路况。 RX / TX回调示例是L2FWD示例的概括。此代码从一个端口接收流量,并将其转发到另一个端口。 如果没有传入流量,则该应用程序将永远进行轮询,试图接收某些内容并且不会转发任何内容。

由于2个端口正在使用DPDK驱动程序,因此内核看不到它们。因此,常用工具(ifconfig,tcpdump,pktgen等)看不到这些接口。

您只能将dpdk绑定到一个物理接口,并将tap接口用作第二个接口。 tap接口绑定到内核,因此您可以轻松地向其中注入流量(例如,使用tcpreplay)。

要使用点击界面,您只需添加参数sudo ./build/rxtx_callbacks -l1 -n4 --vdev=net_tap0

dtap0

这将创建一个从ifconfig可见的接口dtap0 --- dpdk port --- rxtx_callbacks --- dpdk port --- dtap1 。 rxtx_callbacks应用程序将接收进入此接口的所有流量,并将其转发到另一个物理端口。

来源:https://doc.dpdk.org/guides/nics/tap.html

端到端实验

您还可以删除所有dpdk物理端口,仅使用2个TAP端口。 通过这种方式,您可以:

sudo ./rxtx_callbacks -l1 -n4 --vdev=net_tap0 --vdev=net_tap1

,两个TAP可以通过rxtx_callbacks应用程序相互ping通。

重现此步骤的步骤是:

1)从DPDK取消绑定所有物理接口

2)使用2个TAP运行rxtx_callbacks:

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

3)现在您有2个TAP接口:dtap0和dtap1。将dtap1移至其他网络名称空间,并将IP分配给dtap0和dtap1:

sudo ping 11.0.0.2
sudo ip netns exec ns1 ping 11.0.0.1

4)您可以从dtap0 ping dtap1(反之亦然):

sudo ip netns exec ns1 ip link set dtap1 netns 1
sudo ip netns del ns1

5)清理:将dtap1移至默认名称空间并删除该名称空间。

for i in animals:
    for j in i:
        print(j)