DPDK 函数 rte_pktmbuf_alloc 和 rte_pktmbuf_free 线程安全吗?

如何解决DPDK 函数 rte_pktmbuf_alloc 和 rte_pktmbuf_free 线程安全吗?

我们有一个用例,有一个 RX 线程和两个 TX 线程在同一端口上运行。 RX 线程在处理接收到的数据包后使用 rte_pktmbuf_free 释放 mbuf。 TX 线程使用 rte_pktmbuf_alloc 调用分配 mbuf,并在端口上传输。

当使用相同的池进行 RX 描述符 init 和 TX 线程中的 mbuf 分配时,我们看到有时会出现意外的 mbuf 泄漏和分配失败。如果我们为 RX 和每个 TX 线程使用单独的池,那么我们不会看到这些问题

我们没有在 mempool_create 调用中使用任何标志。 DPDK 文档似乎表明内存池操作是线程安全的?

我们使用的是 DPDK 版本:19.11

我们是否应该为每个 RX 和两个 TX 线程创建唯一的内存池?

EDIT1:按照 Vipin 的要求添加代码片段

DPDK 主进程

mbuf_pool = rte_pktmbuf_pool_create("fast_pkt",8192,256,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());

/* Configure the Ethernet device. */
retval = rte_eth_dev_configure(port,rx_rings,tx_rings,&port_conf);

/* Allocate and set up 1 RX queue per Ethernet port. */
retval = rte_eth_rx_queue_setup(port,q,128,rte_eth_dev_socket_id(port),NULL,mbuf_pool);

/* Allocate and set up 2 TX queue  */
for (q = 0; q < tx_rings; q++) {
    retval = rte_eth_tx_queue_setup(port,512,NULL);
}

/* Start the Ethernet port. */
retval = rte_eth_dev_start(port);

次要进程

主线程

mbuf_pool = rte_mempool_lookup("fast_pkt");

/* Create rx thread attach it to vCPU #4 */
rte_eal_remote_launch( main_rx,4 );


/* create two tx threads and assign affinity to different vCPUs*/
pthread_create(&thread_id,tx_1,NULL );
CPU_ZERO(&cpuset);
CPU_SET(5,&cpuset);
pthread_setaffinity_np(thread_id,sizeof(cpuset),&cpuset);

pthread_create(&thread_id,tx_2,NULL );
CPU_ZERO(&cpuset);
CPU_SET(6,&cpuset);

接收线程(main_rx)

for (;; )
{
    nb_rx = rte_eth_rx_burst(port,pkts_burst,32);

    for ( i = 0; i < nb_rx ; i++ )
    {
        process_packet( pkts_burst[ i] );
        rte_pktmbuf_free(pkts_burst[ i]);
    }
}

传输线程(tx_1、tx_2)

   tx_q = <thread_sepcific queue ID>
   for ( ;; )
   {
         /* Receive Internal message for TX*/
         get_packet ( work_buffer [Burst]);
 
         for ( iterate through each index in work_buffer )
         {  
             tx_mbuf[i] = rte_pktmbuf_alloc(mbuf_pool);
             
             /* combination of following calls to construct packet */
             rte_pktmbuf_mtod( .. );
             /* follow above call with copy from work buffer */

            rte_pktmbuf_prepend( .. );
            rte_pktmbuf_append( .. );
         }

         rte_eth_tx_burst(start_port_id,tx_q,tx_mbuf,num_burst) 

         /* loop through packets not processed by rte_eth_tx_burst */
         for(.. )
         {
             rte_pktmbuf_free (... );
         }
    }

解决方法

[下面共享的 EDIT-1 答案是共享的聚合问题并提供了说明]

  1. question-1 is mempool operations are thread-safe? - (answer) 是的,它是关于 Lcore DPDK 线程的。
  2. question-2 Are we supposed to create unique mempool for each of the RX and the two TX threads? - (answer) 不,可以安全地跨不同端口和端口队列对使用相同的内存池。
  3. question-3 there is mbuf leak and depletion of mbuf_pool (sample code flow shared in question) - (answer) 更正代码后,已运行 12 多个小时无泄漏。
  4. 问题 4 we wanted to understand if the rte_pktmbuf_alloc and rte_pktmbuf_free are intended to be thread-safe or not -(答案)是
  5. 问题 5 Our RX thread uses "rte_eal_remote_launch" whereas our TX threads are created directly using pthread_create from the application. Do you think that makes a difference to thread safety? Should our TX threads also be launched using "rte_eal_remote_launch"? -(答案)是
  6. question-6 we should not have multiple threads (I.e.,pthreads) allocated to same lcore and accessing same memory pool. - (answer) 是的,这是正确的理解

原因:DPDK lcore 线程在内部完成的事情比 thread create and set affinity 多。请参考DPDK EAL Documentation for clarity。基于为 rte_eal_init

选择的选项
  1. coremask(十六进制)是 DPDK lcore 线程的 1:1 CPU 逻辑内核。
  2. lcores(十进制)是 DPDK lcore 线程的 1:1 CPU 逻辑内核。
  3. lcoresmask(十进制)为 1:N,其中 1 个 CPU 逻辑核心可以拆分为 N 个 DPDK lcore 线程。
  4. 每个DPDK lcore线程在内部存储线程局部变量index,即rte_lcore_id
  5. 因此,当使用 rte_pktmbuf_alloc 时,它使用 id 来获取缓存内存池对象。在多个线程上使用相同的 id 违反了无锁模型,如果多个请求同时出现,可能会导致危险。

因此,在主从模式下使用正确的 API 调用使用 DPDK 示例 skeleton 重写代码片段不会产生内存泄漏。统计数据显示下面共享的运行

  ######################## NIC statistics for port 0  ########################
  RX-packets: 15048531    RX-errors:  0           RX-bytes:  1123238216
  RX-nombuf:  0
  TX-packets: 15048504    TX-errors:  0           TX-bytes:  902910240


  ############################################################################

  ######################## NIC statistics for port 0  ########################
  RX-packets: 23424430063  RX-errors:  0           RX-bytes:  1405686130136
  RX-nombuf:  0
  TX-packets: 23424430036  TX-errors:  0           TX-bytes:  1405465802032


  ############################################################################

RX-nombuf 轻松显示 PMD 是否因缺少 mbuf 而无法获取数据包

内存池信息

========== show - MEMPOOL ==========
mempool <MBUF_POOL>@0x11ff9fad00
  flags=10
  socket_id=1
  pool=0x11ff9eab00
  iova=0xeff9fad00
  nb_mem_chunks=1
  size=8191
  populated_size=8191
  header_size=64
  elt_size=2304
  trailer_size=0
  total_obj_size=2368
  private_data_size=64
  ops_index=7
  ops_name: <ring_mp_mc>
  avg bytes/object=2368.289098
  internal cache infos:
    cache_size=250
    cache_count[32]=171
    cache_count[34]=90
    total_cache_count=261
  common_pool_count=2874

注意:以上统计数据是通过 dpdk-proc-info 实用程序获取的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-