作者:markchen7788
接触NVIDIA网络产品和SDN、NFV技术差不多一年左右,从2021年8月开始接触的NVIDIA ConnectX-6 Dx(以下简称cx6),3个月后开始接触NVIDIA BlueField-2 DPU(以下简称bf2)。本文将结合自己的探索经历来介绍如何快速入门NVIDIA BlueField-2 DPU,主要包括:
1)如何使用SR_IOV+OVS构建自己的拓扑;
2)如何运行DOCA应用(DNS_Filter)。
cx6-dx 作为子模块集成到bf2中,所以本文会将两者进行一些比较。另外,bf2的许多功能需要运行在嵌入式模式(Embedded CPU Function Ownership Mode)下,因此接下来的操作我们默认在嵌入式模式下进行,DOCA 版本为DOCA_1.3.0。
一、关于BlueField-2 DPU的一些必要知识
1.嵌入式模式下的默认拓扑和流量走向
1)在arm中查看嵌入式模式下的默认拓扑
[attach]20042[/attach]
2)拓扑图和流量走向
[attach]20044[/attach]
备注:
(1)黄色口为代表口,不可以用内核协议栈来发包,粉色口可以配置IP用来发包;
(2)其中pf0、pf1为主机上的物理网口,pf0hpf、pf1hpf是它们在arm中的代表口;
(3)enp3s0f0s0、enp3s0f1s0为arm上的SF口,en3f0pf0sf0、en3f1pf1sf0为它们的代表口,很多文档都说到的实际上是代表口,进而让我忽略了实际网口,导致我很久才明白enp3s0f0s0、enp3s0f1s0这两个实际网口的作用。DOCA程序中收发报文用到的SF网口是enp3s0f0s0、enp3s0f1s0这两个网口,并不是代表口。这两个SF口和主机的物理口具有同样的作用,配置同一网段IP后支持发送各类报文(包括RDMA)并进行互通,两者互通的带宽可达100Gb/s左右。(从主机传送大量数据给arm时,除了可以使用tmfifo_net0这一管理端口,还可以使用sf,并且sf更快,使用RDMA协议传输文件体验更舒适。)
(4)tmfifo_net0、oob_net0为管理端口,tmfifo_net0通过rshim driver与主机互联通信,oob_net0通过1G以太网口通信。
(5)p0、p1为流量出口。
⑥流量走向:
pf0向远端设备发送流量:pf0—>pf0hpf—>ovsbr1—>p0—>以太网—>目的地
pf0向arm sf发送流量:pf0—>pf0hpf—>ovsbr1—>en3f0pf0sf0—>enp3s0f0s0
2.VF和SF
SF和VF类似,都是通过SR_IOV技术虚拟化出来的PCIE设备。VF出现在宿主机中,可提供给虚拟机使用;SF出现在arm中,主要作用就是构建网络拓扑,分离出流量提供给DOCA应用程序进行处理并将处理好的流量再次传入网络。常用的拓扑如下所示。
[attach]20043[/attach]
备注:
(1)pf0vf0是vf0在DPU上的代表口,连接到OVS后,可以将VM的流量送入DOCA APP进行处理。以此作为实例阐明一下SF、VF的区别;
(2)建议使用DOCA APP时,重新申请两个SF,一个连接宿主机端,一个连接远端。默认的两个SF(enp3s0f0s0、enp3s0f1s0)不在同一个PCIE设备上,且默认的SF标识无从所知,以此使用DOCA APP可能会出现问题,所以建议在同一个PCIE设备上重新申请两个SF,默认的SF用作通信;
3.cx6-dx和bf2的区别
(1)cx6-dx只卸载了数据平面到硬件中;
(2)bf2卸载了数据平面+控制平面,数据平面运行在硬件中,控制平面运行在DPU的arm核中;
(3)最直观的表现就是:插上cx6-dx时,vf的representor出现在host OS中;插上bf2时,vf的representor出现在DPU OS中(划重点),vm网络(VPC)的控制平面运行在arm上。更进一步说,当需要同时卸载控制平面和数据平面实现裸金属服务器时,只有bf2才能胜任。
二、构建拓扑
1.开启VF和SF的方式不做赘述,可参考如下链接,来源DOCA SDK文档:
- 开启VF的参考链接:
[u]https://docs.nvidia.com/doca/sdk/virtual-functions/index.html[/u]
- 开启SF的参考链接:
[u]https://docs.nvidia.com/doca/sdk/scalable-functions/index.html[/u]
-
ovs的使用方式,可自行搜索进行学习,学会构建拓扑和下发流表就足够了;
-
构建一个实例拓扑,用于接下来运行doca app:
①在pf0上申请两个sf:
/opt/mellanox/iproute2/sbin/mlxdevm port add pci/0000:03:00.0 flavour pcisf pfnum 0 sfnum 4
/opt/mellanox/iproute2/sbin/mlxdevm port add pci/0000:03:00.0 flavour pcisf pfnum 0 sfnum 5
/opt/mellanox/iproute2/sbin/mlxdevm port function set pci/0000:03:00.0/229409 hw_addr 02:25:f2:8d:a2:4c trust on state active
/opt/mellanox/iproute2/sbin/mlxdevm port function set pci/0000:03:00.0/229410 hw_addr 02:25:f2:8d:a2:5c trust on state active
echo mlx5_core.sf.4 > /sys/bus/auxiliary/drivers/mlx5_core.sf_cfg/unbind
echo mlx5_core.sf.4 > /sys/bus/auxiliary/drivers/mlx5_core.sf/bind
echo mlx5_core.sf.5 > /sys/bus/auxiliary/drivers/mlx5_core.sf_cfg/unbind
echo mlx5_core.sf.5 > /sys/bus/auxiliary/drivers/mlx5_core.sf/bind
②创建拓扑
/home/ubuntu/scripts# ovs-vsctl add-br ovs-test
/home/ubuntu/scripts# ovs-vsctl del-port p0
/home/ubuntu/scripts# ovs-vsctl del-port pf0hpf
/home/ubuntu/scripts# ovs-vsctl add-port ovs-test pf0hpf
/home/ubuntu/scripts# ovs-vsctl add-port ovs-test p0
/home/ubuntu/scripts# ovs-vsctl add-port ovs-test en3f0pf0sf4
/home/ubuntu/scripts# ovs-vsctl add-port ovs-test en3f0pf0sf5
③下发和检查流表
ovs-ofctl del-flows ovs-test
ovs-ofctl add-flow ovs-test “priority=1,in_port=pf0hpf,actions=output:p0”
ovs-ofctl add-flow ovs-test “priority=2,in_port=p0,actions=output:pf0hpf”
ovs-ofctl add-flow ovs-test “priority=3,in_port=pf0hpf,udp,tp_dst=53,actions=output:en3f0pf0sf4”
ovs-ofctl add-flow ovs-test “priority=3,in_port=en3f0pf0sf5,udp,tp_dst=53,actions=output:p0”
ovs-ofctl add-flow ovs-test “priority=4,in_port=p0,udp,tp_dst=53,actions=output:en3f0pf0sf5”
ovs-ofctl add-flow ovs-test “priority=4,in_port=en3f0pf0sf4,udp,tp_dst=53,actions=output:pf0hpf”
ovs-ofctl dump-flows ovs-test
拓扑图如下所示:
[attach]20045[/attach]
注意:
①ovs-test上的流表不能形成环路,DNS_Filter使用了hairpin队列将非DNS流量卸载转发,因此不删除“actions=NORMAL”这一表项可能会造成环路进而转发失败,可能产生的环路如下图所示:
[attach]20046[/attach]
②如果不设置好DNS_Filter处理过的DNS流量的走向,DNS流量也可能产生环路,可能产生的环路如下图所示:
[attach]20047[/attach]
- 其它值得注意的地方:
①arm 上的OVS默认开启了硬件卸载,会对流表执行自动卸载:
eg:利用iperf工具在宿主机上打流量,在arm上查看动态卸载的流表:
sudo ovs-appctl dpctl/dump-flows type=offloaded
[attach]20048[/attach]
②重启OVS命令如下,DPU OS文档中的命令有些许问题。重启DPU或者重启OVS,通过ovs-ofctl命令下发的流表都会消失,需要重新下发;
sudo /etc/init.d/openvswitch-switch restart
③通过ovs-tcpdump 命令可以在arm上抓取代表口的流量。(roce v2的流量可以在pf0hpf上抓取,不过非常不建议这样做,会极大削弱RDMA的性能)[attach]20049[/attach]
三、运行DOCA程序(DNS_Filter为示例)
1.按照如下步骤,在二中建立好的拓扑上运行DNS_Filter实例
编译RXP过滤规则,DNS_Filter借助Regex Engine实现了DNS的白名单功能(不是黑名单哦!!!),写下域名的正则表达式规则并利用rxp_compiler进行编译。如下是本人编写的规则,允许符合以下四条规则的DNS流量通过。
[attach]20050[/attach]
DNS过滤规则
①编译规则:
rxpc -f regex_rules.txt -p 0.01 -o /tmp/regex_rules
②申请大页,供DPDK使用
echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
③开启regex服务
systemctl start mlx-regex
④没有什么特殊要求,直接/opt/mellanox/doca/applications/DNS_Filter/bin/目录下的运行编译好的程序和并使用json配置文件的参数即可:
./doca_dns_filter --json ./DNS_Filter_params.json
2.验证
1)可以将pf0桥接给vm使用,从而跟物理机网络隔离,或者直接申请一个vf,利用vf-rep在arm中构建上述拓扑也行,最后务必将p0连接至公网。
2)清除一下主机上的DNS缓存,本人在vm中运行的是ubuntu kylin 20.4 OS,命令如下:
sudo systemd-resolve --flush-caches
1)用浏览器浏览域名在白名单中的网页,或者直接ping域名:
[attach]20051[/attach]
VM ping “www.baidu.com”
[attach]20052[/attach]
DNS_Filter运行结果
2)ping 非白名单中的域名:
[attach]20053[/attach]
VM ping “360.cn”
3.为什么不使用官方实例中的拓扑的原因:
1)官方拓扑不需要配置任何流表,但是要在程序中通过建立hairpin队列来实现非DNS流量的卸载;
2)上述建立的拓扑通过ovs的命令将DNS流量分离给DOCA APP处理,可以不再需要hairpin队列,但是配置麻烦了一点;
3)个人觉得用ovs提前将目标流量分离出来更符合实际需求。特别是你需要运行多个doca app时,将流量提前用ovs分离出来更方便。
参考文档:
1)NVIDIA BlueField-2 Ethernet DPU User Guide(硬件文档):
[u]https://docs.nvidia.com/networking/display/BlueField2DPUENUG[/u]
2)NVIDIA BLUEFIELD DPU PLATFORM OPERATING SYSTEM v3.9.2 DOCUMENTATION(软件文档):[u]https://docs.nvidia.com/networking/display/BlueFieldDPUOSLatest[/u]
3)DOCA SDK文档:[u]https://docs.nvidia.com/doca/sdk/index.html[/u]