SDN下的ARP
相信不少兄弟的SDN啟蒙都是各種高大上的論文中五花八門的概念和應用,等到真把開源控制器和mininet裝好,要開始干活了,才發現什么traffic engineering, 什么consistent update,根本不是那么回事兒。大家要處理的***個包甚至都不是TCP,而是ARP,而且還是廣播!這里有兄弟可能會想到DHCP,LLDP,甚至會想到IPv6的鄰居發現,博主會在以后的文章中詳細討論它們,這次只講ARP。
SDN控制器管理的是由一些交換機(包括OVS和物理交換機)構成的網絡而不是網絡邊緣的服務器(包括bare metal server和vm),但是SDN控制器在proactive的編輯各種表的時候又需要知道服務器在網絡當中的位置。ARP幾乎成為***的甚至是唯一的獲取這些信息的渠道(IPv6鄰居發現是另外一個話題),因為從ARP我們至少可以學到兩件事情:***,每一個mac究竟出現在網絡中哪臺交換機的哪個端口。第二,每一個mac上究竟有哪些IP地址。
也許有兄弟會問:我們可以通過服務器發出的任何二層或者三層的報文來學到這兩件事情,為什么一定是ARP呢?答案有三:首先,既然ARP是每一臺服務器發出的幾乎***個報文,我們為什么不直接從這個報文中學到以上的信息呢?既然做proactive的SDN,那就應該在***時間學習網絡中服務器的位置。其次,如果我們的SDN網絡連ARP都沒有處理好,服務器都沒法收到ARP reply,那么也就沒有后面的其他報文了。第三,也是最重要的原因:我們其實并不知道網絡邊緣的服務器是什么設備,它可能是一個一般意義上的服務器,也可能是一個防火墻,或者是一個第三方的路由器。如果我們在SDN網絡邊緣看到了一個三層的報文,并且簡單的認為這個報文的src mac和src IP來自同樣一臺服務器,那么就錯大了。
我們不妨拿傳統的交換機和SDN控制器管理的網絡做個類比。在傳統的交換機上,mac learning是一個非常簡單的過程:我在port1上看到了mac1,那么交換機就有了一個二層的表項:到mac1走port1。在SDN的世界里,并沒有什么本質的不同:我們在switch1 port1上看到了mac1,那么到mac1就走switch1 port1。唯一的不同是:傳統交換機的學習就發生在交換機上。而在SDN的世界里,學習發生在SDN控制器里(有人稱之為centralized mac learning),因為控制器一定要知道它管理的這個網絡究竟連接了一些什么mac/IP,才能proactive的編輯整個SDN網絡的流表。一種比較常見的方式是:交換機把ARP request/reply以packet-in的形式發給控制器,控制器便學習到了mac, vlan, IP, 交換機和端口之間的關系。在開源的floodlight里有一個類似的例子,在所有其他開源的控制器里,也都有類似的例子。
講到這里,做OpenStack/CloudStack的兄弟們會仰天大笑:太老土了吧,還centralized mac learning?有了orchestration之后,網絡中所有vm的一切信息在***時間已經被控制器知道了!此言不假,但有兩個問題:***,如果有人沒有部署orchestration而只用物理服務器怎么辦?其實,對于SDN網絡而言,orchestration也是某種意義上的mac learning,只不過這個learnning沒有通過ARP。
第二個問題則更加重要,無論SDN控制器用何種方式學到mac/IP在網絡中的位置,這僅僅是***步,接下來的問題是:怎樣回復服務器發出的ARP request? 這個問題是SDN系統設計的一個挑戰,并且這個挑戰會隨著系統feature的不斷豐富,一次又一次的出現。接下來博主主要會從L2和L3兩個方面分析一下這個問題可能的解法,歡迎大家查漏補缺。
如果source和destination處于一個subnet,這是一個純二層的問題。有兩種極端的解法。
極端解法一:讓SDN控制器回復所有的ARP request。既然SDN控制器已經通過orchestration或者ARP packet-in的方式學習到了網絡中的mac,那么只要將所有ARP request都以packet-in的形式發送到控制器,控制器就完全有能力將ARP reply通過packet-out的方式回復給source。
這種極端做法顯而易見的缺點是:過多的ARP request會讓SDN控制器應接不暇,成為潛在的安全隱患。于是,不少SDN廠家在這種方案的基礎上進行了改進,一種改進的思路是:既然控制器上有一個大表記錄著網絡中所有IP到mac的映射,那么我們就可以在所有網絡邊緣交換機上把這個表cache下來,這樣,當交換機再次收到ARP request的時候,就可以通過查找這個表直接回復相應的ARP reply,而不需要廣播。
以上這個改進確實是個可行的方案,但是有兩個前提:1)用戶不在乎高可靠性(high availability),2)一定要部署在有orchestration的環境當中。但這兩個大大的前提往往會讓相當一部分客戶止步。首先如果source和destination都好好的,但是SDN控制器宕了,于是最基本的ARP便無法正常工作,這是一件讓任何客戶都很難接受的事情。其次,在沒有orchestration的環境當中,有些服務器是不主動說話的(silent server),也就是說在silent server發出***個ARP之前,控制器根本沒有機會得知它的存在。在這種情況下,SDN網絡必須要能夠正確的廣播ARP request,當SDN網絡收到silent server的ARP reply之后,還要能夠正確的將其轉發。
極端解法二:在一個廣播域中廣播ARP request。既然極端解法一并不適用于所有的情形,那么我們便很自然的想到了另外一個極端解法,索性廣播ARP request吧,該誰回復ARP reply就讓誰回復。這樣做有幾個好處,首先是SDN網絡中ARP的行為和傳統二層交換中ARP的行為是一致的。客戶在destination打開tcpdump會看到ARP request。而在之前的方案中,destination是看不到ARP request的。單就這一點,在向客戶解釋說明的時候就省了好多事。第二個好處是即便控制器宕了,只要source和destination還在,ARP就能工作。第三個好處是這個方案解決了silent server的問題,只要廣播處理的正確,silent server就能夠收到ARP request并回復ARP reply。
當然這個方案的代價也很大,就是要正確的處理廣播。如果僅僅是二層網絡,我們可以用spanning tree,用SDN控制器計算spanning tree是一件麻煩但能夠做到的事情。如果是二層被三層隔離,就需要打隧道了。以vxlan為例,最初vxlan要求在underlay網絡中部署IP multicast來處理ARP,沒有人愿意,于是才有了后來的unicast-only vxlan。
博主把極端解法二稱為“種樹”:從本質上來講,SDN控制器其實在為每一個廣播域種一棵沒有環的樹,好讓ARP在這棵樹上廣播。如何高效的“種樹”是真正體現各個廠家硬實力的地方,不管是用spanning tree在二層種樹,打隧道在三層種樹還是其他方法,這棵樹都必須要做到:無論任何網絡拓撲或者任何網絡事件,有且只有一個廣播報文到達廣播域中的各個服務器。
分析到這里,博主已經把當source和destination在一個subnet時,處理ARP的種種考慮走馬觀花的討論了一遍。博主才疏學淺,但在博主知識范圍內的ARP解決方案基本就是在以上兩個極端之間找一個折中并做一定的創新。
討論完source和destination處于同一個subnet的情況,我們來看一下兩者處于不同subnet的情況,這時我們需要考慮兩個問題。
問題一:誰是default gateway?
傳統網絡中,二層三層的界限往往非常清晰,二三層分界的地方就是default gateway所在的地方。但在seamless vm migration大行其道的今天,二層三層的界限越來越模糊,我們已經很難明確的指出default gateway在網絡當中的位置了,于是常聽人們感嘆:default gateway is everywhere。博主見識有限,到目前為止見到的default gateway大體上會出現在三個地方。
***種情形是網絡中有一個專門的router(可能是硬件也可能是OVS)來做default gateway,這種情形常出現在overlay的解決方案中,比如Juno release之前的neutron reference implementation,比如vxlan L3 gateway。有客戶擔心這種方案的高可靠性,于是人們又在這種方案之上加入了VRRP。
第二種情形是default gateway在SDN控制器上。有些開源的SDN控制器就在采用這種方式。一種常見的邏輯是這樣的:source發出了ARP request問default gateway的mac,交換機把這個ARP request以packet-in的形式告訴控制器,控制器再以packet-out的形式把ARP reply發給source,于是source就知道了default gateway的mac。我知道有兄弟會說:這樣控制器不又成了單點故障和bottleneck了嗎?所以人們在此基礎之上進行了改進,發明了第三種部署default gateway的方式。
這第三種方式就是把default gateway部署在所有的網絡邊緣的交換機上,有人稱之為destributed default gateway。在情形二中,SDN控制器已經掌握了所有subnet的default gateway,我們完全可以把這個信息以某種方式cache/offload到所有的網絡邊緣的交換機上。這樣,這些交換機就可以代替控制器回復所有要default gateway mac的ARP request。
在以上三種方案中,方案一目前來說最常見。方案三在被越來越多的人接受,因為它的優勢實在太明顯了。
問題二:如何處理silent server?
如果沒有部署任何的orchestration system,如果網絡中還有大量的bare metal server,那么silent server帶來的問題就不容忽視。我們設想一下下面這個場景:source和destination處在不同的subnet,并且destination是一個silent server。如果source向destination發了一個ping echo request,由于SDN控制器對destination一無所知,所以網絡中不會有關于destination的任何表項,于是這個echo request被很自然的packet-in到了控制器,此時的控制器又能對這個packet-in做什么呢?
博主目前還沒有看到任何關于這個問題的公開討論。一個最魯莽的辦法就是控制器以packet-out的方式在SDN網絡邊緣的所有端口上發ARP request,要destination IP所對應的mac。如果destination真的接入了我們的網絡,便會回復ARP reply,那時控制器便會學習到destination連接在哪臺交換機的哪個端口,相應的表項便會得到更新。只是這樣一個魯莽的方法代價太大了。如果哪位兄弟有更好的辦法,歡迎提出來大家一起討論。
講到這里,博主已經把SDN系統設計中關于ARP的考量梳理了一遍。不過ARP不會就此罷休。在以后的文章中,博主還會討論到NAT和floating IP,到那時,ARP會卷土重來,給我們制造更多的麻煩。