作者: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中查看嵌入式模式下的默认拓扑 2)拓扑图和流量走向 备注: (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应用程序进行处理并将处理好的流量再次传入网络。常用的拓扑如下所示。 备注: (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的参考链接: * 开启SF的参考链接: 2. ovs的使用方式,可自行搜索进行学习,学会构建拓扑和下发流表就足够了; 3. 构建一个实例拓扑,用于接下来运行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
拓扑图如下所示: 注意: ①ovs-test上的流表不能形成环路,DNS_Filter使用了hairpin队列将非DNS流量卸载转发,因此不删除“actions=NORMAL”这一表项可能会造成环路进而转发失败,可能产生的环路如下图所示: ②如果不设置好DNS_Filter处理过的DNS流量的走向,DNS流量也可能产生环路,可能产生的环路如下图所示: 2. 其它值得注意的地方: ①arm 上的OVS默认开启了硬件卸载,会对流表执行自动卸载: eg:利用iperf工具在宿主机上打流量,在arm上查看动态卸载的流表: sudo ovs-appctl dpctl/dump-flows type=offloaded ②重启OVS命令如下,DPU OS文档中的命令有些许问题。重启DPU或者重启OVS,通过ovs-ofctl命令下发的流表都会消失,需要重新下发; sudo /etc/init.d/openvswitch-switch restart ③通过ovs-tcpdump 命令可以在arm上抓取代表口的流量。(roce v2的流量可以在pf0hpf上抓取,不过非常不建议这样做,会极大削弱RDMA的性能)
三、运行DOCA程序(DNS_Filter为示例) 1.按照如下步骤,在二中建立好的拓扑上运行DNS_Filter实例 编译RXP过滤规则,DNS_Filter借助Regex Engine实现了DNS的白名单功能(不是黑名单哦!!!),写下域名的正则表达式规则并利用rxp_compiler进行编译。如下是本人编写的规则,允许符合以下四条规则的DNS流量通过。 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域名: VM ping “www.baidu.com” DNS_Filter运行结果 2)ping 非白名单中的域名: 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(硬件文档): |