rte_bus_probe()->pci_probe_all_drivers()->rte_pci_probe_one_driver()->eth_ixgbe_pci_probe()

继续分析rte_pci_probe_one_driver()的实现,接下来调用与设备匹配的驱动的probe方法,此处以ixgbe设备的驱动为例,其probe方法为eth_ixgbe_pci_probe()。

static int eth_ixgbe_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_dev *pf_ethdev;struct rte_eth_devargs eth_da;int i, retval;if (pci_dev->device.devargs) {retval = rte_eth_devargs_parse(pci_dev->device.devargs->args, &eth_da);……} elsememset(&eth_da, 0, sizeof(eth_da));retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,sizeof(struct ixgbe_adapter), eth_dev_pci_specific_init, pci_dev, eth_ixgbe_dev_init, NULL);……pf_ethdev = rte_eth_dev_allocated(pci_dev->device.name);……/* probe VF representor ports */for (i = 0; i < eth_da.nb_representor_ports; i++) {struct ixgbe_vf_info *vfinfo;struct ixgbe_vf_representor representor;vfinfo = *IXGBE_DEV_PRIVATE_TO_P_VFDATA(pf_ethdev->data->dev_private);……representor.vf_id = eth_da.representor_ports[i];representor.switch_domain_id = vfinfo->switch_domain_id;representor.pf_ethdev = pf_ethdev;/* 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 ixgbe_vf_representor), NULL, NULL,ixgbe_vf_representor_init, &representor);……}return 0;
}

eth_ixgbe_pci_probe()中,如果存在,首先解析设备的devargs,调用rte_eth_devargs_parse()实现,主要是解析参数中传入的port和representor port的信息(对应的VFIO技术中的PF和VF)。之后调用rte_eth_dev_create()创建设备,调用该函数时,会传入两个函数参数,eth_dev_pci_specific_init()和eth_ixgbe_dev_init(),其中eth_ixgbe_dev_init()不得是空值。

int rte_eth_dev_create(struct rte_device *device, const char *name,size_t priv_data_size, ethdev_bus_specific_init ethdev_bus_specific_init,void *bus_init_params, ethdev_init_t ethdev_init, void *init_params) {struct rte_eth_dev *ethdev;int retval;……if (rte_eal_process_type() == RTE_PROC_PRIMARY) {ethdev = rte_eth_dev_allocate(name);……if (priv_data_size) {ethdev->data->dev_private = rte_zmalloc_socket(name, priv_data_size, RTE_CACHE_LINE_SIZE,device->numa_node);……}} else {ethdev = rte_eth_dev_attach_secondary(name);……}ethdev->device = device;if (ethdev_bus_specific_init) {retval = ethdev_bus_specific_init(ethdev, bus_init_params);if (retval) {RTE_ETHDEV_LOG(ERR,"ethdev bus specific initialisation failed\n");goto probe_failed;}}retval = ethdev_init(ethdev, init_params);if (retval) {RTE_ETHDEV_LOG(ERR, "ethdev initialisation failed\n");goto probe_failed;}rte_eth_dev_probing_finish(ethdev);return retval;……
}

rte_eth_dev_create()中,会根据DPDK是primary还是secondary的不同,采用不同的方式创建设备

  • primary

primary模式下,调用rte_eth_dev_allocate()创建设备,创建设备之前,会检查模块全局指针eth_dev_shared_data是否进行了初始化,未做初始化时进行初始化操作。该指针指向的内存区域,包含了必要的锁和需要共享的数据,且是通过memzone接口创建出来的,故对该内存区域的修改能够被DPDK的secondary进程看到。接下来调用eth_dev_find_free_port()在rte_eth_devices数组中查找空闲的项(rte_eth_dev类型),找到的话,将设备的name,port_id,mtu等信息填充到rte_eth_dev->data中,另外在data->data_private中创建一块区域存储,用来存储struct ixgeb_adaptor结构,这里需要特别注意的是rte_eth_dev->data的存储区域,对应的是eth_dev_shared_data->data[i],对应rte_eth_dev->data的读写实际上是对eth_dev_shared_data->data[i]的读写。

  • secondary

secondary模式下,调用rte_eth_dev_attach_secondary()创建设备。会在eth_dev_shared_data中查找设备的名称,如果找到,则将eth_dev_shared_data中对应port的data赋值给rte_eth_dev->data。这样secondary进程中的数据看到的和primary中的数据是相同的。

创建完成之后,将rte_eth_dev和rte_device进行关联。如果ethdev_bus_specific_init()函数不为空,则执行,此处对应的是eth_dev_pci_specific_init(),主要工作是将rte_pci_device中的一些信息拷贝到rte_eth_dev中。接下来执行ethdev_init(),此处对应的是eth_ixgbe_dev_init()。该func主要是初始化rte_eth_dev中的函数指针,保护数据包的收发,网卡配置,网卡信息获取,网卡队列操作等。如果是VFIO设备,还承担着PF初始化等工作。在最后,调用rte_eth_dev_probing_finish()将设备状态置为RTE_ETH_DEV_ATTACHED。

rte_eth_dev_create()之后,调用rte_eth_dev_allocated()获取PF设备的指针,根据devargs中配置的representor port的信息,配置VF设备。

此处仍然是调用rte_eth_dev_create()来创建设备,与之前不同的是,此时设备的data->data_private存储的是struct ixgeb_vf_representor,设备初始化接口变成了ixgbe_vf_representor_init(),其主要工作与eth_ixgbe_dev_init()类似。

至此,我们对rte_eth_devices数据结构的填充分析完成。从前面的分析内容可以看出,在DPDK的init阶段这些信息就已经被填充到模块局部变量rte_eth_devices当中,接下来,我们可以返回第(九)篇文章中,继续对example/ethtool进行分析。

example/ethtool

ethtool这个范例中,自定义了setup_ports()接口,包含了如下的一些操作。

static void setup_ports(struct app_config *app_cfg, int cnt_ports) {……for (idx_port = 0; idx_port < cnt_ports; idx_port++) {struct app_port *ptr_port = &app_cfg->ports[idx_port];ret = rte_eth_dev_info_get(idx_port, &dev_info);……size_pktpool = dev_info.rx_desc_lim.nb_max +dev_info.tx_desc_lim.nb_max + PKTPOOL_EXTRA_SIZE;snprintf(str_name, 16, "pkt_pool%i", idx_port);ptr_port->pkt_pool = rte_pktmbuf_pool_create(str_name, size_pktpool, PKTPOOL_CACHE,0, RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());……printf("Init port %i..\n", idx_port);ptr_port->port_active = 1;ptr_port->port_dirty = 0;ptr_port->idx_port = idx_port;if (rte_eth_dev_configure(idx_port, 1, 1, &cfg_port) < 0)rte_exit(EXIT_FAILURE,"rte_eth_dev_configure failed");……if (rte_eth_rx_queue_setup(idx_port, 0, nb_rxd,rte_eth_dev_socket_id(idx_port), NULL,ptr_port->pkt_pool) < 0)……if (rte_eth_tx_queue_setup(idx_port, 0, nb_txd,rte_eth_dev_socket_id(idx_port), NULL) < 0)……if (rte_eth_dev_start(idx_port) < 0)……ret = rte_eth_macaddr_get(idx_port, &ptr_port->mac_addr);……rte_spinlock_init(&ptr_port->lock);}
}

setup_ports()将一些需要网卡设备进行配置的工作进行了封装,接下来将对这些内容进行分析,未完待续……

DPU网络开发SDK——DPDK(十二)相关推荐

  1. DPU网络开发SDK——DPDK(二)

    Hello world 上一次的文章中主要介绍了DPDK是什么,主要用在什么地方.作为一个SDK,DPDK提供了大量的function接口用于网络转发面程序的编写.接下来的几篇文章,我们会基于DPDK ...

  2. DPU网络开发SDK——DPDK(九)

    rte_eal_remote_launch() 在过去的几篇文章中,我们重点分析了DPDK初始化过程rte_eal_init()的主要流程,了解了其内存分配,primary和secondary之间如何 ...

  3. DPU网络开发SDK—DPDK(七)

     rte_eal_init() 接上次内容继续对rte_eal_init()所做的工作进行分析. 24. 内存初始化 24.2. 内存分配 调用eal_memalloc_init()来处理内存分配,前 ...

  4. DPU网络开发SDK—DPDK(八)

    rte_eal_init() 接上次内容继续对rte_eal_init()所做的工作进行分析. 25. 内存堆初始化 调用rte_eal_malloc_heap_init()进行初始化. 如果进程类型 ...

  5. DPU网络开发SDK—DPDK(六)

    rte_eal_init() 接上次内容继续对rte_eal_init()所做的工作进行分析. 20. 大页内存配置 internal_conf中的no_hugetlbfs指明是否禁用大页内存,通过命 ...

  6. 20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业

    20189200余超 2018-2019-2 移动平台应用开发实践第十二周作业 服务 Service的声明 Service是Android中的四大组件,使用它一定要在AndroidManifest.x ...

  7. iOS 11开发教程(十二)iOS11应用视图始祖——UIView

    iOS 11开发教程(十二)iOS11应用视图始祖--UIView 在Swift中,NSObject是所有类的根类.同样在UIKit框架(UIKit框架为iOS应用程序提供界面对象和控制器)中,也存在 ...

  8. SAP UI5 应用开发教程之六十二 - 基于 OData V4 的 SAP UI5 表格控件使用方法介绍试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

  9. SAP UI5 应用开发教程之四十二 - SAP UI5 自带的 Diagnostics 诊断工具使用方法介绍

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

最新文章

  1. iOS开发业界毒瘤 Hook
  2. 用SimpleDateFormat类设置时间格式
  3. 分享一下SecureCRT输出颜色和格式
  4. linux netlink 编程示例(二)应用层
  5. java jframe添加按钮_JFrame窗口中如何加按钮啊?(JDK)
  6. mac 下载python库,Mac电脑安装python第三方库(就于python3)
  7. 编译时类型 和运行时类型的 区别(1)
  8. 汇编学习笔记(3)-80x86指令集
  9. hdoj1789:Doing Homework again (贪心)
  10. element-ui组件中的input等的change事件中传递自定义参数
  11. USB和USB2.0万能驱动
  12. 基于JAVA+SpringMVC+Mybatis+Vue+MYSQL的大学体育健康管理系统
  13. python字符串驼峰转换_驼峰风格字符串转换为下滑线风格字符串
  14. 面试题 10.01. 合并排序的数组
  15. BIRCH算法(Java实现)
  16. MongoDB高可用集群搭建(主从、分片、路由、安全验证)
  17. 60分钟带你入门iOS开发
  18. 这个数据库神器真是太diao了
  19. 厘摩(centimorgan,cM)到底是啥鬼
  20. MCAL系列介绍04-GPT

热门文章

  1. 位图(bitset)的使用【STL】
  2. 手机浏览器查看网页源码
  3. 记一次confluence邮件服务器配置的坑(阿里企业邮箱)
  4. wincc7.4安装授权 全(文件分享)
  5. SonarQube7.4集成P3C
  6. 积分球测试软件无法创建新文档,积分球测试光通量不准确的解决方案
  7. 通俗地理解信号与系统中的卷积
  8. 小四年级下册计算机教学计划,小学四年级下第二学期信息技术教学计划.doc
  9. android面试题库,Android面试试题及答案
  10. spark-2.2.0发行说明