【NPU】Ascend Device Plugin — Part 5 公共基础层(pkg/common)超深度源码分析之二
七、fault_code.go 超深度解析
7.1 模块定位
fault_code.go 是整个公共基础层中最复杂、最核心的文件(1922行),实现了完整的故障管理引擎,包括:
- 故障码加载(从JSON文件)
- 故障定制化配置加载(容错时间、频率统计、持续时间统计)
- Switch故障码加载
- 故障回调处理与缓存
- 故障频率/持续时间统计引擎
- HBM与AIC/AIV关联故障处理
- 手动隔离NPU管理
- 故障升级缓存
7.2 核心数据结构
7.3 全局变量与缓存体系
7.4 核心流程深度解析
7.4.1 故障码加载流程
网络故障码映射逻辑:
- 支持映射:NotHandle/PreSeparate/Separate 中的网络故障码 → 对应的网络故障码列表
- 不支持映射:RestartRequest/RestartBusiness/RestartNPU/FreeRestartNPU 中的网络故障码 → 降级为 NotHandleFaultNetworkCodes(网络故障不支持重启类操作)
7.4.2 故障定制化加载流程
容错时间参数校验:
| 参数 | 最小值 | 默认值 | 最大值 |
|---|---|---|---|
| WaitDeviceResetTime | 60s | 150s | 180s |
| WaitProcessReadCMTime | 5s | 30s | 90s |
| WaitFaultSelfHealingTime | 1s | 15s | 30s |
7.4.3 故障回调处理流程
关键设计:
- 异步处理:
SaveDevFaultInfo通过go关键字异步执行,避免阻塞DCMI回调 - 限流保护:每分钟最多1000次回调(
FaultCallBackRateLimit),超限则丢弃并标记设备需重新初始化 - 恢复延迟:故障恢复消息延迟1秒处理,因为DCMI订阅的恢复消息与故障码查询结果可能不同步
- 重置完成处理:收到
ResetFinishFaultCode(0x8C2FA009)时标记设备需要重新初始化
7.4.4 故障频率统计引擎
handleFrequencyFault 核心逻辑:
设计意图:
- 频率统计在滑动时间窗口内计数故障发生次数
- 达到阈值时触发升级(写入升级缓存,持久化到CM)
- 未达阈值但已在升级缓存中,则更新时间(保持升级状态不超时释放)
- 超过释放时间窗口未再发生,则从升级缓存中移除
7.4.5 故障持续时间统计引擎
超时/恢复算法详解:
算法核心思想:
- 故障事件队列按时间排序后,成对处理(occur→recover为一个周期)
- 如果occur到recover的间隔超过FaultTimeout阈值 → 故障超时,设置TimeoutStatus=true
- 如果recover到下一个occur的间隔超过RecoverTimeout阈值 → 恢复超时,设置TimeoutStatus=false
- 队列尾部单个事件用当前时间计算持续时间
7.4.6 HBM与AIC/AIV关联故障处理
设计意图:HBM(高带宽内存)双比特错误和AIC/AIV总线错误如果在5秒内同时发生,认为是关联故障,AIC/AIV错误被抑制(不额外报告),避免重复处理。
7.4.7 故障设置与恢复流程
两轮处理的设计原因:同一条故障可能在同一批次中既出现occur又出现recover(瞬时故障),两轮处理确保这种故障不会对外报告。
八、proto.go 超深度解析
8.1 模块定位
proto.go 定义了整个 device-plugin 的核心数据结构(协议体),是所有模块间数据交换的基础类型库。
8.2 核心结构体类图
8.3 Option 结构体详解
Option 是全局运行参数单例 ParamOption 的类型,通过命令行参数初始化,贯穿整个组件:
var ParamOption Option // 全局单例
8.4 GetAllDeviceInfoTypeList — 设备信息类型清单
func GetAllDeviceInfoTypeList() map[string]struct{} {
return map[string]struct{}{
// 910健康/不健康/网络不健康
GetAscend910Key(""): {},
GetAscend910Key(api.CmCardUnhealthySuffix): {},
GetAscend910Key(api.CmCardNetworkUnhealthySuffix): {},
// 历史遗留键
HuaweiUnHealthAscend910: {}, HuaweiNetworkUnHealthAscend910: {},
// 910物理+虚拟设备类型
api.ResourceNamePrefix + api.Ascend910: {},
api.ResourceNamePrefix + Ascend910vir2: {},
// ... 所有虚拟设备类型
// 310/310P物理+虚拟设备类型
api.ResourceNamePrefix + api.Ascend310: {},
api.ResourceNamePrefix + api.Ascend310P: {},
// AI Core资源
api.ResourceNamePrefix + AiCoreResourceName: {},
}
}
设计意图:返回所有需要在ConfigMap中追踪的设备信息键名,用于设备信息上报和同步。
九、proto_v2.go 超深度解析
9.1 模块定位
proto_v2.go 定义A5芯片特有的 DPU(Data Processing Unit) 数据结构。
9.2 数据结构
type DpuCMData struct {
Name string // 网卡接口名称
Operstate string // 接口操作状态
DeviceID string // 接口设备ID
VendorID string // 接口厂商ID
}
type DpuInfo struct {
BusType string // 总线类型
DPUList []DpuCMData // DPU列表
NpuToDpusMap map[string][]string // NPU到DPU的映射
UpdateTime int64 // 更新时间戳
}
十、send_stat.go 超深度解析
10.1 模块定位
SendStats 用于收集和分析 gRPC 发送操作的统计结果,特别用于检测连续发送失败,以触发重新注册kubelet或重启device-plugin。
10.2 数据结构
type sendResult struct {
sendTime time.Time // 发送时间
success bool // 是否成功
}
type SendStats struct {
rwLock sync.RWMutex // 读写锁
sendResults []sendResult // 发送结果环形缓冲
recordLen int // 最大记录长度
}
10.3 核心方法流程
10.4 使用场景
十一、file_manager.go 超深度解析
11.1 模块定位
提供文件管理工具,包括文件写入、创建、删除,以及重置文件和DataTrace文件的路径生成与清理。
11.2 核心函数
11.3 文件路径体系
/user/restore/reset/
└── {namespace}.{configmap-name}/
├── reset.json # 重置信息数据
└── restartType # 重启类型(hotReset等)
/user/cluster-info/datatrace-config/
└── {namespace}.data-trace-{jobName}/ # DataTrace配置目录
{SoftShareDeviceConfigDir}{namespace}.{jobName}/ # 软共享设备配置目录
十二、atomic_bool.go 超深度解析
12.1 模块定位
提供基于 sync/atomic 的原子布尔值原语,用于多协程间的无锁状态同步。
12.2 实现解析
type AtomicBool struct{ v uint32 } // 用uint32存储bool值(0=false, 1=true)
func NewAtomicBool(initial bool) *AtomicBool {
return &AtomicBool{v: boolToUint(initial)}
}
func (b *AtomicBool) Load() bool {
return atomic.LoadUint32(&b.v) == 1 // 原子加载并比较
}
func (b *AtomicBool) Store(new bool) {
atomic.StoreUint32(&b.v, boolToUint(new)) // 原子存储
}
func boolToUint(b bool) uint32 {
if b { return 1 }
return 0
}
设计意图:Go标准库没有提供原子布尔类型,通过uint32+atomic操作封装实现。相比互斥锁,原子操作更轻量高效。
十三、slice_common.go 超深度解析
13.1 模块定位
提供切片操作工具集,包括int32/int64/string切片的包含判断、元素移除、索引查找、十六进制转换等。
13.2 工具类型
var Int32Tool int32Tool // int32切片工具单例
var Int64Tool int64Tool // int64切片工具单例
var StringTool stringTool // string切片工具单例
13.3 方法清单
13.4 核心方法解析
13.4.1 Int64Tool.Remove — 递归移除
func (i int64Tool) Remove(sources []int64, target int64) []int64 {
if len(sources) == 0 { return sources }
index := i.Index(sources, target) // 查找目标索引
if index == -1 { return sources } // 未找到返回原切片
// 递归移除:append跳过index位置元素后,继续移除可能重复的target
return i.Remove(append(sources[:index], sources[index+1:]...), target)
}
设计意图:递归移除所有等于target的元素,而非仅移除第一个。
13.4.2 Int64Tool.SameElement — 交集判断
func (i int64Tool) SameElement(sources, targets []int64) bool {
for _, source := range sources {
for _, target := range targets {
if source == target { return true } // 有任一相同元素即返回true
}
}
return false
}
时间复杂度:O(n*m),适用于小切片(故障码列表通常很短)。
13.4.3 StringTool.HexStringToInt — 十六进制批量转换
func (s stringTool) HexStringToInt(sources []string) []int64 {
intSlice := make([]int64, 0, len(sources))
for _, source := range sources {
num, err := strconv.ParseInt(source, Hex, 0) // Hex=16
if err != nil {
hwlog.RunLog.Errorf("parse hex int failed and skip it, string: %s", source)
continue // 跳过无效的十六进制字符串
}
intSlice = append(intSlice, num)
}
return intSlice
}
13.4.4 泛型Contains函数
func Contains[T comparable](sources []T, target T) bool {
for _, sourceNum := range sources {
if sourceNum == target { return true }
}
return false
}
设计意图:Go 1.18+泛型支持,提供通用包含判断。与Int32Tool.Contains功能重叠,但更通用。
十四、upgradefault.go 超深度解析
14.1 模块定位
upgradefault.go 实现故障升级缓存管理系统,管理因频率统计或持续时间统计触发的故障升级原因,支持缓存的增删改查、ConfigMap持久化、手动隔离自动填充等高级功能。
14.2 核心概念
14.3 数据结构类图
14.4 核心流程
14.4.1 故障升级缓存写入
14.4.2 ConfigMap与缓存转换
14.4.3 手动隔离修复(FixManuallySeparateReason)
设计意图:当ConfigMap中的 ManuallySeparateNPU 配置变更时,同步更新升级缓存:
- 新增的手动隔离NPU → 自动填充升级原因
- 移除的手动隔离NPU → 从缓存中删除对应升级原因
- 返回自动填充的PhyId列表(用于日志和事件通知)
14.4.4 配置变更更新已有升级故障
14.5 ReasonKeyMatcher — 函数式匹配器
type ReasonKeyMatcher func(UpgradeFaultReasonKey) bool
func CodeMatcher(faultCode string) ReasonKeyMatcher {
return func(key UpgradeFaultReasonKey) bool {
return faultCode == key.FaultCode
}
}
func LevelMatcher(faultLevel string) ReasonKeyMatcher {
return func(key UpgradeFaultReasonKey) bool {
return faultLevel == key.FaultLevel
}
}
func TypeMatcher(upgradeType UpgradeTypeEnum) ReasonKeyMatcher {
return func(key UpgradeFaultReasonKey) bool {
return upgradeType == key.UpgradeType
}
}
设计意图:使用函数式编程模式,通过组合匹配器实现灵活的缓存键过滤。可以链式组合:RemoveTimeoutReasonCache(logicId, CodeMatcher(code), TypeMatcher(FrequencyUpgradeType))。
十五、模块间调用关系全景图
完整数据流图
附录:关键设计模式总结
| 设计模式 | 应用位置 | 说明 |
|---|---|---|
| 单例模式 | ParamOption, Int32Tool, Int64Tool, StringTool, hbmTool | 全局唯一实例 |
| 工厂模式 | NewHbmFaultManager, NewSendStats, NewAtomicBool, NewFileWatch | 对象创建 |
| 策略模式 | ReasonKeyMatcher (CodeMatcher/LevelMatcher/TypeMatcher) | 函数式匹配策略 |
| 观察者模式 | updateTriggerChan, TriggerUpdate/GetUpdateChan | 事件触发通知 |
| 装饰器模式 | FilterPods的conditionFunc参数 | 可插拔过滤条件 |
| 泛型 | Contains[T], Keys[T,U], DeviceKey[T] | Go 1.18+类型参数 |
| 读写锁 | SendStats.rwLock, faultFrequencyMapLock, faultDurationMapLock | 读多写少场景 |
| 限流器 | limiter (rate.Limiter) | 故障回调限流 |
| 原子操作 | AtomicBool (atomic.LoadUint32/StoreUint32) | 无锁并发 |
| sync.Map | Ascend910ResetGoroutine | 并发安全Map |
本文档基于 mind-cluster-v26.0.1 版本源码完成,涵盖 pkg/common 全部12个文件的逐行级分析,包含架构图、流程图、类图共30余个Mermaid图表。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐



所有评论(0)