Linux核心中流量控制 5

2021-08-31 05:06:10 字數 3625 閱讀 3317

嚴禁用於任何商業用途。

msn: [email protected]

5.5 sfq(stochastic fairness queueing discipline)

sfq演算法是個比較簡單的演算法,速度也比較快,演算法維護一定數量的資料報佇列,入隊是將資料報進

行雜湊後插入某佇列,出隊則是輪詢方式出佇列,另外可設定一定的隨機因子,在計算雜湊值時能碰

撞少些,流控演算法在net/sched/sch_sfq.c中定義,在實現中, 佇列數量最大為128個,這是保證sfq私

有資料結構能小於4k,能在乙個頁面內分配。在使用用不建議作為網絡卡的根節點流控,而是最好作為

分類流控方法如cbq等的葉子節點。

5.5.1 sfq操作結構定義

// tc使用的sfq配置引數結構

struct tc_sfq_qopt

;#define sfq_depth 128

#define sfq_hash_divisor 1024

/* this type should contain at least sfq_depth*2 values */

// sfq索引值是無符合8位數

typedef unsigned char sfq_index;

struct sfq_head

;// sfq私有資料

struct sfq_sched_data

;sfq資料結構比較怪異, 資料儲存是陣列, 但邏輯上又是雙向鍊錶, 訪問時又使用陣列索引。

// sfq流控操作結構

static struct qdisc_ops sfq_qdisc_ops = ;

5.5.2 sfq一些基本操作

// hash函式

static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1)

// sfq雜湊函式

static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)

// ipv6

case __constant_htons(eth_p_ipv6):

default:

// 其他協議就用路由引數, 鏈路層協議和sock指標

h = (u32)(unsigned long)skb->dst^skb->protocol;

h2 = (u32)(unsigned long)skb->sk;

}// 計算雜湊值

return sfq_fold_hash(q, h, h2);

}// 鏈結操作

static inline void sfq_link(struct sfq_sched_data *q, sfq_index x)

// 減少, 將x號索引點斷開

static inline void sfq_dec(struct sfq_sched_data *q, sfq_index x)

// 增加, 增加x處索引點

static inline void sfq_inc(struct sfq_sched_data *q, sfq_index x)

5.5.3 初始化

static int sfq_init(struct qdisc *sch, struct rtattr *opt)

// sfq流控資料報總數限制

q->limit = sfq_depth;

q->max_depth = 0;

q->tail = sfq_depth;

// 配置sfq是允許不帶任何引數的

if (opt == null) else

// 初始化索引鍊錶, 初始化dep的前128個元素

for (i=0; iperturbation = net_random()&0x1f;

// 擾動時間非0, 更新定時器, 現在是在時鐘中斷中, 定時器已經從定時鍊錶中拆除了,

// 所以要重新新增定時器

if (q->perturb_period)

}// 設定sfq引數, 只在初始化時呼叫, 以後將不再修改

static int sfq_change(struct qdisc *sch, struct rtattr *opt)

sch_tree_unlock(sch);

return 0;

}5.5.4 入隊

static int

sfq_enqueue(struct sk_buff *skb, struct qdisc* sch)

// 增加backlog

sch->qstats.backlog += skb->len;

// 將資料報新增到佇列鍊錶

__skb_queue_tail(&q->qs[x], skb);

// x節點增加操作

sfq_inc(q, x);

// 如果佇列長度為1, 是新佇列

if (q->qs[x].qlen == 1) else

}// 檢查當前排隊資料報數是否超過限制值

if (++sch->q.qlen < q->limit-1)

// 超限制情況,丟包

sfq_drop(sch);

return net_xmit_cn;

}5.5.5 重入隊

// 和入隊操作幾乎一樣, 只是統計值處理有點變化而已

static int

sfq_requeue(struct sk_buff *skb, struct qdisc* sch)

sch->qstats.backlog += skb->len;

__skb_queue_head(&q->qs[x], skb);

sfq_inc(q, x);

if (q->qs[x].qlen == 1) else

}if (++sch->q.qlen < q->limit - 1)

sch->qstats.drops++;

sfq_drop(sch);

return net_xmit_cn;

}5.5.6 出隊

static struct sk_buff *

sfq_dequeue(struct qdisc* sch)

q->next[q->tail] = a;

q->allot[a] += q->quantum;

} else if ((q->allot[a] -= skb->len) <= 0)

return skb;

}5.5.7 復位

static void

sfq_reset(struct qdisc* sch)

5.5.8 釋放

static void sfq_destroy(struct qdisc *sch)

5.5.9 丟包

static unsigned int sfq_drop(struct qdisc *sch)

if (d == 1)

return 0;

}5.5.10 輸出引數

static int sfq_dump(struct qdisc *sch, struct sk_buff *skb)

...... 待續 ......

Linux核心中流量控制 9

msn yfydz no1 hotmail.com 5.9 ingress ingress流控方法是針對輸入資料進行流控處理的,在net sched sch ingress.c中定義,使用時要求在核心配置中定義config net cls act或config netfilter,不過從 實現看起來...

Linux核心中流量控制 15

msn yfydz no1 hotmail.com 5.15.qdisc的netlink控制 各網絡卡的qdisc的使用者層操作控制是通過rtnetlink介面實現使用者空間和核心之間的通訊的 rtnetlink link,rtnetlink是專門針對路由控制的netlink介面.include l...

置頂 Linux 流量控制

在如今的網路界,也許tc知道的人並不多了,這篇文章做留戀吧。以前研究tc時記錄下的講解與配置檔案。tc filter add dev eth0 parent 1 0 protocol ip prio 4 handle 4 fw classid 1 14 tc filter add dev eth0 ...