>From f1c92f4cae5605dec338b52ac6b261ddbe6e5609 Mon Sep 17 00:00:00 2001 From: Tamir Ronen <tam...@voltaire.com> Date: Tue, 8 Feb 2011 13:01:22 +0200 Subject: [PATCH] add support for ibnetdiscover grouping for Mellanox switches
Group Mellanox switches to the same chassis using SYSTEM_GUID Use the node description format: 'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>' to identify system type, slot type Line/Spine, slotnum and anafanum. Map Line ports 1-18 as external ports 1-18. --- .../libibnetdisc/include/infiniband/ibnetdisc.h | 3 + infiniband-diags/libibnetdisc/src/chassis.c | 220 ++++++++++++++++++- infiniband-diags/libibnetdisc/src/chassis.h | 3 + 3 files changed, 214 insertions(+), 12 deletions(-) diff --git a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h index 935e427..1efd1d6 100644 --- a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h +++ b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h @@ -43,6 +43,8 @@ struct ibnd_chassis; /* forward declare */ struct ibnd_port; /* forward declare */ +#define CHASSIS_TYPE_SIZE 20 + /** ========================================================================= * Node */ @@ -80,6 +82,7 @@ typedef struct ibnd_node { struct ibnd_node *next_chassis_node; /* next node in ibnd_chassis_t->nodes */ struct ibnd_chassis *chassis; /* if != NULL the chassis this node belongs to */ unsigned char ch_type; + char ch_type_str[CHASSIS_TYPE_SIZE]; unsigned char ch_anafanum; unsigned char ch_slotnum; unsigned char ch_slot; diff --git a/infiniband-diags/libibnetdisc/src/chassis.c b/infiniband-diags/libibnetdisc/src/chassis.c index 6bfc45b..3d90034 100644 --- a/infiniband-diags/libibnetdisc/src/chassis.c +++ b/infiniband-diags/libibnetdisc/src/chassis.c @@ -62,30 +62,53 @@ typedef struct chassis_scan { char *ibnd_get_chassis_type(ibnd_node_t * node) { + int chassis_type; + if (!node) { IBND_DEBUG("node parameter NULL\n"); return NULL; } - /* Currently, only if Voltaire chassis */ - if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID) - return NULL; if (!node->chassis) return NULL; - if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT) - return NULL; - return ChassisTypeStr[node->ch_type]; + + chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F); + + switch (chassis_type) + { + case VTR_VENDOR_ID: /* Voltaire chassis */ + { + 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; } - /* Currently, only if Voltaire chassis */ - if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID) + /* Currently, only if Voltaire or Mellanox chassis */ + 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; @@ -574,6 +597,166 @@ static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport) return 0; } + +/* + This function called for every Mellanox node in fabric +*/ +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; + + /* + The node description has the following format: + + 'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>' + + - System slot name in our systems can be L[01-36] , S[01-18] + - Node index is always 1 (we don.t have boards with multiple IS4 chips). + - System name is taken from the currently configured host name. + -The board type is optional and we don.t set it currently - A leaf or spine slot can currently hold a single type of board. + */ + + 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) /* somehow this node has already been passed */ + return 0; + + /* All mellanox IS4 switches have the same vendor id*/ + 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; + } + + /* parse system name*/ + 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++; + /* parse system type*/ + 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++; + /* parse system slot name*/ + 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; + } + + /* set Chip number (node index) */ + node->ch_anafanum = atoi(&node_index[1]); + if(node->ch_anafanum != 1){ + IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum); + } + + + /* set Line Spine numbers */ + 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; + } + + /* The switch will be displayed under Line or Spine and not under Chassis switches */ + node->ch_found = 1; + + node->ch_slotnum = 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; + } + + /*set ch_type_str*/ + strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1); + + /* Line ports 1-18 are mapped to external ports 1-18*/ + 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; /* already filled slot */ + + chassis->linenode[node->ch_slotnum] = node; + } + else if (node->ch_slot == SPINE_CS){ + + if (chassis->spinenode[node->ch_slotnum]) + return 0; /* already filled slot */ + + chassis->spinenode[node->ch_slotnum] = node; + } + else + return 0; + + node->chassis = chassis; + + return 0; +} + + /* forward declare this */ static void voltaire_portmap(ibnd_port_t * port); /* @@ -1064,15 +1247,23 @@ int group_nodes(ibnd_fabric_t * fabric) chassis_scan.current_chassis = NULL; chassis_scan.last_chassis = NULL; + int vendor_id; + /* first pass on switches and build for every Voltaire node */ /* an appropriate chassis record (slotnum and position) */ /* according to internal connectivity */ /* not very efficient but clear code so... */ for (node = fabric->switches; node; node = node->type_next) { - if (mad_get_field(node->info, 0, - IB_NODE_VENDORID_F) == VTR_VENDOR_ID + + 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; + } /* separate every Voltaire chassis from each other and build linked list of them */ @@ -1118,8 +1309,10 @@ int group_nodes(ibnd_fabric_t * fabric) /* now, make another pass to see which nodes are part of chassis */ /* (defined as chassis->nodecount > 1) */ for (node = fabric->nodes; node; node = node->next) { - if (mad_get_field(node->info, 0, - IB_NODE_VENDORID_F) == VTR_VENDOR_ID) + + 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); @@ -1130,6 +1323,9 @@ int group_nodes(ibnd_fabric_t * fabric) node->ch_found = 1; add_node_to_chassis(chassis, node); } + else if (vendor_id == MLX_VENDOR_ID){ + insert_mellanox_line_and_spine(node, chassis); + } } } } diff --git a/infiniband-diags/libibnetdisc/src/chassis.h b/infiniband-diags/libibnetdisc/src/chassis.h index 004156e..7a91be3 100644 --- a/infiniband-diags/libibnetdisc/src/chassis.h +++ b/infiniband-diags/libibnetdisc/src/chassis.h @@ -75,8 +75,11 @@ #define VTR_DEVID_SFB4700X2 0x5a5d #define VTR_DEVID_SFB4200 0x5a60 +#define MLX_DEVID_IS4 0xbd36 + /* Vendor IDs (for chassis based systems) */ #define VTR_VENDOR_ID 0x8f1 /* Voltaire */ +#define MLX_VENDOR_ID 0x2c9 /* Mellanox */ #define TS_VENDOR_ID 0x5ad /* Cisco */ #define SS_VENDOR_ID 0x66a /* InfiniCon */ #define XS_VENDOR_ID 0x1397 /* Xsigo */ -- 1.5.5.6 -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html