基于dpdk的用户态协议栈设计实现(二)

简介: 基于dpdk的用户态协议栈设计实现(二)

前言


本文只介绍应用层代码的编写,不会深入开展讲解计算机底层宏大的架构。

初始dpdk环境以及相关资源

代码:

编译:

运行结果(成功):

判断以太网设备数量

如果数量为0,说明前期的配置工作可能存在错误,停止工作并检查。

获取网卡信息

值得注意的是gDpdkPortId在rte系列函数中,用于代表网卡设备。这些设备在linux操作系统中可能是eth0,eth1……,在rte系列函数中则对应0、1、2、3……

配置网卡接收队列与发送队列数量

之前配置虚拟机vmx配置文件的时候,令ethernet0.virtualDev = “vmxnet3”,vmxnet3就是在模拟多队列网卡。

首先设置一个全局rte_eth_conf结构体变量:

.rxmode意思是设置结构体变量port_conf_default里的rxmode的属性。

.rxmode属性的.max_rx_pkt_len属性设置为一个定值,这个定值一般是1518。其中以太网头和CRC(循环冗余校验)一般会固定占去14个字节和4个字节。

这个结构体这么设置是为了限制接收队列的最大可接收包的长度。

在main函数里继续写上以上代码,意思是设置网卡的接收队列数量和发送队列数量,以及相关的端口参数。每个接收队列和发送队列都有自己的缓冲区和处理逻辑。(rx:receive,tx:transmit)。接收队列和发送队列的数量不可超过网卡可设置的最大队列数量。

创建内存池

这里的内存池也叫mbuf池,负责储存接收到的数据包,这里存储的是原始数据。Mbuf内存和skbuff相似点很多,但是前者一般用在dpdk这类高性能框架,后者一般用在内核协议栈,所以还是会有区别的。

第一个参数用于给内存池起名。

第二个参数用于设置内存块数量。

第三个参数代表每个内存块的本地缓存大小,意思把缓存指定为内存块的一部分。

第四个参数代表每个内存块的私有数据大小,如果mbuf有自定义数据则需要设置。

第五个参数代表了每个内存块的数据缓冲区大小。

第六个参数是一个NUMA节点的套接字标识符,NUMA是一种计算机体系的结构,每个NUMA节点都会有自己对应的内存和处理器资源。rte_socket_id()用于获取当前执行线程所在的NUMA节点套接字标识符。

用内存池配置rx队列

Rx队列也就是接收队列。

第一个参数是网卡标识。

第二个参数是接收队列标识,填了0表示是第一个队列。

第三个参数是设置接收队列中接收描述符的数量,可以通过接收描述符进入对应的数据缓冲区。

第四个参数是一个NUMA节点的套接字标识符。rte_eth_dev_socket_id(gDpdkPortId)用于获取指定的网络设备所在的NUMA节点的套接字标识符。

第五个参数是一个rte_eth_rxconf指针,可以通过这个指针设置接收队列的属性。

第六个参数是接收队列对应的内存池地址。mbuf池需要事先创建。

获取并解析udp数据包

  1. 建立一个while循环,用于循环查询是否接收到数据包,之后再循环体内部写代码。
  2. 建立一个mbuf指针数组,用于存储数据包存储的内存块的地址。
  3. 用rte_eth_rx_burst函数接收多个原始的数据包,并且存入了mbuf中,将mbuf的地址存入mbufs指针数组。如果数据包的数量过多超过了限制,那么报错。
  4. 遍历mbufs指针数组。
  5. 用rte_pktmbuf_mtod函数获取mbuf的地址,并且转为struct rte_ether_head *格式。先对RTE_ETHER_TYPE_IPV4进行大端字节序转换,如果ehter_type不是该值,说明接收到的包包头不是IPv4协议类型。不再继续。
  6. 对mbuf内存块进行指针偏移,要求完美避开以太网头的部分,把后续部分转为IP头。如果发现不是UDP协议,那么也终止操作。否则进一步解析,把payload部分取出尝试报文发送

尝试发送报文

在windows上操作。需要在eth0的统一网段下添加是eth0的IP为静态IP。

未完……

目录
相关文章
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
1103 77
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
264 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
583 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
383 11
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
538 7
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1312 10
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
421 59
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
370 9

热门文章

最新文章