前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vlib ----buffer pool 内存初始化(2)

vlib ----buffer pool 内存初始化(2)

作者头像
dpdk-vpp源码解读
发布2023-03-07 17:12:28
9840
发布2023-03-07 17:12:28
举报
文章被收录于专栏:DPDK VPP源码分析DPDK VPP源码分析

接着上一节,我们来梳理一下mempool create 流程。

代码语言:javascript
复制
dpdk_config()  /* 配置文件解析dpdk相关参数*/
     |————— rte_eal_init() /*dpdk 初始化EAL环境*/ 
     |——————dpdk_buffer_pools_create() /*buffer pool 创建*/

vpp mempool ops操作设置

vpp注册字节mempool 操作函数,后续创建mempool时,会通过name=“vpp”,索引到mempool ops的索引,设置操作入队与出队的操作接口。所以这里并不会使用dpdk的ring队列(应该是从vpp-19.04版本伴随着dpdk增加了ops操作接口后,修改成这样的。)

代码语言:javascript
复制
/*
*dpdk_buffer_pools_create (vlib_main_t * vm) 函数的开始有创建vpp自己的ops操作
*这里存在cache和no_cache两种。
 */ 
 struct rte_mempool_ops ops = { };
  strncpy (ops.name, "vpp", 4);
  ops.alloc = dpdk_ops_vpp_alloc;
  ops.free = dpdk_ops_vpp_free;
  ops.get_count = dpdk_ops_vpp_get_count;
  ops.enqueue = CLIB_MARCH_FN_POINTER (dpdk_ops_vpp_enqueue);
  ops.dequeue = CLIB_MARCH_FN_POINTER (dpdk_ops_vpp_dequeue);
  rte_mempool_register_ops (&ops);
  strncpy (ops.name, "vpp-no-cache", 13);
  ops.get_count = dpdk_ops_vpp_get_count_no_cache;
  ops.enqueue = CLIB_MARCH_FN_POINTER (dpdk_ops_vpp_enqueue_no_cache);
  ops.dequeue = dpdk_ops_vpp_dequeue_no_cache;
  rte_mempool_register_ops (&ops);

dpdk_buffer_pool_init函数处理逻辑

这里有一点需要注意就是rte_mempool创建的时候有传入cache的大小(默认512大小)。而vpp注册的memepool ops函数中,也有相应大小的cache(最大支持4* 256)。这里应该有两级缓存。都是基于线程的。

代码语言:javascript
复制
i40e_recv_pkts() /*i40e PMD网卡收包函数*/
   |——rte_mbuf_raw_alloc(rxq->mp) /*从mempool池上获取rte_mbuf*/
        |-rte_mempool_get(mp, (void **)&m)
             /*首先通过线程ID从mempool的中获取的对应的线程缓存*/
             |-rte_mempool_default_cache(mp, rte_lcore_id())
             /* 先从cache中获取rte_mbuf,cache如果不够够,再通过ops获取*/
             |-rte_mempool_generic_get(mp, obj_table, n, cache)
                   /*cache中不够时,通过ops接口调用出队函数*/
                  |-ops = rte_mempool_get_ops(mp->ops_index);
                   ops->dequeue(mp, obj_table, n);
                   
/*接下来就是vpp的代码中的出队函数*/
CLIB_MULTIARCH_FN (dpdk_ops_vpp_dequeue) (struct rte_mempool * mp,
            void **obj_table, unsigned n)
    /* 这里有个特殊处理,每次取32个。具体意义是什么?*/
        |-n_alloc = vlib_buffer_alloc_from_pool (vm, bufs, batch_size,
               buffer_pool_index);
           |--/*通过buffer pool index找到对应buffer pool。*/
               bp = vec_elt_at_index (bm->buffer_pools, buffer_pool_index);
               /* 通过线程索引找到对应的缓存*/
               bpt = vec_elt_at_index (bp->threads, vm->thread_index);
               /* 获取缓存的中buffer的数量。*/
               len = vec_len (bpt->cached_buffers);
           |- /* 缓存不够时,再从全局大池中获取,有自旋锁。*/ 
              vlib_buffer_pool_get (vlib_main_t * vm, u8 buffer_pool_index, u32 * buffers,
          u32 n_buffers)
          

下面是dpdk_buffer_pool_init的函数处理逻辑;

1、只是调用rte_mempool_create_empty创建mempool结构体所需要的内存,分为三部分:mempool 头、基于core的buffer索引缓存区、pool私有数据。

2、填充mempool结构填充mempool对象缓冲头elt_list;

将当前numa节点所有的mempool entry条目通过objhdr头串联起来;

下图是每个mempool entry的内存分布:

初始化rte_mbuf头。

代码语言:javascript
复制
  for (i = 0; i < bp->n_buffers; i++)
    {
      struct rte_mempool_objhdr *hdr;
      vlib_buffer_t *b = vlib_get_buffer (vm, bp->buffers[i]);
      struct rte_mbuf *mb = rte_mbuf_from_vlib_buffer (b);
      hdr = (struct rte_mempool_objhdr *) RTE_PTR_SUB (mb, sizeof (*hdr));
      hdr->mp = mp;
      hdr->iova = (iova_mode == RTE_IOVA_VA) ?
  pointer_to_uword (mb) : vlib_physmem_get_pa (vm, mb);
      STAILQ_INSERT_TAIL (&mp->elt_list, hdr, next);
      STAILQ_INSERT_TAIL (&nmp->elt_list, hdr, next);
      mp->populated_size++;
      nmp->populated_size++;
    }

  /* call the object initializers */
  rte_mempool_obj_iter (mp, rte_pktmbuf_init, 0);

3、遍历所有buffer区,初始化vlib_buffer_t结构。

代码语言:javascript
复制
for (i = 0; i < bp->n_buffers; i++)
    {
      vlib_buffer_t *b;
      b = vlib_buffer_ptr_from_index (buffer_mem_start, bp->buffers[i], 0);
      vlib_buffer_copy_template (b, &bp->buffer_template);
    }

4、物理网卡存在时,映射DMA页面,------不懂机制?并将每页的映射情况,挂接到mempool 链表上。

STAILQ_INSERT_TAIL (&mp->mem_list, memhdr, next);

总结:

粗略介绍了buffer pool的初始化流程、mempool 内存分布情况及收包的一些处理逻辑。对vpp buffer内存管理及缓存使用,有了大致的了解。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DPDK VPP源码分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • vpp mempool ops操作设置
  • dpdk_buffer_pool_init函数处理逻辑
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档