当前位置: 首页 > news >正文

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;
}

相关文章:

DPDK(F-Stack) 实现UDP通信

因刚开始学习DPDK&#xff0c;在学习过程中了解到需使用用户态协议栈&#xff0c;在网上找到F-Stack的相关介绍&#xff0c;但是缺乏DPDK的相关知识&#xff0c;导致使用F-Stack 时UDP数据无法收到 一文了解dpdk rte_ring无锁队列F-Stack实现UDP服务端、客户端&#xff0c;并进…...

基于ExtendSim的库存与订购实验

说明&#xff1a; 库存和订购实验室是一个单部件模拟模型&#xff0c;旨在测试从组件需求站点到组件分发站点的订购策略&#xff0c;以及 在组件分销现场的生产区域内。最佳解决方案允许为需求站点提供高服务级别&#xff0c;同时最大限度地降低总库存水平。 该模型演示了分层模…...

操作系统个人八股文总结

1.进程和线程的区别 进程和线程的定义 进程&#xff1a; 进程是一个运行中的程序实例&#xff0c;是资源分配的基本单位。每个进程都有自己的地址空间、数据、堆栈以及其他辅助数据。线程&#xff1a; 线程是进程中的一个执行单元&#xff0c;是CPU调度的基本单位。一个进程可…...

scala set训练

Set实训内容&#xff1a; 1.创建一个可变Set&#xff0c;用于存储图书馆中的书籍信息&#xff08;假设书籍信息用字符串表示&#xff09;&#xff0c;初始化为包含几本你喜欢的书籍 2.添加两本新的书籍到图书馆集合中&#xff0c;使用操作符 3.删除一本图书馆集合中的书籍&…...

【d63】【Java】【力扣】141.训练计划III

思路 使用递归实现 出口 &#xff0c;遇到null 每一层要做&#xff1a;把下层放进去&#xff0c;把本层放下去 代码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { …...

【Linux】- 权限(2)

接上一篇文章&#xff0c;继续介绍linux权限的相关知识。https://blog.csdn.net/hffh123/article/details/143432940?spm1001.2014.3001.5501j 目录 一、chown&#xff1a;修改文件的拥有者 二、chgrp&#xff1a;修改文件所属组 三、关于other的介绍 四、文件类型 1、分类…...

如何设置内网IP的端口映射到公网

在现代网络环境中&#xff0c;端口映射&#xff08;Port Mapping&#xff09;是一项非常实用的技术&#xff0c;它允许用户将内网设备的服务端口映射到公网&#xff0c;使外网用户可以访问内网中的服务。这项技术在远程办公、设备远程控制、游戏服务器、家庭监控等场景中得到了…...

Matplotlib | 条形图中的每个条形(patch)设置标签数据的方法

方法一 不使用子图对象如何给形图中的每个条形设置数据 plt.figure(figsize(8, 4)) sns.countplot(xWorkout_Frequency (days/week), datadf)plt.title(会员每周锻炼频率分布) plt.xlabel(锻炼频率 (每周次数)) plt.ylabel(人数)# 获取当前活动的轴对象 ax plt.gca()# 循环遍…...

机器学习3_支持向量机_线性不可分——MOOC

线性不可分的情况 如果训练样本是线性不可分的&#xff0c;那么上一节问题的是无解的&#xff0c;即不存在 和 满足上面所有N个限制条件。 对于线性不可分的情况&#xff0c;需要适当放松限制条件&#xff0c;使得问题有解。 放松限制条件的基本思路&#xff1a; 对每个训…...

bash: git: command not found

在windows上重新安装Git之后&#xff0c;遇到cmd可以使用git命令&#xff0c;但是git bash中使用的git命令的时候&#xff0c;会提示&#xff1a; $ git bash: git: command not found 解决办法 找到用户目录下的.bash_profile和.bashrc文件&#xff0c;编辑打开&#xff0c;找…...

大模型LLama3!!!Ollama下载、部署和应用(保姆级详细教程)

首先呢&#xff0c;大家在网站先下载ollama软件 这就和anaconda和python是一样的 废话不多说 直接上链接&#xff1a;Download Ollama on Windows 三个系统都支持 注意&#xff1a; 这里的Models&#xff0c;就是在上面&#xff0c;大家点开之后&#xff0c;里面有很多模型…...

ReactPress系列—NestJS 服务端开发流程简介

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎提出宝贵的建议&#xff0c;感谢Star。 NestJS 服务端开发流程简介 NestJS 是一个用于构建高效、可靠和可扩展的服务器端应用程序的框架。它使用 TypeScript&#xff08;但也支持纯 Java…...

Maven 下载配置 详解 我的学习笔记

Maven 下载配置 详解 我的学习笔记 一、Maven 简介二、maven安装配置三、maven基本使用四、idea配置mavenidea配置maven环境maven坐标idea创建maven项目配置Maven-Helper插件 五、依赖管理 一、Maven 简介 Apache Maven 是一个项目管理和构建工具&#xff0c;它基于项目对象模型…...

【学术精选】SCI期刊《Electronics》特刊“New Challenges in Remote Sensing Image Processing“

英文名称&#xff1a;New Challenges in Remote Sensing Image Processing 中文名称&#xff1a;"遥感图像处理的新挑战"特刊 期刊介绍 “New Challenges in Remote Sensing Image Processing”特刊隶属于《Electronics》期刊&#xff0c;聚焦遥感图像处理领域快速…...

卷积神经网络——pytorch与paddle实现卷积神经网络

卷积神经网络——pytorch与paddle实现卷积神经网络 本文将深入探讨卷积神经网络的理论基础&#xff0c;并通过PyTorch和PaddlePaddle两个深度学习框架来展示如何实现卷积神经网络模型。我们将首先介绍卷积神经网络、图像处理的基本概念&#xff0c;这些理论基础是理解和实现卷…...

云平台虚拟机运维笔记整理,使用libvirt创建和管理虚拟机,以及开启虚拟机嵌套,虚拟磁盘扩容,物理磁盘扩容等等

云平台虚拟机运维笔记整理,使用libvirt创建和管理虚拟机,以及开启虚拟机嵌套,虚拟磁盘扩容,物理磁盘扩容等等。 掌握和使用qemu和libvirt,分别使用它们创建一个cirros虚拟机,并配置好网络。 宿主机node0的系统为ubuntu16,IP为192.168.56.200。 qemu和libvirt简介 QEMU…...

最佳实践:如何实现函数参数之间的TS类型相依赖和自动推断

引入 最近在开发一款极致优雅的前端状态管理库AutoStore时碰到这样一个问题。 拟实现Field组件&#xff0c;该组件相关类型简化代码如下&#xff1a; type Field (props:{validate,render:(props:{value,isValid}) })该组件&#xff0c;具有validate和render两个属性: 其中…...

Linux基础指令1

好久没写博客了&#xff0c;这次我将重新做人&#xff0c;每星期都更&#xff0c;做不到的话直接倒立洗头。最近在学Linux&#xff0c;感觉很厉害的样子&#xff0c;先浅学一下再弄数据结构去。 Linux的基本操作是通过指令来执行的&#xff0c;所以我们先来学习下指令。 1.简…...

软件设计师:排序算法总结

一、直接插入 排序方式&#xff1a;从第一个数开始&#xff0c;拿两个数比较&#xff0c;把后面一位跟前面的数比较&#xff0c;把较小的数放在前面一位 二、希尔 排序方式&#xff1a;按“增量序列&#xff08;步长&#xff09;”分组比较&#xff0c;组内元素比较交换 假设…...

「Mac畅玩鸿蒙与硬件25」UI互动应用篇2 - 计时器应用实现

本篇将带领你实现一个实用的计时器应用&#xff0c;用户可以启动、暂停或重置计时器。该项目将涉及时间控制、状态管理以及按钮交互&#xff0c;是掌握鸿蒙应用开发的重要步骤。 关键词 UI互动应用时间控制状态管理用户交互 一、功能说明 在这个计时器应用中&#xff0c;用户…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...