DPDK-----内存管理之mempool

无论对于DPDK做怎样的增量开发,了解DPDK的内存管理模式有利于在满足自己产品功能同时最大化的提高性能;

一:Mempool的基本单元概念(https://doc.dpdk.org/guides/prog_guide/mempool_lib.html

Mempool是固定大小的对象分配器。 在DPDK中,它由名称唯一标识,并且使用mempool操作来存储空闲对象。Mempool的组织是通过三个部分实现的:

  • mempool对象节点:mempool的对象挂接在 static struct rte_tailq_elem rte_mempool_tailq 全局队列中,可以通过名字进行唯一标识符;此队列只是mempool的一个对象指示结构,并不是实际的内存区;
  • mempool实际内存区: struct rte_memzone 是实际分配的连续内存空间,存储所创建的mempool对象;
  • ring无锁队列:作为一个无锁环形队列 struct rte_ring ,存储着mempool对象的指针,提供了方便存取使用mempool的空间的办法。

二:一般结构

如图所示,mempool的对象通过与ring无锁队列建立关联方便存取;同时,为了减少多核访问造成的冲突,引入了local_cache对象缓冲区。该local_cache非硬件上的cache,而是为了减少多核访问ring造成的临界区访问,

coreX app会优先访问该local_cache上的对象。入队的时候优先入local_cache中,出队的时候优先从local_cache中出队。

三:mempool的创建和使用

先注意一下 rte_mempool_create 的参数中的两个 mp_init  和 obj_init ,前者负责初始化mempool中配置的私有参数,如在数据包中加入的我们自己的私有结构;后者负责初始化每个mempool对象。我们然后按照mempool的3个关键部分展开说明。

(1)mempool头结构的创建

   mempool头结构包含3个部分: struct rte_mempool , struct rte_mempool_cache 和mempool private。创建是在 rte_mempool_create_empty() 中完成的,看这个函数,先进行了对齐的检查

    RTE_BUILD_BUG_ON((sizeof(struct rte_mempool) &
              RTE_CACHE_LINE_MASK) != 0);
    RTE_BUILD_BUG_ON((sizeof(struct rte_mempool_cache) &
              RTE_CACHE_LINE_MASK) != 0);

然后从mempool队列中取出头节点,我们创建的mempool结构填充好,就挂接在这个节点上。接下来做一些检查工作和创建flag的设置。

 rte_mempool_calc_obj_size() 计算了每个obj的大小,这个obj又是由三个部分组成的,header_size、elt_size、trailer_size,即头,数据区,尾。在没有开启RTE_LIBRTE_MEMPOOL_DEBUG调试时,没有尾部分;头部分的结构为: struct rte_mempool_objhdr ,

通过这个头部,mempool中的obj都是链接到队列中的,所以,提供了遍历obj的方式(尽管很少这么用)。函数返回最后计算对齐后的obj的大小,为后面分配空间提供依据。

然后分配了一个mempool队列条目,为后面挂接在队列做准备。

    /* try to allocate tailq entry */
    te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
    if (te == NULL) {
        RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
        goto exit_unlock;
    }

接下来,就是计算整个mempool头结构多大。

    mempool_size = MEMPOOL_HEADER_SIZE(mp, cache_size);
    mempool_size += private_data_size;
    mempool_size = RTE_ALIGN_CEIL(mempool_size, RTE_MEMPOOL_ALIGN);

这里指的是计算mempool的头结构的大小。而不是内存池实际的大小。在这里可以清晰的看出这个mempool头结构是由三部分组成的。cache计算的是所有核上的cache之和。

然后,使用 rte_memzone_reserve() 分配这个mempool头结构大小的空间,填充mempool结构体,并把mempool头结构中的cache地址分配给mempool。初始化这部分cache。

最后就是挂接mempool结构。  TAILQ_INSERT_TAIL(mempool_list, te, next); (这里上了锁?)。

(2)mempool实际空间的创建

这部分的创建是在函数 rte_mempool_populate_default(struct rte_mempool *mp) 中完成的。

首先计算为这些元素需要分配多大的空间, rte_mempool_ops_calc_mem_size() 

接着 rte_memzone_reserve_aligned() 分配空间。把元素添加到mempool,实际上就是把申请的空间分给每个元素。

(3)ring的创建

先看到的是这么一段代码:

static int
mempool_ops_alloc_once(struct rte_mempool *mp)
{
    int ret;

    /* create the internal ring if not already done */
    if ((mp->flags & MEMPOOL_F_POOL_CREATED) == 0) {
        ret = rte_mempool_ops_alloc(mp);
        if (ret != 0)
            return ret;
        mp->flags |= MEMPOOL_F_POOL_CREATED;
    }
    return 0;
}

这就是创建ring的过程咯,其中的函数rte_mempool_ops_alloc()就是实现。那么,对应的ops->alloc()在哪注册的呢?

    /*
     * Since we have 4 combinations of the SP/SC/MP/MC examine the flags to
     * set the correct index into the table of ops structs.
     */
    if ((flags & MEMPOOL_F_SP_PUT) && (flags & MEMPOOL_F_SC_GET))
        ret = rte_mempool_set_ops_byname(mp, "ring_sp_sc", NULL);
    else if (flags & MEMPOOL_F_SP_PUT)
        ret = rte_mempool_set_ops_byname(mp, "ring_sp_mc", NULL);
    else if (flags & MEMPOOL_F_SC_GET)
        ret = rte_mempool_set_ops_byname(mp, "ring_mp_sc", NULL);
    else
        ret = rte_mempool_set_ops_byname(mp, "ring_mp_mc", NULL);

就是根据ring的类型,来注册对应的操作函数,如默认的就是ring_mp_mc,多生产者多消费者模型,其操作函数不难找到:

static const struct rte_mempool_ops ops_mp_mc = {
    .name = "ring_mp_mc",
    .alloc = common_ring_alloc,
    .free = common_ring_free,
    .enqueue = common_ring_mp_enqueue,
    .dequeue = common_ring_mc_dequeue,
    .get_count = common_ring_get_count,
};

接下来,又分配了一个 struct rte_mempool_memhdr *memhdr; 结构的变量,就是这个变量管理着mempool的实际内存区,它记录着mempool实际地址区的物理地址,虚拟地址,长度等信息。

再然后,就是把每个元素对应到mempool池中了: mempool_add_elem() 。在其中,把每个元素都挂在了elt_list中,可以遍历每个元素。最后 rte_mempool_ops_enqueue_bulk(struct rte_mempool *mp, void * const *obj_table, ,最终,把元素对应的地址入队,这样,mempool中的每个元素都放入了ring中。

四:mempool的使用及实践

mempool的常见使用是获取元素空间和释放空间。

待补充

部分内容转载自:https://www.cnblogs.com/yhp-smarthome/p/6687175.html

posted on 2018-11-29 16:17 Rex_Zhang 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/rex-2018-cloud/p/10039065.html

<think>嗯,用户想了解OVS-DPDK的工作原理。我需要先回顾一下之前提供的参考资料,然后整理出一个清晰的解释。首先,OVS-DPDK是Open vSwitch结合DPDK的优化版本,对吧?根据引用[2],DPDK加速的OVS和原始OVS的主要区别在于数据路径的处理。原始OVS需要通过内核模块openvswitch.ko处理数据包,而OVS-DPDK通过DPDK的PMD驱动直接将报文送到用户态的ovs-vswitchd进程,避免了内核态的开销。 接下来,用户态快速路径dpif-netdev取代了原来的内核datapath,这一点在引用[4]中提到过。这意味着数据包处理完全在用户空间进行,利用DPDK的高性能特性。然后,关于流表查询,引用[1]提到使用Classifier进行流表匹配,这应该涉及到高效的哈希算法或查找结构,比如元组空间搜索算法,以快速匹配流表项。 另外,OVS-DPDK的架构可能包括主线程负责管理,而数据面线程负责实际的包处理。这些线程绑定到特定的CPU核心,减少上下文切换,提升性能。还有内存管理方面,DPDK使用大页内存和内存池技术,减少内存分配的开销,确保零拷贝传输,这点可能需要在回答中详细说明。 用户可能还关心OVS-DPDK的优化点,比如流缓存、批处理、多队列等,这些在性能优化中很重要。同时,应用场景如NFV、云计算中的虚拟网络也是需要提到的部分,结合引用[3]中的安装和概述资料。 需要确保回答结构清晰,分点解释,比如架构变化、数据流向、流表处理、性能优化等。同时,生成的相关问题要围绕用户可能进一步想了解的内容,比如性能优化方法、与内核OVS的区别、适用场景等。检查是否有遗漏的关键点,比如零拷贝、CPU亲和性等,确保覆盖所有重要方面。</think>### OVS-DPDK工作原理详解 OVS-DPDK是Open vSwitch(OVS)结合Data Plane Development Kit(DPDK)技术实现的高性能用户态虚拟交换机,其核心目标是通过绕过内核协议栈来提升数据包处理效率。以下是其关键工作原理: --- #### 1. **架构变化** - **用户态数据路径**:OVS-DPDK使用`dpif-netdev`模块替代传统OVS的内核态`datapath`和用户态`dpif-netlink`,使数据包处理完全在用户空间完成,避免了内核态与用户态之间的上下文切换开销[^4]。 - **DPDK PMD驱动**:网络接口通过DPDK的Poll Mode Driver(PMD)直接管理,报文从物理网卡或虚拟网卡(如vhost-user)通过DPDK PMD直接进入用户态,无需内核参与[^2]。 --- #### 2. **数据流向** 1. **收包阶段**: 报文通过物理网卡或虚拟网卡(如vhost-user)进入,由DPDK PMD驱动直接传递给用户态的`ovs-vswitchd`进程。 2. **流表匹配**: 使用`Classifier`模块进行流表查询,通过元组(如五元组)匹配流表项。若命中流表,则按流表动作(如转发、修改字段)处理;若未命中,则上送控制面生成新流表项[^1]。 3. **转发处理**: 处理后的报文通过DPDK PMD发送到目标端口(如另一个虚拟机或物理网卡)。 --- #### 3. **流表处理优化** - **高效匹配算法**:采用哈希表或元组空间搜索算法(TSS)加速流表查询。 - **流缓存机制**:频繁访问的流表项缓存在快速路径中,减少控制面交互。 - **批量处理**:DPDK支持报文批量处理(如一次处理32个包),降低单包处理开销。 --- #### 4. **性能优化技术** - **零拷贝技术**:DPDK通过内存池(`mempool`)和大页内存(HugePages)实现报文内存零拷贝。 - **CPU亲和性**:将PMD线程绑定到专属CPU核心,减少缓存失效和线程切换。 - **多队列优化**:为每个CPU核心分配独立队列,避免资源竞争。 --- #### 5. **应用场景** - **NFV(网络功能虚拟化)**:为虚拟机或容器提供高性能虚拟网络。 - **云计算网络**:在OpenStack等平台中实现低延迟的虚拟交换机。 - **边缘计算**:适用于需要高吞吐量的边缘网关场景[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值