OpenvSwitch简介
OVS是一个高质量的、多层虚拟交换机,使用开源Apache2.0许可协议,主要实现代码为可移植的C代码。OpenvSwitch是一个虚拟交换软件,主要用于虚拟机VM环境,作为一个虚拟交换机,支持Xen/XenServer,KVM以及virtualBox多种虚拟化技术。在这种虚拟化的环境中,一个虚拟交换机主要有两个作用:传递虚拟机之间的流量,以及实现虚拟机和外界网络的通信。
OpenvSwitch组件
OVS包含三个重要的组件:ovsdb-server、ovs-vswitchd、以及OVS内核模块。
ovsdb-server:OVS的数据库服务进程,用于存储虚拟交换机的配置信息(比如网桥、端口、vlan等),为控制器和ovs-vswitchd提供OVSDB操作接口。
ovs-vswitchd:OVS的核心组件,负责保存和管理控制器下发的所有流表,为OVS的内核模块提供流表查询功能,并为控制器提供OpenFlow协议的操作接口。它和上层controller 通信遵从 OPENFLOW 协议,它与 ovsdb-server 通信使用 OVSDB协议,它和内核模块通过netlink通信,它支持多个独立的 datapath(网桥),它通过更改flow table实现了绑定和VLAN等功能。
OVS内核模块:缓存某些常用流表,并负责数据包转发,当遇到无法匹配的报文,该模块将向ovs-vswitchd发送pack-in请求,获取报文处理指令。
OpenvSwitch配置和管理的工具:
ovs-dpctl 管理OVS内核模块,提供缓存流表的操作方法;
ovs-vsctl 管理ovsdb-server的配置,提供OVSDB的配置方法,包括创建和删除网桥、端口等,此工具操作的时候会更新ovsdb-server中的数据库
ovs-appctl 管理ovs-vswitchd的日志输出
ovs-ofctl 管理ovs-vswitchd的流表配置方法
ovs-pki 创建和管理公钥 ovs-tcpundump 抓取并解析OpenFlow消息
ovsdb-tool 创建和管理ovsdb
OpenvSwitch工具和组件之间的关系:
用户空间(ovs-vswitchd)
上图是我对ovs整体框架的一个总结。通过图片可以看到,用户空间运行了两个进程:ovs-vswitchd和ovsdb-server。ovsdb-server将ovs-vswitchd的配置持久化到db中,ovs-vswitchd是一个守护进程,它会向ovsdb-server读取相关配置信息,并且如果有配置需要更新也会将其同步到ovsdb-server中。它们之间的通信是通过unix domain socket进行的。ovsdb通常是一个文件保存在linux的存储系统里面,一般它的路径是/etc/openvswitch/conf.db。
内核空间(openvswitch.ko)
在内核空间中,open vSwitch则提供了一个内核模块:openvswitch.ko来支持数据流的交换。从图上也可以看出:内核空间和用户空间的交互是通过Netlink协议实现的每一个ovs网桥或者说ovs交换机,都有一个内核空间的datapath与之相对应,可以说这个datapath就是网桥或交换机的实体,数据流都是受它控制。而它则是根据flow table这张表进行数据都转发。每一个datapath在内核中都有一个flow table,当数据包匹配到表中的某一项时,就会执行该项指定的action,转发数据包。
OpenvSwitch转发通道
快速通路
当datapath接收到数据包后,能直接查询到内核空间对应的flow table,并将该数据包转发。
慢速通路
而如果内核中的flow table中找不到匹配的项时,内核空间就会与用户空间进行交互,通过ovs-vswitchd查询数据库判断数据包应该发送到哪个端口上,并将该行为缓存到内核中的flow table中,下一次就不再需要通过用户空间查询了。 上述两种通路工作详情可以参考下图:
OpenvSwitch常用命令
控制类命令
添加网桥:
ovs-vsctl add-br br0
列出所有网桥:
ovs-vsctl list-br
判断网桥是否存在:
ovs-vsctl br-exists br0
将物理网卡挂载到网桥上:
ovs-vsctl add-port br0 eth0
列出网桥中的所有端口:
ovs-vsctl list-ports br0
列出所有挂载到网卡eth0的网桥:
ovs-vsctl port-to-br eth0
查看ovs的网络状态:
ovs-vsctl show
删除网桥上已经挂载的网口:
ovs-vsctl
del-port br0 eth0
删除网桥:
ovs-vsctl del-br br0
设置控制器:
ovs-vsctl set-controller br0 tcp:ip:6633
删除控制器:
ovs-vsctl del-controller br0
设置支持OpenFlow Version 1.3:
ovs-vsctl set bridge br0 protocols=OpenFlow13
删除OpenFlow支持设置:
ovs-vsctl clear bridge br0 protocols
设置vlan标签:
ovs-vsctl add-port br0 vlan3 tag=3 – set interface vlan3 type=internal
删除vlan标签:
ovs-vsctl del-port br0 vlan3
查询 VLAN:
ovs-vsctl show ifconfig vlan3
查看网桥上所有交换机端口的状态:
ovs-ofctl dump-ports br0
查看网桥上所有的流规则:
ovs-ofctl dump-flows br0
查看ovs的版本:
ovs-ofctl -V
给端口配置tag
ovs-vsctl set port br-ex tag=101
设置fail模式,支持standalone或者secure
standalone(default):清除所有控制器下发的流表,ovs自己接管
secure:按照原来流表继续转发
ovs-vsctl del-fail-mode br0
ovs-vsctl set-fail-mode br0 secure
ovs-vsctl get-fail-mode br0
流表命令
ovs-ofctl的Flow语法由一系列field=value形式的键值对组成,用英文逗号和空格隔开。在描述Flow时,必须要遵循TCP/IP协议栈。比如说,在flow中使用了L3(网络层)的字段时,必须也要指明L2(数据链路层)所用的协议。使用了L4(传输层)的字段时,必须也要指明L2和L3所用的协议。常用字段如下:
in_port
匹配从OpenFlow port id 进入的数据包。
dl_vlan
匹配IEEE 802.1Q VLAN tag的值为[0-4095]这个区间的数据包。 为0xffff表示匹配没有VLAN tag的包。
dl_src 和 dl_dst
例如: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
匹配L2(Data Link ,数据链路层) header中的协议类型,该字段描述L3的类型。有效值区间[0, 65535],可以是十进制数或者是以”0x”开头的十六进制数。比如:
dl_type=0x0800 匹配IP数据包
dl_type=0x08dd 匹配IPv6数据包
dl_type=0x0806 匹配ARP数据包
dl_type=0x8035 匹配RARP数据包
dl_type=0x8847 匹配MPLS数据包
需要说明的是dltype=0x0800 可以用关键字 ip 代替。 而 dltype=0x0806 可以用关键字 arp
代替。dl_type=0x8035 可以用关键字 rarp 代替。
tp_src 和tp_dst
传输层协议如TCP/UDP协议的源端口号、目的端口号
nw_proto 和 ip_proto
要和 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的值会被忽略
actions
ovs-ofctl的 add-flow 以及 mod-flows命令都需要 actions 字段,描述对匹配的数据包执行的动作
在上述的三条命令中,actions字段是flow的一部分,actions字段中可以有多个action,它们之间用逗号隔开,一个flow的完整语法如下:
=,[=]…,actions=[,…]
1.动作为出接口 从指定接口转发出去
ovs-ofctl add-flow br0 in_port=1,actions=output:2
2.动作为指定group group id为已创建的group table
ovs-ofctl add-flow br0 in_port=1,actions=group:666
3.动作为normal 转为L2/L3处理流程
ovs-ofctl add-flow br0 in_port=1,actions=normal
4.动作为flood 从所有物理接口转发出去,除了入接口和已关闭flooding的接口
ovs-ofctl add-flow br0 in_port=1,actions=flood
5.动作为all 从所有物理接口转发出去,除了入接口
ovs-ofctl add-flow br0 in_port=1,actions=all
6.动作为local 一般是转发给本地网桥
ovs-ofctl add-flow br0 in_port=1,actions=local
7.动作为in_port 从入接口转发回去
ovs-ofctl add-flow br0 in_port=1,actions=in_port
8.动作为controller 以packet-in消息上送给控制器
ovs-ofctl add-flow br0 in_port=1,actions=controller
9.动作为drop 丢弃数据包操作
ovs-ofctl add-flow br0 in_port=1,actions=drop
10.动作为mod_vlan_vid 修改报文的vlan id,该选项会使vlan_pcp置为0
ovs-ofctl add-flow br0 in_port=1,actions=mod_vlan_vid:8,output:2
11.动作为mod_vlan_pcp 修改报文的vlan优先级,该选项会使vlan_id置为0
ovs-ofctl add-flow br0 in_port=1,actions=mod_vlan_pcp:7,output:2
12.动作为strip_vlan 剥掉报文内外层vlan tag
ovs-ofctl add-flow br0 in_port=1,actions=strip_vlan,output:2
13.动作为push_vlan 在报文外层压入一层vlan tag,需要使用openflow1.1以上版本兼容
ovs-ofctl add-flow -O OpenFlow13 br0 in_port=1,actions=push_vlan:0x8100,set_field:4097->vlan_vid,output:2
ps: set field值为4096+vlan_id,并且vlan优先级为0,即4096-8191,对应的vlan_id为0-4095
14.动作为修改源/目的MAC,修改源/目的IP
修改源MAC
ovs-ofctl add-flow br0 in_port=1,actions=mod_dl_src:00:00:00:00:00:01,output:2
修改目的MAC
ovs-ofctl add-flow br0 in_port=1,actions=mod_dl_dst:00:00:00:00:00:01,output:2
修改源IP
ovs-ofctl add-flow br0 in_port=1,actions=mod_nw_src:192.168.1.1,output:2
修改目的IP
ovs-ofctl add-flow br0 in_port=1,actions=mod_nw_dst:192.168.1.1,output:2
15.动作为修改TCP/UDP/SCTP源目的端口
修改TCP源端口
ovs-ofctl add-flow br0 tcp,in_port=1,actions=mod_tp_src:67,output:2
修改TCP目的端口
ovs-ofctl add-flow br0 tcp,in_port=1,actions=mod_tp_dst:68,output:2
修改UDP源端口
ovs-ofctl add-flow br0 udp,in_port=1,actions=mod_tp_src:67,output:2
修改UDP目的端口
ovs-ofctl add-flow br0 udp,in_port=1,actions=mod_tp_dst:68,output:2
流表操作举例
添加
flow ovs-ofctl add-flow br0 in_port=3,actions=output:2
修改
flow ovs-ofctl mod-flows br0 xx
删除 flow
删除br0上的所有flow
ovs-ofctl del-flows br0
按照匹配项删除br0上的flow
ovs-ofctl del-flows br0 “in_port=1”
goto table配置
数据流先从table0开始匹配,如actions有goto_table,再进行后续table的匹配,实现多级流水线,如需使用goto table,则创建流表时,指定table id,范围为0-255,不指定则默认为table0
在table0中添加一条流表条目
ovs-ofctl add-flow br0 table=0,in_port=1,actions=goto_table=1
在table1中添加一条流表条目
ovs-ofctl add-flow br0 table=1,ip,nw_dst=10.10.0.0/16,actions=output:2
计量表命令
由于meter表是openflow1.3版本以后才支持,所以所有命令需要指定OpenFlow1.3版本以上
ps:在openvswitch-v2.8之前的版本中,还不支持meter
1.查看当前设备对meter的支持
ovs-ofctl -O OpenFlow13 meter-features br0
2.查看meter表
ovs-ofctl -O OpenFlow13 dump-meters br0
3.查看meter统计
ovs-ofctl -O OpenFlow13 meter-stats br0
4.创建meter表
限速类型以kbps(kilobits per second)计算,超过20kb/s则丢弃
ovs-ofctl -O OpenFlow13 add-meter br0 meter=1,kbps,band=type=drop,rate=20
同上,增加burst size参数
ovs-ofctl -O OpenFlow13 add-meter br0 meter=2,kbps,burst,band=type=drop,rate=20,burst_size=256
同上,增加stats参数,对meter进行计数统计
ovs-ofctl -O OpenFlow13 add-meter br0 meter=3,kbps,burst,stats,band=type=drop,rate=20,burst_size=256
限速类型以pktps(packets per second)计算,超过1000pkt/s则丢弃
ovs-ofctl -O OpenFlow13 add-meter br0 meter=4,pktps,band=type=drop,rate=1000
5.删除meter表
删除全部meter表
ovs-ofctl -O OpenFlow13 del-meters br0
删除meter id=1
ovs-ofctl -O OpenFlow13 del-meter br0 meter=1
6.创建有meter动作的流表
ovs-ofctl -O OpenFlow13 add-flow br0 in_port=1,actions=meter:1,output:2
组表命令
由于group表是openflow1.1版本以后才支持,所以所有命令需要指定OpenFlow1.1版本以上 group
table支持4种类型
all:所有buckets都执行一遍
select: 每次选择其中一个bucket执行,常用于负载均衡应用
ff(FAST FAILOVER):快速故障修复,用于检测解决接口等故障
indirect:间接执行,类似于一个函数方法,被另一个group来调用
1.查看当前设备对group的支持
ovs-ofctl -O OpenFlow13 dump-group-features br0
2.查看group表
ovs-ofctl -O OpenFlow13 dump-groups br0
3.创建group表
类型为all
ovs-ofctl -O OpenFlow13 add-group br0 group_id=1,type=all,bucket=output:1,bucket=output:2,bucket=output:3
类型为select ovs-ofctl -O OpenFlow13 add-group br0 group_id=2,type=select,bucket=output:1,bucket=output:2,bucket=output:3
类型为select,指定hash方法(5元组,OpenFlow1.5+)
ovs-ofctl -O OpenFlow15 add-group br0
group_id=3,type=select,selection_method=hash,fields=ip_src,bucket=output:2,bucket=output:3
4.删除group表
ovs-ofctl -O OpenFlow13 del-groups br0 group_id=2
5.创建流表
ovs-ofctl -O OpenFlow13 add-flow br0 in_port=1,actions=group:2