五、程序员指南:数据平面开发套件(3)

加权循环法 (WRR)
WRR 设计解决方案从简单到复杂的演变如表 12 所示。
表 21.12:加权循环法 (WRR)

# All Queues Active? Equal Weights for All Queues? All Packets Equal? Strategy
1 Yes Yes Yes 字节级循环轮询(Byte level round robin) Next queue: queue #i,i = (i + 1) % n
2 Yes Yes No 分组级循环轮询(Packet level round robin) 每从队列 #i 消耗一个字节需要消耗队列 #i 的一个令牌。T(i) = 之前从队列 #i 消耗的令牌总数。每次从队列 #i 消耗一个数据包时,T(i) 更新为:T(i) += pkt_len。 Next queue:具有最小 T 的队列。
3 Yes No No 分组级加权轮询(Packet level weighted round robin) 通过为每个队列引入不同的每字节成本,将此情况简化为前一情况。具有较低权重的队列每字节的成本较高。这样,仍然有意义地比较不同队列之间的消耗,以选择下一个队列。w(i) = 队列 #i 的权重 t(i) = 队列 #i 的每字节令牌,定义为队列 #i 的倒数权重。例如,如果 w[0…3] = [1:2:4:8],则 t[0…3] = [8:4:2:1];如果 w[0…3] = [1:4:15:20],则 t[0…3] = [60:15:4:3]。每从队列 #i 消耗一个字节需要为队列 #i 消耗 t(i) 个令牌。T(i) = 之前从队列 #i 消耗的令牌总数。每次从队列 #i 消耗一个数据包时,T(i) 更新为:T(i) += pkt_len * t(i)。Next queue:具有最小 T 的队列。
4 No No No 可变队列状态的分组级加权轮询(Packet level weighted round robin with variable queue status) 通过将不活动队列的消耗设置为一个较高的数字,将此情况简化为前一情况,以使不活动队列永远不会被最小 T 逻辑选中。为防止连续累加导致 T 溢出,每次数据包消耗后,对所有队列截断 T(i)。例如,T[0…3] = [1000, 1100, 1200, 1300] 截断为 T[0…3] = [0, 100, 200, 300],通过从 T(i) 中减去最小的 T,i = 0…n。这需要在输入队列集中至少有一个活动队列,由出队状态机永远不会选择不活动流量类别来保证。mask(i) = 队列 #i 的饱和掩码,定义为:mask(i) = (队列 #i 是否活动)? 0 : 0xFFFFFFFF; w(i) = 队列 #i 的权重 t(i) = 队列 #i 的每字节令牌,定义为队列 #i 的倒数权重。T(i) = 之前从队列 #i 消耗的令牌总数。
子端口流量类别超额订阅

问题陈述
对于子端口流量类别X,超额订阅是在配置时发生的事件。这种情况发生在子端口成员管道级别为流量类别X分配的带宽比父子端口级别为相同流量类别分配的带宽更多时。
对于特定子端口和流量类别的超额订阅的存在,纯粹是由于管道和子端口级别的配置而不是由于运行时流量负载的动态演变(就像拥塞一样)。

当流量类别X的整体需求较低时
对于当前子端口的流量类别X的整体需求较低时,超额订阅条件的存在并不代表问题,因为对于所有成员管道,流量类别X的需求得到了完全满足。然而,当所有子端口成员管道的流量类别X的总需求超过了在子端口级别配置的限制时,这就无法再实现了。

解决方案空间
解决这个问题的一些可能方法被总结如下,其中第三种方法被选定用于实现。

表21.13:子端口流量类别超额订阅

No. Approach Description
1 Don’t care 首来先服务。这种方法在子端口成员管道之间不公平,因为首先服务的管道将根据它们需要的 TC X 的带宽使用尽可能多的带宽,而稍后服务的管道由于子端口级别的 TC X 带宽稀缺而接收到较差的服务。
2 Scale down all pipes 子端口内的所有管道的 TC X 的带宽限制按相同比例缩减。这种方法在子端口成员管道之间不公平,因为低端管道(即配置带宽较低的管道)可能会遭受严重的服务降级,可能导致其服务不可用(如果这些管道的可用带宽降至可用服务的最低要求以下),而高端管道的服务降级可能根本不可察觉。
3 Cap the high demand pipes 每个子端口成员管道在子端口级别的 TC X 可用带宽上收到相等份额。任何未被低需求管道使用的带宽会以相等份额重新分配给高需求管道。这样,高需求管道被截断,而低需求管道不受影响。
子端口流量类别超额订阅实现概述

典型情况下
通常情况下,子端口流量类别(TC)超额订阅功能仅对最低优先级流量类别(TC 3)启用,该流量类别通常用于尽力而为的流量,并且管理平面可以防止此条件发生于其他(优先级更高的)流量类别。

前提假设
为了简化实现,还假设子端口 TC 3 的上限设置为子端口速率的 100%,管道 TC 3 的上限对于所有子端口成员管道也设置为各自管道速率的 100%。

实现概述
算法计算一个水位线(watermark),它基于子端口成员管道当前需求而周期性更新,其目的是限制每个管道允许发送给 TC 3 的流量量。水位线在每个流量类别上限执行期间的开始时在子端口级别计算,并且相同的值在整个当前执行期间内被所有子端口成员管道使用。下图说明了水位线如何在每个期间开始时从子端口级别传播到所有子端口成员管道。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在当前执行期间的开始(与前一执行期间结束同时),水位线的值根据前一期间开始时分配给 TC 3 的带宽量进行调整,而该量在前一期间结束时未被子端口成员管道使用。

如果存在未使用的子端口 TC 3 带宽,当前期间水位线的值将增加,以鼓励子端口成员管道消耗更多带宽。否则,水位线的值将减少,以强制要求 TC 3 的带宽消耗在子端口成员管道之间平等。

水位线值的增加或减少以小幅度增量进行,因此可能需要多个执行周期才能达到平衡状态。这种状态可能随时发生变化,原因是子端口成员管道对 TC 3 的需求发生变化,例如需求增加时(需要降低水位线)或需求减少时(需要增加水位线)。

需求低时,水位线设置得较高,以防止其阻碍子端口成员管道消耗更多带宽。水位线的最高值是从子端口成员管道配置的最高速率中选择的。

表21.14:水位线从子端口级别传播到每个流量类别上限执行期间的成员管道开始时

No. Subport Traffic Class Operation Description
1 Initialization 子端口级别:subport_period_id = 0管道级别:pipe_period_id = 0
2 Credit update 子端口级别:如果(时间 >= subport_tc_time){subport_wm = water_mark_update(); subport_tc_time = time + subport_tc_period; subport_period_id++;} 管道级别:如果(pipe_period_id != subport_period_id){pipe_ov_credits = subport_wm * pipe_weight; pipe_period_id = subport_period_id;}
3 Credit consumption (on packet scheduling) 管道级别:pkt_credits = pk_len + frame_overhead; 如果(pipe_ov_credits >= pkt_credits){pipe_ov_credits -= pkt_credits;}

表 21.15:水印计算

No. Subport Traffic Class Operation Description
1 Initialization 子端口级别:wm = WM_MAX
2 Credit update 子端口级别(water_mark_update):tc0_cons = subport_tc0_credits_per_period - subport_tc0_credits; tc1_cons = subport_tc1_credits_per_period - subport_tc1_credits; tc2_cons = subport_tc2_credits_per_period - subport_tc2_credits; tc3_cons = subport_tc3_credits_per_period - subport_tc3_credits; tc3_cons_max = subport_tc3_credits_per_period - (tc0_cons + tc1_cons + tc2_cons); 如果(tc3_consumption > (tc3_consumption_max - MTU)){ wm -= wm >> 7; if(wm < WM_MIN) wm = WM_MIN; } else { wm += (wm >> 7) + 1; if(wm > WM_MAX) wm = WM_MAX; }
21.2.5 性能最差情景

大量活跃队列但信用不足
调度器需要检查大量队列以选择一个包和信用时,其性能会降低。调度器维护活跃队列的位图,跳过非活跃队列,但为了检测特定管道是否有足够的信用,需要使用管道出队状态机深入探查管道,这会消耗周期,而不管调度结果如何(无包生成或至少生成一个包)。这种情况强调了对调度器性能的速度控制的重要性:如果管道没有足够的信用,其数据包应尽快被丢弃(在到达分层调度器之前),从而将管道队列渲染为非活跃状态,允许出队端跳过该管道而无需花费用于调查管道信用的周期,因为这将导致“信用不足”状态。

单个队列达到100%线速率
端口调度器的性能针对大量队列进行了优化。如果队列数较少,则相同活跃流量水平下,端口调度器的性能预计会比小型消息传递队列的性能差。

21.3 丢弃器

DPDK丢弃器的目的
DPDK丢弃器的目的是在分组调度器到达时丢弃分组,以避免拥塞。丢弃器支持随机早期检测(RED)、加权随机早期检测(WRED)和尾部丢弃算法。图21.7说明了丢弃器如何与调度器集成。目前DPDK不支持拥塞管理,因此丢弃器提供了唯一的拥塞避免方法。

在这里插入图片描述
图 21.7:DPDK Dropper 的高级框图

丢弃器使用的拥塞避免算法

丢弃器使用文献中记录的随机早期检测(RED)拥塞避免算法。RED算法的目的是监视数据包队列,确定队列的当前拥塞水平,并决定是否应该将到达的数据包入队或丢弃。RED算法使用指数加权移动平均(EWMA)滤波器来计算平均队列大小,从而指示队列的当前拥塞水平。

对于每个入队操作,RED算法将平均队列大小与最小和最大阈值进行比较。根据平均队列大小是低于、高于还是介于这些阈值之间的情况,RED算法计算到达数据包应该被丢弃的概率,并基于这一概率进行随机决策。

丢弃器还通过允许调度器在运行时为同一个数据包队列选择不同的RED配置来支持加权随机早期检测(WRED)。在严重拥塞情况下,丢弃器会使用尾部丢弃。当数据包队列达到最大容量并且无法存储更多数据包时,就会发生尾部丢弃。在这种情况下,所有到达的数据包都会被丢弃。

丢弃器的数据流程如图21.8所示。首先执行RED/WRED算法,其次执行尾部丢弃。

丢弃器支持的使用案例有:

  • 初始化配置数据
  • 初始化运行时数据
  • 入队(决定是将到达的数据包入队还是丢弃)
  • 标记为空(记录数据包队列变为空的时间)

配置用例在"配置"中解释,入队操作在"入队操作"中解释,标记为空操作在"队列为空操作"中解释。

21.3.1 配置

RED配置包含表21.16中给出的参数。

表21.16:RED配置参数

Parameter Minimum Maximum Typical
Minimum Threshold 0 1022 1/4 x queue size
Maximum Threshold 1 1023 1/2 x queue size
Inverse Mark Probability 1 255 10
EWMA Filter Weight 1 12 9

这些参数的含义在后续章节中将

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值