能否在 vpp 外部释放 vpp 创建的 vlib buffer?

需求

基于 vpp 引流,vpp 负责将流量外发到其它 dpdk secondary 进程中进行处理,当外部的 dpdk secondary 进程异常退出后,需要回收这部分报文,避免 buffer 泄露。

vpp 中创建 vlibbuffer mempool 的代码

vpp 在初始化时会为每一个 worker 创建一个 vpp mempool + 一个 vpp no cache mempool,vpp 自己实现了名为 vpp mempool_ops 与 vpp-no-cache mempool_ops,分别绑定到这两个 mempool 中。
相关代码如下:

  rte_mempool_set_ops_byname (mp, "vpp", NULL);
  rte_mempool_set_ops_byname (nmp, "vpp-no-cache", NULL);

vpp 实现的 mempool_ops 只在 vpp 内部能够使用,不能在其它非 vpp 程序中使用,因此不能在其它非 vpp 程序中直接释放 vpp 创建的 vlibbuffer(mbuf)。

能否在非 vpp worker 线程中释放 vpp 创建的报文?

非 vpp worker 线程,其每线程数据 __os_thread_index 非法。当在这些线程中释放 vlibbuffer 时,上层接口最终会调用到 mempool_ops 中的 enqueue 方法,在 vpp 中对应 dpdk_ops_vpp_enqueue 接函数,由于 __os_thread_index 非法,则调用 vlib_get_main 将不能获取到一个合法的 vlib_maint_t 结构,vlibbuffer 无法正常释放。

vpp 中相关代码如下:

static_always_inline uword
os_get_thread_index (void)
{
  return __os_thread_index;
}

always_inline vlib_main_t *
vlib_get_main (void)
{
  vlib_main_t *vm;
  vm = vlib_mains[vlib_get_thread_index ()];
  ASSERT (vm);
  return vm;
}

__os_thread_index 是每线程变量,vpp 自己创建的线程会初始化此变量,此变量将作为下标用于获取当前线程的 vlib_main_t 结构,非管理线程不能获取。

如果提前记录每个 vlibbuffer 所在的 worker 的 index 下标,在释放前主动修改 __os_thread_index 每线程变量看似能够解决这个问题。

然而继续阅读 vpp 注册的 dpdk_ops_vpp_enqueue 函数,发现它会调用 vlib_buffer_pool_put 将 buffer 还入vlib_buffer_pool 中。

vlib_buffer_pool_put 函数部分代码如下:

static_always_inline void
vlib_buffer_pool_put (vlib_main_t * vm, u8 buffer_pool_index,
		      u32 * buffers, u32 n_buffers)
{
.....................................................
  if(vm->thread_index != 0)
  {
  	n_cached = bpt->n_cached;
  	n_empty = VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ - n_cached;
  	if (n_buffers <= n_empty)
    {
      vlib_buffer_copy_indices (bpt->cached_buffers + n_cached,
				buffers, n_buffers);
      bpt->n_cached = n_cached + n_buffers;
      return;
    }

  	vlib_buffer_copy_indices (bpt->cached_buffers + n_cached,
			    buffers + n_buffers - n_empty, n_empty);
  	bpt->n_cached = VLIB_BUFFER_POOL_PER_THREAD_CACHE_SZ;
  }

  clib_spinlock_lock (&bp->lock);
  vlib_buffer_copy_indices (bp->buffers + bp->n_avail, buffers,
			    n_buffers - n_empty);
  bp->n_avail += n_buffers - n_empty;
  clib_spinlock_unlock (&bp->lock);
}

此函数首先尝试将报文还入 bpt->cached_buffers 中,然后将其余的报文还入 bp->buffers 中,还入 bp->buffers 的过程使用互斥锁保护,而 bpt->cached_buffers 没有任何锁保护,意味着同时只能有一个线程访问它。当多个线程同时访问时就会出现异常,故而不能在其它线程中释放 vpp 特定 worker 上分配的报文。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值