1. 程式人生 > >路由查表演算法:雜湊表&Trie樹

路由查表演算法:雜湊表&Trie樹

1. Linux的雜湊查詢演算法

這是Linux作業系統的經典的路由查詢演算法,直到現在還是預設的路由查詢演算法。然而它很簡單。由於它的簡單性,核心(kernel)開發組一直很推崇它,雖然它有這樣那樣的侷限性,但由於Linux核心的哲學就是“夠用即可”,因為Linux幾乎從來不被用於專業的核心網路路由系統,因此雜湊查詢法一直都是預設的選擇。

1.1. 查詢過程

查詢結構如下圖所示:

查詢順序如下圖所示:

為了實現最長字首匹配,從最長的掩碼開始匹配,每一個掩碼都有一個雜湊表,目的IP地址雜湊到這些雜湊表的特定的桶中,然後遍歷其衝突連結串列得到最終結果。

     注意,雜湊查詢演算法是基於掩碼的遍歷來實現嚴格的最長字首匹配的,也就是說如果一條最終將要通過預設閘道器發出的資料報,它起碼要匹配32次才能得到結果。

這種方式十分類似於傳統的Netfilter的filter表的過濾方式-一個一個嘗試匹配,而不像HiPac的過濾方式,是基於查詢的。接下來我們會看到,高效能的路由器在查詢路由的時候使用的都是基於查詢型資料結構的方式,最常用的就是查詢樹了。

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,最後變成下面的形狀:

一個節點,如果它只有兩個節點且左右節點都存在,用兩個子節點代替這個節點,如果節點的兩個節點都為葉子節點,則停止替換。這個替換可在子樹中進行重複。