DPDK 网卡设备scan及probe流程

本文以X710网卡设备为例,介绍网卡的scan和probe流程的;通过本篇文章的介绍可以大致了解UIO驱动、PMD驱动之间的关联关系以及如何确认网卡对应的PMD驱动的。针对probe流程处理了解的比较片面,有了解比较深的同学,希望能找您学习一下。

1、BUS总线设备扫描

ret_bus_scan函数在目录dpdk/lib/librte_eal/common/eal_common_bus.c
初始化流程在EAL环境初始化调用 ret_bus_scan函数完成的。内部会调用各自类型的bus->scan接口;目的是扫描所有该类型bus下注册的设备。
下面有bus设备注册、以PCI设备的注册来详细说明注册流程。

1.1 Bus设备的注册

是由宏RTE_REGISTER_BUS,是一个构造函数,在程序main启动前完成的注册;将bus类型注册到全局结构rte_bus_list 链表上;目前有6中设备类型,本文主要关心网卡设备的。目前查询宏使用的地方如下。(对应宏所在文件:dpdk/lib/librte_eal/include/rte_bus.h)

 1/**
 2 * Helper for Bus registration.
 3 * The constructor has higher priority than PMD constructors.
 4 */
 5#define RTE_REGISTER_BUS(nm, bus) \
 6RTE_INIT_PRIO(businitfn_ ##nm, BUS) \
 7{\
 8  (bus).name = RTE_STR(nm);\
 9  rte_bus_register(&bus); \
10}
11RTE_REGISTER_BUS(FSL_DPAA_BUS_NAME, rte_dpaa_bus.bus);/*drivers/bus/dpaa/dpaa_bus.c*/
12RTE_REGISTER_BUS(FSLMC_BUS_NAME, rte_fslmc_bus.bus)/*drivers/bus/fslmc/fslmc_bus.c*/
13RTE_REGISTER_BUS(IFPGA_BUS_NAME, rte_ifpga_bus);/*drivers/bus/ifpga/ifpga_bus.c*/
14RTE_REGISTER_BUS(pci, rte_pci_bus.bus);/*drivers/bus/pci/pci_common.c*/
15RTE_REGISTER_BUS(vdev, rte_vdev_bus);/*drivers/bus/vdev/vdev.c*/
16RTE_REGISTER_BUS(vmbus, rte_vmbus_bus.bus);/*drivers/bus/vmbus/vmbus_common.c*/

网卡设备BUS的注册
我们重点学习网卡设备的注册,网卡设备bus已经注册到全局变量rte_bus_list链表上。

 1/*网卡bus的全局变量*/
 2struct rte_pci_bus rte_pci_bus = {
 3  .bus = { /*网卡的struct rte_bus设备内容*/
 4    .scan = rte_pci_scan,
 5    .probe = pci_probe,
 6    .find_device = pci_find_device,
 7    .plug = pci_plug,
 8    .unplug = pci_unplug,
 9    .parse = pci_parse,
10    .dma_map = pci_dma_map,
11    .dma_unmap = pci_dma_unmap,
12    .get_iommu_class = rte_pci_get_iommu_class,
13    .dev_iterate = rte_pci_dev_iterate,
14    .hot_unplug_handler = pci_hot_unplug_handler,
15    .sigbus_handler = pci_sigbus_handler,
16  },
17  /*实例化网卡设备后下挂到尾队列链表中*/
18  .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),
19  /*对应所有网卡的PMD驱动链表,下面重点说一下*/
20  .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),
21};
22/*网卡设备注册*/
23RTE_REGISTER_BUS(pci, rte_pci_bus.bus);

下面是通过gdb在全局bus链表上查找到pci设备全局变量注册信息。来打印看一下网卡设备注册后struct rte_bus 内容如下:

 1/*打印对应pci 内容*/
 2(gdb) p rte_bus_list.tqh_first[0].next.tqe_next[0].next.tqe_next[0].next.tqe_next[0]
 3$7 = {
 4  next = {/*双向链表情况*/
 5    tqe_next = 0x399cd40 <rte_vdev_bus>,
 6    tqe_prev = 0x399cb40 <rte_ifpga_bus>
 7  },
 8  name = 0x33f0f9f "pci", /*注册时的name*/
 9  scan = 0x485183 <rte_pci_scan>,
10  probe = 0x489590 <rte_pci_probe>,/*最新的代码是pci_probe*/
11  find_device = 0x489a35 <pci_find_device>,
12  plug = 0x489cf8 <pci_plug>,
13  unplug = 0x489d26 <pci_unplug>,
14  parse = 0x489835 <pci_parse>,
15  dma_map = 0x489d90 <pci_dma_map>,
16  dma_unmap = 0x489e76 <pci_dma_unmap>,
17  conf = {
18    scan_mode = RTE_BUS_SCAN_BLACKLIST
19  },
20  get_iommu_class = 0x489fc8 <rte_pci_get_iommu_class>,
21  dev_iterate = 0x488dc0 <rte_pci_dev_iterate>,
22  hot_unplug_handler = 0x489bd6 <pci_hot_unplug_handler>,
23  sigbus_handler = 0x489c70 <pci_sigbus_handler>
24}

网卡设备scan操作
在EAL环境初始化函数rte_eal_init()->rte_bus_scan()遍历全局变量rte_bus_list,调用对应bus回调函数scan。

 1int rte_bus_scan(void)
 2{
 3  int ret;
 4  struct rte_bus *bus = NULL;
 5  /*遍历bus链表,执行相应bus的scan函数*/
 6  TAILQ_FOREACH(bus, &rte_bus_list, next) {
 7    ret = bus->scan();
 8    if (ret)
 9      RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
10        bus->name);
11  }
12  return 0;
13}

网卡设备调用rte_pci_scan(),函数的大致意思是打开并扫描目录“/sys/bus/pci/devices”下的PCI设备;一个目录名称表示一个pci设备;根据我们设置的网卡黑名单或白名单进行过滤,符合条件的设备,调用pci_scan_one实例化网卡设备rte_pci_device,并进行一些数据的填充(rte_pci_addr(网卡pci编号),struct rte_pci_id (网卡身份信息vendor_id、device_id来确定使用那个网卡驱动)max_vfs(sriov支持最大数量)、numa_node)。
pci_scan_one 函数只是实例化网卡设备并填充网卡的一些基本信息,并没有申请相应的资源,资源是由函数rte_bus_probe完成的。下面大概说一下具体操作流程。

1、打开目录并扫描目录“/sys/bus/pci/devices,”的网卡设备。

1root@domain 0000:00:07.0]# cd /sys/bus/pci/devices/
2[root@domain devices]# ls /*当前目录的pci设备编码如下*/
30000:00:00.0  0000:00:01.0  0000:00:01.1  0000:00:01.2  0000:00:01.3  0000:00:02.0  0000:00:03.0  0000:00:04.0  0000:00:05.0  0000:00:06.0  0000:00:07.0  0000:00:08.0

2、通过lspci | grep Eth ,我们可以知道哪些是Eth网卡设备

1[root@domain devices]# lspci | grep Eth /*但是只有四个数据以太网卡设备*/
200:03.0 Ethernet controller: Red Hat, Inc. Virtio network device
300:04.0 Ethernet controller: Red Hat, Inc. Virtio network device
400:06.0 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)
500:07.0 Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GbE SFP+ (rev 02)

3、以PCi 0000:00:07.0为例,查看目录下的文件信息

1root@domain 0000:00:07.0]# ls /*读取当前目录下文件,用来填充实例化后rte_pci_device 响应的字段*/
2broken_parity_status  consistent_dma_mask_bits  dma_mask_bits    enable         local_cpulist  modalias  numa_node  rescan    resource0     resource3_wc  subsystem_device  uio class 
3d3cold_allowed            driver           firmware_node  local_cpus     msi_bus   power      reset     resource0_wc  rom           subsystem_vendor  vendor
4config                device                    driver_override  irq            max_vfs        msi_irqs  remove     resource  resource3     subsystem     uevent

4、实例化网卡设备并填充相关信息,我们重点说明的有2个,后续使用:

1)当前网卡的驱动类型使用igb_uio还是vfio;enum rte_kernel_driver kdrv。

1[root@domain 0000:00:07.0]# ls driver -l /*当前网卡驱动是igb_uio*/
2lrwxrwxrwx 1 root root 0 7月   5 12:00 driver -> ../../../bus/pci/drivers/igb_uio

2)网卡物理资源初始化pci_parse_sysfs_resource来对资源进行填充mem_resource[6]

 1[root@domain 0000:00:07.0]# cat resource
 2resource      resource0     resource0_wc  resource3     resource3_wc
 3[root@domain 0000:00:07.0]# cat resource
 40x00000000fc800000 0x00000000fcffffff 0x000000000014220c
 50x0000000000000000 0x0000000000000000 0x0000000000000000
 60x0000000000000000 0x0000000000000000 0x0000000000000000
 70x00000000fd008000 0x00000000fd00ffff 0x000000000014220c
 80x0000000000000000 0x0000000000000000 0x0000000000000000
 90x0000000000000000 0x0000000000000000 0x0000000000000000
100x00000000fea80000 0x00000000feafffff 0x000000000004e200
110x0000000000000000 0x0000000000000000 0x0000000000000000
120x0000000000000000 0x0000000000000000 0x0000000000000000
130x0000000000000000 0x0000000000000000 0x0000000000000000
140x0000000000000000 0x0000000000000000 0x0000000000000000
150x0000000000000000 0x0000000000000000 0x0000000000000000
160x0000000000000000 0x0000000000000000 0x0000000000000000

并且将实例化后的dev 添加到rte_pci_bus.device_list链表中,下面有通过全局找到我们的网卡设备。
5、通过全局rte_pci_bus.device_list找到对应的网卡0000:00:07.0,gdb 打印处填充内容。

  1(gdb) p rte_pci_bus.device_list.tqh_first.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next[0]
  2$6 = {
  3  next = {  /*用于在全局网卡rte_pci_bus.device_list链表挂接使用*/
  4    tqe_next = 0x4d08b70,
  5    tqe_prev = 0x4cee8b0
  6  },
  7  device = {
  8    next = {
  9      tqe_next = 0x0,
 10      tqe_prev = 0x0
 11    },
 12    name = 0x4d02330 "0000:00:07.0",  /*指向当前结构体的name字段*/
 13    driver = 0x39b3e50 <rte_i40e_pmd+16>,/*对应的PMD驱动是i40E*/
 14    bus = 0x399dc40 <rte_pci_bus>,      /*全局的PCI bus 结构体*/
 15    numa_node = 0,
 16    devargs = 0x0
 17  },
 18  addr = {/*pci编号分割后的赋值0000:00:07.0*/
 19    domain = 0,
 20    bus = 0 '\000',
 21    devid = 7 '\a',
 22    function = 0 '\000'
 23  },
 24  id = {
 25    class_id = 131072, /*对应系统文件的数值/sys/bus/pci/devices/0000:00:07.0/class*/
 26    vendor_id = 32902, /*对应系统文件的数值/sys/bus/pci/devices/0000:00:07.0/vendor*/
 27    device_id = 5490,/*对应系统文件的数值/sys/bus/pci/devices/0000:00:07.0/device*/
 28    subsystem_vendor_id = 32902,/*对应系统文件的数值/sys/bus/pci/devices/0000:00:07.0/subsystem_vendor*/
 29    subsystem_device_id = 0/*对应系统文件的数值/sys/bus/pci/devices/0000:00:07.0/subsystem_device*/
 30  },
 31  mem_resource = {
   
   { /*对应资源文件中的内容/sys/bus/pci/devices/0000:00:07.0/resource*/
 32      phys_addr = 4236247040,/*物理地址和len是在scan的时候读取资源文件填充的*/
 33      len = 8388608,  /*对应资源的文件大小 /sys/bus/pci/devices/0000:00:07.0/resource0*/
 34      addr = 0x7f7c0080d000 /*虚拟地址是在probe函数调用的时候填充的*/
 35    }, {
 36      phys_addr = 0,
 37      len = 0,
 38      addr = 0x0
 39    }, {
 40      phys_addr = 0,
 41      len = 0,
 42      addr = 0x0
 43    }, {
 44      phys_addr = 4244668416,
 45      len = 32768,  /*对应资源的文件大小 /sys/bus/pci/devices/0000:00:07.0/resource3*/
 46      addr = 0x7f7c0100d000
 47    }, {
 48      phys_addr = 0,
 49      len = 0,
 50      addr = 0x0
 51    }, {
 52      phys_addr = 0,
 53      len = 0,
 54      addr = 0x0
 55    }},
 56  intr_handle = {
 57    {
 58      vfio_dev_fd = 25,
 59      uio_cfg_fd = 25 /*uio配置文件描述符号,对应文件/sys/class/uio/uio1/device/config*/
 60    },
 61    fd = 24, /*文件描述符,对应文件 /dev/uio1*/
 62    type = RTE_INTR_HANDLE_UIO,/*表示当前使用的是 igb——uio 驱动*/
 63    max_intr = 0,
 64    nb_efd = 0,
 65    efd_counter_size = 0 '\000',
 66    efds = {0 <repeats 512 times>},
 67    elist = {
   
   {
 68        status = 0,
 69        fd = 0,
 70        epfd = 0,
 71        epdata = {
 72          event = 0,
 73          data = 0x0,
 74          cb_fun = 0x0,
 75          cb_arg = 0x0
 76        }
 77      } <repeats 512 times>},
 78    intr_vec = 0x0
 79  },
 80  driver = 0x39b3e40 <rte_i40e_pmd>,
 81  max_vfs = 0,/*sriov VF的个数*/
 82  kdrv = RTE_KDRV_IGB_UIO, /*表示当前使用的是 igb_uio 驱动*/
 83  name = "0000:00:07.0\000\000\000\000\000",/*当前网卡pci编号*/
 84  vfio_req_intr_handle = {
 85    {
 86      vfio_dev_fd = 0,
 87      uio_cfg_fd = 0
 88    },
 89    fd = 0,
 90    type = RTE_INTR_HANDLE_UNKNOWN,
 91    max_intr = 0,
 92    nb_efd = 0,
 93    efd_counter_size = 0 '\000',
 94    efds = {0 <repeats 512 times>},
 95    elist = {
   
   {
 96        status = 0,
 97        fd = 0,
 98        epfd = 0,
 99        epdata = {
100          event = 0,
101          data = 0x0,
102          cb_fun = 0x0,
103          cb_arg = 0x0
104        }
105      } <repeats 512 times>},
106    intr_vec = 0x0
107  }
108}

 
学习更多dpdk视频
DPDK 学习资料、教学视频和学习路线图 :https://space.bilibili.com/1600631218
Dpdk/网络协议栈/ vpp /OvS/DDos/NFV/虚拟化/高性能专家 学习地址: https://ke.qq.com/course/5066203?flowToken=1043799
DPDK开发学习资料、教学视频和学习路线图分享有需要的可以自行添加学习交流q 君羊909332607备注(XMG) 获取

2、网卡驱动注册

网卡驱动注册宏在drivers/bus/pci/rte_bus_pci.h文件中具体如下:

 1/*将驱动PMD添加到全局驱动链表中rte_pci_bus.driver_list,在probe函数中会使用*/
 2void rte_pci_register(struct rte_pci_driver *driver);
 3
 4/** Helper for PCI device registration from driver (eth, crypto) instance */
 5#define RTE_PMD_REGISTER_PCI(nm, pci_drv) \
 6RTE_INIT(pciinitfn_ ##nm) \
 7{\
 8  (pci_drv).driver.name = RTE_STR(nm);\
 9  rte_pci_register(&pci_drv); \
10} \

下面是i40e网卡注册,主要是有个全局变量pci_id_i40e_map,存储的是网卡的id信息;在probe函数中通过通过struct rte_pci_id 中的vendor_id、device_id来匹配到当前的驱动。

1tatic struct rte_pci_driver rte_i40e_pmd = {
2  .id_table = pci_id_i40e_map, /*是个全局遍量通过struct rte_pci_id 中的vendor_id、device_id来匹配到当前的驱动*/
3  .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
4  .probe = eth_i40e_pci_probe,
5  .remove = eth_i40e_pci_remove,
6};
7RTE_PMD_REGISTER_PCI(net_i40e, rte_i40e_pmd);
8RTE_PMD_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
9RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio-pci");

举例如下:
我当前的X710网卡的vendor和device信息如下,正好可以匹配到pci_id_i40e_map表中。

1[root@domain 0000:00:07.0]# cat vendor
20x8086
3[root@domain 0000:00:07.0]# cat device
40x1572

pci_id_i40e_map表中对应的vendor和device信息如下:

1/*pci_id_i40e_map{ RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) }*/
2/* Vendor ID */
3#define I40E_INTEL_VENDOR_ID    0x8086
4/* Device IDs */
5#define I40E_DEV_ID_SFP_XL710    0x1572

通过rte_pci_bus.driver_list遍历到rte_i40e_pmd并打印rte_i40e_pmd信息如下:

 1(gdb)  p rte_pci_bus.driver_list.tqh_first.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next.next.tqe_next
 2$1 = (struct rte_pci_driver *) 0x39b3e40 <rte_i40e_pmd>
 3(gdb) p *$1
 4$3 = {
 5  next = {
 6    tqe_next = 0x39b3ec0 <rte_i40evf_pmd>,
 7    tqe_prev = 0x39b3500 <rte_hns3vf_pmd>
 8  },
 9  driver = {
10    next = {
11      tqe_next = 0x0,
12      tqe_prev = 0x0
13    },
14    name = 0x34abd6e "net_i40e",
15    alias = 0x0
16  },
17  bus = 0x399dc40 <rte_pci_bus>,
18  probe = 0x1561c12 <eth_i40e_pci_probe>,
19  remove = 0x1561e4e <eth_i40e_pci_remove>,
20  dma_map = 0x0,
21  dma_unmap = 0x0,
22  id_table = 0x34aae20 <pci_id_i40e_map>,
23  drv_flags = 9
24}

3 网卡probe处理流程

DPDK通过内核的UIO机制将硬件资源(MMIO, IO,interrupt)映射到用户态。可以参考博客
(https://blog.csdn.net/whenloce/article/details/88374867)

3.1 通过igb_uio驱动来映射到用户态

uio驱动在目录kernel/linux/igb_uio/igb_uio.c中。在dpdk EAL初始化中通过调用rte_bus_probe(目录文件lib/librte_eal/common/eal_common_bus.c)函数来完成的。下面我们来简单分析一下。
在用户态pci driver probe过程中,如果driver设置了RTE_PCI_DRV_NEED_MAPPING标记,就会执行地址映射,对应函数调用如下:

 1rte_bus_probe()->
 2   /*遍历rte_pci_bus.device_list链表调用pci_probe_all_drivers */
 3   pci_probe(drivers/bus/pci/pci_common.c)->
 4   /*遍历全局网卡驱动链表rte_pci_bus.driver_list链表和当前网卡的struct rte_pci_id 信息来匹配确定相应的的驱动PMD,驱动已经在设备启动是注册完成*/
 5   pci_probe_all_drivers()->rte_pci_probe_one_driver()->
 6       rte_pci_match()/*网卡驱动匹配函数*/
 7       rte_pci_map_device()/*通过igb_uio 来给当前设备映射资源mem_resource[6]*/
 8           pci_uio_map_resource()->pci_uio_alloc_resource()
 9                /*读取目录/sys/bus/pci/devices/0000:00:07.0/uio下目录uio1,获取uio num = 1,
10                 *进入uio1目录读取dev文件获取主次设备号,创建字符设备,具体看下面链接。*/
11                pci_get_uio_dev()
12                /*scan模块读取mem_resource资源物理地址和大小,这里为资源mmap虚拟地址*/
13                pci_uio_map_resource_by_index()
14       dr->probe=eth_i40e_pci_probe() /*网卡驱动probe*/

1)pci_get_uio_dev 读取主次设备号及uio编号,创建/dev/uio1 字符设备。

 1[root@domain uio]# pwd
 2/sys/bus/pci/devices/0000:00:07.0/uio
 3[root@domain uio]# ls
 4uio1         /*1、读取uio文件,来获取uio_num = 1*/
 5[root@domain uio]# cd uio1/
 6[root@domain uio1]# ls
 7dev  device  event  maps  name  power  subsystem  uevent  version
 8[root@domain uio1]# cat dev
 9242:1  /* 2、create the char device "mknod /dev/uioX c major minor" 获取主设备和次设备好,创建字符设备
10  snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
11  dev = makedev(major, minor);
12  ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);*/
13[root@domain uio1]# ls /sys/dev/char/ -l | grep uio
14lrwxrwxrwx 1 root root 0 7月  12 13:45 242:0 -> ../../devices/pci0000:00/0000:00:06.0/uio/uio0
15lrwxrwxrwx 1 root root 0 7月  12 13:45 242:1 -> ../../devices/pci0000:00/0000:00:07.0/uio/uio1
16lrwxrwxrwx 1 root root 0 7月  12 13:45 242:2 -> ../../devices/pci0000:00/0000:00:04.0/uio/uio2
17[root@domain uio1]# ls /dev/uio1 /*mknod*/
18/dev/uio1

3.2 网卡资源链表管理

全局变量rte_uio_tailq是用来管理网卡通过igb驱动map后的资源链表。由函数pci_uio_map_resource_by_index()来完成在大页中找一个靠近结尾的地址,根据mem长度使用mmap(pci_map_resource)进行映射。

 1(gdb) p rte_uio_tailq.head[0] /*全局资源尾队列头*/
 2$7 = {
 3  tailq_head = {
 4    tqh_first = 0x7f577fd9e200,
 5    tqh_last = 0x7f577fbb6c00
 6  },
 7  name = "UIO_RESOURCE_LIST", '\000' <repeats 14 times>
 8}
 9/*查询到PCI:0000:00:07.0对应mapped_pci_resource资源,gdb输出map资源信息*/
10(gdb) p (struct mapped_pci_resource)rte_uio_tailq.head->tailq_head.tqh_first.next.tqe_next.next.tqe_next.next.tqe_next
11$18 = {
12  next = {
13    tqe_next = 0x0,
14    tqe_prev = 0x7f577fd83dc0
15  },
16  pci_addr = {
17    domain = 0,
18    bus = 0 '\000',
19    devid = 7 '\a',
20    function = 0 '\000'
21  },
22  path = "/dev/uio1",
23  nb_maps = 2,
24  maps = {
   
   {
25      addr = 0x7f7c0080d000,
26      path = 0x7f577fbb5b80 "/sys/bus/pci/devices/0000:00:07.0/resource0",
27      offset = 0,
28      size = 8388608,
29      phaddr = 4236247040
30    }, {
31      addr = 0x7f7c0100d000,
32      path = 0x7f577fbb4b00 "/sys/bus/pci/devices/0000:00:07.0/resource3",
33      offset = 0,
34      size = 32768,
35      phaddr = 4244668416
36    }, },
37  msix_table = {
38    bar_index = 0,
39    offset = 0,
40    size = 0
41  }
42}
43(gdb)

3.3 eth_i40e_pci_probe 代码待深入分析

此处代码没有深入阅读,待后续深入分析。

  1retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
  2    sizeof(struct i40e_adapter),
  3    eth_dev_pci_specific_init, pci_dev,
  4    eth_i40e_dev_init, NULL)
  5
  6(gdb) p rte_eth_devices[2]
  7$30 = {
  8  rx_pkt_burst = 0x170be9b <i40e_recv_scattered_pkts_vec>, /*收包函数*/
  9  tx_pkt_burst = 0x16a47cb <i40e_xmit_pkts>, /*发包函数*/
 10  tx_pkt_prepare = 0x16c2900 <i40e_prep_pkts>,/*发包前的对报文的预处理函数*/
 11  data = 0x7f577fda2d80, /*对应全局共享数据rte_eth_dev_shared_data->data[2]*/
 12  process_private = 0x0,
 13  dev_ops = 0x398fa20 <i40e_eth_dev_ops>, /*驱动ops函数集合*/
 14  device = 0x4cfba20,  
 15  intr_handle = 0x4cfbb00,
 16  link_intr_cbs = {
 17    tqh_first = 0x0,
 18    tqh_last = 0x3f50700 <rte_eth_devices+33216>
 19  },
 20  post_rx_burst_cbs = {0x0 <repeats 1024 times>},
 21  pre_tx_burst_cbs = {0x0 <repeats 1024 times>},
 22  state = RTE_ETH_DEV_ATTACHED,
 23  security_ctx = 0x0,
 24  reserved_64s = {0, 0, 0, 0},
 25  reserved_ptrs = {0x0, 0x0, 0x0, 0x0}
 26}
 27(gdb) p rte_eth_dev_shared_data->data[2]
 28$22 = {
 29  name = "0000:00:07.0",
 30  rx_queues = 0x7f577fb3ed00,
 31  tx_queues = 0x7f577fcfd880,
 32  nb_rx_queues = 1,
 33  nb_tx_queues = 3,
 34  sriov = {
 35    active = 0 '\000',
 36    nb_q_per_pool = 0 '\000',
 37    def_vmdq_idx = 0,
 38    def_pool_q_idx = 0
 39  },
 40  dev_private = 0x7f577fbb2940,
 41  dev_link = {
 42    link_speed = 10000,
 43    link_duplex = 1,
 44    link_autoneg = 1,
 45    link_status = 1
 46  },
 47  dev_conf = {
 48    link_speeds = 3888,
 49    rxmode = {
 50      mq_mode = ETH_MQ_RX_NONE,
 51      max_rx_pkt_len = 9220,
 52      max_lro_pkt_size = 0,
 53      split_hdr_size = 0,
 54      offloads = 2048,
 55      reserved_64s = {0, 0},
 56      reserved_ptrs = {0x0, 0x0}
 57    },
 58    txmode = {
 59      mq_mode = ETH_MQ_TX_NONE,
 60      offloads = 32780,
 61      pvid = 0,
 62      hw_vlan_reject_tagged = 0 '\000',
 63      hw_vlan_reject_untagged = 0 '\000',
 64      hw_vlan_insert_pvid = 0 '\000',
 65      reserved_64s = {0, 0},
 66      reserved_ptrs = {0x0, 0x0}
 67    },
 68    lpbk_mode = 0,
 69    rx_adv_conf = {
 70      rss_conf = {
 71        rss_key = 0x0,
 72        rss_key_len = 0 '\000',
 73        rss_hf = 0
 74      },
 75      vmdq_dcb_conf = {
 76        nb_queue_pools = (unknown: 0),
 77        enable_default_pool = 0 '\000',
 78        default_pool = 0 '\000',
 79        nb_pool_maps = 0 '\000',
 80        pool_map = {
   
   {
 81            vlan_id = 0,
 82            pools = 0
 83          } <repeats 64 times>},
 84        dcb_tc = ""
 85      },
 86      dcb_rx_conf = {
 87        nb_tcs = (unknown: 0),
 88        dcb_tc = ""
 89      },
 90      vmdq_rx_conf = {
 91        nb_queue_pools = (unknown: 0),
 92        enable_default_pool = 0 '\000',
 93        default_pool = 0 '\000',
 94        enable_loop_back = 0 '\000',
 95        nb_pool_maps = 0 '\000',
 96        rx_mode = 0,
 97        pool_map = {
   
   {
 98            vlan_id = 0,
 99            pools = 0
100          } <repeats 64 times>}
101      }
102    },
103    tx_adv_conf = {
104      vmdq_dcb_tx_conf = {
105        nb_queue_pools = (unknown: 0),
106        dcb_tc = ""
107      },
108      dcb_tx_conf = {
109        nb_tcs = (unknown: 0),
110        dcb_tc = ""
111      },
112      vmdq_tx_conf = {
113        nb_queue_pools = (unknown: 0)
114      }
115    },
116    dcb_capability_en = 0,
117    fdir_conf = {
118      mode = RTE_FDIR_MODE_NONE,
119      pballoc = RTE_FDIR_PBALLOC_64K,
120      status = RTE_FDIR_NO_REPORT_STATUS,
121      drop_queue = 0 '\000',
122      mask = {
123        vlan_tci_mask = 0,
124        ipv4_mask = {
125          src_ip = 0,
126          dst_ip = 0,
127          tos = 0 '\000',
128          ttl = 0 '\000',
129          proto = 0 '\000'
130        },
131        ipv6_mask = {
132          src_ip = {0, 0, 0, 0},
133          dst_ip = {0, 0, 0, 0},
134          tc = 0 '\000',
135          proto = 0 '\000',
136          hop_limits = 0 '\000'
137        },
138        src_port_mask = 0,
139        dst_port_mask = 0,
140        mac_addr_byte_mask = 0 '\000',
141        tunnel_id_mask = 0,
142        tunnel_type_mask = 0 '\000'
143      },
144      flex_conf = {
145        nb_payloads = 0,
146        nb_flexmasks = 0,
147        flex_set = {
   
   {
148            type = RTE_ETH_PAYLOAD_UNKNOWN,
149            src_offset = {0 <repeats 16 times>}
150          }},
151        flex_mask = {
   
   {
152            flow_type = 0,
153            mask = ""
154          } <repeats 24 times>}
155      }
156    },
157    intr_conf = {
158      lsc = 0,
159      rxq = 0,
160      rmv = 0
161    }
162  },
163  mtu = 1500,
164  min_rx_buf_size = 2176,
165  rx_mbuf_alloc_failed = 0,
166  mac_addrs = 0x7f577fb30500,
167  mac_pool_sel = {0 <repeats 128 times>},
168  hash_mac_addrs = 0x0,
169  port_id = 2,
170  promiscuous = 1 '\001',
171  scattered_rx = 1 '\001',
172  all_multicast = 1 '\001',
173  dev_started = 1 '\001',
174  lro = 0 '\000',
175  rx_queue_state = "\001",
176  tx_queue_state = "\001\001\001",
177  dev_flags = 3,
178  kdrv = RTE_KDRV_IGB_UIO,
179  numa_node = 0,
180  vlan_filter_conf = {
181    ids = {0 <repeats 64 times>}
182  },
183  owner = {
184    id = 0,
185    name = ""
186  },
187  representor_id = 0,
188  reserved_64s = {0, 0, 0, 0},
189  reserved_ptrs = {0x0, 0x0, 0x0, 0x0}
190}

4、总结
本文只是简单介绍了网卡设备及PMD驱动的探测,并且实例化网卡设备;利用igb_uio驱动将网卡设备的IO及中断资源映射到用户态。但是对eth_i40e_pci_probe()函数还需要深入研究.

猜你喜欢

转载自blog.csdn.net/weixin_60043341/article/details/126607259