LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/topo/topo_addr_info/src - product_server.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.0 % 155 138
Test Date: 2026-08-17 10:19:35 Functions: 91.7 % 12 11

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : #include "product_server.h"
      11              : #include <string.h>
      12              : #include <stdlib.h>
      13              : #include <syslog.h>
      14              : #include "rank_info_types.h"
      15              : #include "hal.h"
      16              : #include "topo.h"
      17              : #include "eid_util.h"
      18              : #include "securec.h"
      19              : 
      20              : #define MAX_SERVER_ROOTINFO_LEN (2048)
      21              : #define PRODUCT_MESH_LEVEL (0)
      22              : #define PRODUCT_CLOS_LEVEL (1)
      23              : #define IP_ADDR_LEN (32)
      24              : 
      25              : /* 用于识别FE*/
      26              : #define MAX_UE_ID_IN_LEVEL (4)
      27              : #define MAX_LEVEL_NUM (4)
      28              : #define SERVER_NPU_NUM (8)
      29              : #define CLOS_LEVEL3 {.level = 3, .netType = NET_TYPE_CLOS, .ueNum = 0, .instanceIdFunc = GetNetInstanceIdForCluster}
      30              : 
      31              : enum UbEntityType {
      32              :     UE_TYPE_MESH = 0,
      33              :     UE_TYPE_CLOS = 1,
      34              :     UE_TYPE_UBOE = 2,
      35              :     UE_TYPE_UBG = 3,
      36              :     UE_TYPE_CLOS_PORTS = 4,
      37              : };
      38              : 
      39              : typedef struct stUEInfo {
      40              :     int dieId;
      41              :     int feId;
      42              :     enum UbEntityType type;
      43              :     char ports[256];
      44              : } UEInfo;
      45              : 
      46              : typedef int (*GetNetInstanceIdFunc)(
      47              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen);
      48              : 
      49              : typedef struct stLevelInfo {
      50              :     int level;
      51              :     int ueNum;
      52              :     UEInfo ueList[MAX_UE_ID_IN_LEVEL];
      53              :     char netType[16];
      54              :     GetNetInstanceIdFunc instanceIdFunc;
      55              : } LevelInfo;
      56              : 
      57              : typedef struct _stUBRule {
      58              :     unsigned int mainBoardId;
      59              :     unsigned int spodType;
      60              :     int levelNum;
      61              :     LevelInfo levelInfos[MAX_LEVEL_NUM];
      62              : } NetInfo;
      63              : 
      64              : /**
      65              :  *  获取OS级net instance id, 用于不组超节点形态
      66              :  */
      67              : int GetNetInstanceIdForOS(int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen);
      68              : 
      69              : /**
      70              :  *  获取超节点中单个服务器的net instance id
      71              :  */
      72              : int GetNetInstanceIdForPod(
      73              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen);
      74              : 
      75              : /**
      76              :  *  获取超节点的net instance id
      77              :  */
      78              : int GetNetInstanceIdForSuperPod(
      79              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen);
      80              : 
      81              : int GetNetInstanceIdForCluster(
      82              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen);
      83              : 
      84              : #define MAX_UE_ID (99) // 定义一个MAX_UE_ID, mesh必须使用最大的UE
      85              : static const NetInfo g_netInfoList[] = {
      86              :     {
      87              :         .mainBoardId = MAIN_BOARD_ID_SERVER_UBX,
      88              :         .spodType = TOPO_TYPE_IGNORE,
      89              :         .levelNum = 2, 
      90              :         {
      91              :             {
      92              :                 .level = 0,
      93              :                 .netType = NET_TYPE_TOPO_FILE_DESC,
      94              :                 .ueNum = 3,
      95              :                 .instanceIdFunc = GetNetInstanceIdForOS,
      96              :                 .ueList = {
      97              :                     {.dieId = UDIE_1, .feId = 3, .type =UE_TYPE_MESH}, 
      98              :                     {.dieId = UDIE_1, .feId = 2, .type =UE_TYPE_CLOS_PORTS},
      99              :                     {.dieId = UDIE_1, .feId = 2, .type =UE_TYPE_CLOS}
     100              :                 }
     101              :             },
     102              :             CLOS_LEVEL3,
     103              :         },
     104              :    },
     105              :    {
     106              :         .mainBoardId = MAIN_BOARD_ID_SERVER_8PMESH,
     107              :         .spodType = TOPO_TYPE_IGNORE,
     108              :         .levelNum = 3, 
     109              :         {
     110              :             {  // level 0 为OS内通信
     111              :                 .level = 0,
     112              :                 .netType = NET_TYPE_TOPO_FILE_DESC,
     113              :                 .ueNum = 1,
     114              :                 .instanceIdFunc = GetNetInstanceIdForPod,
     115              :                 .ueList = {
     116              :                     {.dieId = UDIE_1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH},
     117              :                 }
     118              :             },
     119              :             { // level 1 为超平面
     120              :                 .level = 1,
     121              :                 .netType = NET_TYPE_CLOS,
     122              :                 .ueNum = 1,
     123              :                 .instanceIdFunc = GetNetInstanceIdForSuperPod,
     124              :                 .ueList = { // 8口scaleup
     125              :                     {.dieId = UDIE_0, .feId = 3, .type = UE_TYPE_CLOS},
     126              :                 },
     127              :             },
     128              :             CLOS_LEVEL3,
     129              :         },
     130              :    },
     131              :    {
     132              :         .mainBoardId = MAIN_BOARD_ID_SERVER_8PMESH_UBOE,
     133              :         .spodType = TOPO_TYPE_IGNORE,
     134              :         .levelNum = 4, 
     135              :         {
     136              :             {
     137              :                 .level = 0, .netType = NET_TYPE_TOPO_FILE_DESC, .ueNum = 1,
     138              :                 .instanceIdFunc = GetNetInstanceIdForPod,
     139              :                 .ueList = { {.dieId = UDIE_1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH}, }
     140              :             },
     141              :             {
     142              :                 .level = 1, .netType = NET_TYPE_CLOS, .ueNum = 1,
     143              :                 .instanceIdFunc = GetNetInstanceIdForSuperPod,
     144              :                 .ueList = { {.dieId = UDIE_0, .feId = 3, .type =UE_TYPE_CLOS} },
     145              :             },
     146              :             { 
     147              :                 .level = 2, .netType = NET_TYPE_CLOS, .ueNum = 1, .instanceIdFunc = GetNetInstanceIdForCluster,
     148              :                 .ueList = { {.dieId = UDIE_0, .feId = 0, .type =UE_TYPE_UBOE, .ports = "1/8"} } 
     149              :             },
     150              :             CLOS_LEVEL3,
     151              :         },
     152              :    },
     153              :    {// 由两个8 NPU服务器组成一个16NPU的小超节点,共16个NPU组成fullmesh组网
     154              :         .mainBoardId = MAIN_BOARD_ID_SERVER_8PMESH_UBOE,
     155              :         .spodType = TOPO_TYPE_SERVER_16FM,  // 两个服务器组16p fullmesh
     156              :         .levelNum = 3, 
     157              :         {
     158              :             {
     159              :                 .level = 0, .netType = NET_TYPE_TOPO_FILE_DESC, .ueNum = 2,
     160              :                 .instanceIdFunc = GetNetInstanceIdForPod,
     161              :                 .ueList = { 
     162              :                     {.dieId = UDIE_0, .feId = MAX_UE_ID, .type = UE_TYPE_MESH}, 
     163              :                     {.dieId = UDIE_1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH}
     164              :                 }
     165              :             },
     166              :             { // 支持UBOE出口
     167              :                 .level = 2, .netType = NET_TYPE_CLOS, .ueNum = 1, .instanceIdFunc = GetNetInstanceIdForCluster,
     168              :                 .ueList = { {.dieId = UDIE_0, .feId = 0, .type =UE_TYPE_UBOE, .ports = "1/8"} },
     169              :             },
     170              :             CLOS_LEVEL3,
     171              :         },
     172              :    },
     173              :    {
     174              :         .mainBoardId = MAIN_BOARD_ID_SERVER_8PMESH_NOSP_UBOE, // 这种形态无超平面,但是有UBOE
     175              :         .spodType = TOPO_TYPE_IGNORE,
     176              :         .levelNum = 3, 
     177              :         {
     178              :             {
     179              :                 .level = 0,
     180              :                 .netType = NET_TYPE_TOPO_FILE_DESC,
     181              :                 .ueNum = 1,
     182              :                 .instanceIdFunc = GetNetInstanceIdForOS,
     183              :                 .ueList = {
     184              :                     {.dieId = UDIE_1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH},
     185              :                 }
     186              :             },
     187              :             { 
     188              :                 .level = 2, .netType = NET_TYPE_CLOS, .ueNum = 1, .instanceIdFunc = GetNetInstanceIdForCluster,
     189              :                 .ueList = { {.dieId = UDIE_0, .feId = 0, .type =UE_TYPE_UBOE, .ports = "1/8"} } 
     190              :             },
     191              :             CLOS_LEVEL3,
     192              :         },
     193              :    },
     194              :    {
     195              :         .mainBoardId = MAIN_BOARD_ID_SERVER_8PMESH_NOSP, // 无超平面,无UBOE
     196              :         .spodType = TOPO_TYPE_IGNORE,
     197              :         .levelNum = 2,
     198              :         {
     199              :             {
     200              :                 .level = 0, .netType = NET_TYPE_TOPO_FILE_DESC, .ueNum = 1,
     201              :                 .instanceIdFunc = GetNetInstanceIdForOS,
     202              :                 .ueList = { {.dieId = UDIE_1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH} }
     203              :             },
     204              :             CLOS_LEVEL3,
     205              :         },
     206              :    },
     207              :    {
     208              :         .mainBoardId = MAIN_BOARD_ID_SERVER_TYPE1,
     209              :         .spodType = TOPO_TYPE_IGNORE,
     210              :         .levelNum = 3, 
     211              :         {
     212              :             {
     213              :                 .level = 0,
     214              :                 .ueNum = 1,
     215              :                 .ueList = {
     216              :                     {.dieId = 1, .feId = MAX_UE_ID, .type = UE_TYPE_MESH},
     217              :                 }
     218              :             },
     219              :             {
     220              :                 .level = 1,
     221              :                 .ueNum = 2,
     222              :                 .ueList = {
     223              :                     {.dieId = 0, .feId = 3, .type =UE_TYPE_CLOS },
     224              :                     {.dieId = 1, .feId = 2, .type =UE_TYPE_CLOS },
     225              :                 }
     226              :             },
     227              :             CLOS_LEVEL3,
     228              :         },
     229              :    },
     230              : };
     231              : 
     232            0 : int ServerGetRootinfoLen(size_t* len)
     233              : {
     234            0 :     *len = MAX_SERVER_ROOTINFO_LEN;
     235            0 :     return 0;
     236              : }
     237              : 
     238           98 : int GetNetInstanceIdForOS(int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen)
     239              : {
     240           98 :     return get_server_id(netInstanceId, netInstanceIdLen);
     241              : }
     242              : 
     243           68 : int GetNetInstanceIdForPod(int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen)
     244              : {
     245           68 :     return sprintf_s(netInstanceId, netInstanceIdLen, "sp_%ld_srv_%ld", spodInfo->super_pod_id, spodInfo->server_index);
     246              : }
     247              : 
     248           67 : int GetNetInstanceIdForSuperPod(
     249              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen)
     250              : {
     251           67 :     return sprintf_s(netInstanceId, netInstanceIdLen, "sp_%ld", spodInfo->super_pod_id);
     252              : }
     253              : 
     254           67 : int GetNetInstanceIdForCluster(
     255              :     int npu_id, const struct dcmi_spod_info* spodInfo, char* netInstanceId, int netInstanceIdLen)
     256              : {
     257           67 :     return sprintf_s(netInstanceId, netInstanceIdLen, "cluster");
     258              : }
     259              : 
     260          166 : const NetInfo* GetNetInfo(unsigned int mainBoardId, unsigned int spodType)
     261              : {
     262              :     // 优先匹配满足mainboard id和 super pod type的情况
     263         1324 :     for (size_t i = 0; i < sizeof(g_netInfoList) / sizeof(g_netInfoList[0]); ++i) {
     264         1159 :         if (g_netInfoList[i].mainBoardId == mainBoardId && g_netInfoList[i].spodType == spodType) {
     265            1 :             return &g_netInfoList[i];
     266              :         }
     267              :     }
     268              :     //  忽略spod type,只匹配mainboard id
     269          554 :     for (size_t i = 0; i < sizeof(g_netInfoList) / sizeof(g_netInfoList[0]); ++i) {
     270          554 :         if (g_netInfoList[i].mainBoardId == mainBoardId) {
     271          165 :             return &g_netInfoList[i];
     272              :         }
     273              :     }
     274            0 :     return NULL;
     275              : }
     276              : 
     277              : /*
     278              :  * @brief 处理mesh entity的地址, 将UBEntity中的地址加到layer中
     279              :  * 将UB entity中的所有地址按每个端口填入
     280              :  * @param layer: 网络层
     281              :  * @param ue: ue entity
     282              :  * @param spod_info: spod信息
     283              :  * @return int: 0 成功
     284              :  */
     285            9 : static int LayerAddMesh(const UBEntity* ue, NetLayer* layer, int type)
     286              : {
     287           68 :     for (unsigned int j = 0; j < ue->eidNum; ++j) {
     288           59 :         if (UrmaEidIsPortGroup(&ue->eidList[j].eid)) {
     289            9 :             continue;
     290              :         }
     291              :         Addr addr;
     292           50 :         memset_s(&addr, sizeof(Addr), 0x00, sizeof(Addr));
     293           50 :         AddrSetEID(&addr, &ue->eidList[j].eid);
     294           50 :         char port[MAX_PORT_LEN] = {0};
     295           50 :         char planeId[MAX_PLANE_ID_LEN] = {0};
     296           50 :         int portId = UrmaEidGetPortId(&ue->eidList[j].eid);
     297           50 :         int dieId = UrmaEidGetDieId(&ue->eidList[j].eid);
     298              :         // topo中端口从0开始编,CNA中需要规避全0,从1开始
     299           50 :         sprintf_s(port, MAX_PORT_LEN, "%d/%d", dieId, portId);
     300           50 :         if (type == UE_TYPE_MESH) {
     301           42 :             sprintf_s(planeId, sizeof(planeId), "plane_%d", dieId);
     302            8 :         } else if (type == UE_TYPE_CLOS_PORTS) {
     303            8 :             sprintf_s(planeId, sizeof(planeId), "plane_clos_%d_%d", dieId, portId);
     304              :         }
     305           50 :         AddrAddPort(&addr, port);
     306           50 :         AddrSetPlaneId(&addr, planeId);
     307           50 :         NetLayerAddAddr(layer, &addr);
     308              :     }
     309            9 :     return 0;
     310              : }
     311              : 
     312            5 : static int LayerAddClos(const UBEntity* ue, NetLayer* layer)
     313              : {
     314            5 :     int portGroupIdx = UBEntityGetPortGroupIdx(ue);
     315            5 :     if (portGroupIdx < 0) {
     316            0 :         return -1;
     317              :     }
     318            5 :     int dieId = UrmaEidGetDieId(&ue->eidList[portGroupIdx].eid);
     319              :     Addr addr;
     320            5 :     memset_s(&addr, sizeof(Addr), 0x00, sizeof(Addr));
     321            5 :     AddrSetEID(&addr, &ue->eidList[portGroupIdx].eid);
     322           42 :     for (unsigned int i = 0; i < ue->eidNum; ++i) {
     323           37 :         if (UrmaEidIsPortGroup(&ue->eidList[i].eid)) {
     324            5 :             continue;
     325              :         }
     326           32 :         char port[MAX_PORT_LEN] = {0};
     327           32 :         sprintf_s(port, MAX_PORT_LEN, "%d/%d", dieId, UrmaEidGetPortId(&ue->eidList[i].eid));
     328           32 :         AddrAddPort(&addr, port);
     329              :     }
     330              : 
     331            5 :     char planeId[MAX_PLANE_ID_LEN] = {0};
     332            5 :     sprintf_s(planeId, sizeof(planeId), "plane_clos_%d", dieId);
     333            5 :     AddrSetPlaneId(&addr, planeId);
     334            5 :     NetLayerAddAddr(layer, &addr);
     335            5 :     return 0;
     336              : }
     337              : 
     338            2 : static int LayerAddUBOE(const UBEntity* ue, const UEInfo* ueInfo, NetLayer* layer)
     339              : {
     340              : #define INVLID_IP_PREFIX "254" // 该IP是有协议栈无DHCP等场景自动生成的本地私有地址前缀
     341              :     Addr addr;
     342            2 :     memset_s(&addr, sizeof(Addr), 0x00, sizeof(Addr));
     343            2 :     int result = -1;
     344            6 :     for (unsigned int i = 0; i < ue->eidNum; ++i) {
     345            4 :         char cna[IP_ADDR_LEN] = {0};
     346            4 :         UrmaEid2CNA(&ue->eidList[i].eid, cna, sizeof(cna));
     347            4 :         if (strncmp(cna, INVLID_IP_PREFIX, strlen(INVLID_IP_PREFIX)) == 0) {
     348            2 :             continue;
     349              :         }
     350            2 :         AddrSetIP(&addr, cna);
     351            2 :         char port[MAX_PORT_LEN] = {0};
     352            2 :         int ret = sprintf_s(port, MAX_PORT_LEN, "%s", ueInfo->ports);
     353            2 :         if (ret < 0) {
     354            0 :             break;
     355              :         }
     356            2 :         AddrAddPort(&addr, port);
     357            2 :         result = 0;
     358              :     }
     359            2 :     char planeId[MAX_PLANE_ID_LEN] = {0};
     360            2 :     int ret = sprintf_s(planeId, sizeof(planeId), "plane_uboe");
     361            2 :     if (ret < 0) {
     362            0 :         return -1;
     363              :     }
     364            2 :     AddrSetPlaneId(&addr, planeId);
     365            2 :     NetLayerAddAddr(layer, &addr);
     366            2 :     return result;
     367              : }
     368              : 
     369              : /**
     370              :  * @brief 根据dieId和feId从UEList中获取UBEntity
     371              :  * @param ueList: ue entity列表
     372              :  * @param dieId: die id
     373              :  * @param ueId: ue id
     374              :  * @param type: UB类型
     375              :  * @return UBEntity*: ue entity
     376              :  */
     377          369 : static const UBEntity* GetUBEntityByFilter(const UEList* ueList, int dieId, int ueId, int type)
     378              : {
     379          369 :     if (type == UE_TYPE_UBOE) {
     380           79 :         for (unsigned int i = 0; i < ueList->ueNum; i++) {
     381           14 :             if (UrmaEidIsUBOE(&ueList->ueList[i].eidList[0].eid)) {
     382            2 :                 return &ueList->ueList[i];
     383              :             }
     384              :         }
     385           65 :         return NULL;
     386              :     }
     387          302 :     if (type == UE_TYPE_UBG) {
     388            0 :         for (unsigned int i = 0; i < ueList->ueNum; i++) {
     389            0 :             if (UrmaEidIsUBG(&ueList->ueList[i].eidList[0].eid)) {
     390            0 :                 return &ueList->ueList[i];
     391              :             }
     392              :         }
     393            0 :         return NULL;
     394              :     }
     395          302 :     int maxFe = 0;
     396          302 :     const UBEntity* ubEntity = NULL;
     397          331 :     for (unsigned int i = 0; i < ueList->ueNum; i++) {
     398           38 :         if (UrmaEidIsUBOE(&ueList->ueList[i].eidList[0].eid)) {
     399            4 :             continue;
     400              :         }
     401           34 :         int die = UrmaEidGetDieId(&ueList->ueList[i].eidList[0].eid);
     402           34 :         int fe = UBEntityGetId(&ueList->ueList[i]);
     403           34 :         if (die == dieId && fe == ueId) { // MAX_UE_ID足够大,这里不会匹配到
     404            9 :             return &ueList->ueList[i];
     405              :         }
     406              :         //  获取本iodie上UBEntity ID最大的UB Entity
     407           25 :         if (die == dieId && fe > maxFe) {
     408           15 :             maxFe = fe;
     409           15 :             ubEntity = &ueList->ueList[i];
     410              :         }
     411              :     }
     412          293 :     if (ueId == MAX_UE_ID) {
     413          133 :         return ubEntity;
     414              :     }
     415          160 :     return NULL;
     416              : }
     417              : 
     418              : /**
     419              :  * @brief 根据配置从ueList中过滤出ub entity, 并处理其中的地址添加到netlayer中
     420              :  * @param layer: 网络层信息
     421              :  * @param ueList: 全量的ue entity数组
     422              :  * @param levelInfo:  当前处理的层级信息
     423              :  * @param spodInfo: spod信息
     424              :  * @return int: 0 成功
     425              :  */
     426          466 : static int ProcessLayer(
     427              :     int npuId, NetLayer* layer, UEList* ueList, const LevelInfo* levelInfo, const struct dcmi_spod_info* spodInfo)
     428              : {
     429              :     /* RoCE 层(level 3)走独立路径,不查 UEList */
     430          466 :     if (levelInfo->level == 3) {
     431          166 :         return ProcessLayerRoce(npuId, layer);
     432              :     }
     433              : 
     434          300 :     char net_instance_id[MAX_INSTANCE_ID_LEN] = {0};
     435          300 :     levelInfo->instanceIdFunc(npuId, spodInfo, net_instance_id, sizeof(net_instance_id));
     436          300 :     NetLayerInit(layer, levelInfo->level, net_instance_id);
     437          300 :     NetLayerSetNetType(layer, levelInfo->netType);
     438              : 
     439          300 :     int ret = -1;
     440          669 :     for (int i = 0; i < levelInfo->ueNum; ++i) {
     441          369 :         int fe = levelInfo->ueList[i].feId;
     442          369 :         int die = levelInfo->ueList[i].dieId;
     443          369 :         int type = levelInfo->ueList[i].type;
     444          369 :         const UBEntity* ue = GetUBEntityByFilter(ueList, die, fe, type);
     445          369 :         if (ue == NULL) {
     446          353 :             continue;
     447              :         }
     448           16 :         if (type == UE_TYPE_MESH || type == UE_TYPE_CLOS_PORTS) {
     449            9 :             ret = LayerAddMesh(ue, layer, type);
     450            7 :         } else if (type == UE_TYPE_CLOS) {
     451            5 :             ret = LayerAddClos(ue, layer);
     452            2 :         } else if (type == UE_TYPE_UBOE) {
     453            2 :             ret = LayerAddUBOE(ue, &levelInfo->ueList[i], layer);
     454              :         }
     455              :     }
     456          300 :     return ret;
     457              : }
     458              : 
     459          166 : int ServerGetRootinfo(int npu_id, unsigned mainboard_id, void* buf, size_t* len)
     460              : {
     461          166 :     if (buf == NULL || len == NULL) {
     462            0 :         return RET_NOK;
     463              :     }
     464              :     struct dcmi_spod_info spod_info;
     465              :     UEList ueList;
     466          166 :     HalGetUBEntityList(npu_id, &ueList);
     467          166 :     hal_get_spod_info(npu_id, &spod_info);
     468              : 
     469              :     RootInfo rootinfo;
     470              :     Rank rank;
     471          166 :     RootInfoInit(&rootinfo);
     472          166 :     int localId = npu_id;
     473          166 :     if (spod_info.super_pod_type == TOPO_TYPE_SERVER_16FM) {
     474            1 :         localId = npu_id + (spod_info.server_index * SERVER_NPU_NUM);
     475              :     }
     476          166 :     RankInit(&rank, npu_id, localId);
     477          166 :     TopoGetFilePath(mainboard_id, spod_info.super_pod_type, rootinfo.topo_file_path, MAX_TOPO_PATH_LEN);
     478              : 
     479          166 :     const NetInfo* netInfo = GetNetInfo(mainboard_id, spod_info.super_pod_type);
     480          166 :     if (netInfo == NULL) {
     481            0 :         return -1;
     482              :     }
     483              : 
     484          632 :     for (int i = 0; i < netInfo->levelNum; ++i) {
     485              :         NetLayer layer;
     486          466 :         if (ProcessLayer(npu_id, &layer, &ueList, &netInfo->levelInfos[i], &spod_info) == 0) {
     487          121 :             RankAddNetLayer(&rank, &layer);
     488              :         }
     489              :     }
     490              : 
     491          166 :     RootInfoAddRank(&rootinfo, &rank);
     492          166 :     char* rootinfo_buf = RootInfoToString(&rootinfo);
     493          166 :     if (rootinfo_buf == NULL) {
     494            0 :         return -1;
     495              :     }
     496          166 :     if ((*len) < strlen(rootinfo_buf)) {
     497            0 :         (*len) = strlen(rootinfo_buf);
     498            0 :         free(rootinfo_buf);
     499            0 :         return -1;
     500              :     }
     501          166 :     errno_t ret = strcpy_s(buf, *len, rootinfo_buf);
     502          166 :     (*len) = strlen(buf);
     503          166 :     free(rootinfo_buf);
     504          166 :     return ret;
     505              : }
        

Generated by: LCOV version 2.0-1