OVS架构

Open vSwitch

Open vSwitch 是一个开源的虚拟交换机实现。广泛应用在云计算行业,为网络管理员提供虚拟云主机之间和之内的流量可见性与可控性。Open vSwitch 旨在用虚拟化方案解决网络问题,与控制器软件一起实现分布式的虚拟交换技术。这意味着,交换机和控制器软件能够在多个服务器之间创建集群网络配置,从而不需要在每一台云主机和物理主机上单独配置网络。这个交换机还支持 VLAN 中继,通过 NetFlow、sFlow 和 RSPAN 实现可见性,通过 OpenFlow 协议进行管理。它还有其他一些特性:严格流量控制,它由 OpenFlow 交换协议实现;远程管理功能,它能通过网络策略实现更多控制。

在虚拟交换机的 Flow 控制器或管理工具方面,OvS 需要借助第三方控制器或管理工具实现复杂的转发策略。例如 OvS 支持 OpenFlow 协议,我们就可以使用任何支持 OpenFlow 协议的控制器来对 OvS 进行远程管理。但这并不意味着 OvS 必须要有一个控制器才能工作。在不连接外部控制器情况下,OvS 自身可以依靠 MAC 地址学习实现二层数据包转发功能,就像 Linux Bridge。

ogre 架构 ovs架构_运维

Open vSwitch 的特性清单:

* 支持通过 NetFlow、sFlow、IPFIX、SPAN、RSPAN 和 GRE-tunneled 镜像使
  虚拟机内部通讯可以被监控;
* 支持 LACP(IEEE 802.1AX-2008,多端口绑定)协议;
* 支持标准的 802.1Q VLAN 模型以及 Trunk 模式;
* 支持 BFD 和 802.1ag 链路状态监测;
* 支持 STP(IEEE 802.1D-1998);
* 支持细粒度的 QoS;
* 支持 HFSC 系统级别的流量控制队列;
* 支持每虚拟机网卡的流量的流量控制策略;
* 支持基于源 MAC 负载均衡模式、主备模式、L4 哈希模式的多端口绑定;
* 支持 OpenFlow 协议(包括许多虚拟化的增强特性);
* 支持IPV6
* 支持多种隧道协议(GRE, VXLAN, IPsec, GRE and VXLAN over IPsec)
* 支持通过 C 或者 Python 接口远程配置;
* 支持内核态和用户态的转发引擎设置;
* 支持多列表转发的发送缓存引擎;
* 支持转发层抽象以容易的定向到新的软件或者硬件平台;

架构组成

OvS 主要由三部分组件构成:

用户空间: ovsdb-server,ovs-vswitchd,ovs-vsctl/ovs-ofctl/ovs-dpctl等
内核空间:datapath、vswitchd、ovsdb
Controller: 表示 OpenFlow 控制器,控制器与 OvS 是通过 OpenFlow 协议进行连接

三大部分模式图:

ogre 架构 ovs架构_网络_02

架构组件图:

ogre 架构 ovs架构_内核态_03

组件细节:

ovs-vswitchd:主要模块,实现内核datapath upcall 处理以及ofproto 查表,
             同时是dpdk datapath处理程序。
             
ovsdb-server:数据库服务程序, 使用目前普遍认可的ovsdb 协议。

ovs-vsctl:网桥、接口等的创建、删除、设置、查询等。

ovs-dpctl:配置vswitch内核模块

ovs-appctl:发送命令消息到ovs-vswithchd, 查看不同模块状态

ovs-ofctl:下发流表信息。该命令可以配置其他openflow 交换机(采用openflow 协议)

ogre 架构 ovs架构_架构_04

ovsdb

ovsdb 是 OvS 轻量级的数据库服务,用于存储整个 OvS 的配置信息,包括接口、交换内容、VLAN、虚拟交换机的创建、网卡的添加等信息与操作记录,都被 ovsdb 保存到一个 conf.db 文件(JSON 格式)里面,通过 db.sock 提供服务。OvS 主进程 ovs-vswitchd 根据数据库中的配置信息工作。

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

## /etc/openvswitch/conf.db:

是数据库文件存放位置,ovsdb-server 需要该文件才能启动,
可使用 ovsdb-tool create 命令创建并初始化此数据库文件。

## --remote=punix:/var/run/openvswitch/db.sock:

实现了一个 Unix Sockets 连接,OvS 主进程 ovs-vswitchd 或其它命令工具
(e.g. ovsdb-client) 通过这个 Socket 连接来管理 ovsdb。

ogre 架构 ovs架构_内核态_05

ovs-vswitchd

ogre 架构 ovs架构_ogre 架构_06

ovs-vswitchd 本质是一个守护进程,是 OvS 的核心部件。ovs-vswitchd 和 Datapath 一起实现 OvS 基于流表(Flow-based Switching)的数据交换。

功能:

通过 OpenFlow 协议可以与 OpenFlow 控制器通信
使用 ovsdb 协议与 ovsdb-server 数据库服务通信
使用 netlink 和 Datapath 内核模块通信。

责职:

ovs-vswitchd 支持多个独立的 Datapath,ovs-vswitchd 需要加载 Datapath 内核模块才能正常运行。
ovs-vswitchd 在启动时读取 ovsdb-server 中的配置信息,然后自动配置 Datapaths 和 OvS Switches
的 Flow Tables,所以用户不需要额外的通过执行 ovs-dpctl 指令工具去操作 Datapath。
当 ovsdb 中的配置内容被修改,ovs-vswitched 也会自动更新其配置以保持数据同步。
ovs-vswitchd 也可以从 OpenFlow 控制器获取流表项。

配置:

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

datapath

Datapath模块能够从网卡接收并处理流量的原理:

Datapath 加载到内核后,会在网卡上注册一个钩子函数,每当有网络包到达网卡时,
这个函数就会被调用,将网络包开始层层拆包(MAC 层,IP 层,TCP 层等),
然后与流表项匹配,如果找到匹配的流表项则根据既定策略来处理网络包
(e.g. 修改 MAC,修改 IP,修改 TCP 端口,从哪个网卡发出去等等),
再将网络包从网卡发出。

在 OpenFlow Switch 规则的语义中,给交换机,或者桥,用了一个专业的名词,叫做 Datapath。Open vSwitch 的内核模块 openvswitch.ko 实现了多个 Datapath,每个 Datapath 可以具有多个 Ports。每个 Datapath 通过关联流表(Flow Table)来定义网络包的流向。Datapath 监听网卡接口设备,将监听到的数据包首先在流表中进行匹配,找到匹配的流表项之后把对应的 Actions 返回给 Datapath,作为数据处理行为的描述。Datapath 支持数据在内核空间进行交换。

Datapath 的内核模块信息:

# modinfo openvswitch
filename:       /lib/modules/3.10.0-327.el7.x86_64/kernel/net/openvswitch/openvswitch.ko
license:        GPL
description:    Open vSwitch switching datapath
rhelversion:    7.2
srcversion:     F75F2B83324DCC665887FD5
depends:        libcrc32c
intree:         Y
...

工作原理:

Bridge 处理数据帧遵循以下几条规则:

* 在一个 Port 上接收到的帧不会再往此 Port 发送此帧。

* 接收到的帧都要学习其 Source MAC 地址。

* 如果数据帧是多播或者广播包(通过 2 层 MAC 地址确定)则要向接收 Port 以外的
  所有 Port 转发,如果上层协议感兴趣,则还会递交上层处理。
   
* 如果数据帧的地址不能在 CAM(MAC-Port Mapping)表中找到,
  则向接收 Port 以外的所有 Port 转发。
  
* 如果 CAM 表中能找到,则转发给相应 Port,如果发送和接收都是同一个 Port,则不发送。

* 网桥是以混杂模式工作的,所有 MAC 地址的数据帧都能够通过。

用户空间 ovs-vswitchd 和内核模块 Datapath 决定了数据包的转发,如下图:

ogre 架构 ovs架构_网络_07

数据流向:

1、内核态的 Datapath 监听接口设备流入的数据包。

2、如果 Datapath 在内核态流表缓存没有找到相应的匹配流表项则将数据包传入
   (upcall)到用户态的 ovs-vswitchd 守护进程处理。

3、(可选)用户态的 ovs-vswitchd 拥有完整的流表项,通过 OpenFlow 协议与
    OpenFlow 控制器或者 ovs-ofctl 命令行工具进行通信,
    主要是接收 OpenFlow 控制器南向接口的流表项下发。或者根据流表项设置,
    ovs-vswitchd 可能会将网络包以 Packet-In 消息发送给 OpenFlow 控制器处理。
    
4、ovs-vswitchd 接收到来自 OpenFlow 控制器或 ovs-ofctl 命令行工具的消息后
   会对内核态的 Flow Table 进行更新。或者根据局部性原理,
   用户态的 ovs-vswitchd 会将刚执行过的 Datapath 没有缓存的流表项注入到Flow Table

5、ovs-vswitchd 匹配完流表项之后将数据包重新注入(reinject)到 Datapath。

6、Datapath 再次访问 Flow Table 获取流表项进行匹配。

7、最后,网络包被 Datapath 根据流表项 Actions 转发或丢弃。

上述,Datapath 和 ovs-vswitchd 相互配合中包含了两种网络包的处理方式:

Fast Path:

Datapatch 加载到内核后,会在网卡上注册一个钩子函数,每当有网络包到达网卡时,
这个函数就会被调用,将网络包开始层层拆包(MAC 层,IP 层,TCP 层等),
然后与流表项匹配,如果找到匹配的流表项则根据既定策略来处理网络包
(e.g. 修改 MAC,修改 IP,修改 TCP 端口,从哪个网卡发出去等等),
再将网络包从网卡发出。这个处理过程全在内核完成,所以非常快,称之为 Fast Path。

Slow Path:(造成首包延迟的原因)

内核态并没有被分配太多内存,所以内核态能够保存的流表项很少,往往有新的流表项到来后,
老的流表项就被丢弃。如果在内核态找不到流表项,则需要到用户态去查询,
网络包会通过 netlink(一种内核态与用户态交互的机制)发送给 ovs-vswitchd,
ovs-vswitchd 有一个监听线程,当发现有从内核态发过来的网络包,就进入自己的处理流程,
然后再次将网络包重新注入到 Datapath。
显然,在用户态处理是相对较慢的,故称值为 Slow Path。

ogre 架构 ovs架构_运维_08

在用户态的 ovs-vswtichd 不需要吝啬内存,它包含了所有流表项,这些流表项可能是 OpenFlow 控制器通过 OpenFlow 协议下发的,也可能是 OvS 命令行工具 ovs-ofctl 设定的。ovs-vswtichd 会根据网络包的信息层层匹配,直到找到一款流表项进行处理。如果实在找不到,则一般会采用默认流表项,比如丢弃这个包。

当最终匹配到了一个流表项之后,则会根据 “局部性原理(局部数据在一段时间都会被频繁访问,是缓存设计的基础原理)” 再通过 netlink 协议,将这条策略下发到内核态,当这条策略下发给内核时,如果内核的内存空间不足,则会开始淘汰部分老策略。这样保证下一个相同类型的网络包能够直接从内核匹配到,以此加快执行效率。由于近因效应,接下来的网络包应该大概率能够匹配这条策略的。例如:传输一个文件,同类型的网络包会源源不断的到来。

ogre 架构 ovs架构_运维_09

工具命令:

ovs-vsctl:用于管理 ovs-vswitchd 的配置信息。
ovs-ofctl:用于管理 OvS 的流表信息。
ovs-pki:用于管理 OvS 与 OpenFlow Controller 之间的 TSL 通信框架。
ovs-dpctl:用于管理 Datapath,比如查看 Datapath 信息。
ovs-appctl:应用层的指令集,例如:模拟数据包用于测试 OvS Switch 数据转发流程。

ogre 架构 ovs架构_ogre 架构_10

参考链接:
https://houmin.cc/posts/7e150da0/