DPDK(F-Stack) 实现UDP通信

因刚开始学习DPDK,在学习过程中了解到需使用用户态协议栈,在网上找到F-Stack的相关介绍,但是缺乏DPDK的相关知识,导致使用F-Stack 时UDP数据无法收到

  • 一文了解dpdk rte_ring无锁队列
  • F-Stack实现UDP服务端、客户端,并进行吞吐量测试的实现
  • github F-Stack

环境

在一台机器上,系统为Ubuntu 22.4

硬件上是一张100G网卡 两个网口,光纤直连两个网口

UDPServer 的port0.ini配置文件中设置IP如下并使用网卡的PORT0端口

[port0]
addr=192.168.2.15
netmask=255.255.255.0
broadcast=192.168.2.255
gateway=192.168.2.1

UDPClient 的port1.ini配置文件中设置IP如下并使用网卡的PORT1端口

[port1]
addr=192.168.2.16
netmask=255.255.255.0
broadcast=192.168.2.255
gateway=192.168.2.1

问题

服务端可以接收到客户端的arp请求报文并且应答了arp报文,然后就卡住了,ff_envent()函数无法检测到sockfd有数据
UDPServer配置文件中的 lcore_mask 参数我配置的是f0

lcore_mask=f0

本意是想启动一个UDPServer程序使用4个逻辑核心,经过测试启动一个程序只能使用配置的第一个逻辑核心,此时去使用UDPClient发送数据到UDPServer时就无法收到数据,不知道是我个人有这个问题,还是在同一电脑上的同一张网卡配置多个逻辑核心时都无法收到数据,就是这么设计的吗

解决

后续又买了一块相同的100G网卡,放在另一台电脑,光纤直连,然后发送数据,此时竟然可以收到数据。那就证明代码收发是正确的

后续查看源码时在源码文件 ff_dpdk_if.cmain_loop() 函数中有调用 process_dispatch_ring() 函数,函数内调用了 rte_ring_dequeue_burst(),大概了解了一下,我猜测因为我配置了4个核心,在初始化时创建了4个ring队列

从打印的信息来看也是这样的:

create ring:dispatch_ring_p0_q0 success, 2047 ring entries are now free!
create ring:dispatch_ring_p0_q1 success, 2047 ring entries are now free!
create ring:dispatch_ring_p0_q2 success, 2047 ring entries are now free!
create ring:dispatch_ring_p0_q3 success, 2047 ring entries are now free!

我个人猜测,很有可能是因为接收UDP数据被分发给了其它的队列上,我只启动一个程序也就是只是用了第一个ring队列,那么就不可能收到数据,然后我相应的启动了4个程序,终于收到了数据,老天爷,对于一个刚学习DPDK的人简直是折磨。

$ ./UDPServer -c port0.ini -p 0 &
$ ./UDPServer -c port0.ini -p 1 &
$ ./UDPServer -c port0.ini -p 2 &
$ ./UDPServer -c port0.ini -p 3 &

如果不想启动多个进程的话,把配置文件中的核心数配置为1个,启动一个程序就可以收发数据了。

代码

UDPserver


#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#include <cerrno>
#include <stdlib.h>
#include <rte_ethdev.h>// F-stack
#include <ff_api.h>
#include <ff_config.h>#define MAX_EVENTS 512
#define MAXLINE 512int kq;
int sockfd;
/* kevent set */
struct kevent kevSet;
/* events */
struct kevent events[MAX_EVENTS];int loop(void *arg){char buf[MAXLINE] = {"0"};struct sockaddr_in cliAddr;socklen_t recvAddrLen = sizeof(cliAddr);int nevents = ff_kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);if (nevents < 0) {printf("ff_kevent failed:%d, %s\n", errno, strerror(errno));return -1;}for (int i = 0; i < nevents; ++i) {struct kevent event = events[i];int clientfd = (int)event.ident;printf("event.data = %d \n", (int)event.data);printf("listen event %d\n", nevents);printf("clientfd %d\n", clientfd);printf("sockfd %d\n", sockfd);printf("event.flags = %d \n", event.flags);if (clientfd == sockfd) {int n = ff_recvfrom(sockfd, buf, MAXLINE, 0,  (struct linux_sockaddr *)&cliAddr, &recvAddrLen);if(n < 0){printf("ff_recvfrom failed, errno:%d, %s\n", errno, strerror(errno));}else{// 接收数据 并打印printf("Server recv   %s\n", buf);printf("Client Family %d\n", cliAddr.sin_family);printf("Client Addr   %s\n", inet_ntoa(cliAddr.sin_addr));printf("Client Port   %u\n", ntohs(cliAddr.sin_port));strcpy(buf, "hello client, i am server");int num = ff_sendto(sockfd, buf, sizeof(buf) / sizeof(buf[0]), 0, (struct linux_sockaddr *)&cliAddr, recvAddrLen);if(num < 0){printf("ff_sendto failed, errno:%d, %s\n", errno, strerror(errno));ff_stop_run();}else{printf("Server send %d bytes\n", num);}}}}return 1;
}int main(int argc, char **argv){int on = 1;struct sockaddr_in my_addr;ff_init(argc, argv);kq = ff_kqueue();if (kq < 0) {printf("ff_kqueue failed, errno:%d, %s\n", errno, strerror(errno));exit(1);}sockfd = ff_socket(AF_INET, SOCK_DGRAM, 0);ff_ioctl(sockfd, FIONBIO, &on);bzero(&my_addr, sizeof(my_addr));my_addr.sin_family = AF_INET;my_addr.sin_port = htons(34824);my_addr.sin_addr.s_addr =  htonl(INADDR_ANY);int ret = ff_bind(sockfd, (struct linux_sockaddr *)&my_addr, sizeof(my_addr));if (ret < 0) {printf("ff_bind failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));exit(1);}EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);/* Update kqueue */ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);ff_run(loop, NULL);if(rte_eth_dev_stop(0) < 0)rte_exit(EXIT_FAILURE, "Cannot close eth %" PRIu16 "\n", 0);rte_eal_cleanup();return 1;
}

UDPClient

#include <stdio.h>#include <sys/ioctl.h>
#include <string.h>
#include <cerrno>
#include <stdlib.h>
#include <rte_ethdev.h>// F-stack
#include <ff_api.h>
#include <ff_config.h>#define MAX_EVENTS 512
#define MAXLINE 512
int kq;
int sockfd;
/* kevent set */
struct kevent kevSet;
/* events */
struct kevent events[MAX_EVENTS];
struct sockaddr_in serverAddr;int loop(void *arg){int num;char buf[MAXLINE] = {"0"};struct sockaddr_in recvAddr;socklen_t recvAddrLen = sizeof(recvAddr);strcpy(buf,"hello, i am client");num = ff_sendto(sockfd, buf, sizeof(buf)/sizeof(buf[0]), 0, (struct linux_sockaddr *)&serverAddr, sizeof(serverAddr));if(num < 0){printf("ff_kevent failed:%d, %s\n", errno, strerror(errno));ff_stop_run();}elseprintf("sendto num:%d\n", num);int nevents = ff_kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);if (nevents < 0) {printf("ff_kevent failed:%d, %s\n", errno, strerror(errno));ff_stop_run();return -1;}for (int i = 0; i < nevents; ++i) {printf("listen nevents !!! \n");struct kevent event = events[i];int serverfd = (int)event.ident;printf("event.data = %d \n", (int)event.data);printf("event.flags = %d \n", event.flags);printf("serverfd = %d \n", serverfd);printf("sockfd = %d \n", sockfd);if (serverfd == sockfd) {int n = ff_recvfrom(sockfd, buf, MAXLINE, 0,  (struct linux_sockaddr *)&recvAddr, &recvAddrLen);if(n < 0){printf("ff_recvfrom failed, errno:%d, %s\n", errno, strerror(errno));}else{// 接收数据 并打印printf("Client recv   %s\n", buf);printf("Server Family %d\n", recvAddr.sin_family);printf("Server Addr   %s\n", inet_ntoa(recvAddr.sin_addr));printf("Server Port   %u\n", ntohs(recvAddr.sin_port));ff_stop_run();}}}return 1;
}int main(int argc, char **argv){struct sockaddr_in my_addr;int on = 1;ff_init(argc, argv);kq = ff_kqueue();if (kq < 0) {printf("ff_kqueue failed, errno:%d, %s\n", errno, strerror(errno));exit(1);}sockfd = ff_socket(AF_INET, SOCK_DGRAM, 0);ff_ioctl(sockfd, FIONBIO, &on);bzero(&my_addr, sizeof(my_addr));my_addr.sin_family = AF_INET;my_addr.sin_port = htons(34825);my_addr.sin_addr.s_addr = inet_addr( "192.168.2.16" );ff_bind(sockfd, (struct linux_sockaddr *)&my_addr, sizeof(my_addr));// 指定发送的地址和端口号bzero(&serverAddr, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(34824);serverAddr.sin_addr.s_addr = inet_addr( "192.168.2.15" );EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);/* Update kqueue */ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);ff_run(loop, NULL);ff_close(sockfd);return 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/465242.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用ChatGPT提高工作效率,轻松搞定每天任务!

ChatGPT 在现代工作环境中的关键作用 随着数字化时代的到来&#xff0c;商业环境也进入了一个迅速发展的新时代&#xff0c;技术进步成为推动这一变革的核心力量。自动化和效率已不再是理想&#xff0c;而是企业保持竞争力的必备条件。在这一变化的过程中&#xff0c;人工智能…

程序员开发速查表

作为一名苦逼的程序员&#xff0c;在开发的过程中&#xff0c;我们总是在各种编程语言中来回穿梭&#xff0c;忙完后端整前端&#xff0c;还得做一部分的运维工作&#xff0c;忙的我们有时候忘记语法&#xff0c;忘记编写规则&#xff0c;甚至混淆。这时候我们就希望有一个综合…

【大数据学习 | kafka高级部分】kafka的快速读写

1. 追加写 根据以上的部分我们发现存储的方式比较有规划是对于后续查询非常便捷的&#xff0c;但是这样存储是不是会更加消耗存储性能呢&#xff1f; 其实kafka的数据存储是追加形式的&#xff0c;也就是数据在存储到文件中的时候是以追加方式拼接到文件末尾的&#xff0c;这…

Embedding模型部署及效果评测

最近大模型发展迅速&#xff0c;与之对应的向量化需求也被带动起来了&#xff0c;由此社区也衍生出很多模型&#xff0c;本文选几款&#xff0c;简单做下评测。 前置概念 为方便读者&#xff0c;先简单介绍几个概念。 概念1&#xff1a;Vector Embedding 也即向量化嵌入&am…

RDMA驱动学习(二)- command queue

为了实现用户对网卡硬件的配置&#xff0c;查询&#xff0c;或者执行比如create_cq等命令&#xff0c;mellanox网卡提供了command queue mailbox的机制&#xff0c;本节将以create_cq为例看下这个过程。 command queue&#xff08;后续简称cmdq&#xff09;是一个4K对齐的长度…

在docker里创建 bridge 网络联通不同容器

1.网络创建&#xff1a; docker network create --subnet192.168.1.0/24 --gateway192.168.1.1 uav_management 2.查看网络&#xff1a; docker network ls 3.给已经创建的容器分配ip: docker network connect --ip 192.168.1.10 uav_management 容器名/容器id 示例&#xf…

影响神经网络速度的因素- FLOPs、MAC、并行度以及计算平台

影响神经网络速度的四个主要因素分别是 FLOPs&#xff08;浮点操作数&#xff09;、MAC&#xff08;内存访问成本&#xff09;、并行度以及计算平台。这些因素共同作用&#xff0c;直接影响到神经网络的计算速度和资源需求。 1. FLOPs&#xff08;Floating Point Operations&a…

基于STM32单片机太阳能充电循迹避障小车

本设计基于STM32单片机太阳能充电循迹避障小车&#xff0c;以STM32单片机为微控制器核心&#xff0c;在太阳能板对车载电池充电情况下配合传感器能够实现循迹避障行驶的小车的设计过程。小车采用3.7V锂电池作为电源&#xff0c;太阳能板接入TP4056充电模块&#xff0c;使用MT36…

高效集成金蝶云星空销售出库单的解决方案

审核销售出库单(金蝶->金蝶)集成方案 在企业日常运营中&#xff0c;销售出库单的审核是一个关键环节。为了确保数据的准确性和及时性&#xff0c;我们采用了轻易云数据集成平台&#xff0c;将金蝶云星空系统中的销售出库单数据无缝集成到另一个金蝶云星空系统中。本次案例将…

SpringBoot中使用RESTful风格

文章目录 SpringBoot中使用RESTful风格一、引言二、SpringBoot与RESTful风格1、RESTful风格简介2、SpringBoot中的RESTful注解2.1、代码示例 三、SpringBoot核心配置四、总结 SpringBoot中使用RESTful风格 一、引言 在现代Web开发中&#xff0c;RESTful架构风格因其简洁性和易…

DAY21|二叉树Part08|LeetCode: 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

目录 LeetCode: 669. 修剪二叉搜索树 基本思路 C代码 LeetCode: 108.将有序数组转换为二叉搜索树 基本思路 C代码 LeetCode: 538.把二叉搜索树转换为累加树 基本思路 C代码 LeetCode: 669. 修剪二叉搜索树 力扣代码链接 文字讲解&#xff1a;LeetCode: 669. 修剪二叉搜…

ubuntu20.04安装ros与rosdep

目录 前置配置 配置apt清华源 配置ros软件源 添加ros安装源&#xff08;中科大软件源&#xff09; 设置秘钥 更新源 ros安装 安装ros 初始化 rosdep 更新 rosdep 设置环境变量 安装 rosinstall 安装验证 启动海龟仿真器 操控海龟仿真器 rosdep安装更新 安装 使用…

高亚科技签约酸动力,助力研发管理数字化升级

近日&#xff0c;中国企业管理软件资深服务商高亚科技与广东酸动力生物科技有限公司&#xff08;以下简称“酸动力”&#xff09;正式签署合作协议。借助高亚科技的8Manage PM项目管理软件&#xff0c;酸动力将进一步优化项目过程跟踪与节点监控&#xff0c;提升研发成果的高效…

CSRF与SSRF

csrf(跨站请求伪造)的原理: csrf全称是跨站请求伪造(cross-site request forgery)&#xff0c;也被称为one-click attack 或者 session riding scrf攻击利用网站对于用户网页浏览器的信任&#xff0c;劫持用户当前已登录的web应用程序&#xff0c;去执行分用户本意的操作。 利…

享元模式-实现大颗粒度对象缓存机制

详解 享元模式是一种结构型设计模式&#xff0c;其主要目的是通过共享尽可能多的相同部分来有效地支持大量细粒度的对象。它通过将对象的属性分为内在属性&#xff08;可以共享、不随环境变化的部分&#xff09;和外在属性&#xff08;根据场景变化、不能共享的部分&#xff0…

HTML 基础标签——结构化标签<html>、<head>、<body>

文章目录 1. <html> 标签2. <head> 标签3. <body> 标签4. <div> 标签5. <span> 标签小结 在 HTML 文档中&#xff0c;使用特定的结构标签可以有效地组织和管理网页内容。这些标签不仅有助于浏览器正确解析和渲染页面&#xff0c;还能提高网页的可…

新华三H3CNE网络工程师认证—VLAN的配置

VLAN&#xff08;虚拟局域网&#xff09;是一种在逻辑上划分网络的技术&#xff0c;它可以将一个物理网络分割成多个虚拟网络&#xff0c;从而实现不同组的设备之间的隔离。在配置VLAN时&#xff0c;通常涉及到三种端口类型&#xff1a;Access、Trunk和Hybrid。Access端口用于连…

R语言*号标识显著性差异判断组间差异是否具有统计意义

前言 该R代码用于对Iris数据集进行多组比较分析&#xff0c;探讨不同鸢尾花品种在不同测量变量&#xff08;花萼和花瓣长度与宽度&#xff09;上的显著性差异。通过将数据转换为长格式&#xff0c;并利用ANOVA和Tukey检验&#xff0c;代码生成了不同品种间的显著性标记&#x…

手边酒店多商户版V2源码独立部署_博纳软云

新版采用laraveluniapp开发&#xff0c;为更多平台小程序开发提供坚实可靠的底层架构基础。后台UI全部重写&#xff0c;兼容手机端管理。 全新架构、会员卡、钟点房、商城、点餐、商户独立管理

Multi Agents协作机制设计及实践

01 多智能体协作机制的背景概述 在前述博客中&#xff0c;我们利用LangChain、AutoGen等开发框架构建了一个数据多智能体的平台&#xff0c;并使用了LangChain的Multi-Agents框架。然而&#xff0c;在实施过程中&#xff0c;我们发现现有的框架存在一些局限性&#xff0c;这些…