OpenFlow(OF)被認爲是第一個 軟件定義網絡(SDN)標準之一。它最初在SDN環境中定義了通訊協議,使SDN控制器可以與物理和虛擬的交換機和路由器等網絡設備的轉發平面直接進行交互,從而更好地適應不斷變化的業務需求。
若是把OpenFlow控制器比做「大腦」,OVS流表就像是「大腿」同樣接受來自「大腦」的指令,決定要向哪一個方向前進。但OVS流表功能更增強大,在沒有OpenFlow控制器時,也能夠自主工做,它自己也供一些命令讓咱們能夠直接管理流表。算法
# 查看br-tun上的所有流表規則 ovs-ofctl dump-flows br-tun
ovs-ofctl add−flow/add−flows/mod−flows 「流表匹配條件,actions=[動做1][,動做2…]」
若是你有過編程的經驗,流表規則其實就是一個個簡單的if
語句,僞代碼以下。編程
if (流表匹配條件){ 動做1, 動做2... } if (流表匹配條件){ 動做1, 動做2... }
# 刪除br-tun上的所有流表規則 ovs-ofctl del-flows br-tun # 刪除br-tun上匹配xx的所有流表規則 ovs-ofctl del-flows br-tun xx
OVS 流表匹配條件較多,下面我將其分紅四部分來講明,分別是:bash
流量進入的端口編號或者名稱,示例 in_port=br-int
網絡
規則保存的流表編號,範圍是 0-254,默認值:0。tcp
dl
便是 data link
的縮寫。spa
匹配以太網協議類型以太類型,以10到65535之間的整數(包括0和65535)指定,以十進制或以0x前綴的十六進制數表示,示例以下。設計
dl_type=0x0800
匹配IPv4數據包,等同於dl_type=ip
。dl_type=0x086dd
匹配IPv6數據包,等同於dl_type=ipv6
。dl_type=0x0806
匹配ARP數據包,等同於dl_type=arp
。dl_type=0x8035
匹配RARP數據包,等同於 dl_type=rarp
。數據包的 VLAN Tag 值,範圍是 0-4095,0xffff
表明不包含 VLAN Tag 的數據包指針
VLAN 優先級,取值區間爲[0-7]。數字越大,表示優先級越高。code
源或目的的 MAC地址orm
01:00:00:00:00:00/01:00:00:00:00:00
表明廣播00:00:00:00:00:00/01:00:00:00:00:00
表明單播fe:ff:ff:ff:ff:ff
匹配除多播位之外的全部位,基本上不會用到。ff:ff:ff:ff:ff:ff
徹底匹配(等同於省略子網掩碼)。00:00:00:00:00:00
匹配所有位(等同於 dl_dst=*
)。若是dl_type爲0x0800(多是經過簡寫形式,例如ip或tcp),則匹配IPv4源(或目標)地址ip,能夠將其指定爲IP地址或主機名(例如192.168.1.1或www.example.com)。可選的網絡掩碼容許將匹配限制爲IPv4地址前綴。網絡掩碼能夠指定爲點分四邊形(例如192.168.1.0/255.255.255.0)或CIDR塊(例如192.168.1.0/24)。 Open vSwitch 1.8和更高版本支持任意點狀四元掩碼;早期版本僅支持CIDR掩碼,即等效於某些CIDR塊的虛線四邊形。
dl_type
爲0x0800
或者ip
時,匹配源或者目標的 IPv4 地址,能夠將其指定爲IP地址或主機名,例如192.168.1.1
或www.typesafe.cn
。同時也能夠寫做192.168.1.0/255.255.255.0
或者192.168.1.0/24
的形式。dl_type
爲0x0806
或arp
時,分別與IPv4和Ethernet的ARP數據包中的ar_spa
或ar_tpa
字段匹配。dl_type
爲0x8035
或rarp
時,分別與IPv4和Ethernet的RARP數據包中的ar_spa
或ar_tpa
字段匹配。dl_type
爲0x0800
、0x0806
或0x8035
以外的其餘值時,將忽略nw_src
和nw_dst
的值。ip
或dl_type=0x0800
,則匹配IP協議類型proto,該協議類型被指定爲0到255之間的十進制數(包括1和0,用於包含ICMP數據包或6以匹配TCP數據包)。ipv6
或dl_type=0x86dd
,則匹配IPv6標頭類型原型,該形式指定爲0到255之間的十進制數字(例如,包括58以匹配ICMPv6數據包或6以匹配TCP)。標頭類型是設計文檔中描述的終端標頭。arp
或dl_type=0x0806
時,與ARP操做碼的低8位匹配。大於255的ARP操做碼被視爲0。rarp
或dl_type=0x8035
時,與ARP操做碼的低8位匹配。大於255的ARP操做碼被視爲0。0x0800
、0x0806
、0x8035
或0x86dd
以外的其餘值時,將忽略nw_proto的值(請參見上面的流語法)。匹配IP ToS / DSCP或IPv6流量類別字段tos,該字段tos指定爲0到255之間的十進制數字(包括0和255)。請注意,出於匹配目的,將忽略兩個較低的保留位。
當通配符dl_type或將其設置爲0x0800
或0x86dd
以外的其餘值時,將忽略nw_tos的值。
匹配IP ToS / DSCP或IPv6流量類字段dscp,該字段指定爲介於0和63之間(含0和63)的十進制數。
當通配符dl_type或將其設置爲0x0800
或0x86dd
以外的其餘值時,將忽略ip_dscp的值(請參見上面的流語法)。
匹配IP ToS或IPv6流量類別字段中的ecn位,該ecn位指定爲0到3(含0和3)之間的十進制數。當通配符dl_type或將其設置爲0x0800
或0x86dd
以外的其餘值時,將忽略nw_ecn的值(請參見上面的流語法)。
匹配IP TTL或IPv6躍點限制值ttl,該值指定爲0到255之間的十進制數字(包括0和255)。
當通配符dl_type或將其設置爲0x0800
或0x86dd
以外的其餘值時,將忽略nw_ttl的值(請參見上面的流語法)。
匹配TCP,UDP或SCTP源端口或目標端口,端口號指定爲0到65535(含0和65535)之間的十進制數。
當通配符dl_type和nw_proto或將其設置爲不表示適當協議的值時,這些設置的值將被忽略(請參見上面的流語法)。
TCP(或UDP或SCTP)源或目標端口上的按位匹配。端口和掩碼是16位數字,以十進制或十六進制寫爲0x。掩碼中的每一個1位要求端口中的相應位必須匹配。掩碼中的每一個0位都會致使忽略相應的位。
傳輸端口上的按位匹配不多在隔離中有用,可是可使用一組匹配項來減小在一系列傳輸端口上進行匹配所需的流數。例如,假設目標是將TCP源端口1000匹配到1999(含)。一種方法是插入1000個流,每一個流在單個源端口上匹配。另外一種方法是查看1000和1999的二進制表示形式,以下所示:
01111101000 11111001111
而後將其轉換爲一系列按位匹配,以實現相同的結果:
01111101xxx 0111111xxxx 10xxxxxxxxx 110xxxxxxxx 1110xxxxxxx 11110xxxxxx 1111100xxxx
使用ovs-ofctl所需的語法編寫時,這些內容以下:
tcp,tcp_src=0x03e8/0xfff8 tcp,tcp_src=0x03f0/0xfff0 tcp,tcp_src=0x0400/0xfe00 tcp,tcp_src=0x0600/0xff00 tcp,tcp_src=0x0700/0xff80 tcp,tcp_src=0x0780/0xffc0 tcp,tcp_src=0x07c0/0xfff0
僅Open vSwitch 1.6和更高版本支持傳輸端口上的按位匹配。
與上述徹底匹配形式同樣,按位匹配形式僅在dl_type和nw_proto指定TCP或UDP或SCTP時適用。
這些是L4端口匹配項已棄用的通用形式。在新代碼中,請使用上述特定於TCP,UDP或SCTP的形式。
TCP標誌按位匹配。標誌和掩碼是16位數字,以十進制或以0x爲前綴的十六進制表示。掩碼中的每一個1位要求標誌中的相應位必須匹配。掩碼中的每一個0位都會致使忽略相應的位。
或者,能夠經過標誌的符號名(在下面列出)來指定標誌,每一個標誌名的前面都帶有+,表示必須設置的標誌,或者-表示必須取消設置的標誌,且標誌之間沒有其餘定界符。未說起的標誌是通配符。例如,tcp,tcp_flags = + syn-ack匹配不是ACK的TCP SYN。 TCP協議當前定義9個標誌位,並保留另外3個位(必須做爲零發送),請參閱RFC 79三、3168和3540。這些標誌位的編號從最低有效位開始:
當dl_type和nw_proto指定ICMP或ICMPv6時,type匹配ICMP類型,而代碼匹配ICMP代碼。每一個參數都指定爲介於0和255之間(含兩端)的十進制數。
當dl_type和nw_proto採用其餘值時,這些設置的值將被忽略(請參見上面的流語法)。
在元數據字段中徹底匹配值或使用可選掩碼匹配值。 value和mask是64位整數,默認狀況下爲十進制(使用0x前綴指定十六進制)。容許使用任意掩碼值:掩碼中的1位表示值中的對應位必須徹底匹配,而該位則使用0位通配符。在Open vSwitch 1.8中添加了對元數據的匹配。
等同於dl_type=0x0800
等同於dl_type=0x86dd
等同於dl_type=0x0800,nw_proto=1
等同於dl_type=0x86dd,nw_proto=58
等同於dl_type=0x0800,nw_proto=6
等同於dl_type=0x86dd,nw_proto=6
等同於dl_type=0x0800,nw_proto=17
等同於dl_type=0x86dd,nw_proto=17
等同於dl_type=0x0800,nw_proto=132
等同於dl_type=0x86dd,nw_proto=132
等同於dl_type=0x0806
等同於dl_type=0x8035
等同於dl_type=0x8847
等同於dl_type=0x8848
匹配修改後的VLAN TCI tci。若是省略mask,則tci是要匹配的確切VLAN TCI;若是指定了mask,則mask中的1位表示tci中的對應位必須徹底匹配,而0位通配符表示該位。 tci和mask均爲16位值,默認狀況下爲十進制。使用0x前綴以十六進制指定它們。
對於沒有802.1Q標頭的數據包,vlan_tci與之匹配的值爲0。不然,它是802.1Q標頭中的TCI值,其中CFI位(值爲0x1000)被強制爲1。
使用dl_vlan和dl_vlan_pcp也能夠實現某些匹配可能性。
當dl_type指定IP或IPv6時,frag_type指定要匹配的IP片斷或非片斷類型。支持如下frag_type值:
僅匹配非分段數據包。
匹配全部片斷。
僅匹配偏移量爲0的片斷。
僅匹配非零偏移量的片斷。
當dl_type指定ARP或RARP時,arp_spa和arp_tpa分別與源和目標IPv4地址匹配。能夠將地址指定爲IP地址或主機名(例如192.168.1.1或www.example.com)。可選的網絡掩碼容許將匹配限制爲IPv4地址前綴。網絡掩碼能夠指定爲點分四邊形(例如192.168.1.0/255.255.255.0)或CIDR塊(例如192.168.1.0/24)。
當dl_type指定ARP或RARP時,arp_sha和arp_tha分別匹配源和目標硬件地址。地址指定爲以冒號分隔的6對十六進制數字(例如00:0A:E4:25:6B:B0)。
當dl_type指定ARP或RARP時,arp_sha和arp_tha分別匹配源和目標硬件地址。地址指定爲以冒號分隔的6對十六進制數字(例如00:0A:E4:25:6B:B0),並在斜槓後加上通配符掩碼。
當dl_type指定ARP或RARP時,arp_op與ARP操做碼匹配。只能指定1到255之間的ARP操做碼進行匹配。
當dl_type爲0x86dd時(可能經過簡寫形式,例如ipv6或tcp6),匹配IPv6源(或目標)地址ipv6,該地址能夠按RFC 2373中的規定指定。首選格式爲x:x:x:x:x:x:x:x
,其中x是地址的八個16位塊的十六進制值。 ::的單個實例可用於指示16位零的多個組。可選的網絡掩碼容許將匹配限制爲IPv6地址前綴。網絡掩碼被指定爲IPv6地址(例如2001:db8:3c4d:1::/ffff:ffff:ffff:ffff::
)或CIDR塊(例如2001:db8:3c4d:1::/64
)。打開vSwitch 1.8及更高版本,支持仲裁掩碼;早期版本僅支持CIDR掩碼,即CIDR塊和等同於CIDR塊的IPv6地址。
當dl_type爲0x86dd時(可能經過簡寫形式,例如ipv6或tcp6),匹配IPv6流標籤label。
匹配隧道標識符tunnel-id。只有經過帶有密鑰的隧道到達的數據包(例如具備RFC 2890密鑰擴展名和非零密鑰值的GRE)纔會具備非零的隧道ID。若是省略mask,則tunnel-id是要匹配的確切隧道ID;若是指定了mask,則mask中的1位表示tunnel-id中的相應位必須徹底匹配,而0位通配符則將該位匹配。
匹配標誌,指示隧道封裝的各個方面。當前,僅定義一個標誌:
隧道協議指示這是一個OAM控制數據包。
能夠在標誌前面加上+或-來分別指示該標誌應匹配爲存在或不存在。另外,能夠指定沒有前綴的標誌,並用|分隔。表示徹底匹配。
請注意,較新版本的Open vSwitch可能會引入具備不一樣含義的其餘標誌。所以,不建議在此字段上使用徹底匹配,由於這些新標誌的行爲是未知的,應忽略。
對於非隧道數據包,該值爲0。
此字段是在Open vSwitch 2.5中引入的。
匹配隧道IPv4源(或目標)地址ip。僅經過隧道到達的數據包將具備非零的隧道地址。該地址能夠指定爲IP地址或主機名(例如192.168.1.1或www.example.com)。可選的網絡掩碼容許將匹配限制爲被掩碼的IPv4地址。子網掩碼能夠指定爲點分四邊形(例如192.168.1.0/255.255.255.0)或CIDR塊(例如192.168.1.0/24)。
等同於dl_type=0x86dd
等同於dl_type=0x86dd,nw_proto=6
等同於dl_type=0x86dd,nw_proto=17
等同於dl_type=0x86dd,nw_proto=132
等同於dl_type=0x86dd,nw_proto=58
知足匹配條件以後將會執行的動做。
將數據包輸出到OpenFlow端口號port。若是port是數據包的輸入端口,則不輸出數據包。
將數據包輸出到OpenFlow組group_id。僅OpenFlow 1.1+支持組表。有關更多詳細信息,請參見組語法。
使數據包通過設備的常規L2 / L3處理。 (並不是全部OpenFlow交換機都執行此操做。)
在全部交換機物理端口上輸出數據包,而不是在接收數據包的端口以及任何禁用洪泛的端口上進行輸出(一般,這些端口是IEEE 802.1D生成樹協議禁用的端口)。
在全部交換機物理端口上輸出數據包,而不是在接收數據包的端口上。
在與本地網橋名稱相同的網絡設備對應的``本地端口''上輸出數據包。
在接收數據包的端口上輸出數據包。
將數據包放入端口port中的指定隊列中,該隊列必須是OpenFlow端口號或關鍵字(例如LOCAL)。支持的隊列數取決於交換機;具體取決於交換機。一些OpenFlow實現根本不支持排隊。
丟棄數據包,所以不會進行進一步的處理或轉發。若是使用丟棄動做,則不能指定其餘動做。
修改報文的VLAN ID。根據須要添加或修改VLAN標記以匹配指定的值。若是添加了VLAN標記,則使用零優先級(請參閱mod_vlan_pcp操做來設置此優先級)。
修改報文的VLAN優先級。根據須要添加或修改VLAN標記以匹配指定的值。有效值介於0(最低)和7(最高)之間。若是添加了VLAN標記,則使用的vid爲零(請參閱mod_vlan_vid操做進行設置)。
從數據包中剝離VLAN標記(若是存在)。
將新的VLAN標籤推入數據包。以太網類型用做標籤的以太網類型。僅應使用ethertype 0x8100。 (目前尚不支持規範容許的0x88a8。)新標籤使用優先級爲零且標籤爲零。
將源以太網地址設置爲mac。
將目標以太網地址設置爲mac。
將IPv4源地址設置爲ip。
將IPv4目標地址設置爲ip。
將TCP或UDP或SCTP源端口設置爲port。
將TCP或UDP或SCTP目標端口設置爲port。
將IPv4 ToS / DSCP或IPv6流量類字段中的DSCP位設置爲tos,該值必須爲0到255之間的4的倍數。此操做不會修改ToS字段的兩個最低有效位(ECN位)。
將IPv4 ToS或IPv6流量類別字段中的ECN比特設置爲ecn,該值必須介於0和3之間(包括0和3)。此操做不會修改該字段的六個最高有效位(DSCP位)。
須要OpenFlow 1.1或更高版本。
將IPv4 TTL或IPv6跳數限制字段設置爲ttl,指定爲0到255之間的十進制數(包括0和255)。可是,沒有很好地指定將ttl設置爲零時的開關行爲。
須要OpenFlow 1.1或更高版本。
從新搜索此OpenFlow流表(或由表指定其編號的表),用in_port字段替換爲端口(若是指定了port),並執行找到的操做(若是有),以及此流條目中的任何其餘操做。
若是輸出到將數據包封裝在隧道中並支持標識符(例如GRE)的端口,則將標識符設置爲id。若是使用set_tunnel形式,而且id能夠容納32位,則此操做將使用Open vSwitch 1.0和更高版本支持的操做擴展。不然,若是id是64位值,則須要Open vSwitch 1.1或更高版本。
設置輸出數據包時應用於排隊的隊列。支持的隊列數取決於交換機;具體取決於交換機。一些OpenFlow實現根本不支持排隊。
將隊列恢復爲應用任何set_queue操做以前的值。
將已命名的位從字段src複製到字段dst。 src和dst必須是nicira-ext.h中定義的NXM字段名稱,例如NXM_OF_UDP_SRC或NXM_NX_REG0。每一個開始和結束對(包括首尾對)必須指定相同的位數,而且必須適合其各自的字段。存在[start..end]的簡寫形式:使用[bit]指定單個位,或使用[]指定整個字段。
將文字值加載到字段或字段的一部分中。對於set_field,在字段dst的慣用語法中給出了值和可選掩碼,表示爲字段名。例如,set_field:00:11:22:33:44:55-> eth_src將以太網源地址設置爲00:11:22:33:44:55。加載時,值必須是整數值(十進制或以0x開頭的十六進制前綴),而dst是該字段的NXM或OXM名稱。例如,load:0x001122334455-> OXM_OF_ETH_DST []與前面的set_field示例具備相同的效果。
出於歷史緣由,存在這兩種形式。 Open vSwitch 1.1引入了NXAST_REG_LOAD做爲OpenFlow 1.0的Nicira擴展,並使用load來表達它。後來,Open-Flow 1.2引入了一個標準的OFPAT_SET_FIELD操做,該操做僅限於加載整個字段,所以Open vSwitch添加了具備此限制的表單set_field。 OpenFlow 1.5將OFPAT_SET_FIELD擴展到了它成爲NXAST_REG_LOAD的超集的地步。 Open vSwitch會根據所使用的OpenFlow版本轉換兩種語法:OpenFlow 1.0和1.1中的NXAST_REG_LOAD;在OpenFlow 1.二、1.3和1.4中,NXAST_REG_LOAD用於加載或加載子字段,不然爲OFPAT_SET_FIELD; OpenFlow 1.5及更高版本,OFPAT_SET_FIELD。
在堆棧頂部的字段中,壓入開始(包括結束)位。
示例:push:NXM_NX_REG2 [0..5]將存儲在寄存器2位0到5(含0和5)中的值壓入內部堆棧。
從堆棧的頂部彈出,從彈出的值中檢索包含開始到結束的位,並將它們存儲在dst中的相應位中。
示例:pop:NXM_NX_REG2 [0..5]從堆棧頂部彈出該值。根據剛剛彈出的值的0至5位,將寄存器2的0至5位(包括0和5)設置爲1。
使用base做爲通用哈希參數對字段進行哈希處理,而後應用多路徑連接選擇算法(帶有參數arg)從0到n_links減去1來選擇n_links輸出連接之一,並將連接存儲到dst [start..end]中,它必須是如上所述的NXM字段。