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字段。