本文主要介绍rte_mbuf与rte_mempool数据结构之间的组织关系、以及网卡接收到的数据是如何存储在rte_mbuf中的。

一、rte_mbuf、rte_mempool及网卡收到的数据包在内存中的组织结构

      

调用rte_mempool_create()函数创建rte_mempool的时候,指定申请多少个rte_mbuff及每个rte_mbuf中elt_size的大小。elt_size是为网卡接收的数据包预先分配的内存的大小,该内存块就是rte_mbuf->pkt.data的实际存储区域。具体如上图所示。

在申请的rte_mempool内存块中,最前面存储struct rte_mempool数据结构,后面紧接着是rte_pktmbuf_pool_private数据,再后面就是N个rte_mbuf内存块。

每个rte_mbuf内存中,最前面同样存储的是struct rte_mbuf数据结果,后面是RTE_PKTMBUF_HEADROOM,最后面就是实际网卡接收到的数据,如下:

   struct rte_mbuf *m = _m;uint32_t buf_len = mp->elt_size - sizeof(struct rte_mbuf);RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf));memset(m, 0, mp->elt_size);/* start of buffer is just after mbuf structure */m->buf_addr = (char *)m + sizeof(struct rte_mbuf);m->buf_physaddr = rte_mempool_virt2phy(mp, m) +sizeof(struct rte_mbuf);m->buf_len = (uint16_t)buf_len;/* keep some headroom between start of buffer and data */m->pkt.data = (char*) m->buf_addr + RTE_MIN(RTE_PKTMBUF_HEADROOM, m->buf_len);/* init some constant fields */m->type = RTE_MBUF_PKT;m->pool = mp;m->pkt.nb_segs = 1;m->pkt.in_port = 0xff;

二、网卡接收的数据是如何存储到rte_mbuf中的?

以e1000网卡为例,在网卡初始化的时候,调用eth_igb_rx_init()初始化网卡的收包队列。每个收包队列数据结果如下:

/*** Structure associated with each RX queue.*/
struct igb_rx_queue {struct rte_mempool  *mb_pool;   /**< mbuf pool to populate RX ring. */volatile union e1000_adv_rx_desc *rx_ring; /**< RX ring virtual address. */uint64_t            rx_ring_phys_addr; /**< RX ring DMA address. */volatile uint32_t   *rdt_reg_addr; /**< RDT register address. */volatile uint32_t   *rdh_reg_addr; /**< RDH register address. */struct igb_rx_entry *sw_ring;   /**< address of RX software ring. */struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */struct rte_mbuf *pkt_last_seg;  /**< Last segment of current packet. */uint16_t            nb_rx_desc; /**< number of RX descriptors. */uint16_t            rx_tail;    /**< current value of RDT register. */uint16_t            nb_rx_hold; /**< number of held free RX desc. */uint16_t            rx_free_thresh; /**< max free RX desc to hold. */uint16_t            queue_id;   /**< RX queue index. */uint16_t            reg_idx;    /**< RX queue register index. */uint8_t             port_id;    /**< Device port identifier. */uint8_t             pthresh;    /**< Prefetch threshold register. */uint8_t             hthresh;    /**< Host threshold register. */uint8_t             wthresh;    /**< Write-back threshold register. */uint8_t             crc_len;    /**< 0 if CRC stripped, 4 otherwise. */uint8_t             drop_en;  /**< If not 0, set SRRCTL.Drop_En. */
};

我们只关注其中两个成员变量,rx_ring和sw_ring。rx_ring记录的是union e1000_adv_rx_desc数组,每个union e1000_adv_rx_desc中指定了网卡接收数据的DMA地址,网卡收到数据后,直接往该地址写数据。sw_ring数组记录的是每个具体的rte_mbuf地址,每个rte_mbuf的rte_mbuff->buf_phyaddr + RTE_PKTMBUF_HEADROOM映射后的DMA地址就存储在rx_ring队列的union e1000_adv_rx_desc数据结构中。rte_mbuff->buf_phyaddr + RTE_PKTMBUF_HEADROOM指向的就是rte_mbuf->pkt.data的地址。此时,rte_mbuf、rte_mbuf->pkt.data,已经网卡的收包队列就关联起来了。具体如下:

static int
igb_alloc_rx_queue_mbufs(struct igb_rx_queue *rxq)
{struct igb_rx_entry *rxe = rxq->sw_ring;uint64_t dma_addr;unsigned i;/* Initialize software ring entries. */for (i = 0; i < rxq->nb_rx_desc; i++) {volatile union e1000_adv_rx_desc *rxd;struct rte_mbuf *mbuf = rte_rxmbuf_alloc(rxq->mb_pool);if (mbuf == NULL) {PMD_INIT_LOG(ERR, "RX mbuf alloc failed ""queue_id=%hu\n", rxq->queue_id);return (-ENOMEM);}dma_addr =rte_cpu_to_le_64(RTE_MBUF_DATA_DMA_ADDR_DEFAULT(mbuf));rxd = &rxq->rx_ring[i];rxd->read.hdr_addr = dma_addr;rxd->read.pkt_addr = dma_addr;rxe[i].mbuf = mbuf;}return 0;
}

网卡收到数据后,向rx_ring指定的DMA地址上写数据,其实,就是往每个rte_mbuf->pkt.data写数据。应用程序在调用rte_eth_rx_burst()收包时,以e1000网卡为例,最后调用的是eth_igb_recv_pkts(),就是从每个收包队列中,从sw_ring数组中将rte_mbuf取出来,然后重启申请新的rte_mbuf替换到rx_ring中,重新关联rte_mbuf、union e1000_adv_rx_desc、sw_ring以及rte_mbuf->pkt.data的DMA地址。如下简图所示。

    

(转)DPDK内存管理05 -- rte_mbuf相关推荐

  1. DPDK内存管理 ----- (四) rte_mbuf

    本文主要介绍 rte_mbuf 与 rte_mempool 数据结构之间的组织关系.以及网卡接收到的数据是如何存储在 rte_mbuf 中的. 一.   rte_mbuf.rte_mempool及网卡 ...

  2. dpdk内存管理分析

    dpdk内存管理分析 文章目录 dpdk内存管理分析 1.1 简述 1.2 `rte_config_init`分析 1.3 `eal_hugepage_info_init`的分析 1.4 `rte_e ...

  3. DPDK 内存管理---malloc_heap和malloc_elem

    博文是基于dpdk20.5代码阅读所写,如理解有错误或不当之处,烦请指正,不甚感激.也可以私信我一起探讨. 两种数据结构体介绍 Malloc 库内部使用了两种数据结构类型(可以参考dpdk官方文档3. ...

  4. dpdk内存管理——内存初始化

    *说明:本系列博文源代码均来自dpdk17.02* 1.1内存初始化 1.1.1 hugepage技术 hugepage(2M/1G..)相对于普通的page(4K)来说有几个特点: (1) huge ...

  5. dpdk内存管理之rte_eal_hugepage_init()函数分析

    dpdk版本:dpdk-stable-16.11.11 今天我们来看一下rte_eal_hugepage_init() 函数都干了哪些事. 1.计算大页总数 在调用rte_eal_hugepage_i ...

  6. DPDK内存管理总结

    1.前言 本文基于DPDK-17.05.2分析总结, DPDK通过使用hugetlbfs,减少CPU TLB表的Miss次数,提高性能. 2.Hugetlbfs初始化 DPDK的内存初始化工作,主要是 ...

  7. dpdk 内存管理 原理剖析

    dpdk 的内存管理层次结构 物理巨页的管理 虚拟地址空间的管理 heap管理(变长buffer) mempool管理(定长buffer) 物理巨页的管理 dpdk中通过 数组 hugepg_tbl[ ...

  8. DPDK内存管理二:初始化

    DPDK 内存的初始化主要在rte_eal_init()函数中进行: eal_hugepage_info_init() /* 获取系统中hugepage种类以及数量信息到internal_config ...

  9. 收藏:DPDK内存基本概念

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 来源:DPDK与SPDK开源社区 作者简介:Anatoly Burakov ...

  10. DPDK内存篇(三): 标准大页、NUMA、DMA、IOMMU、IOVA、内存池

    作者简介:Anatoly Burakov,英特尔软件工程师,目前在维护DPDK中的VFIO和内存子系统. 目录 引言 标准大页 将内存固定到NUMA节点 硬件.物理地址和直接内存存取(DMA) IOM ...

最新文章

  1. 二叉树的前序,中序,后序的递归、迭代实现
  2. tensorflow 进阶 五 ---TensorFlow conv2d原理及实践
  3. 开源 java CMS - FreeCMS2.4 模型管理
  4. QT学习笔记(十四):QLayout的属性介绍
  5. 操作excel方便么_【Excel好推荐】专业仪表板
  6. 研究理解lanproxy实现内网穿透
  7. 万达酒店及度假村旗下“万达颐华”品牌第一家直营酒店正式开业
  8. 专业的PRD撰写模板
  9. eset杀毒软件隔离区在哪里
  10. eps、emf等图片格式转换
  11. 怎样在oblog中添加音乐播放器
  12. LMIC一直busy解决方法
  13. 修改蒙特卡洛树搜索让人工智能像人类一样玩视频游戏
  14. 未来的科技之光生物计算机,寻觅科技之光,点亮美好未来
  15. 如何清除redis缓存
  16. 将 腾讯 QLV文件 转成MP4
  17. 总结Criteria的简要使用概述(Hibernate5.2+)
  18. 三国志手游挂机脚本 三国志辅助玩法介绍
  19. python学习之旅_第2天
  20. PIXI学习历程 -- 持续更新

热门文章

  1. 微信小程序之----加载中提示框loading
  2. sql server连接字符串
  3. 最近学习 variant configuration
  4. 在复杂度o(n)的要求下找到n个数的中位数(n为奇数)_啊这,一道找中位数的算法题把东哥整不会了…...
  5. 自定义RPC通讯框架,实现dubbo远程RPC服务治理功能
  6. CA证书服务器(6) 利用CA证书配置安全Web站点
  7. Swift3.0:Get/Post同步和异步请求
  8. 【Android】3.21 示例21—兴趣点收藏功能
  9. idea在编辑界面上显示多个文件
  10. 关于深度学习caffe for Windows编译入门