DPDK网卡PMD驱动

/home/user/dpdk-stable-18.11.11/drivers/net/i40e目录下的驱动为例

源代码文件有

# ls
base           i40e_ethdev_vf.c  i40e_logs.h  i40e_regs.h  i40e_rxtx_vec_altivec.c  i40e_rxtx_vec_neon.c  i40e_vf_representor.c  rte_pmd_i40e.c
i40e_ethdev.c  i40e_fdir.c       i40e_pf.c    i40e_rxtx.c  i40e_rxtx_vec_avx2.c     i40e_rxtx_vec_sse.c   Makefile               rte_pmd_i40e.h
i40e_ethdev.h  i40e_flow.c       i40e_pf.h    i40e_rxtx.h  i40e_rxtx_vec_common.h   i40e_tm.c             meson.build            rte_pmd_i40e_version.map
# ls base/
i40e_adminq.c      i40e_alloc.h   i40e_dcb.h     i40e_diag.h  i40e_lan_hmc.c  i40e_osdep.h      i40e_status.h  README
i40e_adminq_cmd.h  i40e_common.c  i40e_devids.h  i40e_hmc.c   i40e_lan_hmc.h  i40e_prototype.h  i40e_type.h    virtchnl.h
i40e_adminq.h      i40e_dcb.c     i40e_diag.c    i40e_hmc.h   i40e_nvm.c      i40e_register.h   meson.build

从Makefile可以看出PMD驱动最终编译生成librte_pmd_i40e.a静态链接库文件,依赖的静态库有librte_eal.a, librte_mbuf.a, librte_mempool.a, librte_ring.a, librte_ethdev.a, librte_net.a, librte_kvargs.a, librte_hash.a, librte_bus_pci.a 。

# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2010-2017 Intel Corporation

include $(RTE_SDK)/mk/rte.vars.mk

#
# library name
#
LIB = librte_pmd_i40e.a

CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS) -DPF_DRIVER -DVF_DRIVER -DINTEGRATED_VF
CFLAGS += -DX722_A0_SUPPORT
CFLAGS += -DALLOW_EXPERIMENTAL_API

LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
LDLIBS += -lrte_bus_pci

EXPORT_MAP := rte_pmd_i40e_version.map

LIBABIVER := 2

librte_pmd_i40e.a的入口函数为

static struct rte_pci_driver rte_i40e_pmd = {
        .id_table = pci_id_i40e_map,
        .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
                     RTE_PCI_DRV_IOVA_AS_VA,
        .probe = eth_i40e_pci_probe,
        .remove = eth_i40e_pci_remove,
};

RTE_PMD_REGISTER_PCI(net_i40e, rte_i40e_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio-pci");

/* i40e_ethdev.c */

eth_i40e_pci_probe->rte_eth_dev_create->eth_i40e_dev_init

static int
eth_i40e_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
        struct rte_pci_device *pci_dev)
{
        char name[RTE_ETH_NAME_MAX_LEN];
        struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
        int i, retval;

        if (pci_dev->device.devargs) {
                retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
                                ð_da);
                if (retval)
                        return retval;
        }

        retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
                sizeof(struct i40e_adapter),
                eth_dev_pci_specific_init, pci_dev,
                eth_i40e_dev_init, NULL);

        if (retval || eth_da.nb_representor_ports < 1)
                return retval;

        /* probe VF representor ports */
        struct rte_eth_dev *pf_ethdev = rte_eth_dev_allocated(
                pci_dev->device.name);

        if (pf_ethdev == NULL)
                return -ENODEV;

        for (i = 0; i < eth_da.nb_representor_ports; i++) {
                struct i40e_vf_representor representor = {
                        .vf_id = eth_da.representor_ports[i],
                        .switch_domain_id = I40E_DEV_PRIVATE_TO_PF(
                                pf_ethdev->data->dev_private)->switch_domain_id,
                        .adapter = I40E_DEV_PRIVATE_TO_ADAPTER(
                                pf_ethdev->data->dev_private)
                };

                /* representor port net_bdf_port */
                snprintf(name, sizeof(name), "net_%s_representor_%d",
                        pci_dev->device.name, eth_da.representor_ports[i]);


                retval = rte_eth_dev_create(&pci_dev->device, name,
                        sizeof(struct i40e_vf_representor), NULL, NULL,
                        i40e_vf_representor_init, &representor);

                if (retval)
                        PMD_DRV_LOG(ERR, "failed to create i40e vf "
                                "representor %s.", name);
        }

        return 0;
}

static int
eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
{
        struct rte_pci_device *pci_dev;
        struct rte_intr_handle *intr_handle;
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct i40e_vsi *vsi;
        int ret;
        uint32_t len, val;
        uint8_t aq_fail = 0;

        PMD_INIT_FUNC_TRACE();

        dev->dev_ops = &i40e_eth_dev_ops;
        dev->rx_pkt_burst = i40e_recv_pkts;
        dev->tx_pkt_burst = i40e_xmit_pkts;
        dev->tx_pkt_prepare = i40e_prep_pkts;

        /* for secondary processes, we don't initialise any further as primary
         * has already done this work. Only check we don't need a different
         * RX function */
        if (rte_eal_process_type() != RTE_PROC_PRIMARY){
                i40e_set_rx_function(dev);
                i40e_set_tx_function(dev);
                return 0;
        }
        i40e_set_default_ptype_table(dev);
        pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        intr_handle = &pci_dev->intr_handle;

        rte_eth_copy_pci_info(dev, pci_dev);

        pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        pf->adapter->eth_dev = dev;
        pf->dev_data = dev->data;

        ........
}

比如收包函数

static inline uint16_t
rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
                 struct rte_mbuf **rx_pkts, const uint16_t nb_pkts)

实际调用了

        nb_rx = (*dev->rx_pkt_burst)(dev->data->rx_queues[queue_id],
                                     rx_pkts, nb_pkts);

发包函数

static inline uint16_t
rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
                 struct rte_mbuf **tx_pkts, uint16_t nb_pkts)

实际调用了

(*dev->tx_pkt_burst)(dev->data->tx_queues[queue_id], tx_pkts, nb_pkts);

参考资料:

DPDK总结(网卡初始化)_hz5034的博客-CSDN博客

dpdk添加设备基本流程_zhenghuaduo的博客-CSDN博客_local_dev_probe

dpdk PMD_51CTO博客_vpp dpdk

DPDK收发包流程分析(一)_confirmwz的博客-CSDN博客

dpdk + ixgbe adater _ hw 通过pci_map_resource 读写dma寄存器 + 总线地址 + dma读写地址 - tycoon3 - 博客园 (cnblogs.com)

你可能感兴趣的:(DPDK,DPDK)