以下是一个简单的DPDK程序,并且针对每行代码进行了详细的注释说明:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#define RX_RING_SIZE 128
#define TX_RING_SIZE 512
static const struct rte_eth_conf port_conf_default = {
.rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN }
};
int main(int argc, char *argv[])
{
int ret;
/* 初始化EAL环境 */
ret = rte_eal_init(argc, argv);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot init EAL\n");
/* 获取设备数量 */
uint16_t nb_ports = rte_eth_dev_count_avail();
if (nb_ports < 1)
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
/* 配置第一个端口 */
struct rte_eth_conf port_conf = port_conf_default;
const uint16_t portid = 0;
ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", ret, portid);
/* 分配并设置RX队列 */
ret = rte_eth_rx_queue_setup(portid, 0, RX_RING_SIZE, rte_eth_dev_socket_id(portid), NULL, NULL);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot setup RX queue: err=%d, port=%u\n", ret, portid);
/* 分配并设置TX队列 */
ret = rte_eth_tx_queue_setup(portid, 0, TX_RING_SIZE, rte_eth_dev_socket_id(portid), NULL);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot setup TX queue: err=%d, port=%u\n", ret, portid);
/* 启动设备 */
ret = rte_eth_dev_start(portid);
if (ret < 0)
rte_exit(EXIT_FAILURE, "Cannot start device: err=%d, port=%u\n", ret, portid);
printf("Success!\n");
return 0;
}
这个简单的程序实现了如下的功能:
- 初始化EAL(Environment Abstraction Layer)环境,是DPDK框架的一个重要组成部分。主要用于系统初始化、内存分配等。
- 获取网卡设备数量,并检查是否有可用的网卡。
- 配置第一个网卡端口。
- 分配并设置接收(RX)队列和发送(TX)队列。
- 启动指定的网卡设备。
- 输出成功信息。
注释详解:
第1到9行:包含所需要使用的各种头文件。
第11到12行:定义了接收和发送队列的大小。
第14行:定义了一个结构体变量port_conf_default,该结构体定义了端口的默认配置,我们在后面会将其作为参数传递给端口配置函数。
第16至25行:main()函数,从命令行参数中读取参数,以便初始化DPDK运行时环境。
第27到31行:如果无法初始化EAL环境则退出程序,其中rte_exit()函数是DPDK中提供的一个用于安全退出程序的API。
第33行:获取系统中网卡设备的数量。
第34至37行:如果没有可用的网卡,则退出程序执行。
第39到43行:定义了端口配置结构体变量port_conf,并将其初始化为默认配置port_conf_default。我们将在后面的代码中使用该结构体变量作为参数传递给端口配置函数。
第44行:定义了一个变量portid,表示要操作的网卡设备的端口号,0表示第一个网卡设备。
第45至49行:使用rte_eth_dev_configure()函数配置网卡设备,其中使用&port_conf来指定使用刚刚定义的端口配置结构体变量port_conf。
第51至55行:使用rte_eth_rx_queue_setup()函数分配接收队列,并使用rte_eth_dev_socket_id()函数确定要运行网卡设备的NUMA节点,并将其设置为NULL代表不使用共享内存池(shared memory pool)。
第57至61行:使用rte_eth_tx_queue_setup()函数分配发送队列,并使用rte_eth_dev_socket_id()函数确定要运行网卡设备的NUMA节点。
第63至67行:使用rte_eth_dev_start()函数启动网卡设备。
第69行:输出成功信息并退出程序使其终止。