嚴禁用於任何商業用途。
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 ...