| |||||
| |||||
|
Open vSwitch概述
Open vSwitch(下面简称OVS)是一个高质量的、多层虚拟交换机。OVS遵循开源Apache2.0许可,通过可编程扩展,OVS可以实现大规模网络的自动化(配置、管理、维护),OVS也提供了对 OpenFlow协议的支持,用户可以使用任何支持 OpenFlow协议的控制器对 OVS进行远程管理控制,同时支持现有标准管理接口和协议比如NetFlow、sFlow、SPAN(本地端口镜像)、RSPAN(远程端口镜像)、CLI(命令行界面)、LACP(链路汇聚)、802.1ag等。此外OVS支持多种linux虚拟化技术,包括Xen/XenServer,KVM和VirtualBox等,在虚拟化平台上,OVS可以为动态变化的端点提供 2层交换功能,很好的控制虚拟网络中的访问策略、网络隔离、流量监控等。
虚拟交换是利用虚拟平台,通过软件的方式模拟交换机部件。跟传统的物理交换机相比,虚拟交换机同样具备众多优点,一是配置更加灵活。一台普通的服务器可以配置出数十台甚至上百台虚拟交换机,且端口数目可以灵活选择。例如,VMware的ESX一台服务器可以仿真出248台虚拟交换机,且每台交换机预设虚拟端口即可达56个;二是成本更加低廉,通过虚拟交换往往可以获得昂贵的普通交换机才能达到的性能,例如微软的Hyper-V平台,虚拟机与虚拟交换机之间的联机速度轻易可达10Gbps。
OVS支持的特性:
Open vSwitch是一种开源软件,专门管理多租赁公共云计算环境,为网络管理员提供虚拟VM之间和之内的流量可见性和控制。
Open vSwitch项目由网络控制软件创业公司NiciraNetworks支持,旨在用虚拟化解决网络问题,与控制器软件一起实现分布式虚拟交换技术。这意味着,交换机和控制器软件能够在多个服务器之间创建集群网络配置,从而不需要在每一个VM和物理主机上单独配置网络。这个交换机还支持VLAN中继,通过NetFlow、sFlow和RSPAN实现可见性,通过OpenFlow协议进行管理。它还有其他一些特性:严格流量控制,它由OpenFlow交换协议实现;远程管理功能,它能通过网络策略实现更多控制。
l 支持通过NetFlowsFlow IPFIX, SPAN, RSPAN,和 GRE-tunneled镜像使虚拟机内部通讯可以被监控;
l 支持LACP(IEEE 802.1AX-2008)(多端口绑定)协议;
l 支持标准的802.1Q VLAN模型以及 trunk模式;
l 支持 BFD和 802.1ag链路状态监测;
l 支持STP(IEEE 802.1D-1998);
l 支持细粒度的Qos;分析原理
l 支持HFSC系统级别的流量控制队列;
l 支持每虚拟机网卡的流量的流量控制策略;
l 支持基于源MAC负载均衡模式、主备模式、L4哈希模式的多端口绑定;
l 支持OpenFlow协议(包括许多虚拟化的增强特性);
l 支持IPV6
l 支持多种隧道协议((GRE,VXLAN, IPsec, GRE and VXLAN over IPsec)
l 支持通过C或者Python接口远程配置;
l 支持内核态和用户态的转发引擎设置;
l 支持多列表转发的发送缓存引擎;
l 支持转发层抽象以容易的移植到新的软件或者硬件平台;
OVS几个重要的概念
Packet:网络转发的最小数据单元,每个包都来自某个端口,最终会被发往一个或多个目标端口,转发数据包的过程就是网络的功能。
Bridge: Bridge 代表一个以太网交换机(Switch),一个主机中可以创建一个或者多个 Bridge 设备。
Port: 端口与物理交换机的端口概念类似,每个 Port都隶属于一个 Bridge。端口收到的数据包会经过流规则的处理,发往其他端口;也会把其他端口来的数据包发送出去,主要有一下几种接口类型:
类型 | 说明 |
Normal | 用户可以把操作系统中的网卡绑定到ovs上,ovs会生成一个普通端口处理这块网卡进出的数据包 |
internal | 端口类型为internal时,ovs会创建一块虚拟网卡,端口收到的所有数据包都会交给该网卡,发出的包会通过该端口交给ovs。当ovs创建一个新网桥时,默认会创建一个与网桥同名的Internal Port. |
patch | 当机器中有多个ovs网桥时,可以使用Patch Port把两个网桥连起来。Patch Port总是成对出现,分别连接在两个网桥上,在两个网桥之间交换数据。 |
tunnel | 隧道端口是一种虚拟端口,支持使用gre或vxlan等隧道技术与位于网络上其他位置的远程端口通讯。 |
梳理下具体的端口类型
Interface: 连接到 Port的网络接口设备。在通常情况下,Port和 Interface是一对一的关系,只有在配置 Port为 bond模式后,Port和 Interface是一对多的关系。
举例子说明。
Controller:OpenFlow 控制器。OVS可以同时接受一个或者多个 OpenFlow控制器的管理。
datapath: 在 OVS中,datapath负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。
Flow table: 每个 datapath都和一个“flowtable”关联,当 datapath接收到数据之后, OVS会在 flow table中查找可以匹配的 flow,执行对应的操作,例如转发数据到另外的端口。
OpenvSwitch系统架构
OVS的架构分为内核空间、用户空间、配置管理层3个部分,如下图所示。内核空间包含了流表(Flow Table)和一个或多个Datapath模块,其中Datapath模块类似于网桥,主要负责对数据分组进行操作,另外内核空间中维护的流表规定了针对数据分组应该进行的操作,Datapath通过关联流表与其协同完成分组处理过程。用户空间中运行着OVS的守护进程(OpenvSwitch Daemon,vswitchd)和数据库(Open vSwitch Database,ovsdb),它们是OVS的核心功能模块,vswitchd类似于OVS的心脏,它维持着OVS的生命周期,而ovsdb就像OVS的大脑,它存储着OVS的配置信息和数据流信息,vswitchd和ovsdb协调工作确保OVS健康的运行状态。配置管理层包括ovs-dpctl、ovs-ofctl、ovs-appctl、ovs-vsctl和ovsdb-tool等,主要用于和vswitchd、ovsdb之间进行交互操作以及OVS的安装配置和部署。
OpenvSwitch的组成
(1)OVS内核空间(包含Datapath和流表)
· Datapath:主要负责实际的数据分组处理,把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。它同时与vswitchd和流表保持关联,使OVS上层可以对数据分组处理进行控制。
· 流表:流表中存储着分组处理的依据--流表项,每个Datapath 都和一个流表关联,当Datapath接收到数据之后,OVS会在流表中查找可以匹配的 flow(流表项),执行对应的操作,例如转发数据到另外的端口。同时还与vswitchd进程上下关联,是OVS上层对底层分组处理过程进行管理的接口。
(2)OVS用户空间(vswitchd和ovsdb)
· vswitchd:守护程序,实现交换功能,和Linux内核模块一起,实现基于流的交换flow-based switching,负责检索和更新数据库信息,并根据数据库中的配置信息维护和管理OVS。Vswitchd可以配置一些列特性:基于MAC地址学习的二层交换、支持IEEE 802.1Q VLAN 、端口镜像、sFlow监测、连接OpenFlow控制器等。Vswitchd也可以通过Netlink协议与内核模块Datapath直接通信。
· ovsdb-server:轻量级的数据库服务,主要保存了整个OVS的配置信息和数据流信息,ovsdb-server直接管理ovsdb,与ovsdb通信进行数据库的增删改查操作。Vswitchd可以通过socket与ovsdb-server进行通信,用于查询和更新数据库信息,或者在检索数据库信息后做出首个数据包的转发策略。
(3)OVS管理工具
· ovs-dpctl:管理OVS Datapath的实用工具,用来配置交换机内核模块,控制数据包的转发规则。可以创建、修改和删除Datapath。
· ovs-vsctl:查询和配置OVS数据库的实用工具,用于查询或修改vswitchd的配置信息,该工具会直接更新ovsdb数据库。
· ovs-appctl:主要是向OVS守护进程发送命令的工具,一般用不上。
· ovs-ofctl:用来控制OVS作为OpenFlow交换机工作时的各种参数,它是OVS提供的命令行工具。在没有配置 OpenFlow控制器的模式下,用户可以使用 ovs-ofctl命令通过 OpenFlow协议去连接 OVS,创建、修改或删除 OVS中的流表项,并对 OVS的运行状况进行动态监控。
· ovs-pki:OpenFlow交换机创建和管理公钥框架。
· ovs-tcpundump:tcpdump的补丁,解析 OpenFlow的消息。
OpenvSwitch流表分析
流表是交换机进行转发策略控制的核心数据结构。交换机芯片通过查找流表项来决策进入交换机网络的数据包执行适当的处理动作。流表中包含若干个流表项,每一个流表项中包含若干个域:包头域、活动计数器、0个或多个执行动作。
1、包头域:执行规则的条件,主要是指定数据包各层协议字段值,作为数据包中与流规则的匹配条件。
2、计数器:用来统计流量的信息,如:duration存活时间、错误、n_packets发包数等。
3、动作:定义了对匹配规则的数据包的处理方式,如:drop丢包、转发、修改等。
例:br-tun流表信息
# ovs-ofctl dump-flows br-tun
NXST_FLOW reply (xid=0x4):
#从port1进来的包转到表1处理
cookie=0x0,duration=10970.064s, table=0, n_packets=189, n_bytes=16232, idle_age=16,priority=1,in_port=1 actions=resubmit(,1)
#从port2进来的包转到表2处理
cookie=0x0,duration=10906.954s, table=0, n_packets=29, n_bytes=5736, idle_age=16,priority=1,in_port=2 actions=resubmit(,2)
#不匹配上面两条则drop
cookie=0x0,duration=10969.922s, table=0, n_packets=3, n_bytes=230, idle_age=10962,priority=0 actions=drop
#表1,单播包转到表20处理
cookie=0x0,duration=10969.777s, table=1, n_packets=26, n_bytes=5266, idle_age=16,priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,20)
#多播包转到表21处理
cookie=0x0,duration=10969.631s, table=1, n_packets=163, n_bytes=10966, idle_age=21,priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,21)
#表2,port2进来的包在这里处理了.同样是转给表10处理
cookie=0x0, duration=688.456s,table=2, n_packets=29, n_bytes=5736, idle_age=16, priority=1,tun_id=0x1actions=mod_vlan_vid:1,resubmit(,10)
#表10,进行规则学习,具体就不解释了。学习到的规则后续会给表20来使用 cookie=0x0, duration=10969.2s, table=10, n_packets=29, n_bytes=5736,idle_age=16, priority=1actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1
#表20,根据目的mac设置tun_id,通过指定的port发出去
cookie=0x0, duration=682.603s,table=20, n_packets=26, n_bytes=5266, hard_timeout=300, idle_age=16,hard_age=16, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:32:0d:dbactions=load:0->NXM_OF_VLAN_TCI[],load:0x1->NXM_NX_TUN_ID[],output:2
#无规则的交给表21处理
cookie=0x0,duration=10969.057s, table=20, n_packets=0, n_bytes=0, idle_age=10969,priority=0 actions=resubmit(,21)
#表21,根据vlan找到对应的出去的口
cookie=0x0, duration=688.6s,table=21, n_packets=161, n_bytes=10818, idle_age=21, priority=1,dl_vlan=1actions=strip_vlan,set_tunnel:0x1,output:2
# drop
cookie=0x0,duration=10968.912s, table=21, n_packets=2, n_bytes=148, idle_age=689,priority=0 actions=drop
字段介绍:
Cookie:流规则标识。
duration:流表项创建持续的时间(单位是秒)。
table:流表项所属的table编号。
n_packets:此流表项匹配到的报文数。
n_bytes:此流表项匹配到的字节数。
idle_age:此流表项从最后一个匹配的报文到现在空闲的时间。
hard_age:此流表项从最后一次被创建或修改到现在持续的时间。
Priority:流表项的优先级,数字越大优先级越高,范围是:0~7。
Open vSwitch数据包处理流程
OVS的主要功能是数据包的处理,它对数据包的处理分以下两个步骤:第一步是由内核空间的Datapath尝试直接对数据包进行转发操作;第二步是由用户空间和内核空间协同工作进行数据包处理。
OVS对数据包处理的第一步:当数据包到达内核时,内核模块提取数据包的关键信息查找Flow Table存储的流表项,若存在匹配的流表项则执行对应的流表项中的动作。如果流表中查找不到对应的流表项,OVS就无法再第一步中完成转发的处理,OVS将执行第二步操作,第二步的步骤是:当数据包到达Datapath时,FLow Table中查找不到对应的流表项,则将数据包从内核空间发送到用户空间进行处理。Vswitchd进程检索ovsdb获取数据包处理的相关flow信息,制定转发策略并通知给内核模块,同时vswitchd会设置流表项用于后续数据包的规则处理。当第一个数据包转发成功后内核模块会更新流表项,这样后续相同的数据包会按照相同的处理规则进行转发,避免再次发送到用户空间处理提高转发性能。
流表项中的action动作:
①output转发数据包到指定端口
②丢包
③发送到用户态
④Push/Pop VLAN tags
⑤Push/Pop MPLS标签
⑥Set-Queue: QoS
Datapath流表查询源码分析
数据结构关系图
函数调用关系图
① ovs_vport_receive() ,vport端口接收数据包。
②ovs_flow_key_extract(),提取数据包中的信息,封装key值。
③ ovs_dp_process_packet(),处理数据包。
④ ovs_flow_tbl_lookup_stats()查询并匹配流表。
⑤ ovs_execute_actions()执行处理动作。
Ovs中的流规则匹配是采用的TSS包分类算法,并在此算法的基础上进行了优化,匹配的步骤如下:
①提取数据包中的关键字段封装在struct sw_flow_key key结构中,对此key值计算hash值skb_hash;
②skb_hash传入ovs_flow_tbl_lookup_stats函数,在此函数内部将skb_hash和key->recirc_id作为jhash_1word的参数再次进行哈希,得到hash_key,利用此hash_key找到哈希桶,匹配哈希格子后得到mask_index。
③将此mask_index传入flow_lookup函数得到mask掩码值。
④将此mask掩码作为参数传入masked_flow_lookup函数。将masked_key和key值进行与运算得到masked_key。
⑤将此masked_key作为参数调用flow_hash再次计算hash得到哈希值。
⑥将第五步中得到的hash值作为参数传入find_bucket得到hash冲突链的头指针。
⑦遍历冲突链比较链表节点中的mask掩码值、hash值、masked_key,如果都匹配则匹配此节点,并得到流规则获取流规则中的action信息,调用ovs_execute_actions执行处理动作。
OVS的常用命令工具
Ovs-vsctl和ovs-ofctl是ovs的两个常用的命令工具,下面重点介绍下这两个工具的常用功能描述。
ovs-vsctl
该工具是查询和配置OVS数据库的实用工具,用于查询或者变更vswitchd的配置信息,通过它可以直接更新ovsdb。
Ovs-vsctl命令格式为:ovs-vsctl [命令][选项],具体命令参见下表。
命令 | 含义 |
init | 初始化数据库 |
show | 打印数据库信息摘要 |
emer-rest | 将OVS配置复位为空状态 |
add-br BRIDGE | 添加新的网桥 |
del-br BRIDGR | 删除网桥 |
list-br | 打印网桥摘要信息 |
list-ports BRIDGE | 打印网桥中的所有port摘要信息 |
add-port BRIDGE port | 向网桥中添加端口 |
del-port [BRIDGE] port | 删除网桥上的端口 |
get-controller BRIDGE | 获取网桥上的控制器信息 |
del-controller BRIDGE | 删除网桥上的控制器信息 |
set-controller BRIDGE TARGET ... | 向网桥添加控制器 |
例:ovs-vsctl show(打印数据库信息摘要)
[root@10-0-192-15 ~]# ovs-vsctl show
b2fca0a8-bbd3-4f3d-a682-408ba5bf2fdc
Bridge br-int
fail_mode: secure
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "qvoa471a431-4c"
tag: 21
Interface"qvoa471a431-4c"
......
Port "qvof913abbb-cc"
tag: 42
Interface"qvof913abbb-cc"
Bridge br-tun
fail_mode: secure
Port "vxlan-0a00cc05"
Interface "vxlan-0a00cc05"
type: vxlan
options:{df_default="true", in_key=flow, local_ip="10.0.204.6",out_key=flow, remote_ip="10.0.204.5"}
Port "vxlan-0a00cc04"
Interface"vxlan-0a00cc04"
type: vxlan
options:{df_default="true", in_key=flow,
Port br-tun
Interface br-tun
type: internal
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Bridge br-ex
Port "fg-6431ec47-de"
Interface"fg-6431ec47-de"
type: internal
Port "enp1s0f0.210"
Interface "enp1s0f0.210"
Port br-ex
Interface br-ex
type: internal
Port phy-br-ex
Interface phy-br-ex
type: patch
options: {peer=int-br-ex}
ovs_version: "2.4.0"
ovs-ofctl
该工具是OPENFLOW交换机的命令行管理工具,用于管理OVS作为OPENFLOW交换机时的各种参数,用户可以通过ovs-ofctl查询或修改OPENFLOW交换机的状态、配置和流表等信息。
ovs-ofctl 命令格式为:ovs-ofctl[命令][选项],具体常用命令如下表格。
命令 | 含义 |
show SWITCH | 输出openflow信息 |
dump-ports SWITCH [PORT] | 输出端口统计信息 |
dump-ports-desc SWITCH | 输出端口描述信息 |
dump-flows SWITCH | 输出交换机中的所有流表项 |
dump-flows SWITCH FLOW | 输出交换机中指定的流表项 |
add-flow SWITCH FLOW | 添加流表项 |
add-flows SWITCH FILE | 从文件中向交换机添加流表项 |
mod-flows SWITCH FLOW | 修改交换机的流表项 |
del-flows SWITCH[FLOW] | 删除交换机的流表项 |
例:ovs-ofctl dump-flows ovs-switch(查看交换机中的所有流表项)
[root@lizheng ~]# ovs-ofctldump-flows ovs-switch
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=502929.347s, table=0,n_packets=269, n_bytes=26362, idle_age=65534, hard_age=65534, icmpactions=output:102
cookie=0x0, duration=248210.152s, table=0,n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534,priority=3,in_port=100,vlan_tci=0x0000 actions=mod_vlan_vid:101,NORMAL
cookie=0x0, duration=502929.771s, table=0,n_packets=38, n_bytes=2532,idle_age=65534,hard_age=65534, priority=0 actions=NORMAL
ovs-ofctl add-flow参数详解
ovs-ofctl的Flow语法由一系列field=value形式的键值对组成,用英文逗号和空格隔开,在描述Flow时,必须要遵循IP stack常理。比如说,在flow中使用了L3(层3)的字段时,必须也要指明L2所用的协议。使用了L4的字段时,必须也要指明L2和L3所用的协议。
例:ovs-ofctl add-flowovs-switch "in_port=2,actions=output:8"此条规则表示的是由端口号为2进来的报文,从端口8转发出去。
常用的语法词汇如下:
字段 | 含义 |
in_port=<port> | 匹配port id为port值进入的报文 |
vlan=<vlan_tag> | 匹配VLAN tag为vlan_tag的报文,范围是[0~4095] |
dl_src | 匹配指定源mac地址 |
dl_dst | 匹配指定目的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,0x0800是ip协议 |
nw_src | 匹配源ip |
nw_dst | 匹配目的ip |
nw_proto | 协议类型,注意和dl_type区分,同时也需要和dl_type一起使用,比如dl_type是ip(0x0800),那么nw_proto=1就表示icmp packet |
tp_src | 源端口号 |
tp_dst | 目的端口号 |
|
|
举几个简单的表示语法如下:
ip | Same as dl_type=0x0800. |
icmp | Same as dl_type=0x0800,nw_proto=1. |
tcp | Same as dl_type=0x0800,nw_proto=6. |
udp | Same as dl_type=0x0800,nw_proto=17. |
arp | Same as dl_type=0x0806. |
rarp | Same as dl_type=0x8035. |
Actions动作字段详解:
ovs-ofctl的 add-flow, add-flows 以及 mod-flows 命令都需要 actions 字段,描述对匹配的数据包执行的动作,在上述的三条命令中,actions字段是flow的一部分,actions字段中可以有多个 action,它们之间用逗号隔开,一个flow的完整语法如下:
<field
>=<value
>,[<field
>=<value
>]...,actions
=<action
>[,<action
>...]
动作 | 含义 |
output:<port> | 将数据包输出到port端口 |
group:<group_id> | 将数据包输出到grop |
normal | 按照设备的常规L2/L3处理流程来处理数据包。通常是OVS默认flow中的action。要注意的是,并不是所有的OpenFlow switch都支持这个action。 |
flood | 将数据包输出到所有物理端口,除了该数据包的输入口以及不可被flooding的端口。 |
all | 将数据包输出到所有物理端口,除了该数据包的输入口 |
local | 将数据包输出到local port(与bridge同名的端口) |
In_port | 将数据包输出到其输入口 |
controller | 将数据包以"packet in"消息的形式发送到OpenFlow控制器。 |
enqueue | 将数据包放到端口的队列中。其中必须是OpenFlow端口号或关键字(如"LOCAL")。不同交换机支持的队列数不同,有些OpenFlow实现根本不支持队列。 |
drop | 丢掉该数据包 |
mod_vlan_vid:<vlan_vid> | 修改数据包的VLAN id为vlan_vid。如果数据包没有VLAN tag则添加VLAN id为vlan_vid的VLAN tag。如果数据包VLAN id已经为vlan_vid,则将其VLAN优先级priority设为0. |
mod_vlan_pcp:<vlan_pcp> | 修改数据包的VLAN优先级priority为vlan_pcp。如果数据包没有VLAN tag则添加VLAN priority为vlan_pcp的VLAN tag。合法值区间为[0, 7],数字越大优先级越高。如果数据包VLAN priority已经为vlan_pcp,则将其VLAN id设为0. |
Strip_vlan | 如果数据包有VLAN tag,则剥去VLAN tag。 |
mod_dl_src:<mac> mod_dl_dst:<mac> | 将数据包的源或目的MAC地址设置成mac |
mod_nw_src:<ip> mod_nw_dst:<ip> | 将数据包的源或目的IP地址设置成IP |
mod_tp_src:<port> mod_tp_dst:<port> | 将数据包的TCP/UDP/SCTP源或目的端口设置成port。 |
Ovs在openstack中的应用
以计算节点为例:
主要包括两个网桥:集成网桥 br-int和隧道网桥 br-tun。
通过ovs-vsctl show命令可以查看网桥信息
br-int
集成网桥 br-int规则比较简单,作为一个正常的二层交换机使用。无论下面虚拟化层是哪种技术实现,集成网桥是看不到的,只知道根据 vlan和 mac进行转发。
所连接接口除了从安全网桥过来的qvo-xxx(每个虚拟机会有一个),就是一个往外的 patch-tun接口,连接到 br-tun网桥。
其中,qvo-xxx接口上会为每个网络分配一个内部 vlan号,比如这里是同一个网络启动了两台虚机,所以 tag都为 1。
Bridge br-int
fail_mode: secure
Port br-int
Interface br-int
type: internal
Port "qvoc4493802-43"
tag: 1
Interface"qvoc4493802-43"
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "qvof47c62b0-db"
tag: 1
Interface"qvof47c62b0-db"
br-tun
br-tun 作为虚拟化层网桥,规则就要复杂一些。要将内部过来的网包进行合理甄别,内部带着正确 vlan tag过来的,从正确的 tunnel扔出去;外面带着正确 tunnel号过来的,要改到对应的内部 vlan tag扔到里面。
Bridge br-tun
fail_mode: secure
Port "vxlan-0a00644d"
Interface"vxlan-0a00644d"
type: vxlan
options:{df_default="true", in_key=flow, local_ip="10.0.100.88",out_key=flow, remote_ip="10.0.100.77"}
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port br-tun
Interface br-tun
type: internal
其中,端口 br-tun是内部端口,vxlan-0a00644d这样的端口是向其它节点发包时候的 VXLAN隧道端点,patch-int和 br-int是接口对。
正常情况下,虚拟机的流量经过br-int转发,经过 patch-tun端口,抵达 patch-int端口,从而到达 br-tun网桥,该网桥根据自身规则将合适的网包经过 VXLAN隧道送出去。
转发逻辑如下图:
表 0
先看 table0中的规则
cookie=0x0, duration=329.194s, table=0,n_packets=31, n_bytes=2906, idle_age=29, priority=1,in_port=1actions=resubmit(,2)
cookie=0x0, duration=325.847s, table=0,n_packets=14, n_bytes=1591, idle_age=33, priority=1,in_port=2actions=resubmit(,4)
cookie=0x0, duration=328.954s, table=0,n_packets=6, n_bytes=480, idle_age=321, priority=0 actions=drop
从 1端口(patch-int)进来的网包,扔给表 2处理,从 2端口(vxlan-0a00644d)进来的网包,扔给表 4处理。即一个处理来自内部vm的,一个处理来自外面的 vxlan隧道的。
对于内部包,表 2中规则为
cookie=0x0, duration=53316.397s, table=2,n_packets=0, n_bytes=0, idle_age=53316, priority=0,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00actions=resubmit(,20)
cookie=0x0, duration=53316.162s, table=2,n_packets=161, n_bytes=39562, idle_age=422,priority=0,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=resubmit(,22)
即里面过来的单播包,扔给表 20处理;多播和广播包,扔给表22处理。
丢弃所有包。
cookie=0x0, duration=328.223s, table=3,n_packets=0, n_bytes=0, idle_age=328, priority=0 actions=drop
对于外部来的数据,表 4中规则为
cookie=0x0, duration=50.703s, table=4,n_packets=12, n_bytes=1451, idle_age=33, priority=1,tun_id=0x3e9 ,actions=mod_vlan_vid:1,resubmit(,10)
cookie=0x0, duration=327.979s, table=4,n_packets=2, n_bytes=140, idle_age=94, priority=0,actions=drop
匹配给定的 tunnel号,添加对应的 vlan号,扔给表 10去学习一下后扔到br-int网桥。
cookie=0x0, duration=327.742s, table=10,n_packets=12, n_bytes=1451, idle_age=33,priority=1,actions=learn(table=20,hard_timeout=300,priority=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:0->NXM_OF_VLAN_TCI[],load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],output:NXM_OF_IN_PORT[]),output:1
主要作用是学习外部(从 tunnel)进来的包,往表 20中添加对返程包的正常转发规则,并且从 patch-int扔给 br-int。
使用了 openvswitch的 learn动作。该动作能根据处理的流来动态修改其它表中的规则。
具体来看 learn规则:
table=20 说明是修改表 20中的规则,后面是添加的规则内容;
NXM_OF_VLAN_TCI[0..11],匹配跟当前流同样的VLAN头。
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],包的目的 mac跟当前流的源 mac匹配;
load:0->NXM_OF_VLAN_TCI[],将 vlan号改为 0;
load:NXM_NX_TUN_ID[]->NXM_NX_TUN_ID[],将 tunnel号修改为当前的tunnel号;
output:NXM_OF_IN_PORT[],从当前入口发出。
cookie=0x0, duration=38.551s, table=20,n_packets=9, n_bytes=694,hard_timeout=300,idle_age=33,hard_age=33,priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:83:95:fa,actions=load:0->NXM_OF_VLAN_TCI[],load:0x3e9->NXM_NX_TUN_ID[],output:2,cookie=0x0,duration=327.504s, table=20, n_packets=0, n_bytes=0, idle_age=327, priority=0actions=resubmit(,22)
其中,第一条规则就是表 10学习来的结果。对于vlan号为 1,目标 mac是 fa:16:3e:83:95:fa的网包,去掉 vlan号,添加当时的 vxlan号,并从 tunnel发出。
对于没学习到规则的网包,则扔给表 22处理。
cookie=0x0, duration=50.94s, table=22,n_packets=11, n_bytes=1334, idle_age=29, dl_vlan=1,actions=strip_vlan,set_tunnel:0x3e9,output:2,cookie=0x0,duration=327.261s,table=22, n_packets=10, n_bytes=808, idle_age=51, priority=0 actions=drop
表 22检查如果 vlan号正确,则去掉 vlan头后从 tunnel扔出去。