Linux-虚拟网络设备-OpenvSwitch(持续更新)

xiaoxiao2021-02-28  25

概述

     OpenvSwitch,简称OVS是一个虚拟交换软件,主要用于虚拟机VM环境,作为一个虚拟交换机,支持Xen/XenServer, KVM, and VirtualBox多种虚拟化技术。 在虚拟化平台上,OVS 可以为动态变化的端点提供 2 层交换功能,很好的控制虚拟网络中的访问策略、网络隔离、流量监控等等。

     OVS 遵循 Apache 2.0 许可证, 能同时支持多种标准的管理接口和协议。OVS 也提供了对 OpenFlow 协议的支持,用户可以使用任何支持 OpenFlow 协议的控制器对 OVS 进行远程管理控制。

     在这种某一台机器的虚拟化的环境中,一个虚拟交换机(vswitch)主要有两个作用:传递虚拟机VM之间的流量,以及实现VM和外界网络的通信。

The bulk of the code is written in platform-independent C and is easily ported to other environments. The current release of Open vSwitch supports the following features: • Standard 802.1Q VLAN model with trunk and access ports • NIC bonding with or without LACP on upstream switch • NetFlow, sFlow(R), and mirroring for increased visibility • QoS (Quality of Service) configuration, plus policing • Geneve, GRE, VXLAN, STT, and LISP tunneling • 802.1ag connectivity fault management • OpenFlow 1.0 plus numerous extensions • Transactional configuration database with C and Python bindings • High-performance forwarding using a Linux kernel module

几个重要的概念

Bridge

Bridge代表一个以太网交换机(switch),一个主机中可以创建一个或多个bridge设备。

Port

端口与物理交换机的端口概念类似,每个port都隶属于一个bridge。

Interface

连接到port的网络接口设备。通常情况下,port和interface是一对一的关系,只有在配置port为bond模式后,port和interface才是一对多的关系。

Controller

OpenFlow控制器。OVS可以同时接受一个或多个OpenFlow控制器管理。

Datapath

在ovs中,datapath负责执行数据交换,也就是把从接收端口收到的数据包在流表中进行匹配,并执行匹配到的动作。

Flowtable

每个datapath都和一个“flowtable”关联,当datapath接收到数据之后,ovs会在flow table中查找可以匹配到的flow,执行对应的操作,例如转发数据到另外的端口。

安装与配置

下载代码

git clone https://github.com/openvswitch/ovs.git

编译代码

./boot.sh ./configure

By default all files are installed under /usr/local. Open vSwitch also expects to find its database in /usr/local/etc/openvswitch by default. If you want to install all files into, e.g., /usr and /var instead of /usr/local and /usr/local/var and expect to use /etc/openvswitch as the default database directory, add options as shown here:

./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc make && make install

load the kernel modules

/sbin/modprobe openvswitch

校验安装

/sbin/lsmod | grep openvswitch

启动

export PATH=$PATH:/usr/local/share/openvswitch/scripts ovs-ctl start

校验

ovs-vsctl add-br ovs-bridge-test

工作原理

组件介绍

The main components of this distribution are: • ovs-vswitchd, a daemon that implements the switch, along with a companion Linux kernel module for flow-based switching. • ovsdb-server, a lightweight database server that ovs-vswitchd queries to obtain its configuration. • ovs-dpctl, a tool for configuring the switch kernel module. • Scripts and specs for building RPMs for Citrix XenServer and Red Hat Enterprise Linux. The XenServer RPMs allow Open vSwitch to be installed on a Citrix XenServer host as a drop-in replacement for its switch, with additional functionality. • ovs-vsctl, a utility for querying and updating the configuration of ovs-vswitchd. • ovs-appctl, a utility that sends commands to running Open vSwitch daemons. Open vSwitch also provides some tools: • ovs-ofctl, a utility for querying and controlling OpenFlow switches and controllers. ovs-pki, a utility for creating and managing the public-key infrastructure

openflow

      OpenFlow 是用于管理交换机流表的协议,ovs-ofctl 则是 OVS 提供的命令行工具。在没有配置 OpenFlow 控制器的模式下,用户可以使用 ovs-ofctl 命令通过 OpenFlow 协议去连接 OVS,创建、修改或删除 OVS 中的流表项,并对 OVS 的运行状况进行动态监控。 OpenFlow 的匹配流程,如下图所示(来源于网络)

flow语法

     flow被定义为某个特定的网络流量。例如:一个tcp连接就是一个flow,或者从某个ip地址发出来的数据包,都可以认为是一个flow。支持openflow协议的交换机应该包含一个或多个流表,流表中的条目包含:数据包头的信息、匹配成功之后要执行的指令和统计信息。      当数据包进入ovs后,会将数据包和流表中的流表项进行匹配,如果发现了匹配的流表项,则执行该流表项中的指令集。相反,如果数据包在流表中没有发现任何匹配,ovs会通过控制通道把数据包发送到openflow控制器中。

参数

     在ovs中,流表项作为ovs-ofctl的参数,采用如下的格式:字段=值。如果有多个字段,可以用逗号或者空格分开。一些常用的字段列举如下:

动作

对于 add−flow,add−flows 和 mod−flows 这三个命令,还需要指定要执行的动作:actions=[target][,target…] 一个流规则中可能有多个动作,按照指定的先后顺序执行。 常见的操作有:

实验

初始化设备信息

#创建一个新的 OVS 交换机 ovs-vsctl add-br ovs-switch #添加端口,并设置端口号(如果不指定,ovs会自动生成一个) #对于 internal 类型的的网络接口,OVS 会同时在 Linux 系统中创建一个可以用来收发数据的模拟网络设备。 #我们可以为这个网络设备配置 IP 地址、进行数据监听等等。 ovs-vsctl add-port ovs-switch p0 -- set Interface p0 type=internal ofport_request=100 ovs-vsctl add-port ovs-switch p1 -- set Interface p1 type=internal ofport_request=101 ovs-vsctl add-port ovs-switch p2 -- set Interface p2 type=internal ofport_request=102 #查看设备信息 ethtool -i p0 driver: openvswitch version: firmware-version: expansion-rom-version: bus-info: supports-statistics: no supports-test: no supports-eeprom-access: no supports-register-dump: no supports-priv-flags: no #创建network namespace和设置ip ip netns add ns0 ip netns add ns1 ip netns add ns2 ip link set dev p0 netns ns0 ip link set dev p1 netns ns1 ip link set dev p2 netns ns2 ip netns exec ns0 ip addr add 100.2.96.100/24 dev p0 ip netns exec ns1 ip addr add 100.2.96.101/24 dev p1 ip netns exec ns2 ip addr add 100.2.96.102/24 dev p2 ip netns exec ns0 ifconfig p0 promisc up ip netns exec ns1 ifconfig p1 promisc up ip netns exec ns2 ifconfig p2 promisc up ip netns exec ns0 ifconfig lo up ip netns exec ns1 ifconfig lo up ip netns exec ns2 ifconfig lo up

查看设备信息

root@ubuntu:/home/sunld# ovs-vsctl show ad3594eb-ebf6-4255-916f-c737b652d7bf Bridge ovs-switch Port ovs-switch Interface ovs-switch type: internal Port "p0" Interface "p0" type: internal Port "p2" Interface "p2" type: internal Port "p1" Interface "p1" type: internal ovs_version: "2.8.90"

查看 Open vSwitch 中的端口信息

#datapath ID (dpid),以及每个端口的 OpenFlow 端口编号,端口名称,当前状态 ovs-ofctl show ovs-switch OFPT_FEATURES_REPLY (xid=0x2): dpid:0000b2e05257c141 n_tables:254, n_buffers:0 capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst 100(p0): addr:fe:7f:00:00:36:88 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 101(p1): addr:fe:7f:00:00:36:88 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max 102(p2): addr:fe:7f:00:00:36:88 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max LOCAL(ovs-switch): addr:b2:e0:52:57:c1:41 config: PORT_DOWN state: LINK_DOWN speed: 0 Mbps now, 0 Mbps max OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0

查看某个端口的编号

ovs-vsctl get interface p0 ofport

查看datapath信息

ovs-dpctl show system@ovs-system: lookups: hit:33 missed:23 lost:0 flows: 0 masks: hit:58 total:0 hit/pkt:1.04 port 0: ovs-system (internal) port 1: p1 (internal) port 2: ovs-switch (internal) port 3: p0 (internal) port 4: p2 (internal)

屏蔽数据包

#屏蔽所有进入ovs的以太网广播数据包 ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop" #屏蔽 STP 协议的广播数据包 ovs-ofctl add-flow ovs-switch "table=0, dl_src=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"

修改数据包

#修改从端口p0收到数据包的源地址为192.168.100.2 ovs-ofctl add-flow ovs-switch "priority=1 idle_timeout=0, in_port=100, actions=mod_nw_src:192.168.100.2,normal" #查看效果 ip netns exec ns0 ping -c 4 100.2.96.101 #新开一个窗口监控p1 ip netns exec ns1 tcpdump -i p1 icmp #数据包来源变成192.168.100.2 20:04:23.123827 IP 192.168.100.2 > 100.2.96.101: ICMP echo request, id 6266, seq 3, length 64 20:04:24.132375 IP 192.168.100.2 > 100.2.96.101: ICMP echo request, id 6266, seq 4, length 64

重定向数据包

#重定向icmp数据包到端口p2 ovs-ofctl add-flow ovs-switch "idle_timeout=0, dl_type=0x0800, nw_proto=1, actions=output:102" #测试 #从p0发送数据到p1 ip netns exec ns0 ping -c 4 100.2.96.101 #监控p2端口,发现数据包已被转发到p2 ip netns exec ns2 tcpdump -i p2 icmp 20:12:00.305874 IP 100.2.96.100 > 100.2.96.101: ICMP echo request, id 6295, seq 1, length 64 20:12:01.324529 IP 100.2.96.100 > 100.2.96.101: ICMP echo request, id 6295, seq 2, length 64 20:12:02.353814 IP 100.2.96.100 > 100.2.96.101: ICMP echo request, id 6295, seq 3, length 64 20:12:03.365809 IP 100.2.96.100 > 100.2.96.101: ICMP echo request, id 6295, seq 4, length 64

修改数据包的vlan tag

除了使用“ping”、“tcpdump”和“iperf” 等 Linux 命令以外,我们也可以使用 OVS 提供的 ovs-appctl ofproto/trace 工具来测试 OVS 对数据包的转发状况。ovs-appctl ofproto/trace 可以用来生成测试用的模拟数据包,并一步步的展示 OVS 对数据包的流处理过程。

#设置端口p1 vlan=101 ovs-vsctl set port p1 tag=101

现在由于端口 p0 和 p1 属于不同的 VLAN,它们之间无法进行数据交换。我们使用 ovs-appctl ofproto/trace 生成一个从端口 p0 发送到端口 p1 的数据包,这个数据包不包含任何 VLAN tag,并观察 OVS 的处理过程。

ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07 -generate Flow: in_port=100,vlan_tci=0x0000,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07,dl_type=0x0000 bridge("ovs-switch") -------------------- 0. in_port=100, priority 1 mod_nw_src:192.168.100.2 NORMAL -> learned that 1a:63:2e:ad:b9:c4 is on port p0 in VLAN 0 -> no learned MAC for destination, flooding Final flow: unchanged Megaflow: recirc_id=0,eth,in_port=100,vlan_tci=0x0000/0x1fff,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07,dl_type=0x0000 Datapath actions: 2,4

说明: 在第一行输出中,“Flow:”之后的字段描述了输入的流的信息。由于我们没有指定太多信息,所以多数字段 (例如 dl_type 和 vlan_tci)被 OVS 设置为空值。 在第二行的输出中,“Rule:” 之后的字段描述了匹配成功的流表项。 在第三行的输出中,“OpenFlow actions”之后的字段描述了实际执行的操作。 最后一段以”Final flow”开始的字段是整个处理过程的总结,“Datapath actions: 2,4”代表数据包被发送到 datapath 的 2 和 4 号端口。

#对于从端口 p0 进入交换机的数据包, #如果它不包含任何 VLAN tag,则自动为它添加 VLAN tag 101 ovs-ofctl add-flow ovs-switch "priority=3,in_port=100,dl_vlan=0xffff,actions=mod_vlan_vid:101,normal" #查看信息 #发现数据包进入端口 p0 之后, 会被加上 VLAN tag101, 同时转发到端口 p1 上 ovs-appctl ofproto/trace ovs-switch in_port=100,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07 -generate Flow: in_port=100,vlan_tci=0x0000,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07,dl_type=0x0000 bridge("ovs-switch") -------------------- 0. in_port=100,vlan_tci=0x0000, priority 3 mod_vlan_vid:101 NORMAL -> learned that 1a:63:2e:ad:b9:c4 is on port p0 in VLAN 101 -> no learned MAC for destination, flooding Final flow: in_port=100,dl_vlan=101,dl_vlan_pcp=0,vlan_tci1=0x0000,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07,dl_type=0x0000 Megaflow: recirc_id=0,eth,in_port=100,vlan_tci=0x0000,dl_src=1a:63:2e:ad:b9:c4,dl_dst=1a:50:8c:91:b3:07,dl_type=0x0000 Datapath actions: push_vlan(vid=101,pcp=0),2,pop_vlan,1,push_vlan(vid=101,pcp=0),4 #反过来从端口 p1 发送数据包,由于 p1 现在是带有 VLAN tag 101 的 Access 类型的端口, #所以数据包进入端口 p1 之后,会被 OVS 添加 VLAN tag 101 并发送到端口 p0 ovs-appctl ofproto/trace ovs-switch in_port=101,dl_dst=1a:63:2e:ad:b9:c4,dl_src=1a:50:8c:91:b3:07 -generate Flow: in_port=101,vlan_tci=0x0000,dl_src=1a:50:8c:91:b3:07,dl_dst=1a:63:2e:ad:b9:c4,dl_type=0x0000 bridge("ovs-switch") -------------------- 0. priority 0 NORMAL -> learned that 1a:50:8c:91:b3:07 is on port p1 in VLAN 101 -> forwarding to learned port Final flow: unchanged Megaflow: recirc_id=0,eth,in_port=101,vlan_tci=0x0000/0x1fff,dl_src=1a:50:8c:91:b3:07,dl_dst=1a:63:2e:ad:b9:c4,dl_type=0x0000 Datapath actions: push_vlan(vid=101,pcp=0),3

其他openflow常用操作

#删除编号为 100 的端口上的所有流表项 ovs-ofctl del-flows ovs-switch "in_port=100" #查看交换机中的所有 Table ovs-ofctl dump-tables ovs-switch 查看交换机中的所有流表项 #ovs−ofctl dump−flows ovs-switch #查看交换机上的端口信息 ovs-ofctl show ovs-switch

kvm安装

常用命令

#查看openflow协议版本 ovs-ofctl --version ovs-ofctl (Open vSwitch) 2.8.90 OpenFlow versions 0x1:0x5 #修改ovs支持OpenFLow版本 ovs-vsctl set Bridge A1 protocols=OpenFlow12,OpenFlow13 #创建一个新的 OVS 交换机 ovs-vsctl add-br ovs-switch #查看交换机中的所有 Table ovs-ofctl dump-tables ovs-switch #查看交换机中的所有流表项 ovs-ofctl dump-flows ovs-switch #删除编号为 100 的端口上的所有流表项 ovs-ofctl del-flows ovs-switch "in_port=100" #查看交换机上的端口信息 ovs-ofctl show ovs-switch #列出 open vswitch 中的所有网桥: ovs-vsctl list-br #判断网桥是否存在 ovs-vsctl br-exists br0 #将物理网卡挂接到网桥: ovs-vsctl add-port br0 eth0 #列出网桥中的所有端口: ovs-vsctl list-ports br0 #列出所有挂接到网卡的网桥: ovs-vsctl port-to-br eth0 #查看 open vswitch 的网络状态 ovs-vsctl show #删除网桥上已经挂接的网口: vs-vsctl del-port br0 eth0 #删除网桥: ovs-vsctl del-br br0

port类型

       端口Port与物理交换机的端口概念类似,Port是OVS Bridge上创建的一个虚拟端口,每个Port都隶属于一个Bridge。Port有以下几种类型:

Normal

       把物理网卡(eth1)attach到ovs上,ovs会生成一个同名的port(eth1)处理这块网卡进出的数据。此时端口类型为Normal。

ovs-vsctl add-port br-ex eth1 ovs-vsctl show #显示信息如下: Bridge br-ex Controller "tcp:127.0.0.1:6633" is_connected: true fail_mode: secure Port phy-br-ex Interface phy-br-ex type: patch options: {peer=int-br-ex} Port "eth1" Interface "eth1" Port br-ex Interface br-ex type: internal

注意:attach到ovs上的网卡设备(物理网卡、虚拟网卡)不支持分配IP地址,因此若之前eth1有ip地址,attach之后ip地址失效。

Internal

       Internal类型是ovs内部创建的虚拟网卡接口,每创建一个port,ovs会自动创建一个同名接口(interface)挂载到新创建的port上。

ovs-vsctl add-br br0 ovs-vsctl add-port br0 port0 -- set Interface port0 type=internal ovs-vsctl show

显示信息如下:

ad3594eb-ebf6-4255-916f-c737b652d7bf Bridge "br0" Port "br0" Interface "br0" type: internal Port "port0" Interface "port0" type: internal Bridge ovs-bridge-test Port ovs-bridge-test Interface ovs-bridge-test type: internal ovs_version: "2.8.90"

可以看到有两个port。当ovs创建一个新网桥时,默认会创建一个与网桥同名的internal port(如:br0)。在ovs中,只有“internal”类型的设备才支持配置IP地址信息,因此我们可以为br0和port0配置ip地址。

ip addr add 100.2.97.10/24 dev br0 ip link set dev br0 up ip route add default via 100.2.97.1 dev br0

上面两种Port类型区别在于,Internal类型会自动创建接口(Interface),而Normal类型是把主机中已有的网卡接口添加到OVS中

Patch

      当主机中有多个ovs网桥时,可以使用patch port把两个网桥连接起来。Patch port总是成对存在,分别连接在两个网桥上,从一个patch port收到的数据包会被发送到另一个patch port上,类似于linux中的veth。使用patch连接的两个网桥跟一个网桥没什么区别,openstack neutron中使用到了patch port。比如连接br-int和br-ext的patch port。

Bridge br-int Port int-br-ex Interface int-br-ex type: patch options: {peer=phy-br-ex} Bridge br-ex Port phy-br-ex Interface phy-br-ex type: patch options: {peer=int-br-ex} root@ubuntu:/# ovs-vsctl add-br br0 root@ubuntu:/# ovs-vsctl add-br br1 root@ubuntu:/# ovs-vsctl \ > -- add-port br0 patch0 -- set interface patch0 type=patch options:peer=patch1 \ > -- add-port br1 patch1 -- set interface patch1 type=patch options:peer=patch0 root@ubuntu:/# ovs-vsctl show ad3594eb-ebf6-4255-916f-c737b652d7bf Bridge "br1" Port "br1" Interface "br1" type: internal Port "patch1" Interface "patch1" type: patch options: {peer="patch0"} Bridge "br0" Port "br0" Interface "br0" type: internal Port "patch0" Interface "patch0" type: patch options: {peer="patch1"} Bridge ovs-bridge-test Port ovs-bridge-test Interface ovs-bridge-test type: internal ovs_version: "2.8.90"

连接两个网桥不止上面一种方法,linux中支持创建Veth设备对,我们可以首先创建一对Veth设备对,然后把这两个Veth分别添加到两个网桥上,其效果跟OVS中创建Patch Port一样,只是性能会有差别.

Patch port的作用

       Open vSwitch中PATCH类型的端口有如下定义:“A pair of virtual devices that act as a patch cable”(一根虚拟电缆),同时在OpenvSwitch官方FAQ可以找到PATCH端口的用途“If you still want to connect two bridges, you can use a pair of patch ports”(用于连接两个网桥)。 简单化,patch port成对,可以看作是一根虚拟电缆,用来连接两个网桥,如下图:

#创建网桥br1、br2 ovs-vsctl add-br br1 ovs-vsctl add-br br2 #创建内部端口 ovs-vsctl add-port br1 tap1 -- set Interface tap1 type=internal ovs-vsctl add-port br2 tap2 -- set Interface tap2 type=internal #配置namespace ip netns add ns1 ip netns add ns2 ip link set dev tap1 netns ns1 ip link set dev tap2 netns ns2 ip netns exec ns1 ip addr add 100.2.96.11/24 dev tap1 ip netns exec ns1 ip link set tap1 up ip netns exec ns1 ip link set lo up ip netns exec ns2 ip addr add 100.2.96.12/24 dev tap2 ip netns exec ns2 ip link set tap2 up ip netns exec ns2 ip link set lo up # patch port ovs-vsctl add-port br1 patch-ovs-1 -- set Interface patch-ovs-1 type=patch -- set Interface patch-ovs-1 options:peer=patch-ovs-2 ovs-vsctl add-port br2 patch-ovs-2 -- set Interface patch-ovs-2 type=patch -- set Interface patch-ovs-2 options:peer=patch-ovs-1 #test ip netns exec ns1 ping 100.2.96.12 ip netns exec ns2 ping 100.2.96.11

显示信息如下

root@ubuntu:/home/sunld# ovs-vsctl show ad3594eb-ebf6-4255-916f-c737b652d7bf Bridge "br2" Port "tap2" Interface "tap2" type: internal Port "br2" Interface "br2" type: internal Port "patch-ovs-2" Interface "patch-ovs-2" type: patch options: {peer="patch-ovs-1"} Bridge "br1" Port "tap1" Interface "tap1" type: internal Port "patch-ovs-1" Interface "patch-ovs-1" type: patch options: {peer="patch-ovs-2"} Port "br1" Interface "br1" type: internal Bridge ovs-bridge-test Port ovs-bridge-test Interface ovs-bridge-test type: internal ovs_version: "2.8.90"

其他

通过 Floodlight 管理 OVS

参考资料

ovs官网 ovs安装 What Is Open vSwitch? OVS - 简介 ovs命令基础 基于 Open vSwitch 的 OpenFlow 实践

转载请注明原文地址: https://www.6miu.com/read-850187.html

最新回复(0)