网络调试工具:https://download.csdn.net/download/hdsHDS6/88390999?spm=1001.2014.3001.5503

DPDK代码:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define NB_MBUF 512
- #define MAX_PKT_BURST 32
- #define SELF_PROTO_TYPE 0x0888
- static struct rte_eth_conf port_conf = {
- .rxmode = {
- .split_hdr_size = 0
- }
- };
- // cat /proc/interrupts
- void init_port(struct rte_mempool *mbuf_pool){
- uint16_t nb_ports = 0;
- int ret = 0;
- int portid = 0;
- struct rte_eth_dev_info dev_info;
- struct rte_ether_addr addr;
- const int num_rx_queues = 1;
- const int num_tx_queues = 0;
- nb_ports = rte_eth_dev_count_avail();
- if(nb_ports == 0){
- rte_exit(EXIT_FAILURE, "No support eth found\n");
- }
- for(portid = 0; portid < nb_ports; portid++){
- ret = rte_eth_macaddr_get(portid, &addr);
- if (ret != 0){
- rte_exit(EXIT_FAILURE, "macaddr get failed\n");
- }
- printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
- " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
- portid, RTE_ETHER_ADDR_BYTES(&addr));
- ret = rte_eth_dev_info_get(portid, &dev_info);
- ret = rte_eth_dev_configure(portid, num_rx_queues, num_tx_queues, &port_conf);
- ret = rte_eth_rx_queue_setup(portid, 0, 128, rte_eth_dev_socket_id(portid), NULL, mbuf_pool);
- ret = rte_eth_dev_start(portid);
- if (ret < 0) {
- rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", ret, portid);
- }
- }
- }
- /*
- 发送方注意设置LP信息
- */
- int
- main(int argc, char **argv)
- {
- int ret;
- unsigned lcore_id;
- int i = 0;
- int portid = 0;
- int nb_rx = 0;
- /* 初始化环境 */
- ret = rte_eal_init(argc, argv);
- if (ret < 0)
- rte_panic("Cannot init EAL\n");
- /* 创建内存池 */
- struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("my pool", NB_MBUF, 32, 0,
- RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
- if (mbuf_pool == NULL){
- return -1;
- }
- init_port(mbuf_pool);
- while(1){
- struct rte_mbuf* pkts_burst[MAX_PKT_BURST];
- nb_rx = rte_eth_rx_burst(portid, 0, pkts_burst, MAX_PKT_BURST);
- if(nb_rx == 0){
- sleep(1);
- continue;
- }
- // printf("recv data start : %d \n", nb_rx);
- for(i = 0; i < nb_rx; i++){
- // ether
- struct rte_ether_hdr *hdr = rte_pktmbuf_mtod(pkts_burst[i], struct rte_ether_hdr *);
- // ip
- // printf("ether_type = %x \n", hdr->ether_type);
- if(hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)){
- struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(pkts_burst[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
- // upd
- if(iphdr->next_proto_id == IPPROTO_UDP){
- // (struct rte_udp_hdr *)RTE_PTR_ADD(iphdr, sizeof(struct rte_ipv4_hdr));
- struct rte_udp_hdr* udphdr = (struct rte_udp_hdr*)(iphdr + 1);
- uint16_t length = ntohs(udphdr->dgram_len);
- *(char*)(udphdr + length) = '\0';
- struct in_addr addr;
- addr.s_addr = iphdr->src_addr;
- printf("src:%s:%d \n", inet_ntoa(addr), ntohs(udphdr->src_port));
- addr.s_addr = iphdr->dst_addr;
- printf("dst:%s:%d, %s \n", inet_ntoa(addr), ntohs(udphdr->dst_port), (char*)(udphdr+1));
- }else if(iphdr->next_proto_id == IPPROTO_TCP){
- struct rte_tcp_hdr* tcphdr = (struct rte_tcp_hdr*)(iphdr + 1);
- struct in_addr addr;
- addr.s_addr = iphdr->src_addr;
- printf("src:%s:%d \n", inet_ntoa(addr), ntohs(tcphdr->src_port));
- addr.s_addr = iphdr->dst_addr;
- printf("dst:%s:%d, date = %s \n", inet_ntoa(addr), ntohs(tcphdr->dst_port), (char*)(tcphdr+1));
- }
- }else if(hdr->ether_type == rte_cpu_to_be_16(SELF_PROTO_TYPE)){
- char *data = rte_pktmbuf_mtod_offset(pkts_burst[i], char *, sizeof(struct rte_ether_hdr));
- printf("recv data: %s \n", data);
- }
- rte_pktmbuf_free(pkts_burst[i]);
- }
- }
- return 0;
- }
Makefile文件
- # SPDX-License-Identifier: BSD-3-Clause
- # Copyright(c) 2010-2014 Intel Corporation
-
- # binary name
- APP = recv
-
- # all source are stored in SRCS-y
- SRCS-y := main.c
-
- PKGCONF ?= pkg-config
-
- # Build using pkg-config variables if possible
- ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
- $(error "no installation of DPDK found")
- endif
-
- all: shared
- .PHONY: shared static
- shared: build/$(APP)-shared
- ln -sf $(APP)-shared build/$(APP)
- static: build/$(APP)-static
- ln -sf $(APP)-static build/$(APP)
-
- PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
- CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
- # Add flag to allow experimental API as l2fwd uses rte_ethdev_set_ptype API
- CFLAGS += -DALLOW_EXPERIMENTAL_API
- LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
- LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
-
- ifeq ($(MAKECMDGOALS),static)
- # check for broken pkg-config
- ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
- $(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
- $(error "Cannot generate statically-linked binaries with this version of pkg-config")
- endif
- endif
-
- build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
- $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
-
- build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
- $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
-
- build:
- @mkdir -p $@
-
- .PHONY: clean
- clean:
- rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
- test -d build && rmdir -p build || true
虚拟机设置
网络适配器2和3用于DPDK的绑定,并设置为桥接模式,使两个网口与物理机处于同一局域网

编译:

加载驱动绑定网卡:
- #! /bin/bash
-
- eth1=$1
- eth2=$2
- DPDK_PATH=$3
- DPDK_KMOD_PATH=$4
- if [ -z "$DPDK_PATH" ];then
- DPDK_PATH="/root/dpdk-22.07/usertools"
- fi
-
- if [ -z "$DPDK_KMOD_PATH" ];then
- DPDK_KMOD_PATH="/root/dpdk-22.07/kmod"
- fi
-
- # 关闭网口
- ifconfig $eth1 down
- ifconfig $eth2 down
-
- # 大页
- echo 512 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
-
- # 加载uio驱动
- modprobe uio
- insmod $DPDK_KMOD_PATH/igb_uio.ko intr_mode=legacy
- # 加载kni驱动
- insmod $DPDK_KMOD_PATH/rte_kni.ko kthread_mode=multiple
-
- # 绑定网口
- $DPDK_PATH/dpdk-devbind.py -b igb_uio "$eth1" "$eth2"
- $DPDK_PATH/dpdk-devbind.py -s

运行:

可以获取到端口1的MAC地址,因为在代码中是端口1在接收数据
windows上设置静态IP与MAC的映射
命令:
netsh i i show in

添加静态IP与MAC的映射
命令:
netsh -c "i i" add neighbors 16 "192.168.1.7" "00-0c-29-c3-b0-c0"
arp -a


利用网络调试工具发送UDP数据:
本地主机地址要与DPDK绑定的网络适配器同属于一个局域网
