DPDK程序结合网络助手接收数据

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

DPDK代码:

#include <stdio.h>
#include <string.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ip.h>
#include <rte_tcp.h>
#include <rte_udp.h>
#include <rte_mbuf.h>
#include <rte_mempool.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#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绑定的网络适配器同属于一个局域网

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DPDK(Data Plane Development Kit)是一个用于优化网络性能的软件开发工具包。它提供了一组库函数和驱动程序,可以帮助开发人员实现高性能的网络包处理应用。 DPDK的性能优化主要体现在以下几个方面: 1. 高性能数据路径:DPDK通过绕过操作系统内核来直接访问网络设备,减少了内核处理的开销,提升了数据包处理的性能。使用DPDK可以实现高达数百万数据包每秒的处理能力,大大降低了网络延迟。 2. 多核并发处理:DPDK支持多核并发处理,可以利用现代多核处理器的优势来实现更高的吞吐量。通过将不同的处理任务分配到不同的核心上,并采用无锁数据结构和锁粒度优化等技术,DPDK可以高效地实现并行处理。 3. 零拷贝技术:DPDK利用了物理内存和非统一内存访问(NUMA)架构的特性,实现了高效的零拷贝技术。通过将网络数据包直接从网络设备接收到应用程序的内存空间,避免了不必要的数据拷贝操作,减少了内存带宽的消耗,提升了数据包处理的效率。 4. 硬件加速技术:DPDK支持一些硬件加速技术,如Intel® QuickAssist 技术,可以用于加速加密、压缩等计算密集型操作。通过利用硬件加速技术,可以进一步提升网络包处理的性能。 综上所述,DPDK是一个用于优化网络性能的工具包,通过提供高性能数据路径、多核并发处理、零拷贝技术和硬件加速技术等功能,可以帮助开发人员实现高性能的网络包处理应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值