DPDK简单案例

        由于资源有限,笔者所选的DPDK环境为虚拟机。虚拟机搭建DPDK的教程网上较多,这里就不再赘述,下来主要说一下在学习过程中遇到的问题。

        通过B站看到铃声学院King老师一个关于DPDK接收数据100行代码实现视频,饶有兴趣的去听了一下,然后自己也跟着实现了代码。DPDK环境是在虚拟机搭建的,DPDK自带的example中的helloworld也能跑成功,但是我自己实现的代码可以成功编译,就是收不到网卡的数据。这个问题让我纠结了好几天,刚开始一直以为是我环境的问题,重新搭建了N个虚拟机版本,问题还是存在。我都要快放弃了,最后通过前同事(之前搞过DPDK)的帮忙,还是代码的问题,在初始化环境的时候少调用接口,加了代码后就成功收到网卡的数据包了。这件事也让我懂得了只要坚持,好运总会眷顾你,嘿嘿嘿!话不多说,直接上代码。

        DPDK代码简单如下:

#include <rte_eal.h>
#include <rte_ether.h>
#include <rte_ethdev.h>

#include <stdio.h>
#include <arpa/inet.h>

#define PRINT_MAC(addr)		printf("%02"PRIx8":%02"PRIx8":%02"PRIx8 \
		":%02"PRIx8":%02"PRIx8":%02"PRIx8,	\
		addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], \
		addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5])


#define NUM_BUFS	(4096 - 1)
#define BURST_SIZE	128

void init_port(struct rte_mempool *mbuf_pool);

int gDpdkPortId = 0;

static struct rte_eth_conf dev_conf_default = {
	.rxmode = {
		.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
	},
};

void init_port(struct rte_mempool *mbuf_pool)
{
	uint16_t nb_ports = rte_eth_dev_count_avail();
	if(nb_ports == 0)
	{
		rte_exit(EXIT_FAILURE, "No Support eth found\n");
	}

#if 0	
	struct rte_eth_dev_info devinfo;
	rte_eth_dev_info_get(gDpdkPortId, &devinfo);
#endif

	const int num_rx_queues = 1;
	const int num_tx_queues = 1;
	int ret = rte_eth_dev_configure(gDpdkPortId, num_rx_queues, num_tx_queues, &dev_conf_default);
	if (ret < 0) {
		rte_exit(EXIT_FAILURE, ":: cannot configure device: err=%d\n", ret);
	}
	
	ret = rte_eth_rx_queue_setup(gDpdkPortId, 0, 128, rte_eth_dev_socket_id(gDpdkPortId), NULL, mbuf_pool);
	if(ret < 0){
		rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup failed\n");
	}
	
	ret = rte_eth_tx_queue_setup(gDpdkPortId, 0, 128, rte_eth_dev_socket_id(gDpdkPortId), NULL);
	if (ret < 0)
	{
		rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup failed\n");	
	}
	
	ret  = rte_eth_dev_start(gDpdkPortId);
	if (ret < 0)
	{
		rte_exit(EXIT_FAILURE, "rte_eth_dev_start failed\n");		
	}
	
	struct rte_ether_addr addr;
	rte_eth_macaddr_get(gDpdkPortId, &addr);
	PRINT_MAC(addr);
}

int main(int argc, char *argv[])
{
	if(rte_eal_init(argc, argv) < 0)
	{
		rte_exit(EXIT_FAILURE, "Error with eal init\n");
	}
	
	struct rte_mempool * mbuf_pool = rte_pktmbuf_pool_create("mbuf pool", NUM_BUFS, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
	
	if(mbuf_pool == NULL)
	{
		rte_exit(EXIT_FAILURE, "mempool creat failed\n");
	}
	
	init_port(mbuf_pool);
	
	while(1)
	{
		struct rte_mbuf *mbufs[BURST_SIZE];
		unsigned num_recvd = rte_eth_rx_burst(gDpdkPortId, 0, mbufs, BURST_SIZE);
		
		if(num_recvd > BURST_SIZE)
		{
			rte_exit(EXIT_FAILURE, "rte_eth_rx_brust failed\n");
		}
		
		if(num_recvd == 0)
			continue;
		
		unsigned i = 0;
		for(i = 0; i < num_recvd; i++)
		{
			struct rte_ether_hdr *ehdr = rte_pktmbuf_mtod(mbufs[i], struct rte_ether_hdr *);
			
			if(ehdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
			{
				struct rte_ipv4_hdr *iphdr = rte_pktmbuf_mtod_offset(mbufs[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
				
				struct rte_udp_hdr *udphr = (struct rte_udp_hdr *)(iphdr + 1);
				
				if(iphdr->next_proto_id == IPPROTO_UDP && ntohs(udphr->dst_port) == 12345)
				{
					uint16_t length = ntohs(udphr->dgram_len);
					*(char *)(udphr + length) = '\0';
					
					struct in_addr addr;
					addr.s_addr = iphdr->src_addr;
					printf("src: %s:%d,", inet_ntoa(addr), ntohs(udphr->src_port));
					
					addr.s_addr = iphdr->dst_addr;
					printf("dst: %s:%d, data:%s\n", inet_ntoa(addr), ntohs(udphr->dst_port), (char *)(udphr + 1));
				}
			}
		}
	}
	
	return 0;
}

        Makefile就是用dpdk自带example中helloworld的Makefile修改一下源文件名跟生成目标文件即可。

         注:dpdk网卡需要收到数据,必须在本地绑定一条静态路由(管理员权限),命令如下:

        绑定静态路由成功如下:

        程序执行结果:

 终于大功告成!这几天的辛苦也算值得了。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值