# pcie_device

## 功能简介

- pcie_device组件包含了从业务TOPO的解析建链到终端设备的纳管，承载了BMC对PCIe设备的端到端管理能力，主要内容分为两部分：
    1. PCIe设备纳管
    2. PCIe业务TOPO管理（PCIe设备加载、高速线缆检测）

### 目录结构

```
├── biz_topo                            -- 业务拓扑总目录
│   ├── biz_topo.lua                    -- PCIE拓扑建立
│   ├── biz_topo_service.lua            -- 业务拓扑入口
│   ├── class
│   │   ├── base.lua                    -- 通用基类
│   │   ├── business_connector.lua      -- 业务连接器类
│   │   ├── load_info.lua               -- 总线BDF信息类
│   │   ├── pcie_addr_info.lua          -- PCIE地址信息类
│   │   ├── serdes.lua                  -- CPU与UBCDD相连的SerDes类
│   │   └── unit_configuration.lua      -- 线缆检测白名单配置类
│   ├── def.lua                         -- 静态枚举
│   ├── device_loader.lua               -- PCIE设备加载
│   ├── signal_mgr.lua                  -- pcie信号管理
│   └── topo_monitor.lua                -- 线缆检测
├── common.lua                          -- PCIE_DEVICE模块公共函数
├── device
│   ├── class
│   │   ├── pcie_card.lua               -- PCIE_CARD类，承载北向、IPMI功能    
│   │   └── pcie_device.lua             -- PCIE_DEVICE类获取、设置方法实现
│   └── device_service.lua              -- 承载BDF信息的同步、更新实现
├── imu                                 -- imu交互实现
│   └── init.lua
├── infrastructure
│   ├── collection_helper.lua           -- 集合库
│   └── log_helper.lua                  -- 日志收集库
├── pcie_device_app.lua                 -- 模块初始化入口
└── service_manager.lua

```

## 关键特性

### 整体架构设计
- 本组件架构设计总体分为接口、服务、领域、基础设施四个层级。
1. 接口层：作为组件级的对外统一出口，提供接口用于跨模块之间的信息交互。
2. 服务层：完成内部多个领域对象和外部其他服务之间协调性、组合性的交互逻辑，作为各业务模块的出口向组件外部提供调用能力。
    - `device_service`：设备管理服务，基于领域对象PCIeDevice、PCIeCard
        1. 对PCIe设备进行管理（如：PCIe卡、基于PCIe协议的NVMe盘）。
    - `biztopo_service`：业务拓扑服务，基于领域对象BizTopo、TopoMonitor、DeviceLoader
        1. 整合csr节点信息，构建业务Topo树，结合PSR实现PCIe设备链路的动态获取。并对高速Topo链路连接启动实时检测。
        2. 向bios提供PCIe设备槽位信息，并接收处理BIOS上报的PCIe卡信息，结合自发现服务实现PCIe卡的加载和管理。
3. 领域层：提供了PCIe设备、PCIe标卡、业务TOPO树相关实体类的定义，承载了核心业务逻辑的实现，主要包括设备加载、高速TOPO检测、对静态属性调用基础设施层提供的接口进行动态信息的获取和更新等。
    - `biz_topo`：承载了天池基础组件业务TOPO的解析与建立，结合整机配置，实现CPU与PCIe设备的建链。
    - `topo_monitor`：提供了业务TOPO高速链路进行故障检测的能力。
    - `device_loader`：基于业务TOPO链路，结合带内上报信息，提供对非标准PCIe设备进行纳管的能力，并提供设备的持久化机制。
    - `PCIeDevice`：对所有PCIe设备抽象出的类定义，承载了PCIe总线相关的属性定义和故障诊断错误标识，针对PCIe设备通用特性对外提供统一的查询、设置入口。
    - `PCIeCard`：承载了PCIe卡的基本信息管理，此类是一个抽象类，承载了各种不同类型PCIe卡的公共属性和方法。不同类型PCIe卡能够获取的动态属性和更新的方式依赖不同的协议，所以每种特定类型的PCIe卡会通过继承来拓展定义，如：SDI卡。
    - `signal_manager`：基于signal库并结合pcie业务需求提供的信号管理机制。

4. 基础设施层：提供对基础协议和通用功能点的封装，属于静态能力，供上层调用。
    - `common_tools`：封装了基于pcie_device组件业务特点的常用逻辑，以功能点的形式向上层提供
![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/WIKI202311182380514/15704920/ef6e783c31314c0eb8088b88f5247ae0.png)

### 业务拓扑建立

- pcie_device组件的核心能力之一即为对业务TOPO的管理能力，PCIe设备相关的其他特性均依赖于对业务TOPO关系的建立，整体流程如下：
    1. SerDes/BusinessConnector（CSR）、UnitConfiguration（PSR）对象分发加载
    2. BCU内部业务连接器与对应的CPU资源关联对接，IEU内部业务连接器下行PCIe设备连接器与上行关联对接
    3. 结合整机配置对象UnitConfiguration中提供的高速线缆连接关系，将IEU侧业务连接器与BCU侧业务连接器建立联系，PCIe设备连接器即可关联上其对应的CPU资源

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/11/2/20231202T1716Z/8f5a5b0e029b49ceb6e2d07605cba14a/image.png)

### PCIe设备加载

- 我们设计了基于BIOS上报BDF对标准PCIe设备进行管理的方案
    1. 在业务拓扑建立完成之后，BIOS将从BMC获取到PCIe设备槽位和CPU资源配置信息
    2. BIOS将向BMC上报PCIe设备的deviceBDF信息
    3. BMC侧通过deviceBDF信息向PMU发出请求，查询到PCIe设备四元组信息
    4. 通过PCIe设备四元组即可完成对应设备CSR的加载，实现对标准PCIe设备的纳管

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/10/18/20231118T2232Z/234167b0e4a64d2298d2d87e812632fc/image.png)



### 高速TOPO/线缆检测

- 在收集到整机链路配置信息和基于SMC读取到的实时组件连接信息后，BMC可以实现对当前的高速链路进行实时连接情况检测的能力，如果连接错误会实时上报告警，指导近端运维人员及时调整连接方式

- 高速TOPO/线缆检测流程如下：
    1. 初始化端口状态和整机配置信息，识别合法检测区域
    2. 通过TOPO发现命令从SMC读取信息当前TOPO链路连接信息
    3. 将实时TOPO链路连接信息与整机链路配置信息进行比对，分析当前设备接入状态是否合法
    4. 更新链路检测状态，存在非法连接状态则上报告警

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/10/22/20231122T0910Z/46dcdba62dba49e0bd06243a373847be/image.png)

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2024/0/17/20240117T1408Z/3d5062bdf5d045f8b0ddc61d5ddf6a0f/image.png)

- 线缆检测代码流程梳理

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/11/2/20231202T1701Z/4adff5a5da664a7caf36cc30d9e076a9/image.png)

## 对外接口
### 资源协作接口

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetPcieErrorStatus`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetPcieErrorStatus` | `a{ss}yyyyysy` | `y` | 根据错误类型设置不同错误事件属性状态 | 根据错误类型设置不同错误事件属性状态 | BDF信息存在且唯一，Value:0.未发生、1.发生 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetUCEByBIOS`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetUCEByBIOS` | `a{ss}yyyyy` | `y` | 设置不可纠正错误标识 | 设置不可纠正错误标识 | BDF信息存在且唯一，Value:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetBandwidthReduction`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetBandwidthReduction` | `a{ss}yyyyy` | `y` | 设置降带宽事件标识 | 设置降带宽事件标识 | BDF信息存在且唯一，Value:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetLinkSpeedReduced`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetLinkSpeedReduced` | `a{ss}yyyyy` | `y` | 设置链路降速事件标识 | 设置链路降速事件标识 | BDF信息存在且唯一，Value:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetDiagnosticFault`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetDiagnosticFault` | `a{ss}yyyyyy` | `y` | 设置严重故障告警标识 | 设置严重故障告警标识 | BDF信息存在且唯一，Value:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetPredictiveFault`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetPredictiveFault` | `a{ss}yyyyyy` | `y` | 设置预故障事件标识 | 设置预故障事件标识 | BDF信息存在且唯一，Value:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `GetDeviceName`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `GetDeviceName` | `a{ss}yyyyy` | `ys` | 获取PCIe设备丝印信息 | 获取PCIe设备丝印信息 | BDF信息存在且唯一 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `GetPCIeCardNum`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `GetPCIeCardNum` | `a{ss}` | `u` | 获取PCIeCard数量 | 获取PCIeCard数量 | 不涉及 | PCIeCard个数 | 不涉及 | 不涉及 | 不涉及 | Id在SystemId下唯一 | 不涉及 |

---

#### `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` - `SetFaultByBios`

| 接口路径（path） | 接口名称（interface） | 方法名（method） | 输入参数 | 输出参数 | 说明 | 业务作用 | 约束 | 单位 | 互斥关系 | 依赖关系 | 格式样例 | 唯一性要求 | 兼容性要求 |
|----------|----------|--------|----------|----------|------|----------|------|------|----------|----------|----------|------------|------------|
| `/bmc/kepler/Systems/${SystemId}/PCIeDevices/${Id}` | `bmc.kepler.Systems.PCIeDevices.PCIeDevice` | `SetFaultByBios` | `a{ss}yyyy` | `y` | 设置FaultByBios属性值 | 设置FaultByBios属性值 | BDF信息存在且唯一，FaultStatus:0.无故障、1.故障 | 不涉及 | 不涉及 | 对应的pcie设备需要加载并初始化 | 不涉及 | Id在SystemId下唯一 | 不涉及 |


### IPMI命令
- 具体参数参考本组件配置文件`ipmi.json`

| 方法  | 描述  |
| :------------: | :------------: |
| SetCpuBusSize | BIOS通过此命令上报CPU BUS信息 |
| UpdateIntegratedPcieConfig | BIOS通过此命令上报Socket内集成的PCIe化控制器（Integrated PCIe Controller）的BDF信息 |

## 配置介绍

### 关键类定义

- 为了知道某个PCIe设备在哪个CPU的哪个SerDes上，引入了一下几个实体器件：
    - PCIeSlot：对应IEU上的两个PCIe槽位，即对应了两个PCIe Connector
    - Riser：插在BCU上的IO扩展器，用来插PCIe设备，有上行和下行两种BusinessConnector对象
    Riser中下行对象的UpstreamResources配置了上行对象的Name
    - UBCDD：一种连接器，有BusinessConnector对象(上行和下行)
    - SerDes-x：也叫HiLink，CPU出的几个接口，几个接口都连到UBCDD上

![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/10/18/20231118T2111Z/49e586143e2b4959b4eda08e41e933ac/image.png)

#### UnitConfiguration
- UnitConfiguration承载了BCU和IEU的连接关系
    - Slot：全局唯一，硬件提供
    - SrcPortName：B4a(B4b)对应的槽位7，B4c(B4d)对应的槽位8
    - TargetPortID：Riser向上连接的端口号
- 如图X8的SerDes_1_8对应B4c(B4d)，X4的SerDes_1_7和SerDes_1_10对应B4a(B4b)
（ActualResourceOrder和Ports有对应顺序）
![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/10/18/20231118T2143Z/b91b33e13b874b27adc4d739e99e35ff/image.png)

#### SerDes
- SerDes承载了BCU组件内部的CPU资源配置
    - Device：代表SerDes对应的设备Device为14/14/15/15，这个Device就是PCIeAddrInfo中的Device
    - Socket：代表SerDes连着哪个CPU
![image](https://wiki.huawei.com/vision-file-storage/api/file/download/upload-v2/2023/10/18/20231118T2148Z/35bce18c74b748b5b5b7f3930388f088/image.png)

#### PCIeDevice

- PCIe设备的管理对象
    - BDF：RootBDF，物理上的BDF，根据槽位写死的
    - DevBDF：设备BDF，由BIOS分配
    - FunctionClass：卡类型的区分

#### PCIeAddrInfo
- 承载PCIe设备槽位信息
- 先加载PCIeAddrInfo，再加载PCIeDevice，**PCIeDevice中槽位号和BDF由PCIeAddrInfo同步而来**
- biztopo模块完成PCIeAddrInfo属性设置
