在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

点击上方蓝字 关注我们吧

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

 --改善TCP/IP 存储应用的性能

杨子夜 | Intel 存储软件开发工程师

最近Intel发布了最新的100Gbps的以太网网卡控制器E810, 这款新的网卡不仅支持两种不同协议的RDMA 协议(iWARP 和RoCE v2),并且针对基于TCP/IP协议的应用(包括各种使用网络的应用)给出了基于ADQ(Application Device Queues)特性的性能改善方案,可用于改善网络应用的性能(诸如平均或者长尾延迟,以及throughput等)。在这篇文章中我们将会简要介绍如何在SPDK 中使能ADQ特性,以便于改善TCP/IP存储应用的性能。

ADQ简介

在SPDK中使能E810网卡ADQ 特性

Intel 网卡中的ADQ特性是一种智能的系统级方法,旨在提高网络I/O性能。ADQ特性的目标是确保高优先级应用程序具有可预期的高性能,并显著降低抖动。ADQ的核心技术是将隔离的硬件网卡队列供某些应用程序进行专有使用。并且希望这些硬件网卡队列可以最佳地连接到所需应用程序中的不同线程。显而易见, 这种方法可以防止专有程序的网络流量与其他应用程序竞争,并且该应用程序的性能(例如,延迟)可以变得可预测。此外开启ADQ特性以后,我们仍然可以对专有应用程序在队列上提供QoS控制。

图1 Without ADQ那部分的图,给出了不使用ADQ的例子(也就是正常网卡的包处理)。如果把图中不同颜色的汽车看成不同的应用,不同的车道看成不同的网卡队列,我们可以看到同一个网卡队列上可以同时处理不同应用的网络包。这样的处理方法是通用的,但是不利于某些专有应用的QoS  控制。图1中使用了ADQ以后,我们可以看到某些网络队列可以直接分配给某些专有应用,于是这些应用的网络包可以在特定分配的队列上被处理,和其他应用程序隔离,继而可以进行后续的QoS控制。

在SPDK中使能E810网卡ADQ 特性

图1 ADQ 特性的开启以及关闭

总结一下ADQ隔离队列的思想,和DPDK/SPDK PMD的思想有些相似。基于DPDK 的application可以去操纵分配给这个应用的物理队列,这一点来讲和ADQ的思想是完全相同的。唯一的区别是目前DPDK 只工作在层3以下,所以工作在TCP/IP层的应用想要通过DPDK PMD驱动来享受到隔离队列的特性,必须使用基于DPDK的用户态TCP/IP栈。所以从这一点看来,ADQ的特性通用性更好一些,不需要应用强制使用用户态的解决方案。

另外我们可以看到ADQ的特性,对于多核应用的支持还存在需要加强的地方。因为使用ADQ以后,我们可以分配一些特定的队列给应用。比如给一个应用程序A 分配4个队列,这个可以保证应用程序对这4个队列的独享 。但是如果这个应用是使用多CPU的,那么这个应用的多个线程(可能运行在不同的CPU core上)形成对这4个队列的内部竞争。我们在SPDK 库中的集成工作,就是为了避免内部竞争的出现。

SPDK 应用使用ADQ的使用示例

在SPDK中使能E810网卡ADQ 特性

为了更好地解释SPDK 库中ADQ的集成, 图2给出了SPDK NVMe-oF TCP应用使用ADQ的一个例子。首先在SPDK NVMe-oF TCP应用启动之前,需要做一些配置工作(预计会在这个系列的下一篇文章出现),诸如分配一些网卡队列,对应到不同的TC (traffic class)。于是监听在以下三元组的<IP, port, TC>的套接字(如图2 Socket init module中的绿色描述,需要调用setsockopt函数使用SO_PRIORITY 作为OPT_NAME进行设置)。那么这个套接字所接收到的连接都会被分配在预先设置好的队列中。比如我们预先分配了4个队列,那么得到的NAPI_ID 在APP的生命周期中,只会存在4个不同的值,比如789,790, 791和792。很显然我们可以通过getsockopt, 传入SO_INCOMING_NAPI_ID 作为OPT_NAME进行NAPI_ID的获取。那么在NVMe-oF层的accepter logic 模块,对于新接收的连接位于哪个物理队列上了如指掌。那么就可以利用NAPI_ID的信息,把具有相同NAPI_ID的连接交于同一个NVMe-oF的polling group 进行处理,从而可以最优地利用ADQ 特性。

在SPDK中使能E810网卡ADQ 特性

图 2 SPDK NVMe-oF集成ADQ的特性

SPDK socket library中的支持

在SPDK中使能E810网卡ADQ 特性

为了实现图2中的使用需求,在SPDK SOCK库中,我们做了以下的工作,使得使用SPDK库的应用诸如NVMe-over TCP target 可以更好地使用分配的队列。

在SPDK 的thread 设计中(涉及到SPDK framework以及SPDK thread的介绍可参考SPDK 社区的相关文章[1]),每一个SPDK thread都可以使用一个polling group。这个polling group中可以处理所有归属于这个polling group处理的连接。比如在NVMe-oF  target (app/nvmf/nvmf_tgt)以及相关的库(module/event/subsystems/nvmf/, lib/nvmf)实现中,  当NVMe-oF target启动以后,每个Reactor线程上启动一个NVMe-oF的SPDK thread,然后这个SPDK thread上会运行一个polling group。这个polling group可以处理不同transport上的polling group,诸如RDMA, TCP或者Fibre Channel上的各个polling group的连接。

所以在没有使用ADQ 之前, 每一个SPDK thread上的TCP polling group 处理的TCP连接,可能位于不同的队列上。而使用ADQ 之后,处理的TCP 连接可能分布在有限的几个队列上。举个例子,如果SPDK的NVMe-oF TCP 应用使用了两个CPU core,被分配了4个队列。那么每个CPU core上运行的sock polling group能处理到4个不同的队列。那么这两个CPU 对于网卡队列还是存在竞争关系。原则上,我们需要让不同的CPU core去处理不同的队列,才是效率最高的。也就是说, 假设一个CPU core i上处理的网卡队列集合是 N(i),  那么任意的CPU 之间处理的网卡队列的交集都是空集,也就是:For any CPU core i and j, N(i)  ∩ N(j) = ∅ 

为了满足这一实现,我们在SPDK的sock library中,维护了placement_id (网卡队列的NAPI_ID在SPDK sock 库中被抽象为placement_id)到sock polling group的映射, i.e.,  <placement_id, sock_polling_group, reference_count>。另外我们提供了spdk_sock_get_optimal_sock_group 这个调用,可以针对一个spdk socket,去寻找最佳的polling group。这个其实就是利用这个mapping 关系。因为每一个SPDK socket 都可以得到一个placement_id。如果得到的placement_id不是有效的,则认为ADQ 特性没有被开启,那么就不会得到一个被优化的polling group;如果得到的placement_id是有效的,我们就去寻找是否存在这个这个placement_id所对应的polling group。然后这个sock polling group的信息会被上层逻辑(诸如nvmf层)使用。

如果在nvmf 层的逻辑中,通过查询spdk_sock_get_optimal_sock_group得到无效的sock_polling_group,就会采用默认的算法, 比如使用Roundrobin的算法(如图2所示)进行调度,寻找一个SPDK thread;如果发现了有效的sock_polling_group,我们就会找寻这个sock_polling_group的创建者(意思是由哪个SPDK thread 创建),然后交由这个SPDK thread 处理。无论哪种方式,我们最终都会到一个SPDK thread去处理这个连接,最后我们将会更新这个placement_id 和对应的sock_polling_group的映射信息。此外, 在一个socket 被一个polling group移除的时候,我们也要对placement_id和sock_polling_group相应的映射进行维护。

性能数据分享

在SPDK中使能E810网卡ADQ 特性

在今年的SDC (storage developer conference) 会议上,我们有一个presentation (Optimizing User Space NVMe-oF TCP Transport Solution with Both Software and Hardware Methodologies [2])分享了一些使用ADQ的性能数据。在这里我们选取了一些数据进行分享。

图3给出了同样硬件环境下,服务器端的SPDK NVMe-oF TCP target程序使用ADQ特性后的性能变化。我们可以看到在使用ADQ以后,可以更高效地利用CPU 资源, 比如SPDK NVMe-oF TCP target使用5个CPU core,就基本可以达到E810网卡的line rate。如果不开启,那么可能需要使用6-7个CPU core。并且在1- 5个CPU core的配置下,在ADQ 模式和非ADQ 模式下运行同样的工作负载,ADQ模式可以提升IOPS以及降低延迟。图4 给出了同样测试下,长尾延迟(p99, p999以及p9999)的改善。我们可以看出使用了ADQ特性以后,NVMe-oF TCP target应用的可预测性有了很大的改善,也就是延迟的普遍降低趋势。

在SPDK中使能E810网卡ADQ 特性

图 3  SPDK NVMe-oF TCP 性能

在SPDK中使能E810网卡ADQ 特性

图 4  长尾延迟的改善

总结和后续

在SPDK中使能E810网卡ADQ 特性

这篇文章中主要介绍了在通过SPDK SOCK库中怎样透明的向上层模块暴露出Intel E810网卡的ADQ (Application Device Queue)的特性。一旦系统开启ADQ的支持,基于TCP/IP的服务器端存储应用可以得到很好的性能提升,比如IOPS的提升以及延迟的降低。在后续系列文章中,我们将会具体介绍怎样在装备Intel E810网卡的环境下,配置ADQ特性,然后供SPDK的NVMe-oF TCP target应用使用。

References

在SPDK中使能E810网卡ADQ 特性

[1] SPDK线程模型解析

[2]https://www.snia.org/events/storage-developer/2020/abstracts#nvmeof

在SPDK中使能E810网卡ADQ 特性

转载须知

DPDK与SPDK开源社区公众号文章转载声明

推荐阅读

英特尔®以太网控制器E810介绍:面向5G核心网络

Intel E810 DDP在VPP offload加速框架中的应用

Intel E810 Advanced RSS介绍

DPDK Rx flexible descriptor 在Intel E810 网卡中的使用

基于Intel®以太网800系列网络适配器的FDIR功能及原理介绍

在SPDK中使能E810网卡ADQ 特性

在SPDK中使能E810网卡ADQ 特性

点点“分享”,给我充点儿电吧~