路由查表演算法:雜湊表&Trie樹
1. Linux的雜湊查詢演算法
這是Linux作業系統的經典的路由查詢演算法,直到現在還是預設的路由查詢演算法。然而它很簡單。由於它的簡單性,核心(kernel)開發組一直很推崇它,雖然它有這樣那樣的侷限性,但由於Linux核心的哲學就是“夠用即可”,因為Linux幾乎從來不被用於專業的核心網路路由系統,因此雜湊查詢法一直都是預設的選擇。
1.1. 查詢過程
查詢結構如下圖所示:
查詢順序如下圖所示:
為了實現最長字首匹配,從最長的掩碼開始匹配,每一個掩碼都有一個雜湊表,目的IP地址雜湊到這些雜湊表的特定的桶中,然後遍歷其衝突連結串列得到最終結果。
注意,雜湊查詢演算法是基於掩碼的遍歷來實現嚴格的最長字首匹配的,也就是說如果一條最終將要通過預設閘道器發出的資料報,它起碼要匹配32次才能得到結果。
2. Trie樹
IP地址為32位,當報文在網路上傳輸時,要在路由表中進行查詢。IP地址的對應位如果能與路由表中儲存的進行匹配,這些報文就會發送到路由指向的地址。如下面是一個路由表(列出的是網路字首,掩碼對應的主機部分省去了):
Entry
--------
0 0000
1 0001
2 00101
3 010
4 0110
5 0111
6 100
7 101000
8 101001
9 10101
10 10110
11 10111
12 110
13 11101000
14 11101001
目標地址和路由表中的各項比較,如果有多個都能匹配,選擇最長的那個,如果沒有一個能匹配,使用預設路由。
在核心中,這個路由表由trie來表示:
左孩子表示0,右孩子表示1。這樣比如010就會到達節點3的位置。trie數的最大深度理論上可以達到32。
從圖中看,有很多空的節點,並且高度太深,為提高效率,可使用路徑壓縮,這樣就變成如下的形狀:
每一個空節點都被移除了,在每個節點新增一個變數skip,儲存被移除的空節點的個數。這樣11101001從根節點開始,先到右邊一個節點,再到右邊一個節點,再到右邊一個節點,這時要跳過4位,最後一位是1,到右邊的節點,就到達14的位置。這種方式其實就是謝希仁計算機網路教材中提到的對每個ip地址取出唯一的字首。
再進行優化,對trie的層級進行壓縮,就成為LC-tries,最後變成下面的形狀:
一個節點,如果它只有兩個節點且左右節點都存在,用兩個子節點代替這個節點,如果節點的兩個節點都為葉子節點,則停止替換。這個替換可在子樹中進行重複。