dpdk 实验代码

实验代码

代码结构图

structure


prepare.sh

前置准备工作

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
# get dpdk
# 由于链接失效,该部分跳过
#cd aux
#wget http://vmx.cs.pub.ro/~vmchecker/lib_src.zip
#unzip lib_src
#rm lib_src.zip
# 获取 DPDK 19.11.6
wget https://fast.dpdk.org/rel/dpdk-19.11.6.tar.xz
tar xJf dpdk-19.11.6.tar.xz
rm dpdk-19.11.6.tar.xz
mv dpdk-stable-19.11.6/ dpdk2
cd dpdk2
# 使用 meson + ninja 进行编译
meson build
cd build
ninja

cd ../../
wget http://vmx.cs.pub.ro/~vmchecker/dpdk3.zip
unzip dpdk3
cd dpdk3
meson build
cd build
ninja
# 挂载 hugetlbfs
if [[ ! -d /mnt/huge1G ]]; then
mkdir /mnt/huge1G
mount -t hugetlbfs -o pagesize=1G none /mnt/huge1G
fi

udp_echo.sh

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
#!/bin/bash

file_prefix=cl_tx_rx
pipeline=${1}
interval=${2}
cpufreq=${3}
file_path=${4}

generate_requests()
{
cat ${1} | grep -A10 "received/transmitted" | grep ^[0-9] | awk -v interval=${3} -F"," 'BEGIN {i=1; printf "Interval, Number of Round Trip Requests\n"; } {if (i%interval == 0)printf "%d,%lu\n", i, $3; i++;}' > ${2}
}

generate_latency()
{
cat ${1} | grep -A10 "received/transmitted" | grep ^[0-9] | awk -v interval=${3} -v frequency=${4} -F"," 'BEGIN {i=1; printf "Interval, Latency for the round trip in microseconds\n"; } {if (i%interval == 0)printf "%d,%0.04f\n", i, $1/(frequency * $3); i++;}' > ${2}
}

cl_in_file=${file_path}/${file_prefix}_${pipeline}p
printf "\n"
[[ -f ${cl_in_file} ]] || { printf "Inputfile ${cl_in_file} missing\n"; exit 1; }
cl_rqst_out_file=${cl_in_file}_rqstpersecond_out
cl_lat_out_file=${cl_in_file}_latency_out

generate_requests ${cl_in_file} ${cl_rqst_out_file} ${interval}
generate_latency ${cl_in_file} ${cl_lat_out_file} ${interval} ${cpufreq}

aux

dpdk

该文件夹为软链接,指向/aux/lib_src/dpdk。

dpdk2

该文件夹存放的是 19.11.6 版本的 DPDK 源码。

lib_src

该文件夹原本应该从链接下载,但链接失效,目前只能推测其中包含 19.08.2 版本的 DPDK 源码

libs

unikraft 中的 libs 文件夹,用于存放库文件。

unikraft

unikraft 本体代码。


server

result

Makefile.uk

在这个文件中,可以观察到每个测试分别引入了哪个文件

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
$(eval $(call addlib,apptestsuite))
ifeq ($(CONFIG_APPTESTSUITE_KERNARGS),y)
$(eval $(call addlib_paramprefix,apptestsuite,test))
endif

APPTESTSUITE_CINCLUDES-y += -I$(APPTESTSUITE_BASE)/include

APPTESTSUITE_SRCS-y += $(APPTESTSUITE_BASE)/main.c
EXTRA_LD_SCRIPT-y += $(APPTESTSUITE_BASE)/testsuite.ld

## FDT Test suite.
APPTESTSUITE_CINCLUDES-$(CONFIG_APPTESTSUITE_FDT) += -I$(UK_PLAT_DRIVERS_BASE)/include
APPTESTSUITE_CINCLUDES-$(CONFIG_APPTESTSUITE_FDT) += -I$(LIBKVMPLAT_BASE)/include
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_FDT) += $(APPTESTSUITE_BASE)/test_fdt/test_fdt.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_FDT) += $(APPTESTSUITE_BASE)/test_fdt/test.dts

## GIC Test suite.
APPTESTSUITE_CINCLUDES-$(CONFIG_APPTESTSUITE_GICV2) += -I$(UK_PLAT_DRIVERS_BASE)/include
APPTESTSUITE_CINCLUDES-$(CONFIG_APPTESTSUITE_GICV2) += -I$(LIBKVMPLAT_BASE)/include
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_GICV2) += $(APPTESTSUITE_BASE)/gicv2/test_gicv2.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_GICV2) += $(APPTESTSUITE_BASE)/gicv2/test.dts

## Adding the test for kernel arguments
## TODO: Define a Variable to separate the Unit Test case from the Functional
## tests.
## TODO: Separate Multiple makefile. Makes it easier to manage.

#APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_KERNARGS) +=\
# $(APPTESTPARAM_BASE)/test_libukparam/test_ucparam.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_KERNARGS) +=\
$(APPTESTSUITE_BASE)/test_libukparam/test_ukparam.c
APPTESTSUITE_CFLAGS-$(CONFIG_APPTESTSUITE_KERNARGS) += \
-save-temps=obj -DUK_DEBUG

APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_UC_LIBPARAM) +=\
$(APPTESTSUITE_BASE)/test_libukparam/test_ucparam.c
APPTESTSUITE_CFLAGS-$(CONFIG_APPTESTSUITE_UC_LIBPARAM) += \
-I$(CONFIG_UK_BASE)/lib/uklibparam/
APPTESTSUITE_CFLAGS-$(CONFIG_APPTESTSUITE_UC_LIBPARAM) += \
-DUK_LIBPARAM_PREFIX=apptestsuite -save-temps=obj\
-I$(CONFIG_UK_BASE)/lib/uklibparam/include -DUK_DEBUG
EXTRA_LD_SCRIPT-$(CONFIG_APPTESTSUITE_UC_LIBPARAM) += \
$(APPTESTSUITE_BASE)/test_libukparam/libparam.lds

APPTESTSUITE_SRCS-$(CONFIG_VFSCORETEST_OPEN) += \
$(APPTESTSUITE_BASE)/test_vfscore/test_open.c
APPTESTSUITE_SRCS-$(CONFIG_VFSCORETEST_STAT) += \
$(APPTESTSUITE_BASE)/test_vfscore/test_stat.c
APPTESTSUITE_SRCS-$(CONFIG_VFSCORETEST_IOCTL) += \
$(APPTESTSUITE_BASE)/test_vfscore/test_ioctl.c
APPTESTSUITE_SRCS-$(CONFIG_VFSCORETEST_MOUNT) += \
$(APPTESTSUITE_BASE)/test_vfscore/test_mount.c

APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_LOCK) += \
$(APPTESTSUITE_BASE)/test_lock/test_lock.c

APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_LDS) += \
$(APPTESTSUITE_BASE)/test_lds/test.ld

APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_LDS) += \
$(APPTESTSUITE_BASE)/test_lds/lds_test.c
APPTESTSUITE_CFLAGS-$(CONFIG_APPTESTSUITE_LDS) += -save-temps=obj

## TEST SUITE FOR NETDEVICE
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_INITTAB) += \
$(APPTESTSUITE_BASE)/test_inittab/test_inittab.c
APPTESTSUITE_CFLAGS-$(CONFIG_APPTESTSUITE_INITTAB) += -save-temps=obj

## TEST SUITE FOR NETDEVICE
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_NETDEV) += $(APPTESTSUITE_BASE)/test_netdev/test_netdev.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_UK_LWIP) += $(APPTESTSUITE_BASE)/test_lwip/test_lwip.c

## TEST SUITE FOR DPDK
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_RING) += $(APPTESTSUITE_BASE)/test_dpdk/test_ring/test_ring.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_INIT) += $(APPTESTSUITE_BASE)/test_dpdk/test_init/init.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_MEMORY) += $(APPTESTSUITE_BASE)/test_dpdk/test_memory/test_memory.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_BASIC_FWD) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/pktgen.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_BASIC_FWD) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/dev.c

APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_TXONLY) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/txonly.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_RTT) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/rtt.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_CLOSED_LOOP) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/closed_loop_latency.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_RXONLY) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/rxonly.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_CL_SERVER) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/cl_tx_rx.c
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_DPDK_UDP_ECHO) += $(APPTESTSUITE_BASE)/test_dpdk/basic_forward/udp_echo.c

## Test suite for raw netdev performance.
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_RAW_NETDEV) += $(APPTESTSUITE_BASE)/perf_netdev/main_nolwip.c

## TEST SUITE FOR STRING
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_STRTOK_R) += \
$(APPTESTSUITE_BASE)/test_string/strtok_r.c

## Test suite for mTCP
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_MTCPAPP_PERF) += $(APPTESTSUITE_BASE)/mtcp/apps/perf/client.c\

我们可以使用 make menuconfig 对测试选项进行选择

select

linux

linux guest single/batch 部分测试代码

该部分通过执行脚本来启动指定的 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/bash
if [ $( id -u ) != 0 ]; then
echo "Try to run as root..." 1>&2
exec sudo "$0" "$@"
fi

QCOW="../../aux/debian.qcow2"
MEMPATH="/mnt/huge1G/test"
TAPNAME="tap88"
BRNAME="expbr0"

TAPNAME_EXP="tap98"
BRNAME_EXP="testbr0"

set -x

# setup mgmt bridge
ip tuntap add dev $TAPNAME mode tap
ip link add $BRNAME type bridge
ip link set master $BRNAME dev $TAPNAME
ip link set promisc on dev $BRNAME
ip link set promisc on dev $TAPNAME
ip addr add 172.19.0.254/24 dev $BRNAME
ip link set dev $BRNAME up
ip link set dev $TAPNAME up

ip link set dev enp1s0f1 down
ip link add link enp1s0f1 macvtap2 type macvtap mode bridge
ip link set promisc on dev enp1s0f1
ip a a 172.18.0.1/24 dev macvtap2
ip link set promisc on dev macvtap2
ip link set dev enp1s0f1 up
ip link set macvtap2 up

my_fd=$(cat /sys/class/net/macvtap2/ifindex)

# run VM
taskset -c 4,5 qemu-system-x86_64 \
-m 6G \
-cpu host,+invtsc \
-smp cpus=2 \
-enable-kvm \
-object memory-backend-file,id=mem,size=6144M,mem-path=/mnt/linux-huge,share=on -numa node,memdev=mem \
\
-netdev tap,ifname=$TAPNAME,id=mgm0,script=no,downscript=no \
-device virtio-net-pci,netdev=mgm0 \
\
-netdev tap,fd=5,id=testtap1,vhost=on,vhostforce=on 5<>/dev/tap$my_fd\
-device virtio-net-pci,netdev=testtap1,ioeventfd=on,guest_csum=off,gso=off \
\
-hda "$QCOW" \
-display curses \
-boot c
RET=$?

# destroy network setup
ip link del macvtap2

ip link set dev $BRNAME down
ip link set dev $TAPNAME down
ip tuntap del dev $TAPNAME mode tap
ip link del $BRNAME

exit $RET

由于虚拟机的链接失效,无法执行测试。

linux_single

linux baremetal single 部分测试代码

执行 run.sh 来调用 server.c

1
2
3
4
5
6
7
8
9
10
11
12
gcc server.c -O3 -o server
sudo arp -s 172.18.0.4 a0:36:9f:52:29:D0
sudo ip a a 172.18.0.114 dev enp1s0f1
sudo ifconfig enp1s0f1 hw ether 52:54:00:12:34:57
sudo ip l set enp1s0f1 up
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo sysctl -w net.core.rmem_max=26214400
sudo sysctl -w net.core.rmem_default=26214400
taskset -c 6 ./server
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
// Driver code 
int main() {
int sockfd;
char buffer[MAXLINE];
struct sockaddr_in servaddr, cliaddr;

sockfd = socket(AF_INET, SOCK_DGRAM, 0);
assert(sockfd > 2);
int disable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) < 0) {
perror("setsockopt failed");
}

memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));

servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);

assert(bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) == 0);

int len, ret1, ret2;
init_hashmap();
len = sizeof(cliaddr);
printf("Server started \n");
while (1) {
ret1 = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
//do_processing(buffer);
ret2 = sendto(sockfd, (const char *)buffer, ret1,
0, (const struct sockaddr *) &cliaddr,
len);

assert(ret1 >= 0);
assert(ret2 >= 0);
}

return 0;
}

linux_batch

linux baremetal batch 部分测试代码

执行 run.sh 来调用 udpreceiver1.c

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
int main(int argc, const char *argv[])
{
const char *listen_addr_str = "0.0.0.0:9001";
int recv_buf_size = 4*1024;
int thread_num = 1;
int reuseport = 0;

switch (argc) {
case 4:
reuseport = atoi(argv[3]);
case 3:
thread_num = atoi(argv[2]);
case 2:
listen_addr_str = argv[1];
case 1:
break;
default:
FATAL("Usage: %s [listen ip:port] [fork cnt] [reuseport]", argv[0]);
}

struct sockaddr_in addr;
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
perror("socket()");
exit(EXIT_FAILURE);
}

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = (inet_addr("172.18.0.5"));
addr.sin_port = htons(9000);
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
}
global_sockfd = sockfd;

struct net_addr listen_addr;
parse_addr(&listen_addr, listen_addr_str);

int main_fd = -1;
if (reuseport == 0) {
fprintf(stderr, "[*] Starting udpreceiver on %s, recv buffer %iKiB\n",
addr_to_str(&listen_addr), recv_buf_size / 1024);

main_fd = net_bind_udp(&listen_addr, 0);
net_set_buffer_size(main_fd, recv_buf_size, 0);
}

struct state *array_of_states = calloc(thread_num, sizeof(struct state));

int t;
for (t = 0; t < thread_num; t++) {
struct state *state = &array_of_states[t];
state_init(state);
if (reuseport == 0) {
state->fd = main_fd;
} else {
fprintf(stderr, "[*] Starting udpreceiver on %s, recv buffer %iKiB\n",
addr_to_str(&listen_addr), recv_buf_size / 1024);

int fd = net_bind_udp(&listen_addr, 1);
net_set_buffer_size(fd, recv_buf_size, 0);
state->fd = fd;
}
thread_spawn(thread_loop, state);
}

uint64_t last_pps = 0;
uint64_t last_bps = 0;

while (1) {
struct timeval timeout =
NSEC_TIMEVAL(MSEC_NSEC(1000UL));
while (1) {
int r = select(0, NULL, NULL, NULL, &timeout);
if (r != 0) {
continue;
}
if (TIMEVAL_NSEC(&timeout) == 0) {
break;
}
}

uint64_t now_pps = 0, now_bps = 0;
for (t = 0; t < thread_num; t++) {
struct state *state = &array_of_states[t];
now_pps += __atomic_load_n(&state->pps, 0);
now_bps += __atomic_load_n(&state->bps, 0);
}

double delta_pps = now_pps - last_pps;
double delta_bps = now_bps - last_bps;
last_pps = now_pps;
last_bps = now_bps;

printf("%7.3fM pps %7.3fMiB / %7.3fMb\n",
delta_pps / 1000.0 / 1000.0,
delta_bps / 1024.0 / 1024.0,
delta_bps * 8.0 / 1000.0 / 1000.0 );
}

return 0;
}

linux_dpdk

linux guest DPDK 部分测试代码

该部分直接使用 testpmd 程序来完成

1
2
3
4
5
6
7
sudo ../../aux/dpdk2/build/app/dpdk-testpmd   -m 1024 -n 4 --proc-type=primary  -- -i

# in testpmd
#port stop all
#set fwd udpecho
#port start all
#start

unikraft_lwip

unikraft guest lwip 部分测试代码

该部分直接使用 app-httpreply 作为测试程序,并引入 lib-lwip

unikraft_raw

unikraft guest uknetdev 部分测试代码

该部分对应的测试文件夹为 perf_netdev

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
static int perf_netdev(void)
{
struct uk_alloc *a;
struct uk_netdev *dev;
struct uk_netdev_conf dev_conf;
struct uk_netdev_rxqueue_conf rxq_conf;
struct uk_netdev_txqueue_conf txq_conf;
int devid = 0;
int ret;

a = uk_alloc_get_default();
assert(a != NULL);

dev = uk_netdev_get(devid);
assert(dev != NULL);

struct uk_netdev_info info;
uk_netdev_info_get(dev, &info);
assert(info.max_tx_queues);
assert(info.max_rx_queues);

rx_headroom = (rx_headroom < info.nb_encap_rx)
? info.nb_encap_rx : rx_headroom;
tx_headroom = (tx_headroom < info.nb_encap_tx)
? info.nb_encap_tx : tx_headroom;

dev_conf.nb_rx_queues = 1;
dev_conf.nb_tx_queues = 1;
// 配置设备
/* Configure the device */
ret = uk_netdev_configure(dev, &dev_conf);
assert(ret >= 0);
// 配置队列
/* Configure the RX queue */
rxq_conf.a = a;
rxq_conf.alloc_rxpkts = netif_alloc_rxpkts;
rxq_conf.alloc_rxpkts_argp = a;
/* No threads */
#ifdef INTERRUPT_MODE
rxq_conf.callback = packet_handler;
rxq_conf.callback_cookie = NULL;
#ifdef CONFIG_LIBUKNETDEV_DISPATCHERTHREADS
rxq_conf.s = uk_sched_get_default();
assert(rxq_conf.s);
#endif /* CONFIG_LIBUKNETDEV_DISPATCHERTHREADS */
#else
rxq_conf.callback = NULL;
rxq_conf.callback_cookie = NULL;
#endif /* INTERRUPT_MODE */

ret = uk_netdev_rxq_configure(dev, 0, 0, &rxq_conf);
assert(ret >= 0);

/* Configure the TX queue*/
txq_conf.a = a;
ret = uk_netdev_txq_configure(dev, 0, 0, &txq_conf);
assert(ret >= 0);

/* GET mTU */
uint16_t mtu = uk_netdev_mtu_get(dev);
assert(mtu == 1500);

/* Start the netdev */
ret = uk_netdev_start(dev);

#ifndef INTERRUPT_MODE
ret = uk_netdev_rxq_intr_disable(dev, 0);
assert(ret >= 0);
#else
ret = uk_netdev_rxq_intr_enable(dev, 0);
assert(ret >= 0 );
#endif

struct ether_header *eth_header;
struct iphdr *ip_hdr;
while (1) {

#ifdef INTERRUPT_MODE
uk_sched_yield();
#else
packet_handler(dev, 0, NULL);
#endif
/* We echo all the packets that are in queue */

#ifdef USE_SIMPLE_QUEUE
for (int i = 0; i < k; i++) {
struct uk_netbuf *nb;
nb = queue[i];
uknetdev_output(dev, nb);
#endif

}
return 0;
}

奇怪的是,该文件在 Makefile.uk 中被引入

1
2
## Test suite for raw netdev performance.
APPTESTSUITE_SRCS-$(CONFIG_APPTESTSUITE_RAW_NETDEV) += $(APPTESTSUITE_BASE)/perf_netdev/main_nolwip.c

但在 Config.uk 文件中并没有发现 CONFIG_APPTESTSUITE_RAW_NETDEV,并且在其余的测试文件中,通常在末尾会调用 TESTSUITE_REGISTER 来将该测试函数注册,以便在 main.c 中可以顺利调用,此处并未发现该步骤。
到底跑了没 🤔

unikraft_dpdk

unikraft guest DPDK 部分测试代码

推测测速相关代码位于 cl_tx_rx.c 中

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
static int test_tx_rx(int argc, char *argv[])
{
struct rte_mempool *mbuf_pool;
unsigned nb_ports;
uint16_t portid, first_portid = 0xff;
int i;
int pkt_in_flight = CONFIG_INPIPELINE;

#if 0
/* Application args process */
int ret = test_app_args(argc, argv);
#endif

/* Initialize the Environment Abstraction Layer (EAL). */
int ret = rte_eal_init(argc, argv);
if (ret < 0)
UK_CRASH("Error with EAL initialization\n");

argc -= ret;
argv += ret;

/* Check that there is an even number of ports to send/receive on. */
nb_ports = rte_eth_dev_count_avail();
printf("%d number of ports detected Pool Size: %d\n", nb_ports,
RTE_MBUF_DEFAULT_BUF_SIZE);

/* Creates a new mempool in memory to hold the mbufs. */
mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());

/* Initialize all ports. */
RTE_ETH_FOREACH_DEV(portid) {
if (first_portid == 0xff)
first_portid = portid;
if (port_init(portid, mbuf_pool) != 0)
UK_CRASH("Cannot init port %"PRIu16 "\n",
portid);
}

tx_pkt_setup(arg_src_ipv4_addr, arg_dst_ipv4_addr,
arg_src_port, arg_dst_port);

if (rte_lcore_count() > 1)
printf("\nWARNING: Too many lcores enabled. Only 1 used.\n");

/* Call lcore_main on the master core only. */
i = 0;
int tx_count = 0, total_tx_count = 0;
int rx_count = 0, total_rx_count = 0;
uint64_t start_tsc = rte_rdtsc();
uint64_t curr_tsc;
uint64_t latency;
uint64_t j = 0;
int cnt = CONFIG_INPIPELINE;
uint64_t exp_start = start_tsc, exp_curr, dur = 0;
#if 0
pkt_burst_transmit_cnt(first_portid, mbuf_pool, 1, 0);
int rc = pkt_burst_receive_arp(first_portid, mbuf_pool, 0);
#endif
pkt_stats.rxpkt_dropped[0] = 0;
do {
while (dur < arg_exp_end_time) {
if (cnt > 0) {
tx_count = pkt_burst_transmit_cnt(first_portid, mbuf_pool, cnt, j);
pkt_stats.total_txpkts_pps[j] += tx_count;
pkt_stats.txburst_itr[j]++;
cnt -= tx_count;
}
int rc = pkt_burst_receive_cnt(first_portid, mbuf_pool, j);
if (unlikely(rc == -1)) {
/**
* Resetting the pipeline because packet loss.
*/
rx_count = 0;
pkt_stats.rxpkt_dropped[j] += CONFIG_INPIPELINE;
cnt += CONFIG_INPIPELINE;
} else {
rx_count = rc;
pkt_stats.total_rxpkts_pps[j] += rc;
cnt += rx_count;
}
/* Send the remaining packet */
curr_tsc = rte_rdtsc();
dur = curr_tsc - exp_start;

if (curr_tsc - start_tsc > arg_stat_timer) {
pkt_stats.total_rxpkts += pkt_stats.total_rxpkts_pps[j];
pkt_stats.total_txpkts += pkt_stats.total_txpkts_pps[j];
j++;
if (j == arg_print_itr) {
/* Print stat Computation */
dump_stats(j);
j = 0;
}
/* Resetting the tx count */
pkt_stats.total_txpkts_pps[j] = 0;
pkt_stats.total_rxpkts_pps[j] = 0;
pkt_stats.latency[j] = 0;
pkt_stats.rxburst_itr[j] = 0;
pkt_stats.txburst_itr[j] = 0;
pkt_stats.total_txpkts_tries_pps[j] = 0;
pkt_stats.total_txpkts_tries_dropped[j] = 0;
pkt_stats.total_txpkts_tries_ra_pps[j] = 0;
pkt_stats.total_txpkts_alloc_failed[j] = 0;
pkt_stats.txpkt_xmit_cycles[j] = 0;
pkt_stats.txpkt_gen_cycles[j] = 0;
pkt_stats.txpkt_buf_cycles[j] = 0;
pkt_stats.rxpkt_recv_cycles[j] = 0;
pkt_stats.rxpkt_zrecv_cycles[j] = 0;
pkt_stats.rxpkt_process_cycles[j] = 0;
pkt_stats.rxpkt_buf_free[j] = 0;
pkt_stats.rxpkt_dropped[j] = 0;

/* Restart a new cycle */
start_tsc = rte_rdtsc();
}
}
exp_start = rte_rdtsc();
dur = 0;
} while (1);
return 0;
}

client

prepare.sh

完成 client 端编译工作的脚本

1
2
3
4
5
6
7
8
echo "Building the unikraft image with dpdk"
cd unikraft/uk_test_suite/ && make fetch
cd build/libukdpdkbuild/origin/
rm -rf dpdk-19.08
ln -s ../../../../../../aux/lib_src/dpdk/ dpdk-19.08
cd ../../..
make -j12
cd ../../

run_vhost.sh

启动 vhost 的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装内核模块
sudo modprobe ixgbe
sudo modprobe uio_pci_generic
# 会造成SSH断连,注释掉
# sudo ip a flush enp1s0f0
# 调用DPDK提供的bind来办顶网卡,需要使用ifconfig查看信息后对应修改
sudo python3 ../aux/dpdk/usertools/dpdk-devbind.py --bind=uio_pci_generic ens160
# 启动testpmd
sudo ../aux/dpdk2/build/app/dpdk-testpmd -l 2,3 -n 4 --vdev 'eth_vhost0,iface=vhost-net,queues=1' -- -i --txd=1024 --rxd=1024 --nb-cores=1 --eth-peer=0,52:54:00:12:34:57

# we run in the vhost
# port stop all
# set fwd mac
# port start all
# start

unirkaft/uk_test_suit

测试代码主体部分。