最简单的dpdk udp程序

 

记录一下测试dpdk udp收发的程序,程序很简单,从网卡收到ipv4 udp包后,将udp包回传给源

  1. export 两个dpdk环境变量
    export RTE_SDK=/root/dpdk-19.11
    export RTE_TARGET=x86_64-native-linuxapp-gcc
  2. 设置好环境(安装驱动/大页/配置端口)
    可参考dpdk个人学习使用全过程_地上一个猴的博客-优快云博客_dpdk教程
  3. 参考其他示例的makefile,写一个                                                  
  4. 写代码(send.c),编译
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <rte_eal.h>
    #include <rte_ethdev.h>
    #include <rte_mbuf.h>
    
    #define NUM_MBUFS		(4096-1)
    #define MBUFS_SIZE		32
    #define ENABLE_SEND		1
    
    uint16_t port_id = 0;
    
    
    
    #if ENABLE_SEND
    
    static uint32_t gSrcIp; 
    static uint32_t gDstIp;
    
    static uint8_t gSrcMac[RTE_ETHER_ADDR_LEN];
    static uint8_t gDstMac[RTE_ETHER_ADDR_LEN];
    
    static uint16_t gSrcPort;
    static uint16_t gDstPort;
    
    #endif
    
    
    
    static const struct rte_eth_conf port_conf_default = {
    	.rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN }
    };
    
    static void init_port(struct rte_mempool *mbufpool)
    {
    	/*Get the number of ports which are usable for the application.*/
    	uint16_t sys_port = rte_eth_dev_count_avail();
    	if(sys_port == 0){
    		rte_exit(EXIT_FAILURE, "Not available eth\n");
    	}
    
    	/*Get ethernet information*/
    	struct rte_eth_dev_info dev_info;
    	rte_eth_dev_info_get(port_id, &dev_info);
    
    	/*Configure an Ethernet device*/
    	uint16_t nb_rx_q = 1;
    	uint16_t nb_tx_q = 1;
    	struct rte_eth_conf dev_conf = port_conf_default;
    	rte_eth_dev_configure(port_id, nb_rx_q, nb_tx_q, &dev_conf);
    
    	/*Allocate and set up a receive queue for an Ethernet device*/
    	uint16_t rx_queue_id = nb_rx_q - 1;
    	unsigned int socket_id = rte_eth_dev_socket_id(port_id);
    	if(rte_eth_rx_queue_setup(port_id, rx_queue_id, 1024, socket_id, NULL, mbufpool) < 0)
    		rte_exit(EXIT_FAILURE, "Receive queue error\n");
    		
    #if ENABLE_SEND
    	/*Allocate and set up a transmit queue for an Ethernet device*/
    	struct rte_eth_txconf txq_conf = dev_info.default_txconf;
    	txq_conf.offloads = dev_conf.rxmode.offloads;
    	if (rte_eth_tx_queue_setup(port_id, 0 , 1024, socket_id, &txq_conf) < 0)
    		rte_exit(EXIT_FAILURE, "Could not setup TX queue\n");
    
    #endif
    
    	/*Start an Ethernet device*/
    	if(rte_eth_dev_start(port_id) < 0)
    		rte_exit(EXIT_FAILURE, "Start ethernet error\n");
    
    }
    
    
    
    int main(int argc, char **argv)
    {
        unsigned int i =0;
        //uint8_t   au8SendMsg[] = "hello misss";
        
    	/*init*/
    	if(rte_eal_init(argc, argv) < 0)
    		rte_exit(EXIT_FAILURE, "EAL init Error\n");
    
    	/*create a mbuf pool*/
    	struct rte_mempool *mbufpool = rte_pktmbuf_pool_create("mbufpool", NUM_MBUFS, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
    	if(mbufpool == NULL)
    		rte_exit(EXIT_FAILURE, "Create mbufpool Error\n");
    
    	/*init port*/
    	init_port(mbufpool);
    
    
        rte_eth_macaddr_get(port_id, (struct rte_ether_addr *)gSrcMac);
    
    	while(1){
    		struct rte_mbuf *rx_pkts[MBUFS_SIZE];
    		/*Retrieve a burst of input packets from a receive queue of an Ethernet device*/
    		unsigned num_recv = rte_eth_rx_burst(port_id, 0, rx_pkts, MBUFS_SIZE);
    		if(num_recv > MBUFS_SIZE)
    			rte_exit(EXIT_FAILURE, "Receive from eth error\n");
    
    		for(i = 0; i < num_recv; i++){
                
    			struct rte_ether_hdr *ehdr  = rte_pktmbuf_mtod(rx_pkts[i], struct rte_ether_hdr*);
    			if (ehdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
    				rte_pktmbuf_free(rx_pkts[i]);
    				continue;
    			}
    			
    			struct rte_ipv4_hdr *iphdr =  rte_pktmbuf_mtod_offset(rx_pkts[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
    			if (iphdr->next_proto_id == IPPROTO_UDP) {
    				/*IPPROTO_UDP is defined in kernel source code include/uapi/inux/in.h*/
    
    				struct rte_udp_hdr *udphdr = (struct rte_udp_hdr *)(iphdr + 1);
    
    #if ENABLE_SEND
    
    				//rte_eth_macaddr_get(port_id, (struct rte_ether_addr *)gSrcMac);
    				rte_memcpy(gDstMac, ehdr->s_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
    								
    				rte_memcpy(&gSrcIp, &iphdr->dst_addr, sizeof(uint32_t));
    				rte_memcpy(&gDstIp, &iphdr->src_addr, sizeof(uint32_t));
                    
    				rte_memcpy(&gSrcPort, &udphdr->dst_port, sizeof(uint16_t));
    				rte_memcpy(&gDstPort, &udphdr->src_port, sizeof(uint16_t));
    			
    #endif
    
    				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, ", inet_ntoa(addr), udphdr->src_port);
    				addr.s_addr = iphdr->dst_addr;
    				printf("dst: %s:%d, %s\n", inet_ntoa(addr), udphdr->dst_port, (char *)(udphdr+1));
    				
    #if ENABLE_SEND
                    //20220926add
                    rte_memcpy(&iphdr->src_addr, &gSrcIp, sizeof(uint32_t));
                    rte_memcpy(&iphdr->dst_addr, &gDstIp, sizeof(uint32_t));
                    addr.s_addr = iphdr->src_addr;
    				printf("-> src: %s:%d, ", inet_ntoa(addr), udphdr->src_port);
    				addr.s_addr = iphdr->dst_addr;
    				printf("dst: %s:%d, %s\n", inet_ntoa(addr), udphdr->dst_port, (char *)(udphdr+1));
    
                    rte_memcpy(ehdr->s_addr.addr_bytes, gSrcMac, RTE_ETHER_ADDR_LEN);
                    rte_memcpy(ehdr->d_addr.addr_bytes, gDstMac, RTE_ETHER_ADDR_LEN);
                    
    				//调测增加,实际使用可去掉端口限制
                    if (4369 == udphdr->src_port)
                    {
        				rte_eth_tx_burst(port_id , 0, rx_pkts, num_recv);
      								
                    }
    #endif
    				rte_pktmbuf_free(rx_pkts[i]);
    			}
    		}
    	}
    }
    
    

     

  5. Windows本地添加静态地址
    运行管理员cmd,其中ip地址为自定义,不与局域网冲突即可,mac地址必须正确,是配置给dpdk的网卡地址。
    netsh -c i i add neighbors 12  "10.180.147.55" "00-0c-29-88-c1-9a"
  6. 打开网络调试助手网络调试助手下载_网络调试助手绿色版免费下载-华军软件园
    填写正确的本地ip,连接后填写刚才添加的目标主机地址
  7. windows发送消息到dpdk,udp将消息传回windows

 

 文章参考:[4].dpdk实现udp协议发送数据_u.意思的博客-优快云博客_dpdk udp

 

         

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值