https://cloud.tencent.com/developer/article/1989615
本文全是个人感想和猜测,写一写软件人眼中的硬件,越底层越难,个人理解不一定对,请用批判的眼光看,特此声明,免得被人贻笑大方。
大学学的是计算机专业,学过《计算机组成原理》和《计算机体系结构》,工作十年了还是觉得自己对计算机硬件理解的很浅,以前做过交换机,一直想用自己所学的计算机体系结构知识解释下一台框式交换机的体系结构,但一直没想明白,现在碰到mellanox DPU bluefield-2卡,感觉自己又有点懵逼,这玩意站在计算机体系结构的角度怎么解释,请听我乱讲。
DPU上内置交换芯片,还有自己的ARM CPU和DRAM,卡上可以单独运行自己的操作系统,它就是一台SOC计算机,有自己的PCI-e结构,有03:00.0和03:00.1两个PCI-e endpoint,它俩用的驱动是mlx5_core。
代码语言:javascript复制root@dpu:/# lspci
00:00.0 PCI bridge: Mellanox Technologies MT42822 BlueField-2 SoC Crypto disabled
01:00.0 PCI bridge: Mellanox Technologies MT42822 Family [BlueField-2 SoC PCIe Bridge]
02:00.0 PCI bridge: Mellanox Technologies MT42822 Family [BlueField-2 SoC PCIe Bridge]
03:00.0 Ethernet controller: Mellanox Technologies MT42822 BlueField-2 integrated ConnectX-6 Dx network controller
03:00.1 Ethernet controller: Mellanox Technologies MT42822 BlueField-2 integrated ConnectX-6 Dx network controller
mellanox的卡上交换芯片有legacy和switchdev模式,在switchdev模式下,每创建一个vf就为这个vf生成一个representor,legacy模式下创建vf不会为这个vf生成representor,主要是switchdev下可以做offload,但并不是所有报文在任何情况下都能成功命中硬件规则,如果不命中需要cpu介入处理,此时vf已经passthrough给虚拟机,物理机不能再操作vf,需要一种机制把报文从交换芯片再搬运到物理机DRAM中,representor就代表着这种机制,硬件为representor提供这种能力,软件上看representor就是一个netdev,添加到ovs上,ovs是软件交换机,交换芯片是硬件交换机,ovs offload一些功能到硬件交换机,exception path由ovs处理,多么完美的模型。
DPU卡上能创建subfunction,subfunction可以简单理解为驱动和硬件给操作系统把这张卡复制了几份,但其实并没有增加PCI-e endpoint,只是多虚拟了几份,方便用于虚拟化环境,卡上做数据面加速并且在数据面上实现资源切分和隔离,控制还是由驱动来处理,类似于mdev。
代码语言:javascript复制root@dpu:/sys/bus# mlnx-sf -a show
SF Index: pci/0000:03:00.0/294912
Parent PCI dev: 0000:03:00.0
Representor netdev: en3f0pf0sf0
Function HWADDR: 02:77:53:3f:f9:7b
Auxiliary device: mlx5_core.sf.2
netdev: enp3s0f0s0
RDMA dev: mlx5_2
SF Index: pci/0000:03:00.1/360448
Parent PCI dev: 0000:03:00.1
Representor netdev: en3f1pf1sf0
Function HWADDR: 02:33:5d:18:b5:fa
Auxiliary device: mlx5_core.sf.3
netdev: enp3s0f1s0
RDMA dev: mlx5_3
这张卡物理上具有RDMA和Ethernet的功能,所以mlx5_core又给操作系统抽象出rdma device和net device,还有这两种device的representor,并把这些device都挂载到auxiliary bus上。真真假假,虚虚实实,一堆设备在/sys目录下,互相都有链接,仔细分析还是有逻辑和章法,eth-rep.0和eth-rep.1是物理机上两个netdev的representor,rdma-rep.0和rdma-rep.0是物理机上两个rdma device的representor,eth.0和eth.1对应着DPU卡两个uplink port,sf.2和sf.3是创建的两个subfunction,eth.2/eth.3/rdma.2/rdma.3是这两个subfunction提供的功能。
代码语言:javascript复制root@dpu:/sys/class/infiniband# ll
total 0
drwxr-xr-x 2 root root 0 Aug 9 02:42 ./
drwxr-xr-x 66 root root 0 Aug 9 02:42 ../
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_0 -> ../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/infiniband/mlx5_0/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_1 -> ../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/infiniband/mlx5_1/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_2 -> ../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.sf.2/infiniband/mlx5_2/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_3 -> ../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.sf.3/infiniband/mlx5_3/
root@dpu:/sys/bus/auxiliary# ll drivers
total 0
drwxr-xr-x 9 root root 0 Aug 9 02:42 ./
drwxr-xr-x 4 root root 0 Aug 9 02:42 ../
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_core.eth/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_core.eth-rep/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_core.sf/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_core.sf_cfg/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_ib.multiport/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_ib.rdma/
drwxr-xr-x 2 root root 0 Aug 9 02:42 mlx5_ib.rep/
root@dpu:/sys/bus/auxiliary# ll devices/
total 0
drwxr-xr-x 2 root root 0 Aug 9 02:42 ./
drwxr-xr-x 4 root root 0 Aug 9 02:42 ../
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.eth-rep.0 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.eth-rep.0/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.eth-rep.1 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.eth-rep.1/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_core.eth.0 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.eth.0/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_core.eth.1 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.eth.1/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.eth.2 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.sf.2/mlx5_core.eth.2/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.eth.3 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.sf.3/mlx5_core.eth.3/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.rdma-rep.0 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.rdma-rep.0/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.rdma-rep.1 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.rdma-rep.1/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.rdma.2 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.sf.2/mlx5_core.rdma.2/
lrwxrwxrwx 1 root root 0 Aug 10 06:44 mlx5_core.rdma.3 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.sf.3/mlx5_core.rdma.3/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_core.sf.2 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.0/mlx5_core.sf.2/
lrwxrwxrwx 1 root root 0 Aug 9 02:42 mlx5_core.sf.3 -> ../../../devices/pci0000:00/0000:00:00.0/0000:01:00.0/0000:02:00.0/0000:03:00.1/mlx5_core.sf.3/
DPU内置交换芯片,操作系统要管理交换芯片,mellanox搞了devlink这一套通用管理方法。
代码语言:javascript复制root@dpu:/sys/bus# devlink dev
pci/0000:03:00.0
pci/0000:03:00.1
auxiliary/mlx5_core.sf.2
auxiliary/mlx5_core.sf.3
root@dpu:/sys/bus# devlink port
pci/0000:03:00.0/327679: type eth netdev p0 flavour physical port 0
pci/0000:03:00.0/262144: type eth netdev pf0hpf flavour pcipf pfnum 0
pci/0000:03:00.1/393215: type eth netdev p1 flavour physical port 1
pci/0000:03:00.1/327680: type eth netdev pf1hpf flavour pcipf pfnum 1
auxiliary/mlx5_core.sf.2/3473408: type eth netdev enp3s0f0s0 flavour physical port 0
auxiliary/mlx5_core.sf.3/7667712: type eth netdev enp3s0f1s0 flavour physical port 0
DPU有两种运行模式Separated和Embeded,Separated模式下网卡流量在DPU和物理机之间平分,可以理解为mellanox网卡的multiple-host PCI-e技术,这种模式下物理机和DPU上都不能配置交换芯片offload,可能交换芯片上资源不能切分。Embeded模式下交换芯片被DPU独占,DPU就可以配置交换芯片的offload,理解起来和虚拟化环境有点类似的感觉,虚拟化环境虚拟机占用了vf,物理机有vf的representor,物理机配置offload,这里物理机占用了pf,DPU有pf的representor,DPU配置offload,但从硬件角度来看完全不一样,虚拟化环境虽然有vf但硬件上是一套PCI-e结构,这里有两套PCI-e结构,难道DPU卡偷偷加了一根线和一个口,把物理机的口和DPU加的这个口通过线连接在一起,这样物理机发送的报文就到了DPU PCI-e这个口,如果flow能命中就硬件处理,不能命中通过representor上送给ARM处理。
intel网卡升级firmware可以把一个40G口分成4个10G口用,mellanox网卡一些功能也要求firmware升级到一个特定的版本,升级后重启生效。升级时把firmware存在网卡的flash中,网卡重启后加载firmware,firmware和硬件结合后,CPU看到的网卡表现就不同了,真神奇,也不知道firmware ASIC和FPGA有啥不同?
代码语言:javascript复制root@dpu:/opt/mellanox/mlnx-fw-updater# ./mlnx_fw_updater.pl
Initializing...
Attempting to perform Firmware update...
Querying Mellanox devices firmware ...
Device #1:
----------
Device Type: BlueField2
Part Number: MBF2H332A-AENO_Ax_Bx
Description: BlueField-2 P-Series DPU 25GbE Dual-Port SFP56; PCIe Gen4 x8; Crypto Disabled; 16GB on-board DDR; 1GbE OOB management; HHHL
PSID: MT_0000000539
PCI Device Name: 03:00.0
Base GUID: 043f720300ea4fb0
Base MAC: 043f72ea4fb0
Versions: Current Available
FW 24.31.1014 24.31.1014
NVMe N/A 20.1.0003
PXE 3.6.0403 3.6.0403
UEFI 14.24.0013 14.24.0013
UEFI Virtio blk 22.1.0011 22.1.0011
UEFI Virtio net 21.1.0011 21.1.0011
UEFI一般是启动时用,等操作系统加载后UEFI可以给操作系统提供run time service,但一般操作系统很少用到,这儿怎么有个UEFI Virtio blk/net???
在DPU卡可以给物理机模拟nvme/virtio_blk/virtio_net,相当于给物理机的PCI-e总线上hotplug了一个endpoint,首先要模拟PCI-e配置空间,其次要模拟virtio通用部分,如virtqueue写哪个寄存器,doorbell在哪?最后要模拟网卡或者磁盘专有部分,如MAC/MTU写到哪里。
代码语言:javascript复制root@dpu:~# snap_rpc.py emulation_managers_list
[
{
"emulation_manager": "mlx5_0",
"hotplug_support": true,
"supported_types": [
"nvme",
"virtio_blk",
"virtio_net"
]
}
]
个人理解PCI-e是报文式交互,DPU卡给物理机RC发PCE-e报文,报文信息就是我这多了个PCI-e设备,配置空间长什么样。物理机驱动读写这个PCI-e设备时RC就把读写请求封装在PCI-e报文,然后把报文路由给DPU卡,DPU卡收到后做对应的处理。
DPU卡提供了一个库和两个应用程序模拟PCI-e设备。
- mlnx-libsnap
Library that assists in common tasks when interacting with the emulating hardware in order to present a SNAP device to an external host or a VM.
- mlnx-snap
Mellanox Device emulation SDK and controller emulation
- virtio-net-controller
Mellanox virtio-net device full emulation SDK and controller
devx allows userspace access firmware objects,RDMA device就是通道,用户态程序操作firmware,firmware触发PCI-e报文的收发。
https://github.com/linux-rdma/rdma-core/pull/397
https://github.com/torvalds/linux/commit/a8b92ca1b0e5ce620e425e9d2f89ce44f1a82a82
DPU卡要处理doorbell/中断/DMA,而且要同时处理物理机x86和ARM侧的这三点,假如物理机要把一块数据从自己的DRAM搞到DPU的DRAM,那么物理机首先要触发doorbell,DPU DMA搬数据到ARM的DRAM,DPU中断ARM,DPU中断物理机,到底什么顺序,DMA了几次,什么个细节搞不明白,DPU卡上x86和ARM的cache一致性又是怎么实现的,想想就复杂。
看了阿里在HotChips讲的神龙架构,和mellanox DPU比较一下,感觉最核心有三点:
- 一对多
一个白色的baremetal hypervisor要支持很多个灰色的裸金属服务器,反观mellanox DPU,一台裸金属服务器上需要一张DPU卡,即使用了multiple-host才能支持4台裸金属服务器,成本还是太高,一张DPU卡要支持更多裸金属服务器。
- shadow vring
这技术就相当于在裸金属服务器和DPU卡之间交互IO数据,大概明白,细节不清楚。
- memory pool
不知道自己理解的对不对,意思就是裸金属服务器的内存大小可以随便指定,内存都不在本地,如果CPU型号和个数也能随便定,CPU和内存随便组合,那真是牛逼大发了,反观自己想的格局太小,如果阿里真实现了,那感觉要颠覆计算机体系结构了,大学课本必须让阿里重新写。
假如说我有一张xilinx的PCI-e卡,卡上有ASIC,有FPGA,有ARM,我把这张卡插在x86服务器上,数据在x86 CPU/ASIC/FPGA/ARM之间又该怎么传来传去?
硬件真是太难了,真希望有高人给我高屋建瓴地指点一把,也许没有捷径。