DPDK-PACKET DISTRIBUTOR LIBRARY 包分发库

来源:互联网 发布:windows系统制作mac 编辑:程序博客网 时间:2024/06/05 16:36

0x01 缘由

     在产品开发过程中,通过无锁队列去实现生产者和消费者模型。类似DPDK下面这种模式类似,单生产者多消费者模式。

0x02 简介

     DPDK包分发库使用来做流量动态负载均衡,而一次仅支持单个数据包。但使用这个库时,逻辑核的绑定要考虑两种用途:(1)一个分发逻辑核,负责负载均衡和派发包。(2)许多工作逻辑核负责接收分发器分发的数据包然后进行处理。这个模式如下图:
     
     这个库有两种API操作模式,一种用32bits的flow_id每次发送给Worker,另一种优化的模式,用15字节一次发送8个包给Worker。模式的选择通过api 类型字段决定rte_distributor_create()。

     1.分发逻辑核的操作

     这个分发器逻辑核做大量的处理工作来保证数据包被公平的在Workers 间分享。分发器的操作如下:
     a.通过rte_distributor_process() API创建分发器逻辑核线程将数据包传送给分发器组件。
     b每个worker线程与分发器线程共享一个单独的cache行,用来worker和disributor之间传送消息和数据包。处理API将轮询所有worker cache行来判断哪个worker在请求数据包。
     c.当worker请求数据包时,distributor从接收队列中取出数据包传输给worker。如此,将检查tag--mbuf结构中在RSS hash域中存储--每个worker 记录正在处理的每个包的tag是什么。
     d.如果worker处理的下一个包已经打上被一个被正在处理的tag,那么这个包将被这个worker放入队列等待,如果其他包来了将优先处理。这确保没有两个包有同样的tag被并行处理,而且所有相同tag的数据包将在队列中排序等待。
     e.一旦所有的输入数据包传递给处理API,要么被分发到workers,要么被worker去排队,处理API都会给一个tag,然后处理API返回给调用者。
     distributor 需要用到的API:
     rte_distributor_returned_pkts()     rte_distributor_flush()     rte_distributor_clear_returns()


     

     2.work 操作

     worker线程是对数据包进行实际操作的线程。每个worker当完成前一个处理过程后,调用rte_distributor_get_pkt()来请求一个新的数据包。处理的前一个包应该通过API的最后一个参数传送给分发处理组件。
     依据数据流量负载大小来动态的调整work线程数,例如:省电,尽可能的停止worker处理数据包,通过调用rte_distributor_return_pkt()来表示已经完成当前数据包的处理,不想处理其他数据包。

0x03 使用

     进入:dpdk-16.04/examples/distributor目录
     make编译,运行,指定参数。
     相关源码:
//上面都是一些基本初始化,下面是线程创建RTE_LCORE_FOREACH_SLAVE(lcore_id) {if (worker_id == rte_lcore_count() - 2)rte_eal_remote_launch((lcore_function_t *)lcore_tx /*收包*/,output_ring, lcore_id);else {struct lcore_params *p =rte_malloc(NULL, sizeof(*p), 0);if (!p)rte_panic("malloc failure\n");*p = (struct lcore_params){worker_id, d, output_ring, mbuf_pool};rte_eal_remote_launch((lcore_function_t *)lcore_worker /*处理WORK*/,p, lcore_id);}worker_id++;}/* call lcore_main on master core only */struct lcore_params p = { 0, d, output_ring, mbuf_pool};lcore_rx(&p);
distributor:
static intlcore_rx(struct lcore_params *p){.......rte_distributor_process(d, NULL, 0);/* flush distributor to bring to known state */rte_distributor_flush(d);/* set worker & tx threads quit flag */        ......return 0;}

原创粉丝点击