天天看点

DPDK QOS4 -- PORT数据结构的初始化

DPDK的Port初始化的时候已经把整个树建立起来了,并没有靠配置来动态增加和删除,而且从初始化的整个过程来看,为了后续入队和出队流程的流水线的处理以及cache的处理来加快性能,整个树是被压扁了的。

我们先来看看,官网上对于整个数据的组织图示:

A schematic of the internal data structures in shown in with details in.

DPDK QOS4 -- PORT数据结构的初始化

Internal Data Structures per Port

# Data structure Size (bytes) # per port Access type Description
Enq Deq
1 Subport table entry 64 # subports per port Rd, Wr Persistent subport data (credits, etc).
2 Pipe table entry 64 # pipes per port Rd, Wr

Persistent data for pipe, its TCs and its queues (credits, etc) that is updated during run-time.

The pipe configuration parameters do not change during run-time. The same pipe configuration parameters are shared by multiple pipes, therefore they are not part of pipe table entry.

3 Queue table entry 4 #queues per port Rd, Wr Rd, Wr

Persistent queue data (read and write pointers). The queue size is the same per TC for all queues, allowing the queue base address to be computed using a fast formula, so these two parameters are not part of queue table entry.

The queue table entries for any given pipe are stored in the same cache line.

4 Queue storage area Config (default: 64 x8) # queues per port Wr Rd Array of elements per queue; each element is 8 byte in size (mbuf pointer).
5 Active queues bitmap 1 bit per queue 1 Wr (Set) Rd, Wr (Clear)

The bitmap maintains one status bit per queue: queue not active (queue is empty) or queue active (queue is not empty).

Queue bit is set by the scheduler enqueue and cleared by the scheduler dequeue when queue becomes empty.

Bitmap scan operation returns the next non-empty pipe and its status (16-bit mask of active queue in the pipe).

6 Grinder ~128 Config (default: 8) Rd, Wr

Short list of active pipes currently under processing. The grinder contains temporary data during pipe processing.

Once the current pipe exhausts packets or credits, it is replaced with another active pipe from the bitmap.

大概说明了下数据的组织和入队、出队对数据结构访问的方式,下面我们具体说明。

  1. Port的初始化

  • 根据Port的初始化参数结构体或者配置文件,计算Port的需要的所有的内存

       mem_size = sizeof(struct rte_sched_port) + x * sizeof(subport) + y * sizeof(pipe)

           + z * sizeof(queue_array) + a * sizeof(queue) + b * sizeof(profile) + bitmap;

     所以subport越多,pipe越多,内存的需求增加的是很大的,这个需要根据实际的环境和需求配置。

  • 初始化各种参数,特别需要注意的令牌桶相关的初始化,初始化的思想可以参见3.1的实现。
  • Queue base calculation 根据每个队列的大小,计算队列queue_add[]的大小。
  • 根据subport --> pipe --> TC[0 .. 3] --> queue[0[0 ..63] ..3]的层次关系,给Port里面的

        Subport、pipe、queue、pipe_profiles、bmp_array、queue_array赋值。

  • 初始化profiles,主要是port令牌桶相关的一些初始化,并以Port的基准计算pipe下的TC的令牌桶参数,还根据传入的队列的weight[0 .. 15]的比例,根据最小公倍数计算每个队列的cost,为TC下面的QUEUE的WRR调度做准备。
  • 初始化位图,位图为了使用cache line并优化查找,实现成了2级层次化,使用两个数组(array1和array2)对位图进行分层组织,array1 cache line对齐,array2 64位对齐,当array2位中有1位设置的时候,关联的array1中的位被置位,都在被清除。

2、Subport的初始化

主要是subport令牌桶和下面的4个TC的初始化,没什么说的。

3、Pipe的初始化

主要是Pipe的令牌桶和下面4个TC的初始化,没什么说的

初始化后整块内存的组织形式如下,以1个subport,2个Pipe为例,队列的大小为4:

DPDK QOS4 -- PORT数据结构的初始化