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

Generated by: LCOV version 2.0-1