int gDpdkPortId = 0;
static const struct rte_eth_conf port_conf_default = {
.rxmode = {.max_rx_pkt_len = RTE_ETHER_MAX_LEN }
};
static void ng_init_port(struct rte_mempool *mbuf_pool) {
uint16_t nb_sys_ports= rte_eth_dev_count_avail(); //
if (nb_sys_ports == 0) {
rte_exit(EXIT_FAILURE, "No Supported eth found\n");
}
struct rte_eth_dev_info dev_info;
rte_eth_dev_info_get(gDpdkPortId, &dev_info); // 可以使用这些信息来确定设备支持的功能、配置接收和发送队列的数量、设置MTU大小等。
const int num_rx_queues = 1;
const int num_tx_queues = 1;
struct rte_eth_conf port_conf = port_conf_default;
rte_eth_dev_configure(gDpdkPortId, num_rx_queues, num_tx_queues, &port_conf);
if (rte_eth_rx_queue_setup(gDpdkPortId, 0 , 1024,
rte_eth_dev_socket_id(gDpdkPortId),NULL, mbuf_pool) < 0) {
rte_exit(EXIT_FAILURE, "Could not setup RX queue\n");
}
#if ENABLE_SEND
struct rte_eth_txconf txq_conf = dev_info.default_txconf;
txq_conf.offloads = port_conf.rxmode.offloads;
if (rte_eth_tx_queue_setup(gDpdkPortId, 0 , 1024,
rte_eth_dev_socket_id(gDpdkPortId), &txq_conf) < 0) {
rte_exit(EXIT_FAILURE, "Could not setup TX queue\n");
}
#endif
if (rte_eth_dev_start(gDpdkPortId) < 0 ) {
rte_exit(EXIT_FAILURE, "Could not start\n");
}
}
代码功能概述:通过获取网口信息,配置网卡接收队列数、发送队列数,设置发送和接收队列,并启动以太网设备,进行以太网设备端口的初始化。
概念:用于获取当前可用(指已经通过 DPDK 绑定(或绑定到 DPDK 驱动程序)的网卡)的以太网设备(网卡端口,非传输层端口)的数量。
函数原型:
#include
uint16_t rte_eth_dev_count_avail(void ); 返回可用的以太网设备的数量。
概念:根据port_id端口号检索以太网设备的上下文信息,若检索成功,信息保存到dev_info变量中。
函数原型:
#include
int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info * dev_info); 参数:
- port_id:以太网设备的端口标识符。
- dev_info:指向rte_eth_dev_info类型的结构的指针,以填充以太网设备的上下文信息。
返回值:
- 0:成功。
- ENOTSUP:设备不支持 dev_infos_get()。
- ENODEV:port_id无效。
- EINVAL: 参数错误。
struct rte_eth_dev_info:(用于存储获取到的设备信息)
#include
struct rte_eth_dev_info{
struct rte_device *device;
:指向设备的指针,可以用于访问底层设备信息。
const char *driver_name;
:设备驱动程序的名称,指示设备所使用的 DPDK 驱动程序。
unsigned int if_index;
:设备的网络接口索引。
uint16_t min_mtu;
:最小的最大传输单元(MTU),即可以设置给设备的最小数据包大小。
uint16_t max_mtu;
:最大的最大传输单元(MTU),即可以设置给设备的最大数据包大小。
const uint32_t *dev_flags;
:指向设备标志的指针,用于标识设备的各种特性和支持的功能。
uint32_t min_rx_bufsize;
:接收缓冲区的最小大小。
uint32_t max_rx_pktlen;
:接收数据包的最大长度。
uint32_t max_lro_pkt_size;
:支持的最大大数据包 LRO(Large Receive Offload)的大小。
uint16_t max_rx_queues;
:最大接收队列数。
uint16_t max_tx_queues;
:最大发送队列数。
uint32_t max_mac_addrs;
:最大支持的 MAC 地址数。
uint32_t max_hash_mac_addrs;
:最大支持的哈希表中的 MAC 地址数。
uint16_t max_vfs;
:最大虚拟功能数(如果设备支持 SR-IOV)。
uint16_t max_vmdq_pools;
:最大支持的 VMDq(Virtual Machine Device Queues) 池数。
struct rte_eth_rxseg_capa rx_seg_capa;
:接收段(Rx Segment)的能力描述。
uint64_t rx_offload_capa;
:接收数据包的硬件卸载功能的能力标志。
uint64_t tx_offload_capa;
:发送数据包的硬件卸载功能的能力标志。
uint64_t rx_queue_offload_capa;
:接收队列的硬件卸载功能的能力标志。
uint64_t tx_queue_offload_capa;
:发送队列的硬件卸载功能的能力标志。
uint16_t reta_size;
:可配置的 RSS(Receive Side Scaling)哈希表条目数。
uint8_t hash_key_size;
:哈希计算所需的哈希键的大小(以字节为单位)。
uint64_t flow_type_rss_offloads;
:支持 RSS 的数据流类型标志。
struct rte_eth_rxconf default_rxconf;
:默认的接收配置。
struct rte_eth_txconf default_txconf;
:默认的发送配置。
uint16_t vmdq_queue_base;
:VMDq 队列的基本索引。
uint16_t vmdq_queue_num;
:VMDq 队列的数量。
uint16_t vmdq_pool_base;
:VMDq 池的基本索引。
struct rte_eth_desc_lim rx_desc_lim;
:接收队列描述符限制的配置。
struct rte_eth_desc_lim tx_desc_lim;
:发送队列描述符限制的配置。
uint32_t speed_capa;
:设备支持的速度能力。
uint16_t nb_rx_queues;
:接收队列的数量。
uint16_t nb_tx_queues;
:发送队列的数量。
struct rte_eth_dev_portconf default_rxportconf;
:默认的接收端口配置。
struct rte_eth_dev_portconf default_txportconf;
:默认的发送端口配置。
uint64_t dev_capa;
:设备的能力标志。
struct rte_eth_switch_info switch_info;
:与交换机相关的信息。
uint64_t reserved_64s[2];
:保留的 64 位整数数组。
void *reserved_ptrs[2];
:保留的指针数组。};
概念:它用于初始化和配置网卡设备的各种属性,以便设备能够进行数据包的接收和发送。
必须先调用此函数,然后再调用以太网 API 中的任何其他函数。当设备处于停止状态时,也可以重新调用此函数。
函数原型:
#include
int rte_eth_dev_configure( uint16_t port_id, uint16_t nb_rx_queue, uint16_t nb_tx_queue, const struct rte_eth_conf * eth_conf ); 参数说明:
参数 含义 port_id 要配置的以太网设备的端口标识符。 nb_rx_queue 要为以太网设备设置的接收队列数。 nb_tx_queue 要为以太网设备设置的传输队列数。 eth_conf 一个指向 struct rte_eth_conf
结构体的指针,包含了以太网设备的配置信息。注:这里配置的接收和发送队列是dpdk队列,而不是硬件队列,在下文有详细解释。
返回值:
- 0:成功,设备已配置。
- <0:驱动程序配置函数返回的错误代码。
dpdk的队列概念:
接收队列(Rx Queue):
- 接收队列用于从网络接口卡接收数据包。一个 DPDK 端口(以太网设备)通常会有多个接收队列,每个队列对应一个物理或虚拟队列,用于并行接收数据包。
- 接收队列通常配置为循环使用环形缓冲区,以提高性能。DPDK 使用 ring buffer 来实现这种循环队列,数据包被放置到队列的尾部,并从队列的头部被取出进行处理。
发送队列(Tx Queue):
- 发送队列用于将数据包发送到网络接口卡,以便进一步发送到网络。一个 DPDK 端口通常也有多个发送队列,每个队列对应一个物理或虚拟队列,用于并行发送数据包。
- 发送队列通常也配置为循环使用环形缓冲区,以提高性能。数据包从应用程序的缓冲区被放置到发送队列,并从队列的尾部被取出发送到网络。
队列数量:
- DPDK 应用程序可以根据需要配置多个接收和发送队列,以充分利用多核处理器的性能。多个队列可以并行处理多个数据包,提高了数据包处理的并发性能。
队列的配置:
- DPDK 允许应用程序配置队列的参数,如队列的大小、硬件卸载功能、队列深度等。这些配置参数可以根据应用程序的需求进行调整,以获得最佳性能。
队列的处理:
- 在 DPDK 应用程序中,队列通常由不同的处理线程或核心处理。每个队列的处理线程可以执行特定的数据包处理任务,如数据包分析、修改、路由等。
队列与多核处理器:
- DPDK 旨在充分利用多核处理器的性能。通过将不同队列分配给不同核心的处理线程,可以实现数据包处理的并行性,从而提高吞吐量。
队列的同步与协调:
- 在多核处理器上并行处理多个队列时,需要考虑队列之间的同步和协调问题。DPDK 提供了各种同步机制和 API,以确保队列之间的数据包处理不会发生冲突或竞争条件。
总之,DPDK 的队列概念是实现高性能数据包处理的关键。通过合理配置和管理接收和发送队列,以及合理分配队列给多核处理器的处理线程,可以实现高性能的数据包处理应用程序。队列的概念使 DPDK 应用程序能够充分利用多核处理器的性能,同时确保数据包的高效处理和传递。
struct rte_eth_conf:
用于配置以太网端口的结构。根据Rx多队列模式,可能需要额外的高级配置设置。
#include
struct rte_eth_conf{
uint32_t link_speeds;
struct rte_eth_rxmode rxmode;
struct rte_eth_txmode txmode;
uint32_t lpbk_mode;
struct {
struct rte_eth_rss_conf rss_conf;
struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf;
struct rte_eth_dcb_rx_conf dcb_rx_conf;
struct rte_eth_vmdq_rx_conf vmdq_rx_conf;
} rx_adv_conf;
union {
struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf;
struct rte_eth_dcb_tx_conf dcb_tx_conf;
struct rte_eth_vmdq_tx_conf vmdq_tx_conf;
} tx_adv_conf;
uint32_t dcb_capability_en;
struct rte_eth_fdir_conf fdir_conf;
struct rte_eth_intr_conf intr_conf;
};
rte_eth_conf结构体讲解:
uint32_t link_speeds
:
- 用于指定以太网链路的速度配置。您可以将所支持的链路速度的位掩码设置为此字段的值,以表示设备支持的链路速度。例如,如果设备支持 1G 和 10G 速度,则可以将此字段设置为
ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G
。
struct rte_eth_rxmode rxmode
:
- 用于配置接收模式的结构体,包括接收队列的配置参数。该结构体包含了以下字段:
uint32_t mq_mode
:用于指定接收队列的多队列模式,例如 ETH_MQ_RX_RSS(RSS 模式)或 ETH_MQ_RX_NONE(单队列模式)。uint32_t max_rx_pkt_len
:用于指定接收的最大数据包长度。
struct rte_eth_txmode txmode
:
- 用于配置发送模式的结构体,包括发送队列的配置参数。该结构体包含了以下字段:
uint32_t mq_mode
:用于指定发送队列的多队列模式,例如 ETH_MQ_TX_NONE(单队列模式)。int32_t pvid
:用于指定发送数据包的 VLAN ID。
uint32_t lpbk_mode
:
- 用于配置环回模式。可以设置为以下值之一:
0
:关闭环回模式。ETH_LPBK_PHY
:物理环回模式。ETH_LPBK_MAC
:逻辑环回模式。
struct rx_adv_conf
:
- 用于配置接收高级参数的结构体,包括 RSS(Receive Side Scaling)配置、DCB(Data Center Bridging)配置等。这是一个嵌套结构体,包含以下子结构体:
struct rte_eth_rss_conf rss_conf
:用于配置 RSS 参数。struct rte_eth_vmdq_dcb_conf vmdq_dcb_conf
:用于配置 VMDQ DCB 参数。struct rte_eth_dcb_rx_conf dcb_rx_conf
:用于配置 DCB 接收参数。struct rte_eth_vmdq_rx_conf vmdq_rx_conf
:用于配置 VMDQ 接收参数。
union tx_adv_conf
:
- 用于配置发送高级参数的联合体。这是一个联合体,包含以下子结构体之一,根据发送队列的配置类型不同而使用不同的子结构体:
struct rte_eth_vmdq_dcb_tx_conf vmdq_dcb_tx_conf
:用于配置 VMDQ DCB 发送参数。struct rte_eth_dcb_tx_conf dcb_tx_conf
:用于配置 DCB 发送参数。struct rte_eth_vmdq_tx_conf vmdq_tx_conf
:用于配置 VMDQ 发送参数。
uint32_t dcb_capability_en
:
- 用于启用或禁用 Data Center Bridging(DCB)能力。可以设置为
0
(禁用)或1
(启用)。
struct rte_eth_fdir_conf fdir_conf
:
- 用于配置流识别功能的参数,包括过滤器和流识别表的配置。
struct rte_eth_intr_conf intr_conf
:
- 用于配置中断处理的参数,包括中断分配策略和中断处理函数。
概念:它用于初始化和配置 DPDK 端口上的接收队列,以便从网络接口卡(NIC)接收数据包。
int rte_eth_rx_queue_setup (uint16_t port_id, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool);
参数说明:
- port_id:要配置接收队列的 DPDK 端口 ID。
- rx_queue_id:接收队列的唯一标识符,通常从 0 开始递增。
- nb_rx_desc:接收队列中能容纳的描述符数量。描述符是用于存储接收数据包的内存块。
- socket_id:指定接收队列内存分配所使用的 NUMA 套接字。
- rx_conf:一个指向 struct rte_eth_rxconf 结构体的指针,用于配置接收队列的参数。这个结构体包含了接收队列的各种配置选项,例如接收队列的模式、偏好配置等。常见的配置选项包括:
- rx_free_thresh:接收队列中缓冲区的数量,低于此阈值时将触发数据包的接收。
- rx_drop_en:启用或禁用在接收队列上丢弃接收队列满的数据包。
- 其他与接收队列相关的配置项。
- mb_pool:一个指向 struct rte_mempool 结构体的指针,表示数据包缓冲区的内存池。
概念:返回以太网设备连接到的NUMA套接字。
#include
int rte_eth_dev_socket_id(uint16_t port_id) port_id:以太网设备的端口标识符。
返回:以太网设备连接到的NUMA套接字ID,如果无法确定套接字,则默认为零。当port_id值超出范围时返回-1。
概念:分配并初始化以太网设备的传输队列。
函数原型:
#include
int rte_eth_tx_queue_setup( uint16_t port_id, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf * tx_conf ); 成功,返回0,发送队列正确建立。
失败,返回-ENOMEM,无法分配传输环描述符。
参数 含义 port_id 以太网设备的端口标识符。 tx_queue_id 要设置的传输队列的索引。该值必须在之前提供给 rte_eth_dev_configure() 的发送队列数范围。 nb_tx_desc 要为传输环分配的传输描述符的数量。 socket_id socket_id参数是 NUMA 情况下的套接字标识符。如果为环的传输描述符分配的 DMA 内存没有 NUMA 约束,则可以使用SOCKET_ID_ANY。 tx_conf 使用传输队列的配置数据的指针。允许使用 NULL 值。
概念:启动以太网设备。
设备启动步骤是最后一个步骤,包括设置配置的卸载功能以及启动设备的发送和接收单元。
函数原型:
#include
int rte_eth_dev_start(uint16_t port_id); 成功返回0;
失败返回负数。