dpdk18.11 收发包流程分析

pci probe

RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd); 宏注册了net_ixgbe driver到pci bus

rte_ixgbe_pmd 的定义如下

static struct rte_pci_driver rte_ixgbe_pmd = {.id_table = pci_id_ixgbe_map,.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,.probe = eth_ixgbe_pci_probe,.remove = eth_ixgbe_pci_remove,
};

当扫描到到的device 能和pci_id_ixgbe_map 里的id 匹配上时就表示这个device和net_ixgbe 这个driver相匹配,接着便会调用.probe = eth_ixgbe_pci_probe指定的probe函数,这里我们关注下probe 函数对收发报函数的设置

static int
->eth_ixgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,struct rte_pci_device *)->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);->eth_ixgbe_dev_init(struct rte_eth_dev *, void *init_params )

eth_ixgbe_dev_init 中会完成driver的初始化,其中就包括了调用 ixgbe_set_tx_function、ixgbe_set_rx_function根据情况设置对应的收发函数

static int
eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
{/*省略*/eth_dev->dev_ops = &ixgbe_eth_dev_ops;eth_dev->rx_pkt_burst = &ixgbe_recv_pkts;eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts;eth_dev->tx_pkt_prepare = &ixgbe_prep_pkts;/*省略*/if (rte_eal_process_type() != RTE_PROC_PRIMARY) {struct ixgbe_tx_queue *txq;/* TX queue function in primary, set by last queue initialized* Tx queue may not initialized by primary process*/if (eth_dev->data->tx_queues) {txq = eth_dev->data->tx_queues[eth_dev->data->nb_tx_queues-1];ixgbe_set_tx_function(eth_dev, txq);} else {/* Use default TX function if we get here */PMD_INIT_LOG(NOTICE, "No TX queues configured yet. ""Using default TX function.");}ixgbe_set_rx_function(eth_dev);return 0;	//对于从核只会执行到这里}/*省略*/return 0;
}

设置收发函数

  1. tx函数设置
    • 发送队列offloads为0时
      • 未启用向量 tx_pkt_burst = ixgbe_xmit_pkts_simple
      • 启用向量 dev->tx_pkt_burst = ixgbe_xmit_pkts_vec;
    • 发送队列offloads非0
      • dev->tx_pkt_burst = ixgbe_xmit_pkts
  2. rx函数设置
    • if dev->data->lro设置时
      • adapter->rx_bulk_alloc_allowed 设置,允许bulk时dev->rx_pkt_burst = ixgbe_recv_pkts_lro_bulk_alloc;
      • dev->rx_pkt_burst = ixgbe_recv_pkts_lro_single_alloc;
    • else if dev->data->scattered_rx 设置时
      • dev->data->scattered_rx 设置,支持向量时 dev->rx_pkt_burst = ixgbe_recv_scattered_pkts_vec;
      • adapter->rx_bulk_alloc_allowed 设置支持bulk时 dev->rx_pkt_burst = ixgbe_recv_pkts_lro_bulk_alloc;
      • dev->rx_pkt_burst = ixgbe_recv_pkts_lro_single_alloc;
    • else ifadapter->rx_vec_allowed 设置时
      • dev->rx_pkt_burst = ixgbe_recv_pkts_vec;
    • else if adapter->rx_bulk_alloc_allowed 设置时
      • dev->rx_pkt_burst = ixgbe_recv_pkts_bulk_alloc;
    • else dev->rx_pkt_burst = ixgbe_recv_pkts;

启动网卡及配置收发队列

下面是以L2FWD为例,总结了下dpdk对网卡配置、收发队列配置的API。以下代码做了省略,删除了返回判断代码

在这里插入图片描述

int
main(int argc, char **argv)
{   struct lcore_queue_conf *qconf;int ret;uint16_t nb_ports;uint16_t nb_ports_available = 0;uint16_t portid, last_port;unsigned lcore_id, rx_lcore_id;unsigned nb_ports_in_mask = 0;unsigned int nb_lcores = 0;unsigned int nb_mbufs;/* init EAL */ret = rte_eal_init(argc, argv);if (ret < 0)rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");argc -= ret;argv += ret;force_quit = false;signal(SIGINT, signal_handler);signal(SIGTERM, signal_handler);/* 解析传入的参数 (after the EAL ones) */ret = l2fwd_parse_args(argc, argv);if (ret < 0)rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled");nb_ports = rte_eth_dev_count_avail();if (nb_ports == 0)rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");/* check port mask to possible port mask */if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1))rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n",(1 << nb_ports) - 1);/*计算所需的mbuf个数*/nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST +nb_lcores * MEMPOOL_CACHE_SIZE), 8192U);/* 创建内存池 */l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs,MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());/* Initialise each port */RTE_ETH_FOREACH_DEV(portid) {struct rte_eth_rxconf rxq_conf;struct rte_eth_txconf txq_conf;struct rte_eth_conf local_port_conf = port_conf;struct rte_eth_dev_info dev_info;/* skip ports that are not enabled */if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {printf("Skipping disabled port %u\n", portid);continue;}nb_ports_available++;/* init port */printf("Initializing port %u... ", portid);fflush(stdout);rte_eth_dev_info_get(portid, &dev_info);if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)local_port_conf.txmode.offloads |=DEV_TX_OFFLOAD_MBUF_FAST_FREE;ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,&nb_txd);rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]);/* init one RX queue */fflush(stdout);rxq_conf = dev_info.default_rxconf;rxq_conf.offloads = local_port_conf.rxmode.offloads;ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,rte_eth_dev_socket_id(portid),&rxq_conf,l2fwd_pktmbuf_pool);if (ret < 0)rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",ret, portid);/* init one TX queue on each port */fflush(stdout);txq_conf = dev_info.default_txconf;txq_conf.offloads = local_port_conf.txmode.offloads;ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,rte_eth_dev_socket_id(portid),&txq_conf);/* Initialize TX buffers */tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,rte_eth_dev_socket_id(portid));if (tx_buffer[portid] == NULL)rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n",portid);rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST);/*设置错误统计回调函数*/ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],rte_eth_tx_buffer_count_callback,&port_statistics[portid].dropped);/* Start device */ret = rte_eth_dev_start(portid);rte_eth_promiscuous_enable(portid);}if (!nb_ports_available) {rte_exit(EXIT_FAILURE,"All available ports are disabled. Please set portmask.\n");}check_all_ports_link_status(l2fwd_enabled_port_mask);ret = 0;/* launch per-lcore init on every lcore */rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, NULL, CALL_MASTER);RTE_LCORE_FOREACH_SLAVE(lcore_id) {if (rte_eal_wait_lcore(lcore_id) < 0) {ret = -1;break;}}RTE_ETH_FOREACH_DEV(portid) {if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)continue;printf("Closing port %d...", portid);rte_eth_dev_stop(portid);rte_eth_dev_close(portid);printf(" Done\n");}printf("Bye...\n");return ret;
}

rte_eth_dev_configure

rte_eth_dev_configure是EAL对外提供的api(lib/librte_ethdev/rte_ethdev.c),下面分析下dpdk中对网卡设备的配置

在这里插入图片描述

rte_eth_rx_queue_setup

rte_eth_rx_queue_setup是EAL对外提供的api(lib/librte_ethdev/rte_ethdev.c),下面分析下dpdk中对队列的配置
在这里插入图片描述

  • 在rte_eth_dev_configure中设置的offload属性会被设置到每个队列
  • 调用调用eth_dev_ops中的rx_queue_setup回调函数
    在ixgbe网卡中,对应的rx_queue_setup回调函数是ixgbe_dev_rx_queue_setup

在这里插入图片描述
rte_eth_rx_queue_setup就完成了

下面就是启动网卡设备了:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能芯片龙头之一gti概念股_AI芯片龙头寒武纪IPO价格定了!概念股全名单收好...

寒武纪披露首次公开发行股票并在科创板上市发行公告&#xff0c;确定发行价格为64.39元/股&#xff0c;本次科创板上市发行剔除无效报价和最高报价后剩余报价拟申购总量为3,405,910万股&#xff0c;整体申购倍数为回拨前网下初始发行规模的1327.12倍。战略配售投资者包含中信证…

x86汇编语言-从实模式到保护模式----第五章

注释由;开始。将显存映射到地址空间里&#xff0c;0xB8000~0xBFFFF。Intel的处理器不允许将一个立即数传送到段寄存器&#xff0c;只允许这样的指令&#xff1a;mov 段寄存器&#xff0c;通用寄存器 mov 段寄存器&#xff0c;内存单元 为了方便&#xff0c;多数汇编语言编译器允…

Java面向对象(3) —— 抽象类、接口、内部类、匿名内部类

目录抽象类&#xff08;abstract&#xff09;抽象类的使用方法抽象类的应用&#xff1a;模板方法模式接口接口的概念接口的特点接口的使用接口实现与抽象类继承的区别接口的多继承内部类概念成员内部类&#xff08;使用较多&#xff09;及应用创建成员内部类的实例在成员内部类…

Kohana和Zencart

2019独角兽企业重金招聘Python工程师标准>>> 我有一个Kohana php框架但是客户求和zencart系统结合。我有一个想法是Kohana重新zencart 有没有人用过&#xff1f;应该没有吧 Kohana 是一款纯 PHP5 的框架&#xff0c;基于 MVC 模式开发&#xff0c; 它的特点就是高安…

Linux stmac网卡代码分析 -- open

Open stmmac_open是在stmmac_netdev_ops结构体里的&#xff0c;这个ops在probe时就已经注册到了net_device结构体里&#xff0c;在网卡对于stmmac_open函数调用的时间我还不确定是否是在网卡link up时 下面看看stmmac_open函数&#xff0c;文件位置&#xff1a; drivers/net/…

g++ linux 编译开栈_方舟编译器编译hello world踩坑全记录

闲来无事&#xff0c;看到方舟编译器完整开源&#xff0c;于是打算拿来试着编译一个东西来&#xff0c;接下来把踩过的一些坑记录一下。参考文档方舟编译器的官网是OpenArkCompiler​www.openarkcompiler.cn但是这个网站上的文档其实是过时的&#xff0c;没有更新过的&#xff…

绘制自定义键盘

先看下微信当中的自带的数字键盘 这种实现方式比较简单&#xff0c;可以直接用inline-block标签&#xff0c;设置每行平均宽度&#xff0c;比如一行要放4个按钮&#xff0c;可以那么宽度就可以设为25%&#xff0c;同时要注意设置css样式为box-sizing: border-box,这样在设置边框…

配置管理小报100329:脚本中ftp命令无法自动输入密码怎么办?

为什么80%的码农都做不了架构师&#xff1f;>>> 知识点&#xff1a; 作者&#xff1a;王&#xff08;zbwangjian.cn&#xff09; 脚本中ftp命令无法自动输入密码怎么办&#xff1f;参考&#xff1a; http://www.linji.cn/post/1620/ http://www.hamo…

linux下使用网易邮箱发邮件

0x0 最近要写个脚本监视系统运行情况&#xff0c;有异常及时通过邮件通知我。 本次测试中使用网易的邮箱作为邮件发送服务器&#xff08;邮箱账号需要开启smtp服务如下图&#xff09;&#xff0c;由于网易邮箱验证比较严格&#xff0c;需要进行一些额外操作才可以正常发送邮件…

Java面向对象(4) ——多态

目录多态的概念对象上下转型多态应用之打印机多态的概念 多态是指同一个操作作用于某一类对象&#xff0c;可以有不同的解释&#xff0c;产生不同的执行结果。比如&#xff1a;猫吃鱼、狗吃肉、人吃米饭。 多态存在的三个必要条件: 需要存在继承&#xff08;extends&#xf…

ffmpeg 转换flv压缩大小_ffmpeg转换参数和压缩输出大小的比率 参考 最新版本FFMPEG...

https://blog.cnlabs.NET/3668.htmlffmpeg 转换压缩比例FFMPEG如果是压缩为FLV文件 3个编码可选1. -c:v flv 标准FLV编码 这个好处是速度快 清晰度高的话 视频文件会比较大2. -c:v vp6 VP6编码 这个大家都很少使用 其实这个也算不错3. -c:v libx264 H.264编码 估计使用这个的比…

Git 常用命令清单,掌握这些,轻松驾驭版本管理

GitHub 地址&#xff0c;欢迎star&#xff0c;查看更多整理的前端知识点 工程下载、分支的增删查改 工程下载&#xff1a; clone 远程工程&#xff1a;git clone https://XXXX.gitfetch 远程分支到本地某分支&#xff1a;git fetch origin <orginname>:<localname>…

【运维囧事】运维的苦乐之旅

人生就是一段充满苦与乐的旅程&#xff0c;在人生当中有痛苦也有欢乐&#xff0c;痛苦不一定是负面的&#xff0c;有的时候还会使你进步&#xff0c;增强应变能力。对一般人而言&#xff0c;人生一定要是快乐的才是有意义的&#xff0c;可是你仔细想想&#xff0c;有谁不是因为…

ubuntu下网易云音乐适配高分辨率屏幕

0x0 环境 ubuntu20处理器 AMD 我主流工作环境是Ubuntu20&#xff0c;而且很依赖音乐&#xff0c;网易云音乐适配了Ubuntu&#xff0c;而最近我换了个4K屏幕 开机启动网易云音乐后发现界面文字变得很小完全没法看&#xff0c;如下图 分析发现网易云音乐是通过 /opt/netease/ne…

Java基础 —— 异常

目录异常的概念及分类异常的处理try-catch-finally异常抛出throw(s)自定义异常异常的概念及分类 什么是异常 异常是指在程序的运行过程中发生的一些不正常事件。比如&#xff1a;除0溢出、数组下标越界、所要读取的文件不存在。 异常导致的后果 项目JAVA程序的执行过程中如出现…

excel函数去重_excel去重函数

在日常工作问题中&#xff0c;经常会遇到一个问题&#xff0c;当你呼哧呼哧处理了大半天的数据后才发现&#xff0c;原始数据好多重复的&#xff0c;导致你得到的结果全部错误……顿时&#xff0c;想砍人的心都有了&#xff0c;心理阴影面积无穷大……当然&#xff0c;胖斯基也…

解决网站请求速度慢的一些方法

开门见山&#xff0c;网站请求反应速度慢首先考虑服务器问题。 我在开发中遇到的就是服务器实例限制cpu占用10%以内访问正常&#xff0c;超出则限制访问速度&#xff0c;也就是网站请求速度慢 具体和阿里工程师聊天截图如下&#xff1a; 按照对方说的&#xff0c;升级了相关配置…

Windows Server 2012 在个人终端上使用的推荐设置

Windows Server 2012&#xff0c;也就是 Windows 8 的服务器版本&#xff0c;相对于 Windows 8 企业版而言&#xff0c;增强了作为服务器的功能&#xff0c;弱化了作为终端系统的功能。   目前微软官方提供了 Windows 8 企业版&#xff08;90 天评估期&#xff09;和 Windows…

解决crontab 定时任务加载失败

0x0 系统&#xff1a;centos7内核&#xff1a;3.10.0-1160.15.2.el7.x86_64 今天用crontab创建定时任务&#xff0c;在测试时发现任务并没有按预期执行&#xff0c; 使用systemctl status crond 查看crond的状态 > # systemctl status crond …

Java高级 —— 泛型

目录泛型概念泛型可设置多个类型参数泛型继承泛型接口限制泛型可用类型泛型通配声明泛型方法泛型方法限制泛型可用类型泛型概念 问题引入&#xff1a;如果我们需要产生多个对象&#xff0c;每个对象的逻辑完全一样&#xff0c;只是对象内的成员啊变量的类型不同。那我们如何去…