ovs flow 原理及實驗
OpenFlow概述
在支持OpenFlow的交換機中包含了若幹個Flow table,Flow table可以用來控制數據包的處理,交換機會執行與flow相匹配的表項中所羅列的動作。
OpenFlow controller通過使用OpenFlow協議來管理交換機,並且controller也能通過使用OpenFlow協議來獲取交換機上的端口、流量的統計信息或其他情報,並可以根據這些信息來調整各端口的流量。
交換機中維護的每個flow table都包含有很多個條目,這些條目會根據自身的一個優先級從高到底進行排序,優先級最高的條目位於flow table的頂部。
當一個數據包進入到交換機時,先和優先級最高的條目進行匹配,如果匹配成功,那麽就停止繼續匹配動作,去執行該條目中的一組action。如果匹配失敗,則按照優先級高低,繼續匹配下一條。如果flow table中所有的條目都不匹配,這個數據包就會被丟棄或發送到控制器(問題:如何決定是丟棄還是發送到控制器)。
OpenFlow協議的版本已經從1.0更新到了1.5,其中為了保證OpenFlow能有一個穩定的發展平臺,把1.0和1.3版本作為其中長期支持的穩定版本。1.0版本功能比較簡單,本次主要學習其中的1.3版本。
Flow Tables介紹
在OpenFlow中用來控制flow的table主要涉及到flow table和group table,先簡單了解一下這兩張table的構成。
Flow table
Flow table中每個條目中包含的字段如上圖所示,其中每個字段的含義可以參考下面的表格。
每個Flow table中的條目(表項)都是由Match Fields和Priority兩個字段來共同唯一標識的。
Group table
同樣的,上圖列出了Group table中每個條目包含的字段,其含義參考下表:
這裏簡單了解一下兩張table的結構,至於table中每個字段的具體含義和用途我們先不著急去了解,在後面結合具體的流程來更方便的去理解。
Pipeline Processing
在了解了上述兩張table後,我們不禁會想:在交換機運行過程中是如何配合這兩張表來實現流量轉發的呢?
這就不得不提到openflow中的一個重要概念:pipeline processing。什麽是pipeline?如果把每個table當成一道加工工藝的話,pipeline就可以看成是一條加工流水線。在這條流水線上,多個flow table按照其數字編號從小到大排列著(table0, table1, table2 …… table N),進入交換機的數據包都是從pipeline的第一個flow table也就是table0開始處理,按照上文描述的那樣,對table0中的條目一條一條開始匹配,如果匹配成功則執行相應的動作(這些動作可能導致從flow table跳到group table中),若果沒有所有條目都沒有成功匹配,則根據table自身的不同配置執行相應的處理(Table Miss Flow Entry):
- drop
- 轉發給下一個table
- 發送給controller
Table Miss Flow Entry是flow table中專門處理沒有成功匹配的數據包的一個條目,它的Match Fields能夠匹配任何數據包,並且Priority為0,也就是會被最後執行。
Table Miss Flow Entry不是必須存在的,當不存在的時候,對沒成功匹配的數據包會執行table中的默認動作。
整個流程形象點的話我們可以通過下面這張圖來理解:
這張圖是我從網絡上復制過來的,相關文章可以在最後的參考鏈接中查看。
在這張圖中我們可以很形象的看到flow table和group table在數據轉發過程中的地位。
在Open vSwitch上的應用
OVS對Open Flow的支持情況
在使用open vswitch來實際應用open flow之前,我們有必要先了解一下ovs目前對openflow協議各版本的支持情況。為此,我在官網找到了如下這張表(2018年4月):
- —: Not supported.
- yes: Supported and enabled by default
- (*): Supported, but missing features, and must be enabled by user.
- (%): Experimental, unsafe implementation.
本文中使用的Open vSwitch版本為2.5.0,默認支持Open Flow 1.3。
操作Open Flow的工具
在實際的環境中,基本上都是由controller來操作修改交換機的open flow。本實驗將通過使用ovs-ofctl工具手動來配置修改OVS交換機的open flow。
ovs-ofctl的使用方法可以參考官方文檔:Open vSwitch Manual : ovs-ofctl
基本實驗環境
環境拓撲
基本實驗環境
環境拓撲
環境構築
# 創建namespace ip netns add ns1 ip netns add ns2 ip netns add ns3 ip netns add ns4 # 創建tap設備 ip link add tap0 type veth peer name tap0_br ip link add tap1 type veth peer name tap1_br ip link add tap2 type veth peer name tap2_br ip link add tap3 type veth peer name tap3_br ip link add tap4 type veth peer name tap4_br ip link add tap5 type veth peer name tap5_br ip link add tap6 type veth peer name tap6_br ip link add tap7 type veth peer name tap7_br # 設置tap設備的namespace ip link set tap0 netns ns1 ip link set tap1 netns ns1 ip link set tap2 netns ns2 ip link set tap3 netns ns2 ip link set tap4 netns ns3 ip link set tap5 netns ns3 ip link set tap6 netns ns4 ip link set tap7 netns ns4 # 創建OVS網橋 ovs-vsctl add-br vswitch0 # 將tap設備另一端綁到網橋 ovs-vsctl add-port vswitch0 tap0_br ovs-vsctl add-port vswitch0 tap1_br ovs-vsctl add-port vswitch0 tap2_br ovs-vsctl add-port vswitch0 tap3_br ovs-vsctl add-port vswitch0 tap4_br ovs-vsctl add-port vswitch0 tap5_br ovs-vsctl add-port vswitch0 tap6_br ovs-vsctl add-port vswitch0 tap7_br
實驗一(單個table及驗證其flow的優先級)
實驗準備
環境配置
# 啟動tap0和tap3及它們的對端 ip netns exec ns1 ip link set tap0 up ip netns exec ns2 ip link set tap3 up ip link set tap0_br up ip link set tap3_br up # 設置tap0和tap3的ip地址 ip netns exec ns1 ip addr add 192.168.1.100 dev tap0 ip netns exec ns2 ip addr add 192.168.1.200 dev tap3 # 配置路由 ip netns exec ns1 route add -net 192.168.1.0 netmask 255.255.255.0 dev tap0 ip netns exec ns2 route add -net 192.168.1.0 netmask 255.255.255.0 dev tap3 # 測試網絡連通性 ip netns exec ns1 ping 192.168.1.200 >> 64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.030 ms >> 64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.055 ms
查看tap設備對應的ovs port
# ovs-vsctl list interface tap0_br | grep "ofport " ofport : 1 # ovs-vsctl list interface tap3_br | grep "ofport " ofport : 4
實驗過程
首先查看一下vswitch0上的flow table:
# ovs-ofctl dump-flows vswitch0 cookie=0x0, duration=267197.837s, table=0, n_packets=459, n_bytes=42190, idle_age=387, hard_age=65534, priority=0 actions=NORMAL
發現有一條actions為NORMAL的流表項,這是默認存在的,用以實現交換機的基本動作。
當我們把這條flow刪除後發現兩個tap設備之間已無法ping通:
# ovs-ofctl del-flows vswitch0 # ovs-ofctl dump-flows vswitch0 NXST_FLOW reply (xid=0x4): # ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. ^C --- 192.168.1.200 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2052ms
簡單的講,如果要實現tap0和tap3之間流量互通,其實就是要交換機將port1上的數據發往port4,port4上的數據發往port1(port1和port4分別是tap0和tap3對應的ovs端口,查看方法見上),所以我們可以添加下面兩條flow:
# ovs-ofctl add-flow vswitch0 "priority=1,in_port=1,actions=output:4" # ovs-ofctl add-flow vswitch0 "priority=2,in_port=4,actions=output:1"
當添加完這兩條flow後發現tap0和tap3之間又能相互ping通了
# ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. 64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.396 ms 64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.050 ms ^C --- 192.168.1.200 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1030ms rtt min/avg/max/mdev = 0.050/0.223/0.396/0.173 ms
可以看到我們給這兩個flow設置了優先級分別是1和2,根據上文所講,flow優先級越高,會優先匹配,所以我們再增加下面的flow來測試:
ovs-ofctl add-flow vswitch0 "priority=3,in_port=1,actions=drop"
這條flow是將所有從port1上的數據全部drop掉,如果成功匹配,則tap0和tap3將不再互通。
# ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. ^C --- 192.168.1.200 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2057ms
發現果然ping不通了,這就驗證了上文的描述:優先級越高,優先匹配。
實驗二(多個table)
在實驗一的基礎上繼續往下做。
首先清除所有的flow,重新開始配置
# ovs-ofctl del-flows vswitch0
還記得轉發的兩條flow嗎?在實驗一中我們配置到了table0,現在將他們配置到table1
# ovs-ofctl add-flow vswitch0 "table=1,priority=1,in_port=1,actions=output:4" # ovs-ofctl add-flow vswitch0 "table=1,priority=2,in_port=4,actions=output:1" # ovs-ofctl dump-flows vswitch0 NXST_FLOW reply (xid=0x4): cookie=0x0, duration=3.485s, table=1, n_packets=0, n_bytes=0, idle_age=3, priority=1,in_port=1 actions=output:4 cookie=0x0, duration=3.033s, table=1, n_packets=0, n_bytes=0, idle_age=3, priority=2,in_port=4 actions=output:1
嘗試ping對端設備,發現無法ping通,因為數據包從table0開始處理,當前table0中沒有匹配的flow,所以數據包被drop掉了。
# ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. ^C --- 192.168.1.200 ping statistics --- 3 packets transmitted, 0 received, 100% packet loss, time 2026ms
現在給table0加上一條將數據包發送到table1處理的flow
# ovs-ofctl add-flow vswitch0 "table=0,actions=goto_table=1"
再次嘗試ping對端的設備,可以正常ping通
# ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. 64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.309 ms 64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.050 ms ^C --- 192.168.1.200 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1054ms rtt min/avg/max/mdev = 0.050/0.179/0.309/0.130 ms
實驗三(group table)
繼續使用這個環境,第一步還是清除所有的flow
# ovs-ofctl del-flows vswitch0
查看交換機上存在的group表,發現當前沒有任何group table。
# ovs-ofctl -O OpenFlow13 dump-groups vswitch0 OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):
我們計劃讓數據包從table0發送到group table處理,再發送到table1處理。
# ovs-ofctl -O OpenFlow13 add-group vswitch0 "group_id=1,type=select,bucket=resubmit(,1)" # ovs-ofctl -O OpenFlow13 dump-groups vswitch0 OFPST_GROUP_DESC reply (OF1.3) (xid=0x2): group_id=1,type=select,bucket=actions=resubmit(,1)
在table0中增加兩條flow,目的是將數據包發送到group table1
# ovs-ofctl -O OpenFlow13 add-flow vswitch0 "table=0,in_port=1,actions=group:1" # ovs-ofctl -O OpenFlow13 add-flow vswitch0 "table=0,in_port=4,actions=group:1"
向table1中增加兩條flow,真正的數據轉發在table1中進行。
# ovs-ofctl add-flow vswitch0 "table=1,priority=1,in_port=1,actions=output:4" # ovs-ofctl add-flow vswitch0 "table=1,priority=2,in_port=4,actions=output:1"
嘗試ping對端,可以成功ping通,說明數據包被正確處理。
# ip netns exec ns1 ping 192.168.1.200 PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data. 64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=0.329 ms 64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=0.048 ms ^C --- 192.168.1.200 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1048ms rtt min/avg/max/mdev = 0.048/0.188/0.329/0.141 ms
ovs flow 原理及實驗