锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Linux公平队列FQ配置

时间:2023-08-02 07:07:01 连接器fq18

FQ (Fair Queue)是类别(classless)报文调度器主要用于本地流量。设计控制每个流的发送节奏(pacing)。FQ完成流的区分,可以完成TCP层层所需的发送节奏。所有属于套接口的报纸都被认为是流动的(flow)。可用于非本地生成的报纸(如路由器设备)sk_buff结构成员hash作为区分流的备选。

可以使用应用程序setsockopt调用系统的选项SO_MAX_PACING_RATE指定最大的pacing速率。FQ调度器可以在发送报纸之间增加延迟TCP栈所需的发送速率。

轮询列出队列Round-Robin这样做。留了一种特殊的方式。FIFO队列用于高优先级高优先级:TC_PRIO_CONTROL,用于IGMP,IPv6多播,STP等协议报文),这个队列的报文总是优先发送。

TCP pacing有空闲时间流动是有益的,因为拥堵的窗口是允许的TCP栈在队列中缓存大量报纸,进入空闲时,由pacing发送避免了TCP业余时间后重新进入慢启动的问题。BDP大流量和发送大量数据的应用(如视频流)有不利影响。

1. FQ配置

配置如下:

$ sudo tc qdisc add dev ens38 root fq $  $ sudo tc -s qdisc show dev ens38  qdisc fq 8001: root refcnt 2 limit 10000p flow_limit 100p buckets 1024 orphan_mask 1023 quantum 3028 initial_quantum 15140 low_rate_threshold 550Kbit refill_delay 40.0ms   Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)   backlog 0b 0p requeues 0    0 flows (0 inactive, 0 throttled)   0 gc, 0 highprio, 0 throttled 

FQ参数:

limit : 真实队列长度的硬限值。当达到这个限值时,新的报纸将被丢弃。如果降低此值,当满足新值时,报纸将被丢弃。默认情况下,此值为:1万。
flow_limit : 每流最大报文数量的硬性限值。默认为:100。
quantum : 每次轮询队列的信用值(credit),例如,每次都可以排队的字节数量。这个值的设置意味着下一个流等待服务的时间更长,默认为两倍MTU值。
refill_delay : 默认情况下,非活动流重新分配信用值的时间间隔为40ms。
low_rate_threshold : 当pacing当速率低于此值时,在发送报纸之间增加延迟。
initial_quantum : 信用值的初始发送(credit),例如,当一个新的流刚被排队处理时,可以处理的字节数量。特别允许此选项IW10而设置(TCP初始窗口值已调整为10)。默认值为10倍的接口MTU值,对于标准的以太网为15140。
maxrate : 流量的最大发送率。默认情况下,速度没有限制。此外,应用程序还可以通过设置接口选项SO_MAX_PACING_RATE设定最大速率,但真正生效的速率是两者中的较小值。
buckets : 流查找使用的hash表的大小。为了进行高效的冲突检测,每一个bucket桶给红黑树结构(red-black tree)。默认值为:1024。
[no]pacing : 流的pacing默认开启功能控制。
orphan_mask : 对于不属于套接口的报文,或TCP未完成连接的报纸(套接口状态为TCPF_LISTEN或者TCPF_NEW_SYN_RECV),FQ将保存在报文中skb结构成员hash的值进行mask操作(使用orphan_mask),这将导致这些报纸不能侵占一切bucket,实现预防DDOS攻击效果。默认值为1023(16)x3FF),这意味着不会为此类报纸分配超过1024数量的流结构。
ce_threshold : 对于报纸的正常发送时间戳,如果超过此阈值间隔,则设置所有尚未发送的报纸ECN标记ECE(ECN Congestion Experienced)。这对于类似DCTCP拥塞控制算法更有用,需要在队列占用率较低的情况下进行标记。

2. 内核FQ初始化

函数fq_init实现FQ从以下可以看出初始化FQ每个参数的默认值。bucket选项对应的参数fq_trees_log,保存的为bucket数量取2对数,对应1024,去2对数后为10。

static int fq_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) {     struct fq_sched_data *q = qdisc_priv(sch);      sch->limit      = 10000;     q->flow_plimit      = 100;     q->quantum      = 2 * psched_mtu(qdisc_dev(sch));     q->initial_quantum  = 10 * psched_mtu(qdisc_dev(sch));     q->flow_refill_delay    = msecs_to_jiffies(40);     q->flow_max_rate    = ~0UL;     q->time_next_delayed_flow = ~0ULL;     q->rate_enable      = 1;     q->new_flows.first  = NULL;     q->old_flows.first  = NULL;     q->delayed      = RB_ROOT;     q->fq_root      = NULL;     q->fq_trees_log     = ilog2(1024);     q->orphan_mask      = 1024 - 1;     q->low_rate_threshold   = 550000 / 8;      /* Default ce_threshold of 4294 seconds */     q->ce_threshold     = (u64)NSEC_PER_USEC * ~0U;      qdisc_watchdog_init_clockid(&q->watchdog, sch, CLOCK_MONOTONIC);     if (opt)         err = fq_change(sch, opt, extack);     else         err = fq_resize(sch, q->fq_trees_log);     return err; 

内核初始化low_rate_threshold参数单位为bit,换算为byte的话为:

550000 / 8 = (550000 / 8) * 8 = 550000bytes = 550kbytes。 

参数ce_threshold默认值等于: ~0U,内核变量q->ce_threshold中保存的为纳秒值:(NSEC_PER_USEC * ~0U),转换为秒:4294s。

1000L * 0xFFFF FFFF = 4294967295000 ns ≈ 4294s 

tc命令在显示ce_threshold转换后的微秒值(即:0xFFFF FFFF),,对于默认值0xFFFF FFFF,tc不显示。应该没有超过正常发送时间这么长时间未发送的报纸。

static int fq_dump(struct Qdisc *sch, struct sk_buff *skb) {     struct fq_sched_data *q = qdisc_priv(sch);     u64 ce_threshold = q->ce_threshold;          opts = nla_nest_start(skb, TCA_OPTIONS);     if (opts == NULL)          goto nla_put_failure;          /* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore */              do_div(ce_threshold, NSEC_PER_USEC); 

内核版本 5.0

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章