Linux公平佇列FQ配置

2021-10-24 07:59:33 字數 4129 閱讀 6525

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等協議報文),此佇列的報文總是優先被取出傳送。

配置如下:

$ 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: 真實的佇列長度的硬性限值。當達到這一限值時,新的報文將被丟棄。如果降低此值,當滿足新設值時,報文被丟棄,預設情況下,此值為:10000。

flow_limit: 每個流最大入隊的報文數量的硬性限值。預設為:100。

quantum: 每次輪詢出佇列的信用值(credit),例如,每個流每次可出隊的位元組數量。此值設定的較大意味值下乙個流等待服務的時間更長,預設為2倍的介面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(十六進製制為:0x3ff),意味著不會為此類報文分配超過1024數量的流結構。

ce_threshold: 對於報文的正常傳送時間戳,如果超過此閾值間隔還沒有被傳送出去的所有報文都將被設定ecn標記ece(ecn congestion experienced)。這對於類似dctcp的擁塞控制演算法比較有用,其要求在佇列佔用率較低的情況下進行標記操作。

函式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

CLH同步佇列是怎麼實現非公平和公平的

the wait queue is a variant of a clh craig,landin,and hagersten lock queue.clh locks are normally used for spinlocks 1 名稱 clh 由三個人名字組成 craig,landin,an...

Linux 完全公平排程器

讀書筆記,linux 系統程式設計 第六章高階程序管理 linux排程器為完全公平排程器,簡稱為cfs。和最近華為鴻蒙提出的確定時延排程相反。完全公平排程器和傳統的unix排程器有很大的區別。在大多數unix系統中,包括引入cfs之前的linux系統,在程序排程中存在兩個基本的基於程序的因素 優先順...

RabbitMQ 四 工作佇列之公平分發

public class producer channel.close connection.close public class consumer1 監聽佇列,第2個引數設定為手動確認.true 則為自動確認.channel.basicconsume queuename,false,false,f...