(本文为参考诸多资料后作者的总结与理解)
1 虚拟交换机
利用软件的方式形成交换部件,所以也叫软件交换机,跟传统的物理交换机相比,虚拟交换机有很多优点:1.配置灵活,因为是软件实现的,一台物理服务器上可以配置数十台或者数百台虚拟交换机,而且端口数目可以灵活选择。2. 成本低廉,通过软件的方式可轻易达到10Gbps的交换速度。
2 openVswitch设计目的
openVswitch是一种虚拟交换机。它的设计是为了解决物理交换机存在的一些局限性:openVswitch较物理交换机而言有着更低的成本和更高的工作效率;一个虚拟交换机可以有几十个端口来连接虚拟机,而openVswitch本身占用的资源也非常小;可以根据自己的选择灵活的配置,可以对数据包进行接收分析处理;同时还支持标准的管理接口和协议,如NetFlow,sFlow,SPAN,RSPAN等。
3OVS工作原理
虽然是虚拟交换机,但是其工作原理与物理交换机类似。在虚拟交换机的实现中,其两端分别连接着物理网卡和多块虚拟网卡。,当数据包从虚拟机发出后,首先将通过虚拟机上配置的虚拟网卡。虚拟网卡会根据一些既定的规则决定如何处理数据包,例如放行、阻隔或者修改。数据包在被网卡放行后将转发至虚拟交换机,与其他虚拟交换机不同的是,提供了OpenFlow支持能力的OVS将根据自身保存的流表对数据包进行匹配,如果匹配成功则按照相应的指令进行数据包操作,如果匹配未成功则将数据包发给控制器等待相关流表的指定和下发。当数据包需要通过物理网卡转发时,它将会被发送到与虚拟交换机相连的物理网卡上,进而被转发给外部网络设备。
4OVS主要构件
有了全局的概念后,我们来详细了解OVS的内部组件。简单来看,OVS由这三大部分构成:
其中这三部分构件的作用分别如下:
ovsdb-sever:OVS的数据库服务器,用于管理ovsdb,通过与ovs-vswitchd之间的UNIXsocket机制进行通信,来存储虚拟交换机的配置信息。
ovs-vswitchd:OVS的核心部件,它和上层controller通信遵从OPENFLOW协议,它与ovsdb-server通信使用OVSDB协议,它和内核模块通过netlink通信。
ovs kernel module:OVS的内核模块,如果在内核的缓存中找到转发规则就转发,否则发向用户空间去处理。
5OVS功能实现
OVS在实现中分为用户空间和内核空间两个部分。其中,OVS在用户空间程序拥有多个组件,它们主要负责用于实现数据交换和OpenFlow流表功能,是OVS的核心。同时,OVS还提供了一些工具用于交换机管理、数据库搭建,以及和内核组件的交互。OVS的核心组件及其关联关系如下图5.1所示。
如图5-1所示,OVS中最重要的组件是ovs-vswitchd,它实现了OpenFlow交换机的核心功能,并且通过netlink协议直接和OVS的内核模块进行通信。交换机运行过程中,ovs-vswitchd还会将交换机的配置、数据流信息及其变化保存到数据库ovsdb中,因为这个数据库由ovsdb-server直接管理,所以ovs-vswitchd需要和ovsdb-server通过UNIXsocket机制进行通信以获得或者保存配置信息。数据库ovsdb的存在,使得OVS交换机的配置能够被持久化存储,即便设备被重启后相关的OVS配置仍旧能够存在。
ovs-vsctl组件是一个用于交换机管理的基本工具,它需要直接和ovs-vswitchd通信,能够支持很多管理操作,用户可以登录到交换机部署的服务器上通过ovs-vsctl管理OVS交换机。同时,ovs-appctl组件也是一个管理工具,通过发送一些内部命令给ovs-vswitchd组件以改变其配置。另外,在一些情况下,用户可能会需要自行管理运行在内核中的数据通路,那么也可以通过调用ovs-dpctl驱使ovs-vswitchd在不依赖于数据库的情况下去管理内核空间中的数据通路。
当用户需要和ovsdb-server通信以进行一些数据库操作时,可以通过运行ovsdb-client组件访问ovsdb-server,或者直接使用ovsdb-tool而不经ovsdb-server就对ovsdb数据库进行操作。
对于支持OpenFlow的OVS而言,支持集中部署的控制器对其进行远程管理和监控,才是它所体现出的软件定义网络的核心。在OVS实现中,OpenFlow是用于管理交换机流表的协议。通过使用ovs-ofctl,用户可以使用OpenFlow去连接交换机并在远程开展监控和管理。另外,OVS还提供了sFlow协议用于数据包的采样和监控,可以通过额外的sFlowTrend等软件(未包含在OVS软件包中)驱动该协议。
OVS在数据包的转发中拥有一条基于内核模块的快速通道,这主要是依赖了netlink协议(Linux系统中用户空间与内核空间进行数据交换的一种方式,OVS使用的是genericnetlink)。OVS在其内核空间中定义了几组genl命令,用于get/set/add/delete相应的datapath/flow/vport以及针对特定的数据包执行一些动作。其中,datapath/flow/vport都是OVS对网络资源进行的抽象描述。
6 OVS数据流发送流程
OVS交换机负责数据流发送的相关流程如下。
1 OVS定义的port结构在内核态观察到从OVS上链接的某块虚拟网卡上有数据包发来时,将其传递给一个名为internal_dev_xmit()的函数,该函数会依次接收数据包。
2 OVS在内核状态下查看流表结构,观察是否有缓存的信息可用于转发这个数据包,这项工作主要是由ovs_flow_tbl_lookup()函数完成。该函数的运行需要一个key值,key值将从ovs_flow_extract()函数通过收集数据包的L2~L4层的细节信息中得到,然后为相应的流构建一个独一无二的key值。
(3)假设数据包是从虚拟网卡上发出的第一个包,那么在OVS内核中将不会有相应的流表缓存存在,那么内核将不会知道如何处置这个数据包。这时,内核就会通过genl(generic netlink)发送一个upcall给用户空间。
(4)位于OVS用户空间的ovs-vswitchd进程在接收到upcall后,将检查数据库以查看数据包的目的端口是哪里,然后通过OVS_ACTION_ATTR_OUTPUT告诉内核应该将数据包转发到哪个端口,例如eth0。
(5)最终,OVS_PACKET_CMD_EXECUTE命令将使得内核执行用户此前设置的动作。即内核将在do_execute_actions()函数中执行这条genl命令,并将数据包通过do_output()函数转发给端口eth0,进而数据包将被发出。
OVS在接收数据包时与上述流程类似,OVS会利用netdev_frame_hook()函数为每个与外部相连的设备注册一个rx_handler。因此,一旦这些设备在线上接收到了数据包,那么OVS将把它转发到用户空间并检查它应该发往何处及应该对其采用何种动作。例如,如果这是一个VLAN数据包,那么VLANtag就需要首先从数据包中被去除,然后再将其转发到正确的端口。
7常用OVS指令
一些常用的OVS指令如下所示:
sudoovs-vsctl show
sudoovs-vsctl add-br mybridge
sudoovs-vsctl del-br mybridge
sudoovs-vsctl add-port mybridge port-name
sudoovs-vsctl del-port mybridge port-name
sudoovs-vsctl list Bridge/Port/Interface/...
sudoovs-appctl fdb/show mybridge
sudoovs-ofctl show mybridge
sudoovs-ofctl dump-flows mybridge
sudoovs-ofctl add-flow mybridgedl_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
sudoovs-ofctl del-flows mybridge 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
sudoovs-ofctl add-flow dp0 in_port=2,actions=output:6
#This will delete all the flow entries in the flow table
sudoovs-ofctl del-flows mybridge
8布置OVS时的问题与解决
8.1创建一个bridge,并绑定物理网卡eth0,eth0上的网络无法正常连接:
ovs-vsctl add-br br0
ovs-vsctl add-port br0eth0
问题解决:一块物理以太网卡如果作为 OpenvSwitch bridge 的一部分,则它不能拥有 IP 地址,如果有,也会完全不起作用。可以将 IP 地址绑定至 OpenvSwitch“internal” 设备来恢复网络访问功能。
例如,假设eth0 IP 地址为 192.168.128.5,在执行上文问题中的命令后,可以使用如下方法来将 IP 地址绑定至br0 上:
ifconfig eth0 0.0.0.0
ifconfig br0 192.168.128.5
8.2创建一个 bridge,把两块物理网卡绑定到网桥,产生了网络风暴:
ovs-vsctl add-br br0
ovs-vsctl add-port br0eth0
ovs-vsctl add-port br0eth1
问题解决: 在上面的设置下,OpenvSwitch 在 eth0 上收到一个广播包后会将其发给 eth1,然后 eth1 上的物理交换机又将这个广播包发还给 eth0,如此往复产生网络风暴。当有多个 switch 时产生更复杂的情况。
解决方案1:
将 eth0 与 eth1 都绑定至同一个 bridge 从而获得更大的带宽、更高的可靠性:
ovs-vsctl add-br br0
ovs-vsctl add-bond br0bond0 eth0 eth1
解决方案2:
建立两个bridge:
ovs-vsctl add-br br0
ovs-vsctl add-port br0eth0
ovs-vsctl add-br br1
ovs-vsctl add-port br1eth1
解决方案3:
打开生成树协议(spanning tree protocol, STP):
ovs-vsctl add-br br0
ovs-vsctl set bridge br0stp_enable=true
ovs-vsctl add-port br0eth0
ovs-vsctl add-port br0eth1