DPDK端口初始化过程解析

一、端口初始化代码

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");

    }

}

代码功能概述:通过获取网口信息,配置网卡接收队列数、发送队列数,设置发送和接收队列,并启动以太网设备,进行以太网设备端口的初始化。

二、各函数功能

1.rte_eth_dev_count_avail()。

概念:用于获取当前可用(指已经通过 DPDK 绑定(或绑定到 DPDK 驱动程序)的网卡)的以太网设备(网卡端口,非传输层端口)的数量。

函数原型:

#include <rte_ethdev.h>

uint16_t rte_eth_dev_count_avail(void );

返回可用的以太网设备的数量。

2.rte_eth_dev_info_get()

概念:根据port_id端口号检索以太网设备的上下文信息,若检索成功,信息保存到dev_info变量中。

函数原型:

#include <rte_ethdev.h>

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 <rte_ethdev.h>

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];:保留的指针数组。

};

3.rte_eth_dev_configure()

概念:它用于初始化和配置网卡设备的各种属性,以便设备能够进行数据包的接收和发送。

必须先调用此函数,然后再调用以太网 API 中的任何其他函数。当设备处于停止状态时,也可以重新调用此函数。

函数原型:

#include <rte_ethdev.h>

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的队列概念:

  1. 接收队列(Rx Queue)

    • 接收队列用于从网络接口卡接收数据包。一个 DPDK 端口(以太网设备)通常会有多个接收队列,每个队列对应一个物理或虚拟队列,用于并行接收数据包。
    • 接收队列通常配置为循环使用环形缓冲区,以提高性能。DPDK 使用 ring buffer 来实现这种循环队列,数据包被放置到队列的尾部,并从队列的头部被取出进行处理。
  2. 发送队列(Tx Queue)

    • 发送队列用于将数据包发送到网络接口卡,以便进一步发送到网络。一个 DPDK 端口通常也有多个发送队列,每个队列对应一个物理或虚拟队列,用于并行发送数据包。
    • 发送队列通常也配置为循环使用环形缓冲区,以提高性能。数据包从应用程序的缓冲区被放置到发送队列,并从队列的尾部被取出发送到网络。
  3. 队列数量

    • DPDK 应用程序可以根据需要配置多个接收和发送队列,以充分利用多核处理器的性能。多个队列可以并行处理多个数据包,提高了数据包处理的并发性能。
  4. 队列的配置

    • DPDK 允许应用程序配置队列的参数,如队列的大小、硬件卸载功能、队列深度等。这些配置参数可以根据应用程序的需求进行调整,以获得最佳性能。
  5. 队列的处理

    • 在 DPDK 应用程序中,队列通常由不同的处理线程或核心处理。每个队列的处理线程可以执行特定的数据包处理任务,如数据包分析、修改、路由等。
  6. 队列与多核处理器

    • DPDK 旨在充分利用多核处理器的性能。通过将不同队列分配给不同核心的处理线程,可以实现数据包处理的并行性,从而提高吞吐量。
  7. 队列的同步与协调

    • 在多核处理器上并行处理多个队列时,需要考虑队列之间的同步和协调问题。DPDK 提供了各种同步机制和 API,以确保队列之间的数据包处理不会发生冲突或竞争条件。

总之,DPDK 的队列概念是实现高性能数据包处理的关键。通过合理配置和管理接收和发送队列,以及合理分配队列给多核处理器的处理线程,可以实现高性能的数据包处理应用程序。队列的概念使 DPDK 应用程序能够充分利用多核处理器的性能,同时确保数据包的高效处理和传递。

struct rte_eth_conf:

 用于配置以太网端口的结构。根据Rx多队列模式,可能需要额外的高级配置设置。

#include <rte_ethdev.h>

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结构体讲解:

  1. uint32_t link_speeds

    • 用于指定以太网链路的速度配置。您可以将所支持的链路速度的位掩码设置为此字段的值,以表示设备支持的链路速度。例如,如果设备支持 1G 和 10G 速度,则可以将此字段设置为 ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G
  2. struct rte_eth_rxmode rxmode

    • 用于配置接收模式的结构体,包括接收队列的配置参数。该结构体包含了以下字段:
      • uint32_t mq_mode:用于指定接收队列的多队列模式,例如 ETH_MQ_RX_RSS(RSS 模式)或 ETH_MQ_RX_NONE(单队列模式)。
      • uint32_t max_rx_pkt_len:用于指定接收的最大数据包长度。
  3. struct rte_eth_txmode txmode

    • 用于配置发送模式的结构体,包括发送队列的配置参数。该结构体包含了以下字段:
      • uint32_t mq_mode:用于指定发送队列的多队列模式,例如 ETH_MQ_TX_NONE(单队列模式)。
      • int32_t pvid:用于指定发送数据包的 VLAN ID。
  4. uint32_t lpbk_mode

    • 用于配置环回模式。可以设置为以下值之一:
      • 0:关闭环回模式。
      • ETH_LPBK_PHY:物理环回模式。
      • ETH_LPBK_MAC:逻辑环回模式。
  5. 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 接收参数。
  6. 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 发送参数。
  7. uint32_t dcb_capability_en

    • 用于启用或禁用 Data Center Bridging(DCB)能力。可以设置为 0(禁用)或 1(启用)。
  8. struct rte_eth_fdir_conf fdir_conf

    • 用于配置流识别功能的参数,包括过滤器和流识别表的配置。
  9. struct rte_eth_intr_conf intr_conf

    • 用于配置中断处理的参数,包括中断分配策略和中断处理函数。

4.rte_eth_rx_queue_setup()

概念:它用于初始化和配置 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 结构体的指针,表示数据包缓冲区的内存池。

5.rte_eth_dev_socket_id()

概念:返回以太网设备连接到的NUMA套接字。

#include <rte_ethdev.h>

int rte_eth_dev_socket_id(uint16_t 	port_id)	

port_id:以太网设备的端口标识符。

返回:以太网设备连接到的NUMA套接字ID,如果无法确定套接字,则默认为零。当port_id值超出范围时返回-1。

6.rte_eth_tx_queue_setup()

概念:分配并初始化以太网设备的传输队列。

函数原型:

#include <rte_ethdev.h>

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_idsocket_id参数是 NUMA 情况下的套接字标识符。如果为环的传输描述符分配的 DMA 内存没有 NUMA 约束,则可以使用SOCKET_ID_ANY。
tx_conf使用传输队列的配置数据的指针。允许使用 NULL 值。

7.rte_eth_dev_start()

概念:启动以太网设备。

设备启动步骤是最后一个步骤,包括设置配置的卸载功能以及启动设备的发送和接收单元。

函数原型:

#include <rte_ethdev.h>

int rte_eth_dev_start(uint16_t port_id);

成功返回0;

失败返回负数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值