/* This function called for every Voltaire node in fabric It could be optimized so, but time overhead is very small and its only diag.util */ static void fill_chassis_record(Node *node) { Port *port; Node *remnode = 0; ChassisRecord *ch = 0; if (node->chrecord) /* somehow this node has already been passed */ return; if (!(node->chrecord = calloc(1, sizeof(ChassisRecord)))) IBPANIC("out of mem"); ch = node->chrecord; /* node is router only in case of using unique lid */ /* (which is lid of chassis router port) */ /* in such case node->ports is actually a requested port... */ if (is_router(node) && is_spine(node->ports->remoteport->node)) get_router_slot(node, node->ports->remoteport); else if (is_spine(node)) { for (port = node->ports; port; port = port->next) { if (!port->remoteport) continue; remnode = port->remoteport->node; if (remnode->type != SWITCH_NODE) { if (!remnode->chrecord) get_router_slot(remnode, port); continue; } if (!ch->chassistype) /* we assume here that remoteport belongs to line */ get_sfb_slot(node, port->remoteport); /* we could break here, but need to find if more routers connected */ } } else if (is_line(node)) { for (port = node->ports; port; port = port->next) { if (port->portnum > 12) continue; if (!port->remoteport) continue; /* we assume here that remoteport belongs to spine */ get_slb_slot(ch, port->remoteport); break; } } return; }
/* This function called for every Voltaire node in fabric It could be optimized so, but time overhead is very small and its only diag.util */ static int fill_voltaire_chassis_record(ibnd_node_t * node) { int p = 0; ibnd_port_t *port; ibnd_node_t *remnode = 0; if (node->ch_found) /* somehow this node has already been passed */ return 0; node->ch_found = 1; /* node is router only in case of using unique lid */ /* (which is lid of chassis router port) */ /* in such case node->ports is actually a requested port... */ if (is_router(node)) /* find the remote 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; /* * Skip ISR4700 double density fabric boards ports 19-36 * as they are chassis external ports */ 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) /* we assume here that remoteport belongs to line */ get_sfb_slot(node, port->remoteport); /* we could break here, but need to find if more routers connected */ } } 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; /* we assume here that remoteport belongs to spine */ get_slb_slot(node, port->remoteport); break; } } /* for each port of this node, map external ports */ for (p = 1; p <= node->numports; p++) { port = node->ports[p]; if (!port) continue; voltaire_portmap(port); } return 0; }
int is_chassis_switch(ibnd_node_t * n) { return (is_spine(n) || is_line(n)); }
/* Main grouping function Algorithm: 1. pass on every Voltaire node 2. catch spine chip for every Voltaire node 2.1 build/interpolate chassis around this chip 2.2 go to 1. 3. pass on non Voltaire nodes (SystemImageGUID based grouping) 4. now group non Voltaire nodes by SystemImageGUID Returns: 0 on success, -1 on failure */ 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; /* 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) { 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 */ /* algorithm: catch spine and find all surrounding nodes */ 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; } /* now make pass on nodes for chassis which are not Voltaire */ /* grouped by common SystemImageGUID */ 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 { /* Possible new chassis */ 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; } } } /* 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) { 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; }
/* Main grouping function Algorithm: 1. pass on every Voltaire node 2. catch spine chip for every Voltaire node 2.1 build/interpolate chassis around this chip 2.2 go to 1. 3. pass on non Voltaire nodes (SystemImageGUID based grouping) 4. now group non Voltaire nodes by SystemImageGUID */ ChassisList *group_nodes() { Node *node; int dist; int chassisnum = 0; struct ChassisList *chassis; mylist.first = NULL; mylist.current = NULL; mylist.last = NULL; /* 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 (dist = 0; dist <= maxhops_discovered; dist++) { for (node = nodesdist[dist]; node; node = node->dnext) { if (node->vendid == VTR_VENDOR_ID) fill_chassis_record(node); } } /* separate every Voltaire chassis from each other and build linked list of them */ /* algorithm: catch spine and find all surrounding nodes */ for (dist = 0; dist <= maxhops_discovered; dist++) { for (node = nodesdist[dist]; node; node = node->dnext) { if (node->vendid != VTR_VENDOR_ID) continue; if (!node->chrecord || node->chrecord->chassisnum || !is_spine(node)) continue; add_chassislist(); mylist.current->chassisnum = ++chassisnum; build_chassis(node, mylist.current); } } /* now make pass on nodes for chassis which are not Voltaire */ /* grouped by common SystemImageGUID */ for (dist = 0; dist <= maxhops_discovered; dist++) { for (node = nodesdist[dist]; node; node = node->dnext) { if (node->vendid == VTR_VENDOR_ID) continue; if (node->sysimgguid) { chassis = find_chassisguid(node); if (chassis) chassis->nodecount++; else { /* Possible new chassis */ add_chassislist(); mylist.current->chassisguid = get_chassisguid(node); mylist.current->nodecount = 1; } } } } /* now, make another pass to see which nodes are part of chassis */ /* (defined as chassis->nodecount > 1) */ for (dist = 0; dist <= MAXHOPS; ) { for (node = nodesdist[dist]; node; node = node->dnext) { if (node->vendid == VTR_VENDOR_ID) continue; if (node->sysimgguid) { chassis = find_chassisguid(node); if (chassis && chassis->nodecount > 1) { if (!chassis->chassisnum) chassis->chassisnum = ++chassisnum; if (!node->chrecord) { if (!(node->chrecord = calloc(1, sizeof(ChassisRecord)))) IBPANIC("out of mem"); node->chrecord->chassisnum = chassis->chassisnum; } } } } if (dist == maxhops_discovered) dist = MAXHOPS; /* skip to CAs */ else dist++; } return (mylist.first); }
int is_chassis_switch(Node *node) { return (is_spine(node) || is_line(node)); }