DPDK初始化Mellanox失败(mlx5)无法获取VF

记录一下,方便以后查阅。

错误如下

1、
EAL: VFIO support initialized
EAL: Probe PCI driver: mlx5_pci (15b3:101e) device: 0000:12:01.0 (socket 0)
mlx5_pci: no Verbs device matches PCI device 0000:12:01.0, are kernel drivers loaded?
common_mlx5: Failed to load driver = mlx5_pci.
EAL: Requested device 0000:b5:01.2 cannot be used
EAL: Bus (pci) probe failed.
EAL: No legacy callbacks, legacy socket not created

代码如下
code from:
https://github.com/zartbot/learn_dpdk

#include <stdint.h>
#include <unistd.h>
#include <inttypes.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_cycles.h>
#include <rte_lcore.h>
#include <rte_mbuf.h>
#include <rte_ether.h>
#include <rte_ip.h>
#include <rte_udp.h>
#include <pthread.h>
#include <string.h>

#define MAX_PORTS 16
#define RX_RING_SIZE 1024
#define TX_RING_SIZE 1024

#define NUM_MBUFS 8191
#define MBUF_CACHE_SIZE 250
#define BURST_SIZE 32

static int hwts_dynfield_offset = -1;

static inline rte_mbuf_timestamp_t *
hwts_field(struct rte_mbuf *mbuf)
{
 return RTE_MBUF_DYNFIELD(mbuf,
   hwts_dynfield_offset, rte_mbuf_timestamp_t *);
}

typedef uint64_t tsc_t;
static int tsc_dynfield_offset = -1;

static inline tsc_t *
tsc_field(struct rte_mbuf *mbuf)
{
 return RTE_MBUF_DYNFIELD(mbuf, tsc_dynfield_offset, tsc_t *);
}

static uint16_t
add_timestamps(uint16_t port __rte_unused, uint16_t qidx __rte_unused,
  struct rte_mbuf **pkts, uint16_t nb_pkts,
  uint16_t max_pkts __rte_unused, void *_ __rte_unused)
{
 unsigned i;
 uint64_t now = rte_rdtsc();

 for (i = 0; i < nb_pkts; i++)
  printf("packet[%d] sendtime: %ld\n",i,now);
 return nb_pkts;
}

static const struct rte_eth_conf port_conf_default = {
    .rxmode = {
        .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
    },
};

static inline int
port_init(uint16_t port, struct rte_mempool *mbuf_pool)
{
    struct rte_eth_conf port_conf = port_conf_default;
    const uint16_t rx_rings = 1, tx_rings = 1;
    uint16_t nb_rxd = RX_RING_SIZE;
    uint16_t nb_txd = TX_RING_SIZE;
    int retval;
    uint16_t q;
    struct rte_eth_dev_info dev_info;
    struct rte_eth_txconf txconf;

    if (!rte_eth_dev_is_valid_port(port))
        return -1;

    retval = rte_eth_dev_info_get(port, &dev_info);
    if (retval != 0)
    {
        printf("Error during getting device (port %u) info: %s\n",
               port, strerror(-retval));
        return retval;
    }
    printf("\n\ninitializing port %d...\n", port);


    if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_CHECKSUM)
    {
        printf("port[%u] support RX cheksum offload.\n", port);
        port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
    }


 if (!(dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP)) {
   printf("\nERROR: Port %u does not support hardware timestamping\n"
     , port);
   return -1;
  }
  port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
  rte_mbuf_dyn_rx_timestamp_register(&hwts_dynfield_offset, NULL);
  if (hwts_dynfield_offset < 0) {
   printf("ERROR: Failed to register timestamp field\n");
   return -rte_errno;
 }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
    {
        printf("port[%u] support TX mbuf fast free offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE;
    }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MT_LOCKFREE)
    {
        printf("port[%u] support TX MT lock free offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MT_LOCKFREE;
    }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
    {
        printf("port[%u] support TX IPv4 checksum offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
    }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)
    {
        printf("port[%u] support TX UDP checksum offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
    }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)
    {
        printf("port[%u] support TX TCP checksum offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
    }

    if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)
    {
        printf("port[%u] support TX SCTP checksum offload.\n", port);
        port_conf.txmode.offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
    }

    /* Configure the Ethernet device. */
    retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
    if (retval != 0)
        return retval;

    retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
    if (retval != 0)
        return retval;

    /* Allocate and set up 1 RX queue per Ethernet port. */
    for (q = 0; q < rx_rings; q++)
    {
        retval = rte_eth_rx_queue_setup(port, q, nb_rxd,
                                        rte_eth_dev_socket_id(port), NULL, mbuf_pool);
        if (retval < 0)
            return retval;
    }

    txconf = dev_info.default_txconf;
    txconf.offloads = port_conf.txmode.offloads;
    /* Allocate and set up 1 TX queue per Ethernet port. */
    for (q = 0; q < tx_rings; q++)
    {
        retval = rte_eth_tx_queue_setup(port, q, nb_txd,
                                        rte_eth_dev_socket_id(port), &txconf);
        if (retval < 0)
            return retval;
    }

    /* Start the Ethernet port. */
    retval = rte_eth_dev_start(port);
    if (retval < 0)
        return retval;

    struct rte_eth_link link;
    do
    {
        retval = rte_eth_link_get_nowait(port, &link);
        if (retval < 0)
        {
            printf("Failed link get (port %u): %s\n",
                   port, rte_strerror(-retval));
            return retval;
        }
        else if (link.link_status)
            break;

        printf("Waiting for Link up on port %" PRIu16 "\n", port);
        sleep(1);
    } while (!link.link_status);

    /* Display the port MAC address. */
    struct rte_ether_addr addr;
    retval = rte_eth_macaddr_get(port, &addr);
    if (retval != 0)
        return retval;

    printf("Port[%u] MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8
           ":%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n",
           port,
           addr.addr_bytes[0], addr.addr_bytes[1],
           addr.addr_bytes[2], addr.addr_bytes[3],
           addr.addr_bytes[4], addr.addr_bytes[5]);

    /* Enable RX in promiscuous mode for the Ethernet device. */
    retval = rte_eth_promiscuous_enable(port);
    if (retval != 0)
        return retval;

    //rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);

    return 0;
}

rte_be32_t string_to_ip(char *s)
{
    unsigned char a[4];
    int rc = sscanf(s, "%hhd.%hhd.%hhd.%hhd", a + 0, a + 1, a + 2, a + 3);
    if (rc != 4)
    {
        fprintf(stderr, "bad source IP address format. Use like: 1.1.1.1\n");
        exit(1);
    }
    return (rte_be32_t)(a[3]) << 24 |
           (rte_be32_t)(a[2]) << 16 |
           (rte_be32_t)(a[1]) << 8 |
           (rte_be32_t)(a[0]);
}




static int
lcore_send(struct rte_mempool *mbuf_pool) {

    struct rte_ether_hdr *eth_hdr;
    struct rte_ipv4_hdr *ipv4_hdr;
    struct rte_udp_hdr *udp_hdr;

    //Defined header in UDP
    struct SRoU
    {
        uint8_t magic_num;
        uint8_t srou_length;
        uint8_t flags;
        uint8_t next_protcol;
        uint64_t pad;
    };

    //init mac
    struct rte_ether_addr s_addr = {{0x14, 0x02, 0xEC, 0x89, 0x8D, 0x24}};
    struct rte_ether_addr d_addr = {{0x3c, 0xfd, 0xfe, 0xa9, 0xa8, 0x89}};

    //init IP header
    rte_be32_t s_ip_addr = string_to_ip("1.0.0.253");
    rte_be32_t d_ip_addr = string_to_ip("1.0.0.1");
    uint16_t ether_type = rte_cpu_to_be_16(0x0800);

    //init udp payload
    struct SRoU obj = {
        .magic_num = 1,
        .srou_length = 4,
        .flags = 0xFF,
        .next_protcol = 0,
    };
    struct SRoU *msg;
    struct rte_mbuf *pkt[BURST_SIZE];

 

    for(;;) {
           for (int i = 0; i < BURST_SIZE; i++)
    {
        pkt[i] = rte_pktmbuf_alloc(mbuf_pool);
 }

 for (int i = 0; i < BURST_SIZE; i++)
    {
        eth_hdr = rte_pktmbuf_mtod(pkt[i], struct rte_ether_hdr *);
        eth_hdr->d_addr = d_addr;
         struct rte_ether_addr s_addr = {{0x14, 0x02, 0xEC, 0x89, 0x8D, i}};
        eth_hdr->s_addr = s_addr;
        eth_hdr->ether_type = ether_type;

        ipv4_hdr = rte_pktmbuf_mtod_offset(pkt[i], struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr));
        ipv4_hdr->version_ihl = 0x45;
        ipv4_hdr->next_proto_id = 0x11;
        ipv4_hdr->src_addr = s_ip_addr;
        ipv4_hdr->dst_addr = d_ip_addr;
        ipv4_hdr->time_to_live = 0x40;

        udp_hdr = rte_pktmbuf_mtod_offset(pkt[i], struct rte_udp_hdr *, sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr));
        udp_hdr->dgram_len = rte_cpu_to_be_16(sizeof(struct SRoU) + sizeof(struct rte_udp_hdr));
        udp_hdr->src_port = rte_cpu_to_be_16(1234);
        udp_hdr->dst_port = rte_cpu_to_be_16(6666);
        ipv4_hdr->total_length = rte_cpu_to_be_16(sizeof(struct SRoU) + sizeof(struct rte_udp_hdr) + sizeof(struct rte_ipv4_hdr));

        msg = (struct SRoU *)(rte_pktmbuf_mtod(pkt[i], char *) + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr));
        *msg = obj;
        int pkt_size = sizeof(struct SRoU) + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr);

        pkt[i]->l2_len = sizeof(struct rte_ether_hdr);
        pkt[i]->l3_len = sizeof(struct rte_ipv4_hdr);
        pkt[i]->l4_len = sizeof(struct rte_udp_hdr);
        pkt[i]->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;
        ipv4_hdr->hdr_checksum = 0;
        udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr, pkt[i]->ol_flags);
        pkt[i]->data_len = pkt_size;
        pkt[i]->pkt_len = pkt_size;
    }

    uint16_t nb_tx = rte_eth_tx_burst(0, 0, pkt, BURST_SIZE);
    for (int i = 0; i < BURST_SIZE; i++)
    {
        rte_pktmbuf_free(pkt[i]);
    }

   }

}

int main(int argc, char *argv[])
{

    struct rte_mempool *mbuf_pool;
    unsigned nb_ports;
    uint16_t portid;
 	uint64_t now = rte_rdtsc();
 	uint64_t pkt_cnt = 0;

    int ret = rte_eal_init(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, "initlize fail!");

    printf("\n\n\n*****************************************\n");

    nb_ports = rte_eth_dev_count_avail();
    printf("number of available port: %d\n", nb_ports);

    /* Creates a new mempool in memory to hold the mbufs. */
    mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
                                        MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());

    if (mbuf_pool == NULL)
        rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");

    /* Initialize all ports. */
    RTE_ETH_FOREACH_DEV(portid)
    if (port_init(portid, mbuf_pool) != 0)
        rte_exit(EXIT_FAILURE, "Cannot init port %" PRIu16 "\n",
                 portid);

    /* start packet send function on lcore-1 */
    rte_eal_remote_launch((lcore_function_t *)lcore_send,mbuf_pool,1);

    struct rte_mbuf *rx_pkt[BURST_SIZE];
    for (int i = 0; i < BURST_SIZE; i++)
    {
        rx_pkt[i] = rte_pktmbuf_alloc(mbuf_pool);
    }


    uint64_t freq = rte_get_tsc_hz() ;
 
    for (;;)
    {
        uint16_t nb_rx = rte_eth_rx_burst(1, 0, rx_pkt, BURST_SIZE);
        if (unlikely(nb_rx == 0))
        {
            continue;
        }
  pkt_cnt += nb_rx;
  
  if (unlikely(rte_rdtsc() - now > freq)) {
   printf("PPS: %ld\n",pkt_cnt);
   pkt_cnt= 0;
   now = rte_rdtsc() ;
  }
        /*struct rte_ether_hdr *eth_hdr;  
        for (int i = 0; i < nb_rx; i++)
        {
            eth_hdr = rte_pktmbuf_mtod(rx_pkt[i], struct rte_ether_hdr *);
            printf("Recv Pkt[%d] from MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
                   " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " \n",i,
                   eth_hdr->s_addr.addr_bytes[0], eth_hdr->s_addr.addr_bytes[1],
                   eth_hdr->s_addr.addr_bytes[2], eth_hdr->s_addr.addr_bytes[3],
                   eth_hdr->s_addr.addr_bytes[4], eth_hdr->s_addr.addr_bytes[5]);
            rte_pktmbuf_free(rx_pkt[i]);
        }*/
    }
    return 0;
}

使用的链接选项

-L/home/alen/dpdk-20.11.1/build/lib -L/home/alen/dpdk-20.11.1/build/drivers  -Wl,-Bdynamic -Wl,--whole-archive -Wl,-lrte_mempool_ring -Wl,-lrte_pci -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_net  -Wl,-lrte_distributor -Wl,-lrte_reorder -Wl,-lrte_kni -Wl,-lrte_pipeline -Wl,-lrte_table -Wl,-lrte_eventdev -Wl,-lrte_timer -Wl,-lrte_hash -Wl,-lrte_jobstats -Wl,-lrte_lpm -Wl,-lrte_power -Wl,-lrte_acl  -Wl,-lrte_meter -Wl,-lrte_sched -Wl,--start-group -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ip_frag -Wl,-lrte_ethdev -Wl,-lrte_cryptodev -Wl,-lrte_mempool -Wl,-lrte_ring -Wl,-lrte_eal -Wl,-lrte_cmdline  -Wl,-lrte_cfgfile  -Wl,-lrte_net_bond -Wl,-lrte_net_vmxnet3  -Wl,-lrte_net_virtio  -Wl,-lrte_net_cxgbe -Wl,-lrte_net_enic  -Wl,-lrte_net_i40e -Wl,-lrte_net_iavf -Wl,-lrte_net_ice -Wl,-lrte_net_fm10k -Wl,-lrte_net_ixgbe -Wl,-lrte_net_e1000  -Wl,-lrte_net_ring -Wl,-lrte_net_af_packet -Wl,-lrte_net_null -Wl,-lrte_telemetry -Wl,-lrte_security -Wl,-lrte_rcu -Wl,-lrte_common_iavf -Wl,-lrte_common_cpt -Wl,-lrte_common_dpaax -Wl,-lrte_common_octeontx -Wl,-lrte_common_octeontx2 -Wl,-lrte_common_sfc_efx -Wl,-lrte_bus_dpaa -Wl,-lrte_bus_fslmc -Wl,-lrte_bus_ifpga -Wl,-lrte_bus_vmbus -Wl,-lrte_mempool_bucket -Wl,-lrte_mempool_dpaa -Wl,-lrte_mempool_dpaa2 -Wl,-lrte_mempool_octeontx -Wl,-lrte_mempool_octeontx2 -Wl,-lrte_mempool_stack -Wl,-lrte_net_ark -Wl,-lrte_net_atlantic -Wl,-lrte_net_avp -Wl,-lrte_net_axgbe  -Wl,-lrte_net_bnx2x -Wl,-lrte_net_bnxt  -Wl,-lrte_net_dpaa -Wl,-lrte_net_dpaa2  -Wl,-lrte_net_ena -Wl,-lrte_net_enetc -Wl,-lrte_net_failsafe -Wl,-lrte_net_hinic -Wl,-lrte_net_hns3 -Wl,-lrte_net_igc  -Wl,-lrte_net_kni -Wl,-lrte_net_liquidio -Wl,-lrte_net_memif -Wl,-lrte_net_netvsc -Wl,-lrte_net_nfp -Wl,-lrte_net_octeontx -Wl,-lrte_net_octeontx2 -Wl,-lrte_net_pfe -Wl,-lrte_net_qede -Wl,-lrte_net_sfc -Wl,-lrte_net_tap -Wl,-lrte_net_thunderx -Wl,-lrte_net_txgbe -Wl,-lrte_net_vdev_netvsc -Wl,-lrte_net_vhost -Wl,-lrte_net_mlx5 -Wl,-lrte_common_mlx5 -Wl,-lrte_regex_mlx5 -Wl,-lrte_vdpa_mlx5 -Wl,-lrte_raw_dpaa2_cmdif -Wl,-lrte_raw_dpaa2_qdma -Wl,-lrte_raw_ioat -Wl,-lrte_raw_ntb -Wl,-lrte_raw_octeontx2_dma -Wl,-lrte_raw_octeontx2_ep -Wl,-lrte_raw_skeleton -Wl,-lrte_crypto_bcmfs -Wl,-lrte_crypto_caam_jr -Wl,-lrte_crypto_dpaa_sec -Wl,-lrte_crypto_dpaa2_sec -Wl,-lrte_crypto_nitrox -Wl,-lrte_crypto_null -Wl,-lrte_crypto_octeontx -Wl,-lrte_crypto_octeontx2 -Wl,-lrte_crypto_scheduler -Wl,-lrte_crypto_virtio -Wl,-lrte_compress_octeontx -Wl,-lrte_compress_zlib -Wl,-lrte_regex_octeontx2 -Wl,-lrte_vdpa_ifc -Wl,-lrte_event_dlb -Wl,-lrte_event_dlb2 -Wl,-lrte_event_dpaa -Wl,-lrte_event_dpaa2 -Wl,-lrte_event_octeontx2 -Wl,-lrte_event_opdl -Wl,-lrte_event_skeleton -Wl,-lrte_event_sw -Wl,-lrte_event_dsw -Wl,-lrte_event_octeontx -Wl,-lrte_node -Wl,-lrte_graph -Wl,-lrte_bpf -Wl,-lrte_flow_classify -Wl,-lrte_fib -Wl,-lrte_ipsec -Wl,-lrte_vhost -Wl,-lrte_stack -Wl,-lrte_rib -Wl,-lrte_regexdev -Wl,-lrte_rawdev -Wl,-lrte_pdump -Wl,-lrte_member -Wl,-lrte_latencystats -Wl,-lrte_gso -Wl,-lrte_gro -Wl,-lrte_efd -Wl,-lrte_compressdev -Wl,-lrte_bitratestats -Wl,-lrte_bbdev -Wl,-lrte_metrics -Wl,--end-group -Wl,--no-whole-archive -Wl,-Bdynamic -lhugetlbfs -lnuma -ldl -Wl,-lm -Wl,-lrt -Wl,-ldl -lz -lelf

解决方法
http://doc.dpdk.org/guides/nics/mlx5.html#how-to-configure-a-vf-as-trusted

在这里插入图片描述

1、 Create 2 VFs on the PF pf0 when in Legacy SR-IOV mode:
/sys/class/net/eth0/device/sriov_numvfs
用sriov_numvfs貌似不可以工作
移除VF

$ echo 0 > /sys/class/net/enp181s0f1/device/mlx5_num_vfs
$ echo 2 > /sys/class/net/enp181s0f1/device/mlx5_num_vfs

2、Verify the VFs are created:

$lspci |grep Mellanox
82:00.0 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5]
82:00.1 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5]
82:00.2 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5 Virtual Function]
82:00.3 Ethernet controller: Mellanox Technologies MT27800 Family [ConnectX-5 Virtual Function]

3、Unbind all VFs. For each VF PCIe, using the following command to unbind the driver:

$ echo "0000:b5:01.2" >> /sys/bus/pci/drivers/mlx5_core/unbind

4、Set the VFs to be trusted for the kernel by using one of the methods below:
• Using sysfs file:

$ echo ON | tee /sys/class/net/enp181s0f1/device/sriov/0/trust
$ echo ON | tee /sys/class/net/enp181s0f1/device/sriov/1/trust

5、Using “ip link” command:

$ ip link set enp181s0f1 vf 0 trust on
$ ip link set enp181s0f1 vf 1 trust on

6、Configure all VFs using mlxreg:
这一步我们可以忽略

$ mlxreg -d /dev/mst/mt4121_pciconf0 --reg_name VHCA_TRUST_LEVEL --yes --set "all_vhca=0x1,trust_level=0x1"

Note
Firmware version used must be >= xx.29.1016 and MFT >= 4.18
7. For each VF PCIe, using the following command to bind the driver:

$ echo "0000:b5:01.2" >> /sys/bus/pci/drivers/mlx5_core/bind

到这一步宿主机上是可以成功获取并初始化VF了,但是如果是docker里面运行,需要注意使用net --host参数,使得宿主机和容器用一个网络。同时,最为重要的是,如果是在宿主机中生成VF,则必须先生成VF,后启动docker,否则在docker中则不能访问的VF。如果已存在docker并启动了,那我们在echo 2生成VF时,就需要stop docker,然后echo 2生成VF,然后docker start。当然也有其他容器和主机网卡设置的技术,例如pipework等。
成功的结果如下

EAL: Detected 4 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Detected shared linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: No available 1048576 kB hugepages reported
EAL: VFIO support initialized
EAL:   Invalid NUMA socket, default to 0
EAL: Probe PCI driver: net_virtio (1af4:1041) device: 0000:01:00.0 (socket 0)
eth_virtio_pci_init(): Failed to init PCI device

EAL: Requested device 0000:01:00.0 cannot be used
EAL:   Invalid NUMA socket, default to 0
EAL: Probe PCI driver: mlx5_pci (15b3:101a) device: 0000:06:00.0 (socket 0)
EAL:   Invalid NUMA socket, default to 0
EAL: Probe PCI driver: mlx5_pci (15b3:101a) device: 0000:07:00.0 (socket 0)
TELEMETRY: No legacy callbacks, legacy socket not created



*****************************************
number of available port: 2


initializing port 0...
port[0] support RX cheksum offload.
port[0] support TX mbuf fast free offload.
port[0] support TX IPv4 checksum offload.
port[0] support TX UDP checksum offload.
port[0] support TX TCP checksum offload.
Port[0] MAC: 7a:99:ed:5f:e3:a6


initializing port 1...
port[1] support RX cheksum offload.
port[1] support TX mbuf fast free offload.
port[1] support TX IPv4 checksum offload.
port[1] support TX UDP checksum offload.
port[1] support TX TCP checksum offload.
Port[1] MAC: 5a:d8:51:db:17:2d
PPS: 2081708
PPS: 23912180

2、
EAL: Failed to open group 58
EAL: 0001:01:08.0 not managed by VFIO driver, skipping
EAL: Failed to open group 60
EAL: 0001:01:0e.0 not managed by VFIO driver, skipping

如果是这个错误,一般发生在container中。
1、重新生成vf,先检查是否是在container exit的状态下生成的VF。需要保证生成vf时候,容器是退出的,这点很关键。
2、如果第一种方式不行。在启动docker时加–device参数
ETH1_VFIO_0 = /sys/class/net/eth1/device/virtfn0/iommu_group
ETH2_VFIO_0 = /sys/class/net/eth2/device/virtfn0/iommu_group

docker run -dit --device /dev/vfio/$ETH1_VFIO_0 dockerimage bash

3、容器中使用vf
a、在启动容器时通过 --net host参数和主机共用网卡
b、使用pipework工具将host上的eth,pipework到容器。

./pipework --direct-phys eth1 -i eth1 container_name 0/0
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DPDK是数据平面开发工具包(Data Plane Development Kit)的简称,是一种轻量级的数据平面框架,用于加速数据包处理。而mlx5是一种在DPDK中的驱动程序,专门用于与Mellanox的网络适配器进行通信和数据包处理。 DPDKmlx5驱动程序具有以下特点和功能: 1. 高性能:mlx5驱动程序充分利用了Mellanox的硬件加速功能,通过与硬件适配器紧密集成,能够提供优异的数据包处理性能。该驱动程序采用了零拷贝技术和事件模型,减少了很多传统网络协议栈中的开销,实现了低延迟和高吞吐量。 2. 多队列支持:mlx5驱动程序支持多队列技术,允许应用程序并行处理多个网络队列。这样可以充分利用多核处理器的计算能力,并实现更好的负载均衡和并发性能。 3. 硬件加速功能:mlx5驱动程序通过与Mellanox网络适配器紧密集成,能够充分利用硬件的加速功能,如RSS(Receive Side Scaling)和TSS(Transmit Side Scaling),提高数据包的处理效率。 4. 协议支持:mlx5驱动程序支持多种网络协议,如Ethernet、IPv4/IPv6、TCP、UDP等。它能够对网络协议进行解析和处理,并提供相应的接口供应用程序使用。 5. 灵活性:mlx5驱动程序提供了丰富的配置选项,可以根据具体的需求进行灵活的配置和调优。例如,它支持灵活的RSS配置,可以根据不同的数据包字段进行负载均衡,以实现更好的性能。 总之,DPDKmlx5驱动程序是一种高性能的数据包处理驱动程序,通过与Mellanox的网络适配器协同工作,能够实现高吞吐量、低延迟的数据包处理,提供了丰富的配置选项和协议支持,适用于高性能的网络应用场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值