ovs flow 原理及實驗

OpenFlow概述

在支持OpenFlow的交換機中包含了若干個Flow table,Flow table能夠用來控制數據包的處理,交換機會執行與flow相匹配的表項中所羅列的動做。html

OpenFlow controller經過使用OpenFlow協議來管理交換機,而且controller也能經過使用OpenFlow協議來獲取交換機上的端口、流量的統計信息或其餘情報,並能夠根據這些信息來調整各端口的流量。cookie

交換機中維護的每一個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中每一個條目中包含的字段如上圖所示,其中每一個字段的含義能夠參考下面的表格。spa

每一個Flow table中的條目(表項)都是由Match Fields和Priority兩個字段來共同惟一標識的。3d

 

Group table

一樣的,上圖列出了Group table中每一個條目包含的字段,其含義參考下表:orm

這裏簡單瞭解一下兩張table的結構,至於table中每一個字段的具體含義和用途咱們先不着急去了解,在後面結合具體的流程來更方便的去理解。htm

 

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
相關文章
相關標籤/搜索