DPDK用户态协议栈-TCP Posix API 2
tcp posix api
send发送
ssize_t nsend(int sockfd, const void *buf, size_t len, __attribute__((unused))int flags) {ssize_t length = 0;void* hostinfo = get_host_fromfd(sockfd);if (hostinfo == NULL) {return -1;}struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;if (stream->proto == IPPROTO_TCP) {struct ln_tcp_fragment* fragment = rte_malloc("send frag", sizeof(struct ln_tcp_fragment), 0);if (fragment == NULL) {return 0;}memset(fragment, 0, sizeof(struct ln_tcp_fragment));fragment->sport = stream->dport;fragment->dport = stream->sport;fragment->acknum = stream->recv_next;fragment->seqnum = stream->send_next;fragment->windows = LN_TCP_INITIAL_WINDOWS;fragment->tcp_flags = RTE_TCP_ACK_FLAG | RTE_TCP_PSH_FLAG;fragment->hdr_off = 0x50;fragment->data = rte_malloc("frag data", len + 1, 0);if (fragment->data == NULL) {rte_free(fragment);return -1;}memset(fragment->data, 0, len + 1);rte_memcpy(fragment->data, buf, len);fragment->length = len;length = fragment->length;rte_ring_mp_enqueue(stream->send_next, (void*)fragment);}return length;
}
recv接收
ssize_t nrecv(int sockfd, void *buf, size_t len, __attribute__((unused))int flags) {ssize_t length = 0;void* hostinfo = get_host_fromfd(sockfd);if (hostinfo == NULL) {return -1;}struct ln_tcp_stream* stream = (struct ln_tcp_stream*)hostinfo;if (stream->proto == IPPROTO_TCP) {struct ln_tcp_fragment* fragment = NULL;int nb_rev = 0;pthread_mutex_lock(&stream->mutex);while((nb_rev = rte_ring_mc_dequeue(stream->recvbuf, (void**)&fragment)) < 0) {pthread_cond_wait(&stream->cond, &stream->mutex);}pthread_mutex_unlock(&stream->mutex);if (fragment->length > len) {rte_memcpy(buf, fragment->data, len);int i;for (i = 0; i < fragment->length - len; i++) {fragment->data[i] = fragment->data[i + len];}fragment->length = fragment->length - len;length = fragment->length;rte_ring_mp_enqueue(stream->recvbuf, (void*)fragment);}else if (fragment->length == 0) {rte_free(fragment);}else {rte_memcpy(buf, fragment->data, len);length = fragment->length;rte_free(fragment->data);fragment->data = NULL;rte_free(fragment);}}return length;
}
数据包收发管理管理
接收
static int ln_tcp_enqueue_recvbuf(struct ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr, int tcplen) {struct ln_tcp_fragment* fragment = rte_malloc("tcp frag", sizeof(struct ln_tcp_fragment));if (fragment == NULL) {return -1;}memset(fragment, 0, sizeof(struct ln_tcp_fragment));fragment->dport = ntohs(tcphdr->dst_port);fragment->sport = ntohs(tcphdr->src_port);uint8_t hdrlen = tcphdr->data_off >> 4;int payloadlen = tcplen - hdrlen * 4;if (payloadlen > 0) {uint8_t* payload = (uint8_t*)tcphdr + hdrlen * 4;fragment->data = rte_malloc("frag data", payloadlen + 1, 0);if (fragment->data == NULL) {rte_free(fragment);return -1;}memset(fragment, 0, payloadlen + 1);rte_memcpy(fragment->data, payload, payloadlen);fragment->length = payloadlen;}else if (payloadlen == 0) {fragment->length = 0;fragment->data = NULL;}rte_ring_mp_enqueue(stream->recvbuf, (void*)fragment);pthread_mutex_lock(&stream->mutex);pthread_cond_signal(&stream->cond);pthread_mutex_unlock(&stream->mutex);return 0;
}
发送
static int ln_tcp_send_ackpkt(struct ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr) {struct ln_tcp_fragment* fragment = rte_malloc("ack frag", sizeof(struct ln_tcp_fragment), 0);if (fragment == NULL) {return -1;}memset(fragment, 0, sizeof(struct ln_tcp_fragment));fragment->sport = stream->dport;fragment->dport = stream->sport;fragment->acknum = stream->recv_next;fragment->seqnum = stream->send_next;fragment->windows = LN_TCP_INITIAL_WINDOWS;fragment->length = 0;fragment->data = NULL;fragment->hdr_off = 0x50;fragment->tcp_flags = RTE_TCP_ACK_FLAG;rte_ring_mp_enqueue(stream->sendbuf, (void*)fragment);return 0;
}
establish handle
static int ln_tcp_handle_close_established(struct ln_tcp_stream* stream, struct rte_tcp_hdr* tcphdr, int tcplen) {if (tcphdr->tcp_flags & RTE_TCP_SYN_FLAG) {}if (tcphdr->tcp_flags & RTE_TCP_PSH_FLAG) {ln_tcp_enqueue_recvbuf(stream, tcphdr, tcplen);uint8_t hdrlen = tcphdr->data_off >> 4;int payloadlen = tcphdr - hdrlen * 4;stream->recv_next = stream->recv_next + payloadlen;stream->send_next = ntohl(tcphdr->recv_ack);ln_tcp_send_ackpkt(stream, tcphdr);}if (tcphdr->tcp_flags & RTE_TCP_ACK_FLAG) {}if (tcphdr->tcp_flags & RTE_TCP_FIN_FLAG) {stream->status = LN_TCP_STATUS_CLOSE_WAIT;ln_tcp_enqueue_recvbuf(stream, tcphdr, tcphdr->data_off >> 4);stream->recv_next = stream->recv_next + 1;stream->send_next = ntohl(tcphdr->recv_ack);ln_tcp_send_ackpkt(stream, tcphdr);}return 0;
}
tcp server
static int tcp_server_entry(__attribute__((unused)) void* arg) {int sockfd = nsocket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {return -1;}printf("tcp sockfd is %d\n", sockfd);struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(struct sockaddr));servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_family = AF_INET;servaddr.sin_port = htons(8888);nbind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));nlisten(sockfd, 10);while (1) {struct sockaddr_in client;socklen_t len = sizeof(client);int connfd = naccept(sockfd, (struct sockaddr*)&client, &len);char buff[BUFFER_SIZE] = {0};while (1) {int n = nrecv(connfd, buff, BUFFER_SIZE, 0); // blockif (n > 0) {printf("recv: %s\n", buff);nsend(connfd, buff, n, 0);}else if (n == 0) {nclose(connfd);break;}else {//nonblock}}}nclose(sockfd);
}
效果展示
回去之后调好了,有点难调
总结
到目前为止,IP/TCP和IP/UDP的协议栈都写完了,但是没有并发效果;这个后面会解决。下一步是探索一下协议的扩展,写一个dns服务器来看一下如何基于tcp或者udp来扩展协议。
项目地址
项目地址
参考资料:https://github.com/0voice
相关文章:

DPDK用户态协议栈-TCP Posix API 2
tcp posix api send发送 ssize_t nsend(int sockfd, const void *buf, size_t len, __attribute__((unused))int flags) {ssize_t length 0;void* hostinfo get_host_fromfd(sockfd);if (hostinfo NULL) {return -1;}struct ln_tcp_stream* stream (struct ln_tcp_stream…...

[IT项目管理]项目时间管理(本章节3w字爆肝)
七.项目时间管理 7.1 项目进度的重要性 为什么要重视项目进度:在项目进行的过程之中会遇到变故。但是不论项目中发生了什么,时间总是在流逝,就可能会导致项目不可以在规定的时间完成。 7.2可能影响项目进度的因素 有员工离职个人的工作方…...

【python因果库实战5】使用银行营销数据集研究营销决策的效果5
目录 接触次数的效应 重新定义治疗变量和潜在混杂因素 更深入地审视干预情景 逆概率加权 标准化 总结及与非因果分析的比较 接触次数的效应 我们现在转而研究当前营销活动中接触次数的数量(campaign)对积极结果发生率的影响。具体来说,…...

【Qt】QWidget中的常见属性及其功能(二)
目录 六、windowOpacity 例子: 七、cursor 例子: 八、font 九、toolTip 例子: 十、focusPolicy 例子: 十一、styleSheet 计算机中的颜色表示 例子: 六、windowOpacity opacity是不透明度的意思。 用于设…...
9 OOM和JVM退出。OOM后JVM一定会退出吗?
首先我们把两个概念讲清楚 OOM是线程在申请堆内存,发现堆内存空间不足时候抛出的异常。 JVM退出的条件如下: java虚拟机在没有守护线程的时候会退出。守护线程是启动JVM的线程,服务于用户线程。 我们简单说下守护线程的功能: 1.日志的记录…...
学习笔记070——Java中【泛型】和【枚举】
文章目录 1、泛型1.1、为什么要使用泛型?1.2、泛型的应用1.3、泛型通配符1.4、泛型上限和下限1.5、泛型接口 2、枚举 1、泛型 Generics 是指在定义类的时候不指定类中某个信息(属性/方法返回值)的具体数据类型,而是用一个标识符来…...

【工具变量】碳排放市场交易数据(2013-2023年)
一、时间范围:2013年8月5日到2023年1月13日 二、具体指标: 交易日期 城市名称 交易品种 开盘价 最高价 最低价 成交均价 收盘价 前收盘价 涨跌幅 总成交量 总成交额 …...

【视频生成模型】——Hunyuan-video 论文及代码讲解和实操
🔮混元文生视频官网 | 🌟Github代码仓库 | 🎬 Demo 体验 | 📝技术报告 | 😍Hugging Face 文章目录 论文详解基础介绍数据预处理 (Data Pre-processing)数据过滤 (Data Filtering)数据标注 (Data…...

基线检查:Windows安全基线.【手动 || 自动】
基线定义 基线通常指配置和管理系统的详细描述,或者说是最低的安全要求,它包括服务和应用程序设置、操作系统组件的配置、权限和权利分配、管理规则等。 基线检查内容 主要包括账号配置安全、口令配置安全、授权配置、日志配置、IP通信配置等方面内容&…...
uniapp跨端适配—条件编译
在uniapp中,跨端适配是通过条件编译实现的。条件编译允许开发者根据不同的平台(如iOS、Android、微信小程序、百度小程序等)编写不同的代码。这样可以确保每个平台上的应用都能得到最优的性能和用户体验。 以下是uniapp中条件编译的基本语法…...

【Java基础面试题013】Java中静态方法和实例方法的区别是是么?
回答重点 静态方法 使用static关键字修修饰的方法属于类随着类的加载而加载,随着类的卸载而消失可以通过类名直接调用,也可以通过对象调用,但是这种方式不推荐,会混淆意义,也不利于后期维护与扩展 class Example {st…...

C语言入门(一):A + B _ 基础输入输出
前言 本专栏记录C语言入门100例,这是第(一)例。 目录 一、【例题1】 1、题目描述 2、代码详解 二、【例题2】 1、题目描述 2、代码详解 三、【例题3】 1、题目描述 2、代码详解 四、【例题4】 1、题目描述 2、代码详解 一、【例…...
Vue日历组件FullCalendar使用方法
FullCalendar (全日历)Vue组件的使用 FullCalendar官方文档地址 FullCalendar日历组件支持Vue React Angular Javascript Vue2的框架示例: npm install --save fullcalendar/core fullcalendar/vue<template><div class"cal…...

TinyML在OBD-II边缘设备上燃油类型分类的实现与优化
论文标题:TinyML Implementation and Optimization for Fuel Type Classification on OBD-II Edge Device(TinyML在OBD-II边缘设备上燃油类型分类的实现与优化) 作者信息:Miguel Amaral, Morsinaldo Medeiros, Matheus Andrade, …...
vue3 中 defineProps 声明示例
1、直接声明 // 1、直接使用 defineProps(["tableData", "acceptType"]); 2、运行时声明方式不使用TypeScript类型注解,而是使用JavaScript对象,使用 type 来定义props // 2、运行时声明方式不使用TypeScript类型注解,…...
SpringBoot整合MybatisPlus报错Bean不存在:NoSuchBeanDefinitionException
报错信息: Exception in thread “main” org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.feng.mybatisplusdemo.dao.UserMapper’ available 解决办法: 将原来引入的MybatisPlus依赖:…...
异步电机的控制是否还有研究的必要,是不是已经非常成熟了?
随着工业现代化和自动化进程的加快,异步电机作为最为常见的电动机之一,广泛应用于各类机械设备和工业自动化系统中。异步电机因其结构简单、成本低廉、维护方便等优点而备受青睐。 异步电机的基本原理与应用 异步电机,又称感应电机…...
【Android】解决 ADB 中 SELinux 设置与 `Failed transaction (2147483646)` 错误
解决 ADB 中 SELinux 设置与 Failed transaction (2147483646) 错误 在使用 ADB 进行开发和调试时,经常会遇到由于 Android 系统安全策略(SELinux)引起的权限问题,尤其是在执行某些操作时,可能会遇到类似 cmd: Failur…...

企业车辆管理系统(源码+数据库+报告)
一、项目介绍 352.基于SpringBoot的企业车辆管理系统,系统包含两种角色:管理员、用户,系统分为前台和后台两大模块 二、项目技术 编程语言:Java 数据库:MySQL 项目管理工具:Maven 前端技术:Vue 后端技术&a…...

SAP RESTful架构和OData协议
一、RESTful架构 RESTful 架构(Representational State Transfer)是一种软件架构风格,专门用于构建基于网络的分布式系统,尤其是在 Web 服务中。它通过利用 HTTP 协议和一组简单的操作(如 GET、POST、PUT、DELETE&…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...