1. 程式人生 > >思科VPP原始碼分析(路由框架分析一)

思科VPP原始碼分析(路由框架分析一)

基本概念

VPP作為思科開源專案,路由系統基本繼承了Cisco快速轉發(Cisco Express Forwarding,CEF)設計思路。作為理解VPP路由原始碼第一步,首先要掌握起理論基礎。

在前面章節的討論中,雖然基於快取的交換機制相對程序交換而言提高了轉發的效能,但是它們的效能是不確定的。程序交換和基於快取的交換都是資料驅動的(data-driven),或者說是需求驅動的(demand-driven)。換句話說,只有當資料包進入路由器的時候交換元件才會被佈置到位,一旦這些資料包不被路由器轉發,交換元件就會被清除。如果存在大量的不可預知流量模式的資料包,交換效能就會顯著地下降。顯然,在Internet的級別上,這些交換路線是不可擴充套件的。

建立CEF是為了避免基於快取交換機制所固有的問題。它的設計最好地適應了頻繁變化的網路態勢和流量特徵,這些都是由於不斷增長的較短持續時間的流所產生的。典型地,這些較短持續時間的流與基於Web的應用和互動式TCP會話相關聯。

CEF具有以下幾個優點:

可擴充套件性(Scalability)——CEF是拓撲驅動的(topology-driven),並與路由選擇表緊密相關。當激活了分散式CEF(Distributed CEF)模式時,CEF在每一塊線卡(line card)上也提供了全部的交換能力。CEF支援硬體輔助的(hardware-assisted)轉發方式,這是在高容量的線卡上,提供線速交換(line rate switching)能力所必需的。
增強的效能——CEF的CPU密集程度比路由快取機制的CPU密集程度低。更多的CPU處理能力可以專注於第3層服務,例如,處理BGP更新。
彈性(Resilience)——在大型動態網路中,CEF提供了更好的交換一致性和穩定性。在這樣一些網路中,由於路由選擇的變化,快速交換快取表項會頻繁地失效。這些變化導致路由器使用路由選擇表程序交換流量,而不是使用路由快取快速交換流量。由於CEF查詢表包含了存在於路由選擇表中所有已知的路由,因此它消除了路由快取的維護需要,並使快速交換/程序交換轉發不再適用。CEF能夠比典型的按需快取機制更有效地交換流量。
注意:

IP RIB中所有路由的表項不管是否被使用,它們都需要被維護,因而CEF可能比其他交換方式需要更多的記憶體。
CEF是拓撲驅動的交換機制,它的轉發表和路由選擇表是緊密關聯的。無論何時路由選擇表發生變化,CEF轉發表也將被更新。在表項被建立的時候,資料包被交換到更慢的交換路線上。CEF把路由快取的功能分割成兩部分:

轉發資訊庫(Forwarding Information Base,FIB);
鄰接表(ajdancency table)。
1.FIB
FIB包含了來自於路由選擇表的所有IP字首。如果不同的路由選擇表被維護著,例如在MPLS VPN環境中,那麼每個VPN都有自己的FIB。FIB不是資料驅動的。更確切地說,它是通過路由選擇表來建立和更新的。FIB子系統負責確保所有的遞迴路由(是指那些沒有與直接下一跳相聯絡的路由)被解析。

為了增強一致性和減少查詢時間,FIB被組織成一個被稱為mtrie的多路(multiway)資料結構。在mtrie資料結構中,樹結構用來定位所要找的資料,但是資料本身儲存在其他地方。相反,mtree資料結構在樹結構本身中儲存了實際的資料。例如,在最優交換的mtree快取中,用來轉發資料包的MAC頭的資料就是實際儲存於mtree中的。

Cisco路由器通常使用兩種型別的mtrie結構:

8-8-8-8——這種格式也被稱為256-way mtrie,因為4個八位組的IPv4地址被對映到4個8bit的結構中。因此,一條字首的最大查詢次數是4次。這種格式用在大多數Cisco路由器中。
16-8-8——這是一個3級的mtrie,它的根級有65536個表項。因此,一條字首的最大查詢次數是3次。換句話說,第一次查詢解析了前面的兩個八位組,接著最多再需要2次查詢就可以解析最後的兩個八位組。這種格式只用於Cisco 12000系列路由器。
mtrie的每一級都被稱為一個節點(node)。最後的節點被稱為葉節點(leaf)。葉節點指向鄰接表(adjacency table),或者當到達相同目的地的多條路徑存在時,指向另一個負載分擔的結構。IP FIB的內容可以使用show ip cef命令來顯示。

下面列舉了一些FIB表項:

附接的(attached)——這種字首被配置為可以通過介面直接到達,不需要由IP下一跳來建立鄰接關係。這種字首是指路由器本地介面所屬的網路。
連線的(connected)——這種介面是由IP addressaddress mask配置命令來配置的。所有連線的FIB表項都是附接的,但不是所有附接的表項都是連線的。
收到(receive)——這種字首是一個32位掩碼的主機地址,它是路由器始終接收到的主機地址之一。每個介面通常有3種這樣的地址:實際的介面地址、全0的子網和全1的廣播地址。(博主理解為就是本機local地址)
遞迴的(recursive)——當前綴的輸出介面不能通過路由選擇協議或靜態配置指定時,它就被標記為遞迴的。當找不到遞迴FIB表項的下一跳IP地址時,這個遞迴FIB表項也許就不能被解析。因此,遞迴標記實際上與下一跳地址,而不是與FIB表項相關聯。
2.鄰接表
鄰接表被建立,以包含所有連線的下一跳地址。鄰接節點(adjacency node)是指通過鏈路層一跳就可以到達的節點。一旦鄰居變成了鄰接的關係,用來到達那個鄰居的鏈路層幀頭——被稱為MAC字串或者MAC改寫字串——就會被建立,並且被儲存在鄰接表中。例如,在乙太網段上,幀頭資訊就是目的地MAC地址、源MAC地址和以太型別(EtherType),並按乙太網的定義來排列。

例2-6顯示了乙太網的MAC頭。在這個例子中,00044EB31838是目的地MAC地址,0003E4BB2000是源MAC地址,0800是IP的以太型別。

一旦路由被解析,它就會指向一個鄰接的下一跳地址。如果在鄰接表中發現了一個鄰接,那麼與這個鄰接相對應的一個指標就會被快取到FIB單元中。如果存在到達相同目的地的多條路徑(也就是說,存在多個下一跳或者鄰接),那麼每一個鄰接的指標都會被增添到負載分擔的結構中去。在CEF中,基於每資料包的負載分擔在中斷級別上是有用的。

除了上述情況,還存在幾種異常鄰接的型別。當前綴被增加到FIB表中時,需要異常處理(exception handling)的字首被快取為特殊的鄰接。下面列舉了一些特殊的鄰接:

Null——這種鄰接針對那些指向Null 0介面的、要被丟棄的資料包。
Glean——這種鄰接針對那些通過廣播網路附接的目的地,但是其廣播網路又沒有對應可用的MAC改寫字串。可以設想路由器直連到一個包含幾臺主機的子網的情形。路由器的FIB表維護著這個子網的字首,而不是單個的主機字首。這個子網字首就指向一個glean鄰接。當資料包需要被轉發到一臺特定的主機時,為這個特定的字首就需要收集(glean)鄰接資料庫。這將導致額外的查詢成本。(博主理解為,就是同一個網路中的主機,目前mac地址不知道,所以用glean表項標記其連線表項,然後再由arp協議來填充)
Punt——如果資料包不被CEF支援,那麼它們就會被轉發給下一級慢速的交換路線來處理。
Drop——是指要丟棄這種資料包,因為這些資料包不能被CEF交換,或者不能被踢給(punt)其他交換路線處理。
Discard——類似於Drop鄰接,但是隻應用於Cisco 12000系列路由器。
圖2-5中顯示了CEF的所有元件之間的關聯關係。

這裡寫圖片描述

- 256-way mtrie