Linux核心中流量控制 15

2021-08-31 05:06:10 字數 4162 閱讀 4879

msn: [email protected]

5.15. qdisc的netlink控制

各網絡卡的qdisc的使用者層操作控制是通過rtnetlink介面實現使用者空間和核心之間的通訊的: rtnetlink_link, rtnetlink是專門針對路由控制的netlink介面.

/* include/linux/rtnetlink.h */

struct rtnetlink_link

;// 全域性陣列, 具體在 net/core/rtnetlink.c中定義

extern struct rtnetlink_link * rtnetlink_links[nproto];

其中的兩個成員定義如下:

/* net/core/rtnetlink.c */

void __init rtnetlink_init(void)

其中link_rtnetlink_table是乙個陣列, 定義為:

static struct rtnetlink_link link_rtnetlink_table[rtm_nr_msgtypes] =

,[rtm_setlink - rtm_base] = ,

[rtm_getaddr - rtm_base] = ,

[rtm_getroute - rtm_base] = ,

[rtm_newneigh - rtm_base] = ,

[rtm_delneigh - rtm_base] = ,

[rtm_getneigh - rtm_base] = ,

#ifdef config_fib_rules

[rtm_newrule - rtm_base] = ,

[rtm_delrule - rtm_base] = ,

#endif

[rtm_getrule - rtm_base] = ,

[rtm_getneightbl - rtm_base] = ,

[rtm_setneightbl - rtm_base] = ,

};5.15.1 初始化

初始化過程是定義對應tc的qdisc和class的操作命令的處理函式:

/* net/sched/sch_api.c */

static int __init pktsched_init(void)

else

} else

/* it may be default qdisc, ignore it */

// 如果找到的qdisc的控制代碼為0, 放棄q

if (q && q->handle == 0)

q = null;

if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) else

}} else

// 到這裡是屬於qdisc修改操作

/* change qdisc parameters */

// 沒找到qdisc節點, 返回錯誤

if (q == null)

return -enoent;

// 找到qdisc節點, 但設定了nlm_f_excl(排斥)標誌, 返回物件存在錯誤

if (n->nlmsg_flags&nlm_f_excl)

return -eexist;

// 檢查找到的qdisc節點的名稱和tc中指定的是否匹配

if (tca[tca_kind-1] && rtattr_strcmp(tca[tca_kind-1], q->ops->id))

return -einval;

// 修改qdisc引數

err = qdisc_change(q, tca);

if (err == 0)

qdisc_notify(skb, n, clid, null, q);

return err;

create_n_graft:

// 建立新qdisc節點

// 如果tc命令中沒有建立標誌, 返回錯誤

if (!(n->nlmsg_flags&nlm_f_create))

return -enoent;

// 建立新qdisc節點

if (clid == tc_h_ingress)

q = qdisc_create(dev, tcm->tcm_parent, tca, &err);

else

q = qdisc_create(dev, tcm->tcm_handle, tca, &err);

if (q == null)

graft:

// 嫁接操作

if (1)

return err;

}// qdisc通告

qdisc_notify(skb, n, clid, old_q, q);

if (old_q)

}return 0;

}5.15.2.2 獲取/刪除qdisc

/** delete/get qdisc.

*/static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)

else

} else

if (!q)

return -enoent;

if (tcm->tcm_handle && q->handle != tcm->tcm_handle)

return -einval;

} else

// 檢查找到的qdisc名稱和tc命令中指定的是否一致

if (tca[tca_kind-1] && rtattr_strcmp(tca[tca_kind-1], q->ops->id))

return -einval;

// 刪除qdisc操作

if (n->nlmsg_type == rtm_delqdisc)

} else

return 0;

}// 傳送qdisc通知資訊, new是處理後新qdisc節點資訊, old是處理前老節點資訊

static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,

u32 clid, struct qdisc *old, struct qdisc *new)

if (new)

// 傳送資料報

if (skb->len)

return rtnetlink_send(skb, pid, rtnlgrp_tc, n->nlmsg_flags&nlm_f_echo);

err_out:

// 錯誤處理, 釋放資料報

kfree_skb(skb);

return -einval;

}5.15.2.3 輸出網絡卡qdisc引數

static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)

// 填充qdisc資訊到資料報

if (tc_fill_qdisc(skb, q, q->parent, netlink_cb(cb->skb).pid,

cb->nlh->nlmsg_seq, nlm_f_multi, rtm_newqdisc) <= 0)

q_idx++;

}read_unlock(&qdisc_tree_lock);

}done:

read_unlock(&dev_base_lock);

// 返回處理的所有網絡卡數和qdisc數

cb->args[0] = idx;

cb->args[1] = q_idx;

return skb->len;

}// 填充qdisc資訊到skb資料報

static int tc_fill_qdisc(struct sk_buff *skb, struct qdisc *q, u32 clid,

u32 pid, u32 seq, u16 flags, int event)

5.16 qdisc小結

關於流控(qdisc)的分析就此告一段落, 後面將繼續分析分類(class), 過濾(filter)和動作(action)的處理過程.

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

Linux核心中流量控制 5

嚴禁用於任何商業用途。msn yfydz no1 hotmail.com 5.5 sfq stochastic fairness queueing discipline sfq演算法是個比較簡單的演算法,速度也比較快,演算法維護一定數量的資料報佇列,入隊是將資料報進 行雜湊後插入某佇列,出隊則是輪詢...

Linux核心中流量控制 9

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

置頂 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 ...