Linux TC流控實現(xiàn)機制過程
一、TC核心架構
Linux TC采用模塊化分層設計,核心組件包括:
- Qdisc(排隊規(guī)則):流量調(diào)度的基本單元(如
pfifo_fast、htb) - Class(分類):Qdisc內(nèi)部的子隊列(僅存在于分類型Qdisc中)
- Filter(過濾器):將流量分類到特定Class(如
u32、fwmark) - Policer(策略器):執(zhí)行速率限制(如
tbf) - Action(動作):對數(shù)據(jù)包執(zhí)行操作(如
mirred重定向)
二、核心數(shù)據(jù)結構
1.Qdisc結構體(net/sched/sch_generic.c)
struct Qdisc {
int (*enqueue)(struct sk_buff *skb, struct Qdisc *sch); // 入隊操作
struct sk_buff* (*dequeue)(struct Qdisc *sch); // 出隊操作
struct Qdisc_ops *ops; // Qdisc操作函數(shù)集
struct netdev_queue *dev_queue; // 關聯(lián)的網(wǎng)絡設備隊列
};
2.Qdisc操作集(include/net/sch_generic.h)
struct Qdisc_ops {
struct Qdisc_ops *next;
const struct Qdisc_class_ops *cl_ops; // Class操作函數(shù)集
int (*enqueue)(struct sk_buff *, struct Qdisc *);
struct sk_buff * (*dequeue)(struct Qdisc *);
// ... 其他鉤子函數(shù)(init, destroy, reset等)
};
3.Filter結構體(net/sched/cls_api.c)
struct tcf_proto {
__be16 protocol; // 匹配的協(xié)議(如ETH_P_IP)
struct tcf_proto_ops *ops; // Filter操作函數(shù)集
struct tcf_result result; // 分類結果(指向Class)
};
三、關鍵處理流程
1.數(shù)據(jù)包入隊流程
graph TD
A[數(shù)據(jù)包到達] --> B{設備是否啟用TC?}
B -->|是| C[調(diào)用dev_queue_xmit()]
C --> D[執(zhí)行__dev_xmit_skb()]
D --> E[調(diào)用sch_direct_xmit() -> qdisc->enqueue()]
E --> F[Qdisc特定入隊邏輯]
F --> G[按調(diào)度算法緩存/丟棄]
2.數(shù)據(jù)包出隊調(diào)度
無分類Qdisc(如pfifo):
static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *sch) {
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
return skb;
}
分類型Qdisc(如HTB):
struct sk_buff *htb_dequeue(struct Qdisc *sch) {
while ((skb = htb_do_dequeue(sch, prio, band)) != NULL) {
// 按類別優(yōu)先級和令牌桶算法出隊
}
}
四、經(jīng)典Qdisc實現(xiàn)分析
1.HTB(Hierarchical Token Bucket)
核心機制:
- 令牌桶按層次分配帶寬
- 子類可借用父類空閑帶寬
關鍵數(shù)據(jù)結構:
struct htb_class {
struct Qdisc_class_common common;
struct psched_ratecfg rate; // 速率配置
struct psched_ratecfg ceil; // 上限配置
s64 tokens, ctokens; // 令牌計數(shù)
struct htb_class *parent; // 父類指針
};
2.Netem(網(wǎng)絡模擬器)
實現(xiàn)延遲/丟包/亂序:
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) {
if (loss_condition) { // 按概率丟包
kfree_skb(skb);
return NET_XMIT_SUCCESS;
}
if (delay_calculated) { // 計算延遲時間
tfifo = netem_skb_cb(skb);
tfifo->time_to_send = now + delay;
}
__qdisc_enqueue_tail(skb, &sch->q); // 加入延遲隊列
}
五、Filter與Classifier機制
1.U32過濾器示例
static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res) {
struct tc_u32_key *key = tp->data;
if (skb->len < key->off + 4) // 檢查偏移量是否有效
return -1;
if (*(u32*)(skb->data + key->off) == key->val) // 匹配關鍵值
res->classid = key->classid; // 設置分類ID
}
2.eBPF集成(cls_bpf)
允許加載eBPF程序進行高級分類:
static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res) {
struct cls_bpf_prog *prog = tp->data;
int ret = bpf_prog_run(prog->filter, skb); // 執(zhí)行eBPF程序
if (ret == TC_ACT_SHOT) return -1; // 丟棄包
res->classid = ret; // 設置分類ID
}
六、TC配置接口(Netlink)
用戶空間工具:iproute2的tc命令
內(nèi)核處理路徑:
// net/sched/sch_api.c
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) {
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm = nlmsg_data(n);
struct net_device *dev = __dev_get_by_index(net, tcm->tcm_ifindex);
// 解析并調(diào)用qdisc/class/filter操作函數(shù)
}
七、性能優(yōu)化機制
多隊列Qdisc (mq):
- 每個CPU核心一個隊列,減少鎖競爭
FQ_Codel (Fair Queuing with Controlled Delay):
- 使用流哈希分離流量
- 基于延遲的ECN標記
?
static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch) {
struct fq_codel_flow *flow;
list_for_each_entry(flow, &q->new_flows, flowchain) {
skb = flow->head;
if (codel_time_after(skb->tstamp, now)) // 檢查是否需延遲
continue;
// ... 出隊邏輯
}
}
?八、調(diào)試與監(jiān)控
TC統(tǒng)計信息:
tc -s qdisc show dev eth0
內(nèi)核Tracepoint:
perf record -e 'net:net_dev_queue' -e 'net:net_dev_xmit'
九、代碼目錄結構
net/sched/ ├── sch_generic.c // Qdisc基礎框架 ├── sch_htb.c // HTB實現(xiàn) ├── sch_netem.c // Netem實現(xiàn) ├── cls_api.c // Filter框架 ├── cls_u32.c // U32分類器 ├── act_api.c // Action框架 └── act_mirred.c // 重定向Action
十、總結與挑戰(zhàn)
優(yōu)勢:
- 靈活的分層流量控制
- 可擴展的模塊化設計
挑戰(zhàn):
- 復雜配置導致學習曲線陡峭
- 單核處理瓶頸(部分Qdisc未充分并行化)
- 與XDP/BPF等新技術的整合
通過深入分析可見,Linux TC通過抽象Qdisc/Class/Filter三層模型,實現(xiàn)了從簡單FIFO到復雜分層調(diào)度的靈活控制,其代碼設計充分體現(xiàn)了UNIX的"組合小工具"哲學。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Linux文件服務器實戰(zhàn)詳解(系統(tǒng)用戶)
這篇文章主要介紹了Linux文件服務器實戰(zhàn)詳解(系統(tǒng)用戶),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2018-06-06
Jetson xavier nx的擴容及安裝cuda經(jīng)驗分享
這段描述主要圍繞圍繞述了Jetson設備內(nèi)存不足導致黑屏的解決方法,以及固態(tài)硬盤擴容的具體步驟,包括進入命令行刪除文件、固態(tài)硬盤安裝和配置等并還建議使用官方下載源以避免安裝過程中出現(xiàn)的問題2026-06-06

