首頁/ 汽車/ 正文

一篇講解IPv4路由表

如下IP命令新增路由表項,預設情況下路由新增在main路由表中:

# ip route add 192。2。0。0/16 via 192。168。1。106## ip route show table main 192。2。0。0/16 via 192。168。1。106 dev ens32

也可指定路由表,如下在local/default表中新增相同目的網路,但是閘道器不同的路由項:

# ip route add 192。2。0。0/16 via 192。168。1。1 table local## ip route show table local192。2。0。0/16 via 192。168。1。1 dev ens32 ### ip route add 192。2。0。0/16 via 192。168。1。200 table default## ip route show table default192。2。0。0/16 via 192。168。1。200 dev ens32

下面使用ping命令測試到目的網段192。2。0。0/16,可見其使用的是local表中的路由項,而不是main表中項:

# tcpdump -i ens32 host 192。2。0。1 -n -e & // 後臺啟動tcpdump## ping 192。2。0。1PING 192。2。0。1 (192。2。0。1) 56(84) bytes of data。23:05:53。330337 00:0c:29:1e:20:e3 > 00:90:27:fe:c9:34, ethertype IPv4 (0x0800), length 98: 192。168。1。140 > 192。2。0。1: ICMP echo request, id 64942, seq 1, length 64 # # ip neigh show192。168。1。1 dev ens32 lladdr 00:90:27:fe:c9:34 REACHABLE

以下刪除local表中新增的路由,再執行ping操作,這次是main表中的路由生效,閘道器使用的是192。168。1。106:

# ip route del 192。2。0。0/16 via 192。168。1。1 table local# # ping 192。2。0。1PING 192。2。0。1 (192。2。0。1) 56(84) bytes of data。23:21:47。752867 00:0c:29:1e:20:e3 > 00:60:e0:6f:9c:e3, ethertype IPv4 (0x0800), length 98: 192。168。1。140 > 192。2。0。1: ICMP echo request, id 528, seq 1, length 64# # ip neigh show192。168。1。106 dev ens32 lladdr 00:60:e0:6f:9c:e3 STALE

更多linux核心影片教程文件資料免費領取後臺私信

【核心】

自行獲取。

一篇講解IPv4路由表

一篇講解IPv4路由表

Linux核心原始碼/記憶體調優/檔案系統/程序管理/裝置驅動/網路協議棧-學習影片教程-騰訊課堂

最後,刪除main中的路由,

# ip route del 192。2。0。0/16 via 192。168。1。106 table main## ping 192。2。0。1 PING 192。2。0。1 (192。2。0。1) 56(84) bytes of data。23:50:55。690358 00:0c:29:1e:20:e3 > 00:60:e0:85:7a:06, ethertype IPv4 (0x0800), length 98: 192。168。1。140 > 192。2。0。1: ICMP echo request, id 2079, seq 1, length 64# # ip neigh 192。168。1。200 dev ens32 lladdr 00:60:e0:85:7a:06 STALE

路由表建立

在新增表項時,沒有指定路由表ID,或者指定的表ID等於0,核心使用main表RT_TABLE_MAIN,函式fib_trie_table分配一個新的fib_table結構,代表一個新的路由表。對於main表,將其制賦值給名稱空間中的fib_main成員。最後將其連結到雜湊桶fib_table_hash的對應連結串列中。

如果指定的路由表ID等於RT_TABLE_LOCAL,但是此名稱空間中沒有配置過IPv4策略路由,也使用main路由表,作為alias,參見fib_trie_table。這種情況下,fib_new_table會在呼叫自身,引數ID使用RT_TABLE_MAIN,獲取main表的結構,賦值與alias。

對於default表,目前不太清楚其使用情況,在建立之後,核心將其賦值給名稱空間的fib_default成員。

struct fib_table *fib_new_table(struct net *net, u32 id){ struct fib_table *tb, *alias = NULL; unsigned int h; if (id == 0) id = RT_TABLE_MAIN; tb = fib_get_table(net, id); if (tb) return tb; if (id == RT_TABLE_LOCAL && !net->ipv4。fib_has_custom_rules) alias = fib_new_table(net, RT_TABLE_MAIN); tb = fib_trie_table(id, alias); if (!tb) return NULL; switch (id) { case RT_TABLE_MAIN: rcu_assign_pointer(net->ipv4。fib_main, tb); break; case RT_TABLE_DEFAULT: rcu_assign_pointer(net->ipv4。fib_default, tb); break; default: break; } h = id & (FIB_TABLE_HASHSZ - 1); hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4。fib_table_hash[h]); return tb;

對於main路由表,以及其它路由表,fib_trie_table的引數alias為空;但是對於local路由表,alias執向main表結構,就不用重新分配trie結構了。對於所有的路由表,都需要分配一個fib_table結構。

對於local路由表,其資料欄位指向main路由表的資料欄位。可見local表不是一個完全單獨的路由表,其資料與main表是公用的。所以local路由表不需要進行以下對資料欄位的初始化操作。

struct fib_table *fib_trie_table(u32 id, struct fib_table *alias){ struct fib_table *tb; struct trie *t; size_t sz = sizeof(*tb); if (!alias) sz += sizeof(struct trie); tb = kzalloc(sz, GFP_KERNEL); if (!tb) return NULL; tb->tb_id = id; tb->tb_num_default = 0; tb->tb_data = (alias ? alias->__data : tb->__data); if (alias) return tb; t = (struct trie *) tb->tb_data; t->kv[0]。pos = KEYLENGTH; t->kv[0]。slen = KEYLENGTH;#ifdef CONFIG_IP_FIB_TRIE_STATS t->stats = alloc_percpu(struct trie_use_stats); if (!t->stats) { kfree(tb); tb = NULL; }#endif return tb;

路由查詢

如下核心的路由查詢入口函式fib_lookup,可見其查詢順序為:路由策略->main路由表->default路由表。對local路由表的查詢包含在main路由表查詢中。

static inline int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res, unsigned int flags){ struct fib_table *tb; int err = -ENETUNREACH; flags |= FIB_LOOKUP_NOREF; if (net->ipv4。fib_has_custom_rules) return __fib_lookup(net, flp, res, flags); rcu_read_lock(); res->tclassid = 0; tb = rcu_dereference_rtnl(net->ipv4。fib_main); if (tb) err = fib_table_lookup(tb, flp, res, flags); if (!err) goto out; tb = rcu_dereference_rtnl(net->ipv4。fib_default); if (tb) err = fib_table_lookup(tb, flp, res, flags);

由函式fib_insert_alias可知,在trie樹葉子節點中,路由表項時按照表ID由大到小排列的,如果local和main表中存在相同的路由,優先選擇的是local表中的路由,宏RT_TABLE_LOCAL(255)大於RT_TABLE_MAIN(254)。

static int fib_insert_alias(struct trie *t, struct key_vector *tp, struct key_vector *l, struct fib_alias *new, struct fib_alias *fa, t_key key){ if (!l) return fib_insert_node(t, tp, new, key); if (fa) { hlist_add_before_rcu(&new->fa_list, &fa->fa_list); } else { struct fib_alias *last; hlist_for_each_entry(last, &l->leaf, fa_list) { if (new->fa_slen < last->fa_slen) break; if ((new->fa_slen == last->fa_slen) && (new->tb_id > last->tb_id)) break; fa = last; } if (fa) hlist_add_behind_rcu(&new->fa_list, &fa->fa_list); else hlist_add_head_rcu(&new->fa_list, &l->leaf); }

導讀-最新發表 - 我愛核心網 - 構建全國最權威的核心技術交流分享論壇

轉載地址:一篇講解IPv4路由表! - 圈點 - 我愛核心網 - 構建全國最權威的核心技術交流分享論壇

一篇講解IPv4路由表

相關文章

頂部