当前位置: 首页 > news >正文

OpenvSwitch/OpenFlow 架构解析与实践案例

目录

文章目录

  • 目录
  • 前言
  • 软件定义网络(SDN)
    • 虚拟交换机(vSwitch)
    • 为什么说云计算时代的 SDN 非常重要
  • OpenFlow 简介
  • Open vSwitch
    • Open vSwitch 的架构
      • ovsdb(ovsdb-server)
      • ovs-vswitchd(vswitchd)
      • Datapatch(openvswitch.ko)
      • OvS 的工具集
      • ovs-vsctl 常用指令
    • Open vSwitch 的工作原理
    • OpenvSwitch 的典型工作流程
    • Open vSwitch 的安装部署
    • Open vSwitch 的 DB(ovs-db)
  • Open vSwitch 的操作对象
    • Manager
      • 配置 Manager OvS DB Connection
    • SSL
      • 配置 SSL Connection
    • Bridge
      • Bridge 常用操作指令
    • Controller
      • Controller 常用指令
      • 安装 Floodlight
      • 将 KVM 虚拟机接入 OvS Bridge
      • Floodlight Controller 常用指令
    • Mirror
      • SPAN
      • RSPAN
    • Interface
    • Port
      • Port 与 VLAN
      • Port 与 VLAN 的常用操作指令
      • Port 与 Bond
      • Port 与 QoS
      • 网络流程 QoS 的实现原理与方式
      • 使用 TC 创建一个 HTB(Hierarchical Token Bucket)树
    • Tunnel
      • OvS Tunnel 的操作指令示例
    • Flow Table
      • 常用流表操作指令
  • 参考文档

前言

该篇文章是在《通俗说 Openvswitch》的基础上再结合我再网上收集的资料进行学习、整理与归纳,感谢刘大(公众号:刘超的通俗云计算)以及创作者的分享。

软件定义网络(SDN)

软件定义有啥好处呢?
想象你有一个大的数据中心,里面有很多的网络设备,光交换机就有很多,你希望在交换机上配置一些网络的策略,例如某个口应该属于某个 VLAN。
怎么配置呢?登到这台交换机上去,敲几行命令就搞定了。
如果要配置 100 台交换机呢?头大了吧,难不成登陆 100 台?
想不想有一个集中的地方,能看到整个网络的拓扑图,统一配置一下,然后一回车,配置的策略就通过管理网络平面下发到 100 台交换机上。这样整个网络的拓扑结构就不是硬的了,也即不是通过插线,拔线,登陆盒子配置的,而是变成了软的,也即通过软件统一控制,这个统一控制的地方我们称为 SDN Controller(控制器),这样的网络拓扑结构,我们称为软件定义的网络

虚拟交换机(vSwitch)

虚拟交换机(vSwitch)就是利用虚拟平台,通过软件的方式实现(Software Defined Network,SDN,软件定义网络)的交换机部件。跟传统的物理交换机相比,虚拟交换机具备众多优点:一是配置灵活,一台普通的服务器可以配置出数十台甚至上百台虚拟交换机,且端口数目也可以灵活选择。例如,一台 VMware ESXi 服务器可以仿真出 248 台虚拟交换机,且每台交换机预设虚拟端口即可达 56 个;二是成本低廉,通过虚拟交换同样可以获得昂贵的普通交换机才能达到的性能,例如,微软的 Hyper-V,虚拟机与虚拟交换机之间的联机速度轻易可达 10Gbps。

为什么说云计算时代的 SDN 非常重要

因为虚拟机的创建,删除,迁移比物理机灵活的多,所以很难像物理的交换机一样,用网线将交换机和物理服务器连接起来,就不怎么变了。虚拟机就不一样了,所以需要虚拟交换机,也即通过软件模拟一个交换机,用软件模拟一根网线,一头插在虚拟机上,一头插在虚拟交换机上,一会儿创建五个虚拟机,要插到一个交换机上,一会儿其中两个虚拟机迁移到了另外的物理机上,则他们两个的网口要从上一台交换机上拔下来,插到新的虚拟交换机上,这样做没有问题,因为都是软件实现的,很灵活。

OpenFlow 简介

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”.

OpenFlow,一种网上通信协议,属于数据链路层,能够控制网上交换器或路由器的数据转发平面(Forwarding Plane),借此改变网上数据包所经过的网上路径。简而言之,OpenFlow 就是 SDN Controller 远程控制网络设备的协议,经由网上交换器,决定网上数据包要由何种路径通过网络交换机。虽然 OpenFlow 的功能不如各大网络厂商的自家协议强大,但正因如此,OpenFlow 成为了一个兼容非常高的功能子集,以至于让各网络厂商能够达成了部分的共识。

OpenFlow 允许从远程控制网上交换器的数据包转送表,透过新增、修改、移除数据包控制规则与行动,来改变数据包转送的路径。比起用访问控制表(ACLs)和路由协议,允许更加复杂且灵活的流量管理。同时,OpenFlow 允许不同网络供应商用一个简单,开源的协议去远程管理交换机(通常提供专有的接口和描述语言)。OpenFlow 协议用来描述控制器和交换机之间交互所用信息的标准,以及控制器和交换机的接口标准。

在这里插入图片描述

Open vSwitch

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 交换协议实现;远程管理功能,它能通过网络策略实现更多控制。
在这里插入图片描述

简而言之,Open vSwitch 即开放的软件虚拟交换机,能够达到产品级的质量,也就是说可以部署一些生产环境使用。它不光支持基本的二层交换,还支持标准的管理机接口和协议(e.g. NetFlow,sFlow,SPAN,RSAPN,CLI,LACP,802.1ag),同时也支持 OpenFlow,可以很好的与 SDN 体系融合

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 接口远程配置;
  • 支持内核态和用户态的转发引擎设置;
  • 支持多列表转发的发送缓存引擎;
  • 支持转发层抽象以容易的定向到新的软件或者硬件平台;

Open vSwitch 的架构

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ovsdb(ovsdb-server)

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

ovs-vswitchd(vswitchd)

OvS 的核心部件,实现交换功能,与 Linux 内核兼容模块一起实现基于流的交换(Flow-based Switching)。它和上层 Controller 通信遵从 OpenFlow 协议,它与 ovsdb-server 通信遵从 OVSDB 协议,它和内核模块通过 netlink 进行通信,它支持多个独立的 Datapath(网桥),它通过更改 Flow Table 实现了 Binding(绑定)和 VLAN 等功能。是真正的虚拟交换机生命周期管理进程。它通过 db.sock 文件从 ovsdb-server 进程读取 conf.db 的配置信息(e.g. 用户所创建的虚拟交换机、所添加的网卡等等操作记录)。

Datapatch(openvswitch.ko)

在 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 的工具集

  • ovs-vsctl:用于获取、更改 ovs-vswitchd 的配置信息。
  • ovs-ofctl:用于查询、控制 OvS 作为 OpenFlow 交换机工作时的流表内容。
  • ovs-pki:用于创建、管理 OvS 与 Controller 之间的 SSL 通信框架。
  • ovs-dpctl:用于配置 Switch 内核模块,可以控制转发规则。
  • ovs-appctl:用于向 ovs-vswitchd 守护进程发送命令消息,一般用不上。
    在这里插入图片描述

ovs-vsctl 常用指令

# 查看 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

Open vSwitch 的工作原理

要理解 OvS 的工作原理,首先要了解网桥的工作原理。网桥也叫做桥接器,工作在数据链路层,将两个 LAN 连接,根据 MAC 地址来转发数据帧,可以看成一个 “低层的路由器”。网桥处理数据帧遵循以下几条规则:

  • 在一个接口上接收到的帧不会再往那个接口上发送此帧。
  • 每个接收到的帧都要学习其 Source MAC 地址。
  • 如果数据帧是多播或者广播包(通过 2 层 MAC 地址确定)则要向接收端口以外的所有端口转发,如果上层协议感兴趣,则还会递交上层处理。
  • 如果数据帧的地址不能在 CAM(MAC-Port Mapping)表中找到,则向接收端口以外的所有端口转发。
  • 如果 CAM 表中能找到,则转发给相应端口,如果发送和接收都是同一个端口,则不发送。
  • 网桥是以混杂模式工作的,所有 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 中的这些远程管理功能,云计算的集成商和供应商就能够向客户提供在一台计算机上持续管理各自虚拟网络、应用和策略的功能。

OpenvSwitch 的典型工作流程

在这里插入图片描述

  1. Instance 产生一个数据包并发送至虚拟网络接口 vNIC(Instance eth0)。
  2. 这个数据包传递到物理机的 vNIC 接口(vnet)。
  3. 数据包从 vnet 出来,到达 Bridge br100 上。
  4. 数据包经过 Bridge 的处理,从物理节点上的 NIC(eth0)发出。
  5. 数据包从 eth0 出去后,按照宿主机的路由以及默认网关操作。此时该数据包已经不再受你控制了。

NOTE:L2 Switch 连接到宿主机的 eth0 通常是一个 Trunk 口,因为虚拟机对应的 vnet 往往会设置 VLAN TAG 来隔离虚拟机的广播域。所以 eth0 就相当于一个 Trunk 口,而 vnets 就相当于 Access 口。

Open vSwitch 的安装部署

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)进行互相通信。

Open vSwitch 的 DB(ovs-db)

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.

  • Bridge 设备的配置
  • OvS 本身的配置
    • other_config:stats-update-interval:将统计信息写入数据库的间隔时间
    • other_config:flow-restore-wait: 针对 hot-upgrade,如果为 True 则不处理任何包。一般使用的过程为:先停掉 ovs-vswitchd,然后将这个值设为 True,再启动 ovs-vswitchd。这个时候不处理任何包,然后使用 ovs-ofctl 将 flow table restore 到一个正确的状态,最后设置这个值为 False,开始处理包。
    • other_config:flow-limit:指定 Flow Table 中 flow entry(入口)的数量
    • other_config:n-handler-threads:用于处理新 Flow 的线程数
    • other_config:n-revalidator-threads:用于验证 Flow 的线程数
    • other_config:enable-statistics:是否统计以下项目
      • statistics:cpu:统计 CPU 数量,线程
      • statistics:load_average:system load
      • statistics:memory:总 RAM,Swap
      • statistics:process_NAME:统计 memory size, cpu time 等(with NAME replaced by a process name)
      • statistics:file_systems:mount point, size, used
    • client request id:cur_cfg 和 next_cfg,当一个 Client 修改完数据库时,next_cfg 加 1,然后等待 OvS 应用这些修改,当应用完毕,则 cur_cfg 加 1,此时 cur_cfg 等于 next_cfg。显然,该配置是为了保证高并发请求的一致性而存在的。
    • 对 ovsdb-server 的配置,指向 Manager 表,ovs-vswitchd 作为 ovsdb-server 的 Client 之一,Manager 配置了 DB Connection 的字段。
    • 对 SSL DB Connection 的配置:指向 SSL 表,主要配置 SSL 安全通信所需要的 private key、certificate 等文件的路径。

Open vSwitch 的操作对象

数据库结构是一款软件的资源模型设计的映射,下文主要根据 OvS 的资源模型来依次认识每种资源对象的特性与作用。

Manager

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 上,协议为 SSL
    • tcp:ip[:port]:监听在指定 Remote IP 的 Port 上,协议为 TCP
    • unix:FILE:Unix domain socket named FILE
  • Passive(被动)database connection methods:

    • pssl:[port][:ip]:监听在本机 IP 的指定 Port 上,协议为 SSL
    • ptcp:[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。

配置 Manager OvS DB Connection

[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:注意防火墙的干扰因素。

SSL

如果将 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 表属性

  • private_key:私钥
  • ca_cert:CA 根证书
  • bootstrap_ca_cert(Boolean):如果为 True,则每次启动 ovsdb-server,都会向 Controller 获取最新的 CA 证书。否则,就继续使用旧的 CA 证书。
  • certificate:CA 签发的证书

其中主机(客户端)的 Public key 包含在 CA 签发的证书(certificate)内,然后再由 CA 中心的 private key 进行签名,CA 中心来担保这个 certificate 是合法的。为了验证 CA 签名,还需要 CA 的 public key,并放到 ca_cert 指向的 CA 证书里面。而 CA 本身的 public key 也需要被签名更高级的 CA 或者 CA(根 CA)自己担保。

SSL 验证流程

  1. 客户端持有 CA 根证书(ca_cert)并与 CA 的私钥进行验证(CA 根证书由 CA 通过自己的私钥进行自签发),验证成功则说明该 CA 是 root CA,可以自己担保自己。
  2. 客户端持有 CA 签发的证书(certificate,内含客户端公钥)并与 CA 根证书进行验证(由 CA 签发的证书可以使用 CA 私钥解开),如果验证成功则返回客户端的公钥。
  3. 客户端持有自己的私钥并与 CA 解开的客户端公钥进行验证,验证成功,则说明该客户端是受到 CA 担保的。
  4. 客户端与服务器建立 SSL 连接。
    在这里插入图片描述
    简而言之,客户端需要保证持有自己的私钥、CA 签发的证书、CA 根证书才可以完成 SSL 验证。更多 CA 自签发的内容,请浏览《自建 CA 中心并签发 CA 证书》。
# 查询 SSL 连接
ovs-vsctl get-ssl
# 设置 SSL 证书
ovs-vsctl set-ssl sc-privkey.pem sc-cert.pem cacert.pem
# 删除 SSL 连接
ovs-vsctl del-ssl

配置 SSL Connection

自签发 CA 根证书

  • Step 1. 生成 CA 根证书的 RSA 私钥
mkdir ~/OVS_CA
cd ~/OVS_CA

openssl genrsa -out caprivate.key 1024
  • Step 2. 生成 CA 根证书的签名请求(CSR)
openssl req -key caprivate.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=fanguiju@163.com" -out cacertificate.req
  • Step 3. 自签发CA 根证书(内含了 CA 的公钥)
openssl x509 -req -in cacertificate.req -signkey caprivate.key -out cacertificate.pem

PS:自签发即自己担保自己,用自己的私钥对自己的 CSR 进行签发,所以也称为根证书。

签发客户端证书

  • Step 1. 生成客户端私钥
mkdir ~/ClientCerts
cd ~/ClientCerts

openssl genrsa -out cliu8private.key 1024
  • Step 2. 生成客户端签名请求
openssl req -key cliu8private.key -new -subj "/C=CN/ST=CN/L=CN/O=CN/CN=cliu8@163.com" -out cliu8certificate.req
  • Step 3. CA 中心签发客户端证书(CA 中心担保该客户端)
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"

验证

  • 此时如果不输入 PKI 配置则无法通过 SSL 认证
[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)
  • 将 cliu8private.key、cliu8certificate.pem、cacertificate.pem 的副本复制到客户端
scp cliu8private.key cliu8certificate.pem cacertificate.pem root@192.168.1.110:~/certs
  • 在客户端请求建立 SSL 连接
[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

Bridge 即网桥,但在 Linux 的语义中 Bridge 与 vSwitch 具有相同的含义,可见 Bridge 正式 Open vSwitch 最为核心的对象与概念。关于 Bridge 的概念不再多谈,更详细的内容可以浏览《Networking 基本术语/概念》一文。下面主要记录了 OvS 关于 Bridge 的常见操作。

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"
  • 创建虚拟 “网线”(VETH pair):
[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 地址。

Controller

OvS 是一个 OpenFlow Switch 实现,可以通过 OpenFlow Controller(OpenFlow 协议)对所有分布式的 Bridge 进行统一管理。所谓 “管理”,实际上是对 Bridge 的 Flow Table 的管理。SDN Controller 的核心是控制策略的下发,并以此来决策数据的流向

Controller 有两种类型

  • Primary Controller:真正控制 Bridge 的 Flow Table,Bridge 会保持与 Controller 的连接,如果连接失败或断开,取决于 Bridge 的 Fail Mode 来进行处理。一个 Bridge 可以连接到多个 Controller,但是 Controller 之间的协作需要 Controller 自己来完成。
  • Service Controller:仅仅用于 Support,偶尔操作,Maintain 使用,如果 Connection 与 Bridge 断开连接,Bridge 的 Fail Mode 也不会起作用。

OvS 为 Bridge 提供了下列两种 Fail Mode

  • Secure:断开连接后 Bridge 会试图重连 Controller 直至成功,并不会自己维护 Flow Table。
  • Standalone:若 Bridge 尝试三次依旧连接不上 Controller,则会自己建立并维护独立的 Flow Table。
# 查询 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 常用指令

# 设置 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>

安装 Floodlight

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 虚拟机接入 OvS Bridge

将三台 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:VM1、2、3 都连接到同一个 Bridge 上,只要三者具有网段的 IP 地址就可以通信了。

查看 Floodlight Dashboard
在这里插入图片描述
等待一段时间 Floodlight 就会将会主机上的 Bridges、Bridge 上的 Hosts、Host 的 IP/MAC 地址等信息收集上来。

Floodlight Controller 常用指令

Floodlight Dashboard 基本上只作为展示,所以大部分操作依旧需要通过指令行来完成。

  • 请求该 Controller 上所有 Switch 的 DPID
curl http://localhost:8080/wm/core/controller/switches/json
  • 查看流表项
curl http://localhost:8080/wm/staticflowentrypusher/list/all/json
  • 查看指定 Switch 的流表项
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
  • 只允许 10.0.0.101 和 10.0.0.103 相互 Ping 的静态流表
# 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
  • 删除指定 Switch 所有流表
curl http://localhost:8080/wm/staticflowentrypusher /clear/<dpid>/json

Mirror

Mirror 的功能就是配置一个 Bridge 将某些具有特定条件的包发给指定的 Mirrored Ports。

包的条件有以下几种:

  • select_all
  • select_dst_port
  • select_src_port
  • select_vlan

指定的目的 Ports 有以下两种:

  • output_port (SPAN Switched Port ANalyzer)
  • output_vlan (RSPAN Remote Switched Port ANalyzer)

SPAN

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

RSPAN

  • 被监控的流量不是发送到一个指定的端口,而是 Flood 给指定的 VLAN
  • 监听的端口不一定要在本地 Switch 上,可以在指定的 VLAN 的任意 Switch 上
  • S1 is a source switch
  • S2 and S3 are intermediate switches
  • S4 and S5 are destination switches.
  • learning is disabled to enable flooding
    在这里插入图片描述

Interface

Open vSwitch 支持的网卡类型

  • netdev:通用网卡设备(e.g. eth0、veth)

    • 接收:一个 netdev 在 L2 收到报文后会直接通过 OvS 接收函数处理,不会再走传统内核 TCP/IP 协议栈。
    • 发送:OvS 中的一条流指定从该 netdev 发出的时候就通过该网卡设备发送。
  • internal:虚拟网卡设备

    • 接收:当从系统发出的报文路由查找通过该设备发送的时候,就进入 OvS 接收处理函数。
    • 发送:OvS 中的一条流制定从该 internal 设备发出的时候,该报文被重新注入内核协议栈。
  • gre device:隧道设备(不管用户态创建多少个 GRE Tunnel,在内核态有且只有一个 GRE 设备)

    • 接收:当系统收到 GRE 报文后,传递给 L4 层解析 gre header,然后传递给 OvS 接收处理函数。
    • 发送:OvS 中的一条流制定从该 GRE 设备发送,报文会根据流表规则加上 GRE 头以及外层包裹 IP,查找路由发送。

Port

Port 与 VLAN

Port 的一个重要的特性就是 VLAN Configuration,具有两种类型:

  • Trunk Port
  • Access Port

Trunk Port:

  • 这个 Port 不配置 Tag,配置 trunks。
  • 如果 trunks 为空,则所有的 VLAN 都 trunk,缺省 VLAN ID 为 0,全部允许通过。
  • 如果 trunks 不为空,则仅有符合条件(ID)的 VLAN 能通过。

简而言之,就是物理交换机的 Trunk 口,符合 Trunks 列表的 VLAN ID 可通过。

Access Port:

  • 这个 Port 配置 Tag,从这个 Port 进来的包都被打上 Tag(ID)。
  • 如果从其他的 Trunk Port 中进来的本身就带有 VLAN ID 的包,若 VLAN ID 等于这个 Port 的 Tag,则会从这个 Port 发出。
  • 从其他的 Access Port 进来的包,如果 Tag 相同,也会被 Forward 到这个 Port。
  • 从 Access Port 发出的包会被摘除 Tag,不带 VLAN ID。
  • 如果一个本身带 VLAN ID 的包到达 Access Port,即便 VLAN ID 等于 Tag,也会被抛弃,Access Port 只接受 Untag 包。

简而言之,由 Access Port 接收到的包会被打上 Tag,Access Port 只接收 Untag 包,否则丢弃。具有相同 VLAN ID 的包会给转发到对应的 Access Port 然后解除 Tag 再发出。

Port 与 VLAN 的常用操作指令

# 添加 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 与 Bond

Port 和 Interface 的关系是一对多的关系,因为 OvS 支持 Bond 功能。所谓 Bond 就是将多个 Interface “捆绑” 在一起形成一个虚拟的连接,从而实现高可用性以及高吞吐量的效果。

常见的 bond_mode 有以下几种:

  • active-backup:故障转移,一个连接 Active,其他连接 Backup。
  • balance-slb:负载均衡,根据源 MAC 和 output VLAN 进行负载均衡。
  • balance-tcp:负载均衡,必须在支持 LACP 协议的情况下才可以,可根据 L2, L3, L4 进行负载均衡。
  • stable(LACP):Attempts to always assign a given flow to the same slave consistently.

PS:LACP (Link Aggregation Control Protocol,链路聚合控制协议)。
在这里插入图片描述
OvS 的 bond 模型:
在这里插入图片描述

Port 与 QoS

OvS 中的 Qos 往往是和 Flow Policy 一起使用的。总所周知 QoS 有两个方向,一个是入方向(Ingress),一个是出方向(Egress)。

在这里插入图片描述

网络流程 QoS 的实现原理与方式

在 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

  • Shaping:仅仅发生在叶子节点,依赖于其他的 Queue。
  • Borrowing:当网络资源空闲的时候,借点过来为我所用。
  • Rate:设定的速率。
  • Ceil:最大的速率,与 Rate 之间的差值表示最多能向别人借多少。

在这里插入图片描述

使用 TC 创建一个 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。

  • 在 Port 上可以创建 QoS
  • 一个 QoS 可以有多个 Queue
  • 规则通过 Flow 设定

在这里插入图片描述

Tunnel

OvS 支持三种隧道类型,这三种 Tunnel 的原理均在 《Networking 基础术语/概念》中讲过,不再赘述。

  • GRE
  • VxLAN
  • IPSec_gre

OvS Tunnel 的操作指令示例

# 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

在这里插入图片描述

Flow Table

Open vSwitch 定义了一系列的 Flow Table,通过这些 Tables 来控制网络包的流向和结构。
在这里插入图片描述
在这里插入图片描述
根据 OpenFlow 协议,一行 Flow Entry 应该由两部分组成:

  • Match Field
  • Action

如果数据包符合 Match 则执行 Action。
在这里插入图片描述

Match Field 对网络包进行解析,解析的内容涵盖了 TCP/IP 协议族各层,具有下列字段,看这些字段是否能够匹配某个值。
在这里插入图片描述

  • Layer 1 – Tunnel ID, In Port, QoS priority, skb mark
  • Layer 2 – MAC address, VLAN ID, Ethernet type
  • Layer 3 – IPv4/IPv6 fields, ARP
  • Layer 4 – TCP/UDP, ICMP, ND

Action 主要包含下列操作:

  • Output to port (port range, flood, mirror)
  • Discard, Resubmit to table x
  • Packet Mangling (Push/Pop VLAN header, TOS, …)
  • Send to controller, Learn

常用流表操作指令

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

参考文档

https://www.cnblogs.com/popsuper1982/p/3800576.html
https://blog.csdn.net/w0823m/article/details/71319973
https://blog.csdn.net/tantexian/article/details/46707175

转载于:https://www.cnblogs.com/jmilkfan-fanguiju/p/10589725.html

相关文章:

  • CSS opacity设置不透明度
  • runC爆严重安全漏洞,主机可被攻击!使用容器的快打补丁
  • CH5102 Mobile Service
  • 区块链共识机制优缺点对比都是什么
  • Python数据可视化的10种技能
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • sql语句实战
  • 小程序微服务单个SSL证书部署多个项目解决方案
  • Async注解的使用,异步进行代码解耦
  • 我们在编写python代码时应该注意那几件事 !
  • Collection和Collections的区别是什么?
  • 根据出生日期计算年龄
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • centos7系统安装完成初始化
  • tkinter内嵌Matplotlib系列(一)之解读官网教材
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • js数组之filter
  • magento2项目上线注意事项
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • nodejs实现webservice问题总结
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Service Worker
  • vue-cli在webpack的配置文件探究
  • windows下mongoDB的环境配置
  • 官方解决所有 npm 全局安装权限问题
  • 批量截取pdf文件
  • 算法-图和图算法
  • 树莓派用上kodexplorer也能玩成私有网盘
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • # Apache SeaTunnel 究竟是什么?
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (12)Linux 常见的三种进程状态
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (九十四)函数和二维数组
  • (算法)求1到1亿间的质数或素数
  • (一)appium-desktop定位元素原理
  • (转)ABI是什么
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)四层和七层负载均衡的区别
  • .form文件_一篇文章学会文件上传
  • .net 受管制代码
  • .net对接阿里云CSB服务
  • @ConditionalOnProperty注解使用说明
  • [145] 二叉树的后序遍历 js
  • [Android 13]Input系列--获取触摸窗口
  • [Android]使用Git将项目提交到GitHub
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [C++]:for循环for(int num : nums)
  • [CF]Codeforces Round #551 (Div. 2)
  • [CSS] 点击事件触发的动画
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误
  • [FxCop.设计规则]8. 也许参数类型应该是基类型
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)