【SR-IOV cni】(Part 4) SR-IOV Network Device Plugin 3.11.0 — 超深度架构分析

SR-IOV Network Device Plugin 3.11.0 --- 超深度架构分析

第四部分:总体架构、模块关系、核心流程与设计决策


一、总体架构

1.1 系统架构全景图

#mermaid-svg-tWxuwLCkvdy9Mp1C{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tWxuwLCkvdy9Mp1C .error-icon{fill:#552222;}#mermaid-svg-tWxuwLCkvdy9Mp1C .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tWxuwLCkvdy9Mp1C .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .marker.cross{stroke:#333333;}#mermaid-svg-tWxuwLCkvdy9Mp1C svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tWxuwLCkvdy9Mp1C p{margin:0;}#mermaid-svg-tWxuwLCkvdy9Mp1C .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster-label text{fill:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster-label span{color:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster-label span p{background-color:transparent;}#mermaid-svg-tWxuwLCkvdy9Mp1C .label text,#mermaid-svg-tWxuwLCkvdy9Mp1C span{fill:#333;color:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .node rect,#mermaid-svg-tWxuwLCkvdy9Mp1C .node circle,#mermaid-svg-tWxuwLCkvdy9Mp1C .node ellipse,#mermaid-svg-tWxuwLCkvdy9Mp1C .node polygon,#mermaid-svg-tWxuwLCkvdy9Mp1C .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .rough-node .label text,#mermaid-svg-tWxuwLCkvdy9Mp1C .node .label text,#mermaid-svg-tWxuwLCkvdy9Mp1C .image-shape .label,#mermaid-svg-tWxuwLCkvdy9Mp1C .icon-shape .label{text-anchor:middle;}#mermaid-svg-tWxuwLCkvdy9Mp1C .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .rough-node .label,#mermaid-svg-tWxuwLCkvdy9Mp1C .node .label,#mermaid-svg-tWxuwLCkvdy9Mp1C .image-shape .label,#mermaid-svg-tWxuwLCkvdy9Mp1C .icon-shape .label{text-align:center;}#mermaid-svg-tWxuwLCkvdy9Mp1C .node.clickable{cursor:pointer;}#mermaid-svg-tWxuwLCkvdy9Mp1C .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .arrowheadPath{fill:#333333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tWxuwLCkvdy9Mp1C .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tWxuwLCkvdy9Mp1C .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tWxuwLCkvdy9Mp1C .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster text{fill:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C .cluster span{color:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tWxuwLCkvdy9Mp1C .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tWxuwLCkvdy9Mp1C rect.text{fill:none;stroke-width:0;}#mermaid-svg-tWxuwLCkvdy9Mp1C .icon-shape,#mermaid-svg-tWxuwLCkvdy9Mp1C .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tWxuwLCkvdy9Mp1C .icon-shape p,#mermaid-svg-tWxuwLCkvdy9Mp1C .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tWxuwLCkvdy9Mp1C .icon-shape .label rect,#mermaid-svg-tWxuwLCkvdy9Mp1C .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tWxuwLCkvdy9Mp1C .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tWxuwLCkvdy9Mp1C .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tWxuwLCkvdy9Mp1C :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SR-IOV Network Device Plugin
外部系统
NAD集成
工具层
CDI层
服务器层
资源池层
过滤层
信息提供者层
设备构建层
设备发现层
工厂层
入口层
Kubernetes API Server
Kubelet Device Plugin Manager
Container Runtime: CRI-O/containerd
Multus CNI
cmd/sriovdp/main.go

信号管理/生命周期
cmd/sriovdp/manager.go

resourceManager
pkg/factory/factory.go

resourceFactory

所有组件的创建中心
pkg/netdevice/

netDeviceProvider

PCI Class 0x02
pkg/accelerator/

accelDeviceProvider

PCI Class 0x12
pkg/auxnetdevice/

auxNetDeviceProvider

辅助设备
pkg/devices/host.go

HostDeviceImpl

基类+InfoProvider组合
pkg/devices/gen_pci.go

GenericPciDevice

PCI装饰器
pkg/devices/gen_net.go

GenericNetDevice

网络装饰器
pkg/devices/rdma.go

RdmaDeviceSpec

RDMA能力
pkg/devices/vfio.go

VfioDevice

VFIO能力
pkg/devices/vdpa.go

VdpaDeviceImpl

vDPA能力
infoprovider/genericInfoProvider

通用: deviceID
infoprovider/vfioInfoProvider

VFIO: /dev/vfio/*
infoprovider/uioInfoProvider

UIO: /dev/uioX
infoprovider/rdmaInfoProvider

RDMA: /dev/infiniband/*
infoprovider/vdpaInfoProvider

vDPA: /dev/vhost-vdpa-*
infoprovider/vhostNetInfoProvider

vhost: /dev/vhost-net
infoprovider/extraInfoProvider

额外: 自定义键值
pkg/resources/deviceSelectors.go

12个选择器

策略模式
pkg/netdevice/netResourcePool

网络资源池+NAD
pkg/accelerator/accelResourcePool

加速器资源池
pkg/auxnetdevice/auxNetResourcePool

辅助资源池
pkg/resources/server.go

resourceServer

gRPC Device Plugin
pkg/cdi/cdi.go

CDI Spec生成/注解
pkg/utils/utils.go

SYSFS操作
pkg/utils/netlink_provider.go

netlink封装
pkg/utils/sriovnet_provider.go

sriovnet封装
pkg/utils/rdma_provider.go

rdmamap封装
pkg/utils/vdpa_provider.go

govdpa封装
pkg/netdevice/nadutils.go

NAD信息存储

1.2 架构分层

层次 模块 职责
入口层 cmd/sriovdp/ 程序启动、CLI参数、信号处理、资源管理器编排
工厂层 pkg/factory/ 组件创建中心,所有对象的工厂方法
设备发现层 pkg/netdevice/, accelerator/, auxnetdevice/ PCI/辅助设备扫描与 HostDevice 构建
设备构建层 pkg/devices/ 设备基类与装饰器,InfoProvider 组合链
信息提供者层 pkg/infoprovider/ 各类设备文件/环境变量/挂载点的生成策略
过滤层 pkg/resources/deviceSelectors.go 12个设备选择器的策略模式实现
资源池层 三个子包中的 ResourcePool 设备池管理、健康检查、环境变量/设备规格聚合
服务器层 pkg/resources/server.go gRPC Device Plugin 协议实现
CDI层 pkg/cdi/ CDI 规范文件生成与容器注解
工具层 pkg/utils/ sysfs/netlink/sriovnet/rdmamap/govdpa 封装
NAD集成 pkg/netdevice/nadutils.go Multus CNI 设备信息存储

二、25模块概览表

# 模块 关键类型 核心方法 依赖 行数(约)
1 cmd/sriovdp/main.go cliParams main, flagInit manager, signal 90
2 cmd/sriovdp/manager.go resourceManager newResourceManager, readConfig, discoverHostDevices, initServers, startAllServers, stopAllServers factory, types, utils, cdi 260
3 pkg/types/types.go ResourceConfig, DeviceSelectors×5, 接口×8 --- pluginapi 380
4 pkg/factory/factory.go resourceFactory GetDeviceProvider, GetDefaultInfoProvider, GetSelector, GetResourcePool, GetDeviceFilter, FilterBySelector, GetRdmaSpec, GetVdpaDevice types, netdevice, accelerator, auxnetdevice, infoprovider, resources 300
5 pkg/devices/api.go APIDevice GetDeviceSpecs, GetEnvVal, GetMounts, GetAPIDevice pluginapi, types 30
6 pkg/devices/host.go HostDeviceImpl NewHostDeviceImpl, GetDeviceSpecs, GetEnvVal, GetMounts, GetAPIDevice + Getters infoprovider, utils 180
7 pkg/devices/gen_pci.go GenericPciDevice NewGenericPciDevice, GetPciAddr, GetAcpiIndex devices 40
8 pkg/devices/gen_net.go GenericNetDevice NewGenericNetDevice, GetPfNetName, GetNetName, IsRdma + Getters devices, utils, factory 150
9 pkg/devices/rdma.go RdmaDeviceSpec NewRdmaDeviceSpec, IsRdma, GetRdmaDeviceSpec, GetRdmaDeviceName utils, pluginapi 120
10 pkg/devices/vfio.go VfioDevice NewVfioDevice utils 30
11 pkg/devices/vdpa.go VdpaDeviceImpl NewVdpaDeviceImpl, GetPath, GetType utils, types, govdpa 80
12 pkg/infoprovider/generic.go genericInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts types, pluginapi 40
13 pkg/infoprovider/vfio.go vfioInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts types, utils, pluginapi 60
14 pkg/infoprovider/uio.go uioInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts types, utils, pluginapi 50
15 pkg/infoprovider/rdma.go rdmaInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts types, pluginapi 70
16 pkg/infoprovider/vdpa.go vdpaInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts, isHealthy types, pluginapi 90
17 pkg/infoprovider/vhost.go vhostNetInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts, VhostNetDeviceExist types, pluginapi 70
18 pkg/infoprovider/extra.go extraInfoProvider GetName, GetDeviceSpecs, GetEnvVal, GetMounts types, pluginapi 50
19 pkg/netdevice/netDeviceProvider.go netDeviceProvider AddTargetDevices, GetDevices, GetFilteredDevices, ValidConfig types, factory, devices, utils, infoprovider 200
20 pkg/netdevice/pciNetDevice.go pciNetDevice NewPciNetDevice, GetDDPProfiles, GetVdpaDevice, GetPKey, GetEnvVal devices, utils 100
21 pkg/netdevice/netResourcePool.go netResourcePool NewNetResourcePool, GetDeviceSpecs, GetEnvs, Probe, StoreDeviceInfoFile types, nadutils, utils 180
22 pkg/netdevice/nadutils.go nadutils NewNadUtils, DiscoverSriovNetworks, StoreDeviceInfoFile, CleanSriovNetworks types, k8s/client-go 150
23 pkg/accelerator/accelDeviceProvider.go accelDeviceProvider AddTargetDevices, GetDevices, GetFilteredDevices types, factory, devices 120
24 pkg/accelerator/accelDevice.go accelDevice NewAccelDevice devices 20
25 pkg/accelerator/accelResourcePool.go accelResourcePool NewAccelResourcePool, GetCDIName types 60

续表:

# 模块 关键类型 核心方法 依赖 行数(约)
26 pkg/auxnetdevice/auxNetDeviceProvider.go auxNetDeviceProvider AddTargetDevices, GetDevices, GetFilteredDevices types, factory, devices, utils 160
27 pkg/auxnetdevice/auxNetDevice.go auxNetDevice NewAuxNetDevice, GetAuxType + Getters devices 80
28 pkg/auxnetdevice/auxNetResourcePool.go auxNetResourcePool NewAuxNetResourcePool, GetEnvs, Probe, StoreDeviceInfoFile, GetCDIName types 100
29 pkg/resources/server.go resourceServer NewResourceServer, Start, Stop, Init, ListAndWatch, Allocate, GetDevicePrefix types, cdi, pluginapi, grpc 320
30 pkg/resources/deviceSelectors.go 12个 Selector Filter (×12) types, utils 350
31 pkg/resources/pool_stub.go poolStub 通用ResourcePool方法 types 90
32 pkg/cdi/cdi.go impl CreateCDISpecForPool, CreateContainerAnnotations, CleanupSpecs types, cdi/specs 120
33 pkg/utils/utils.go --- 30+工具函数(sysfs操作) ghw, netlink 500
34 pkg/utils/netlink_provider.go NetlinkProvider GetLinkAttrs, GetDevLinkDeviceEswitchAttrs, GetIPv4RouteList, etc. vishvananda/netlink 130
35 pkg/utils/sriovnet_provider.go SriovnetProvider GetUplinkRepresentor, GetPfPciFromAux, GetNetDevicesFromAux, etc. sriovnet 50
36 pkg/utils/rdma_provider.go RdmaProvider GetRdmaDevicesForPcidev, GetRdmaDevicesForAuxdev, GetRdmaCharDevices rdmamap 30
37 pkg/utils/vdpa_provider.go VdpaProvider GetVdpaDeviceByPci govdpa 30

三、模块间调用关系矩阵

3.1 调用关系图

#mermaid-svg-3hGzRCAqhwXel3GA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3hGzRCAqhwXel3GA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3hGzRCAqhwXel3GA .error-icon{fill:#552222;}#mermaid-svg-3hGzRCAqhwXel3GA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3hGzRCAqhwXel3GA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3hGzRCAqhwXel3GA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3hGzRCAqhwXel3GA .marker.cross{stroke:#333333;}#mermaid-svg-3hGzRCAqhwXel3GA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3hGzRCAqhwXel3GA p{margin:0;}#mermaid-svg-3hGzRCAqhwXel3GA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3hGzRCAqhwXel3GA .cluster-label text{fill:#333;}#mermaid-svg-3hGzRCAqhwXel3GA .cluster-label span{color:#333;}#mermaid-svg-3hGzRCAqhwXel3GA .cluster-label span p{background-color:transparent;}#mermaid-svg-3hGzRCAqhwXel3GA .label text,#mermaid-svg-3hGzRCAqhwXel3GA span{fill:#333;color:#333;}#mermaid-svg-3hGzRCAqhwXel3GA .node rect,#mermaid-svg-3hGzRCAqhwXel3GA .node circle,#mermaid-svg-3hGzRCAqhwXel3GA .node ellipse,#mermaid-svg-3hGzRCAqhwXel3GA .node polygon,#mermaid-svg-3hGzRCAqhwXel3GA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3hGzRCAqhwXel3GA .rough-node .label text,#mermaid-svg-3hGzRCAqhwXel3GA .node .label text,#mermaid-svg-3hGzRCAqhwXel3GA .image-shape .label,#mermaid-svg-3hGzRCAqhwXel3GA .icon-shape .label{text-anchor:middle;}#mermaid-svg-3hGzRCAqhwXel3GA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3hGzRCAqhwXel3GA .rough-node .label,#mermaid-svg-3hGzRCAqhwXel3GA .node .label,#mermaid-svg-3hGzRCAqhwXel3GA .image-shape .label,#mermaid-svg-3hGzRCAqhwXel3GA .icon-shape .label{text-align:center;}#mermaid-svg-3hGzRCAqhwXel3GA .node.clickable{cursor:pointer;}#mermaid-svg-3hGzRCAqhwXel3GA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3hGzRCAqhwXel3GA .arrowheadPath{fill:#333333;}#mermaid-svg-3hGzRCAqhwXel3GA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3hGzRCAqhwXel3GA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3hGzRCAqhwXel3GA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3hGzRCAqhwXel3GA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3hGzRCAqhwXel3GA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3hGzRCAqhwXel3GA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3hGzRCAqhwXel3GA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3hGzRCAqhwXel3GA .cluster text{fill:#333;}#mermaid-svg-3hGzRCAqhwXel3GA .cluster span{color:#333;}#mermaid-svg-3hGzRCAqhwXel3GA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3hGzRCAqhwXel3GA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3hGzRCAqhwXel3GA rect.text{fill:none;stroke-width:0;}#mermaid-svg-3hGzRCAqhwXel3GA .icon-shape,#mermaid-svg-3hGzRCAqhwXel3GA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3hGzRCAqhwXel3GA .icon-shape p,#mermaid-svg-3hGzRCAqhwXel3GA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3hGzRCAqhwXel3GA .icon-shape .label rect,#mermaid-svg-3hGzRCAqhwXel3GA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3hGzRCAqhwXel3GA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3hGzRCAqhwXel3GA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3hGzRCAqhwXel3GA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建+编排
创建组件
发现设备
发现设备
发现设备
创建服务器
创建Provider
创建Provider
创建Provider
创建Selector
创建Pool
创建Pool
创建Pool
创建Server
创建InfoProvider
创建RdmaSpec
构建设备
装饰
装饰
组装
过滤
创建池
构建设备
装饰
组装
过滤
构建设备
组装
过滤
聚合
获取属性
获取属性
NAD集成
gRPC
CDI
持有
持有
持有
main.go
manager.go
factory.go
netDeviceProvider
accelDeviceProvider
auxNetDeviceProvider
server.go
deviceSelectors
netResourcePool
accelResourcePool
auxNetResourcePool
infoprovider/*
rdma.go
host.go
gen_net.go
gen_pci.go
pciNetDevice.go
accelDevice.go
auxNetDevice.go
utils.go
nadutils.go
Kubelet
cdi.go

3.2 核心调用路径

#mermaid-svg-TKGUvpRai8VqlIMO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TKGUvpRai8VqlIMO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TKGUvpRai8VqlIMO .error-icon{fill:#552222;}#mermaid-svg-TKGUvpRai8VqlIMO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TKGUvpRai8VqlIMO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TKGUvpRai8VqlIMO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TKGUvpRai8VqlIMO .marker.cross{stroke:#333333;}#mermaid-svg-TKGUvpRai8VqlIMO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TKGUvpRai8VqlIMO p{margin:0;}#mermaid-svg-TKGUvpRai8VqlIMO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TKGUvpRai8VqlIMO .cluster-label text{fill:#333;}#mermaid-svg-TKGUvpRai8VqlIMO .cluster-label span{color:#333;}#mermaid-svg-TKGUvpRai8VqlIMO .cluster-label span p{background-color:transparent;}#mermaid-svg-TKGUvpRai8VqlIMO .label text,#mermaid-svg-TKGUvpRai8VqlIMO span{fill:#333;color:#333;}#mermaid-svg-TKGUvpRai8VqlIMO .node rect,#mermaid-svg-TKGUvpRai8VqlIMO .node circle,#mermaid-svg-TKGUvpRai8VqlIMO .node ellipse,#mermaid-svg-TKGUvpRai8VqlIMO .node polygon,#mermaid-svg-TKGUvpRai8VqlIMO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TKGUvpRai8VqlIMO .rough-node .label text,#mermaid-svg-TKGUvpRai8VqlIMO .node .label text,#mermaid-svg-TKGUvpRai8VqlIMO .image-shape .label,#mermaid-svg-TKGUvpRai8VqlIMO .icon-shape .label{text-anchor:middle;}#mermaid-svg-TKGUvpRai8VqlIMO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TKGUvpRai8VqlIMO .rough-node .label,#mermaid-svg-TKGUvpRai8VqlIMO .node .label,#mermaid-svg-TKGUvpRai8VqlIMO .image-shape .label,#mermaid-svg-TKGUvpRai8VqlIMO .icon-shape .label{text-align:center;}#mermaid-svg-TKGUvpRai8VqlIMO .node.clickable{cursor:pointer;}#mermaid-svg-TKGUvpRai8VqlIMO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TKGUvpRai8VqlIMO .arrowheadPath{fill:#333333;}#mermaid-svg-TKGUvpRai8VqlIMO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TKGUvpRai8VqlIMO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TKGUvpRai8VqlIMO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TKGUvpRai8VqlIMO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TKGUvpRai8VqlIMO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TKGUvpRai8VqlIMO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TKGUvpRai8VqlIMO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TKGUvpRai8VqlIMO .cluster text{fill:#333;}#mermaid-svg-TKGUvpRai8VqlIMO .cluster span{color:#333;}#mermaid-svg-TKGUvpRai8VqlIMO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TKGUvpRai8VqlIMO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TKGUvpRai8VqlIMO rect.text{fill:none;stroke-width:0;}#mermaid-svg-TKGUvpRai8VqlIMO .icon-shape,#mermaid-svg-TKGUvpRai8VqlIMO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TKGUvpRai8VqlIMO .icon-shape p,#mermaid-svg-TKGUvpRai8VqlIMO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TKGUvpRai8VqlIMO .icon-shape .label rect,#mermaid-svg-TKGUvpRai8VqlIMO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TKGUvpRai8VqlIMO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TKGUvpRai8VqlIMO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TKGUvpRai8VqlIMO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 分配路径
KL.Allocate → rs.Allocate → pool.GetDeviceSpecs → pool.GetEnvs → pool.GetMounts → cdi.CreateContainerAnnotations → pool.StoreDeviceInfoFile
服务器启动路径
rs.Start → rs.Init → cdi.CreateCDISpecForPool → gRPC Server → register/watch → triggerUpdate goroutine
过滤路径
dp.GetFilteredDevices → factory.FilterBySelector → selector.Filter × N
设备构建路径
dp.GetDevices → factory.GetDefaultInfoProvider → NewHostDeviceImpl → NewGenericNetDevice → NewGenericPciDevice → NewPciNetDevice
设备发现路径
discoverHostDevices → dp.AddTargetDevices → ghw.PCI → utils.IsSriovPF → utils.HasDefaultRoute → utils.IsNetlinkStatusUp
启动路径
main → newResourceManager → readConfig → discoverHostDevices → initServers → startAllServers


四、三大核心流程详解

4.1 流程一:插件启动与设备注册

Kubelet CDI ResourceServer ResourcePool DeviceSelector DeviceProvider ResourceFactory ResourceManager main Kubelet CDI ResourceServer ResourcePool DeviceSelector DeviceProvider ResourceFactory ResourceManager main #mermaid-svg-OcUYIx0PiAf4XHMw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OcUYIx0PiAf4XHMw .error-icon{fill:#552222;}#mermaid-svg-OcUYIx0PiAf4XHMw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OcUYIx0PiAf4XHMw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OcUYIx0PiAf4XHMw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OcUYIx0PiAf4XHMw .marker.cross{stroke:#333333;}#mermaid-svg-OcUYIx0PiAf4XHMw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OcUYIx0PiAf4XHMw p{margin:0;}#mermaid-svg-OcUYIx0PiAf4XHMw .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-OcUYIx0PiAf4XHMw text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-OcUYIx0PiAf4XHMw .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-OcUYIx0PiAf4XHMw .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-OcUYIx0PiAf4XHMw #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-OcUYIx0PiAf4XHMw .sequenceNumber{fill:white;}#mermaid-svg-OcUYIx0PiAf4XHMw #sequencenumber{fill:#333;}#mermaid-svg-OcUYIx0PiAf4XHMw #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-OcUYIx0PiAf4XHMw .messageText{fill:#333;stroke:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-OcUYIx0PiAf4XHMw .labelText,#mermaid-svg-OcUYIx0PiAf4XHMw .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .loopText,#mermaid-svg-OcUYIx0PiAf4XHMw .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-OcUYIx0PiAf4XHMw .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-OcUYIx0PiAf4XHMw .noteText,#mermaid-svg-OcUYIx0PiAf4XHMw .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-OcUYIx0PiAf4XHMw .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-OcUYIx0PiAf4XHMw .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-OcUYIx0PiAf4XHMw .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-OcUYIx0PiAf4XHMw .actorPopupMenu{position:absolute;}#mermaid-svg-OcUYIx0PiAf4XHMw .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-OcUYIx0PiAf4XHMw .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-OcUYIx0PiAf4XHMw .actor-man circle,#mermaid-svg-OcUYIx0PiAf4XHMw line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-OcUYIx0PiAf4XHMw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 遍历PCI设备ClassID匹配+排除PF/默认路由 构建HostDevice组装InfoProvider链 loop每个ResourceConfig altPlugin Watch模式旧模式 loop每个ResourceServer newResourceManager(cliParams)NewResourceFactory(prefix, suffix, pluginWatch, useCdi)GetDeviceProvider(NetDeviceType) → NetDeviceProviderGetDeviceProvider(AcceleratorType) → AccelDeviceProviderGetDeviceProvider(AuxNetDeviceType) → AuxNetDeviceProviderreadConfig()os.ReadFile → json.Unmarshal → ResourceConfListGetDeviceFilter(config) → parseObjectOrSlice → SelectorObjsvalidConfigs()ValidResourceName + 资源名去重 + DeviceType验证 + DP.ValidConfigdiscoverHostDevices()AddTargetDevices(ghw.PCI.Devices, 0x02)initServers()GetDevices(config, selectorIndex)GetFilteredDevices(devices, config, selectorIndex)Filter × N (AND逻辑)excludeAllocatedDevicesGetResourcePool(config, filteredDevices)GetResourceServer(resourcePool)startAllServers()Start()Init() → CDI.CreateCDISpecForPool创建gRPC Server监听Unix SocketKubelet主动发现SocketRegister(版本,Socket,资源名)triggerUpdate goroutine (30s健康检查)

4.2 流程二:设备健康监控与状态更新

pkg/utils Kubelet updateCh ResourcePool ResourceServer 30s定时器 pkg/utils Kubelet updateCh ResourcePool ResourceServer 30s定时器 #mermaid-svg-MqPjSS49KH3Lm2Yb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MqPjSS49KH3Lm2Yb .error-icon{fill:#552222;}#mermaid-svg-MqPjSS49KH3Lm2Yb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MqPjSS49KH3Lm2Yb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MqPjSS49KH3Lm2Yb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MqPjSS49KH3Lm2Yb .marker.cross{stroke:#333333;}#mermaid-svg-MqPjSS49KH3Lm2Yb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MqPjSS49KH3Lm2Yb p{margin:0;}#mermaid-svg-MqPjSS49KH3Lm2Yb .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MqPjSS49KH3Lm2Yb text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MqPjSS49KH3Lm2Yb .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-MqPjSS49KH3Lm2Yb .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-MqPjSS49KH3Lm2Yb #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-MqPjSS49KH3Lm2Yb .sequenceNumber{fill:white;}#mermaid-svg-MqPjSS49KH3Lm2Yb #sequencenumber{fill:#333;}#mermaid-svg-MqPjSS49KH3Lm2Yb #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-MqPjSS49KH3Lm2Yb .messageText{fill:#333;stroke:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MqPjSS49KH3Lm2Yb .labelText,#mermaid-svg-MqPjSS49KH3Lm2Yb .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .loopText,#mermaid-svg-MqPjSS49KH3Lm2Yb .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-MqPjSS49KH3Lm2Yb .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-MqPjSS49KH3Lm2Yb .noteText,#mermaid-svg-MqPjSS49KH3Lm2Yb .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-MqPjSS49KH3Lm2Yb .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MqPjSS49KH3Lm2Yb .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MqPjSS49KH3Lm2Yb .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-MqPjSS49KH3Lm2Yb .actorPopupMenu{position:absolute;}#mermaid-svg-MqPjSS49KH3Lm2Yb .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-MqPjSS49KH3Lm2Yb .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-MqPjSS49KH3Lm2Yb .actor-man circle,#mermaid-svg-MqPjSS49KH3Lm2Yb line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-MqPjSS49KH3Lm2Yb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} altoperstate == "up"operstate != "up" loop每个设备 更新Node.Status.Allocatable调度器感知设备变化 loop每30秒 triggerUpdate tickProbe()IsNetlinkStatusUp(pciAddr)读取 /sys/bus/pci/devices/<addr>/net/*/operstatetrueapiDevicesid.Health = HealthyfalseapiDevicesid.Health = UnhealthyProbe完成updateCh <- GetDevices()ListAndWatch读取Send(ListAndWatchResponse{Devices})

健康状态影响:

设备状态 operstate Health值 调度行为
链路正常 "up" Healthy 可调度,新Pod可请求
链路异常 非"up" Unhealthy 不可调度,已绑定Pod不受影响
设备移除 无operstate文件 Unhealthy 不可调度

4.3 流程三:设备分配(Allocate)

Container Runtime NadUtils CDI InfoProvider链 HostDevice ResourcePool ResourceServer Kubelet API Server Scheduler Container Runtime NadUtils CDI InfoProvider链 HostDevice ResourcePool ResourceServer Kubelet API Server Scheduler #mermaid-svg-R1GGWMLrgfHrYqBl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-R1GGWMLrgfHrYqBl .error-icon{fill:#552222;}#mermaid-svg-R1GGWMLrgfHrYqBl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-R1GGWMLrgfHrYqBl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-R1GGWMLrgfHrYqBl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-R1GGWMLrgfHrYqBl .marker.cross{stroke:#333333;}#mermaid-svg-R1GGWMLrgfHrYqBl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-R1GGWMLrgfHrYqBl p{margin:0;}#mermaid-svg-R1GGWMLrgfHrYqBl .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-R1GGWMLrgfHrYqBl text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-R1GGWMLrgfHrYqBl .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-R1GGWMLrgfHrYqBl .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-R1GGWMLrgfHrYqBl #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-R1GGWMLrgfHrYqBl .sequenceNumber{fill:white;}#mermaid-svg-R1GGWMLrgfHrYqBl #sequencenumber{fill:#333;}#mermaid-svg-R1GGWMLrgfHrYqBl #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-R1GGWMLrgfHrYqBl .messageText{fill:#333;stroke:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-R1GGWMLrgfHrYqBl .labelText,#mermaid-svg-R1GGWMLrgfHrYqBl .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .loopText,#mermaid-svg-R1GGWMLrgfHrYqBl .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-R1GGWMLrgfHrYqBl .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-R1GGWMLrgfHrYqBl .noteText,#mermaid-svg-R1GGWMLrgfHrYqBl .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-R1GGWMLrgfHrYqBl .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-R1GGWMLrgfHrYqBl .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-R1GGWMLrgfHrYqBl .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-R1GGWMLrgfHrYqBl .actorPopupMenu{position:absolute;}#mermaid-svg-R1GGWMLrgfHrYqBl .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-R1GGWMLrgfHrYqBl .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-R1GGWMLrgfHrYqBl .actor-man circle,#mermaid-svg-R1GGWMLrgfHrYqBl line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-R1GGWMLrgfHrYqBl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pod调度阶段 容器创建阶段 loop每个InfoProvider loop每个deviceID loop每个InfoProvider loop每个deviceID altuseCdi模式 loop每个ContainerRequest 检查Node Allocatable ≥ Pod请求绑定Pod到NodeAllocate(ContainerRequests{DevicesIDs})GetDeviceSpecs(deviceIDs)GetDeviceSpecs()GetDeviceSpecs()DeviceSpec切片合并DeviceSpecs全部DeviceSpecsGetEnvs(prefix, deviceIDs)GetEnvVal()GetEnvVal()AdditionalInfo合并EnvVal格式化: PCIDEVICE_<PREFIX><NAME><KEY>全部EnvsGetMounts(deviceIDs)Mounts列表CreateContainerAnnotations(deviceIDs, prefix, kind)AnnotationKey: cdi.k8s.io/<prefix><kind>QualifiedName: <prefix>/<kind>/<deviceID>AnnotationsStoreDeviceInfoFile(prefix, deviceIDs)StoreDeviceInfoFile(dev, prefix, name)写入 /var/run/k8s.cni.cncf.io/devinfo/dpd/<prefix><name>/<id>AllocateResponse{ContainerResponses}CreateContainer(设备注入信息)创建设备文件 / 挂载 / 设置环境变量


五、输入输出分析

5.1 插件全局输入输出

输入 来源 格式 处理模块
配置文件 /etc/pcidp/config.json JSON manager.readConfig
CLI 参数 命令行 string/bool main.flagInit
PCI 设备列表 /sys/bus/pci/devices sysfs DeviceProvider.AddTargetDevices
辅助设备列表 /sys/bus/auxiliary/devices sysfs auxNetDeviceProvider.AddTargetDevices
设备驱动 /sys/bus/pci/.../driver sysfs符号链接 utils.GetDriverName
NUMA 节点 /sys/bus/pci/.../numa_node sysfs utils.GetDevNode
网络接口名 /sys/bus/pci/.../net/ sysfs utils.GetNetNames
链路状态 /sys/bus/pci/.../net/*/operstate sysfs utils.IsNetlinkStatusUp
链路属性 netlink netlink NetlinkProvider.GetLinkAttrs
devlink 属性 devlink netlink NetlinkProvider.GetDevLinkDeviceEswitchAttrs
RDMA 设备 rdmamap 库查询 RdmaProvider.GetRdmaDevicesForPcidev
vDPA 设备 govdpa 库查询 VdpaProvider.GetVdpaDeviceByPci
IB PKey sriovnet 库查询 SriovnetProvider.GetDefaultPKeyFromPci
DDP 配置 devlink info netlink utils.DevlinkGetDDPProfiles
信号 SIGHUP/SIGINT/SIGTERM/SIGQUIT OS main.sigCh
输出 目标 格式 生成模块
设备注册 Kubelet gRPC Register resourceServer.register
设备列表 Kubelet gRPC ListAndWatchResponse resourceServer.ListAndWatch
设备分配 Kubelet gRPC AllocateResponse resourceServer.Allocate
CDI Spec /etc/cdi/sriov-dp-*.json JSON CDI.CreateCDISpecForPool
设备信息文件 /var/run/k8s.cni.cncf.io/devinfo/dpd/ JSON NadUtils.StoreDeviceInfoFile
Unix Socket /var/lib/kubelet/plugins_registry/ Unix域Socket resourceServer.Start
日志 stderr glog格式 全局

5.2 配置文件输入格式详解

json 复制代码
{
  "resourceList": [
    {
      "resourcePrefix": "intel.com",
      "resourceName": "sriov_net",
      "deviceType": "netDevice",
      "excludeTopology": false,
      "selectors": {
        "vendors": ["8086"],
        "devices": ["154c"],
        "drivers": ["vfio-pci"],
        "pciAddresses": ["0000:19:02.1"],
        "pfNames": ["enp2s0f0#0-3"],
        "rootDevices": ["0000:02:00.0"],
        "linkTypes": ["ether"],
        "isRdma": true,
        "vdpaType": "vhost",
        "needVhostNet": true,
        "ddpProfiles": ["GTP*"],
        "pKeys": ["0x8001"],
        "acpiIndexes": ["1"]
      },
      "additionalInfo": {
        "*": {"custom-key": "global-value"},
        "0000:19:02.1": {"custom-key": "device-specific-value"}
      }
    },
    {
      "resourceName": "sriov_accel",
      "deviceType": "accelerator",
      "selectors": {
        "vendors": ["8086"],
        "devices": ["0b30"],
        "drivers": ["vfio-pci"],
        "pciAddresses": ["0000:af:00.0"]
      }
    },
    {
      "resourceName": "sriov_sf",
      "deviceType": "auxNetDevice",
      "selectors": {
        "vendors": ["15b3"],
        "drivers": ["mlx5_core"],
        "auxTypes": ["sf"],
        "linkTypes": ["ether"],
        "isRdma": true,
        "needVhostNet": true
      }
    }
  ]
}

5.3 AllocateResponse 输出格式详解

json 复制代码
{
  "containerResponses": [
    {
      "envs": {
        "PCIDEVICE_INTEL_COM_SRIOV_NET_deviceID": "0000:19:02.1",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_mount": "/dev/vfio/vfio",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_dev-mount": "/dev/vfio/12",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_uverbs": "/dev/infiniband/uverbs0",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_rdma_dev": "mlx5_0",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_pfNetName": "enp2s0f0",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_netName": "enp2s0f0v1",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_linkType": "ether",
        "PCIDEVICE_INTEL_COM_SRIOV_NET_linkSpeed": "10000"
      },
      "mounts": [],
      "devices": [
        {
          "hostPath": "/dev/vfio/vfio",
          "containerPath": "/dev/vfio/vfio",
          "permissions": "rw"
        },
        {
          "hostPath": "/dev/vfio/12",
          "containerPath": "/dev/vfio/12",
          "permissions": "rw"
        },
        {
          "hostPath": "/dev/infiniband/uverbs0",
          "containerPath": "/dev/infiniband/uverbs0",
          "permissions": "rw"
        },
        {
          "hostPath": "/dev/infiniband/rdma_cm",
          "containerPath": "/dev/infiniband/rdma_cm",
          "permissions": "rw"
        }
      ],
      "annotations": {
        "cdi.k8s.io/intel_com_net": "intel.com/net/0000:19:02.1"
      }
    }
  ]
}

六、关键设计决策分析

6.1 设计决策一:工厂模式集中创建

决策 :所有组件(DeviceProvider、ResourcePool、ResourceServer、DeviceInfoProvider、DeviceSelector)的创建都通过 resourceFactory 集中管理。

优点

  1. 依赖注入:调用者不需要知道具体实现类,只需依赖接口
  2. 可测试性:工厂方法可被替换为 Mock 工厂
  3. 一致性:所有组件的创建遵循相同的参数传递模式
  4. 解耦:模块之间通过接口和工厂交互,不直接依赖具体实现

缺点

  1. 工厂类承担了过多职责(违反 SRP)
  2. 工厂方法数量多(~12个),代码量较大

#mermaid-svg-v4VVZZHJ4qoGqmpk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-v4VVZZHJ4qoGqmpk .error-icon{fill:#552222;}#mermaid-svg-v4VVZZHJ4qoGqmpk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-v4VVZZHJ4qoGqmpk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .marker.cross{stroke:#333333;}#mermaid-svg-v4VVZZHJ4qoGqmpk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-v4VVZZHJ4qoGqmpk p{margin:0;}#mermaid-svg-v4VVZZHJ4qoGqmpk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster-label text{fill:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster-label span{color:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster-label span p{background-color:transparent;}#mermaid-svg-v4VVZZHJ4qoGqmpk .label text,#mermaid-svg-v4VVZZHJ4qoGqmpk span{fill:#333;color:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .node rect,#mermaid-svg-v4VVZZHJ4qoGqmpk .node circle,#mermaid-svg-v4VVZZHJ4qoGqmpk .node ellipse,#mermaid-svg-v4VVZZHJ4qoGqmpk .node polygon,#mermaid-svg-v4VVZZHJ4qoGqmpk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .rough-node .label text,#mermaid-svg-v4VVZZHJ4qoGqmpk .node .label text,#mermaid-svg-v4VVZZHJ4qoGqmpk .image-shape .label,#mermaid-svg-v4VVZZHJ4qoGqmpk .icon-shape .label{text-anchor:middle;}#mermaid-svg-v4VVZZHJ4qoGqmpk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .rough-node .label,#mermaid-svg-v4VVZZHJ4qoGqmpk .node .label,#mermaid-svg-v4VVZZHJ4qoGqmpk .image-shape .label,#mermaid-svg-v4VVZZHJ4qoGqmpk .icon-shape .label{text-align:center;}#mermaid-svg-v4VVZZHJ4qoGqmpk .node.clickable{cursor:pointer;}#mermaid-svg-v4VVZZHJ4qoGqmpk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .arrowheadPath{fill:#333333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v4VVZZHJ4qoGqmpk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-v4VVZZHJ4qoGqmpk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v4VVZZHJ4qoGqmpk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster text{fill:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk .cluster span{color:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-v4VVZZHJ4qoGqmpk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-v4VVZZHJ4qoGqmpk rect.text{fill:none;stroke-width:0;}#mermaid-svg-v4VVZZHJ4qoGqmpk .icon-shape,#mermaid-svg-v4VVZZHJ4qoGqmpk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-v4VVZZHJ4qoGqmpk .icon-shape p,#mermaid-svg-v4VVZZHJ4qoGqmpk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-v4VVZZHJ4qoGqmpk .icon-shape .label rect,#mermaid-svg-v4VVZZHJ4qoGqmpk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-v4VVZZHJ4qoGqmpk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-v4VVZZHJ4qoGqmpk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-v4VVZZHJ4qoGqmpk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 工厂模式
GetDeviceProvider
GetDeviceProvider
GetDeviceProvider
GetDefaultInfoProvider
GetSelector
GetResourcePool
GetResourceServer
GetRdmaSpec
GetVdpaDevice
GetDeviceFilter
GetNadUtils
resourceFactory
netDeviceProvider
accelDeviceProvider
auxNetDeviceProvider
DeviceInfoProvider链
12个Selector
3种ResourcePool
resourceServer
RdmaDeviceSpec
VdpaDeviceImpl
SelectorObjs
nadutils

6.2 设计决策二:装饰器模式构建设备

决策:使用 HostDeviceImpl → GenericPciDevice → GenericNetDevice → PciNetDevice 的装饰链构建设备对象。

优点

  1. 渐进式增强:每层只添加自己关注的属性,职责清晰
  2. 接口隔离:不同使用者只需要关心自己需要的接口层
  3. 可组合性:AccelDevice 只需要 GenericPciDevice,不需要 GenericNetDevice

实现方式
#mermaid-svg-cPZVLR79HOQ97Eoe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cPZVLR79HOQ97Eoe .error-icon{fill:#552222;}#mermaid-svg-cPZVLR79HOQ97Eoe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cPZVLR79HOQ97Eoe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cPZVLR79HOQ97Eoe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cPZVLR79HOQ97Eoe .marker.cross{stroke:#333333;}#mermaid-svg-cPZVLR79HOQ97Eoe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cPZVLR79HOQ97Eoe p{margin:0;}#mermaid-svg-cPZVLR79HOQ97Eoe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster-label text{fill:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster-label span{color:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster-label span p{background-color:transparent;}#mermaid-svg-cPZVLR79HOQ97Eoe .label text,#mermaid-svg-cPZVLR79HOQ97Eoe span{fill:#333;color:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe .node rect,#mermaid-svg-cPZVLR79HOQ97Eoe .node circle,#mermaid-svg-cPZVLR79HOQ97Eoe .node ellipse,#mermaid-svg-cPZVLR79HOQ97Eoe .node polygon,#mermaid-svg-cPZVLR79HOQ97Eoe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cPZVLR79HOQ97Eoe .rough-node .label text,#mermaid-svg-cPZVLR79HOQ97Eoe .node .label text,#mermaid-svg-cPZVLR79HOQ97Eoe .image-shape .label,#mermaid-svg-cPZVLR79HOQ97Eoe .icon-shape .label{text-anchor:middle;}#mermaid-svg-cPZVLR79HOQ97Eoe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cPZVLR79HOQ97Eoe .rough-node .label,#mermaid-svg-cPZVLR79HOQ97Eoe .node .label,#mermaid-svg-cPZVLR79HOQ97Eoe .image-shape .label,#mermaid-svg-cPZVLR79HOQ97Eoe .icon-shape .label{text-align:center;}#mermaid-svg-cPZVLR79HOQ97Eoe .node.clickable{cursor:pointer;}#mermaid-svg-cPZVLR79HOQ97Eoe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cPZVLR79HOQ97Eoe .arrowheadPath{fill:#333333;}#mermaid-svg-cPZVLR79HOQ97Eoe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cPZVLR79HOQ97Eoe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cPZVLR79HOQ97Eoe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cPZVLR79HOQ97Eoe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cPZVLR79HOQ97Eoe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cPZVLR79HOQ97Eoe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster text{fill:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe .cluster span{color:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cPZVLR79HOQ97Eoe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cPZVLR79HOQ97Eoe rect.text{fill:none;stroke-width:0;}#mermaid-svg-cPZVLR79HOQ97Eoe .icon-shape,#mermaid-svg-cPZVLR79HOQ97Eoe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cPZVLR79HOQ97Eoe .icon-shape p,#mermaid-svg-cPZVLR79HOQ97Eoe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cPZVLR79HOQ97Eoe .icon-shape .label rect,#mermaid-svg-cPZVLR79HOQ97Eoe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cPZVLR79HOQ97Eoe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cPZVLR79HOQ97Eoe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cPZVLR79HOQ97Eoe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 嵌入
嵌入
嵌入
嵌入
嵌入
嵌入
HostDeviceImpl

PCI基础+InfoProvider组合
GenericPciDevice

+pciAddr, acpiIndex
GenericNetDevice

+pfName, netName, linkType, rdmaSpec
PciNetDevice

+ddpProfiles, pKey, vdpaDev
AccelDevice

无额外属性
AuxNetDevice

+auxType, sfIndex

6.3 设计决策三:组合模式的 InfoProvider 链

决策:设备的信息(DeviceSpecs、EnvVal、Mounts)通过遍历 InfoProvider 链聚合生成,而非硬编码在设备类中。

优点

  1. 开放-封闭原则:新增设备类型只需添加新 InfoProvider,无需修改设备基类
  2. 按需组合:根据配置动态决定注入哪些设备文件
  3. 细粒度控制:每个 InfoProvider 独立测试

组合示例

设备场景 InfoProvider 链 注入的设备文件
VFIO 直通 Generic → VFIO /dev/vfio/vfio + /dev/vfio/N
VFIO + RDMA Generic → VFIO → RDMA /dev/vfio/* + /dev/infiniband/*
内核驱动 + RDMA Generic → RDMA /dev/infiniband/*
UIO 直通 Generic → UIO /dev/uioX
vhost-vDPA Generic → VFIO → VDPA /dev/vfio/* + /dev/vhost-vdpa-N
virtio-vDPA Generic → VDPA (无设备文件)
vhost-net 共享 Generic → VHOST /dev/vhost-net + /dev/net/tun
辅助设备+RDMA Generic → RDMA → EXTRA /dev/infiniband/* + 自定义env

6.4 设计决策四:策略模式的设备选择器

决策:每个选择字段(vendors, drivers, pfNames 等)映射为一个独立的 DeviceSelector 实现,通过 AND 逻辑组合过滤。

优点

  1. 策略模式:每个选择器是独立的过滤策略,可自由组合
  2. 可扩展性:新增选择字段只需新增 Selector 类 + Factory 方法
  3. 一致性:所有选择器遵循相同的 Filter(devices) → filteredDevices 接口

特殊设计

  • IsRdmaVdpaType 通过 DriverSelector 映射,避免了额外的选择器类型
  • pfNames 支持 #VF范围 语法,如 enp2s0f0#1-3
  • ddpProfiles 支持 Glob 模式匹配

渲染错误: Mermaid 渲染失败: Parse error on line 12: ...DRV_ADDdrivers += "rdma" VDPA_ -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'STR'

6.5 设计决策五:Provider 抽象隔离设备类型差异

决策:通过 DeviceProvider 接口将三种设备类型(NetDevice、Accelerator、AuxNetDevice)的发现和构建逻辑隔离在独立子包中。

优点

  1. 隔离变化:新增设备类型只需新增 Provider 子包
  2. 代码清晰:每种设备类型的逻辑自包含
  3. 独立测试:每种 Provider 可独立单元测试

差异矩阵:

能力 NetDeviceProvider AccelDeviceProvider AuxNetDeviceProvider
扫描源 /sys/bus/pci /sys/bus/pci /sys/bus/auxiliary
Class过滤 0x02 0x12 auxTypes字段
PF排除 N/A
默认路由排除
RDMA支持
vDPA支持
NAD集成
NUMA拓扑
DDP配置
IB PKey

6.6 设计决策六:工具层 Provider 接口封装外部库

决策:对外部库(netlink、sriovnet、rdmamap、govdpa)的调用通过 Provider 接口封装,支持运行时替换(用于测试)。

go 复制代码
// 全局变量 + Setter 注入
var netlinkProvider NetlinkProvider = &defaultNetlinkProvider{}
func SetNetlinkProviderInst(inst NetlinkProvider) { netlinkProvider = inst }
func GetNetlinkProvider() NetlinkProvider { return netlinkProvider }

优点

  1. 可测试性:单元测试可注入 Mock Provider
  2. 解耦:业务逻辑不直接依赖外部库实现
  3. 灵活性:可替换为不同实现

Provider 接口一览:

Provider 封装库 核心方法
NetlinkProvider vishvananda/netlink GetLinkAttrs, GetDevLinkDeviceEswitchAttrs, GetIPv4RouteList, GetDevlinkGetDeviceInfoByNameAsMap, HasRdmaParam
SriovnetProvider k8snetworkplumbingwg/sriovnet GetUplinkRepresentor, GetUplinkRepresentorFromAux, GetPfPciFromAux, GetSfIndexByAuxDev, GetNetDevicesFromAux, GetAuxNetDevicesFromPci, GetDefaultPKeyFromPci
RdmaProvider Mellanox/rdmamap GetRdmaDevicesForPcidev, GetRdmaDevicesForAuxdev, GetRdmaCharDevices
VdpaProvider k8snetworkplumbingwg/govdpa GetVdpaDeviceByPci

七、核心数据流图

7.1 配置驱动数据流

渲染错误: Mermaid 渲染失败: Lexical error on line 3. Unrecognized text. ...tc/pcidp/config.json] end subgr -----------------------^

7.2 运行时数据流

渲染错误: Mermaid 渲染失败: Lexical error on line 9. Unrecognized text. ...us/pci/.../operstate] SYSFS --> -----------------------^

7.3 设备信息在容器内的注入

渲染错误: Mermaid 渲染失败: Lexical error on line 3. Unrecognized text. ... DEV1/dev/vfio/vfio VF -->|Dev -----------------------^


八、四种设备注入模式

8.1 模式对比

模式 驱动 设备文件 使用场景
VFIO直通 vfio-pci /dev/vfio/vfio + /dev/vfio/N DPDK 应用,用户态驱动
UIO直通 uio/igb_uio /dev/uioX 旧版 DPDK 应用
内核驱动 i40evf/mlx5_core (无特殊设备文件) 普通网络应用,内核协议栈
RDMA 内核RDMA /dev/infiniband/* RDMA/RoCE 应用
vDPA vhost_vdpa/virtio_vdpa /dev/vhost-vdpa-N 或无 vDPA 硬件卸载
vhost-net 共享 /dev/vhost-net + /dev/net/tun OVS-DPDK vhost-user

8.2 VFIO 直通模式数据流

VFIO InfoProvider ResourcePool ResourceServer Kubelet Container Runtime Pod (DPDK App) VFIO InfoProvider ResourcePool ResourceServer Kubelet Container Runtime Pod (DPDK App) #mermaid-svg-qyBSuglDIjD3inur{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qyBSuglDIjD3inur .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qyBSuglDIjD3inur .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qyBSuglDIjD3inur .error-icon{fill:#552222;}#mermaid-svg-qyBSuglDIjD3inur .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qyBSuglDIjD3inur .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qyBSuglDIjD3inur .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qyBSuglDIjD3inur .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qyBSuglDIjD3inur .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qyBSuglDIjD3inur .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qyBSuglDIjD3inur .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qyBSuglDIjD3inur .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qyBSuglDIjD3inur .marker.cross{stroke:#333333;}#mermaid-svg-qyBSuglDIjD3inur svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qyBSuglDIjD3inur p{margin:0;}#mermaid-svg-qyBSuglDIjD3inur .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-qyBSuglDIjD3inur text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-qyBSuglDIjD3inur .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-qyBSuglDIjD3inur .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-qyBSuglDIjD3inur .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-qyBSuglDIjD3inur .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-qyBSuglDIjD3inur #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-qyBSuglDIjD3inur .sequenceNumber{fill:white;}#mermaid-svg-qyBSuglDIjD3inur #sequencenumber{fill:#333;}#mermaid-svg-qyBSuglDIjD3inur #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-qyBSuglDIjD3inur .messageText{fill:#333;stroke:none;}#mermaid-svg-qyBSuglDIjD3inur .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-qyBSuglDIjD3inur .labelText,#mermaid-svg-qyBSuglDIjD3inur .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-qyBSuglDIjD3inur .loopText,#mermaid-svg-qyBSuglDIjD3inur .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-qyBSuglDIjD3inur .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-qyBSuglDIjD3inur .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-qyBSuglDIjD3inur .noteText,#mermaid-svg-qyBSuglDIjD3inur .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-qyBSuglDIjD3inur .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-qyBSuglDIjD3inur .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-qyBSuglDIjD3inur .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-qyBSuglDIjD3inur .actorPopupMenu{position:absolute;}#mermaid-svg-qyBSuglDIjD3inur .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-qyBSuglDIjD3inur .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-qyBSuglDIjD3inur .actor-man circle,#mermaid-svg-qyBSuglDIjD3inur line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-qyBSuglDIjD3inur :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} DPDK应用通过 /dev/vfio/12直接访问VF硬件 Allocate("0000:19:02.1")GetDeviceSpecs("0000:19:02.1")GetDeviceSpecs()/dev/vfio/vfio (IOMMU框架)/dev/vfio/12 (VF的IOMMU组)DeviceSpec{vfio}, DeviceSpec{vfio/12}DeviceSpecsGetEnvs("intel.com", "0000:19:02.1"){"PCIDEVICE_..._mount": "/dev/vfio/vfio", ...}AllocateResponseCreateContainer(specs + envs)容器启动,设备文件可用

8.3 RDMA 模式数据流

RdmaDeviceSpec RDMA InfoProvider ResourcePool ResourceServer Kubelet Container Runtime Pod (RDMA App) RdmaDeviceSpec RDMA InfoProvider ResourcePool ResourceServer Kubelet Container Runtime Pod (RDMA App) #mermaid-svg-gkYlLCY3M6KC4fgi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gkYlLCY3M6KC4fgi .error-icon{fill:#552222;}#mermaid-svg-gkYlLCY3M6KC4fgi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gkYlLCY3M6KC4fgi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gkYlLCY3M6KC4fgi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gkYlLCY3M6KC4fgi .marker.cross{stroke:#333333;}#mermaid-svg-gkYlLCY3M6KC4fgi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gkYlLCY3M6KC4fgi p{margin:0;}#mermaid-svg-gkYlLCY3M6KC4fgi .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gkYlLCY3M6KC4fgi text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gkYlLCY3M6KC4fgi .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-gkYlLCY3M6KC4fgi .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-gkYlLCY3M6KC4fgi #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-gkYlLCY3M6KC4fgi .sequenceNumber{fill:white;}#mermaid-svg-gkYlLCY3M6KC4fgi #sequencenumber{fill:#333;}#mermaid-svg-gkYlLCY3M6KC4fgi #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-gkYlLCY3M6KC4fgi .messageText{fill:#333;stroke:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gkYlLCY3M6KC4fgi .labelText,#mermaid-svg-gkYlLCY3M6KC4fgi .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .loopText,#mermaid-svg-gkYlLCY3M6KC4fgi .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-gkYlLCY3M6KC4fgi .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-gkYlLCY3M6KC4fgi .noteText,#mermaid-svg-gkYlLCY3M6KC4fgi .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-gkYlLCY3M6KC4fgi .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gkYlLCY3M6KC4fgi .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gkYlLCY3M6KC4fgi .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-gkYlLCY3M6KC4fgi .actorPopupMenu{position:absolute;}#mermaid-svg-gkYlLCY3M6KC4fgi .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-gkYlLCY3M6KC4fgi .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-gkYlLCY3M6KC4fgi .actor-man circle,#mermaid-svg-gkYlLCY3M6KC4fgi line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-gkYlLCY3M6KC4fgi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} rdmamap查询PCI → mlx5_0mlx5_0 → char devices RDMA应用使用 uverbs0进行用户态RDMA操作 Allocate("0000:19:02.1")GetDeviceSpecs("0000:19:02.1")GetDeviceSpecs()GetRdmaDeviceSpec()/dev/infiniband/uverbs0, /dev/infiniband/umad0, /dev/infiniband/issm0, /dev/infiniband/rdma_cmDeviceSpecsGetEnvVal()GetRdmaDeviceSpec() → 解析路径GetRdmaDeviceName() → "mlx5_0"{"uverbs": "/dev/infiniband/uverbs0", "rdma_dev": "mlx5_0", ...}DeviceSpecs + EnvsAllocateResponseCreateContainerRDMA设备文件可用


九、SR-IOV 插件在 Kubernetes 生态中的位置

9.1 与相关组件的交互

#mermaid-svg-GiTPQW576yDPZSC4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GiTPQW576yDPZSC4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GiTPQW576yDPZSC4 .error-icon{fill:#552222;}#mermaid-svg-GiTPQW576yDPZSC4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GiTPQW576yDPZSC4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GiTPQW576yDPZSC4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GiTPQW576yDPZSC4 .marker.cross{stroke:#333333;}#mermaid-svg-GiTPQW576yDPZSC4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GiTPQW576yDPZSC4 p{margin:0;}#mermaid-svg-GiTPQW576yDPZSC4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GiTPQW576yDPZSC4 .cluster-label text{fill:#333;}#mermaid-svg-GiTPQW576yDPZSC4 .cluster-label span{color:#333;}#mermaid-svg-GiTPQW576yDPZSC4 .cluster-label span p{background-color:transparent;}#mermaid-svg-GiTPQW576yDPZSC4 .label text,#mermaid-svg-GiTPQW576yDPZSC4 span{fill:#333;color:#333;}#mermaid-svg-GiTPQW576yDPZSC4 .node rect,#mermaid-svg-GiTPQW576yDPZSC4 .node circle,#mermaid-svg-GiTPQW576yDPZSC4 .node ellipse,#mermaid-svg-GiTPQW576yDPZSC4 .node polygon,#mermaid-svg-GiTPQW576yDPZSC4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GiTPQW576yDPZSC4 .rough-node .label text,#mermaid-svg-GiTPQW576yDPZSC4 .node .label text,#mermaid-svg-GiTPQW576yDPZSC4 .image-shape .label,#mermaid-svg-GiTPQW576yDPZSC4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-GiTPQW576yDPZSC4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GiTPQW576yDPZSC4 .rough-node .label,#mermaid-svg-GiTPQW576yDPZSC4 .node .label,#mermaid-svg-GiTPQW576yDPZSC4 .image-shape .label,#mermaid-svg-GiTPQW576yDPZSC4 .icon-shape .label{text-align:center;}#mermaid-svg-GiTPQW576yDPZSC4 .node.clickable{cursor:pointer;}#mermaid-svg-GiTPQW576yDPZSC4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GiTPQW576yDPZSC4 .arrowheadPath{fill:#333333;}#mermaid-svg-GiTPQW576yDPZSC4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GiTPQW576yDPZSC4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GiTPQW576yDPZSC4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GiTPQW576yDPZSC4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GiTPQW576yDPZSC4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GiTPQW576yDPZSC4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GiTPQW576yDPZSC4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GiTPQW576yDPZSC4 .cluster text{fill:#333;}#mermaid-svg-GiTPQW576yDPZSC4 .cluster span{color:#333;}#mermaid-svg-GiTPQW576yDPZSC4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GiTPQW576yDPZSC4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GiTPQW576yDPZSC4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-GiTPQW576yDPZSC4 .icon-shape,#mermaid-svg-GiTPQW576yDPZSC4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GiTPQW576yDPZSC4 .icon-shape p,#mermaid-svg-GiTPQW576yDPZSC4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GiTPQW576yDPZSC4 .icon-shape .label rect,#mermaid-svg-GiTPQW576yDPZSC4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GiTPQW576yDPZSC4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GiTPQW576yDPZSC4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GiTPQW576yDPZSC4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Pod
主机
Kubernetes集群
注册扩展资源
更新容量
调度决策
Allocate
创建容器
读取设备信息
调用
配置VF
配置VF
扫描
发现
发现
发现
管理
管理
管理
注入设备
注入设备
注入设备
API Server
Scheduler
Kubelet
Container Runtime
Multus CNI
sriov-cni
sriov-device-plugin

本项目
Network Policy
SR-IOV PF
VF 0
VF 1
VF N
sys/bus/pci
DPDK App
RDMA App
Kernel Net App

9.2 完整的 SR-IOV 工作流

#mermaid-svg-nyEA520ABdjEb2JC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nyEA520ABdjEb2JC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nyEA520ABdjEb2JC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nyEA520ABdjEb2JC .error-icon{fill:#552222;}#mermaid-svg-nyEA520ABdjEb2JC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nyEA520ABdjEb2JC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nyEA520ABdjEb2JC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nyEA520ABdjEb2JC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nyEA520ABdjEb2JC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nyEA520ABdjEb2JC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nyEA520ABdjEb2JC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nyEA520ABdjEb2JC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nyEA520ABdjEb2JC .marker.cross{stroke:#333333;}#mermaid-svg-nyEA520ABdjEb2JC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nyEA520ABdjEb2JC p{margin:0;}#mermaid-svg-nyEA520ABdjEb2JC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nyEA520ABdjEb2JC .cluster-label text{fill:#333;}#mermaid-svg-nyEA520ABdjEb2JC .cluster-label span{color:#333;}#mermaid-svg-nyEA520ABdjEb2JC .cluster-label span p{background-color:transparent;}#mermaid-svg-nyEA520ABdjEb2JC .label text,#mermaid-svg-nyEA520ABdjEb2JC span{fill:#333;color:#333;}#mermaid-svg-nyEA520ABdjEb2JC .node rect,#mermaid-svg-nyEA520ABdjEb2JC .node circle,#mermaid-svg-nyEA520ABdjEb2JC .node ellipse,#mermaid-svg-nyEA520ABdjEb2JC .node polygon,#mermaid-svg-nyEA520ABdjEb2JC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nyEA520ABdjEb2JC .rough-node .label text,#mermaid-svg-nyEA520ABdjEb2JC .node .label text,#mermaid-svg-nyEA520ABdjEb2JC .image-shape .label,#mermaid-svg-nyEA520ABdjEb2JC .icon-shape .label{text-anchor:middle;}#mermaid-svg-nyEA520ABdjEb2JC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nyEA520ABdjEb2JC .rough-node .label,#mermaid-svg-nyEA520ABdjEb2JC .node .label,#mermaid-svg-nyEA520ABdjEb2JC .image-shape .label,#mermaid-svg-nyEA520ABdjEb2JC .icon-shape .label{text-align:center;}#mermaid-svg-nyEA520ABdjEb2JC .node.clickable{cursor:pointer;}#mermaid-svg-nyEA520ABdjEb2JC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nyEA520ABdjEb2JC .arrowheadPath{fill:#333333;}#mermaid-svg-nyEA520ABdjEb2JC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nyEA520ABdjEb2JC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nyEA520ABdjEb2JC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nyEA520ABdjEb2JC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nyEA520ABdjEb2JC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nyEA520ABdjEb2JC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nyEA520ABdjEb2JC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nyEA520ABdjEb2JC .cluster text{fill:#333;}#mermaid-svg-nyEA520ABdjEb2JC .cluster span{color:#333;}#mermaid-svg-nyEA520ABdjEb2JC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nyEA520ABdjEb2JC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nyEA520ABdjEb2JC rect.text{fill:none;stroke-width:0;}#mermaid-svg-nyEA520ABdjEb2JC .icon-shape,#mermaid-svg-nyEA520ABdjEb2JC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nyEA520ABdjEb2JC .icon-shape p,#mermaid-svg-nyEA520ABdjEb2JC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nyEA520ABdjEb2JC .icon-shape .label rect,#mermaid-svg-nyEA520ABdjEb2JC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nyEA520ABdjEb2JC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nyEA520ABdjEb2JC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nyEA520ABdjEb2JC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 6-应用运行
5-CNI配置
4-设备分配
3-Pod调度
2-插件发现与注册
1-管理员配置
设置SR-IOV VF数量
编写config.json
部署Device Plugin DaemonSet
扫描PCI设备
过滤匹配设备
创建资源池
注册到Kubelet
API Server更新Node容量
Pod请求intel.com/sriov_net
Scheduler检查容量
绑定Pod到Node
Kubelet调用Allocate
获取DeviceSpecs+Envs
运行时注入设备
Multus读取设备信息
sriov-cni配置VF
设置VF MAC/VLAN/IP
DPDK: 通过VFIO访问VF
RDMA: 通过uverbs访问
Kernel: 通过netdev访问


十、架构模式总结

10.1 使用的设计模式

模式 应用位置 解决的问题
工厂模式 pkg/factory/resourceFactory 集中创建所有组件,依赖注入
单例模式 utils包的全局Provider 全局共享外部库封装
装饰器模式 HostDeviceImpl → GenericPciDevice → GenericNetDevice → PciNetDevice 渐进式添加设备属性
组合模式 InfoProvider链 灵活组合设备信息来源
策略模式 12个DeviceSelector 可插拔的设备过滤策略
模板方法模式 poolStub → netResourcePool/accelResourcePool/auxNetResourcePool 共享通用逻辑,特化差异方法
观察者模式 updateCh + ListAndWatch 设备状态变化通知Kubelet
接口隔离原则 HostDevice/PciDevice/NetDevice/PciNetDevice/AccelDevice/AuxNetDevice 不同角色只需关心所需接口

10.2 架构质量评价

维度 评分 说明
可扩展性 ★★★★☆ 新增设备类型/选择器/InfoProvider很容易,但新增设备发现源需修改Provider
可测试性 ★★★★★ Provider接口全面Mock化,选择器独立测试,InfoProvider独立测试
可维护性 ★★★★☆ 模块划分清晰,职责单一,但factory过大
代码复用 ★★★★☆ poolStub共享逻辑,装饰器复用基类,但三个Provider有重复过滤代码
解耦度 ★★★★★ 接口驱动设计,模块间通过接口交互
性能 ★★★☆☆ 30s健康检查间隔,全量设备列表推送,对大规模场景可能不足

10.3 潜在改进方向

  1. 增量健康检查:当前 Probe() 检查所有设备,可改为只检查变化的设备
  2. 工厂拆分:resourceFactory 可拆分为 DeviceProviderFactory、SelectorFactory、InfoProviderFactory 等
  3. 配置热更新:当前 SIGHUP 信号仅停止服务,可支持配置热重载
  4. 设备缓存:对 sysfs 和 netlink 的查询结果可缓存,减少 I/O 开销
  5. 辅助设备NUMA支持:当前 AuxNetDevice 不支持 NUMA 拓扑

十一、代码行数统计

文件数 估计行数 占比
cmd/sriovdp/ 2 350 7%
pkg/types/ 1 380 8%
pkg/factory/ 1 300 6%
pkg/devices/ 6 600 13%
pkg/infoprovider/ 7 430 9%
pkg/netdevice/ 4 630 13%
pkg/accelerator/ 3 200 4%
pkg/auxnetdevice/ 3 340 7%
pkg/resources/ 3 760 16%
pkg/cdi/ 1 120 3%
pkg/utils/ 5 740 15%
总计 36 ~4850 100%

十二、关键函数索引

函数 文件 核心职责
main cmd/sriovdp/main.go 程序入口,编排生命周期
newResourceManager cmd/sriovdp/manager.go 创建资源管理器
readConfig cmd/sriovdp/manager.go 读取并解析配置文件
validConfigs cmd/sriovdp/manager.go 验证配置合法性
discoverHostDevices cmd/sriovdp/manager.go 扫描主机PCI设备
initServers cmd/sriovdp/manager.go 创建资源服务器
startAllServers cmd/sriovdp/manager.go 启动所有gRPC服务器
AddTargetDevices pkg/netdevice/netDeviceProvider.go PCI设备发现与过滤
GetDevices pkg/netdevice/netDeviceProvider.go 构建HostDevice实例
GetFilteredDevices pkg/netdevice/netDeviceProvider.go 应用选择器过滤设备
NewHostDeviceImpl pkg/devices/host.go 创建设备基类
NewGenericNetDevice pkg/devices/gen_net.go 装饰网络属性
NewGenericPciDevice pkg/devices/gen_pci.go 装饰PCI属性
NewPciNetDevice pkg/netdevice/pciNetDevice.go 组装完整网络设备
NewRdmaDeviceSpec pkg/devices/rdma.go 创建RDMA规范
NewVdpaDeviceImpl pkg/devices/vdpa.go 创建vDPA设备
GetDeviceSpecs pkg/devices/host.go 聚合InfoProvider的DeviceSpecs
GetEnvVal pkg/devices/host.go 聚合InfoProvider的环境变量
NewNetResourcePool pkg/netdevice/netResourcePool.go 创建网络资源池
NewResourceServer pkg/resources/server.go 创建gRPC服务器
Start pkg/resources/server.go 启动gRPC服务
ListAndWatch pkg/resources/server.go 流式设备列表推送
Allocate pkg/resources/server.go 设备分配
triggerUpdate pkg/resources/server.go 定时健康检查
Filter pkg/resources/deviceSelectors.go (×12) 各类设备过滤
CreateCDISpecForPool pkg/cdi/cdi.go 生成CDI规范文件
CreateContainerAnnotations pkg/cdi/cdi.go 生成CDI容器注解
StoreDeviceInfoFile pkg/netdevice/nadutils.go 存储NAD设备信息
GetDefaultInfoProvider pkg/factory/factory.go 创建InfoProvider链
GetDeviceFilter pkg/factory/factory.go 解析选择器配置
FilterBySelector pkg/factory/factory.go 应用选择器
相关推荐
汤愈韬2 小时前
IPSec-NAT穿越原理和配置
网络·网络协议·安全·网络安全·security
疯狂打码的少年3 小时前
输入输出控制方式:DMA(直接存储器存取)
网络·笔记
知无不研3 小时前
对套接字的深入理解
linux·服务器·网络·c++·socket·网络套接字
xyzzklk3 小时前
解决Salesforce无法向外发送邮件
android·java·开发语言·网络·crm·salesforce·客户关系管理
珠***格5 小时前
实操落地|防逆流装置的安装规范、调试标准与故障处置
网络·数据库·人工智能·分布式·能源·边缘计算
国科安芯5 小时前
国科安芯推出商业航天级抗辐照全双工 RS485/422 收发器 ASC491S2Y
网络·分布式·单片机·架构·安全性测试
浮芷.7 小时前
鸿蒙PC端 TTS 网络连接错误问题详解:在线/离线模式切换与网络状态管理
网络·华为·开源·harmonyos·鸿蒙·鸿蒙系统
雪度娃娃7 小时前
ASIO异步通信——多线程模型
开发语言·网络·c++·php
luj_17687 小时前
残熵算法:风险缓冲与效率优化的融合
c语言·开发语言·网络·经验分享·算法