命令行方式操作OpenvSwitch Flow

一、OpenvSwitch内核数据交互路径

在这里插入图片描述
通常,用户将通过“ ovs-ofctl” 实用程序与Open vSwitch内核数据路径交互,以将 OpenFlow 规则编程到“ ovs-vswitchd”中。然而,这并不是通过openvswitch内核模块转发数据包的唯一机制。使用“ ovs-dpctl”实用程序也可以使用额外的直接流编程接口将流添加到内核。
了解数据包如何通过内核数据路径非常重要。每当一个数据包到达时,发生的第一件事就是一个流表key填充了数据包中的所有元数据。该元数据包括以太网报头信息、ip 报头信息、arp 信息等,如果数据包通过这样的隧道到达,还可以与隧道协议信息分层。
一旦填充了流表关键数据,就会进行 skb 处理。流表key与现有内核中流缓存数据匹配(hash匹配)。如果找到匹配项,则执行与该流关联的操作。如果未找到匹配项,则数据包将被发送到 ovs-vswitchd 实用程序,称为上调用(upcall),或丢弃(在 ovs-vswitchd 未运行的情况下)。
用OpenvSwitch的说法,数据路径只是vport的集合。通常,一旦发生上调用,就会为数据路径填充流条目。数据包根据OpenFlow规则进行评估,随后的流表key添加操作被编程到内核空间中。

//ovs的主要组成模块:
#ovs-vswitchd:OVS守护进程是,OVS的核心部件,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换(flow-based switching)。它和上层 controller 通信遵从 OPENFLOW 协议,它与 ovsdb-server 通信使用 OVSDB 协议,它和内核模块通过netlink通信,它支持多个独立的 datapath(网桥),它通过更改flow table 实现了绑定和VLAN等功能。
#ovsdb-server:轻量级的数据库服务,主要保存了整个OVS 的配置信息,包括接口啊,交换内容,VLAN啊等等。ovs-vswitchd 会根据数据库中的配置信息工作。它于 manager 和 ovs-vswitchd 交换信息使用了OVSDB(JSON-RPC)的方式。
#ovs-dpctl:一个工具,用来配置交换机内核模块,可以控制转发规则。  
#ovs-vsctl:主要是获取或者更改ovs-vswitchd 的配置信息,此工具操作的时候会更新ovsdb-server 中的数据库。  
#ovs-appctl:主要是向OVS 守护进程发送命令的,一般用不上。
#ovsdbmonitor:GUI 工具来显示ovsdb-server 中数据信息。  
#ovs-controller:一个简单的OpenFlow 控制器  
#ovs-ofctl:用来控制OVS 作为OpenFlow 交换机工作时候的流表内容。

二、action match syntax

一般来说actions之前都是match的部分,常用的一般有:
#in_port: switch的端口
#dl_src: 源mac地址
#dl_dst:目的mac地址
    例如:dl_dst=01:00:00:00:00:00/01:00:00:00:00:00
    匹配源和目的MAC地址。其中”/”后面的为掩码。
    - 01:00:00:00:00:00 只匹配组播MAC (第一个字节LSB为1的MAC地址为MAC组播地址)
    - fe:ff:ff:ff:ff:ff 匹配其他所有MAC,除了组播MAC
    - ff:ff:ff:ff:ff:ff 完全匹配掩码前的MAC,和省掉掩码的效果一样
    - 00:00:00:00:00:00 完全通配,相当于(dl_dst=*)
#dl_type:以太网协议类型 0x0806是arp packet 0x0800是ip packet
    匹配L2(数据链路层) header中的协议类型,该字段描述L3的类型。有效值区间[0, 65535],可以是十进制数或者是以”0x”开头的十六进制数。比如:
    dl_type=0x0800 匹配IP数据包
    dl_type=0x0806 匹配ARP数据包
    dl_type=0x8035 匹配RARP数据包
#nwproto ipproto(要和 dl_type 字段配合使用)
    当dl_type=0x0800或使用了关键字ip时,匹配IP头中的proto字段,取值区间[0, 255],比如为1时可以匹配ICMP数据包,为6时匹配TCP数据包。
    当dl_type=0x86dd或使用了关键字ipv6是,匹配IPv6头中的proto字段,取值区间[0, 255],比如为58时匹配ICMPv6数据包,为6时匹配TCP数据包
    当dl_type=0x0806或者使用了关键字arp时,匹配ARP opcode的低8位,ARP opcode大于255时,与等于0效果一样
    当dl_type=0x8035或者使用了关键字rarp时,匹配ARP opcode的低8位, ARP opcode大于255时,与等于0效果一样
    当dl_type使用了通配符或这除了0x0800, 0x0806, 0x8035以外的值,则nw_proto的值会被忽略
#nw_src:源IP
#nw_dst:目的ip
    当使用了 dl_type=0x0800 或者关键字 ip 或 tcp 时,nw_src 和
    nw_dst分配匹配IP头中的源IP地址和目的IP地址。其中netmask可以是255.255.255.0这样的(dotted quad)形式,也可以是数字 /24 这样的(CIDR)形式
#nw_proto
    协议类型 ,注意和dl_type区分,同时也需要和dl_type一起使用,比如dl_type是ip(0x0800),那么nw_proto=1就表示icmp packet
#tp_src
    tcp/udp源端口
#tp_dst
    tcp/udp目的端口
#dl_vlan= <vlan> 
    匹配IEEE 802.1Q VLAN tag为 的数据包。 值应该在[0-4095]这个区间。为0xffff表示匹配没有VLAN tag的包
#dl_vlan_pcp
    匹配IEEE 802.1Q Priority Code Point(PCP, 优先级代码点)为的数据包,改值取值区间为[0-7]。数字越大,表示优先级越高。可以用于QoS。
#nw_tos 
    匹配IP ToS字段或IPv6的traffic class字段取值为的数据包。取值区间[0, 255],需要注意的是最低2位会被忽略。当dl_type使用除0x800(IP)0x86dd(IPv6)以外的数值时,该字段被忽略。
#nw_ttl
     匹配IP和IPv6的TTL字段为的数据包。取值区间[0, 255]。当dl_type使用除0x800(IP)0x86dd(IPv6)以为的数值时,该字段被忽略。
#icmp_type 和 icmp_code
    icmp_type=<type>
    icmp_code=<code>
    当 dl_type 和 nw_proto 确定数据包为 ICMP 或 ICMPv6 时,匹配 ICMP type 和 code。取值区间都为[0, 255]。如果 dl_type 和 mw_proto 使用了其他值时,该字段忽略。
    协议关键字 对应关系如下:
    ip     =  dl_type=0x0800 
    ipv6   =  dl_type=0x86dd 
    icmp   =  dl_type=0x0800,nw_proto=1 
    icmp6  =  dl_type=0x86dd,nw_proto=58 
    tcp    =  dl_type=0x0800,nw_proto=6 
    tcp6   =  dl_type=0x86dd,nw_proto=6 
    udp    =  dl_type=0x0800,nw_proto=17 
    udp6   =  dl_type=0x86dd,nw_proto=17 
    sctp   =  dl_type=0x0800,nw_proto=132 
    sctp6  =  dl_type=0x86dd,nw_proto=132 
    arp    =  dl_type=0x0806 
    rarp   =  dl_type=0x8035 
    mpls   =  dl_type=0x8847 
    mplsm  =  dl_type=0x8848 
#cookie
    cookie=<value>
     或cookie=<value/mask>
     cookie 字段可以用于以下命令 :add-flows和 mod-flows

三、actions字段

actions字段是flow的一部分,actions字段中可以有多个action,它们之间用逗号隔开,一个flow的完整语法如下:
<field>=<value>,[<field>=<value>]...,actions=<action>[,<action>...] 
#output:port
    将数据包输出到OpenFlow port
#group:<group_id>
     将数据包输出到OpenFlow group
#normal
    按照设备的常规L2/L3处理流程来处理数据包。这通常是OVS默认flow中的action。要注意的是,并不是所有的OpenFlow switch都支持这个action。
#reason=reason reason
    可以是action,no_match,invalid_ttl
#id=controller-id
    默认是0,特殊的controller会有一个16位的id
#flood
    将数据包输出到所有物理端口,除了该数据包的输入口以及不可被flooding的端口
#all
    将数据包输出到所有物理端口,除了该数据包的输入口
#local
    将数据包输出到local port(与bridge同名的端口)
#in_port
    将数据包输出到其输入口
#controller
    controller(=)
    将数据包以”packet in”消息的形式发送到OpenFlow控制器。其中=键值对可以是:
    max_len= 只将数据包的个字节发送到控制器。默认发送这个数据包。
    reson= 指明”pakcet in”消息中的reason字段。默认reason为action,还可以是no_match, invalid_ttl。
    id= 指明控制器id,16位整数。表示要发送给那个控制器。默认使用的id是0.
    controller
    controller[:nbytes]
    分别是controller()controller(max_len=)的简略写法。
#enqueue(,)
    将数据包放到端口的队列中。其中必须是OpenFlow端口号或关键字(如”LOCAL”)。不同交换机支持的队列数不同,有些OpenFlow实现根本不支持队列。
#drop
    丢掉该数据包。
#vlan
    mod_vlan_vid:<vlan_vid> 
    修改数据包的VLAN id为。如果数据包没有VLAN tag则添加VLAN id为的VLAN tag。如果数据包VLAN id已经为,则将其VLAN 优先级priority设为0.
    mod_vlan_pcp:<vlan_pcp> 
    修改数据包的VLAN 优先级priority为。如果数据包没有VLAN tag则添加VLAN priority为的VLAN tag。合法值区间为[0, 7],数字越大优先级越高。如果数据包VLAN priority已经为,则将其VLAN id设为0.
#strip_vlan
    如果数据包有VLAN tag,则剥去VLAN tag
#datalink header mod
    mod_dl_src:<mac> 
    mod_dl_dst:<mac> 
    设置数据包的源或目的MAC地址
#network header mod
    od_nw_src:<ip> 
    mod_nw_dst:<ip> 
    设置数据包的源或目的IP地址
    mod_nw_tos:<tos> 
    设置IPv4头ToS/DSCP或IPv6头traffic class field中DSCP比特位设置成,数值必须是4的倍数,且在[0, 255]区间。这个action并不会修改ToS中的低2(2 LSB)。
    mod_nw_ecn:<ecn> 
    设置IPv4头ToS或IPv6头traffic class field中ECN比特位为<ecn>,数值区间为[0, 3]。这个action并不会修改高6(6 MSB)。
    需要OpenFLow 1.1以上。
    mod_nw_ttl:<ttl> 
    修改IPv4 TTL或IPv6 hop limit为,取值区间为[0, 255]。
    需要OpenFlow 1.1以上。
#transport header mod
    mod_tp_src:
     mod_tp_dst:
    将数据包的TCP/UDP/SCTP源或目的端口修改

四、ovs-vsctl 管理命令

//获取或者更改ovs-vswitchd的配置信息,此工具操作的时候会更新ovsdb-server 中的数据库。  
– ovs-vsctl –V : Prints the current version of openvswitch.
– ovs-vsctl show : Prints a brief overview of the switch database configuration.
– ovs-vsctl list-br : Prints a list of configured bridges
– ovs-vsctl list-ports <bridge> : Prints a list of ports on a specific bridge.
– ovs-vsctl add-br <bridge> : Creates a bridge in the switch database.
– ovs-vsctl list interface : Prints a list of interfaces.
# ovs-vsctl list interface  tap8934a9a8-f8
_uuid               : 8974f75f-3002-4203-b36a-51ffced91e90
admin_state         : up
bfd                 : {}
bfd_status          : {}
cfm_fault           : []
cfm_fault_status    : []
cfm_flap_count      : []
cfm_health          : []
cfm_mpid            : []
cfm_remote_mpids    : []
cfm_remote_opstate  : []
duplex              : []
error               : []
external_ids        : {attached-mac="fa:16:3e:48:be:87", iface-id="8934a9a8-f846-4f66-a10b-22ec3d7981be", iface-status=active}
ifindex             : 0
ingress_policing_burst: 0
ingress_policing_rate: 0
lacp_current        : []
link_resets         : 1
link_speed          : []
link_state          : up
lldp                : {}
mac                 : []
mac_in_use          : "fa:16:3e:48:be:87"
mtu                 : 1500
mtu_request         : []
name                : "tap8934a9a8-f8"
ofport              : 23
ofport_request      : []
options             : {}
other_config        : {}
statistics          : {collisions=0, rx_bytes=7784390, rx_crc_err=0, rx_dropped=0, rx_errors=0, rx_frame_err=0, rx_over_err=0, rx_packets=164959, tx_bytes=9766348, tx_dropped=0, tx_errors=0, tx_packets=160305}
status              : {driver_name=openvswitch}
type                : internal

五、ovs-ofctl流操作命令

//用来控制OVS OpenFlow交换机工作时候的流表内容
//添加流表:
- ovs-ofctl add-flow <bridge> <flow>
- ovs-ofctl add-flow <bridge> <match-field> actions=all
- ovs-ofctl add-flow br-int in_port=3 actions=output:8
//添加VLAN tag
#ovs-ofctl add-flow br0 in_port=1,actions=mod_vlan_vid:10,output:2
//剥去VLAN tag
#ovs-ofctl add-flow br0 in_port=2,dl_vlan=100,actions=strip_vlan,output:1 
#使用cookie添加一条 flow
#ovs-ofctl add-flow br0 cookie=0xf,tcp,tcp_dst=22,actions=mod_nw_tos:128,normal
//修改流表:
- ovs-ofctl mod-flows <bridge> <flow>
//删除指定匹配流表:
- ovs-ofctl del-flows <bridge> <flow>
#ovs-ofctl del-flows br-int cookie=0xf/-1,tcp,tcp_dst=22 
#ovs-ofctl del-flows br-int cookie=0xf/-1
//Dump flow table
ovs-ofctl dump-tables br-int
//Dump br-int的所有flow:
ovs-ofctl dump-flows br-int
//Dump br-int上匹配xx的flow:
ovs-ofctl dump-flows br-int xx

//查看交换机端口详情(确认端口)
# ovs-ofctl show br-int
OFPT_FEATURES_REPLY (xid=0x2): dpid:00008a6744840049
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
 1(int-br-provider): addr:42:f7:71:ad:6f:0f
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 2(tapd2e481eb-18): addr:fa:16:3e:f6:02:cb
     config:     0
     state:      0
     speed: 0 Mbps now, 0 Mbps max
 ......

六、ovs-dpctl 操作流

//用来配置交换机内核模块,可以控制转发规则
// ovs-dpctl 不接受OpenFlow语法。相反,它使用一种特殊的语法来构建流表项规范。流键匹配规则由元数据的各个部分组成。我们将关注的是最常见的:以太网匹配规则、arp 匹配规则和 ip 匹配规则。甚至还有一个 encap()说明符,它允许窥视封装的数据包。每个流表key匹配规则可能要求下一层至少有一个“空匹配”。
//让我们创建双向 tcp 规则。我们需要匹配从端口2到端口1的数据包,tcp目标端口为8080。这将用于包含 SYN、ACK、FIN 或 RST 标志的 tcp 数据包。
# ovs-dpctl add-flow "in_port(2),eth(),eth_type(0x800),ipv4(proto=6),tcp(dst=8080),tcp_flags(0x1/0x1)"
# ovs-dpctl add-flow "in_port(2),eth(),eth_type(0x800),ipv4(proto=6),tcp(dst=8080),tcp_flags(0x2/0x2)"
# ovs-dpctl add-flow "in_port(2),eth(),eth_type(0x800),ipv4(proto=6),tcp(dst=8080),tcp_flags(0x4/0x4)"
# ovs-dpctl add-flow "in_port(2),eth(),eth_type(0x800),ipv4(proto=6),tcp(dst=8080),tcp_flags(0x10/0x10)"
//对于返回路径,我们需要来自端口 8080 的任何数据包:
# ovs-dpctl add-flow "in_port(1),eth(),eth_type(0x800),ipv4(proto=6),tcp(src=8080),tcp_flags(0x1/0x1)"
# ovs-dpctl add-flow "in_port(1),eth(),eth_type(0x800),ipv4(proto=6),tcp(src=8080),tcp_flags(0x2/0x2)"
# ovs-dpctl add-flow "in_port(1),eth(),eth_type(0x800),ipv4(proto=6),tcp(src=8080),tcp_flags(0x4/0x4)"
# ovs-dpctl add-flow "in_port(1),eth(),eth_type(0x800),ipv4(proto=6),tcp(src=8080),tcp_flags(0x10/0x10)"

七、ovs-appctl trace flow

//向OVS守护进程发送命令
# ovs-appctl ofproto/trace br-int arp,arp_spa=100.127.127.254
Flow: arp,in_port=ANY,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,arp_spa=100.127.127.254,arp_tpa=0.0.0.0,arp_op=0,arp_sha=00:00:00:00:00:00,arp_tha=00:00:00:00:00:00
bridge("br-int")
----------------
 0. priority 1, cookie 0x52d47332fa25b1d1
    resubmit(,104)
104. priority 0, cookie 0x52d47332fa25b1d1
    resubmit(,59)
59. priority 0, cookie 0x52d47332fa25b1d1
    goto_table:60
60. priority 5, cookie 0x52d47332fa25b1d1
    resubmit(,101)
101. priority 0, cookie 0x52d47332fa25b1d1
    NORMAL
     -> no learned MAC for destination, flooding
bridge("br-provider")
---------------------
 0. in_port=2, priority 2, cookie 0x5d1d2bf2cde950b8
    drop
Final flow: unchanged
Megaflow: recirc_id=0,eth,arp,in_port=ANY,vlan_tci=0x0000/0x1fff,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00
Datapath actions: 3

八、查看生效的流表信息

//查看现在生效的流表命令:
# 查看默认的datapath类型的OVS桥的生效流表
ovs-appctl dpctl/dump-flows system@ovs-system
recirc_id(0),in_port(4),eth(src=fe:12:8c:6b:45:be,dst=76:06:f5:a5:89:80),eth_type(0x0800),ipv4(frag=no), packets:83887, bytes:8220204, used:0.487s, flags:SFPR., actions:7
recirc_id(0),in_port(3),eth(src=fe:12:8c:6b:45:be,dst=76:06:f5:a5:89:80),eth_type(0x0800),ipv4(frag=no), packets:83887, bytes:8220204, used:0.487s, flags:SFPR., actions:5
recirc_id(0),in_port(7),eth(src=76:06:f5:a5:89:80,dst=fe:12:8c:6b:45:be),eth_type(0x0800),ipv4(frag=no), packets:84009, bytes:8227760, used:0.487s, flags:SFPR., actions:4
recirc_id(0),in_port(5),eth(src=76:06:f5:a5:89:80,dst=fe:12:8c:6b:45:be),eth_type(0x0800),ipv4(frag=no), packets:84009, bytes:8227760, used:0.487s, flags:SFPR., actions:3

# 查看datapath类型为netdev的OVS桥的生效流表
ovs-appctl dpctl/dump-flows netdev@ovs-netdev

上述两条命令显示结果中的in_port(port_num)和actions:port_num,port_num值可能与使用ovs-ofctl命令查看到的不一致,
这是因为使用ovs-appctl命令显示的端口号是所有datapath类型的桥下接口的编号,而ovs-ofctl命令下的端口号是此OVS桥下的端口号。 
查看完整的datapath类型的接口编号命令为:
# 查看当前OVS中的datapath类型
ovs-appctl dpctl/dump-dps

# 查看默认datapath类型的接口编号
ovs-appctl dpctl/show system@ovs-system

# 查看datapath=netdev类型的接口编号
ovs-appctl dpctl/show netdev@ovs-netdev

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值