小言_互联网的博客

CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 下篇

384人阅读  评论(0)

作者简介

万群,Intel存储软件工程师 主要从事SPDK软件测试工作

目录

一. 系统配置(包括target端和host端)

二. NVME/TCP的ADQ特性在target端的配置实例 

三. NVME/TCP的ADQ特性在host端的配置实例 

四. 故障排除 

五. 参考文献 

提示

由于篇幅限制,这篇文章是CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 上篇[1]的续篇,所有操作系统、内核以及相应工具包的安装都可以参照此篇文章的上篇CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 上篇

系统配置(包括target端和host端)

提示:这里很多配置在系统重启之后需要重新配置,你可以参照你的操作系统进行持久配置或者启动之后运行脚本。

系统优化

注意:这里的系统优化也会依赖于硬件和软件环境和不同的负载。这里的优化在重载系统和快速IO系统中比较明显,但是也只是在有限的硬件和软件系统中测试过。在我们的环境(Fedora29)里的配置步骤如下:

1.禁用防火墙

#service firewalld stop; systemctl mask firewalld

2.禁用SELinux

#vim /etc/selinux/config

修改SELINUX=enforcing为SELINUX=disabled

3.启用latency-performance低延迟的性能模式

#yum install -y tuned

#tuned-adm profile latency-performance

使用以下命令查看配置的结果

#cat /etc/tuned/active_profile

结果为latency-performance

#cat /etc/tuned/profile_mode

结果为manual

4.设置CPU调整频率模式为performance

#cpupower frequency-set -g performance

5.禁用irqbalance服务

#systemctl stop irqbalance

6.配置操作系统参数来处理增加的数据包速率

a.增加socket侦听队列的连接请求的最大数目,该配置再重启后会失效,参数值重新恢复成默认的128

#sysctl -w net.core.somaxconn=4096

b.当特定接口接收数据包的速度快于内核处理数据包的速度时,增加允许排队的最大数据包数目

#sysctl -w net.core.netdev_max_backlog=8192

c.指定所能接受SYN同步包的最大客户端数量

#sysctl -w net.ipv4.tcp_max_syn_backlog=16384

d.增加发送和接受套接字缓冲区大小的最大值

#sysctl -w net.core.rmem_max=16777216

#sysctl -w net.core.wmem_max=16777216

e.确定TCP栈应该如何反映内存使用,每个值的单位都是内存页(通常是4KB)。第一个值是内存使用的下限;第二个值是内存压力模式开始对缓冲区使用应用压力的上限;第三个值是内存使用的上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。示例中第一个值为786432*4/1024/1024=3G,第二个值为1019584*4/1024/1024=3.9G,第三个值为16777216*4/1024/1024=64G

#sysctl -w net.ipv4.tcp_mem=”764688 1019584 16777216”

f.自动调优定义socket使用的内存,第一个值是为socket接收/发送缓冲区分配的最少字节数;第二个值是默认值(该值会被rmem_default/wmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;第三个值是接收/发送缓冲区空间的最大字节数(该值会被rmem_max/wmem_max覆盖)

#sysctl -w net.ipv4.tcp_rmem=”8192 87380 16777216”

#sysctl -w net.ipv4.tcp_wmem=”8192 65536 16777216”

g.允许分配所有的物理内存

#sysctl -w vm.overcommit_memory=1

h.禁用透明大页

#echo never > /sys/kernel/mm/transparent_hugepage/enabled

以上所有系统优化的步骤总结在以下脚本里(除了禁用SELinux的命令)

service firewalld stop

systemctl mask firewalld

tuned-adm profile latency-performance

cat /etc/tuned/active_profile

cat /etc/tuned/profile_mode

cpupower frequency-set -g performance

systemctl stop irqbalance

sysctl -w net.core.somaxconn=4096

sysctl -w net.core.netdev_max_backlog=8192

sysctl -w net.ipv4.tcp_max_syn_backlog=16384

sysctl -w net.core.rmem_max=16777216

sysctl -w net.core.wmem_max=16777216

sysctl -w net.ipv4.tcp_mem="764688 1019584 16777216"

sysctl -w net.ipv4.tcp_rmem="8192 87380 16777216"

sysctl -w net.ipv4.tcp_wmem="8192 65536 16777216"

sysctl -w vm.overcommit_memory=1

echo never > /sys/kernel/mm/transparent_hugepage/enabled

网卡优化

1.卸载并重新加载ice驱动以清除之前所有TC配置

#modprobe -r ice

#modprobe ice

2.启用硬件TC卸载功能

#ethtool -K $iface hw-tc-offload on

3.配置flower director,配置’channel inline’

#ethtool –set-priv-flags $iface channel-inline-flow-director on

4.禁用LLDP

#ethtool –set-priv-flags $iface fw-lldp-agent off

5.禁用channel packet inspection optimization

#ethtool –set-priv-flags $iface channel-pkt-inspect-optimize off

6.启用繁忙的轮询专用标志(这里要求ice版本1.1.0以上)

#ethtool –set-priv-flags $iface channel-pkt-clean-bp-stop on

#ethtool –set-priv-flags $iface channel-pkt-clean-bp-stop-cfg on

7.验证配置

#ethtool -k $iface | grep “hw-tc”

#ethtool –show-priv-flags $iface

输出范例如下

link-down-on-close : off

fw-lldp-agent : off

channel-inline-flow-director : on

channel-pkt-inspect-optimize : off

channel-pkt-clean-bp-stop : on

channel-pkt-clean-bp-stop-cfg: on

vf-true-promisc-support : off

mdd-auto-reset-vf : off

legacy-rx : off

以上所有网卡优化的步骤总结在以下脚本里:

iface=#ifacename

modprobe -r ice

modprobe ice

ethtool -K $iface hw-tc-offload on

ethtool --set-priv-flags $iface channel-inline-flow-director on

ethtool --set-priv-flags $iface fw-lldp-agent off

ethtool --set-priv-flags $iface channel-pkt-inspect-optimize off

ethtool --set-priv-flags $iface channel-pkt-clean-bp-stop on

ethtool --set-priv-flags $iface channel-pkt-clean-bp-stop-cfg on

ethtool -k $iface | grep "hw-tc"

ethtool --show-priv-flags $iface

NVME/TCP的ADQ特性在target端的配置实例 

在NVMe/TCP target端配置ADQ

本章节详细介绍如何配置NVME/TCP并使能ADQ特性。“[ADQ]”表示ADQ相关配置,当测试baseline的TCP性能时,不能够配置相应的命令。这里不要求ADQ既配置在target端也配置在host端。任何配置了ADQ的TCP端都可以和没有配置ADQ的TCP端通信。

1.[ADQ]创建TC

# tc qdisc add dev $iface root mqprio num_tc 2 map 0 1 queues $num_queues_tc0 $num_queues_tc1@$num_queues_tc0 hw 1 mode channel

# tc qdisc add dev $iface ingress

2.[ADQ]创建TC filter,这里NVMe/TCP target使用dst_port,NVMe/TCP host使用src_port。

# tc filter add dev $iface protocol ip ingress prio 1 flower dst_ip ${ipaddrserver}/32 ip_proto tcp dst_port $app_port skip_sw hw_tc 1

3.[ADQ]验证TC配置正确性

验证TC正确地创建了

# tc qdisc show dev $iface

验证TC filter

# tc filter show dev $iface ingress

4.将tx的终端审核率设置为静态值,并关闭rx的中断审核率

#ethtool --coalesce ${iface} adaptive-rx off rx-usecs 0

#ethtool --coalesce ${iface} adaptive-tx off tx-usecs 500

5.运行ice目录中的set_irq_affinity脚本

#${pathtoicepackage}/scripts/set_irq_affinity local $iface

6.[ADQ]运行ice目录中的set_xps_rxqs脚本

#${pathtoicepackage}/scripts/set_xps_rxqs $iface

7.设置busy_read值

# sysctl -w net.core.busy_read=1

以上所有nvmf target端ADQ配置可以总结为以下脚本:

iface=$ifacename

pathtoicepackage=$patch_to_ice_driver

num_queues_tc0=2

num_queues_tc1=8

cpumask="0x1F"

ipaddrserver=$ipaddrserver

app_port=4420

ifup $iface

sleep 5

tc qdisc add dev $iface root mqprio num_tc 2 map 0 1 queues $num_queues_tc0 $num_queues_tc1@$num_queues_tc0 hw 1 mode channel

tc qdisc add dev $iface ingress

tc filter add dev $iface protocol ip ingress prio 1 flower dst_ip ${ipaddrserver}/32 ip_proto tcp dst_port $app_port skip_sw hw_tc 1

tc qdisc show dev $iface

tc filter show dev $iface ingress

ethtool --coalesce ${iface} adaptive-rx off rx-usecs 0

ethtool --coalesce ${iface} adaptive-tx off tx-usecs 500

${pathtoicepackage}/scripts/set_irq_affinity local $iface

${pathtoicepackage}/scripts/set_xps_rxqs $iface

sysctl -w net.core.busy_read=1

在NVMe/TCP target端配置SPDK

1.切换到spdk目录

#cd spdk

2.为了获取更好的性能,建议将target使用的CPU限制为目标nvme设备的NUMA节点

#./scripts/setup.sh status

输出示例如图所示

BDF            Vendor  Device  NUMA    Driver       Device name

NVMe devices

0000:d9:00.0    8086    0a54    1       uio_pci_generic         -

0000:d8:00.0    8086    0a54    1       uio_pci_generic         -

0000:5e:00.0    8086    0a54    0       uio_pci_generic         -

0000:5f:00.0    8086    0a54    0       uio_pci_generic         -

#lscpu

输出示例如图所示

NUMA node0 CPU(s):   0-27,56-83

NUMA node1 CPU(s):   28-55,84-111

3.启动nvmf_tgt应用

#./build/bin/nvmf_tgt -m 0xAAAA

4.设置target端传入连接的轮询间隔

#./scripts/rpc.py nvmf_set_config -r 10000

5.是用rpc命令nvmf_create_transport来创建一个transport(包括TCP, RDMA, FC等,这里指定为TCP),-y 1选项只适用于使能ADQ的情况

#./scripts/rpc.py nvmf_create_transport -t tcp -q 128 -p 64 -c 4096 -I 131072 -u 131072 -a 128 -b 32 -n 4096 -y 1

这里每个参数的意义

-t tcp       #transport是tcp

-q 32       #最大qd

-p 64       #每个session最大queue

-c 4096     #胶囊(incapsule)数据大小为4096

-i 131072   #最大IO大小

-u 131072   #IO单位大小

-a 128      #最大AQ深度

-b 32       #缓冲大小

-n 4096     #transport可用的缓冲池数据

-y 1     #[ADQ]套接字优先级

6.配置NVMe bdev属性执行admin queue轮询异步事件的频率(-p选项),-n指定每次I/O尝试的次数,-a指定当超时(-t选项)采取的行动

#./scripts/rpc.py bdev_nvme_set_options -n 4 -t 0 -a none -p 10000

7.设置transport属性来使能posix的placement ID(SPDK20.10之后的版本)

#./scripts/rpc.py sock_impl_set_options –enable-placement_id -I posix

8.初始化subsystem

#./scripts/rpc.py framework_start_init

9.创建subsystem

#./scripts/rpc.py nvme_create_subsystem nqn.2019-o6.io.spdk:cnode1

10.允许任何host访问target端的subsystem

#./scripts/rpc.py nvmf_subsystem_allow_any_host -e nqn.2019-06.io.spdk:cnode1

11.为susbystem添加监听地址,端口号和transport

#./scripts/rpc.py nvmf_subsystem_add_listener -t tcp -a ${ipaddrserver} -s ${app_port} nqn.2019-06.io.spdk:cnode1

12.列出target端可用的NVMe设备

#./scripts/setup.sh status

13.为每个NVMe设备创建bdev controller

#./scripts/rpc.py bdev_nvme_attach_controller -b nvme1 -t pcie -a 000:8a:00.0

14.为每个nvme bdev添加namespace

#./scripts/rpc.py nvmf_subsystem_add_ns nqn.2019-06.io.spdk:cnode1 nvme1n1

15.查看所有配置的subsystem和transport

#./scripts/rpc.py nvmf_get_subsystems

#./scripts/rpc.py nvmf_get_transports

以上所有target端的SPDK配置可以总结为以下脚本

ipaddrserver=$ipaddrserver

app_port=$app_port

cpumask="0x1F"

pathtospdk=$path_to_spdk

nvmepciaddr=$nvme_pci_addr

nqnname=$nqn_name

nvmename1=$nvme_name

num_queues_tc1=8

cd   $pathtospdk

HUGEMEM=32768   ./scripts/setup.sh

./scripts/setup.sh   status

nohup   ./build/bin/nvmf_tgt --wait-for-rpc -m $cpumask 2>&1 > nvmf_tgt.log   &

sleep   10

./scripts/rpc.py   nvmf_set_config -r 10000

./scripts/rpc.py   bdev_nvme_set_options -n 4 -t 0 -a none -p 100000

./scripts/rpc.py   sock_impl_set_options --enable-placement_id -i posix

./scripts/rpc.py   framework_start_init

./scripts/rpc.py   nvmf_create_transport -t tcp -q 128 -p 64 -c 4096 -i 131072 -u 131072 -a 128   -b 32 -n 4096 -y 1

./scripts/rpc.py   nvmf_create_subsystem ${nqnname}

./scripts/rpc.py   nvmf_subsystem_allow_any_host -e ${nqnname}

./scripts/rpc.py   nvmf_subsystem_add_listener -t tcp -a ${ipaddrserver} -s ${app_port}   ${nqnname}

./scripts/rpc.py   bdev_nvme_attach_controller -b ${nvmename1} -t pcie -a ${nvmepciaddr}

./scripts/rpc.py   nvmf_subsystem_add_ns ${nqnname} "${nvmename1}n1"

./scripts/rpc.py   nvmf_get_subsystems

./scripts/rpc.py   nvmf_get_transports

完成测试之后的步骤

1.从target的控制器移除所有bdev

#./scripts/rpc.py bdev_nvme_detach_controller ${bdev}

2.停止nvmf_tgt

#ctrl+c

3.切换回到kernel驱动

#./scripts/setup.sh reset

NVME/TCP的ADQ特性在host端的配置实例 

在NVMe/TCP host端配置ADQ

1.[ADQ]创建TC

# tc qdisc add dev $iface root mqprio num_tc 2 map 0 1 queues $num_queues_tc0 $num_queues_tc1@$num_queues_tc0 hw 1 mode channel

#tc qdisc add dev $iface ingress

2.[ADQ]创建TC filter

# tc filter add dev $iface protocol ip ingress prio 1 flower dst_ip ${ipaddrhost}/32 ip_proto tcp src_port $app_port skip_sw hw_tc 1

3.[ADQ]验证所创建的TC

# tc qdisc show dev $iface

# tc filter show dev $iface ingress

4.将tx的终端审核率设置为静态值,并关闭rx的中断审核率

# ethtool --coalesce ${iface} adaptive-rx off rx-usecs 0

#ethtool --coalesce ${iface} adaptive-tx off tx-usecs 500

5.运行ice目录中的set_irq_affinity脚本

# ${pathtoicepackage}/scripts/set_irq_affinity local $iface

6.运行ice目录中的set_xps_rxqs脚本

# ${pathtoicepackage}/scripts/set_xps_rxqs $iface

7.设置busy_read值

# sysctl -w net.core.busy_read=1 

以上所有host端的ADQ配置可以总结为以下脚本

iface=$iface

pathtoicepackage=$path_to_ice_package

num_queues_tc0=2

num_queues_tc1=16

cpumask="0x1F"

ipaddrserver=$ipaddr_server

ipaddrhost=$ipaddr_host

app_port=$app_port

tc qdisc add dev $iface root mqprio num_tc 2 map 0 1 queues $num_queues_tc0@0 $num_queues_tc1@$num_queues_tc0 hw 1 mode channel

tc qdisc add dev $iface ingress

tc filter add dev $iface protocol ip ingress prio 1 flower dst_ip ${ipaddrhost}/32 ip_proto tcp src_port $app_port skip_sw hw_tc 1

tc qdisc show dev $iface

tc filter show dev $iface ingress

ethtool --coalesce ${iface} adaptive-rx off rx-usecs 0

ethtool --coalesce ${iface} adaptive-tx off tx-usecs 500

${pathtoicepackage}/scripts/set_irq_affinity local $iface

${pathtoicepackage}/scripts/set_xps_rxqs $iface

sysctl -w net.core.busy_read=1

在NVMe/TCP host端配置SPDK

1.通过tcp transport发现target端的NVMe设备

#modprobe nvme_tcp

#nvme discover -t tcp -a $ipaddrserver -s $app_port

    类似的运行结果如下

    Discovery Log Number of Records 1, Generation counter 6

    =====Discovery Log Entry 0======

    trtype:  unrecognized

    adrfam:  ipv4

    subtype: nvme subsystem

    treq:    not required

    portid:  0

    trsvcid: 4420

    subnqn:  nqn.2019-06.io.spdk:cnode1

    traddr:  192.168.4.9

2.分配huge page并把NVMe设备从内核驱动绑定到用户态驱动

# HUGEMEM=32768 ./scripts/setup.sh

3.运行fio命令

#fio fio.job

fio.job文件示例如下所示

    [global]

    ioengine=<path_to_spdk>/build/fio/spdk_bdev

    spdk_json_conf=<path_to_spdk_bdev.json>

    ramp_time=10

    runtime=100

    numjobs=1

    iodepth=1

    thread=1

    group_reporting=1

    direct=1

    norandommap=1

    time_based=1

    percentile_list=99:99.9:99.99

    iodepth_batch_complete_min=1

    iodepth_batch=8

    iodepth_batch_complete_max=32

    cpus_allowed_policy=split

    cpus_allowed=0-27

    filename=Nvme0n1

    [4k_rd]

    bs=4k

    rw=randread

spdk_bdev.json文件示例如下所示

    {"subsystems": [

    {

    "subsystem": "bdev",

        "config": [

                {

                  "params": {

                        "name": "Nvme0",

                        "trtype": "tcp",

                        "traddr": "192.168.4.9",

                        "adrfam": "ipv4",

                        "trsvcid": "4420",

                        "priority": "1",

                        "subnqn": "nqn.2019-06.io.spdk:cnode1"

                  },

                  "method": "bdev_nvme_attach_controller"

                }

        ]

    }

    ]

}

故障排除 

网络问题

注意当你下载所需的软件或者kernel文件的时候遇到网络问题,可以尝试打开代理

参考文献

[1] CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 上篇

转载须知

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

推荐阅读

在SPDK中使能E810网卡ADQ 特性

CVL网卡的ADQ特性在SPDK的NVMF测试中的应用实例 - 上篇

你的一个“分享”

让我们之间的距离又近了一步


转载:https://blog.csdn.net/weixin_37097605/article/details/110508233
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场