草庐IT

dpu云主机网络性能问题排查记录

北京五道口A口 2023-09-16 原文

背景

对基于DPU(Mellanox BF2)云主机产品进行网络性能摸底,发现小规格(2核4G内存1队列)的vm pps结果远低于预期,跟非DPU、同规格普通云主机对比,性能差至少一半


环境、测试方案描述

环境拓扑描述
image.png

=

测试方法描述

两台vm端到端通过内核版pktgen工具打流,通过sar观察 tx 和 rx 的pps

image.png
现象

观察、统计了2个云主机,一个tx:49wpps,另一个rx:15wpps,且和普通云主机对比,性能差距明显

image.png

上图第三列是dpu云主机结果,第二列和第三列是不同性能的普通云主机

普通云主机的性能:

image.png

阶段一

初步排查思路

- 小规格vm性能问题
- DPU上流表是否卸载
- vm网卡的队列数,队列深度
- vm的cpu能力,比如频率
- pci 带宽瓶颈
- 整机vf资源数,是否达到最大值,其他vf也在打流
- vm的性能调优
- 宿主机cpu或其他资源竞争

排查过程

- 排除小规格vm性能打不上去

通过在大规格vm(32c 8 queue)跑内核版pktgen打流,观察pps发包性能打到了380wpps,但仍然远远低于预期(2000w+pps)。

然后怀疑打流工具, 让测试用用户态dpdk的程序:dpdk-pktgen或testpmd测试,通过testpmd打流,大规格vm可以将tx 方向pps打到2000w+pps,但是对端只能接受几十万pps

  • 测试方法(testpmd代替内核版pktgen)
# tx
/tmp/dpdk-testpmd2 -a 00:03.0  -l 0-31 -n 4   -- -i --rxq=8 --txq=8 --rxd=2048 --txd=2048 --burst=64  --nb-cores=31 --forward-mode=txonly --eth-peer=0,fa:16:3e:31:ad:12  --tx-ip=10.10.0.26,10.10.0.57
# rx
/tmp/dpdk-testpmd2 -a 00:03.0  -l 0-31 -n 4   -- -i --rxq=8 --txq=8 --rxd=2048 --txd=2048 --burst=64  --nb-cores=31 --forward-mode=rxonly
- 丢包位置排查

换了打流工具后,大规格vm(12c 8队列)和小规格vm(2c 单队列)分别能打出2000wpps和290wpps的性能,此时已经排除了最开始怀疑的vm性能 tx打流上不去的问题。

需要排查丢包点位置,通过在裸机-A、DPU-A、DPU-B、裸机-B上同时多点观察流量统计,包括在vm的vf在DPU的代表口和物理口(bond1,p0,p1),如下右图,从DPU角度看代表口rx pps和物理口的tx pps,多次尝试、正方向打流,报文都是在DPU转发的时候丢了,所以应该排查DPU的转发问题

image.png
- DPU上的流表是否卸载

通过在dpu上查看dp流表卸载状态,多次尝试、多方(厂商和我们)确认dp流表都是卸载状态; 通过观察dp流表的统计的确生效,且offladed=yes

image.png

image.png
- 查看dpu的性能瓶颈

流表是卸载的,但当前转发性能远远达不到硬件的预期值,故通过NVIDIA提供的性能监控工具,收集性能信息;

可以从dpu的throughput、 memory、 pcie bandwidth、pcie latency、pcie latency to arm、pps、eswich多个维度去观察当前负载,但是观察下来没有异常

image.png

image.png
- 排查ovs的配置和计算节点的配置

既然dp流表卸载了,且没有达到dpu的各项瓶颈,那么需要继续排查ovs的配置和计算节点的配置,经过和裸金属等dpu配置对比,未发现异常

image.png

计算节点的绑核、隔离调优等,尝试过该因素后,未有明显改善

image.png
怀疑是vm的多队列没有三裂开,同样也怀疑是虚拟化方案,virtio-net存在性能瓶颈,>厂商研发角度:dpu在卡上有个嵌入式芯片去做virio描述符转硬件描述符的动作,可能性能存在瓶颈,但远不至于是40wpps

怀疑是vm的配置参数没有调优,导致vm的多队列没有生效;通过调整vm vcpu的亲和性(vm的vcpu和宿主机物理cpu绑定),且打开了网卡的多队列,效果仍然不明显!

      <driver queues='8' rx_queue_size='1024' tx_queue_size='1024' page_per_vq='on'>
        <host mq='on'/>
      </driver>
排除虚拟化方案

基于以上各种因素调整后,未有改善,此时大家怀疑是虚拟化方案存在瓶颈,需要做最后确认,尝试通过用宿主机的 pf(mlx_core)打流,模拟裸金属的性能,结果性能仍然一样,拓扑如下:

image.png
总结

通过以上尝试,发现dpu云主机的性能上不去,原因跟虚拟化方案不存在直接关系,怀疑是该dpu的环境问题,因为物理口也打不上去


阶段二

根据阶段一的排查,排除了vm的打流性能瓶颈、虚拟化方案瓶颈、dpu的性能瓶颈、流表未卸载、vm的cpu亲和性、vm的多队列等等因素。

新排查思路

和厂商多位研发讨论后,根据问题的现象、性能的实际瓶颈,怀疑dpu还是用的软件转发,并未用硬件转发或者整个pipeline部分流表未实际卸载。

排查过程

排除虚拟化和vnet的复杂流表对卸载的影响

为了该猜想,我们同时排除虚拟化因素,故:

  1. 采用裸机的物理口打流
  2. 创建私有ovs网桥,配置vxlan隧道
  3. 将物理口的代表口添加到私有网桥上
  4. 只配置normal流表
    打流发现性能仍然很低,但是此时dp flow的卸载 offladed:false,即未卸载。

经过排查该最基础的normal流表走vxlan隧道,未卸载,最终排查原因是software steer对table=0的流表不支持卸载,配置成多级流表,结果是卸载成功,此时dpu可以成功转发出去2000w+pps,此时又陷入了疑惑,现在又证明了物理机打流是可以的,虚拟化不行,那么是不虚拟化方案的确存在问题

于是最终又决定将某个vm的代表口同样加入到私有桥上,结果也能成功转发出去2000w+pps,此时已经可以完全排除虚拟化方案和dpu的硬件转发能力瓶颈了,此时,云主机性能问题初步归结为:dpu对云主机场景下vnet流表卸载支持存在问题

image.png
回头二次确认dpu对vnet流表是否卸载

将物理口和vm的代表口又恢复回去,加入到br-int桥,走vnet的流表。看dp流表的卸载情况,多人多方位确认:

  1. 怀疑pipeline某些流表没有卸载,故根据打流源、目ip过滤出来的每条dp流表挨个确认卸载标记: offladed:yes
  2. 不加任何过滤条件dump出来所有的dp流表,每条根据首包统计(个位数、千位、万级别的)过滤掉他们,因为打流期间是千万级别的pps,确定了都是带卸载标记

此时,看dpflow的卸载标记是卸载了,但是其性能又不是卸载能力,因为已经通过前面的步骤排除了硬件转发能力,那么怀疑此时dpu对云主机场景下的vnet卸载裸机和卸载标记存在bug。

确认dpdk软件是否承担转发

于是从软件层面进行确认:

  1. 通过看pmd的统计
    ovs-appctl dpif-netdev/pmd-stats-show
  2. pmd的负载
    ovs-appctl dpif-netdev/pmd-rxq-show
**软转发**
**完全卸载转发**
  1. pmd的rxq
    ovs-appctl dpif-netdev/pmd-perf-show
厂商研发分析

厂商底层研发结合dpflow、dpdk-pmd状态,打流方式,给出结论:单向udp + ct 是不支持卸载,至于dpflow带offloaded:yes是bug。

证明厂商研发给的结论

将云主机的打流方式应用到裸金属测试环境,一样性能打不上去,但是云主机用裸金属的打流方式是可以打上去的,证明最初用的普通云主机打流方法不适用与dpu场景。


总结

该性能摸底耗费时间精力较长,结论只是一个卸载能力支持的问题。但耗费了多人、几乎一礼拜的时间、精力来排查,原因总结为:
1. 我们对厂商的dpu支持能力不够清晰,包含厂商的部分研发和fae等
2. 研发对性能测试工具和方法经验缺乏,比如内核版pktgen,dpdk-pktgen,testpmd等
3. 云主机环境不稳定,耽搁较长时间
4. 厂商部分site员工放假(国外的该问题核心员工)

有关dpu云主机网络性能问题排查记录的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  4. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  5. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  6. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  7. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  8. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

  9. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐