前言ubuntu
熟悉這款設備的同窗,應該也快到不惑之年了吧!這應該是Cisco最古老的路由器了。上個世紀80年代至今,路由交換技術不斷髮展,可是在這波瀾壯闊的變化之中,總有一些東西在嘈雜的機房內閃閃發光,像極了工程師的頭頂,充滿了智慧!cookie
Cisco「古董」路由器網絡
本文主要描述了一種將三層路由變成二層交換轉發(以及二層轉發變成三層路由)的實現方式,以應對OVS(OpenFlow)跨網段路由複雜的問題;固然技術自己是客觀的,具體應用還要看場景。分佈式
隨着SDN技術不斷「發展」,玩路由器交換機的變成了「傳統網工」,搞控制器、轉發器的纔算是正常工做,固然任何新技術的掌握都離開對「歷史」瞭解或者反芻;也許幾年之後當有人聽到一條一條的配置ACL、配置路由表是一件很難以想象的事情,由於那時全部的配置都是控制器作好模型生成配置自動下發的,點點鼠標或者寫個py腳本就能夠了性能
傳統的路由交換機學習
OK,言歸正傳,咱們先來了解一下傳統路由、交換的區別:接口
交換: 通常指的是同網段內分組包的轉發,轉發依據:MAC地址ip
PC視角:當兩臺主機在同一個網段,PC1須要訪問PC2時,PC1首先會發送arp請求報文,請求PC2的的MAC地址;收到響應後,PC1會把PC2的MAC地址封裝在分組包的目的MAC的位置,而後將分組報文扔給交換機;PC2也會作相似的動做。路由
交換機視角:交換機會接收網段上的全部數據幀;利用接收數據幀中的源MAC地址來創建MAC地址表(源地址自學習),使用地址老化機制進行地址表維護。MAC地址表中查找數據幀中的目的MAC地址,若是找到就將該數據幀發送到相應的端口,若是找不到,就向除入端口之外的全部的端口發送;向全部端口轉發廣播幀和多播幀。it
路由:通常指不一樣網段的數據包的轉發,轉發依據:IP路由
PC視角:當兩臺主機在不一樣的網段,PC1須要訪問PC2時,PC1首先會在本身的路由表內查詢PC2的IP地址對應的下一跳(通常默認是網關)地址,而後再去發送ARP報文,請求該下一跳對應的MAC地址;收到響應後,PC1會把該MAC地址封裝在數據包的目的MAC的位置(注意此時的目的IP還是PC2的IP地址,而不是下一跳IP),而後將數據報文扔給路由器;PC2也會作相似的動做。
路由器視角:當路由器收到一個IP數據包,路由器就會找出數據包的三層包頭中的目的IP地址,而後拿着目的IP地址到本身的路由表中進行查詢,找到「最匹配」的路由條目後,將數據包根據路由條目所指示的出接口或者下一跳IP轉發出去,這就是IP路由(固然路由器還會作一些額外的工做:將數據包的三層包頭的TTL減一,修改數據包的二層源MAC地址爲本身出接口的MAC,修改數據包的二層目的MAC地址爲下一跳的MAC);而每一臺路由器都會在本地維護一個路由表(Routing Table),路由表中裝在着路由器獲知的路由條目,路由條目由路由前綴(路由所關聯的目的地址)、路由信息的來源、出接口或者下一跳IP等元素構成;路由器經過靜態配置或者動態的方式獲取路由條目並維護本身的路由表。
OpenFlow的出現
當OpenFlow出現之後,路由器、交換機統一變成了轉發器,轉發依據:流表
OK,咱們先看一下流表長啥樣:
root@ubuntu:~# ovs-ofctl dump-flows br2
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=16080.313s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=200,arp,arp_tpa=2.2.2.0/24 actions=output:100
cookie=0x0, duration=15964.186s, table=0, n_packets=1, n_bytes=42, idle_age=15691, priority=100,arp,arp_tpa=1.1.1.0/24 actions=output:1
cookie=0x0, duration=15985.113s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=200,icmp,nw_dst=2.2.2.0/24 actions=output:100
cookie=0x0, duration=15802.910s, table=0, n_packets=5, n_bytes=490, idle_age=15692, priority=100,icmp,nw_dst=1.1.1.0/24 actions=output:1
固然有人稱流表爲ACL,這也能夠理解,都有着強大的匹配域以及Action,流表的Pipeline能夠算是其特點(性能暫時先不care);到此爲止,MAC表、路由表在轉發器上面已經通通看不到了,你能看到只有上面的流表。
就OVS來講,若是把Bridge配置成Secure模式,默認是沒有什麼流表的;若是如今咱們把OVS配置成一臺普通的傳統二層交換機,只須要增長几條關於ARP、ICMP的流表,就能夠Ping通了(能夠參考以上示例),這仍是比較簡單的。
固然可能有些人說還有更簡單的:只需把Bridge配置Standalone模式或者增長一條默認action=NORMAL的流表就能夠了。可是若是這樣的話,全部的流量又回到傳統的二層三層轉發去了,做爲新時代的OVS,這符合個人個性啊,若是這樣的話,這活仍是交給Linux Bridge來幹吧。
可是問題來了,若是把OVS配置成一臺有路由器功能的轉發器,這就比較困難了;由於經過上文分析路由轉發過程相對來講仍是比較複雜的,須要作的工做以下:
須要一個相似網關的設備(Device),來響應ARP請求:固然能夠在新增OVS時自動生成的設備上配置網關地址,也能夠增長單獨的設備專門做爲網關。
須要修改數據包的二層源目MAC地址以及三層包頭的TTL:由於路由是逐跳轉發的,每一跳都須要作這些工做,即便是如今經過流錶轉發,中間的轉發器直接轉發報文,到達倒數第一跳的時候仍是須要把數據包的目的MAC地址修改成接受端的MAC地址。
一切皆交換的世界
在OpenFlow的世界全部的網絡設備都是轉發器或者稱爲交換機,執行簡單的轉發轉發動做; OK,那咱們能不能將跨網段訪問的路由轉發變換成普通的二層轉發呢?答案是YES!
下面咱們經過一個示例來實現這個想法:
首先咱們要解決的第一個問題就是網關的問題:如何取消對網關的ARP請求?這個在Linux平臺下並非一件難事,只需一條命令:
root@ubuntu:~# ip route add 0.0.0.0/0 dev eth0 scope link
(同時注意arp_ignore須要是0或1)
Link路由是能夠直接arp目標地址的,而不是arp下一跳地址。意思就是說,目標地址是屬於跟本地直連的二層鏈路上,不跨三層。既然是不跨三層的鏈路,arp就能夠暢行無阻,而標準中又沒有規定arp協議包的請求源和請求目標必須是同一個網段的地址(甚至都沒有掩碼約束),因此說,一個如下的arp請求是有效的:
驗證獲得了響應:
細心的童鞋能夠發現上面的命令實際上解決了咱們的兩個問題,網關的問題解決了,另外因爲源主機直接請求目的主機的MAC地址,因此封裝的時候也直接封裝了目的主機的MAC,省去了咱們在倒數第一跳修改數據包的目的MAC爲目的主機的工做。
最後剩下一個問題就是防環的TTL的問題,這個處理起來也比較簡單一些,咱們能夠在流表中加入actions=dec_ttl(1), output:100,在每一跳中自動減少TTL。
而後在接收端的PC上面作相似的操做,中間的OVS添加相關ARP以及業務流的流表,就實現了跨網段的「交換」。
Little Tips
經過以上描述,已經實現了跨網段的路由向交換的轉換,另外也能夠實現所謂二層交換向路由的轉換,好比10.0.0.100/24 訪問10.0.0.200/24,按照咱們的想固然是應該走二層轉發的,也就是直接請求目的主機的MAC地址,而後封裝、發送;
可是因爲種種緣由,目的主機10.0.0.200/24可能跟源主機是跨三層網絡的,那如今怎麼辦呢?OK,能夠在源主機上面增長一條明細路由把10.0.0.200/24指向默認網關,在目的主機上面增長一條明細路由把10.0.0.100/24指向默認網關,而後再ping一下,有木有看到本身的嘴角上揚呢!
交換機本就應該作二層轉發的事情,其餘的分佈式出去吧!