Linux 核心路由發現過程

2021-06-02 13:34:48 字數 3017 閱讀 9650

路由查詢

//這個函式負責從fib_table中查詢fn_key相匹配的fib_node,然後找到相應的fib_info,

//將結果存放在fib_result結構中

//傳入引數fz_divisor是linux kernel 2.6的變化,在2.4.x中是直接傳入key的,而flp引數裡面包含了資料報的全部位址資訊,傳入之後再用目的位址來計算key.

static int

fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)

int err;

struct fn_zone *fz;

//fn_table->tb_data 就是 fn_hash 結構

struct fn_hash *t = (struct fn_hash*)tb->tb_data;

read_lock(&fib_hash_lock);

//遍歷可用的fz_zone列表

for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {

struct hlist_head *head;

struct hlist_node *node;

struct fib_node *f;

//通過目的位址,計算出所要查詢的fn_key

//對於本地接收路由,它就是代表本地網路裝置介面的ip位址,如172.16.48.2,對於子網單播,它就是子網號,比如172.16.48.0

__be32 k = fz_key(flp->fl4_dst, fz);

//fz_hash實際上是乙個雜湊表,每個陣列單元儲存了乙個fib_node鍊錶的頭指標

//fn_new_zone函式用於建立乙個新的fz_zone,可以看到fz_hash的初始化過程:

//fz->fz_hash = fz_hash_alloc(fz->fz_divisor); 所以,fz_hash的長度是由fz_divisor成員指定的

//這個操作取得了fib_node鏈頭指標

head = &fz->fz_hash[fn_hash(k, fz)];

hlist_for_each_entry(f, node, head, fn_hash) {

if (f->fn_key != k)

continue;

err = fib_semantic_match(&f->fn_alias,

flp, res,

f->fn_key, fz->fz_mask,

fz->fz_order);

if (err <= 0)

goto out;

err = 1;

out:

read_unlock(&fib_hash_lock);

return err;

接下來看這個函式呼叫的另外乙個函式fib_semantic_match
int fib_semantic_match(struct list_head *head, const struct flowi *flp,

struct fib_result *res, __be32 zone, __be32 mask,

int prefixlen)

struct fib_alias *fa;

int nh_sel = 0;

//遍歷fib_node中的fib_alias

list_for_each_entry_rcu(fa, head, fa_list) {

int err;

if (fa->fa_tos &&

fa->fa_tos != flp->fl4_tos)

continue;

if (fa->fa_scope < flp->fl4_scope)

continue;

fa->fa_state |= fa_s_accessed

//取**型別錯誤碼

err = fib_props[fa->fa_type].error;

if (err == 0) {

//取得fib_info

struct fib_info *fi = fa->fa_info;

//此標誌表明該節點**不通,直接return

if (fi->fib_flags & rtnh_f_dead)

continue;

switch (fa->fa_type) {

//單目**

case rtn_unicast:

//本地**

case rtn_local:

//廣播**

case rtn_broadcast:

//任意**

case rtn_anycast:

//多目**

case rtn_multicast:

for_nexthops(fi) {

if (nh->nh_flags&rtnh_f_dead)

continue;

if (!flp->oif || flp->oif == nh->nh_oif)

break;

#ifdef config_ip_route_multipath

if (nhsel < fi->fib_nhs) {

nh_sel = nhsel;//**位址編號賦值

goto out_fill_res;

#else

if (nhsel < 1) {

goto out_fill_res;

#endif

endfor_nexthops(fi);

continue;

default:

printk(kern_debug "impossible 102/n");

return -einval;

return err;

return 1;

//省去部分**

linux核心 路由fib表之輸出查詢

2.2.3.2 輸出路由查詢 ip route output key 功能 呼叫ip route output flow ip route output flow 功能 1 路由發包查詢 2 ipsec處理流程 int ip route output flow struct net net,stru...

linux核心 路由fib表之初始化

1 路由表操作 主要實現下列功能 a 路由表初始化 b 路由建立 c 路由刪除 1.1 路由表的初始化 路由表的初始化由ip fib init函式實現的,功能 a 註冊路由操作相關函式 b 將路由模組新增到網路命令空間 c 註冊網路裝置狀態和位址變化到通知鏈 d 為fib node和fib alia...

核心路由器十項效能指標

路由器是一種連線多個網路或網段的網路裝置,它能將不同網路或網段之間的資料資訊進行 翻譯 以使它們能夠相互 讀 懂對方的資料,從而構成乙個更大的網路。路由器有兩大典型功能,即資料通道功能和控制功能。資料通道功能包括 決定 背板 以及輸出鏈路排程等,一般由特定的硬體來完成 控制功能一般用軟體來實現,包括...