| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static const char * const ChassisTypeStr[] = |
| { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700", "ISR4200" }; |
| static const char * const ChassisSlotTypeStr[] = { "", "Line", "Spine", "SRBD" }; |
| |
| typedef struct chassis_scan { |
| ibnd_chassis_t *first_chassis; |
| ibnd_chassis_t *current_chassis; |
| ibnd_chassis_t *last_chassis; |
| } chassis_scan_t; |
| |
| const char *ibnd_get_chassis_type(ibnd_node_t * node) |
| { |
| int chassis_type; |
| |
| if (!node) { |
| IBND_DEBUG("node parameter NULL\n"); |
| return NULL; |
| } |
| |
| if (!node->chassis) |
| return NULL; |
| |
| chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F); |
| |
| switch (chassis_type) |
| { |
| case VTR_VENDOR_ID: |
| { |
| if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT) |
| return NULL; |
| return ChassisTypeStr[node->ch_type]; |
| } |
| case MLX_VENDOR_ID: |
| { |
| if (node->ch_type_str[0] == '\0') |
| return NULL; |
| return node->ch_type_str; |
| } |
| default: |
| { |
| break; |
| } |
| } |
| return NULL; |
| } |
| |
| char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size) |
| { |
| int vendor_id; |
| |
| if (!node) { |
| IBND_DEBUG("node parameter NULL\n"); |
| return NULL; |
| } |
| |
| |
| vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F); |
| |
| if ((vendor_id != VTR_VENDOR_ID) && (vendor_id != MLX_VENDOR_ID)) |
| return NULL; |
| if (!node->chassis) |
| return NULL; |
| if (node->ch_slot == UNRESOLVED_CS || node->ch_slot > SRBD_CS) |
| return NULL; |
| if (!str) |
| return NULL; |
| snprintf(str, size, "%s %d Chip %d", ChassisSlotTypeStr[node->ch_slot], |
| node->ch_slotnum, node->ch_anafanum); |
| return str; |
| } |
| |
| static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric, |
| unsigned char chassisnum) |
| { |
| ibnd_chassis_t *current; |
| |
| for (current = fabric->chassis; current; current = current->next) |
| if (current->chassisnum == chassisnum) |
| return current; |
| |
| return NULL; |
| } |
| |
| static uint64_t topspin_chassisguid(uint64_t guid) |
| { |
| |
| |
| return guid & 0xffffffff00ffffffULL; |
| } |
| |
| int ibnd_is_xsigo_guid(uint64_t guid) |
| { |
| if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL) |
| return 1; |
| else |
| return 0; |
| } |
| |
| static int is_xsigo_leafone(uint64_t guid) |
| { |
| if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL) |
| return 1; |
| else |
| return 0; |
| } |
| |
| int ibnd_is_xsigo_hca(uint64_t guid) |
| { |
| |
| if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL) |
| return 1; |
| else |
| return 0; |
| } |
| |
| int ibnd_is_xsigo_tca(uint64_t guid) |
| { |
| |
| if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL) |
| return 1; |
| else |
| return 0; |
| } |
| |
| static int is_xsigo_ca(uint64_t guid) |
| { |
| if (ibnd_is_xsigo_hca(guid) || ibnd_is_xsigo_tca(guid)) |
| return 1; |
| else |
| return 0; |
| } |
| |
| static int is_xsigo_switch(uint64_t guid) |
| { |
| if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL) |
| return 1; |
| else |
| return 0; |
| } |
| |
| static uint64_t xsigo_chassisguid(ibnd_node_t * node) |
| { |
| uint64_t sysimgguid = |
| mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F); |
| uint64_t remote_sysimgguid; |
| |
| if (!is_xsigo_ca(sysimgguid)) { |
| |
| |
| if (is_xsigo_switch(sysimgguid)) |
| return sysimgguid & 0xffffffff00ffffffULL; |
| else |
| return sysimgguid; |
| } else { |
| if (!node->ports || !node->ports[1]) |
| return 0; |
| |
| |
| if (!node->ports[1]->remoteport) |
| return sysimgguid; |
| |
| |
| remote_sysimgguid = |
| mad_get_field64(node->ports[1]->remoteport->node->info, 0, |
| IB_NODE_SYSTEM_GUID_F); |
| if (is_xsigo_leafone(remote_sysimgguid)) |
| return remote_sysimgguid & 0xffffffff00ffffffULL; |
| else |
| return sysimgguid; |
| } |
| } |
| |
| static uint64_t get_chassisguid(ibnd_node_t * node) |
| { |
| uint32_t vendid = mad_get_field(node->info, 0, IB_NODE_VENDORID_F); |
| uint64_t sysimgguid = |
| mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F); |
| |
| if (vendid == TS_VENDOR_ID || vendid == SS_VENDOR_ID) |
| return topspin_chassisguid(sysimgguid); |
| else if (vendid == XS_VENDOR_ID || ibnd_is_xsigo_guid(sysimgguid)) |
| return xsigo_chassisguid(node); |
| else |
| return sysimgguid; |
| } |
| |
| static ibnd_chassis_t *find_chassisguid(ibnd_fabric_t * fabric, |
| ibnd_node_t * node) |
| { |
| ibnd_chassis_t *current; |
| uint64_t chguid; |
| |
| chguid = get_chassisguid(node); |
| for (current = fabric->chassis; current; current = current->next) |
| if (current->chassisguid == chguid) |
| return current; |
| |
| return NULL; |
| } |
| |
| uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric, unsigned char chassisnum) |
| { |
| ibnd_chassis_t *chassis; |
| |
| if (!fabric) { |
| IBND_DEBUG("fabric parameter NULL\n"); |
| return 0; |
| } |
| |
| chassis = find_chassisnum(fabric, chassisnum); |
| if (chassis) |
| return chassis->chassisguid; |
| else |
| return 0; |
| } |
| |
| static int is_router(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_IB_FC_ROUTER || |
| devid == VTR_DEVID_IB_IP_ROUTER); |
| } |
| |
| static int is_spine_9096(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB4 || devid == VTR_DEVID_SFB4_DDR); |
| } |
| |
| static int is_spine_9288(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB12 || devid == VTR_DEVID_SFB12_DDR); |
| } |
| |
| static int is_spine_2004(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB2004); |
| } |
| |
| static int is_spine_2012(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB2012); |
| } |
| |
| static int is_spine_4700(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB4700); |
| } |
| |
| static int is_spine_4700x2(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB4700X2); |
| } |
| |
| static int is_spine_4200(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SFB4200); |
| } |
| |
| static int is_spine(ibnd_node_t * n) |
| { |
| return (is_spine_9096(n) || is_spine_9288(n) || |
| is_spine_2004(n) || is_spine_2012(n) || |
| is_spine_4700(n) || is_spine_4700x2(n) || |
| is_spine_4200(n)); |
| } |
| |
| static int is_line_24(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SLB24 || |
| devid == VTR_DEVID_SLB24_DDR || devid == VTR_DEVID_SRB2004); |
| } |
| |
| static int is_line_8(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SLB8); |
| } |
| |
| static int is_line_2024(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SLB2024); |
| } |
| |
| static int is_line_4700(ibnd_node_t * n) |
| { |
| uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F); |
| return (devid == VTR_DEVID_SLB4018); |
| } |
| |
| static int is_line(ibnd_node_t * n) |
| { |
| return (is_line_24(n) || is_line_8(n) || |
| is_line_2024(n) || is_line_4700(n)); |
| } |
| |
| |
| static const char line_slot_2_sfb4[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, |
| 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| static const char anafa_line_slot_2_sfb4[37] = { |
| 0, |
| 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, |
| 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| static const char line_slot_2_sfb12[37] = { |
| 0, |
| 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, |
| 10, 10, 11, 11, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| static const char anafa_line_slot_2_sfb12[37] = { |
| 0, |
| 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, |
| 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| static const char line_slot_2_sfb18[37] = { |
| 0, |
| 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, |
| 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18}; |
| |
| static const char anafa_line_slot_2_sfb18[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
| }; |
| |
| |
| static const char line_slot_2_sfb18x2[37] = { |
| 0, |
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
| |
| static const char anafa_line_slot_2_sfb18x2[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| static const char line_slot_2_sfb4200[37] = { |
| 0, |
| 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, |
| 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9}; |
| |
| static const char anafa_line_slot_2_sfb4200[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 |
| }; |
| |
| |
| static const char ipr_slot_2_sfb4_port[37] = { |
| 0, |
| 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, |
| 3, 2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| static const char spine12_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| static const char anafa_spine12_slot_2_slb[37] = { |
| 0, |
| 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| static const char spine4_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| static const char anafa_spine4_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| static const char spine18_slot_2_slb[37] = { |
| 0, |
| 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| static const char anafa_spine18_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| static const char anafa_spine18x2_slot_2_slb[37] = { |
| 0, |
| 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| static const char sfb4200_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| static const char anafa_sfb4200_slot_2_slb[37] = { |
| 0, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| }; |
| |
| |
| |
| static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport) |
| { |
| n->ch_slot = SPINE_CS; |
| if (is_spine_9096(n)) { |
| n->ch_type = ISR9096_CT; |
| n->ch_slotnum = spine4_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_9288(n)) { |
| n->ch_type = ISR9288_CT; |
| n->ch_slotnum = spine12_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_2012(n)) { |
| n->ch_type = ISR2012_CT; |
| n->ch_slotnum = spine12_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_2004(n)) { |
| n->ch_type = ISR2004_CT; |
| n->ch_slotnum = spine4_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_4700(n)) { |
| n->ch_type = ISR4700_CT; |
| n->ch_slotnum = spine18_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine18_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_4700x2(n)) { |
| n->ch_type = ISR4700_CT; |
| n->ch_slotnum = spine18_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum]; |
| } else if (is_spine_4200(n)) { |
| n->ch_type = ISR4200_CT; |
| n->ch_slotnum = sfb4200_slot_2_slb[lineport->portnum]; |
| n->ch_anafanum = anafa_sfb4200_slot_2_slb[lineport->portnum]; |
| } else { |
| IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n", |
| n->guid); |
| } |
| return 0; |
| } |
| |
| static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport) |
| { |
| uint64_t guessnum = 0; |
| |
| n->ch_found = 1; |
| |
| n->ch_slot = SRBD_CS; |
| if (is_spine_9096(spineport->node)) { |
| n->ch_type = ISR9096_CT; |
| n->ch_slotnum = line_slot_2_sfb4[spineport->portnum]; |
| n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum]; |
| } else if (is_spine_9288(spineport->node)) { |
| n->ch_type = ISR9288_CT; |
| n->ch_slotnum = line_slot_2_sfb12[spineport->portnum]; |
| |
| guessnum = spineport->node->guid % 4; |
| |
| |
| |
| n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2)); |
| } else if (is_spine_2012(spineport->node)) { |
| n->ch_type = ISR2012_CT; |
| n->ch_slotnum = line_slot_2_sfb12[spineport->portnum]; |
| |
| guessnum = spineport->node->guid % 4; |
| |
| |
| |
| n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2)); |
| } else if (is_spine_2004(spineport->node)) { |
| n->ch_type = ISR2004_CT; |
| n->ch_slotnum = line_slot_2_sfb4[spineport->portnum]; |
| n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum]; |
| } else { |
| IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n", |
| spineport->node->guid); |
| } |
| return 0; |
| } |
| |
| static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport) |
| { |
| n->ch_slot = LINE_CS; |
| if (is_spine_9096(spineport->node)) { |
| n->ch_type = ISR9096_CT; |
| n->ch_slotnum = line_slot_2_sfb4[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum]; |
| } else if (is_spine_9288(spineport->node)) { |
| n->ch_type = ISR9288_CT; |
| n->ch_slotnum = line_slot_2_sfb12[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum]; |
| } else if (is_spine_2012(spineport->node)) { |
| n->ch_type = ISR2012_CT; |
| n->ch_slotnum = line_slot_2_sfb12[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum]; |
| } else if (is_spine_2004(spineport->node)) { |
| n->ch_type = ISR2004_CT; |
| n->ch_slotnum = line_slot_2_sfb4[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum]; |
| } else if (is_spine_4700(spineport->node)) { |
| n->ch_type = ISR4700_CT; |
| n->ch_slotnum = line_slot_2_sfb18[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb18[spineport->portnum]; |
| } else if (is_spine_4700x2(spineport->node)) { |
| n->ch_type = ISR4700_CT; |
| n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum]; |
| } else if (is_spine_4200(spineport->node)) { |
| n->ch_type = ISR4200_CT; |
| n->ch_slotnum = line_slot_2_sfb4200[spineport->portnum]; |
| n->ch_anafanum = anafa_line_slot_2_sfb4200[spineport->portnum]; |
| } else { |
| IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n", |
| spineport->node->guid); |
| } |
| return 0; |
| } |
| |
| |
| |
| |
| |
| static int fill_mellanox_chassis_record(ibnd_node_t * node) |
| { |
| int p = 0; |
| ibnd_port_t *port; |
| |
| char node_desc[IB_SMP_DATA_SIZE]; |
| char *system_name; |
| char *system_type; |
| char *system_slot_name; |
| char *node_index; |
| char *iter; |
| int dev_id; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| memcpy(node_desc, node->nodedesc, IB_SMP_DATA_SIZE); |
| |
| IBND_DEBUG("fill_mellanox_chassis_record: node_desc:%s \n",node_desc); |
| |
| if (node->ch_found) |
| return 0; |
| |
| |
| dev_id = mad_get_field(node->info, 0,IB_NODE_DEVID_F); |
| if (dev_id != MLX_DEVID_IS4) |
| return 0; |
| |
| if((node_desc[0] != 'M') || |
| (node_desc[1] != 'F') || |
| (node_desc[2] != '0') || |
| (node_desc[3] != ';')) { |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s \n",node_desc); |
| return 0; |
| } |
| |
| |
| system_name = &node_desc[4]; |
| for (iter = system_name ; (*iter != ':') && (*iter != '\0') ; iter++); |
| if(*iter == '\0'){ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_name failed) \n",node_desc); |
| return 0; |
| } |
| *iter = '\0'; |
| iter++; |
| |
| system_type = iter; |
| for ( ; (*iter != '/') && (*iter != '\0') ; iter++); |
| if(*iter == '\0'){ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_type failed) \n",node_desc); |
| return 0; |
| } |
| *iter = '\0'; |
| iter++; |
| |
| system_slot_name = iter; |
| for ( ; (*iter != '/') && (*iter != ':') && (*iter != '\0') ; iter++); |
| if(*iter == '\0'){ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_slot_name failed) \n",node_desc); |
| return 0; |
| } |
| if(*iter == ':'){ |
| *iter = '\0'; |
| iter++; |
| for ( ; (*iter != '/') && (*iter != '\0') ; iter++); |
| if(*iter == '\0'){ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get board type failed) \n",node_desc); |
| return 0; |
| } |
| } |
| *iter = '\0'; |
| iter++; |
| node_index = iter; |
| if(node_index[0] != 'U'){ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get node index) \n",node_desc); |
| return 0; |
| } |
| |
| |
| node->ch_anafanum = (unsigned char) atoi(&node_index[1]); |
| if(node->ch_anafanum != 1){ |
| IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum); |
| } |
| |
| |
| |
| if(system_slot_name[0] == 'L') |
| node->ch_slot = LINE_CS; |
| else if(system_slot_name[0] == 'S') |
| node->ch_slot = SPINE_CS; |
| else{ |
| IBND_DEBUG("fill_mellanox_chassis_record: Unsupported system_slot_name:%s \n",system_slot_name); |
| return 0; |
| } |
| |
| |
| node->ch_found = 1; |
| |
| node->ch_slotnum = (unsigned char) atoi(&system_slot_name[1]); |
| if((node->ch_slot == LINE_CS && (node->ch_slotnum > (LINES_MAX_NUM + 1))) || |
| (node->ch_slot == SPINE_CS && (node->ch_slotnum > (SPINES_MAX_NUM + 1)))){ |
| IBND_ERROR("fill_mellanox_chassis_record: invalid slot number:%d \n",node->ch_slotnum); |
| node->ch_slotnum = 0; |
| return 0; |
| } |
| |
| |
| strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1); |
| |
| |
| if(node->ch_slot == LINE_CS) |
| { |
| for (p = 1; p <= node->numports && p <= 18 ; p++) { |
| port = node->ports[p]; |
| if (!port) |
| continue; |
| port->ext_portnum = p; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int insert_mellanox_line_and_spine(ibnd_node_t * node, ibnd_chassis_t * chassis) |
| { |
| if (node->ch_slot == LINE_CS){ |
| |
| if (chassis->linenode[node->ch_slotnum]) |
| return 0; |
| |
| chassis->linenode[node->ch_slotnum] = node; |
| } |
| else if (node->ch_slot == SPINE_CS){ |
| |
| if (chassis->spinenode[node->ch_slotnum]) |
| return 0; |
| |
| chassis->spinenode[node->ch_slotnum] = node; |
| } |
| else |
| return 0; |
| |
| node->chassis = chassis; |
| |
| return 0; |
| } |
| |
| |
| |
| static void voltaire_portmap(ibnd_port_t * port); |
| |
| |
| |
| |
| |
| static int fill_voltaire_chassis_record(ibnd_node_t * node) |
| { |
| int p = 0; |
| ibnd_port_t *port; |
| ibnd_node_t *remnode = NULL; |
| |
| if (node->ch_found) |
| return 0; |
| node->ch_found = 1; |
| |
| |
| |
| |
| if (is_router(node)) |
| |
| for (p = 1; p <= node->numports; p++) { |
| port = node->ports[p]; |
| if (port && is_spine(port->remoteport->node)) |
| get_router_slot(node, port->remoteport); |
| } |
| else if (is_spine(node)) { |
| int is_4700x2 = is_spine_4700x2(node); |
| |
| for (p = 1; p <= node->numports; p++) { |
| port = node->ports[p]; |
| if (!port || !port->remoteport) |
| continue; |
| |
| |
| |
| |
| |
| if (is_4700x2 && (port->portnum > 18)) |
| continue; |
| |
| remnode = port->remoteport->node; |
| if (remnode->type != IB_NODE_SWITCH) { |
| if (!remnode->ch_found) |
| get_router_slot(remnode, port); |
| continue; |
| } |
| if (!node->ch_type) |
| |
| get_sfb_slot(node, port->remoteport); |
| |
| |
| } |
| |
| } else if (is_line(node)) { |
| int is_4700_line = is_line_4700(node); |
| |
| for (p = 1; p <= node->numports; p++) { |
| port = node->ports[p]; |
| if (!port || !port->remoteport) |
| continue; |
| |
| if ((is_4700_line && (port->portnum > 18)) || |
| (!is_4700_line && (port->portnum > 12))) |
| continue; |
| |
| |
| get_slb_slot(node, port->remoteport); |
| break; |
| } |
| } |
| |
| |
| for (p = 1; p <= node->numports; p++) { |
| port = node->ports[p]; |
| if (!port) |
| continue; |
| voltaire_portmap(port); |
| } |
| |
| return 0; |
| } |
| |
| static int get_line_index(ibnd_node_t * node) |
| { |
| int retval; |
| |
| if (is_line_4700(node)) |
| retval = node->ch_slotnum; |
| else |
| retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum; |
| |
| if (retval > LINES_MAX_NUM || retval < 1) { |
| printf("%s: retval = %d\n", __FUNCTION__, retval); |
| IBND_ERROR("Internal error\n"); |
| return -1; |
| } |
| return retval; |
| } |
| |
| static int get_spine_index(ibnd_node_t * node) |
| { |
| int retval; |
| |
| if (is_spine_9288(node) || is_spine_2012(node)) |
| retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum; |
| else if (is_spine_4700(node) || is_spine_4700x2(node)) |
| retval = 2 * (node->ch_slotnum - 1) + node->ch_anafanum; |
| else |
| retval = node->ch_slotnum; |
| |
| if (retval > SPINES_MAX_NUM || retval < 1) { |
| IBND_ERROR("Internal error\n"); |
| return -1; |
| } |
| return retval; |
| } |
| |
| static int insert_line_router(ibnd_node_t * node, ibnd_chassis_t * chassis) |
| { |
| int i = get_line_index(node); |
| |
| if (i < 0) |
| return i; |
| |
| if (chassis->linenode[i]) |
| return 0; |
| |
| chassis->linenode[i] = node; |
| node->chassis = chassis; |
| return 0; |
| } |
| |
| static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis) |
| { |
| int i = get_spine_index(node); |
| |
| if (i < 0) |
| return i; |
| |
| if (chassis->spinenode[i]) |
| return 0; |
| |
| chassis->spinenode[i] = node; |
| node->chassis = chassis; |
| return 0; |
| } |
| |
| static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis) |
| { |
| ibnd_node_t *node, *remnode; |
| ibnd_port_t *port; |
| int i, p; |
| |
| for (i = 1; i <= LINES_MAX_NUM; i++) { |
| int is_4700_line; |
| |
| node = chassis->linenode[i]; |
| |
| if (!(node && is_line(node))) |
| continue; |
| |
| is_4700_line = is_line_4700(node); |
| |
| for (p = 1; p <= node->numports; p++) { |
| |
| port = node->ports[p]; |
| if (!port || !port->remoteport) |
| continue; |
| |
| if ((is_4700_line && (port->portnum > 18)) || |
| (!is_4700_line && (port->portnum > 12))) |
| continue; |
| |
| remnode = port->remoteport->node; |
| |
| if (!remnode->ch_found) |
| continue; |
| if (insert_spine(remnode, chassis)) |
| return -1; |
| } |
| } |
| return 0; |
| } |
| |
| static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis) |
| { |
| ibnd_node_t *node, *remnode; |
| ibnd_port_t *port; |
| int i, p; |
| |
| for (i = 1; i <= SPINES_MAX_NUM; i++) { |
| int is_4700x2; |
| |
| node = chassis->spinenode[i]; |
| if (!node) |
| continue; |
| |
| is_4700x2 = is_spine_4700x2(node); |
| |
| for (p = 1; p <= node->numports; p++) { |
| port = node->ports[p]; |
| if (!port || !port->remoteport) |
| continue; |
| |
| |
| |
| |
| |
| if (is_4700x2 && (port->portnum > 18)) |
| continue; |
| |
| remnode = port->remoteport->node; |
| |
| if (!remnode->ch_found) |
| continue; |
| |
| if (insert_line_router(remnode, chassis)) |
| return -1; |
| } |
| } |
| return 0; |
| } |
| |
| |
| |
| |
| |
| static void pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis) |
| { |
| ibnd_node_t *node; |
| int i; |
| |
| for (i = 1; i <= SPINES_MAX_NUM; i++) { |
| node = chassis->spinenode[i]; |
| if (!node) |
| continue; |
| |
| |
| chassis->chassisguid = node->guid - 1; |
| break; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis) |
| { |
| int p = 0; |
| ibnd_node_t *remnode = NULL; |
| ibnd_port_t *port = NULL; |
| |
| |
| if (insert_spine(node, chassis)) |
| return -1; |
| |
| |
| for (p = 1; p <= node->numports; p++) { |
| |
| port = node->ports[p]; |
| if (!port || !port->remoteport) |
| continue; |
| |
| |
| |
| |
| |
| if (is_spine_4700x2(node) && (port->portnum > 18)) |
| continue; |
| |
| remnode = port->remoteport->node; |
| |
| if (!remnode->ch_found) |
| continue; |
| |
| insert_line_router(remnode, chassis); |
| } |
| |
| if (pass_on_lines_catch_spines(chassis)) |
| return -1; |
| |
| |
| if (pass_on_spines_catch_lines(chassis)) |
| return -1; |
| |
| |
| |
| |
| if (pass_on_lines_catch_spines(chassis)) |
| return -1; |
| if (pass_on_spines_catch_lines(chassis)) |
| return -1; |
| pass_on_spines_interpolate_chguid(chassis); |
| |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static int int2ext_map_slb24[2][25] = { |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3, |
| 13, 14, 15}, |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9, |
| 19, 20, 21} |
| }; |
| |
| static int int2ext_map_slb8[2][25] = { |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5, |
| 5}, |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7, |
| 7} |
| }; |
| |
| static int int2ext_map_slb2024[2][25] = { |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, |
| 21, 22, 23, 24}, |
| {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, |
| 11, 12} |
| }; |
| |
| static int int2ext_map_slb4018[37] = { |
| 0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 |
| }; |
| |
| static int int2ext_map_sfb4700x2[2][37] = { |
| {0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12}, |
| {0, |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6} |
| }; |
| |
| |
| |
| |
| static void voltaire_portmap(ibnd_port_t * port) |
| { |
| int portnum = port->portnum; |
| int chipnum = 0; |
| ibnd_node_t *node = port->node; |
| int is_4700_line = is_line_4700(node); |
| int is_4700x2_spine = is_spine_4700x2(node); |
| |
| if (!node->ch_found || (!is_line(node) && !is_4700x2_spine)) { |
| port->ext_portnum = 0; |
| return; |
| } |
| |
| if (((is_4700_line || is_4700x2_spine) && |
| (portnum < 19 || portnum > 36)) || |
| ((!is_4700_line && !is_4700x2_spine) && |
| (portnum < 13 || portnum > 24))) { |
| port->ext_portnum = 0; |
| return; |
| } |
| |
| if (port->node->ch_anafanum < 1 || port->node->ch_anafanum > 2) { |
| port->ext_portnum = 0; |
| return; |
| } |
| |
| chipnum = port->node->ch_anafanum - 1; |
| |
| if (is_line_24(node)) |
| port->ext_portnum = int2ext_map_slb24[chipnum][portnum]; |
| else if (is_line_2024(node)) |
| port->ext_portnum = int2ext_map_slb2024[chipnum][portnum]; |
| |
| else if (is_4700_line) |
| port->ext_portnum = int2ext_map_slb4018[portnum]; |
| |
| else if (is_4700x2_spine) |
| port->ext_portnum = int2ext_map_sfb4700x2[chipnum][portnum]; |
| else |
| port->ext_portnum = int2ext_map_slb8[chipnum][portnum]; |
| } |
| |
| static int add_chassis(chassis_scan_t * chassis_scan) |
| { |
| if (!(chassis_scan->current_chassis = |
| calloc(1, sizeof(ibnd_chassis_t)))) { |
| IBND_ERROR("OOM: failed to allocate chassis object\n"); |
| return -1; |
| } |
| |
| if (chassis_scan->first_chassis == NULL) { |
| chassis_scan->first_chassis = chassis_scan->current_chassis; |
| chassis_scan->last_chassis = chassis_scan->current_chassis; |
| } else { |
| chassis_scan->last_chassis->next = |
| chassis_scan->current_chassis; |
| chassis_scan->last_chassis = chassis_scan->current_chassis; |
| } |
| return 0; |
| } |
| |
| static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node) |
| { |
| node->chassis = chassis; |
| node->next_chassis_node = chassis->nodes; |
| chassis->nodes = node; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| int group_nodes(ibnd_fabric_t * fabric) |
| { |
| ibnd_node_t *node; |
| int chassisnum = 0; |
| ibnd_chassis_t *chassis; |
| ibnd_chassis_t *ch, *ch_next; |
| chassis_scan_t chassis_scan; |
| int vendor_id; |
| |
| chassis_scan.first_chassis = NULL; |
| chassis_scan.current_chassis = NULL; |
| chassis_scan.last_chassis = NULL; |
| |
| |
| |
| |
| |
| for (node = fabric->switches; node; node = node->type_next) { |
| |
| vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F); |
| |
| if (vendor_id == VTR_VENDOR_ID |
| && fill_voltaire_chassis_record(node)) |
| goto cleanup; |
| else if (vendor_id == MLX_VENDOR_ID |
| && fill_mellanox_chassis_record(node)) |
| goto cleanup; |
| |
| } |
| |
| |
| |
| for (node = fabric->switches; node; node = node->type_next) { |
| if (mad_get_field(node->info, 0, |
| IB_NODE_VENDORID_F) != VTR_VENDOR_ID) |
| continue; |
| if (!node->ch_found |
| || (node->chassis && node->chassis->chassisnum) |
| || !is_spine(node)) |
| continue; |
| if (add_chassis(&chassis_scan)) |
| goto cleanup; |
| chassis_scan.current_chassis->chassisnum = ++chassisnum; |
| if (build_chassis(node, chassis_scan.current_chassis)) |
| goto cleanup; |
| } |
| |
| |
| |
| for (node = fabric->nodes; node; node = node->next) { |
| if (mad_get_field(node->info, 0, |
| IB_NODE_VENDORID_F) == VTR_VENDOR_ID) |
| continue; |
| if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) { |
| chassis = find_chassisguid(fabric, node); |
| if (chassis) |
| chassis->nodecount++; |
| else { |
| |
| if (add_chassis(&chassis_scan)) |
| goto cleanup; |
| chassis_scan.current_chassis->chassisguid = |
| get_chassisguid(node); |
| chassis_scan.current_chassis->nodecount = 1; |
| if (!fabric->chassis) |
| fabric->chassis = chassis_scan.first_chassis; |
| } |
| } |
| } |
| |
| |
| |
| for (node = fabric->nodes; node; node = node->next) { |
| |
| vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F); |
| |
| if (vendor_id == VTR_VENDOR_ID) |
| continue; |
| if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) { |
| chassis = find_chassisguid(fabric, node); |
| if (chassis && chassis->nodecount > 1) { |
| if (!chassis->chassisnum) |
| chassis->chassisnum = ++chassisnum; |
| if (!node->ch_found) { |
| node->ch_found = 1; |
| add_node_to_chassis(chassis, node); |
| } |
| else if (vendor_id == MLX_VENDOR_ID){ |
| insert_mellanox_line_and_spine(node, chassis); |
| } |
| } |
| } |
| } |
| |
| fabric->chassis = chassis_scan.first_chassis; |
| return 0; |
| |
| cleanup: |
| ch = chassis_scan.first_chassis; |
| while (ch) { |
| ch_next = ch->next; |
| free(ch); |
| ch = ch_next; |
| } |
| fabric->chassis = NULL; |
| return -1; |
| } |