ovs智能网卡卸载相关总结

该文是对一年前ovs流表卸载到mellanox的 cx6的回顾总结,作为记录以备后续查询。

为了验证智能网卡的offload功能,部署了一套开源openstack u + ovn2021+ovs2.15 并配备了Cx6 dx。在此基础上进行了ovs 基于linux tc offload的验证研究。经过验证并修改了ovn流表下发的部分代码,实现了不带CT statect-actionOVN流表的全卸载,完成了跨节点vxlandecap encap的卸载,同节点同子网,同节点跨子网的本地流表offload功能验证。

一. OVS 架构及网卡卸载基本框架

1. Ovs 基本转发流程

OpenVSwitch是一个实现了OpenFlow的虚拟交换机,它由多个模块组成。主要有位于用户空间的ovsdb-server和ovs-vswitchd进程,和位于内核空间的OVS datapath组成。在一个SDN架构中,Controller将各种网络拓扑,网络功能转换成OVS的数据和OpenFlow规则,分别下发给ovsdb-server和ovs-vswitchd进程,OpenFlow规则可以通过ovs-ofctl 查询。ovs的整体架构如下:

 

网络数据的转发,都是由位于内核空间的OVS datapath完成。用户空间和内核空间的信息是怎么同步的?对于一个网络数据流,第一个数据包到达OVS datapath,这个时候的datapath没有转发信息,并不知道怎么完成转发。接下来OVS datapath会查询位于用户空间的ovs-vswitchd进程。ovs-vswitchd进程因为有OpenFlow信息,可以根据OpenFlow规则完成match-action操作,也就是从一堆OpenFlow规则里面匹配网络数据包对应的规则,根据这些规则里的action实现转发。如果ovs-vswitchd 查询用户态精确流表和模糊流表,还不命中,在有SDN 控制器接入的情况下,经过 OpenFlow 协议,通告给控制器,由控制器处理。

这样第一个数据包就完成了转发。与此同时,ovs-vswitchd会通过netlink向OVS datapath写入一条(也有可能是多条)转发规则,这样,同一个网络数据流的后继网络数据包到达OVS datapath时,因为已经有了转发规则,datapath就可以直接完成转发,不再需要向ovs-vswitchd查询。其基本流程如下图:

 

 

通过slow path和fast path之间的交互就完成了普通ovs的转发流程。常规的计算虚拟化方案组网中采用virtio虚拟化技术实现网卡虚拟化,创建的虚拟机使用的是virtio虚拟网卡。用户VM流量通过virtio后端到tap接口接入ovs。下图的virtio引用的,图中virtio的前后端写反了。

ovs常规的流量转发流程:

(1) ovsdatapath接收到从ovs连接的某个网络端口发来的数据包,从数据包中提取源/目的IP、源/目的MAC、端口等信息。

(2) ovs在内核态查看流表结构(通过hash),如果命中,则快速转发。

(3) 如果没有命中,内核态不知道如何处置这个数据包,所以,通过netlink upcall机制从内核态通知用户态,发送给ovs-vswitchd模块组件处理。

(4) ovs-vswitchd查询用户态精确流表和模糊流表,如果还不命中,在SDN控制器接入的情况下,经过OpenFlow协议,上报通告给控制器,由控制器决策处理。

(5) 如果模糊命中,ovs-vswitchd会同时刷新用户态精确流表和内核态精确流表,如果精确命中,则只更新内核态流表。

(6) 刷新后,重新把该数据包注入给内核态datapath模块处理。

 

2. Ovs流表硬件卸载

2.1 网卡配置SRIOV方式实现的组网

 

SR-IOV网卡通过将SR-IOV功能集成到物理网卡上,将单一的物理网卡虚拟成多个VF接口,每个VF接口都有单独的虚拟PCIe通道,这些虚拟的PCIe通道共用物理网卡的PCIe通道。每个虚拟机可占用一个或多个VF接口,这样虚拟机就可以直接访问自己的VF接口,而不需要Hypervisor的协调干预,从而大幅提升网络吞吐性能。Mellanox的SRIOV网卡内部有个eswitch模块,类似与网卡内部的一个二层交互模块。通过硬件实现软件交换机的功能。

 

 

2.2 SRIOV支持硬件卸载方案

为了支持网卡硬件卸载操作,提出了一个VF representor模型,在准虚拟(PV)设置中,VF representor起着与TAP设备相同的作用,与VF一对一映射,主要用于首包上送学习流表的流程。

 

在内核版本4.8中,引入了一种新的SRIOV交换机模式(switchdev)。类似于为硬件交换机asic提供服务的switchdev驱动程序,使用了一个软件表示模型(用于SR-IOV e-switch端口),该模型反过来允许将软件交换机流量规则卸载到硬件eswitch中。

 

 

当前虚拟交换快路径的硬件卸载有两种实现方式:一种是基于TC Flower接口的卸载,另一种是基于rte_flow接口的卸载。常见的大都基于TC FLower的方式进行硬件卸载。

 

使用ovsdatapath作为slowpath,默认下发一个miss规则到eswitch中,首包进入,当前没有命中任何表,匹配到默认规则,通过vf-representor被送到eswitch的管理端口也就是对应的ovsdatapath中,datapath中同样匹配不到表项,这个时候报文通过内核netlink上送到ovs的用户ovs-vswitchd中去查询流表。

 

因为ovs-vswitchd中有OpenFlow规则,ovs-vswitchd还是可以完成转发。不一样的地方是,ovs-vswitchd会判断当前数据流对应的规则能否offload(卸载)到网卡。如果可以的话,ovs-vswitchd会调用通过TC接口将flow规则下发至硬件。这样,同一个数据流的后继报文,可以直接在网卡的eSwitch中完成转发,根本不需要走到主机操作系统来。如果ovs-vswitchd匹配不到,并且控制器存在的话,则通过openflow通道将报文上送到控制器。由控制器决定报文的具体转发规则。该部分的处理流程与ovs之前常规的处理方式类似。

基于SRIOV方式硬件卸载数据转发流程如下:

 

(1) 硬件网卡收到一个转发报文,例如从VM经过passthough一个VF接口,报文直接从VM发送到硬件网卡;

 

(2) 硬件网卡收到报文,根据报文特征值查找本地转发表项,如果命中,则直接转发;

 

(3) 如果不能命中,硬件网卡无法获知该报文的转发逻辑,匹配默认规则,进入miss流程;

 

(4) Miss流程及首包上送流程,即硬件网卡会根据该报文源端口VF找到其对应的VF representor,通过VF representor发送到主机HOST上的bridge上,即OVSBridge,此时是在主机HOSTlinux内核态处理;

 

(5) 首包不能命中,需要上送ovs-vswithd的处理,需要通过netlink upcall机制从内核态通知用户态,发送给ovs-vswitchd模块组件处理。如果非首包,则说明硬件表没有表项存在,则说明该表不支持通过tc flow卸载到网卡,需要通过ovs datapath实现软转发。(ps:目前ovsdatapath初始是没有表项的,需要通过首包上送触发流表下发到datapath,且有表项的老化机制,一段时间没有流量的话会进行datapath转发表的老化。)

 

(6) ovs-vswitchd查询用户态精确流表和模糊流表,如果还不命中,在SDN控制器接入的情况下,经过OpenFlow协议,上报通告给控制器,由控制器决策处理;

 

(7) 如果模糊命中,ovs-vswitchd会同时刷新用户态精确流表和内核态精确流表,如果精确命中,则只更新内核态流表,同时,ovs-vswitchd进程会检查是否支持通过TC Flower接口卸载到硬件网卡,如果支持,则同时完成流表直接卸载;

 

(8) 刷新后,重新把该数据包注入给内核态datapath模块处理,如果是直接通过TC Flower接口卸载到硬件网卡的方式,那么还需要通过VF representor接口发送到硬件网卡,完成转发;

此时硬件网卡已经增加了流表信息,完成报文匹配转发。

二 . 卸载流量的转发分享

上面介绍了ovs的普通转发流程,和卸载流程,下面进行ovs卸载场景下控制器及相应的ovsoffload的交互过程进行分析。

智能网卡使用的是invida的 mlx cx6的卡,所以对于OVS卸载及Mellalox的网卡的sriovoffload支持配置情况可以参考之前的配置文档将 SRIOV IOMMU 等基本配置打开。

需要注意的是本次验证的环境是在Centos8.4上进行的,mlx的驱动为系统自带的。本次实验控制面使用的openstack u版本 + ovs 2.13 + ovn控制器。

 

 

卸载环境中有几个特殊的地方需要注意。

(1)SROIV使能之后,如果neutron的插件替换为ovn plugin之后,创建端口时port security是需要继续使能的,不要加 --disable-port-security 选项,是因为disable之后,ovn创建的流表会删除arp resolve,导致arp报文的广播,东西向跨设备的同子网设备不通。

(2)VF端口要设置成被Netmanager unmanager的状态。

创建/etc/NetworkManager/conf.d/99-unmanaged-devices.conf文件,添加以下内容,注意vxlan接口要加入

[keyfile]

unmanaged-devices=interface-name:eth0;interface-name:eth1;interface-name:eth2;interface-name:eth3;interface-name:eth4;interface-name:eth5;interface-name:eth6;interface-name:eth7;

systemctl reload NetworkManager

然后查询VFVxlan接口的状态,此图为加入vxlan的情况,实际操作无需加入vxlan。

 

注意:图中此处解绑了vxlan,可能会导致vxlan port在内核tc处被删除一些表项,导致vlxan解封装卸载失败:

正常的:

[root@node82 ~]# tc -s qdisc show dev  vxlan_sys_4789

qdisc noqueue 0: root refcnt 2

 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)

 backlog 0b 0p requeues 0

qdisc ingress ffff: parent ffff:fff1 ----------------

 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)

 backlog 0b 0p requeues 0

异常的:

[root@node82 ~]# tc -s qdisc show dev  vxlan_sys_4789

qdisc noqueue 0: root refcnt 2

 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)

 backlog 0b 0p requeues 0

所以此处的unmannager不需要添加vxlan端口

还有一点需要注意:

尽管当前Mellax cx6提供了对CT的支持,但是支持情况不理想,并不是支持当前OVS所有ct matchaction 。所以对于带有CTOVN流表采用跳过的处理逻辑,在OVN下发流表时将CT相关字段都做裁减下发。卡厂商提供的CX6 DX支持CT特性如下:

 

Match on ct_state:
    Already supported: +trk, -trk, +est, -est
    Planned for OFED 5.4: -inv, -rel
    Not plan: +new, -new, +inv, +rel
Supported match on other CT relevant fields:
    ct_zone, ct_mark, ct_label, recirc_id
Supported CT relevant actions:
    ct, ct snat, ct dnat, recirc

但是在实际测试的时候发现当前驱动支持的卸载没有最新的驱动提供的支持特性所显示的,所以为了完全忽略CT对卸载的影响,且为了卸载的连续性我们采用全部跳过的处理。后续带CT的卸载测试可以升级驱动到最新的再进行。本次先不升级就使用原有系统内部驱动。

我们修改了开源ovn,增加ovn的配置命令,增加ct略过流程,完成CT相关字段裁减的配置如下:

ovn-nbctl set NB_Global . options:security_group_enable=false

ovn-nbctl set NB_Global . options:skip-stateful-enable=true

设置跳表之后,清理OVN南北向数据库,删除网络实例,重新创建网络及实例。

组网拓扑:

 

2.1 同子网跨节点

(1) CT跳表未打开

Openstack 基本配置:

openstack network create   test-net2

openstack port create --network test-net2 --vnic-type=direct   --binding-profile '{"capabilities": ["switchdev"]}' direct_port3

openstack port create --network test-net2 --vnic-type=direct   --binding-profile '{"capabilities": ["switchdev"]}' direct_port4

 

openstack server create --flavor m1.big --image smart_centos7 --nic  port-id=direct_port3  --availability-zone nova1 vm3

openstack server create --flavor m1.big --image smart_centos7 --nic  port-id=direct_port4  --availability-zone nova2 vm4

Vm3vm4分布在不同的计算节点上。

a)测试ICMP流量卸载

VM3VM4 发起ping

VM3----->>>>------VM4

通过dump vm3所在计算节点的ovs 相关表项可以看到当前卸载是失败的

通过打开ovsdbg 查询日志,Ovs的卸载日志,提示隧道接口和vf接口上的卸载都失败

Dump vm4所在计算节点的ovs相关流表:

 

查看 vm4所在节点的ovs日志

单从日志上很难判断是什么错误导致了卸载失败。因为表项里面带了很多CX网卡当前驱动不支持的ct statect action相关字段。

 

b)测试TCP Stream卸载

Vm3执行netperf -t TCP_STREAM -H 指定vm4接口地址

Vm3 所在节点查询ovs日志,提示卸载失败。

 

Vm4所在节点ovs日志:

经过多次dump的结果来看,从ovs appctl命令dump type=non-offloaded 看表项并不准确,有时候出现即使下发失败也有type=offloaded可以dump的情况。如果type=offloaded并且tcpdump rep接口抓包抓不到报文,说明流表是真正的offload到网卡了。

所以流表中的CT对卸载的影响还是很大的,所以下一步实验将带CT表项的ct state字段清理掉,再次进行实验。

(2) CT 跳表打开

   经过2.1的测试发现CT跳表未打开会造成很多表项的卸载失败,所以后续的验证都将CT 跳过的配置打开。

aVm3Vm4打流,Netperftcp-stream

   Dump vm3ovs表项:

Ovs tc下发日志打开开关:

ovs-appctl vlog/set netdev_offload_tc:dbg

ovs-appctl vlog/set dpif_netlink:dbg

日志目录:/var/log/ovs-vswitchd

日志截取:

2021-10-21T08:49:05.806Z|00016|netdev_offload_tc(handler1)|DBG|tunnel: id 0x2001 src 10.0.0.132 dst 10.0.0.133 tp_src 53818 tp_dst 4789

 

2021-10-21T08:51:37.854Z|00008|dpif_netlink(handler3)|DBG|added flow  //表示卸载成功,下面的是具体的流表打印//

 

2021-10-21T08:51:37.854Z|00009|dpif_netlink(handler3)|DBG|system@ovs-system: put[create] ufid:97c20076-9b36-4c65-b4dd-72da258e6916 recirc_id(0),dp_hash(0/0),skb_priority(0/0),in_port(3),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=fa:16:3e:6b:95:3a,dst=fa:16:3e:32:c0:ca),eth_type(0x0800),ipv4(src=30.0.0.245,dst=30.0.0.48/255.255.255.224,proto=6/0,tos=0/0x3,ttl=64/0,frag=no),tcp(src=35131/0,dst=12865/0),tcp_flags(0/0), actions:set(tunnel(tun_id=0x1001,src=10.0.0.133,dst=10.0.0.132,ttl=64,tp_dst=4789,flags(df|csum|key))),2

 

2021-10-21T08:51:37.903Z|00010|netdev_offload_tc(handler3)|DBG|tunnel: id 0x2001 src 10.0.0.132 dst 10.0.0.133 tp_src 43862 tp_dst 4789

 

2021-10-21T08:51:37.915Z|00011|dpif_netlink(handler3)|DBG|added flow

 

2021-10-21T08:51:37.915Z|00012|dpif_netlink(handler3)|DBG|system@ovs-system: put[create] ufid:720ff8bf-dc5e-41c3-92c8-3c6342447049 recirc_id(0),dp_hash(0/0),skb_priority(0/0),tunnel(tun_id=0x2001,src=10.0.0.132,dst=10.0.0.133,ttl=64/0,tp_src=43862/0,tp_dst=4789/0,flags(-df+csum+key)),in_port(2),skb_mark(0/0),ct_state(0/0),ct_zone(0/0),ct_mark(0/0),ct_label(0/0),eth(src=fa:16:3e:32:c0:ca,dst=fa:16:3e:6b:95:3a),eth_type(0x0800),ipv4(src=30.0.0.48/0.0.0.0,dst=30.0.0.245,proto=6/0,tos=0/0,ttl=64/0,frag=no),tcp(src=12865/0,dst=35131/0),tcp_flags(0/0), actions:3

 

2021-10-21T08:52:38.011Z|00001|dpif_netlink(revalidator91)|DBG|system@ovs-system: flow_del ufid:720ff8bf-dc5e-41c3-92c8-3c6342447049 recirc_id(0),dp_hash(0),skb_priority(0),tunnel(tun_id=0x2001,src=10.0.0.132,dst=10.0.0.133,ttl=64,tp_src=43862,tp_dst=4789,flags(csum|key)),in_port(2),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),eth(src=fa:16:3e:32:c0:ca,dst=fa:16:3e:6b:95:3a),eth_type(0x0800),ipv4(src=30.0.0.48,dst=30.0.0.245,proto=6,tos=0,ttl=64,frag=no),tcp(src=12865,dst=35131),tcp_flags(syn|ack), packets:488432, bytes:58628260, used:30.404s

 

2021-10-21T08:52:38.035Z|00001|dpif_netlink(revalidator73)|DBG|system@ovs-system: flow_del ufid:97c20076-9b36-4c65-b4dd-72da258e6916 recirc_id(0),dp_hash(0),skb_priority(0),in_port(3),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),eth(src=fa:16:3e:6b:95:3a,dst=fa:16:3e:32:c0:ca),eth_type(0x0800),ipv4(src=30.0.0.245,dst=30.0.0.48,proto=6,tos=0,ttl=64,frag=no),tcp(src=35131,dst=12865),tcp_flags(syn), packets:25499452, bytes:38605606112, used:30.428s

上述操作的是同子网跨节点的vxlan通信,通过设置跳表开关,实现了双向流量的offloadvxlan封装和解封装都在网卡上进行。

Vm4的所在节点ovs表项:

CT表项跳过打开后,ct state全部都清理了,同子网跨节点卸载完全成功,双向 vxlan encapvxlan decap都成功。

 

posted @ 2023-09-28 14:33  stephigher  阅读(3064)  评论(0)    收藏  举报