DPDK收发包处理流程-----(一)网卡初始化【2】

pcai_scan()通过读取/sys/bus/pci/devices/目录下相关PCI设备的如下文件,获取对应的信息,初始化struct rte_pci_device数据结构,并将其按照PCI地址从大到小的顺序挂到pci_device_list链表上。

复制代码
struct rte_pci_device {
        TAILQ_ENTRY(rte_pci_device) next;       /**< Next probed PCI device. */
        struct rte_pci_addr addr;               /**< PCI location. */
        struct rte_pci_id id;                   /**< PCI ID. */
        struct rte_pci_resource mem_resource[PCI_MAX_RESOURCE];   /**< PCI Memory Resource */
        struct rte_intr_handle intr_handle;     /**< Interrupt handle */
        const struct rte_pci_driver *driver;    /**< Associated driver */
        uint16_t max_vfs;                       /**< sriov enable if not zero */
        int numa_node;                          /**< NUMA node connection */
        struct rte_devargs *devargs;            /**< Device user arguments */
};
复制代码
复制代码
root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:09.0/
total 0
-rw-r--r-- 1 root root   4096 Nov 15 12:18 uevent
lrwxrwxrwx 1 root root      0 Nov 15 12:18 subsystem -> ../../../bus/pci
-r--r--r-- 1 root root   4096 Nov 15 12:19 class
-r--r--r-- 1 root root   4096 Nov 15 12:19 vendor
-r--r--r-- 1 root root   4096 Nov 15 12:19 device
-rw-r--r-- 1 root root    256 Nov 15 12:19 config
-r--r--r-- 1 root root   4096 Nov 15 12:19 local_cpus
-r--r--r-- 1 root root   4096 Nov 15 12:19 irq
-r--r--r-- 1 root root   4096 Nov 15 12:20 resource
drwxr-xr-x 2 root root      0 Nov 15 12:20 power
-r--r--r-- 1 root root   4096 Nov 19 14:33 subsystem_vendor
-r--r--r-- 1 root root   4096 Nov 19 14:33 subsystem_device
-r--r--r-- 1 root root   4096 Nov 19 14:33 numa_node
-rw------- 1 root root      8 Nov 19 14:58 resource2
-rw------- 1 root root 131072 Nov 19 14:58 resource0
--w------- 1 root root   4096 Nov 19 14:58 reset
--w--w---- 1 root root   4096 Nov 19 14:58 rescan
--w--w---- 1 root root   4096 Nov 19 14:58 remove
-rw-r--r-- 1 root root   4096 Nov 19 14:58 msi_bus
-r--r--r-- 1 root root   4096 Nov 19 14:58 modalias
-r--r--r-- 1 root root   4096 Nov 19 14:58 local_cpulist
-rw------- 1 root root   4096 Nov 19 14:58 enable
-r--r--r-- 1 root root   4096 Nov 19 14:58 dma_mask_bits
-r--r--r-- 1 root root   4096 Nov 19 14:58 consistent_dma_mask_bits
-rw-r--r-- 1 root root   4096 Nov 19 14:58 broken_parity_status
drwxr-xr-x 3 root root      0 Nov 19 15:31 uio
lrwxrwxrwx 1 root root      0 Nov 19 15:31 driver -> ../../../bus/pci/drivers/igb_uio
-rw-r--r-- 1 root root   4096 Nov 19 15:32 max_vfs
复制代码

目录名:就是PCI设备的地址,记录在struct rte_pci_addr数据结构中。

vendor文件:获取PCI_ID.vendor_id。

device文件:获取PCI_ID.device_id。

subsystem_vendor文件:获取PCI_ID.subsystem_vendor_id。

subsystem_device文件:获取PCI_ID.subsystem_device_id。

numa_node文件:获取PCI设备属于哪个CPU socket。

resource文件:获取PCI设备的在地址总线上的物理地址,以及物理地址空间的大小,记录在struct rte_pci_resouce数据结构中。

三、PCI驱动注册

调用rte_eal_init()--->rte_eal_dev_init()函数,遍历dev_driver_list链表,执行网卡驱动对应的init的回调函数,注册PCI驱动。

复制代码
/* Once the vdevs are initalized, start calling all the pdev drivers */
        TAILQ_FOREACH(driver, &dev_driver_list, next) {
                if (driver->type != PMD_PDEV)
                        continue;
                /* PDEV drivers don't get passed any parameters */
                driver->init(NULL, NULL);
        }
复制代码

以e1000网卡为例,执行的init回调函数就是rte_igb_pmd_init()函数。

static int
rte_igb_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
{
        rte_eth_driver_register(&rte_igb_pmd);
        return 0;
}

rte_eth_driver_register()主要是指定PCI设备的初始化函数为rte_eth_dev_init(),以及注册PCI驱动,将PCI驱动挂到pci_driver_list全局链表上。

void   
rte_eth_driver_register(struct eth_driver *eth_drv)
{
        eth_drv->pci_drv.devinit = rte_eth_dev_init;
        rte_eal_pci_register(&eth_drv->pci_drv);
}

其中,rte_igb_pmd数据结构如下,指定e1000网卡的初始化函数是eth_igb_dev_init()。

复制代码
static struct eth_driver rte_igb_pmd = {
        {
                .name = "rte_igb_pmd",
                .id_table = pci_id_igb_map,
                .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
        },
        .eth_dev_init = eth_igb_dev_init,
        .dev_private_size = sizeof(struct e1000_adapter),
};
复制代码

四、网卡初始化

调用rte_eal_init()--->rte_eal_pci_probe()函数,遍历pci_device_list和pci_driver_list链表,根据PCI_ID,将pci_device与pci_driver绑定,并调用pci_driver的init回调函数rte_eth_dev_init(),初始化PCI设备。

(YK14$%`JT1VRV4HGIA8~5S

在rte_eal_pci_probe_one_driver()函数中,

1、首先通过比对PCI_ID的vendor_id、device_id、subsystem_vendor_id、subsystem_device_id四个字段判断pci设备和pci驱动是否匹配。

2、PCI设备和PCI驱动匹配后,调用pci_map_device()函数为该PCI设备创建map resource。具体如下:

a、首先读取/sys/bus/pci/devices/PCI设备目录下的uio目录,获取uio设备的ID,该ID就是uio目录名最后几位的数字。当igb_uio模块与网卡设备绑定的时候,会在/sys/bus/pci/devices/对应的PCI设备目录下创建uio目录。

如果启动参数中指定了OPT_CREATE_UIO_DEV_NUM,会在/dev目录下创建对应uio设备的设备文件。

复制代码
root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:09.0/uio/
total 0
drwxr-xr-x 5 root root 0 Nov 19 15:31 uio0
root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:0a.0/uio/
total 0
drwxr-xr-x 5 root root 0 Nov 19 15:31 uio1
root@Ubuntu:~#
复制代码

b、初始化PCI设备的中断句柄。

rte_pci_device->intr_handler.fd = open(“/dev/uioID”, O_RDWR); /* ID为0或1,即uio0或uio1*/
rte_pci_device->intr_handler.type = RTE_INTR_HANDLER_UIO;

c、读取/sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/map0/目录下的文件,获取UIO设备的map resource。并将其记录在struct pci_map数据结构中。

struct pci_map {
    void *addr;
    uint64_t offset;
    uint64_t size;
    uint64_t phaddr;
};
复制代码
root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/
total 0
drwxr-xr-x 2 root root 0 Nov 19 15:32 map0
root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/map0/
total 0
-r--r--r-- 1 root root 4096 Nov 19 15:32 size
-r--r--r-- 1 root root 4096 Nov 19 15:32 offset
-r--r--r-- 1 root root 4096 Nov 19 15:32 addr
-r--r--r-- 1 root root 4096 Nov 19 15:34 name
root@Ubuntu:~#
复制代码

d、检查PCI设备和UIO设备在内存总线上的物理地址是否一致。如果一致,对/dev/uioID文件mmap一段内存空间,并将其记录在pci_map->addr和rte_pci_device->mem_resource[].addr中。

root@Ubuntu:~# cat /sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/map0/addr 
0xf0440000
root@Ubuntu:~#
复制代码
root@Ubuntu:~# cat /sys/bus/pci/devices/0000\:00\:09.0/resource
0x00000000f0440000 0x00000000f045ffff 0x0000000000040200
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x000000000000d248 0x000000000000d24f 0x0000000000040101
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 0x0000000000000000
root@Ubuntu:~#
复制代码

e、将所有UIO设备的resource信息都记录在struct mapped_pci_resource数据结构中,并挂到全局链表pci_res_list上。www.sczygb.com点击打开链接

复制代码
struct mapped_pci_resource {
        TAILQ_ENTRY(uio_resource) next;

        struct rte_pci_addr pci_addr;
        char path[PATH_MAX];
        size_t nb_maps;
        struct uio_map maps[PCI_MAX_RESOURCE];
};
复制代码
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值