1.搭建dpdk环境
(1).检测虚拟机是否支持多队列,使用ifconfig命令查看网卡信息,如果是ens33,需要将ens33转为eth0。
为什么需要多队列网卡,因为dpdk需要多队列网卡,单网卡只有一个中断,多队列网卡有多个中断,dpdk可以同时处理多个中断,增加吞吐量
(2).修改完成后查看网卡中断,命令cat /proc/interrupts | grep eth0,如果不是下图这种情况,需要进行第三步修改vmx文件
(3).如果不支持修改对应的vmx文件,修改前关闭虚拟机
(4).上述完成以后,接下来配置巨页,使用命令vim /etc/default/grub,添加这三句
default_hugepagesz=1G hugepagesz=2M hugepages=1024
物理机和虚拟机存在差异
(5).下载dpdk : https://core.dpdk.org/download/
下载完成以后进入dpdk目录使用命令
根据机器选择编译类型,我是本机编译然后本机运行选择带native的,如果不修改dpdk源码选择36,否则选39.
(6).接下来执行43,44,45,46,47,49,46和47设置巨页时选择512,选择49时eth0如果还是活跃状态需要关掉ifconfig eth0 down,执行完毕后,环境配置完成。每次重启系统需要重新执行一遍上述设置
(7).设置dpdk环境变量,根据自己的具体目录修改/home/dpdk,每次重启需要重新设置
# export RTE_SDK=/home/dpdk
2.dpdk使用UDP接收数据
(1).编译方式,使用makefile文件编译,Makefile复制于cp ../dpdk-stable-19.08.2/examples/helloworld/Makefile ./
# binary name
APP = helloworld
# all source are stored in SRCS-y
SRCS-y := main.c
(2).代码
#include <stdio.h>
#include <unistd.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_mbuf.h>
#include <arpa/inet.h>
#define NUM_MBUFS 4096
#define BURST_SIZE 128
int global_portid = 0;
static const struct rte_eth_conf port_conf_default = {
.rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN}
};
static int ustack_init_port(struct rte_mempool *mbuf_pool)
{
uint16_t nb_sys_ports = rte_eth_dev_count_avail();
if(nb_sys_ports == 0)
{
rte_exit(EXIT_FAILURE, "No Support eth found\n");
}
const int num_rx_queues = 1;
const int num_tx_queues = 0;
rte_eth_dev_configure(global_portid, num_rx_queues, num_tx_queues, &port_conf_default);
//创建一个global_portid网卡,0位置的128的mbuf队列
if(rte_eth_rx_queue_setup(global_portid, 0, 128, rte_eth_dev_socket_id(global_portid), NULL, mbuf_pool) < 0)
{
rte_exit(EXIT_FAILURE, "Could not setup RX queue\n");
}
if(rte_eth_dev_start(global_portid) < 0)
{
rte_exit(EXIT_FAILURE, "Could not start\n");
}
return 0;
}
int main(int argc, char* argv[])
{
//检测网卡信息
if(rte_eal_init(argc, argv) < 0)
rte_exit(EXIT_FAILURE, "Error with EAL init\n");
//创建一个mbuf用于接收
struct rte_mempool *mbuf_pool = rte_pktmbuf_pool_create("mbuf pool", NUM_MBUFS, 0, 0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); //rte_socket_id()为内存id
if(!mbuf_pool)
{
rte_exit(EXIT_FAILURE, "Could not create mbuf pool\n");
}
ustack_init_port(mbuf_pool);
while(1)
{
//解析收到的数据
struct rte_mbuf *mbufs[BURST_SIZE] = {0};
uint16_t nb_recvd = rte_eth_rx_burst(global_portid, 0, mbufs, BURST_SIZE);
if(nb_recvd > BURST_SIZE)
{
rte_exit(EXIT_FAILURE, "ERRor receiving from eth\n");
}
int i = 0;
for(i = 0; i < nb_recvd; i++)
{
//获取以太网头
struct rte_ether_hdr *ethhdr = rte_pktmbuf_mtod(mbufs[i], struct rte_ether_hdr *);
if(ethhdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
{
continue;
}
//获取ip头
struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(mbufs[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
if(iphdr->next_proto_id == IPPROTO_UDP)
{
struct rte_udp_hdr *udphdr = (struct rte_udp_hdr*)(iphdr+1);
printf("udp:%s\n", (char*)(udphdr+1));
}
}
}
printf("hello dpdk!\n");
return 0;
}
(3).设置静态arp,在windows命令行输入命令
netsh -c i i add neighbors 16 192.168.2.66 00-0c-29-18-ef-9d
ip地址为dpdk网卡的ip,后面的是对应的mark地址
然后就可以测试dpdk接收数据了