DPDK配置网卡FDIR

在DPDK中,使用流量分布(FDIR)功能可以对数据包进行流分类和过滤操作。以下是一个DPDK配置网卡FDIR的代码示例:

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdbool.h>
#include <rte_eal.h>
#include <rte_ethdev.h>

#define NUM_RX_DESC 128
#define NUM_TX_DESC 512
#define MBUF_POOL_SIZE 8191

#define FDIR_MAX_RULE_NUM 1024
#define FDIR_MAX_FLEXLEN 128

int main(int argc, char *argv[])
{
    int ret;
    uint16_t nb_ports;
    uint16_t port_id;
    struct rte_eth_dev_info dev_info;
    struct rte_eth_conf port_conf;
    struct rte_eth_rxconf rx_conf;
    struct rte_eth_txconf tx_conf;
    struct rte_mempool *mbuf_pool;
    struct rte_fdir_conf fdir_conf;
    struct rte_fdir_flex_conf flex_conf;
    struct rte_fdir_stats fdir_stats;
    struct rte_hash *fdir_hash;
    struct rte_fdir_masks fdir_masks;

    // 初始化 EAL
    ret = rte_eal_init(argc, argv);
    if (ret < 0) {
        rte_panic("Failed to initialize EAL: %s\n", rte_strerror(ret));
    }

    // 获取可用的网卡端口数
    nb_ports = rte_eth_dev_count_avail();
    if (nb_ports == 0) {
        rte_panic("No Ethernet ports found.\n");
    }

    // 配置网卡设备
    for (port_id = 0; port_id < nb_ports; port_id++) {
        rte_eth_dev_info_get(port_id, &dev_info);
        printf("Initializing port %u...\n", port_id);

        // 配置 RX 和 TX 环形队列
        rx_conf = dev_info.default_rxconf;
        rx_conf.rx_drop_en = 1;
        tx_conf = dev_info.default_txconf;
        tx_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE;

        // 配置流控制和RSS
        port_conf = dev_info.default_conf;
        port_conf.rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
        port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
        port_conf.rx_adv_conf.rss_conf.rss_key = NULL;
        port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IPV4 | ETH_RSS_TCP | ETH_RSS_UDP;
        port_conf.rx_adv_conf.flow_control_conf.mode = RTE_FC_FULL;

        // 初始化网卡设备
        ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
        if (ret < 0) {
            rte_panic("Failed to configure Ethernet port %u: %s\n",
                      port_id, rte_strerror(ret));
        }

        // 配置 RX 和 TX 环形队列
        ret = rte_eth_rx_queue_setup(port_id, 0, NUM_RX_DESC,
                                     rte_eth_dev_socket_id(port_id),
                                     &rx_conf, mbuf_pool);
        if (ret < 0) {
            rte_panic("Failed to setup Rx queue for port %u: %s\n",
                      port_id, rte_strerror(ret));
        }

        ret = rte_eth_tx_queue_setup(port_id, 0, NUM_TX_DESC,
                                     rte_eth_dev_socket_id(port_id),
                                     &tx_conf);
        if (ret < 0) {
            rte_panic("Failed to setup Tx queue for port %u: %s\n",
                      port_id, rte_strerror(ret));
        }

        // 启动网卡设备
        ret = rte_eth_dev_start(port_id);
        if (ret < 0) {
            rte_panic("Failed to start Ethernet port %u: %s\n",
                      port_id, rte_strerror(ret));
        }

        printf("Port %u initialization completed.\n", port_id);
    }

    // 创建内存池
    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", MBUF_POOL_SIZE,
                                        256, 0, 2048,
                                        rte_socket_id());
    if (mbuf_pool == NULL) {
        rte_panic("Failed to create packet mbuf pool.\n");
    }

    // 配置FDIR功能
    memset(&fdir_masks, 0, sizeof(fdir_masks));
    memset(&fdir_conf, 0, sizeof(fdir_conf));
    memset(&flex_conf, 0, sizeof(flex_conf));
    fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
    fdir_conf.pballoc = RTE_FDIR_PBALLOC_64K;
    fdir_conf.status = RTE_FDIR_REPORT_STATUS;
    fdir_conf.drop_queue = 127;

    // 配置FDIR规则
    fdir_conf.nb_fdir = FDIR_MAX_RULE_NUM;

    // 配置FDIR灵活报文协议
    flex_conf.nb_payloads = 1;
    flex_conf.nb_flexmasks = 1;
    flex_conf.flex_set[0].type = RTE_ETH_RAW_PAYLOAD;
    flex_conf.flex_set[0].src_offset = 20;
    flex_conf.flex_set[0].dst_offset = 0;
    flex_conf.flex_set[0].src_size = 12;
    flex_conf.flex_set[0].dst_size = 12;
    flex_conf.flex_mask[0].flow_type = RTE_ETH_FLOW_UNKNOWN;
    flex_conf.flex_mask[0].mask = "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00";
    fdir_conf.flex_conf = &flex_conf;

    // 创建FDIR哈希表
    fdir_hash = rte_hash_create(NULL, FDIR_MAX_RULE_NUM, sizeof(uint32_t),
                                RTE_HASH_FLAGS_DEFAULT);
    if (fdir_hash == NULL) {
        rte_panic("Failed to create FDIR hash table.\n");
    }
    fdir_conf.hash_func = rte_hash_crc;
    fdir_conf.hash_table = fdir_hash;

    // 配置FDIR功能
    ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
                                  RTE_ETH_FILTER_ADD, &fdir_conf);
    if (ret < 0) {
        rte_panic("Failed to configure FDIR for port %u: %s\n",
                  port_id, rte_strerror(ret));
    }

    // 获取FDIR统计信息
    rte_eth_fdir_get_stats(port_id, &fdir_stats);
    printf("FDIR hit count: %u, missed count: %u\n",
           fdir_stats.fdirhash_match, fdir_stats.fdirhash_miss);

    return 0;
}

在这段代码中,我们通过配置struct rte_fdir_conf以及相关的哈希表来启用FDIR功能。具体而言,我们使用了rte_eth_dev_filter_ctrl()库函数来启用FDIR功能,用rte_hash_create()函数创建了哈希表,用rte_eth_fdir_get_stats()函数获取了FDIR统计信息。此外,我们使用struct rte_fdir_flex_conf结构体来配置FDIR灵活报文协议。这些配置将使DPDK能够使用指定的网卡进行流分类和过滤操作。

DPDK/网络虚拟化 相关学习资料、视频教程 学习交流群:739729163 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值