Linux核心分析 網路 四 路由表

2021-08-14 17:19:58 字數 3649 閱讀 4000

路由表

在核心中存在路由表

fib_table_hash

和路由快取表

rt_hash_table

。路由快取表主要是為了加速路由的查詢,每次路由查詢都會先查詢路由快取,再查詢路由表。這和

cache

是乙個道理,快取儲存最近使用過的路由項,容量小,查詢快速;路由表儲存所有路由項,容量大,查詢慢。

首先,應該先了解路由表的意義,下面是

route

命令檢視到的路由表:

destination

netmask

gateway

flags

inte***ce

metric

169.254.0.0

255.255.0.0 *

ueth0 1

192.168.123.0

255.255.255.0 *

ueth0 1

default

0.0.0.0

192.168.123.254 ug

eth0 1

一條路由其實就是告知主機要到達乙個目的位址,下一跳應該走**。比如發往

192.168.22.3

報文通過查路由表,會得到下一跳為

192.168.123.254

,再將其傳送出去。在路由表項中,還有乙個很重要的屬性

-scope

,它代表了到目的網路的距離。

路由scope

可取值:

rt_scope_universe, rt_scope_link, rt_scope_host

在報文的**過程中,顯然是每次**都要使到達目的網路的距離要越來越小或不變,否則根本到達不了目的網路。上面提到的

scope

很好的實現這個功能,在查詢路由表中,表項的

scope

一定是更小或相等的

scope(

比如rt_scope_link

,則表項

scope

只能為rt_scope_link

或rt_scope_host)。

路由快取

路由快取用於加速路由的查詢,當收到報文或傳送報文時,首先會查詢路由快取,在核心中被組織成

hash

表,就是

rt_hash_table

。static struct rt_hash_bucket          *rt_hash_table __read_mostly;      [net\ipv4\route.c] 通過

ip_route_input()

進行查詢,首先是快取操作時,通過

[src_ip, dst_ip, iif,rt_genid]

計算出hash

值hash = rt_hash(daddr, saddr, iif, rt_genid(net)); 此時

rt_hash_table[hash].chain

就是要操作的快取表項的鍊錶,比如遍歷該鍊錶

for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.dst.rt_next)

因此,在快取中查詢乙個表項,首先計算出

hash

值,取出這組表項,然後遍歷鍊錶,找出指定的表項,這裡需要完全匹配

[src_ip, dst_ip, iif, tos, mark, net]

,實際上

struct rtable

中有專門的屬性用於快取的查詢鍵值

– struct flowi

。/* cache lookup keys */

struct flowi                fl;

當找到表項後會更新表項的最後訪問時間,並取出

dstdst_use(&rth->u.dst, jiffies);

skb_dst_set(skb, &rth->u.dst);

路由快取的建立

inet_init() -> ip_init() -> ip_rt_init()

rt_hash_table = (struct rt_hash_bucket *)

alloc_large_system_hash("ip route cache",

sizeof(struct rt_hash_bucket),

rhash_entries,

(totalram_pages >= 128 * 1024) ?

15 : 17,

0,&rt_hash_log,

&rt_hash_mask,

rhash_entries ? 0 : 512 * 1024); 其中

rt_hash_mask

表示表的大小,

rt_hash_log = log(rt_hash_mask)

,建立後的結構如圖所示:

路由快取插入條目

函式rt_intern_hash()

要插入的條目是

rt,相應雜湊值是

hash

,首先通過

hash

值找到對應的

bucket

rthp = &rt_hash_table[hash].chain;

然後對bucket

進行一遍查詢,這次查詢的目的有兩個:如果是超時的條目,則直接刪除;如果是與

rt相同鍵值的條目,則刪除並將

rt插入頭部返回。

while ((rth = *rthp) != null)

if (compare_keys(&rth->fl, &rt->fl) && compare_netns(rth, rt))

……rthp = &rth->u.dst.rt_next; }

在掃瞄一遍後,如

rt還未存在,則將其插入頭部

rt->u.dst.rt_next = rt_hash_table[hash].chain;

rcu_assign_pointer(rt_hash_table[hash].chain, rt);

如果新插入rt滿足一定條件,還要與arp鄰居表進行繫結

hint

:快取的每個

bucket

是沒有頭結點的,單向鍊錶,它所使用的插入和刪除操作是值得學習的,簡單實用。

路由快取刪除條目

rt_del()

要刪除的條目是

rt,相應雜湊值是

hash

,首先通過

hash

值找到對應的

bucket

,然後遍歷,如果條目超時,或找到

rt,則刪除它。

rthp = &rt_hash_table[hash].chain;

spin_lock_bh(rt_hash_lock_addr(hash));

ip_rt_put(rt);

while ((aux = *rthp) != null)

rthp = &aux->u.dst.rt_next; }

spin_unlock_bh(rt_hash_lock_addr(hash));

Linux核心分析 網路 四補 路由表補充

核心版本 2.6.34 前篇路由表 說明了路由表的結構及路由表的建立。下面是一些路由表的使用的細枝末節,作補充說明。路由可以分為兩部分 路由快取 rt hash table 和路由表 路由快取顧名思義就是加速路由查詢的,路由快取的插入是由核心控制的,而非人為的插入,與之相對比的是路由表是人為插入的,...

網路 路由表 IP選路

路由表的 flags 字段顯示路由狀態 a 活動的休眠閘道器檢測在路由上被啟用。本字段只適用於 aix 5.1 或更新版本。u up.h 路由至主機而不是網路。g 路由至閘道器。不帶g表示不經過路由 d 路由通過重定向動態地建立。m 路由通過重定向被修改。c 對該路由的訪問建立轉殖路由。本字段只適用...

CQTSC2016 路由表 題解

題目大意 有n個操作,分add和ask兩種。add操作就是新增乙個字串 把ipv4位址轉成32位的二進位制串,取前l位,l為掩碼 保證每次add都不相同。ask操作給出詢問串s 同樣是ipv4位址轉成32位二進位制串 和區間 l,r 對於這次ask之前的add操作,從頭開始,每add一次,s就會找已...