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;
}
设置收发函数
- 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
- 发送队列offloads为0时
- 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;
- if dev->data->lro设置时
启动网卡及配置收发队列
下面是以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就完成了
下面就是启动网卡设备了:
dpdk18.11 收发包流程分析相关推荐
- Linux 网络层收发包流程及 Netfilter 框架浅析
本文作者:sivenzhang,腾讯 IEG 测试开发工程师 1. 前言 本文主要对 Linux 系统内核协议栈中网络层接收,发送以及转发数据包的流程进行简要介绍,同时对 Netfilter 数据包过 ...
- 网卡收包流程分析(一)
由于本人工作内容主要集中于kernel的网络子系统,刚接触这个模块,于是想梳理一下网卡驱动的收包过程,以下内容为个人理解,如有不对,希望大家能够多多指正,相互成长~ 后续会持续更新有关kernel网络 ...
- Linux网络层收发包流程及Netfilter框架浅析
1. 前言 本文主要对 Linux 系统内核协议栈中网络层接收,发送以及转发数据包的流程进行简要介绍,同时对 Netfilter 数据包过滤框架的基本原理以及使用方式进行简单阐述. 内容如有理解错误而 ...
- linux 内核vxlan收发包流程
1.vxlan口收包处理流程 前面几章详细介绍了vxlan接口的使用,而且已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走,在此复习一下内核收发包流程(驱动层 ...
- 【无线】【流程】QCA无线驱动收包流程分析
概述: 无线驱动的收包过程是基于中断的处理方式.在准备接收数据之前,驱动需要先进行初始化接收数据使用到的相关结构( sc_rxbuf和rxfifo ).当数据包到达时,硬件会首先进行 DMA,完成以后 ...
- ixgbe网卡驱动 Ⅳ----收发包流程详解
目录 1 网卡队列收包流程概述 2 ixgbe_ring 结构 3 ixgbe 驱动收包流程 3.1 硬件中断入口 ixgbe_msix_clean_rings/ixgbe_intr 3.2 软中断入 ...
- Android 11 热点(softap)流程分析
最近在做Android 11中热点的功能,主要是网络共享,一个是usb网络共享,一个是热点网络共享,本文只是记录热点分享的流程. 一. settings 里面打开热点的接口跟原来类似 packages ...
- Android 11 热点(softap)流程分析(二) WifiManager--AIDL
Android 10以后引入了stable aidl方法,结合上一篇中WifiManager类中通过aidl调用到WifiServiceImpl类中方法,做个详细的记录. 一.frameworks/b ...
- DPDK 网卡收包流程
Table of Contents 1.Linux网络收发包流程 1.1 网卡与liuux驱动交互 1.2 linux驱动与内核协议栈交互 题外1: 中断处理逻辑 题外2:中断的弊端 2.linux ...
最新文章
- java jdbc效率_Java JDBC效率:连接需要多长时间?
- Max Sum(经典DP)
- 2018年超大规模数据中心总数达到430个
- vmware中centos6.4突然无法进入图形界面解决方法
- “阿基里斯与乌龟”的终结性思考
- h.264并行解码算法分析
- iOS:segment对齐原则
- TA进阶实例36(MMD pmx导入Unreal流程)
- Linux的shell脚本教程(一)
- 如何搭建百度离线地图服务
- 正则表达式详解及示例
- bugku never_give_up file_get_contents()有php://input漏洞 eregi \x00绕过
- 【19/04/18 膜赛】土豪聪要请客(stol)
- linux命令pp,linux命令 $- 是什么意思
- 一堆小众实用工具网站,建议收藏!
- 高并发网络服务器设计
- 【渗透实战】日常挖洞第二期_旁站注入“花式”漏洞拿下大型服务器
- 搜索引擎中输入检索词到返回十条结果,发生了哪些事情
- python查看电脑配置_怎么查看电脑配置
- 利尔达芯智行:破解两轮出行行业智能化难题
热门文章
- matlab张量工具初步
- 2017-2018-1 20155301 《信息安全系统设计基础》第7周学习总结
- C#:Dockpanel的一些入门的基本操作
- 庖丁解牛-----Live555源码彻底解密(根据MediaServer讲解Rtsp的建立过程)
- HALCON示例程序sequence_diff.hdev通过两张连续图像进行车辆流量监控
- HALCON示例程序color_fuses_lut_trans.hdev通过颜色对保险丝进行分类
- HALCON示例程序color_fuses.hdev通过颜色对保险丝进行分类
- 做演员是圆梦 做生意学会面对现实
- C++ vector.insert的用法
- c++分治法求最大最小值实现_程序员:算法导论,分治法、归并排序,伪代码和Java实现...