openstack-notes

OVS报文处理机制

1、传统OVS

在传统OVS中,网卡在加载网络过程中被绑定到OVS端口上,端口的数据包接送和发送函数在datapath中定义,因此报文的接收和发送统一由位于内核空间的datapath进行,内核空间负责报文的解析封装、流表匹配、流表匹配失败上送、报文转发或丢弃等报文处理操作。用户空间只在内核空间将报文上送用户空间时,对报文进行流表匹配操作,根据匹配结果通知内核datapath报文该如何处理,并下发匹配到的流表项至内核态流表,以备后续类似报文匹配。

传统OVS接收报文处理机制: 当报文到达网卡设备,网卡将接收到的报文交给该网卡绑定的端口在OVS中定义的数据包接收函数处理。在datapath中主要首先进行报文头信息的获取,根据报文头信息生成匹配流表项的key值,得到key值后进行内核态流表匹配。在OVS中有两个流表,一个为位于内核空间的内核态流表,另一个是位于用户空间的用户态流表。内核态流表主要是存储近期匹配过得流表项,用户态流表主要由控制器或人为通过OVS提供的ovs-ofctl工具下发。当数据包的key值在内核态流表中匹配到流表项,数据包将不经过用户空间,直接由内核进行action操作并将报文转发或丢弃。若未匹配到内核态流表项,将使用Linux系统的Netlink通信机制实现内核进程和用户进程的通信,把数据包上送到用户空间进行用户态流表匹配,若命中用户态流表项,则在用户空间中完成流表项中相应的action操作,最终获得数据包的出端口信息并告知内核将数据包转发出去,同时将命中到的用户态流表项以内核态流表的规则生成对应的内核态流表项下发至内核态流表。若未命中,则将数据包丢弃或者上送至控制器,由控制器决定如何转发该数据包。

传统OVS发送报文处理机制: OVS接收到数据包后对数据包的处理主要分为修改数据包后转发出去,向上层应用发送、丢弃三种情况。当需要将修改的数据包转发出去时,首先也是进行流表匹配,匹配过程与接收报文一致。通过命中的流表项获得要转发出去的端口号,最终将报文从OVS端口号绑定的网卡发送出去。

2、OVS+DPDK

DPDK平台提供的接口库,可以将底层环境资源做抽象,即在系统中新增了环境抽象层(EAL),将网卡驱动在用户态实现,系统只需在网卡初始化时设置网卡驱动接口即可将网卡收到的报文直接交给用户空间进程进行处理,网卡发送报文时也通过调用用户态定义的发送报文接口将报文直接发送到对应网卡。在OVS的vswitchd进程中新起一个数据收发接管线程(TO-Thread)用于接管系统的OVS中由datapath执行的数据包接收和发送的功能。数据包的流表匹配则直接进行用户态流表匹配。

OVS+DPDK接收报文处理机制: 当报文到达网卡,EAL层根据网卡初始化和驱动层初始化中绑定的用户态网卡驱动,将报文发送到用户空间交给TO-Thread线程进行接管,在该线程中将进行报文的解析、与内核协议栈通信和获取报文key值的操作,然后在vswitchd进程中凭借报文key值完成用户态流表匹配。用户态流表匹配的操作与传统的OVS一样,但若命中流表项本系统将直接交由TO-Thread线程进行action处理,最终将报文通过该接管线程转发出去或丢弃。接收报文的过程中不经过OVS中内核态的datapath进程的处理和内核态流表的匹配。

OVS+DPDK发送报文处理机制: 发送报文时,先经过协议栈的封装处理,将封装好的报文匹配用户态流表,获取action操作。若为隧道转发则还需进行隧道头封装,将报文发往对应的VTEP端口。在隧道转发过程中可能涉及OVS中内部端口多次转发,并在相应端口做报文处理,报文最终要发出的端口通过流表匹配获得。TO-Thread线程将报文直接发往OVS出端口绑定的网卡,由网卡发送到网络中。

3、OVS数据路径

Open vSwitch 在不同的平台支持不同的数据路径。不同的数据路径支持不同的功能集合。

目前支持4种数据路径:

Linux upstream:通过上游Linux 内核自带的内核模块实现的datapath。由于openvswitch功能已经引入内核,可以根据不同发行版Linux 的内核版本查看支持的功能。

Linux OVS tree:通过OVS源代码生成的内核模块实现的。

Userspace: 也称为DPDK,dpif-netdev 或者dummy datapath。这是NetBSD,FreeBSD 和Mac OSX 仅支持的数据路径。

Hyper-V:Windows 平台的数据路径。

下面是不同的数据路径可以实现的功能: