import ctypes
from _ctypes import POINTER
UBSE_UB_DEVICE_GUID_SIZE = 32
UBSE_UB_UPI_STR_SIZE = 4
class UbsBusinstanceId:
_FORMAT = [4, 4, 1, 1, 6, 16]
_TOTAL_LEN = sum(_FORMAT)
def __init__(self, id_str: str = ""):
"""
初始化UbsBusinstanceId
:param id_str:
- 空字符串"" 表示空ID
- 或格式为'xxxx-xxxx-x-x-xxxxxx-xxxxxxxxxxxxxxxx'的字符串
"""
if not isinstance(id_str, str):
raise TypeError("Input must be a string")
if id_str == "":
self._is_empty = True
self._parts = None
else:
self._is_empty = False
parts = id_str.split('-')
if len(parts) != len(self._FORMAT):
raise ValueError(f"Expected {len(self._FORMAT)} parts, got {len(parts)} in '{id_str}'")
validated_parts = []
for i, (part, expected_len) in enumerate(zip(parts, self._FORMAT)):
if len(part) != expected_len:
raise ValueError(f"Part {i + 1} has length {len(part)}, expected {expected_len}: '{part}'")
if not all(c in '0123456789abcdefABCDEF' for c in part):
raise ValueError(f"Part {i + 1} contains non-hex characters: '{part}'")
validated_parts.append(part.lower())
self._parts = validated_parts
@classmethod
def from_raw(cls, raw_str: str):
"""从32位连续字符串创建实例 (如'cc08a000000000000000000000010000')"""
if len(raw_str) == 0:
return raw_str
if len(raw_str) != UBSE_UB_DEVICE_GUID_SIZE:
raise ValueError("Raw string must be exactly 32 characters long")
if not all(c in '0123456789abcdefABCDEF' for c in raw_str):
raise ValueError("Raw string must be hexadecimal")
raw = raw_str.lower()
parts = []
start = 0
for length in cls._FORMAT:
parts.append(raw[start:start + length])
start += length
formatted = '-'.join(parts)
return formatted
@classmethod
def empty(cls):
""" 创建一个空的UbsBusinstanceId"""
return ""
@property
def is_empty(self) -> bool:
"""判断是否为空"""
return self._is_empty
def to_formatted(self) -> str:
""" 返回带'-'的标准格式, 空时返回'' """
if self._is_empty:
return ""
return '-'.join(self._parts)
def to_raw(self) -> str:
"""返回32位连续字符串,空时返回 ''"""
if self._is_empty:
return ""
return ''.join(self._parts)
def __str__(self):
return self.to_formatted() if not self._is_empty else "(empty)"
def __repr__(self):
if self._is_empty:
return "UbsBusinstanceId.empty()"
return f"UbsBusinstanceId('{self.to_formatted()}')"
def __eq__(self, other):
if not isinstance(other, UbsBusinstanceId):
return False
if self._is_empty and other._is_empty:
return True
if self._is_empty or other._is_empty:
return False
return self._parts == other._parts
def __bool__(self):
""" 支持if device_id: 判断非空"""
return not self._is_empty
class UbsUbDevicesTypeT(ctypes.Structure):
_fields_ = [
("device_type", ctypes.c_uint32),
("slot_id", ctypes.c_uint8),
("chip_id", ctypes.c_uint8),
("die_id", ctypes.c_uint8),
("pf_id", ctypes.c_uint16),
("vf_id", ctypes.c_uint16)
]
def __str__(self):
return (
f"ubs_ub_device_type(\n"
f" device type={self.device_type}\n"
f" slot id={self.slot_id}\n"
f" chip id={self.chip_id}\n"
f" die id={self.die_id}\n"
f" pf id={self.pf_id}\n"
f" vf id={self.vf_id}\n"
f")"
)
class UbsUbAllocDevicesInfoT(ctypes.Structure):
_fields_ = [
("upi_str", ctypes.c_uint8 * UBSE_UB_UPI_STR_SIZE),
("bus_instance_guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("ub_dev_list_count", ctypes.c_uint8),
("ub_dev_list", POINTER(UbsUbDevicesTypeT))
]
def __str__(self):
dev_list_str = []
for i in range(self.ub_dev_list_count):
dev = self.ub_dev_list[i]
dev_list_str.append(str(dev))
return (
f"ubs_alloc_dev_info(\n"
f" upi str={list(self.upi_str)[:UBSE_UB_UPI_STR_SIZE]}\n"
f" bus instance guid={list(self.bus_instance_guid)[:UBSE_UB_DEVICE_GUID_SIZE]}\n"
f" ub dev list count={self.ub_dev_list_count}\n"
f" ub dev list ={dev_list_str}\n"
f")"
)
class BusiAttrT(ctypes.Structure):
_fields_ = [
("guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("sub_devices_count", ctypes.c_uint8),
("sub_devices", UbsUbDevicesTypeT * 0)
]
class UbsBusiT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_uint8),
("attr", POINTER(BusiAttrT))
]
class NpuAttrT(ctypes.Structure):
_fields_ = [
("slot_id", ctypes.c_uint8),
("chip_id", ctypes.c_uint8),
("guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("bus_instance_guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("affinity_devices_count", ctypes.c_uint8),
("affinity_devices", UbsUbDevicesTypeT * 0)
]
class UbsNpuT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_uint8),
("attr", POINTER(NpuAttrT))
]
class NicPfeAttrT(ctypes.Structure):
_fields_ = [
("slot_id", ctypes.c_uint8),
("chip_id", ctypes.c_uint8),
("pf_id", ctypes.c_uint16),
("guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("bus_instance_guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("affinity_devices_count", ctypes.c_uint8),
("affinity_devices", UbsUbDevicesTypeT * 0)
]
class NicVfeAttrT(ctypes.Structure):
_fields_ = [
("slot_id", ctypes.c_uint8),
("chip_id", ctypes.c_uint8),
("pf_id", ctypes.c_uint16),
("vf_id", ctypes.c_uint16),
("guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("bus_instance_guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
("affinity_devices_count", ctypes.c_uint8),
("affinity_devices", UbsUbDevicesTypeT * 0)
]
class UbsNicPfeT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_uint8),
("attr", POINTER(NicPfeAttrT))
]
class UbsNicVfeT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_uint8),
("attr", POINTER(NicVfeAttrT))
]
class UbctrlAttrT(ctypes.Structure):
_fields_ = [
("slot_id", ctypes.c_uint8),
("chip_id", ctypes.c_uint8),
("die_id", ctypes.c_uint8),
("guid", ctypes.c_uint8 * UBSE_UB_DEVICE_GUID_SIZE),
]
class UbsUbctrlT(ctypes.Structure):
_fields_ = [
("type", ctypes.c_uint8),
("attr", POINTER(UbctrlAttrT))
]
class UbsUbDevicesListT(ctypes.Structure):
_fields_ = [
("ubctrl_ptr", POINTER(UbsUbctrlT)),
("ubctrl_cnt", ctypes.c_uint8),
("nic_pfe_ptr", POINTER(UbsNicPfeT)),
("nic_pfe_cnt", ctypes.c_uint8),
("nic_vfe_ptr", POINTER(UbsNicVfeT)),
("nic_vfe_cnt", ctypes.c_uint8),
("npu_ptr", POINTER(UbsNpuT)),
("npu_cnt", ctypes.c_uint8),
("busi_ptr", POINTER(UbsBusiT)),
("busi_cnt", ctypes.c_uint8)
]
class DeviceInfo:
"""设备信息基类"""
def __init__(self, device_type):
self.device_type = device_type
def to_dict(self):
"""转换为字典格式"""
return {
"device_type": self.device_type
}
class NicPfeInfo(DeviceInfo):
"""NIC_PFE设备信息类"""
def __init__(self, device_id, guid, bus_instance):
super().__init__("NIC_PFE")
self.device_id = device_id
self.guid = guid
self.bus_instance = bus_instance
self.affinity_devs = []
def to_dict(self):
return {
"device_type": self.device_type,
"device_id": self.device_id,
"guid": self.guid,
"bus_instance": self.bus_instance,
"affinity_devs": self.affinity_devs
}
class NicVfeInfo(DeviceInfo):
"""NIC_VFE设备信息类"""
def __init__(self, device_id, guid, bus_instance):
super().__init__("NIC_VFE")
self.device_id = device_id
self.guid = guid
self.bus_instance = bus_instance
self.affinity_devs = []
def to_dict(self):
return {
"device_type": self.device_type,
"device_id": self.device_id,
"guid": self.guid,
"bus_instance": self.bus_instance,
"affinity_devs": self.affinity_devs
}
class NpuInfo(DeviceInfo):
"""NPU设备信息类"""
def __init__(self, device_id, guid, bus_instance):
super().__init__("NPU")
self.device_id = device_id
self.guid = guid
self.bus_instance = bus_instance
self.affinity_devs = []
def to_dict(self):
return {
"device_type": self.device_type,
"device_id": self.device_id,
"guid": self.guid,
"bus_instance": self.bus_instance,
"affinity_devs": self.affinity_devs
}
class BusInstanceInfo(DeviceInfo):
"""BUSI设备信息类"""
def __init__(self, guid):
super().__init__("BUSI")
self.guid = guid
self.sub_devices = []
def to_dict(self):
return {
"device_type": self.device_type,
"guid": self.guid,
"sub_devices": self.sub_devices
}
class UbctrlInfo(DeviceInfo):
"""UBCTRL设备信息类"""
def __init__(self, device_id):
super().__init__("UBCTRL")
self.device_id = device_id
def to_dict(self):
return {
"device_type": self.device_type,
"device_id": self.device_id
}
class DeviceFactory:
"""设备信息工厂类"""
@staticmethod
def create_device(device_type, **kwargs):
if device_type == "NIC_PFE":
return NicPfeInfo(**kwargs)
elif device_type == "NIC_VFE":
return NicVfeInfo(**kwargs)
elif device_type == "NPU":
return NpuInfo(**kwargs)
elif device_type == "BUSI":
return BusInstanceInfo(**kwargs)
elif device_type == "UBCTRL":
return UbctrlInfo(**kwargs)
else:
raise ValueError(f"Unknown device type: {device_type}")