该篇文章是在《通俗说 Openvswitch》的基础上再结合我再网上收集的资料进行学习、整理与概括,感谢刘大(公众号:刘超的通俗云计算)以及创做者的分享。html
软件定义有啥好处呢?
想象你有一个大的数据中心,里面有不少的网络设备,光交换机就有不少,你但愿在交换机上配置一些网络的策略,例如某个口应该属于某个 VLAN。
怎么配置呢?登到这台交换机上去,敲几行命令就搞定了。
若是要配置 100 台交换机呢?头大了吧,难不成登录 100 台?
想不想有一个集中的地方,能看到整个网络的拓扑图,统一配置一下,而后一回车,配置的策略就经过管理网络平面下发到 100 台交换机上。这样整个网络的拓扑结构就不是硬的了,也即不是经过插线,拔线,登录盒子配置的,而是变成了软的,也即经过软件统一控制,这个统一控制的地方咱们称为 SDN Controller(控制器),这样的网络拓扑结构,咱们称为软件定义的网络。java
虚拟交换机(vSwitch)就是利用虚拟平台,经过软件的方式实现(Software Defined Network,SDN,软件定义网络)的交换机部件。跟传统的物理交换机相比,虚拟交换机具有众多优势:一是配置灵活,一台普通的服务器能够配置出数十台甚至上百台虚拟交换机,且端口数目也能够灵活选择。例如,一台 VMware ESXi 服务器能够仿真出 248 台虚拟交换机,且每台交换机预设虚拟端口便可达 56 个;二是成本低廉,经过虚拟交换一样能够得到昂贵的普通交换机才能达到的性能,例如,微软的 Hyper-V,虚拟机与虚拟交换机之间的联机速度轻易可达 10Gbps。linux
由于虚拟机的建立,删除,迁移比物理机灵活的多,因此很难像物理的交换机同样,用网线将交换机和物理服务器链接起来,就不怎么变了。虚拟机就不同了,因此须要虚拟交换机,也即经过软件模拟一个交换机,用软件模拟一根网线,一头插在虚拟机上,一头插在虚拟交换机上,一下子建立五个虚拟机,要插到一个交换机上,一下子其中两个虚拟机迁移到了另外的物理机上,则他们两个的网口要从上一台交换机上拔下来,插到新的虚拟交换机上,这样作没有问题,由于都是软件实现的,很灵活。git
OpenFlow is a open standard managed by Open Networking Foundation. It specifies a protocol by which a remote controller can modify the behavior of networking devices through a well-defined “forwarding instruction set”.github
OpenFlow,一种网上通讯协议,属于数据链路层,可以控制网上交换器或路由器的数据转发平面(Forwarding Plane),借此改变网上数据包所通过的网上路径。简而言之,OpenFlow 就是 SDN Controller 远程控制网络设备的协议,经由网上交换器,决定网上数据包要由何种路径经过网络交换机。虽然 OpenFlow 的功能不如各大网络厂商的自家协议强大,但正因如此,OpenFlow 成为了一个兼容很是高的功能子集,以致于让各网络厂商可以达成了部分的共识。web
OpenFlow 容许从远程控制网上交换器的数据包转送表,透过新增、修改、移除数据包控制规则与行动,来改变数据包转送的路径。比起用访问控制表(ACLs)和路由协议,容许更加复杂且灵活的流量管理。同时,OpenFlow 容许不一样网络供应商用一个简单,开源的协议去远程管理交换机(一般提供专有的接口和描述语言)。OpenFlow 协议用来描述控制器和交换机之间交互所用信息的标准,以及控制器和交换机的接口标准。算法
Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware’s vNetwork distributed vswitch or Cisco’s Nexus 1000V.
– 官方网站数据库
Open vSwitch(下文简称 OvS)就是一个开源的虚拟交换机实现。普遍应用在云计算行业,为网络管理员提供虚拟云主机之间和以内的流量可见性与可控性。Open vSwitch 旨在用虚拟化方案解决网络问题,与控制器软件一块儿实现分布式的虚拟交换技术。这意味着,交换机和控制器软件可以在多个服务器之间建立集群网络配置,从而不须要在每一台云主机和物理主机上单独配置网络。这个交换机还支持 VLAN 中继,经过 NetFlow、sFlow 和 RSPAN 实现可见性,经过 OpenFlow 协议进行管理。它还有其余一些特性:严格流量控制,它由 OpenFlow 交换协议实现;远程管理功能,它能经过网络策略实现更多控制。
json
简而言之,Open vSwitch 即开放的软件虚拟交换机,可以达到产品级的质量,也就是说能够部署一些生产环境使用。它不光支持基本的二层交换,还支持标准的管理机接口和协议(e.g. NetFlow,sFlow,SPAN,RSAPN,CLI,LACP,802.1ag),同时也支持 OpenFlow,能够很好的与 SDN 体系融合。bootstrap
Open vSwitch 的特性清单:
轻量级的数据库,用于存储整个 OvS 的配置信息,包括接口,交换内容,VLAN,虚拟交换机的建立,网卡的添加等信息与操做记录,都由 ovsdb 保存到一个 conf.db 文件(JSON 格式)里面,经过 db.sock 提供服务。
OvS 的核心部件,实现交换功能,与 Linux 内核兼容模块一块儿实现基于流的交换(Flow-based Switching)。它和上层 Controller 通讯听从 OpenFlow 协议,它与 ovsdb-server 通讯听从 OVSDB 协议,它和内核模块经过 netlink 进行通讯,它支持多个独立的 Datapath(网桥),它经过更改 Flow Table 实现了 Binding(绑定)和 VLAN 等功能。是真正的虚拟交换机生命周期管理进程。它经过 db.sock 文件从 ovsdb-server 进程读取 conf.db 的配置信息(e.g. 用户所建立的虚拟交换机、所添加的网卡等等操做记录)。
在 OvS 中,给一个交换机,或者说一个桥,用了一个专业的名词,叫作 DataPath!是一个 Linux Kernel 模块,监听网卡接口设备,获取网络包并交给 vSwitch 处理,支持数据在内核的交换。当 openvswtich.ko 被加载到了内核,会在网卡上注册一个钩子函数,每当有网络包到达网卡时,这个函数就会被调用,将网络包开始层层拆包(MAC 层,IP 层,TCP 层等),而后查看有没有已经定义好的策略来处理网络包(e.g. 修改 MAC,修改 IP,修改 TCP 端口,从哪一个网卡发出去等等),若是找到了策略,则将网络包从网卡发出。这个处理过程全在内核完成,因此很是快,称之为 Fast Path。
NOTE:然而内核态并无被分配太多内存,因此内核态可以保存的策略不多,每每有新的策略到来,老的策略就被丢弃。若是在内核态找不到策略,则须要到用户态去查询,网络包会经过 netlink(一种内核态与用户态交互的机制)发送给 vswitchd,vswitchd 有一个监听线程,当发现有从内核态发过来的包,就进入本身的处理流程。在用户态相对较慢,故称值为 Slow Path。用户态的 vswtichd 不须要吝啬内存,它包含了全部策略,这些策略都是 Controller(控制器)经过 OpenFlow 协议下发的。vswtichd 会根据网络包的信息层层匹配,直到找到一款策略进行处理。若是实在找不到,则通常会采用默认策略,好比丢弃这个包。当最终匹配到了一个策略以后,则会根据 “局部性原理” 再经过 netlink 协议,将这条策略下发到内核态,为了下一个相同类型的网络包可以直接从内核匹配到,以此加快执行效率。当这条策略下发给内核时,若是内核的内存空间不足,则会开始淘汰部分老策略。因为近因效应,接下来的网络包应该大几率可以匹配这条策略的。例如:传输一个文件,同类型的网络包会源源不断的到来。
# 查看 OvS Log 级别 ovs-appctl vlog/list # 设置 Log 级别 ovs-appctl vlog/set {module name}:{console, syslog, file}:{off, emer, err, warn, info, dbg} # 以 stp 设置 file 为 dbg level 为例 ovs-appctl vlog/set stp:file:dbg # 查看 OvS 版本 ovs-ofctl -V # 查询指令历史记录 ovsdb-tool show-log [-mmm] # 修改 ofport (openflow port number) 为 100 ovs-vsctl add-port <bridge> <interface> -- set Interface <interface> ofport_request=100 # 设置 interface 为 internal ovs-vsctl set Interface <interface> type=internal # 开启指定 Bridge 的 STP ovs-vsctl set bridge <bridge> stp_enable=true # 关闭指定 Bridge 的 STP ovs-vsctl set bridge <bridge> stp_enable=false # 查询指定 Bridge 的 STP 的配置信息 ovs-vsctl get bridge <bridge> stp_enable # 设置指定 Bridge 的 STP Priority ovs−vsctl set bridge <bridge> other_config:stp-priority=0x7800 # 设置指定 Bridge 的 STP Cost ovs−vsctl set port <bridge> other_config:stp-path-cost=10
要理解 OvS 的工做原理,首先要了解网桥的工做原理。网桥也叫作桥接器,工做在数据链路层,将两个 LAN 链接,根据 MAC 地址来转发数据帧,能够当作一个 “低层的路由器”。网桥处理数据帧遵循如下几条规则:
Open vSwitch 的内核模块(openvswitch.ko)实现了多个 “数据路径(Datapath)”(相似于网桥),每一个 Datapath 均可以有多个 vPorts(相似于网桥上的端口)。每一个 Datapath 也经过关联流表(Flow Table)来定义数据流向,一般的操做都是将数据流转发到指定的 vPort 上。当网络包到达一个 vPort,内核模块所作的处理是提取其流的关键信息并在流表中查找这些关键信息,当有一个匹配的流时,就对该网络包执行相应的操做;若是没有匹配,则将网络包送到用户空间的处理队列中,用户空间可能会定义一个流用于之后碰到相同类型的网络包能够在内核中执行操做,这就是所谓的 Slow Path 和 Fast Path。
Open vSwitch 实现的流量控制很大部分上是经过 OpenFlow 交换协议实现的。OpenFlow 使 Controller 可以经过网络访问一个交换机或路由器的 Datapath。网管人员能够在任意一台计算机(Controller)上远程控制数据管理,这样他们就可以进行精细的路由和交换控制,并实现复杂的网络策略。有了 Open vSwitch 中的这些远程管理功能,云计算的集成商和供应商就可以向客户提供在一台计算机上持续管理各自虚拟网络、应用和策略的功能。
NOTE:L2 Switch 链接到宿主机的 eth0 一般是一个 Trunk 口,由于虚拟机对应的 vnet 每每会设置 VLAN TAG 来隔离虚拟机的广播域。因此 eth0 就至关于一个 Trunk 口,而 vnets 就至关于 Access 口。
OS:CentOS7
Step1. 关闭 SELinux,不然 ovsdb-server Manager 没法正常工做。
[root@localhost ~]# setenforce 0 [root@localhost ~]# cat /etc/selinux/config | grep -v ^# SELINUX=disabled SELINUXTYPE=targeted
Step 2. yum install
yum install openvswitch openvswitch-test
Step 3. 启动服务
systemctl enable openvswitch systemctl start openvswitch systemctl status openvswitch
查看当前的 OvS 版本:
[root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f ovs_version: "2.0.0"
查看 OvS 服务进程清单:
ovsdb-server /etc/openvswitch/conf.db -vconsole:emer -vsyslog:err -vfile:info --remote=punix:/var/run/openvswitch/db.sock --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert --no-chdir --log-file=/var/log/openvswitch/ovsdb-server.log --pidfile=/var/run/openvswitch/ovsdb-server.pid --detach --monitor ovs-vswitchd unix:/var/run/openvswitch/db.sock -vconsole:emer -vsyslog:err -vfile:info --mlockall --no-chdir --log-file=/var/log/openvswitch/ovs-vswitchd.log --pidfile=/var/run/openvswitch/ovs-vswitchd.pid --detach --monitor
查看加载的内核模块:
[root@localhost ~]# lsmod | grep openvswitch openvswitch 70743 0 vxlan 37584 1 openvswitch gre 13808 1 openvswitch libcrc32c 12644 2 xfs,openvswitch
从架构图可知,ovsdb-server 与 ovs-vswitchd 能够经过 UNIX Domain Socket(/var/run/openvswitch/db.sock)进行互相通讯。
ovs-db 在操做系统上的载体是 JSON 文件 /etc/openvswitch/conf.db,经过执行指令 ovsdb-client dump
能够查看其内容,e.g.
[root@localhost ~]# ovsdb-client dump Bridge table _uuid controller datapath_id datapath_type external_ids fail_mode flood_vlans flow_tables ipfix mirrors name netflow other_config ports protocols sflow status stp_enable ----- ---------- ----------- ------------- ------------ --------- ----------- ----------- ----- ------- ---- ------- ------------ ----- --------- ----- ------ ---------- Controller table _uuid connection_mode controller_burst_limit controller_rate_limit enable_async_messages external_ids inactivity_probe is_connected local_gateway local_ip local_netmask max_backoff other_config role status target ----- --------------- ---------------------- --------------------- --------------------- ------------ ---------------- ------------ ------------- -------- ------------- ----------- ------------ ---- ------ ------ Flow_Sample_Collector_Set table _uuid bridge external_ids id ipfix ----- ------ ------------ -- ----- Flow_Table table _uuid flow_limit groups name overflow_policy ----- ---------- ------ ---- --------------- IPFIX table _uuid cache_active_timeout cache_max_flows external_ids obs_domain_id obs_point_id sampling targets ----- -------------------- --------------- ------------ ------------- ------------ -------- ------- Interface table _uuid admin_state bfd bfd_status cfm_fault cfm_fault_status cfm_health cfm_mpid cfm_remote_mpids cfm_remote_opstate duplex external_ids ifindex ingress_policing_burst ingress_policing_rate lacp_current link_resets link_speed link_state mac mac_in_use mtu name ofport ofport_request options other_config statistics status type ----- ----------- --- ---------- --------- ---------------- ---------- -------- ---------------- ------------------ ------ ------------ ------- ---------------------- --------------------- ------------ ----------- ---------- ---------- --- ---------- --- ---- ------ -------------- ------- ------------ ---------- ------ ---- Manager table _uuid connection_mode external_ids inactivity_probe is_connected max_backoff other_config status target ----- --------------- ------------ ---------------- ------------ ----------- ------------ ------ ------ Mirror table _uuid external_ids name output_port output_vlan select_all select_dst_port select_src_port select_vlan statistics ----- ------------ ---- ----------- ----------- ---------- --------------- --------------- ----------- ---------- NetFlow table _uuid active_timeout add_id_to_interface engine_id engine_type external_ids targets ----- -------------- ------------------- --------- ----------- ------------ ------- Open_vSwitch table _uuid bridges cur_cfg db_version external_ids manager_options next_cfg other_config ovs_version ssl statistics system_type system_version ------------------------------------ ------- ------- ---------- -------------------------------------------------- --------------- -------- ------------ ----------- --- ---------- ----------- -------------- 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f [] 0 "7.3.0" {system-id="257b9b47-87e7-4404-9af8-37f98b04f2bd"} [] 0 {} "2.0.0" [] {} unknown unknown Port table _uuid bond_downdelay bond_fake_iface bond_mode bond_updelay external_ids fake_bridge interfaces lacp mac name other_config qos statistics status tag trunks vlan_mode ----- -------------- --------------- --------- ------------ ------------ ----------- ---------- ---- --- ---- ------------ --- ---------- ------ --- ------ --------- QoS table _uuid external_ids other_config queues type ----- ------------ ------------ ------ ---- Queue table _uuid dscp external_ids other_config ----- ---- ------------ ------------ SSL table _uuid bootstrap_ca_cert ca_cert certificate external_ids private_key ----- ----------------- ------- ----------- ------------ ----------- sFlow table _uuid agent external_ids header polling sampling targets ----- ----- ------------ ------ ------- -------- -------
使用图形化工具能够更加友好的查看:
数据库表之间的关系以下图所示:
其中 Open_vSwitch 表是 OvS DB 的 root(根)。
它的表结构以下图,记录 ovs-vswitchd 的配置信息,e.g.
数据库结构是一款软件的资源模型设计的映射,下文主要根据 OvS 的资源模型来依次认识每种资源对象的特性与做用。
Manager 对象都是为了配置 ovsdb-server 的 Connection,让 Clients(e.g. ovs-vswitchd、ovs-vsctl、host) 能够远程对 ovsdb-server 执行 DB Operation。
从上述架构图可知,ovsdb-server 是 ovs-db 提供管理的 RPC 接口。加载了 Open_vSwitch 表中的 manager_options 字段值来做为监听端口。
Manager 的表结构:
其中最重要的字段是 target,记录了 ovsdb-server 的监听参数信息:
Active(主动)database connection methods:
ssl:ip[:port]
:监听在指定 Remote IP 的 Port 上,协议为 SSLtcp:ip[:port]
:监听在指定 Remote IP 的 Port 上,协议为 TCPunix:FILE
:Unix domain socket named FILEPassive(被动)database connection methods:
pssl:[port][:ip]
:监听在本机 IP 的指定 Port 上,协议为 SSLptcp:[port][:ip]
:监听在本机 IP 的指定 Port 上,协议为 TCP经过下述指令设置:
ovs-vsctl set-manager TARGET... # set the list of managers to TARGET... # Active Listener ovs-vsctl set-manager tcp:1.2.3.4:6640 # Passive Listener ovs-vsctl set-manager ptcp:6640
NOTE:基于 TCP 的 DB Connection,使得 ovs-vsctl 在远程机器上也能够控制 ovsdb-server。
[root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f ovs_version: "2.0.0" [root@localhost ~]# ovs-vsctl set-manager ptcp:8881 [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" ovs_version: "2.0.0" [root@localhost ~]# ovsdb-client dump ... Manager table _uuid connection_mode external_ids inactivity_probe is_connected max_backoff other_config status target ------------------------------------ --------------- ------------ ---------------- ------------ ----------- ------------ -------------------------------------------------------------------- ----------- 84f0a33c-a798-40fc-a285-ed4d83121d3e [] {} [] false [] {} {bound_port="8881", sec_since_connect="0", sec_since_disconnect="0"} "ptcp:8881"
检查 Port 是否正常开启:
[root@localhost ~]# netstat -lpntu | grep 8881 tcp 0 0 0.0.0.0:8881 0.0.0.0:* LISTEN 3024/ovsdb-server
从远程计算机上执行链接:
[root@localhost ~]# ovs-vsctl --db=tcp:192.168.1.109:8881 show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" ovs_version: "2.0.0"
NOTE:注意防火墙的干扰因素。
若是将 Open vSwitch 配置为经过网络链接到 OpenFlow 控制器(ovs-vswitchd 与 ovs-controller 之间),那么建议你使用 OpenSSL 来构建安全的网络通信,双向的 SSL 互相可确保 OpenFlow 链接的完整性和与安全。
想创建 SSL 链接,首先要获取相关的 CA 证书,并将这些证书记录到 SSL 表中。启动 ovsdb-server 时,经过选项 --private-key=db:Open_vSwitch,SSL,private_key --certificate=db:Open_vSwitch,SSL,certificate --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
来指定应用这些参数。
SSL 表结构:
SSL 表属性:
其中主机(客户端)的 Public key 包含在 CA 签发的证书(certificate)内,而后再由 CA 中心的 private key 进行签名,CA 中心来担保这个 certificate 是合法的。为了验证 CA 签名,还须要 CA 的 public key,并放到 ca_cert 指向的 CA 证书里面。而 CA 自己的 public key 也须要被签名更高级的 CA 或者 CA(根 CA)本身担保。
SSL 验证流程:
# 查询 SSL 链接 ovs-vsctl get-ssl # 设置 SSL 证书 ovs-vsctl set-ssl sc-privkey.pem sc-cert.pem cacert.pem # 删除 SSL 链接 ovs-vsctl del-ssl
自签发 CA 根证书:
mkdir ~/OVS_CA cd ~/OVS_CA openssl genrsa -out caprivate.key 1024
openssl req -key caprivate.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=fanguiju@163.com" -out cacertificate.req
openssl x509 -req -in cacertificate.req -signkey caprivate.key -out cacertificate.pem
PS:自签发即本身担保本身,用本身的私钥对本身的 CSR 进行签发,因此也称为根证书。
签发客户端证书:
mkdir ~/ClientCerts cd ~/ClientCerts openssl genrsa -out cliu8private.key 1024
openssl req -key cliu8private.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=cliu8@163.com" -out cliu8certificate.req
cp ~/OVS_CA/caprivate.key ~/OVS_CA/cacertificate.pem ~/ClientCerts openssl x509 -req -in cliu8certificate.req -CA cacertificate.pem -CAkey caprivate.key -out cliu8certificate.pem -CAcreateserial
配置 SSL Connection:
ovs-vsctl del-manager ovs-vsctl set-manager pssl:8881 ovs-vsctl set-ssl /root/ClientCerts/cliu8private.key /root/ClientCerts/cliu8certificate.pem /root/OVS_CA/cacertificate.pem
NOTE:set-ssl 必定要指定绝对路径,不然没法正确载入证书文件。
查看修改:
[root@localhost newcerts]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "pssl:8881" ovs_version: "2.0.0" [root@localhost ~]# ovsdb-client dump ... SSL table _uuid bootstrap_ca_cert ca_cert certificate external_ids private_key ------------------------------------ ----------------- -------------------------------- ---------------------------------------- ------------ ------------------------------------ f8d8f0f5-f87b-430b-9d48-123a74a6804f false "/root/OVS_CA/cacertificate.pem" "/root/ClientCerts/cliu8certificate.pem" {} "/root/ClientCerts/cliu8private.key"
验证:
[root@localhost ~]# ovs-vsctl --db=ssl:192.168.1.109:8881 show 2019-02-23T06:46:26Z|00001|stream_ssl|ERR|Private key must be configured to use SSL 2019-02-23T06:46:26Z|00002|stream_ssl|ERR|Certificate must be configured to use SSL 2019-02-23T06:46:26Z|00003|stream_ssl|ERR|CA certificate must be configured to use SSL 2019-02-23T06:46:26Z|00004|reconnect|WARN|ssl:192.168.1.109:8881: connection attempt failed (Protocol not available) ovs-vsctl: ssl:192.168.1.109:8881: database connection failed (Protocol not available)
scp cliu8private.key cliu8certificate.pem cacertificate.pem root@192.168.1.110:~/certs
[root@localhost certs]# ovs-vsctl --db=ssl:192.168.1.109:8881 --private-key=cliu8private.key --certificate=cliu8certificate.pem --ca-cert=cacertificate.pem show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "pssl:8881" ovs_version: "2.0.0"
NOTE:
PKI configuration (required to use SSL): -p, --private-key=FILE file with private key -c, --certificate=FILE file with certificate for private key -C, --ca-cert=FILE file with peer CA certificate
Bridge 即网桥,但在 Linux 的语义中 Bridge 与 vSwitch 具备相同的含义,可见 Bridge 正式 Open vSwitch 最为核心的对象与概念。关于 Bridge 的概念再也不多谈,更详细的内容能够浏览《Networking 基本术语/概念》一文。下面主要记录了 OvS 关于 Bridge 的常见操做。
Bridge commands: add-br BRIDGE create a new bridge named BRIDGE add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN del-br BRIDGE delete BRIDGE and all of its ports list-br print the names of all the bridges br-exists BRIDGE exit 2 if BRIDGE does not exist br-to-vlan BRIDGE print the VLAN which BRIDGE is on br-to-parent BRIDGE print the parent of BRIDGE br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE br-set-external-id BRIDGE KEY unset KEY on BRIDGE br-get-external-id BRIDGE KEY print value of KEY on BRIDGE br-get-external-id BRIDGE list key-value pairs on BRIDGE # Bridge 管理操做 ovs-vsctl show ovs-vsctl add-br <bridge> ovs-vsctl del-br <bridge> ovs-vsctl --if-exists del-br <bridge> ovs-vsctl add-port <bridge> <port>|<interface> ovs-vsctl del-port <bridge> <port>|<interface> ovs-vsctl list <bridge>|<port>|<interface> ovs-vsctl list bridge <bridge> # 建立 Bridge 的同时为 Bridge 添加 Port/Interface ovs−vsctl add−br <bridge> -- add−port <bridge> <port>|<interface>
[root@localhost ~]# ovs-vsctl add-br ubuntu_br [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Port ubuntu_br Interface ubuntu_br type: internal ovs_version: "2.0.0"
[root@localhost ~]# ip link add first_br type veth peer name first_if [root@localhost ~]# ip link add second_br type veth peer name second_if [root@localhost ~]# ip link add third_br type veth peer name third_if
[root@localhost ~]# ip l 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 link/ether 00:0c:29:a2:2e:a4 brd ff:ff:ff:ff:ff:ff 3: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether f6:66:5f:f9:ba:17 brd ff:ff:ff:ff:ff:ff 4: ubuntu_br: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1000 link/ether 46:ca:9f:ed:0b:46 brd ff:ff:ff:ff:ff:ff 5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000 link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff 6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000 link/ether 52:54:00:69:fc:47 brd ff:ff:ff:ff:ff:ff 7: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:b8:9a:cf brd ff:ff:ff:ff:ff:ff 8: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:43:07:06 brd ff:ff:ff:ff:ff:ff 9: vnet2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT qlen 1000 link/ether fe:54:00:ce:e6:40 brd ff:ff:ff:ff:ff:ff 10: first_if@first_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 46:df:83:a6:66:bc brd ff:ff:ff:ff:ff:ff 11: first_br@file_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 72:90:6d:0d:4b:e0 brd ff:ff:ff:ff:ff:ff 12: second_if@second_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 6a:68:8f:38:86:a2 brd ff:ff:ff:ff:ff:ff 13: second_br@second_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 86:8d:e3:32:03:b4 brd ff:ff:ff:ff:ff:ff 14: third_if@third_br: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether 5e:72:4c:9b:4d:18 brd ff:ff:ff:ff:ff:ff 15: third_br@third_if: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 link/ether a2:cf:5f:72:da:23 brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ovs-vsctl add-port ubuntu_br first_br [root@localhost ~]# ovs-vsctl add-port ubuntu_br second_br [root@localhost ~]# ovs-vsctl add-port ubuntu_br third_br [root@localhost ~]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Port ubuntu_br Interface ubuntu_br type: internal Port first_br Interface first_br Port second_br Interface second_br Port third_br Interface third_br ovs_version: "2.0.0"
NOTE:Bridge ubuntu_br 的同名 Port,通常就是 Bridge 的管理端口了,类比物理交换机的管理端口,通常会为其配置 IP 地址。
OvS 是一个 OpenFlow Switch 实现,能够经过 OpenFlow Controller(OpenFlow 协议)对全部分布式的 Bridge 进行统一管理。所谓 “管理”,其实是对 Bridge 的 Flow Table 的管理。SDN Controller 的核心是控制策略的下发,并以此来决策数据的流向。
Controller 有两种类型:
OvS 为 Bridge 提供了下列两种 Fail Mode:
# 查询 Bridge 的 Fail Mode ovs-vsctl get-fail-mode ovs-br # 设置 Bridge 的 Fail Mode ovs-vsctl set-fail-mode ovs-br standalone ovs-vsctl set-fail-mode ovs-br secure # 移除 Bridge 的 Fail Mode ovs-vsctl del-fail-mode ovs-br # 查看 Bridge 和 Controller 的链接模式 ovs-vsctl get controller ovs-br connection-mode # 设置 Out-of-band 链接模式 ovs-vsctl set controller ovs-br connection-mode=out-of-band # 设置 In-band (default) 链接模式 ovs-vsctl set controller ovs-br connection-mode=in-band # 移除 hidden flow ovs-vsctl set bridge br0 other-config:disable-in-band=true
Controller 表结构:
# 设置 Controller ovs-vsctl set-controller <bridge> tcp:<controller_ip>:6633 # 设置 Multi Controller ovs-vsctl set-controller <bridge> tcp:<controller_ip1>:6633 tcp:<controller_ip2>:6633 # 获取 Bridge 的 Controller ovs-vsctl get-controller <bridge> # 移除 Controller ovs-vsctl del-controller <bridge>
OpenFlow Controller 的种类繁多,常见有如 OpenDaylight 等等,详细清单可浏览《OpenFlow Controllers in GENI》。本篇以 Floodlight 为例,感觉 Controller 对 Bridge 的流量控制功能。
官方网站:http://www.projectfloodlight.org/getting-started/
官方部署手册:https://floodlight.atlassian.net/wiki/spaces/floodlightcontroller/pages/1343544/Installation+Guide
Installing Floodlight:
git clone git://github.com/floodlight/floodlight.git cd floodlight/ git submodule init git submodule update ant sudo mkdir /var/lib/floodlight sudo mkdir /var/log/floodlight sudo chmod 777 /var/lib/floodlight
NOTE: 这里使用的是 Tag 1.2 版本
Running Floodlight in the Terminal:
nohup java -jar ~/floodlight/target/floodlight.jar > /var/log/floodlight/floodlight.log 2>&1 &
检查 Controller 的监听端口:
[root@localhost ~]# cat /var/log/floodlight/floodlight.log | grep "Listening for switch connections" 09:28:16.102 INFO [n.f.c.i.OFSwitchManager:main] Listening for switch connections on /0.0.0.0:6653 [root@localhost ~]# netstat -lpntu | grep 6653 tcp6 0 0 :::6653 :::* LISTEN 20159/java
NOTE:Floodlight 会经过监听 /0.0.0.0:6653
Socket 来获取 Bridge 的链接。
将 Bridge 链接到 Controller:
[root@localhost floodlight-1.2]# ovs-vsctl set-controller ubuntu_br tcp:192.168.1.109:6653 [root@localhost floodlight-1.2]# ovs-vsctl show 2028eafc-e1db-4ea8-b0fc-30a21fdaca0f Manager "ptcp:8881" Bridge ubuntu_br Controller "tcp:192.168.1.109:6633" Port ubuntu_br Interface ubuntu_br type: internal Port third_br Interface third_br Port first_br Interface first_br Port second_br Interface second_br ovs_version: "2.0.0"
NOTE:Bridge 链接到 Controller 以后,Controller 就能够收集、下发、管理 Bridge 的相关信息了(e.g. Flow Table)。
访问 Web GUI:
http://192.168.1.109:8080/ui/index.html
将三台 KVM 虚拟机接入到 Bridge:
[root@localhost ~]# virsh domiflist VM1 Interface Type Source Model MAC ------------------------------------------------------- macvtap1 direct ubuntu_br rtl8139 52:54:00:b8:9a:cf [root@localhost ~]# virsh domiflist VM2 Interface Type Source Model MAC ------------------------------------------------------- macvtap0 direct ubuntu_br rtl8139 52:54:00:43:07:06 [root@localhost ~]# virsh domiflist VM3 Interface Type Source Model MAC ------------------------------------------------------- macvtap2 direct ubuntu_br rtl8139 52:54:00:ce:e6:40
NOTE:VM一、二、3 都链接到同一个 Bridge 上,只要三者具备网段的 IP 地址就能够通讯了。
查看 Floodlight Dashboard:
等待一段时间 Floodlight 就会将会主机上的 Bridges、Bridge 上的 Hosts、Host 的 IP/MAC 地址等信息收集上来。
Floodlight Dashboard 基本上只做为展现,因此大部分操做依旧须要经过指令行来完成。
curl http://localhost:8080/wm/core/controller/switches/json
curl http://localhost:8080/wm/staticflowentrypusher/list/all/json
curl http://192.168.1.109:8080/wm/core/switch/00:00:46:ca:9f:ed:0b:46/flow/json
curl -d '{"switch": "00:00:00:00:00:00:00:01", "name":"flow-mod-1", "cookie":"0", "priority":"32768", "ingress-port":"1", "active":"true", "actions":"output=2"}' http://localhost:8080/wm/staticflowentrypusher/json
# VM1 curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow2", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:b8:9a:cf","active":"true", "actions":"output=10"}' http://localhost:8080/wm/staticflowentrypusher/json # VM3 curl -d '{"switch": "00:00:46:ca:9f:ed:0b:46", "name":"static-flow1", "cookie":"0", "priority":"32768", "src-mac":"52:54:00:ce:e6:40","active":"true", "actions":"output=12"}' http://localhost:8080/wm/staticflowentrypusher/json
curl -X DELETE -d '{"name":"flow-mod-1"}' http://localhost:8080/wm/staticflowentrypusher/json
curl http://localhost:8080/wm/staticflowentrypusher /clear/<dpid>/json
Mirror 的功能就是配置一个 Bridge 将某些具备特定条件的包发给指定的 Mirrored Ports。
包的条件有如下几种:
指定的目的 Ports 有如下两种:
Source (SPAN) port - A port that is monitored with use of the SPAN feature.
Destination (SPAN) port - A port that monitors source ports, usually where a network analyzer is connected.
ovs-vsctl add-br ovs-br ovs-vsctl add-port ovs-br eth0 ovs-vsctl add-port ovs-br eth1 # 设置 SPAN Mirrors,将 ovs-br 上 add-port {eth0,eth1} Mirror 至 tap0 ovs-vsctl add-port ovs-br tap0 \ -- --id=@p get port tap0 \ -- --id=@m create mirror name=m0 select-all=true output-port=@p \ -- set bridge ovs-br mirrors=@m # 删除 SPAN Mirrors ovs-vsctl clear bridge ovs-br mirrors
Open vSwitch 支持的网卡类型:
netdev:通用网卡设备(e.g. eth0、veth)
internal:虚拟网卡设备
gre device:隧道设备(无论用户态建立多少个 GRE Tunnel,在内核态有且只有一个 GRE 设备)
Port 的一个重要的特性就是 VLAN Configuration,具备两种类型:
Trunk Port:
简而言之,就是物理交换机的 Trunk 口,符合 Trunks 列表的 VLAN ID 可经过。
Access Port:
简而言之,由 Access Port 接收到的包会被打上 Tag,Access Port 只接收 Untag 包,不然丢弃。具备相同 VLAN ID 的包会给转发到对应的 Access Port 而后解除 Tag 再发出。
# 添加 Port 并设置 VLAN tag,ID 为 3 ovs-vsctl add-port <bridge> <vlan_access_interface> tag=3 -- set interface <vlan_access_interface> type=internal # 为已存在的 Port 设置 VLAN tag,ID 为 9 ovs-vsctl set port <port> tag=9 # 移除 VLAN tag ovs-vsctl del-port <bridge> <vlan_access_interface> # 查询 VLAN ifconfig <vlan_access_interface> # 设置 Vlan Trunk ovs-vsctl add-port <bridge> <vlan_trunk_interface> trunk=3,4,5,6 # 添加设置 VLAN 的 Flow,ID 为 100 ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=mod_vlan_vid:100,output:3 ovs-ofctl add-flow <bridge> in_port=1,dl_vlan=0xffff,actions=push_vlan:0x8100,set_field:100-\>vlan_vid,output:3 # 添加摘除 VLAN tag 的 Flow ovs-ofctl add-flow <bridge> in_port=3,dl_vlan=100,actions=strip_vlan,output:1 # ovs-ofctl add-flow pop-vlan ovs-ofctl add-flow ovs-br in_port=3,dl_vlan=0xffff,actions=pop_vlan,output:1
Port 和 Interface 的关系是一对多的关系,由于 OvS 支持 Bond 功能。所谓 Bond 就是将多个 Interface “捆绑” 在一块儿造成一个虚拟的链接,从而实现高可用性以及高吞吐量的效果。
常见的 bond_mode 有如下几种:
PS:LACP (Link Aggregation Control Protocol,链路聚合控制协议)。
OvS 的 bond 模型:
OvS 中的 Qos 每每是和 Flow Policy 一块儿使用的。总所周知 QoS 有两个方向,一个是入方向(Ingress),一个是出方向(Egress)。
在 Linux 上最经常使用的网络 QoS 就是 TC 工具,其主要是经过 队列 的方式来实现的。
1.Classless Queuing Disciplines:默认为 pfifo_fast,是一种不把网络包分类的技术。pfifo_fast 根据网络包中的 TOS 对应的数字,在 TOS 的 priomap 中查看对应的 Band,不一样的 Band 对应的不一样的队列。
2. SFQ, Stochastic Fair Queuing:有不少的 FIFO 的队列,TCP Session 或者 UDP stream 会被分配到某个队列。包会 RoundRobin 的从各个队列中取出发送。这样一个 Session 就不会占据全部的流量。但不是每个 Session 都具备一个队列,而是经过 Hash 算法,将大量的 Session 分配到有限的队列中。这样两个或若干个 Session 会共享一个队列,也有可能互相影响。所以 Hash 函数会常常改变,从而 Session 不会老是相互影响。
3. TBF, Token Bucket Filter:全部的网络包排成队列进行发送,但不是到了队头就能发送,而是须要拿到 Token 的包才能发送。Token 根据设定的速率(Rate)生成,因此即使队列很长,也会按照 Rate 进行发送。当没有包在队列中时,Token 仍是以既定的速度生成,可是并不是无限累积,而是到 Buckets 放满为止,篮子(buckets)的大小经常使用 burst/buffer/maxburst 参数来设定。Buckets 会避免下面这种状况:当长时间没有包发送的时候,积累了大量的 Token,忽然来了大量的包,每一个都能获得 Token,形成瞬间流量大增。
4. Classful Queuing Disciplines:其中典型的为 HTB, Hierarchical Token Bucket。
# 建立一个 HTB 的 qdisc 在 eth0 上,句柄为 1:,default 12 表示默认发送给 1:12。 tc qdisc add dev eth0 root handle 1: htb default 12 # 建立一个 root class,而后再建立几个 sub class。 # 同一个 root class 下的 sub class 能够相互借流量,若是直接不在 qdisc下面建立一个 root class,而是直接建立三个 class,他们之间是不能相互借流量的。 tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:11 htb rate 10kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:12 htb rate 60kbps ceil 100kbps # 建立叶子 qdisc,分别为 fifo 和 sfq。 tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5 tc qdisc add dev eth0 parent 1:11 handle 30: pfifo limit 5 tc qdisc add dev eth0 parent 1:12 handle 40: sfq perturb 10 # 设定规则:从 IP 1.2.3.4 来的而且发送给 port 80 的包,从 1:10 走;其余从 1.2.3.4 发送来的包从 1:11 走;其余的走默认。 # 实现了限速与分流。 tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10 tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11
实际上 OvS 能控制的只有 Egress QoS,经过 Shaping 实现。而 Ingress QoS 是没法控制的,只能经过 Policy 将指定的包丢弃。
Ingress policy:
ovs-vsctl set Interface tap0 ingress_policing_rate=100000 ovs-vsctl set Interface tap0 ingress_policing_burst=10000
Egress shaping:Port QoS policy 仅支持 HTB。
OvS 支持三种隧道类型,这三种 Tunnel 的原理均在 《Networking 基础术语/概念》中讲过,再也不赘述。
# Instance1 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.1/24 ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.100 options:remote_ip=192.168.100.101 ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.100 options:remote_ip=192.168.100.102 # Instance2 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.2/24 ovs-vsctl add-port testbr gre0 -- set Interface gre0 type=gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.100 ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.101 options:remote_ip=192.168.100.102 options:psk=password # Instance3 ovs-vsctl add-br testbr ifconfig testbr 10.0.0.3/24 ovs-vsctl add-port testbr vxlan0 -- set Interface vxlan0 type=vxlan options:local_ip=192.168.100.102 options:remote_ip=192.168.100.100 ovs-vsctl add-port testbr ipsec0 -- set Interface ipsec0 type=ipsec_gre options:local_ip=192.168.100.102 options:remote_ip=192.168.100.101 options:psk=password # enable STP,避免环致使的洪泛(Flood) # Spanning Tree Protocol,即经过协议,将一个有环的二层网络变成一颗树。 ovs-vsctl set Bridge testbr stp_enable=true
Open vSwitch 定义了一系列的 Flow Table,经过这些 Tables 来控制网络包的流向和结构。
根据 OpenFlow 协议,一行 Flow Entry 应该由两部分组成:
若是数据包符合 Match 则执行 Action。
Match Field 对网络包进行解析,解析的内容涵盖了 TCP/IP 协议族各层,具备下列字段,看这些字段是否可以匹配某个值。
Action 主要包含下列操做:
OvS 对 Flow Table 的管理,主要经过 ovs-ofctl 工具来完成:
# 查看 Bridge 的流表 ovs-ofctl show <bridge> # 查询指定 Bridge 的流表 ovs-ofctl dump-flows <bridge> # 添加 Bridge 的流表 ovs-ofctl add−flow <bridge> <flow> # e.g. ovs-ofctl add-flow ovs_br dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2,actions=output:6 # 修改 Bridge 的流表 ovs-ofctl mod−flows <bridge> <flow> # 删除 Bridge 的指定流表 ovs-ofctl del−flows <bridge> <flow> # e.g. ovs-ofctl del-flows <bridge> dl_src=02:a2:a2:a2:a2:a2,dl_dst=02:b2:b2:b2:b2:b2,in_port=2,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2 # 删除 Bridge 的全部流表 ovs-ofctl del-flows <bridge> # This will delete all the flow entries in the flow table
http://www.javashuo.com/article/p-gxyfutsg-nb.html
https://blog.csdn.net/w0823m/article/details/71319973
http://www.javashuo.com/article/p-eoiqiurt-dy.html