目录
在DPDK开发程序中,经常会出现需要验证网卡性能如何,什么时候丢包与否,这时应该使用哪个函数呢? 本文从实际应用讲解收发包最常用的测试函数rte_eth_stats_get。
一、DPDK
DPDK(Data Plane Development Kit)是一个用于快速数据包处理的开源软件框架。它提供了一组库和驱动程序,使开发者能在用户空间高效处理网络数据包,绕过传统的内核协议栈,从而大幅提高网络处理性能。DPDK 支持多种硬件平台,广泛应用于网络功能虚拟化(NFV)、软件定义网络(SDN)、高性能网络设备等领域,能帮助实现高速、低延迟的网络数据处理,满足现代网络应用对性能的苛刻要求。
二、rte_eth_stats_get简介
rte_eth_stats_get是 DPDK(Data Plane Development Kit)里用于获取以太网设备统计信息的关键函数。
函数原型
int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
参数说明
- port_id:以太网设备端口的标识符,用于指定要获取统计信息的具体端口。
- stats:指向 struct rte_eth_stats 结构体的指针,该结构体用于存储获取到的以太网设备统计信息。
功能描述
此函数会从指定的以太网端口收集统计数据,并将其存储于传入的 struct rte_eth_stats
结构体中。这些统计信息涵盖接收和发送的数据包数量、字节数、错误包数量等,有助于开发者深入了解以太网设备的运行状况,例如是否存在丢包、收发流量是否正常等情况。
返回值
- 若执行成功,函数返回值为 0。
- 若出现错误,会返回一个负的错误码,以表明具体的错误类型。
三、rte_eth_stats_reset简介
rte_eth_stats_reset是 DPDK(Data Plane Development Kit)里用于重置以太网设备统计信息的函数。以下为详细介绍:
函数原型
int rte_eth_stats_reset(uint8_t port_id);
参数说明
- port_id:以太网设备端口的标识符,用来指定要重置统计信息的具体端口。
功能描述
该函数的主要功能是将指定以太网端口的统计计数器重置为零。这些统计计数器用于记录以太网设备的各种运行数据,如接收和发送的数据包数量、字节数、错误包数量、丢包数量等。在某些场景下,比如想要重新开始统计设备在某一时间段内的运行情况,就可以使用这个函数把之前的统计数据清零。
返回值
- 若执行成功,函数返回值为 0。
- 若出现错误,会返回一个负的错误码,以此表明具体的错误类型。
四、rte_eth_stats_get应用
其实,无论在dpdk的哪个版本中,dpdk的示例程序都提供了一个函数叫做nic_stats_display。这个函数调用的是rte_eth_stats_get获取到网卡的统计信息,然后将统计信息格式化打印出来呈现给用户,所以编写代码时,直接将这个函数内容进行简单修改即可,具体代码如下所示。
#include <rte_ethdev.h>
// 该函数用于显示指定网口的统计信息
// 参数 port_id 表示要获取统计信息的网口编号
void nic_stats_display(uint16_t port_id) {
// 定义一个 rte_eth_stats 结构体变量 stats,用于存储从网口获取的统计信息
struct rte_eth_stats stats;
// 调用 rte_eth_stats_get 函数获取指定网口的统计信息
// 该函数会将统计信息填充到 stats 结构体中
// 如果获取失败,rte_eth_stats_get 函数会返回非零值
if (rte_eth_stats_get(port_id, &stats) != 0) {
// 若获取失败,打印错误信息,提示用户无法获取该网口的统计信息
printf("Failed to get stats for port %u\n", port_id);
// 函数返回,不再继续执行后续的统计信息打印操作
return;
}
// 打印一个分隔线和当前网口的编号,用于区分不同网口的统计信息
printf("\n=== Port %u Statistics ===\n", port_id);
// 打印接收(RX)相关的基本统计信息
// stats.ipackets 表示接收到的数据包总数
printf("RX packets: %"PRIu64"\n", stats.ipackets);
// stats.ibytes 表示接收到的字节总数
printf("RX bytes: %"PRIu64"\n", stats.ibytes);
// stats.ierrors 表示接收过程中出现的错误总数
printf("RX errors: %"PRIu64"\n", stats.ierrors);
// 打印发送(TX)相关的基本统计信息
// stats.opackets 表示发送的数据包总数
printf("TX packets: %"PRIu64"\n", stats.opackets);
// stats.obytes 表示发送的字节总数
printf("TX bytes: %"PRIu64"\n", stats.obytes);
// stats.oerrors 表示发送过程中出现的错误总数
printf("TX errors: %"PRIu64"\n\n", stats.oerrors);
// 打印 DPDK 特有的高级统计信息
// stats.imissed 表示由于没有可用缓冲区而错过的接收数据包数量
printf("RX missed: %"PRIu64" (no free buffers)\n", stats.imissed);
// stats.rx_nombuf 表示在接收过程中内存缓冲区分配失败的次数
printf("RX no-MBUFS: %"PRIu64" (alloc failures)\n", stats.rx_nombuf);
}
nic_stats_display函数用于获取并显示指定网口的统计信息。它首先尝试获取网口的统计数据,如果获取成功,会打印包括接收和发送的数据包数量、字节数、错误数等基本统计信息,以及一些 DPDK 特有的高级统计信息。
需要注意的是,通常这个函数使用后,建议使用函数rte_eth_stats_reset(port_id);清空每个每个网卡的已有统计信息内容,使得每次显示的值,都是两次调用函数之间的数值,当然,如果你选择查看累计值,那么不要执行rte_eth_stats_reset(port_id);函数即可。我在公司负责经常负责性能调优,尤其是在性能测试时经常出现丢包现象,通过rte_eth_stats_reset和rte_eth_stats_get两个函数来自定义统计信息,可以发现丢包的具体原因,这两个函数真是帮了大忙了。