DPDK 收发包处理流程(二)(网卡初始化)
来源:互联网 发布:程序员需要掌握的知识 编辑:程序博客网 时间:2024/06/06 00:45
转自:http://blog.csdn.net/xy010902100449/article/details/47282937
三、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 intrte_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(ð_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设备。
在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 0drwxr-xr-x 5 root root 0 Nov 19 15:31 uio0root@Ubuntu:~# ls -ltr /sys/bus/pci/devices/0000\:00\:0a.0/uio/total 0drwxr-xr-x 5 root root 0 Nov 19 15:31 uio1root@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 0drwxr-xr-x 2 root root 0 Nov 19 15:32 map0root@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 nameroot@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 0xf0440000root@Ubuntu:~#root@Ubuntu:~# cat /sys/bus/pci/devices/0000\:00\:09.0/resource0x00000000f0440000 0x00000000f045ffff 0x00000000000402000x0000000000000000 0x0000000000000000 0x00000000000000000x000000000000d248 0x000000000000d24f 0x00000000000401010x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000 0x0000000000000000root@Ubuntu:~#
e、将所有UIO设备的resource信息都记录在struct mapped_pci_resource数据结构中,并挂到全局链表pci_res_list上。
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];};
3、调用rte_eth_dev_init()初始化PCI设备。
a、首先,调用rte_eth_dev_allocate()在全局数组rte_eth_devices[]中分配一个网卡设备。并在全局数组rte_eth_dev_data[]中为网卡设备的数据域分配空间。
eth_dev = &rte_eth_devices[nb_ports];eth_dev->data = &rte_eth_dev_data[nb_ports];
并调用rte_zmalloc()为网卡设备的私有数据结构分配空间。
rte_eth_dev->rte_eth_dev_data->dev_private = rte_zmalloc(sizeof(struct e1000_adapter));b、调用eth_igb_dev_init()初始化网卡设备。首先设置网卡设备的操作函数集,以及收包、发包函数。
eth_dev->dev_ops = ð_igb_ops;eth_dev->rx_pkt_burst = ð_igb_recv_pkts;eth_dev->tx_pkt_burst = ð_igb_xmit_pkts;初始化网卡设备的硬件相关数据结构struct e1000_hw,包括设备ID、硬件操作函数集、在内存地址总线上映射的地址、MAC地址等等。
c、注册中断处理函数。
rte_intr_callback_register(&(pci_dev->intr_handle), eth_igb_interrupt_handler, (void *)eth_dev);
五、设备与驱动相互映射关系图
- DPDK 收发包处理流程(二)(网卡初始化)
- DPDK 收发包处理流程(二)(网卡初始化)
- DPDK收发包处理流程-----(一)网卡初始化
- DPDK收发包处理流程-----(一)网卡初始化
- DPDK收发包处理流程-----(一)网卡初始化【1】
- DPDK收发包处理流程-----(一)网卡初始化【2】
- DPDK收发包处理流程-----(一)网卡初始化【3】
- DPDK收发包处理流程 ----- 网卡初始化
- DPDK之(三)——收发包处理流程--网卡初始化
- DPDK 收发包处理流程(一)(网卡驱动注册)
- DPDK 收发包处理流程(一)(网卡驱动注册)
- DPDK之(九)——收发包分析
- DPDK(11):内存初始化
- DPDK(二):系统要求
- DPDK内存管理-----(一)初始化
- DPDK内存管理 -----(一)初始化
- Linux 网卡驱动学习(五)(收发包具体过程)
- Linux 网卡驱动学习(五)(收发包具体过程)
- for循环打印菱形(两个三角)
- iframe的使用
- Spring Bean的自动装配和资源管理
- Ubuntu忘记用户登录密码以及管理员密码,请来这里帮你找回。
- 一个关于javaweb项目名处出现红叉,而项目下的目录和文件没有红叉的问题
- DPDK 收发包处理流程(二)(网卡初始化)
- Ubuntu编译openjdk
- 60,000毫秒内对Linux的性能诊断
- 二叉树面试题总汇
- Hadoop环境搭建
- K
- C++:指针、引用和CONST
- Android面试题目之常见的选择题
- 安卓Binder解析