DPDK PMD( Poll Mode Driver)轮询模式驱动程序
目录
Mellanox PMDs
轮询模式驱动程序
要求和假设
设计原则
逻辑核心,内存和NIC队列关系
设备标识,所有权和配置
设备识别
港口所有权
设备配置
即时配置
发送队列的配置
按需免费发送mbuf
硬件卸载
轮询模式驱动程序API
共性
通用数据包表示
以太网设备API
以太网设备标准设备参数
扩展统计API
NIC重置API
Mellanox PMDs
https://www.mellanox.com/products/software/accelerator-software/pmd-for-dpdk
DPDK is a set of libraries and optimized NIC drivers for fast packet processing in user space. DPDK provides a framework and common API for high speed networking applications.
For more information, see dpdk.org.
DPDK是一组库和经过优化的NIC驱动程序,用于在用户空间中进行快速的数据包处理。 DPDK为高速网络应用程序提供了框架和通用API。
有关更多信息,请参见dpdk.org。
Mellanox is part of the DPDK open source community, contributing not only to the development of high performance Mellanox drivers but also by improving and expanding DPDK functionalities and use cases.
Mellanox是DPDK开源社区的一部分,不仅为高性能Mellanox驱动程序的开发做出了贡献,而且还通过改进和扩展DPDK功能和用例做出了贡献。
Mellanox Poll Mode Driver (PMD) is an open source upstream driver, embedded within dpdk.org releases, designed for fast packet processing and low latency by providing kernel bypass for receive, send, and by avoiding the interrupt processing performance overhead.
Mellanox轮询模式驱动程序(PMD)是嵌入式dpdk.org版本中的开源上游驱动程序,旨在通过提供内核绕过接收,发送并避免中断处理性能开销来实现快速数据包处理和低延迟。
The two Mellanox PMDs are mlx4 for ConnectX?-3 Pro Ethernet adapters, and mlx5 for Mellanox ConnectX?-4/ConnectX?-4 Lx/ConnectX?-5/ConnectX?-5 Ex Ethernet adapters. Mellanox PMDs supports bare metal, KVM and VMware SR-IOV on x86_64, Arm and Power9 architectures.
两个Mellanox PMD是用于ConnectX?-3Pro以太网适配器的mlx4,和用于MellanoxConnectX?-4/ConnectX?-4Lx /ConnectX?-5/ConnectX?-5Ex以太网适配器的mlx5。 Mellanox PMD在x86_64,Arm和Power9架构上支持裸机,KVM和VMware SR-IOV。
Mellanox PMDs are part of the dpdk.org starting DPDK 2.0 release (mlx4) and DPDK 2.2 (mlx5).
从DPDK 2.0版本(mlx4)和DPDK 2.2(mlx5)开始,Mellanox PMD是dpdk.org的一部分。
For installation instructions, and other related information on dpdk.org releases, please see dpdk.org/doc.
有关dpdk.org版本的安装说明和其他相关信息,请参阅dpdk.org/doc。
轮询模式驱动程序
https://doc.dpdk.org/guides/prog_guide/poll_mode_drv.html#:~:text=The%20DPDK%20includes%201%20Gigabit%2C%2010%20Gigabit%20and,to%20configure%20the%20devices%20and%20their%20respective%20queues.
DPDK包括1吉比特,10吉比特和40吉比特以及半虚拟化的virtio轮询模式驱动程序。
轮询模式驱动程序(PMD)由通过在用户空间中运行的BSD驱动程序提供的API组成,用于配置设备及其各自的队列。此外,PMD直接访问RX和TX描述符,而不会产生任何中断(“链接状态更改”中断除外),以便在用户应用程序中快速接收,处理和传递数据包。本节描述了PMD的要求,它们的全局设计原理,并提出了以太网PMD的高级体系结构和通用外部API。
要求和假设
用于数据包处理应用程序的DPDK环境允许两种模型,即完成运行和管道运行:
- 在运行完成 模型中,将通过API轮询特定端口的RX描述符环以获取数据包。然后,数据包在同一内核上进行处理,并通过API放置在端口的TX描述符环上进行传输。
- 在管道 模型中,一个内核通过API轮询一个或多个端口的RX描述符环。数据包被接收并通过环传递到另一个核心。另一个内核继续处理该数据包,然后可以通过API将其放置在端口的TX描述符环上进行传输。
在同步运行到完成模型中,分配给DPDK的每个逻辑核心都执行一个数据包处理循环,该循环包括以下步骤:
- 通过PMD接收API检索输入数据包
- 一次处理每个收到的数据包,直到转发为止
- 通过PMD传输API发送待处理的输出数据包
相反,在异步管线模型中,某些逻辑核心可能专用于检索接收到的数据包,而其他逻辑核心可能专用于处理先前接收到的数据包。接收的数据包通过环在逻辑核心之间交换。数据包检索的循环包括以下步骤:
- 通过PMD接收API检索输入数据包
- 通过数据包队列将接收到的数据包提供给处理内核
数据包处理的循环包括以下步骤:
- 从数据包队列中检索收到的数据包
- 处理接收到的数据包,如果转发,则重传
为了避免任何不必要的中断处理开销,执行环境不得使用任何异步通知机制。每当需要且适当时,应通过使用环来尽可能地引入异步通信。
在多核环境中,避免锁争用是关键问题。为了解决此问题,PMD旨在与每个核心的私有资源尽可能地配合使用。例如,如果PMD不支持,则PMD会为每个核心,每个端口维护一个单独的传输队列DEV_TX_OFFLOAD_MT_LOCKFREE
。同样,端口的每个接收队列都分配给单个逻辑核心(lcore)并由其轮询。
为了符合非统一内存访问(NUMA),内存管理旨在为每个逻辑核心分配本地内存中的专用缓冲池,以最大程度地减少对远程内存的访问。数据包缓冲池的配置应在DIMM,通道和等级方面考虑基础的物理内存体系结构。应用程序必须确保在创建内存池时给出了适当的参数。请参阅Mempool库。
设计原则
以太网* PMD的API和体系结构在设计时考虑了以下准则。
PMD必须帮助在上层应用程序级别实施面向全球策略的决策。相反,NIC PMD功能不应妨碍上层全局策略所期望的收益,或者更糟的是,无法应用此类策略。
例如,PMD的接收和发送功能都具有要轮询的最大数量的数据包/描述符。这允许“完成运行”处理堆栈通过不同的全局循环策略来静态修复或动态调整其整体行为,例如:
- 立即接收,处理并一次发送一个包。
- 接收尽可能多的数据包,然后处理所有接收到的数据包,并立即传输它们。
- 接收给定的最大数量的数据包,处理接收到的数据包,对其进行累加,最后发送所有累积的数据包进行传输。
为了获得最佳性能,必须考虑整体软件设计选择和纯软件优化技术,并与基于硬件的低级优化功能(CPU缓存属性,总线速度,NIC PCI带宽等)进行权衡。在优化面向突发的网络数据包处理引擎时,数据包传输的情况就是此软件/硬件折衷问题的一个示例。在最初的情况下,PMD只能导出rte_eth_tx_one函数以一次在给定队列上发送一个数据包。最重要的是,可以轻松构建一个rte_eth_tx_burst函数,该函数循环调用rte_eth_tx_one函数一次发送多个数据包。然而,
- 在多个数据包之间分摊调用rte_eth_tx_one函数的未摊销成本。
- 启用rte_eth_tx_burst函数以利用面向突发的硬件功能(在高速缓存中预取数据,使用NIC头/尾寄存器),以最大程度地减少每个数据包的CPU周期数,例如,通过避免不必要的读取存储器访问环形传输描述符,或者系统地使用完全适合缓存行边界和大小的指针数组。
- 应用面向突发的软件优化技术来删除原本不可避免的操作,例如环索引回卷管理。
面向突发功能的功能也通过API引入,用于PMD大量使用的服务。这尤其适用于用于填充NIC环的缓冲区分配器,该缓冲区分配器提供了一次分配/释放多个缓冲区的功能。例如,一个mbuf_multiple_alloc函数返回一个指向rte_mbuf缓冲区的指针数组,当补充接收环的多个描述符时,它可以加快PMD的接收轮询功能。
逻辑核心,内存和NIC队列关系
当处理器的逻辑核心和接口利用其本地内存时,DPDK支持NUMA,以实现更好的性能。因此,应从在本地内存中创建的内存池中分配与本地PCIe *接口关联的mbuf分配。如果可能,缓冲区应保留在本地处理器上以获得最佳性能结果,并且应使用从本地内存分配的内存池分配的mbuf填充RX和TX缓冲区描述符。
如果数据包或数据操作位于本地内存而不是远程处理器内存中,则运行至完成模型的性能也更好。如果使用的所有逻辑核心都位于同一处理器上,则对于管道模型也是如此。
多个逻辑核心绝不应共享接口的接收或传输队列,因为这将需要全局锁定并降低性能。
如果PMD有DEV_TX_OFFLOAD_MT_LOCKFREE
能力,则多个线程可以rte_eth_tx_burst()
在没有SW锁定的情况下在同一tx队列上并发调用。在某些NIC中可以找到此PMD功能,在以下用例中很有用:
- 在某些未将lcore映射到具有1:1关系的Tx队列的应用程序中,删除显式自旋锁。
- 在eventdev用例中,请避免将单独的TX内核专用于传输,因为所有工作人员都可以发送数据包,因此可以进行更多扩展。
见硬件卸载的DEV_TX_OFFLOAD_MT_LOCKFREE
能力探测的详细信息。
设备标识,所有权和配置
设备识别
每个NIC端口由其(总线/桥,设备,功能)PCI标识符唯一指定,该PCI标识符由在DPDK初始化时执行的PCI探测/枚举功能分配。根据其PCI标识符,为NIC端口分配了两个其他标识符:
- 端口索引,用于在PMD API导出的所有功能中指定NIC端口。
- 用于在控制台消息中指定端口的端口名称,用于管理或调试目的。为了易于使用,端口名称包括端口索引。
Port所有权
以太网设备端口可以由单个DPDK实体(应用程序,库,PMD,进程等)拥有。所有权机制由ethdev API控制,并允许DPDK实体设置/删除/获取端口所有者。允许这样做可以防止不同实体对以太网端口进行任何多重管理。注意
DPDK实体有责任在使用端口所有者之前设置端口所有者,并管理不同线程或进程之间的端口使用情况同步。
设备配置
每个NIC端口的配置包括以下操作:
- 分配PCI资源
- 将硬件重置(发出全局重置)为众所周知的默认状态
- 设置PHY和链接
- 初始化统计计数器
PMD API还必须导出用于启动/停止端口的全多播功能的功能,以及用于在混杂模式下设置/取消设置端口的功能。
必须在端口初始化时通过特定的配置参数分别配置某些硬件卸载功能。例如,接收方扩展(RSS)和数据中心桥接(DCB)功能就是这种情况。
即时配置
可以“即时”启动或停止的所有设备功能(即,无需停止设备)不需要PMD API为此目的导出专用功能。
所需要的只是设备PCI寄存器的映射地址,以在驱动程序之外的特定功能中实现这些功能的配置。
为此,PMD API导出一个函数,该函数提供与设备关联的所有信息,可用于在驱动程序外部设置给定设备功能。这包括PCI供应商标识符,PCI设备标识符,PCI设备寄存器的映射地址以及驱动程序的名称。
这种方法的主要优点是,它为选择用于配置,启动和停止此类功能的API提供了完全的自由。
例如,请参考testpmd应用程序中针对英特尔?82576千兆位以太网控制器和英特尔?82599 10千兆位以太网控制器控制器的IEEE1588功能的配置。
可以用相同的方式配置其他功能,例如端口的L3 / L4 5元组数据包过滤功能。可以在单个端口上配置以太网*流控制(暂停帧)。有关详细信息,请参考testpmd源代码。另外,只要正确设置了数据包mbuf,就可以为单个数据包启用NIC的L4(UDP / TCP / SCTP)校验和卸载。有关详细信息,请参见硬件卸载。
发送队列的配置
每个传输队列都独立配置了以下信息:
- 传输环的描述符数
- 套接字标识符,用于标识NUMA体系结构中从中分配传输环的适当DMA内存区域
- 传输队列的预取,主机和回写阈值寄存器的值
- 所述最小的发送数据包到自由阈值(tx_free_thresh)。当用于传输数据包的描述符数量超过此阈值时,应检查网络适配器以查看其是否已写回描述符。在TX队列配置期间可以传递0值,以指示应使用默认值。tx_free_thresh的默认值为32。这可确保PMD不会搜索完整的描述符,直到NIC已为此队列至少处理32个为止。
- 该最低 RS位阈值。在设置传输描述符中的报告状态(RS)位之前要使用的最小传输描述符数目。请注意,此参数可能仅对Intel 10 GbE网络适配器有效。如果自上次RS位设置以来(直到用于传输数据包的第一个描述符)使用的描述符数量超过了传输RS位阈值(tx_rs_thresh),则在用于传输数据包的最后一个描述符上设置RS位。简而言之,此参数控制网络适配器将哪些传输描述符写回到主机存储器。可以在TX队列配置期间传递0值,以指示应使用默认值。tx_rs_thresh的默认值为32。这可确保在网络适配器回写最近使用的描述符之前,至少使用32个描述符。这样可以节省由于TX描述符写回而产生的上游PCIe *带宽。重要的是要注意,当tx_rs_thresh大于1时,TX回写阈值(TX wthresh)应设置为0。有关更多详细信息,请参阅《英特尔?82599 10千兆位以太网控制器数据表》(https://ark.intel.com/content/www/us/en/ark/products/66004/intel-82599en-10-gigabit-ethernet-controller.html)。
tx_free_thresh和tx_rs_thresh必须满足以下约束:
- tx_rs_thresh必须大于0。
- tx_rs_thresh必须小于环的大小减去2。
- tx_rs_thresh必须小于或等于tx_free_thresh。
- tx_free_thresh必须大于0。
- tx_free_thresh必须小于环的大小减去3。
- 为了获得最佳性能,当tx_rs_thresh大于1时,TX wthresh应该设置为0。
TX环中的一个描述符用作前哨,以避免硬件争用情况,因此避免了最大阈值约束。注意
当配置DCB操作时,在端口初始化时,发送队列数和接收队列数都必须设置为128。
按需发送mbuf
在发送数据包之后,许多驱动程序不会立即将mbuf释放回内存池或本地缓存。相反,它们将mbuf留在Tx环中,或者tx_rs_thresh
在交叉时执行批量释放,或者在需要Tx环中的插槽时释放mbuf。
应用程序可以请求驱动程序通过rte_eth_tx_done_cleanup()
API 释放使用过的mbuf 。此API要求驱动程序释放不再使用的mbuf,而与是否tx_rs_thresh
已交叉无关。在两种情况下,应用程序可能需要立即释放mbuf:
- 需要将给定的数据包发送到多个目标接口时(用于第2层泛洪或第3层多播)。一种选择是制作需要操作的数据包副本或标头部分的副本。第二种选择是发送数据包,然后轮询
rte_eth_tx_done_cleanup()
API,直到数据包上的引用计数递减为止。然后,相同的数据包可以传输到下一个目标接口。该应用程序仍然负责管理不同目标接口之间所需的任何数据包操作,但是可以避免数据包副本。此API与数据包是发送还是丢弃无关,只是接口不再使用mbuf。 - 某些应用程序旨在进行多次运行,例如数据包生成器。出于性能原因和两次运行之间的一致性,应用程序可能希望在每次运行之间重置回初始状态,在此状态下,所有mbuf都返回到内存池。在这种情况下,它可以
rte_eth_tx_done_cleanup()
为已使用的每个目标接口调用API,以请求释放所有已使用的mbuf。
要确定驱动程序是否支持此API,请检查“ 网络接口控制器驱动程序”文档中的Free Tx mbuf on demand功能。
硬件卸载
根据宣传的驱动程序功能 rte_eth_dev_info_get()
,PMD可以支持硬件卸载功能,例如校验和,TCP分段,VLAN插入或同一TX队列上的无锁多线程TX突发。
对这些卸载功能的支持意味着在rte_mbuf数据结构中添加了专用的状态位和值字段,并通过每个PMD导出的接收/发送功能对其进行了适当的处理。标记列表及其确切含义在mbuf API文档以及Mbuf库中 “元信息”部分中进行了描述。
每端口和每队列卸载
在DPDK卸载API中,卸载分为以下每个端口和每个队列卸载:
- 可以在一个队列上启用每个队列的卸载,并同时在另一个队列上禁用每个队列的卸载。
- 纯粹的每端口卸载是设备支持的卸载,但不是每队列类型的卸载。
- 不能在一个队列上启用纯每端口卸载,而在另一个队列上同时禁用它。
- 必须在所有队列上同时启用或禁用纯每端口卸载。
- 任何卸载都是按队列或纯逐端口类型的,但不能在同一设备上同时使用这两种类型。
- 端口功能=每个队列功能+纯每个端口功能。
- 可以在所有队列上启用任何受支持的卸载。
可以使用来查询不同的卸载功能rte_eth_dev_info_get()
。在dev_info->[rt]x_queue_offload_capa
返回从rte_eth_dev_info_get()
包括所有每个队列的卸载能力。在dev_info->[rt]x_offload_capa
返回从rte_eth_dev_info_get()
包括所有纯每端口和每队列卸载功能。支持的卸载可以是每个端口或每个队列。
使用现有DEV_TX_OFFLOAD_*
或DEV_RX_OFFLOAD_*
标志启用卸载。应用程序请求的任何卸载必须在设备功能范围内。任何卸载被默认禁用,如果它没有在参数设置 dev_conf->[rt]xmode.offloads
来rte_eth_dev_configure()
和 [rt]x_conf->offloads
到rte_eth_[rt]x_queue_setup()
。
如果有任何卸载在启动rte_eth_dev_configure()
一个应用程序,它是在所有队列不管它是每个队列或每个端口类型,不管它是否被设置或清除启用 [rt]x_conf->offloads
到rte_eth_[rt]x_queue_setup()
。
如果尚未在中启用每个队列的卸载rte_eth_dev_configure()
,则可以在rte_eth_[rt]x_queue_setup()
单个队列中启用或禁用它。应用程序[rt]x_conf->offloads
要rte_eth_[rt]x_queue_setup()
输入的新添加的卸载是尚未在中启用的rte_eth_dev_configure()
,要求在中启用rte_eth_[rt]x_queue_setup()
。它必须是按队列类型,否则将触发错误日志。
轮询模式驱动程序API
共性
默认情况下,PMD导出的所有功能都是无锁功能,假定不会在不同逻辑内核上并行调用这些功能以在同一目标对象上工作。例如,不能在两个逻辑内核上并行调用PMD接收功能以轮询同一端口的同一RX队列。当然,该功能可以由不同的RX队列上的不同逻辑内核并行调用。上级应用程序有责任执行此规则。
如果需要,多个逻辑核心对共享队列的并行访问可以通过在其相应的PMD API无锁功能之上构建的专用内联锁感知功能来显式保护。
通用数据包表示
数据包由rte_mbuf结构表示,该结构是一种通用元数据结构,其中包含所有必要的管家信息。这包括与卸载硬件功能相对应的字段和状态位,例如IP标头或VLAN标签的校验和计算。
rte_mbuf数据结构包括特定字段,以通用方式表示网络控制器提供的卸载功能。对于输入数据包,PMD接收功能会使用接收描述符中包含的信息来填充rte_mbuf结构的大多数字段。相反,对于输出数据包,PMD发送功能使用rte_mbuf结构的大多数字段来初始化发送描述符。
mbuf结构在“ Mbuf库”一章中有完整描述(https://doc.dpdk.org/guides/prog_guide/mbuf_lib.html#mbuf-library)。
以太网设备API
《DPDK API参考》中描述了由以太网PMD导出的以太网设备API 。
以太网设备标准设备参数
标准以太网设备自变量允许一组适用于所有以太网设备的常用自变量/参数,可用于指定特定设备并将公共配置参数传递给这些端口。
representor
对于支持创建代表端口的设备,此参数允许用户指定要启用端口代表的交换机端口。-w DBDF,representor=0 -w DBDF,representor=[0,4,6,9] -w DBDF,representor=[0-31]
注意:不需要PMD支持标准设备参数,用户应查阅相关PMD文档以查看支持devargs。
扩展统计API
扩展的统计信息API允许PMD公开其可用的所有统计信息,包括设备唯一的统计信息。每个统计信息都有三个属性name
,id
以及value
:
name
:通过以下详细格式格式化的人类可读字符串。id
:仅代表该统计信息的整数。value
:一个无符号的64位整数,它是统计值。
请注意,扩展的统计信息标识符是特定于驱动程序的,因此对于不同的端口可能不相同。API由各种rte_eth_xstats_*()
功能组成,并允许应用程序灵活地检索统计信息。
人类可读名称方案
存在针对API客户端公开的字符串的命名方案。这是为了抓取API以获得感兴趣的统计信息。命名方案使用由单个下划线分隔的字符串_
。该方案如下:
- direction
- detail 1
- detail 2
- detail n
- unit
通用统计信息xstats字符串的示例,其格式符合上述建议的格式:
rx_bytes
rx_crc_errors
tx_multicast_packets
该方案虽然非常简单,但可以灵活地显示和读取统计字符串中的信息。以下示例说明了命名方案:rx_packets
。在此示例中,字符串被分为两个部分。第一个组件rx
指示该统计信息与NIC的接收方关联。第二部分packets
表示度量单位是数据包。
一个更复杂的示例:tx_size_128_to_255_packets
。在该示例中, tx
指示传输,size
是第一细节128
等是更多细节,并且packets
指示这是分组计数器。
元数据方案中的一些新增内容如下:
- 如果第一部分不匹配
rx
或tx
,则该统计信息与发送的任何接收都没有关联。 - 如果第二部分的第一个字母为,
q
且q
后跟数字,则此统计信息是特定队列的一部分。
使用队列号的示例如下:tx_q7_bytes
它指示此统计信息适用于队列号7,并表示该队列上已传输的字节数。
API设计
该xstats API使用name
,id
以及value
允许特定统计的高性能查找。执行者查询意味着两件事;
- 没有字符串与
name
快速路径中的统计信息进行比较 - 仅允许请求感兴趣的统计信息
API通过将name
统计信息映射到unique来确保满足这些要求,该unique id
用作在快速路径中查找的关键字。该API允许应用程序请求一个id
值数组,以便PMD仅执行所需的计算。预期的用法是应用程序扫描name
每个统计信息的,并缓存id
它是否对该统计信息感兴趣。在快速路径上,整数可用于检索value
所id
代表的统计信息的实际值。
API函数
该API由少量功能构建而成,可用于检索统计信息的数量以及这些统计信息的名称,ID和值。
rte_eth_xstats_get_names_by_id()
:返回统计信息的名称。给定NULL
参数后,函数将返回可用统计信息的数量。rte_eth_xstats_get_id_by_name()
:搜索匹配的统计IDxstat_name
。如果找到,id
则设置整数。rte_eth_xstats_get_by_id()
:填写uint64_t
与提供的ids
数组匹配的值的数组。如果ids
数组为NULL,则返回所有可用的统计信息。
应用用途
想象一个应用程序想要查看丢弃的数据包计数。如果没有丢包,则出于性能原因,应用程序不会读取任何其他指标。如果丢包,则应用程序具有其请求的一组特定统计信息。此统计信息集使应用可以决定要执行的下一步。以下代码片段展示了如何使用xstats API实现此目标。
第一步是获取所有统计信息名称并列出它们:
struct rte_eth_xstat_name *xstats_names;
uint64_t *values;
int len, i;/* Get number of stats */
len = rte_eth_xstats_get_names_by_id(port_id, NULL, NULL, 0);
if (len < 0) {printf("Cannot get xstats count\n");goto err;
}xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
if (xstats_names == NULL) {printf("Cannot allocate memory for xstat names\n");goto err;
}/* Retrieve xstats names, passing NULL for IDs to return all statistics */
if (len != rte_eth_xstats_get_names_by_id(port_id, xstats_names, NULL, len)) {printf("Cannot get xstat names\n");goto err;
}values = malloc(sizeof(values) * len);
if (values == NULL) {printf("Cannot allocate memory for xstats\n");goto err;
}/* Getting xstats values */
if (len != rte_eth_xstats_get_by_id(port_id, NULL, values, len)) {printf("Cannot get xstat values\n");goto err;
}/* Print all xstats names and values */
for (i = 0; i < len; i++) {printf("%s: %"PRIu64"\n", xstats_names[i].name, values[i]);
}
该应用程序可以访问PMD公开的所有统计信息的名称。应用程序可以确定感兴趣的统计信息,并通过如下查找名称来缓存那些统计信息的ID:
uint64_t value;
const char *xstat_name = "rx_errors";if(!rte_eth_xstats_get_id_by_name(port_id, xstat_name, &id)) {rte_eth_xstats_get_by_id(port_id, &id, &value, 1);printf("%s: %"PRIu64"\n", xstat_name, value);
}
else {printf("Cannot find xstats with a given name\n");goto err;
}
该API为应用程序提供了灵活性,因此它可以使用包含多个id
数字的数组来查找多个统计信息。这减少了检索统计信息的函数调用开销,并使多个统计信息的查找对于应用程序而言更加简单。
#define APP_NUM_STATS 4
/* application cached these ids previously; see above */
uint64_t ids_array[APP_NUM_STATS] = {3,4,7,21};
uint64_t value_array[APP_NUM_STATS];/* Getting multiple xstats values from array of IDs */
rte_eth_xstats_get_by_id(port_id, ids_array, value_array, APP_NUM_STATS);uint32_t i;
for(i = 0; i < APP_NUM_STATS; i++) {printf("%d: %"PRIu64"\n", ids_array[i], value_array[i]);
}
这个用于xstats的数组查找API允许应用程序创建多个“组”统计信息,并使用单个API调用查找这些ID的值。最终结果是,该应用程序能够实现监视单个统计信息(在这种情况下为“ rx_errors”)的目标,并且如果该信息显示数据包被丢弃,它可以使用IDs数组参数轻松检索“统计信息”发挥rte_eth_xstats_get_by_id
作用。
NIC重置API
int rte_eth_dev_reset (uint16_t port_id);
有时必须被动重置端口。例如,当重置PF时,应用程序还应重置其所有VF,以使其与PF一致。DPDK应用程序也可以调用此函数来触发端口重置。通常,当检测到RTE_ETH_EVENT_INTR_RESET事件时,DPDK应用程序将调用此函数。
PMD的职责是触发RTE_ETH_EVENT_INTR_RESET事件,并且应用程序应注册一个回调函数来处理这些事件。当PMD需要触发复位时,它可以触发RTE_ETH_EVENT_INTR_RESET事件。收到RTE_ETH_EVENT_INTR_RESET事件后,应用程序可以按以下方式处理它:停止工作队列,停止调用Rx和Tx函数,然后再调用rte_eth_dev_reset()。为了线程安全,所有这些操作应从同一线程调用。
例如,当PF复位时,PF会发送一条消息通知VF此事件,并向VF触发中断。然后,在中断服务程序中,VF检测到该通知消息并调用_rte_eth_dev_callback_process(dev,RTE_ETH_EVENT_INTR_RESET,NULL)。这意味着PF重置会触发VF中的RTE_ETH_EVENT_INTR_RESET事件。函数_rte_eth_dev_callback_process()将调用已注册的回调函数。回调函数可以触发应用程序处理VF重置所需的所有操作,包括停止Rx / Tx队列和调用rte_eth_dev_reset()。
rte_eth_dev_reset()本身是一个泛型函数,它仅通过调用dev_unint()和dev_init()来执行一些硬件重置操作,并且本身不处理由应用程序处理的同步。
PMD本身不应调用rte_eth_dev_reset()。PMD可以触发应用程序处理重置事件。应用程序有责任在调用rte_eth_dev_reset()之前处理所有同步。