1. 程式人生 > >硬體路由轉發原理淺析

硬體路由轉發原理淺析

                有人問我,對於路由轉發,硬體轉發表的效能真的要超出軟體查表比如Linux系統很多嗎?
我怎麼回答呢?給出資料嗎?我沒有資料,因為我的本職不是做這一塊的。給出理論嗎?恐怕我也沒那口才。畫個圖?我發現我係統沒有安裝畫邏輯電路的工具。那怎麼辦?這個問題的答案我真真在心裡,只是難於言表,於是乎,我採用手繪圖手機拍照的方式,展示一下硬體轉發表的威力,由於沒有實際資料,我採用相對比較的方式,讓諸位看一下軟體轉發為什麼是個垃圾。也順便介紹一下專業的路由器交換機是怎麼轉發資料包的。
       不過,手繪圖實在是不敢恭維,所以我就照著手繪圖用viso畫了一個。

我是一個送貨修路的

人生有多少十年?
我想成為一名送貨的,修路的。我送的是IP資料報,修的是全光網路。
如今是一個浮躁的年代,大家都在爭先恐後往食物鏈頂端爬,搞什麼Android app,iOS什麼的,而我始終在我自己感興趣的領域,一混就是10年!而這個領域,就是食物鏈的底端。

開始前的宣告

我假設你已經知道了基本的閘電路的工作原理,比如與門,非門,或門,鎖存器,電容儲存單元,儲存陣列等基本概念。接下來我用這些門來展示一下一個資料包實際的路由查詢過程到底是個什麼樣子。在繼續閱讀之前請注意,
對於專家:本文不適合你,因為這是我自己想的,我為初學者著想,沒有遵循CAM,TCAM的規範,空間利用也不好,總之,跟你想象中的相比,我的做法很垃圾。
對於不知情者:本文十分適合你,可以讓你瞬間體會精髓,這也是我的心願。

step by step

首先給出一幅圖:


給定一個目標IPv4地址,經過幾個門就可以找到下一跳的索引,是不是很奇妙啊。事實上真的就是這樣。
       如果你仔細看這個圖的話,你可能會發現,這有什麼了不起的啊,你的譯碼器譯碼的是32bit的地址,也就是說32位的全集,4G個地址,每一個字首都必須有4G個entry的空間,這可怎能受得了啊,但是我要說的是,這裡僅僅給出一個例子,我當然知道用N路組相連的方式來組織,但是那樣會加入一些比較閘電路,不直觀,所以我就直接用32位地址鍵了。也許你還會反駁,即便用軟體,我建立一個4G大小的hash表,用IPv4地址本身作為hash值,不更加簡單嗎?不比硬體實現更加優化嗎?我想說的是,NO!Why?請看一個CPU cache的普通命中過程,以下是圖示:


跟一個IPv4地址路由查詢過程相比,少不了幾個門。注意,這只是在訪存之前的cache匹配的閘電路,這還算是比較高效的,如果沒有命中,訪存的電路涉及到的電路自不必說,單單是CPU的執行單元這些電路就夠了,如果你瞭解微結構,那你就會知道,一條指令的執行也是一個極其複雜的過程,CPU內部有通用執行單元,流水線等,每一個步驟都是要花費時鐘週期的,那麼請問,以下的程式碼需要多少閘電路呢?
entry = bucket[destIP];
nexthop = entry->nexthop;
先把它翻譯成彙編然後再看吧。更何況,你不可能建立一個如此龐大的hash表,常規的看,TRIE樹查詢法算是高效的了,比它更高效的是我自己的DxR Pro++結構,但是即便是DxR Pro++,和上述的硬體轉發相比,也是弱爆了的了。
       繼續看上面的硬體路由轉發原理圖,譯碼器後面的交叉網路事實上應該畫成黑盒子更加清爽些,但是我還是情不自禁地畫成了不倫不類的樣子,每一個交叉點上都存著1bit的資料,它非0即1。譯碼器譯碼的結果選擇一根字線,然後該字線上的所有與之交叉的位線由於字線電平拉高,交叉點上的1bit資料就稀里嘩啦掉下來了,這其實也是記憶體訪問的原理。在第一個譯碼器後面,有一個比較重要的操作,那就是“最長字首”的邏輯,我不知道標準的TCAM是怎麼做的,但是我覺得我的上述的方式也能說明問題。引入了兩個概念,反掩碼和消除位,其中反掩碼是掩碼按位取反的結果,而消除位是為了唯一取得匹配到的“最長字首”那一項的。最終,我們得到了匹配到的最長字首的那一項對應的下一跳索引地址,然後再來一個譯碼過程,通過地址得到下一跳索引,取得勝利。
       注意,所有的操作都是同時進行的,在匹配28位字首的同時,24位,16位,10位,8位字首也在同步匹配,它們同時經過同一組門。這就是優勢!

硬體轉發和CPU轉發

我們發現,上面我描述的那個電路幾乎不能幹別的,它只能為一個IPv4地址查詢下一跳(當然還有寫入,刪除等電路邏輯,我沒有畫出來),然而就是這樣一個電路,比CPU那個複雜的東西效率高多了,所謂它是專業的,而CPU只是通用的。
       CPU作為一個通用執行單元,它完全是傻瓜的,卻又什麼都能做,具體要做什麼,是通過從記憶體中獲取的“指令”來指示的,也就是說,指令本身就是資料的一種表現形式,程式設計的本質是什麼?程式設計的本質就是從記憶體中獲取的指令對CPU內部電路的程式設計。
       然而,對於硬體轉發而言,它的輸入是一個IPv4地址,純粹一個數據!它沒有指令,指令就是電路本身。所以,它可以同時進行這一切,就好像這條“指令”是從外部輸入的一樣。CPU不能執行這樣的“指令”是因為這個指令它特殊了,現代處理器越來越多地向RISC發展,由程式設計師和編譯器自己完全來決定要做什麼,而不是處理器的設計者猜測程式設計師會用到什麼功能那樣子。我可以想得極端一點,如果在一款CISC處理器中,它為了對得起它的分類,它的設計者為其設計了一條“路由查詢”的指令,那麼該通過CISC處理器內部的電路,真的有可能跟我上面的這個差不多。
       眼睛有點睜不開了....