-The evolution of the WRR design solution from simple to complex is shown in Table 12.
-
-.. _pg_table_12:
-
-**Table 12. Weighted Round Robin (WRR)**
-
-+---+------------+-----------------+-------------+----------------------------------------------------------+
-| # | All Queues | Equal Weights | All Packets | Strategy |
-| | Active? | for All Queues? | Equal? | |
-+===+============+=================+=============+==========================================================+
-| 1 | Yes | Yes | Yes | **Byte level round robin** |
-| | | | | |
-| | | | | *Next queue* queue #i, i = *(i + 1) % n* |
-| | | | | |
-+---+------------+-----------------+-------------+----------------------------------------------------------+
-| 2 | Yes | Yes | No | **Packet level round robin** |
-| | | | | |
-| | | | | Consuming one byte from queue #i requires consuming |
-| | | | | exactly one token for queue #i. |
-| | | | | |
-| | | | | T(i) = Accumulated number of tokens previously consumed |
-| | | | | from queue #i. Every time a packet is consumed from |
-| | | | | queue #i, T(i) is updated as: T(i) += *pkt_len*. |
-| | | | | |
-| | | | | *Next queue* : queue with the smallest T. |
-| | | | | |
-| | | | | |
-+---+------------+-----------------+-------------+----------------------------------------------------------+
-| 3 | Yes | No | No | **Packet level weighted round robin** |
-| | | | | |
-| | | | | This case can be reduced to the previous case by |
-| | | | | introducing a cost per byte that is different for each |
-| | | | | queue. Queues with lower weights have a higher cost per |
-| | | | | byte. This way, it is still meaningful to compare the |
-| | | | | consumption amongst different queues in order to select |
-| | | | | the next queue. |
-| | | | | |
-| | | | | w(i) = Weight of queue #i |
-| | | | | |
-| | | | | t(i) = Tokens per byte for queue #i, defined as the |
-| | | | | inverse weight of queue #i. |
-| | | | | For example, if w[0..3] = [1:2:4:8], |
-| | | | | then t[0..3] = [8:4:2:1]; if w[0..3] = [1:4:15:20], |
-| | | | | then t[0..3] = [60:15:4:3]. |
-| | | | | Consuming one byte from queue #i requires consuming t(i) |
-| | | | | tokens for queue #i. |
-| | | | | |
-| | | | | T(i) = Accumulated number of tokens previously consumed |
-| | | | | from queue #i. Every time a packet is consumed from |
-| | | | | queue #i, T(i) is updated as: *T(i) += pkt_len * t(i)*. |
-| | | | | *Next queue* : queue with the smallest T. |
-| | | | | |
-+---+------------+-----------------+-------------+----------------------------------------------------------+
-| 4 | No | No | No | **Packet level weighted round robin with variable queue |
-| | | | | status** |
-| | | | | |
-| | | | | Reduce this case to the previous case by setting the |
-| | | | | consumption of inactive queues to a high number, so that |
-| | | | | the inactive queues will never be selected by the |
-| | | | | smallest T logic. |
-| | | | | |
-| | | | | To prevent T from overflowing as result of successive |
-| | | | | accumulations, T(i) is truncated after each packet |
-| | | | | consumption for all queues. |
-| | | | | For example, T[0..3] = [1000, 1100, 1200, 1300] |
-| | | | | is truncated to T[0..3] = [0, 100, 200, 300] |
-| | | | | by subtracting the min T from T(i), i = 0..n. |
-| | | | | |
-| | | | | This requires having at least one active queue in the |
-| | | | | set of input queues, which is guaranteed by the dequeue |
-| | | | | state machine never selecting an inactive traffic class. |
-| | | | | |
-| | | | | *mask(i) = Saturation mask for queue #i, defined as:* |
-| | | | | |
-| | | | | mask(i) = (queue #i is active)? 0 : 0xFFFFFFFF; |
-| | | | | |
-| | | | | w(i) = Weight of queue #i |
-| | | | | |
-| | | | | t(i) = Tokens per byte for queue #i, defined as the |
-| | | | | inverse weight of queue #i. |
-| | | | | |
-| | | | | T(i) = Accumulated numbers of tokens previously consumed |
-| | | | | from queue #i. |
-| | | | | |
-| | | | | *Next queue* : queue with smallest T. |
-| | | | | |
-| | | | | Before packet consumption from queue #i: |
-| | | | | |
-| | | | | *T(i) |= mask(i)* |
-| | | | | |
-| | | | | After packet consumption from queue #i: |
-| | | | | |
-| | | | | T(j) -= T(i), j != i |
-| | | | | |
-| | | | | T(i) = pkt_len * t(i) |
-| | | | | |
-| | | | | Note: T(j) uses the T(i) value before T(i) is updated. |
-| | | | | |
-+---+------------+-----------------+-------------+----------------------------------------------------------+
+The evolution of the WRR design solution for the lowest priority traffic class (best effort TC) from simple to complex is shown in :numref:`table_qos_12`.
+
+.. _table_qos_12:
+
+.. table:: Weighted Round Robin (WRR)
+
+ +---+------------+-----------------+-------------+----------------------------------------------------------+
+ | # | All Queues | Equal Weights | All Packets | Strategy |
+ | | Active? | for All Queues? | Equal? | |
+ +===+============+=================+=============+==========================================================+
+ | 1 | Yes | Yes | Yes | **Byte level round robin** |
+ | | | | | |
+ | | | | | *Next queue* queue #i, i = *(i + 1) % n* |
+ | | | | | |
+ +---+------------+-----------------+-------------+----------------------------------------------------------+
+ | 2 | Yes | Yes | No | **Packet level round robin** |
+ | | | | | |
+ | | | | | Consuming one byte from queue #i requires consuming |
+ | | | | | exactly one token for queue #i. |
+ | | | | | |
+ | | | | | T(i) = Accumulated number of tokens previously consumed |
+ | | | | | from queue #i. Every time a packet is consumed from |
+ | | | | | queue #i, T(i) is updated as: T(i) += *pkt_len*. |
+ | | | | | |
+ | | | | | *Next queue* : queue with the smallest T. |
+ | | | | | |
+ | | | | | |
+ +---+------------+-----------------+-------------+----------------------------------------------------------+
+ | 3 | Yes | No | No | **Packet level weighted round robin** |
+ | | | | | |
+ | | | | | This case can be reduced to the previous case by |
+ | | | | | introducing a cost per byte that is different for each |
+ | | | | | queue. Queues with lower weights have a higher cost per |
+ | | | | | byte. This way, it is still meaningful to compare the |
+ | | | | | consumption amongst different queues in order to select |
+ | | | | | the next queue. |
+ | | | | | |
+ | | | | | w(i) = Weight of queue #i |
+ | | | | | |
+ | | | | | t(i) = Tokens per byte for queue #i, defined as the |
+ | | | | | inverse weight of queue #i. |
+ | | | | | For example, if w[0..3] = [1:2:4:8], |
+ | | | | | then t[0..3] = [8:4:2:1]; if w[0..3] = [1:4:15:20], |
+ | | | | | then t[0..3] = [60:15:4:3]. |
+ | | | | | Consuming one byte from queue #i requires consuming t(i) |
+ | | | | | tokens for queue #i. |
+ | | | | | |
+ | | | | | T(i) = Accumulated number of tokens previously consumed |
+ | | | | | from queue #i. Every time a packet is consumed from |
+ | | | | | queue #i, T(i) is updated as: *T(i) += pkt_len * t(i)*. |
+ | | | | | *Next queue* : queue with the smallest T. |
+ | | | | | |
+ +---+------------+-----------------+-------------+----------------------------------------------------------+
+ | 4 | No | No | No | **Packet level weighted round robin with variable queue |
+ | | | | | status** |
+ | | | | | |
+ | | | | | Reduce this case to the previous case by setting the |
+ | | | | | consumption of inactive queues to a high number, so that |
+ | | | | | the inactive queues will never be selected by the |
+ | | | | | smallest T logic. |
+ | | | | | |
+ | | | | | To prevent T from overflowing as result of successive |
+ | | | | | accumulations, T(i) is truncated after each packet |
+ | | | | | consumption for all queues. |
+ | | | | | For example, T[0..3] = [1000, 1100, 1200, 1300] |
+ | | | | | is truncated to T[0..3] = [0, 100, 200, 300] |
+ | | | | | by subtracting the min T from T(i), i = 0..n. |
+ | | | | | |
+ | | | | | This requires having at least one active queue in the |
+ | | | | | set of input queues, which is guaranteed by the dequeue |
+ | | | | | state machine never selecting an inactive traffic class. |
+ | | | | | |
+ | | | | | *mask(i) = Saturation mask for queue #i, defined as:* |
+ | | | | | |
+ | | | | | mask(i) = (queue #i is active)? 0 : 0xFFFFFFFF; |
+ | | | | | |
+ | | | | | w(i) = Weight of queue #i |
+ | | | | | |
+ | | | | | t(i) = Tokens per byte for queue #i, defined as the |
+ | | | | | inverse weight of queue #i. |
+ | | | | | |
+ | | | | | T(i) = Accumulated numbers of tokens previously consumed |
+ | | | | | from queue #i. |
+ | | | | | |
+ | | | | | *Next queue* : queue with smallest T. |
+ | | | | | |
+ | | | | | Before packet consumption from queue #i: |
+ | | | | | |
+ | | | | | *T(i) |= mask(i)* |
+ | | | | | |
+ | | | | | After packet consumption from queue #i: |
+ | | | | | |
+ | | | | | T(j) -= T(i), j != i |
+ | | | | | |
+ | | | | | T(i) = pkt_len * t(i) |
+ | | | | | |
+ | | | | | Note: T(j) uses the T(i) value before T(i) is updated. |
+ | | | | | |
+ +---+------------+-----------------+-------------+----------------------------------------------------------+