Blame libibnetdisc/src/chassis.c

Packit db064d
/*
Packit db064d
 * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
Packit db064d
 * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
Packit db064d
 * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
Packit db064d
 * Copyright (c) 2010 HNR Consulting.  All rights reserved.
Packit db064d
 *
Packit db064d
 * This software is available to you under a choice of one of two
Packit db064d
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit db064d
 * General Public License (GPL) Version 2, available from the file
Packit db064d
 * COPYING in the main directory of this source tree, or the
Packit db064d
 * OpenIB.org BSD license below:
Packit db064d
 *
Packit db064d
 *     Redistribution and use in source and binary forms, with or
Packit db064d
 *     without modification, are permitted provided that the following
Packit db064d
 *     conditions are met:
Packit db064d
 *
Packit db064d
 *      - Redistributions of source code must retain the above
Packit db064d
 *        copyright notice, this list of conditions and the following
Packit db064d
 *        disclaimer.
Packit db064d
 *
Packit db064d
 *      - Redistributions in binary form must reproduce the above
Packit db064d
 *        copyright notice, this list of conditions and the following
Packit db064d
 *        disclaimer in the documentation and/or other materials
Packit db064d
 *        provided with the distribution.
Packit db064d
 *
Packit db064d
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit db064d
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit db064d
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit db064d
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit db064d
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit db064d
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit db064d
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit db064d
 * SOFTWARE.
Packit db064d
 *
Packit db064d
 */
Packit db064d
Packit db064d
/*========================================================*/
Packit db064d
/*               FABRIC SCANNER SPECIFIC DATA             */
Packit db064d
/*========================================================*/
Packit db064d
Packit db064d
#if HAVE_CONFIG_H
Packit db064d
#include <config.h>
Packit db064d
#endif				/* HAVE_CONFIG_H */
Packit db064d
Packit db064d
#include <stdlib.h>
Packit db064d
#include <inttypes.h>
Packit db064d
Packit db064d
#include <infiniband/mad.h>
Packit db064d
Packit db064d
#include "internal.h"
Packit db064d
#include "chassis.h"
Packit db064d
Packit db064d
static const char * const ChassisTypeStr[] =
Packit db064d
{ "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700", "ISR4200" };
Packit db064d
static const char * const ChassisSlotTypeStr[] = { "", "Line", "Spine", "SRBD" };
Packit db064d
Packit db064d
typedef struct chassis_scan {
Packit db064d
	ibnd_chassis_t *first_chassis;
Packit db064d
	ibnd_chassis_t *current_chassis;
Packit db064d
	ibnd_chassis_t *last_chassis;
Packit db064d
} chassis_scan_t;
Packit db064d
Packit db064d
const char *ibnd_get_chassis_type(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	int chassis_type;
Packit db064d
Packit db064d
	if (!node) {
Packit db064d
		IBND_DEBUG("node parameter NULL\n");
Packit db064d
		return NULL;
Packit db064d
	}
Packit db064d
Packit db064d
	if (!node->chassis)
Packit db064d
		return NULL;
Packit db064d
Packit db064d
	chassis_type = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
Packit db064d
Packit db064d
	switch (chassis_type)
Packit db064d
	{
Packit db064d
		case VTR_VENDOR_ID: /* Voltaire chassis */
Packit db064d
		{
Packit db064d
			if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4200_CT)
Packit db064d
				return NULL;
Packit db064d
			return ChassisTypeStr[node->ch_type];
Packit db064d
		}
Packit db064d
		case MLX_VENDOR_ID:
Packit db064d
		{
Packit db064d
			if (node->ch_type_str[0] == '\0')
Packit db064d
				return NULL;
Packit db064d
			return node->ch_type_str;
Packit db064d
		}
Packit db064d
		default:
Packit db064d
		{
Packit db064d
			break;
Packit db064d
		}
Packit db064d
	}
Packit db064d
	return NULL;
Packit db064d
}
Packit db064d
Packit db064d
char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size)
Packit db064d
{
Packit db064d
	int vendor_id;
Packit db064d
Packit db064d
	if (!node) {
Packit db064d
		IBND_DEBUG("node parameter NULL\n");
Packit db064d
		return NULL;
Packit db064d
	}
Packit db064d
Packit db064d
	/* Currently, only if Voltaire or Mellanox chassis */
Packit db064d
	vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
Packit db064d
Packit db064d
	if ((vendor_id != VTR_VENDOR_ID) && (vendor_id != MLX_VENDOR_ID))
Packit db064d
		return NULL;
Packit db064d
	if (!node->chassis)
Packit db064d
		return NULL;
Packit db064d
	if (node->ch_slot == UNRESOLVED_CS || node->ch_slot > SRBD_CS)
Packit db064d
		return NULL;
Packit db064d
	if (!str)
Packit db064d
		return NULL;
Packit db064d
	snprintf(str, size, "%s %d Chip %d", ChassisSlotTypeStr[node->ch_slot],
Packit db064d
		 node->ch_slotnum, node->ch_anafanum);
Packit db064d
	return str;
Packit db064d
}
Packit db064d
Packit db064d
static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric,
Packit db064d
				       unsigned char chassisnum)
Packit db064d
{
Packit db064d
	ibnd_chassis_t *current;
Packit db064d
Packit db064d
	for (current = fabric->chassis; current; current = current->next)
Packit db064d
		if (current->chassisnum == chassisnum)
Packit db064d
			return current;
Packit db064d
Packit db064d
	return NULL;
Packit db064d
}
Packit db064d
Packit db064d
static uint64_t topspin_chassisguid(uint64_t guid)
Packit db064d
{
Packit db064d
	/* Byte 3 in system image GUID is chassis type, and */
Packit db064d
	/* Byte 4 is location ID (slot) so just mask off byte 4 */
Packit db064d
	return guid & 0xffffffff00ffffffULL;
Packit db064d
}
Packit db064d
Packit db064d
int ibnd_is_xsigo_guid(uint64_t guid)
Packit db064d
{
Packit db064d
	if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL)
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int is_xsigo_leafone(uint64_t guid)
Packit db064d
{
Packit db064d
	if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL)
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
int ibnd_is_xsigo_hca(uint64_t guid)
Packit db064d
{
Packit db064d
	/* NodeType 2 is HCA */
Packit db064d
	if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL)
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
int ibnd_is_xsigo_tca(uint64_t guid)
Packit db064d
{
Packit db064d
	/* NodeType 3 is TCA */
Packit db064d
	if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL)
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int is_xsigo_ca(uint64_t guid)
Packit db064d
{
Packit db064d
	if (ibnd_is_xsigo_hca(guid) || ibnd_is_xsigo_tca(guid))
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int is_xsigo_switch(uint64_t guid)
Packit db064d
{
Packit db064d
	if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL)
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static uint64_t xsigo_chassisguid(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	uint64_t sysimgguid =
Packit db064d
	    mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
Packit db064d
	uint64_t remote_sysimgguid;
Packit db064d
Packit db064d
	if (!is_xsigo_ca(sysimgguid)) {
Packit db064d
		/* Byte 3 is NodeType and byte 4 is PortType */
Packit db064d
		/* If NodeType is 1 (switch), PortType is masked */
Packit db064d
		if (is_xsigo_switch(sysimgguid))
Packit db064d
			return sysimgguid & 0xffffffff00ffffffULL;
Packit db064d
		else
Packit db064d
			return sysimgguid;
Packit db064d
	} else {
Packit db064d
		if (!node->ports || !node->ports[1])
Packit db064d
			return 0;
Packit db064d
Packit db064d
		/* Is there a peer port ? */
Packit db064d
		if (!node->ports[1]->remoteport)
Packit db064d
			return sysimgguid;
Packit db064d
Packit db064d
		/* If peer port is Leaf 1, use its chassis GUID */
Packit db064d
		remote_sysimgguid =
Packit db064d
		    mad_get_field64(node->ports[1]->remoteport->node->info, 0,
Packit db064d
				    IB_NODE_SYSTEM_GUID_F);
Packit db064d
		if (is_xsigo_leafone(remote_sysimgguid))
Packit db064d
			return remote_sysimgguid & 0xffffffff00ffffffULL;
Packit db064d
		else
Packit db064d
			return sysimgguid;
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
static uint64_t get_chassisguid(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	uint32_t vendid = mad_get_field(node->info, 0, IB_NODE_VENDORID_F);
Packit db064d
	uint64_t sysimgguid =
Packit db064d
	    mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
Packit db064d
Packit db064d
	if (vendid == TS_VENDOR_ID || vendid == SS_VENDOR_ID)
Packit db064d
		return topspin_chassisguid(sysimgguid);
Packit db064d
	else if (vendid == XS_VENDOR_ID || ibnd_is_xsigo_guid(sysimgguid))
Packit db064d
		return xsigo_chassisguid(node);
Packit db064d
	else
Packit db064d
		return sysimgguid;
Packit db064d
}
Packit db064d
Packit db064d
static ibnd_chassis_t *find_chassisguid(ibnd_fabric_t * fabric,
Packit db064d
					ibnd_node_t * node)
Packit db064d
{
Packit db064d
	ibnd_chassis_t *current;
Packit db064d
	uint64_t chguid;
Packit db064d
Packit db064d
	chguid = get_chassisguid(node);
Packit db064d
	for (current = fabric->chassis; current; current = current->next)
Packit db064d
		if (current->chassisguid == chguid)
Packit db064d
			return current;
Packit db064d
Packit db064d
	return NULL;
Packit db064d
}
Packit db064d
Packit db064d
uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric, unsigned char chassisnum)
Packit db064d
{
Packit db064d
	ibnd_chassis_t *chassis;
Packit db064d
Packit db064d
	if (!fabric) {
Packit db064d
		IBND_DEBUG("fabric parameter NULL\n");
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	chassis = find_chassisnum(fabric, chassisnum);
Packit db064d
	if (chassis)
Packit db064d
		return chassis->chassisguid;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int is_router(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_IB_FC_ROUTER ||
Packit db064d
		devid == VTR_DEVID_IB_IP_ROUTER);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_9096(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB4 || devid == VTR_DEVID_SFB4_DDR);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_9288(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB12 || devid == VTR_DEVID_SFB12_DDR);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_2004(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB2004);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_2012(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB2012);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_4700(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB4700);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_4700x2(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB4700X2);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine_4200(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SFB4200);
Packit db064d
}
Packit db064d
Packit db064d
static int is_spine(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	return (is_spine_9096(n) || is_spine_9288(n) ||
Packit db064d
		is_spine_2004(n) || is_spine_2012(n) ||
Packit db064d
		is_spine_4700(n) || is_spine_4700x2(n) ||
Packit db064d
		is_spine_4200(n));
Packit db064d
}
Packit db064d
Packit db064d
static int is_line_24(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SLB24 ||
Packit db064d
		devid == VTR_DEVID_SLB24_DDR || devid == VTR_DEVID_SRB2004);
Packit db064d
}
Packit db064d
Packit db064d
static int is_line_8(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SLB8);
Packit db064d
}
Packit db064d
Packit db064d
static int is_line_2024(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SLB2024);
Packit db064d
}
Packit db064d
Packit db064d
static int is_line_4700(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
Packit db064d
	return (devid == VTR_DEVID_SLB4018);
Packit db064d
}
Packit db064d
Packit db064d
static int is_line(ibnd_node_t * n)
Packit db064d
{
Packit db064d
	return (is_line_24(n) || is_line_8(n) ||
Packit db064d
		is_line_2024(n) || is_line_4700(n));
Packit db064d
}
Packit db064d
Packit db064d
/* these structs help find Line (Anafa) slot number while using spine portnum */
Packit db064d
static const char line_slot_2_sfb4[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
Packit db064d
	4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
static const char anafa_line_slot_2_sfb4[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2,
Packit db064d
	1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
static const char line_slot_2_sfb12[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
Packit db064d
	10, 10, 11, 11, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
static const char anafa_line_slot_2_sfb12[37] = {
Packit db064d
	0,
Packit db064d
	1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
Packit db064d
	1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/* LB slot = table[spine port] */
Packit db064d
static const char line_slot_2_sfb18[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
Packit db064d
	10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18};
Packit db064d
/* LB asic num = table[spine port] */
Packit db064d
static const char anafa_line_slot_2_sfb18[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Packit db064d
};
Packit db064d
Packit db064d
/* LB slot = table[spine port] */
Packit db064d
static const char line_slot_2_sfb18x2[37] = {
Packit db064d
	0,
Packit db064d
	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
Packit db064d
/* LB asic num = table[spine port] */
Packit db064d
static const char anafa_line_slot_2_sfb18x2[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/* LB slot = table[spine port] */
Packit db064d
static const char line_slot_2_sfb4200[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,
Packit db064d
	5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9};
Packit db064d
/* LB asic num = table[spine port] */
Packit db064d
static const char anafa_line_slot_2_sfb4200[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Packit db064d
};
Packit db064d
Packit db064d
/* IPR FCR modules connectivity while using sFB4 port as reference */
Packit db064d
static const char ipr_slot_2_sfb4_port[37] = {
Packit db064d
	0,
Packit db064d
	3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1,
Packit db064d
	3, 2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/* these structs help find Spine (Anafa) slot number while using spine portnum */
Packit db064d
static const char spine12_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
static const char anafa_spine12_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
static const char spine4_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
static const char anafa_spine4_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/* FB slot = table[line port] */
Packit db064d
static const char spine18_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
/* FB asic = table[line port] */
Packit db064d
static const char anafa_spine18_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
static const char anafa_spine18x2_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/* FB slot = table[line port] */
Packit db064d
static const char sfb4200_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
/* FB asic = table[line port] */
Packit db064d
static const char anafa_sfb4200_slot_2_slb[37] = {
Packit db064d
	0,
Packit db064d
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit db064d
};
Packit db064d
Packit db064d
/*	reference                     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
Packit db064d
Packit db064d
static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport)
Packit db064d
{
Packit db064d
	n->ch_slot = SPINE_CS;
Packit db064d
	if (is_spine_9096(n)) {
Packit db064d
		n->ch_type = ISR9096_CT;
Packit db064d
		n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_9288(n)) {
Packit db064d
		n->ch_type = ISR9288_CT;
Packit db064d
		n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_2012(n)) {
Packit db064d
		n->ch_type = ISR2012_CT;
Packit db064d
		n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_2004(n)) {
Packit db064d
		n->ch_type = ISR2004_CT;
Packit db064d
		n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_4700(n)) {
Packit db064d
		n->ch_type = ISR4700_CT;
Packit db064d
		n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine18_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_4700x2(n)) {
Packit db064d
		n->ch_type = ISR4700_CT;
Packit db064d
		n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum];
Packit db064d
	} else if (is_spine_4200(n)) {
Packit db064d
		n->ch_type = ISR4200_CT;
Packit db064d
		n->ch_slotnum = sfb4200_slot_2_slb[lineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_sfb4200_slot_2_slb[lineport->portnum];
Packit db064d
	} else {
Packit db064d
		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
Packit db064d
			   n->guid);
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
Packit db064d
{
Packit db064d
	uint64_t guessnum = 0;
Packit db064d
Packit db064d
	n->ch_found = 1;
Packit db064d
Packit db064d
	n->ch_slot = SRBD_CS;
Packit db064d
	if (is_spine_9096(spineport->node)) {
Packit db064d
		n->ch_type = ISR9096_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
Packit db064d
		n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
Packit db064d
	} else if (is_spine_9288(spineport->node)) {
Packit db064d
		n->ch_type = ISR9288_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
Packit db064d
		/* this is a smart guess based on nodeguids order on sFB-12 module */
Packit db064d
		guessnum = spineport->node->guid % 4;
Packit db064d
		/* module 1 <--> remote anafa 3 */
Packit db064d
		/* module 2 <--> remote anafa 2 */
Packit db064d
		/* module 3 <--> remote anafa 1 */
Packit db064d
		n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
Packit db064d
	} else if (is_spine_2012(spineport->node)) {
Packit db064d
		n->ch_type = ISR2012_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
Packit db064d
		/* this is a smart guess based on nodeguids order on sFB-12 module */
Packit db064d
		guessnum = spineport->node->guid % 4;
Packit db064d
		// module 1 <--> remote anafa 3
Packit db064d
		// module 2 <--> remote anafa 2
Packit db064d
		// module 3 <--> remote anafa 1
Packit db064d
		n->ch_anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));
Packit db064d
	} else if (is_spine_2004(spineport->node)) {
Packit db064d
		n->ch_type = ISR2004_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
Packit db064d
		n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
Packit db064d
	} else {
Packit db064d
		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
Packit db064d
			   spineport->node->guid);
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
Packit db064d
{
Packit db064d
	n->ch_slot = LINE_CS;
Packit db064d
	if (is_spine_9096(spineport->node)) {
Packit db064d
		n->ch_type = ISR9096_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
Packit db064d
	} else if (is_spine_9288(spineport->node)) {
Packit db064d
		n->ch_type = ISR9288_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
Packit db064d
	} else if (is_spine_2012(spineport->node)) {
Packit db064d
		n->ch_type = ISR2012_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb12[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb12[spineport->portnum];
Packit db064d
	} else if (is_spine_2004(spineport->node)) {
Packit db064d
		n->ch_type = ISR2004_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
Packit db064d
	} else if (is_spine_4700(spineport->node)) {
Packit db064d
		n->ch_type = ISR4700_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb18[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb18[spineport->portnum];
Packit db064d
	} else if (is_spine_4700x2(spineport->node)) {
Packit db064d
		n->ch_type = ISR4700_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum];
Packit db064d
	} else if (is_spine_4200(spineport->node)) {
Packit db064d
		n->ch_type = ISR4200_CT;
Packit db064d
		n->ch_slotnum = line_slot_2_sfb4200[spineport->portnum];
Packit db064d
		n->ch_anafanum = anafa_line_slot_2_sfb4200[spineport->portnum];
Packit db064d
	} else {
Packit db064d
		IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
Packit db064d
			   spineport->node->guid);
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
Packit db064d
/*
Packit db064d
	This function called for every Mellanox node in fabric
Packit db064d
*/
Packit db064d
static int fill_mellanox_chassis_record(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	int p = 0;
Packit db064d
	ibnd_port_t *port;
Packit db064d
Packit db064d
	char node_desc[IB_SMP_DATA_SIZE];
Packit db064d
	char *system_name;
Packit db064d
	char *system_type;
Packit db064d
	char *system_slot_name;
Packit db064d
	char *node_index;
Packit db064d
	char *iter;
Packit db064d
	int dev_id;
Packit db064d
Packit db064d
	/*
Packit db064d
	The node description has the following format:
Packit db064d
Packit db064d
	'MF0;<system name>:<system type>/<system slot name>[:board type]/U<node index>'
Packit db064d
Packit db064d
     - System slot name in our systems can be L[01-36] , S[01-18]
Packit db064d
     - Node index is always 1 (we don.t have boards with multiple IS4 chips).
Packit db064d
     - System name is taken from the currently configured host name.
Packit db064d
     -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.
Packit db064d
	 */
Packit db064d
Packit db064d
	memcpy(node_desc, node->nodedesc, IB_SMP_DATA_SIZE);
Packit db064d
Packit db064d
	IBND_DEBUG("fill_mellanox_chassis_record: node_desc:%s \n",node_desc);
Packit db064d
Packit db064d
	if (node->ch_found)	/* somehow this node has already been passed */
Packit db064d
		return 0;
Packit db064d
Packit db064d
	/* All mellanox IS4 switches have the same vendor id*/
Packit db064d
	dev_id = mad_get_field(node->info, 0,IB_NODE_DEVID_F);
Packit db064d
	if (dev_id != MLX_DEVID_IS4)
Packit db064d
		return 0;
Packit db064d
Packit db064d
	if((node_desc[0] != 'M') ||
Packit db064d
	   (node_desc[1] != 'F') ||
Packit db064d
	   (node_desc[2] != '0') ||
Packit db064d
	   (node_desc[3] != ';')) {
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s \n",node_desc);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	/* parse system name*/
Packit db064d
	system_name = &node_desc[4];
Packit db064d
	for (iter = system_name ; (*iter != ':') && (*iter != '\0') ; iter++);
Packit db064d
	if(*iter == '\0'){
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_name failed) \n",node_desc);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
	*iter = '\0';
Packit db064d
	iter++;
Packit db064d
	/* parse system type*/
Packit db064d
	system_type = iter;
Packit db064d
	for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
Packit db064d
	if(*iter == '\0'){
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_type failed) \n",node_desc);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
	*iter = '\0';
Packit db064d
	iter++;
Packit db064d
	/* parse system slot name*/
Packit db064d
	system_slot_name = iter;
Packit db064d
	for ( ; (*iter != '/') && (*iter != ':') && (*iter != '\0') ; iter++);
Packit db064d
	if(*iter == '\0'){
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get system_slot_name failed) \n",node_desc);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
	if(*iter == ':'){
Packit db064d
		*iter = '\0';
Packit db064d
		iter++;
Packit db064d
		for ( ; (*iter != '/') && (*iter != '\0') ; iter++);
Packit db064d
		if(*iter == '\0'){
Packit db064d
			IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get board type failed) \n",node_desc);
Packit db064d
			return 0;
Packit db064d
		}
Packit db064d
	}
Packit db064d
	*iter = '\0';
Packit db064d
	iter++;
Packit db064d
	node_index = iter;
Packit db064d
	if(node_index[0] != 'U'){
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported node description format:%s - (get node index) \n",node_desc);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	/* set Chip number (node index) */
Packit db064d
	node->ch_anafanum = (unsigned char) atoi(&node_index[1]);
Packit db064d
	if(node->ch_anafanum != 1){
Packit db064d
		IBND_DEBUG("Unexpected Chip number:%d \n",node->ch_anafanum);
Packit db064d
	}
Packit db064d
Packit db064d
Packit db064d
	/* set Line Spine numbers */
Packit db064d
	if(system_slot_name[0] == 'L')
Packit db064d
		node->ch_slot = LINE_CS;
Packit db064d
	else if(system_slot_name[0] == 'S')
Packit db064d
		node->ch_slot = SPINE_CS;
Packit db064d
	else{
Packit db064d
		IBND_DEBUG("fill_mellanox_chassis_record: Unsupported system_slot_name:%s \n",system_slot_name);
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	/* The switch will be displayed under Line or Spine and not under Chassis switches */
Packit db064d
	node->ch_found = 1;
Packit db064d
Packit db064d
	node->ch_slotnum = (unsigned char) atoi(&system_slot_name[1]);
Packit db064d
	if((node->ch_slot == LINE_CS && (node->ch_slotnum >  (LINES_MAX_NUM + 1))) ||
Packit db064d
	   (node->ch_slot == SPINE_CS && (node->ch_slotnum > (SPINES_MAX_NUM + 1)))){
Packit db064d
		IBND_ERROR("fill_mellanox_chassis_record: invalid slot number:%d \n",node->ch_slotnum);
Packit db064d
		node->ch_slotnum = 0;
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	/*set ch_type_str*/
Packit db064d
	strncpy(node->ch_type_str , system_type, sizeof(node->ch_type_str)-1);
Packit db064d
Packit db064d
	/* Line ports 1-18 are mapped to external ports 1-18*/
Packit db064d
	if(node->ch_slot == LINE_CS)
Packit db064d
	{
Packit db064d
		for (p = 1; p <= node->numports && p <= 18 ; p++) {
Packit db064d
			port = node->ports[p];
Packit db064d
			if (!port)
Packit db064d
				continue;
Packit db064d
			port->ext_portnum = p;
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int insert_mellanox_line_and_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	if (node->ch_slot == LINE_CS){
Packit db064d
Packit db064d
		if (chassis->linenode[node->ch_slotnum])
Packit db064d
			return 0;	/* already filled slot */
Packit db064d
Packit db064d
		chassis->linenode[node->ch_slotnum] = node;
Packit db064d
	}
Packit db064d
	else if (node->ch_slot == SPINE_CS){
Packit db064d
Packit db064d
		if (chassis->spinenode[node->ch_slotnum])
Packit db064d
			return 0;	/* already filled slot */
Packit db064d
Packit db064d
		chassis->spinenode[node->ch_slotnum] = node;
Packit db064d
	}
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
Packit db064d
	node->chassis = chassis;
Packit db064d
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
Packit db064d
/* forward declare this */
Packit db064d
static void voltaire_portmap(ibnd_port_t * port);
Packit db064d
/*
Packit db064d
	This function called for every Voltaire node in fabric
Packit db064d
	It could be optimized so, but time overhead is very small
Packit db064d
	and its only diag.util
Packit db064d
*/
Packit db064d
static int fill_voltaire_chassis_record(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	int p = 0;
Packit db064d
	ibnd_port_t *port;
Packit db064d
	ibnd_node_t *remnode = NULL;
Packit db064d
Packit db064d
	if (node->ch_found)	/* somehow this node has already been passed */
Packit db064d
		return 0;
Packit db064d
	node->ch_found = 1;
Packit db064d
Packit db064d
	/* node is router only in case of using unique lid */
Packit db064d
	/* (which is lid of chassis router port) */
Packit db064d
	/* in such case node->ports is actually a requested port... */
Packit db064d
	if (is_router(node))
Packit db064d
		/* find the remote node */
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
			port = node->ports[p];
Packit db064d
			if (port && is_spine(port->remoteport->node))
Packit db064d
				get_router_slot(node, port->remoteport);
Packit db064d
		}
Packit db064d
	else if (is_spine(node)) {
Packit db064d
		int is_4700x2 = is_spine_4700x2(node);
Packit db064d
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
			port = node->ports[p];
Packit db064d
			if (!port || !port->remoteport)
Packit db064d
				continue;
Packit db064d
Packit db064d
			/*
Packit db064d
			 * Skip ISR4700 double density fabric boards ports 19-36
Packit db064d
			 * as they are chassis external ports
Packit db064d
			 */
Packit db064d
			if (is_4700x2 && (port->portnum > 18))
Packit db064d
				continue;
Packit db064d
Packit db064d
			remnode = port->remoteport->node;
Packit db064d
			if (remnode->type != IB_NODE_SWITCH) {
Packit db064d
				if (!remnode->ch_found)
Packit db064d
					get_router_slot(remnode, port);
Packit db064d
				continue;
Packit db064d
			}
Packit db064d
			if (!node->ch_type)
Packit db064d
				/* we assume here that remoteport belongs to line */
Packit db064d
				get_sfb_slot(node, port->remoteport);
Packit db064d
Packit db064d
			/* we could break here, but need to find if more routers connected */
Packit db064d
		}
Packit db064d
Packit db064d
	} else if (is_line(node)) {
Packit db064d
		int is_4700_line = is_line_4700(node);
Packit db064d
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
			port = node->ports[p];
Packit db064d
			if (!port || !port->remoteport)
Packit db064d
				continue;
Packit db064d
Packit db064d
			if ((is_4700_line && (port->portnum > 18)) ||
Packit db064d
			    (!is_4700_line && (port->portnum > 12)))
Packit db064d
				continue;
Packit db064d
Packit db064d
			/* we assume here that remoteport belongs to spine */
Packit db064d
			get_slb_slot(node, port->remoteport);
Packit db064d
			break;
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	/* for each port of this node, map external ports */
Packit db064d
	for (p = 1; p <= node->numports; p++) {
Packit db064d
		port = node->ports[p];
Packit db064d
		if (!port)
Packit db064d
			continue;
Packit db064d
		voltaire_portmap(port);
Packit db064d
	}
Packit db064d
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int get_line_index(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	int retval;
Packit db064d
Packit db064d
	if (is_line_4700(node))
Packit db064d
		retval = node->ch_slotnum;
Packit db064d
	else
Packit db064d
		retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
Packit db064d
Packit db064d
	if (retval > LINES_MAX_NUM || retval < 1) {
Packit db064d
		printf("%s: retval = %d\n", __FUNCTION__, retval);
Packit db064d
		IBND_ERROR("Internal error\n");
Packit db064d
		return -1;
Packit db064d
	}
Packit db064d
	return retval;
Packit db064d
}
Packit db064d
Packit db064d
static int get_spine_index(ibnd_node_t * node)
Packit db064d
{
Packit db064d
	int retval;
Packit db064d
Packit db064d
	if (is_spine_9288(node) || is_spine_2012(node))
Packit db064d
		retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
Packit db064d
	else if (is_spine_4700(node) || is_spine_4700x2(node))
Packit db064d
		retval = 2 * (node->ch_slotnum - 1) + node->ch_anafanum;
Packit db064d
	else
Packit db064d
		retval = node->ch_slotnum;
Packit db064d
Packit db064d
	if (retval > SPINES_MAX_NUM || retval < 1) {
Packit db064d
		IBND_ERROR("Internal error\n");
Packit db064d
		return -1;
Packit db064d
	}
Packit db064d
	return retval;
Packit db064d
}
Packit db064d
Packit db064d
static int insert_line_router(ibnd_node_t * node, ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	int i = get_line_index(node);
Packit db064d
Packit db064d
	if (i < 0)
Packit db064d
		return i;
Packit db064d
Packit db064d
	if (chassis->linenode[i])
Packit db064d
		return 0;	/* already filled slot */
Packit db064d
Packit db064d
	chassis->linenode[i] = node;
Packit db064d
	node->chassis = chassis;
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	int i = get_spine_index(node);
Packit db064d
Packit db064d
	if (i < 0)
Packit db064d
		return i;
Packit db064d
Packit db064d
	if (chassis->spinenode[i])
Packit db064d
		return 0;	/* already filled slot */
Packit db064d
Packit db064d
	chassis->spinenode[i] = node;
Packit db064d
	node->chassis = chassis;
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	ibnd_node_t *node, *remnode;
Packit db064d
	ibnd_port_t *port;
Packit db064d
	int i, p;
Packit db064d
Packit db064d
	for (i = 1; i <= LINES_MAX_NUM; i++) {
Packit db064d
		int is_4700_line;
Packit db064d
Packit db064d
		node = chassis->linenode[i];
Packit db064d
Packit db064d
		if (!(node && is_line(node)))
Packit db064d
			continue;	/* empty slot or router */
Packit db064d
Packit db064d
		is_4700_line = is_line_4700(node);
Packit db064d
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
Packit db064d
			port = node->ports[p];
Packit db064d
			if (!port || !port->remoteport)
Packit db064d
				continue;
Packit db064d
Packit db064d
			if ((is_4700_line && (port->portnum > 18)) ||
Packit db064d
			    (!is_4700_line && (port->portnum > 12)))
Packit db064d
				continue;
Packit db064d
Packit db064d
			remnode = port->remoteport->node;
Packit db064d
Packit db064d
			if (!remnode->ch_found)
Packit db064d
				continue;	/* some error - spine not initialized ? FIXME */
Packit db064d
			if (insert_spine(remnode, chassis))
Packit db064d
				return -1;
Packit db064d
		}
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	ibnd_node_t *node, *remnode;
Packit db064d
	ibnd_port_t *port;
Packit db064d
	int i, p;
Packit db064d
Packit db064d
	for (i = 1; i <= SPINES_MAX_NUM; i++) {
Packit db064d
		int is_4700x2;
Packit db064d
Packit db064d
		node = chassis->spinenode[i];
Packit db064d
		if (!node)
Packit db064d
			continue;	/* empty slot */
Packit db064d
Packit db064d
		is_4700x2 = is_spine_4700x2(node);
Packit db064d
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
			port = node->ports[p];
Packit db064d
			if (!port || !port->remoteport)
Packit db064d
				continue;
Packit db064d
Packit db064d
			/*
Packit db064d
			 * ISR4700 double density fabric board ports 19-36 are
Packit db064d
			 * chassis external ports, so skip them
Packit db064d
			 */
Packit db064d
			if (is_4700x2 && (port->portnum > 18))
Packit db064d
				continue;
Packit db064d
Packit db064d
			remnode = port->remoteport->node;
Packit db064d
Packit db064d
			if (!remnode->ch_found)
Packit db064d
				continue;	/* some error - line/router not initialized ? FIXME */
Packit db064d
Packit db064d
			if (insert_line_router(remnode, chassis))
Packit db064d
				return -1;
Packit db064d
		}
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
/*
Packit db064d
	Stupid interpolation algorithm...
Packit db064d
	But nothing to do - have to be compliant with VoltaireSM/NMS
Packit db064d
*/
Packit db064d
static void pass_on_spines_interpolate_chguid(ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	ibnd_node_t *node;
Packit db064d
	int i;
Packit db064d
Packit db064d
	for (i = 1; i <= SPINES_MAX_NUM; i++) {
Packit db064d
		node = chassis->spinenode[i];
Packit db064d
		if (!node)
Packit db064d
			continue;	/* skip the empty slots */
Packit db064d
Packit db064d
		/* take first guid minus one to be consistent with SM */
Packit db064d
		chassis->chassisguid = node->guid - 1;
Packit db064d
		break;
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
/*
Packit db064d
	This function fills chassis structure with all nodes
Packit db064d
	in that chassis
Packit db064d
	chassis structure = structure of one standalone chassis
Packit db064d
*/
Packit db064d
static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis)
Packit db064d
{
Packit db064d
	int p = 0;
Packit db064d
	ibnd_node_t *remnode = NULL;
Packit db064d
	ibnd_port_t *port = NULL;
Packit db064d
Packit db064d
	/* we get here with node = chassis_spine */
Packit db064d
	if (insert_spine(node, chassis))
Packit db064d
		return -1;
Packit db064d
Packit db064d
	/* loop: pass on all ports of node */
Packit db064d
	for (p = 1; p <= node->numports; p++) {
Packit db064d
Packit db064d
		port = node->ports[p];
Packit db064d
		if (!port || !port->remoteport)
Packit db064d
			continue;
Packit db064d
Packit db064d
		/*
Packit db064d
		 * ISR4700 double density fabric board ports 19-36 are
Packit db064d
		 * chassis external ports, so skip them
Packit db064d
		 */
Packit db064d
		if (is_spine_4700x2(node) && (port->portnum > 18))
Packit db064d
			continue;
Packit db064d
Packit db064d
		remnode = port->remoteport->node;
Packit db064d
Packit db064d
		if (!remnode->ch_found)
Packit db064d
			continue;	/* some error - line or router not initialized ? FIXME */
Packit db064d
Packit db064d
		insert_line_router(remnode, chassis);
Packit db064d
	}
Packit db064d
Packit db064d
	if (pass_on_lines_catch_spines(chassis))
Packit db064d
		return -1;
Packit db064d
	/* this pass needed for to catch routers, since routers connected only */
Packit db064d
	/* to spines in slot 1 or 4 and we could miss them first time */
Packit db064d
	if (pass_on_spines_catch_lines(chassis))
Packit db064d
		return -1;
Packit db064d
Packit db064d
	/* additional 2 passes needed for to overcome a problem of pure "in-chassis" */
Packit db064d
	/* connectivity - extra pass to ensure that all related chips/modules */
Packit db064d
	/* inserted into the chassis */
Packit db064d
	if (pass_on_lines_catch_spines(chassis))
Packit db064d
		return -1;
Packit db064d
	if (pass_on_spines_catch_lines(chassis))
Packit db064d
		return -1;
Packit db064d
	pass_on_spines_interpolate_chguid(chassis);
Packit db064d
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
/*========================================================*/
Packit db064d
/*                INTERNAL TO EXTERNAL PORT MAPPING       */
Packit db064d
/*========================================================*/
Packit db064d
Packit db064d
/*
Packit db064d
Description : On ISR9288/9096 external ports indexing
Packit db064d
              is not matching the internal ( anafa ) port
Packit db064d
              indexes. Use this MAP to translate the data you get from
Packit db064d
              the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)
Packit db064d
Packit db064d
Module : sLB-24
Packit db064d
                anafa 1             anafa 2
Packit db064d
ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
Packit db064d
int port | 22 23 24 18 17 16 | 22 23 24 18 17 16
Packit db064d
ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
Packit db064d
int port | 19 20 21 15 14 13 | 19 20 21 15 14 13
Packit db064d
------------------------------------------------
Packit db064d
Packit db064d
Module : sLB-8
Packit db064d
                anafa 1             anafa 2
Packit db064d
ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24
Packit db064d
int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
Packit db064d
ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12
Packit db064d
int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
Packit db064d
Packit db064d
----------->
Packit db064d
                anafa 1             anafa 2
Packit db064d
ext port | -  -  5  -  -  6  | -  -  7  -  -  8
Packit db064d
int port | 24 23 22 18 17 16 | 24 23 22 18 17 16
Packit db064d
ext port | -  -  1  -  -  2  | -  -  3  -  -  4
Packit db064d
int port | 21 20 19 15 14 13 | 21 20 19 15 14 13
Packit db064d
------------------------------------------------
Packit db064d
Packit db064d
Module : sLB-2024
Packit db064d
Packit db064d
ext port | 13 14 15 16 17 18 19 20 21 22 23 24
Packit db064d
A1 int port| 13 14 15 16 17 18 19 20 21 22 23 24
Packit db064d
ext port | 1 2 3 4 5 6 7 8 9 10 11 12
Packit db064d
A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24
Packit db064d
---------------------------------------------------
Packit db064d
Packit db064d
Module : sLB-4018
Packit db064d
Packit db064d
int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Packit db064d
ext port |  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
Packit db064d
---------------------------------------------------
Packit db064d
Packit db064d
Module : sFB-4700X2
Packit db064d
Packit db064d
  12X port -> 3 x 4X ports:
Packit db064d
Packit db064d
A1 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Packit db064d
   ext port |  7  7  7  8  8  8  9  9  9 10 10 10 11 11 11 12 12 12
Packit db064d
A2 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Packit db064d
   ext port |  1  1  1  2  2  2  3  3  3  4  4  4  5  5  5  6  6  6
Packit db064d
Packit db064d
*/
Packit db064d
Packit db064d
static int int2ext_map_slb24[2][25] = {
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3,
Packit db064d
	 13, 14, 15},
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9,
Packit db064d
	 19, 20, 21}
Packit db064d
};
Packit db064d
Packit db064d
static int int2ext_map_slb8[2][25] = {
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5,
Packit db064d
	 5},
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7,
Packit db064d
	 7}
Packit db064d
};
Packit db064d
Packit db064d
static int int2ext_map_slb2024[2][25] = {
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
Packit db064d
	 21, 22, 23, 24},
Packit db064d
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
Packit db064d
	 11, 12}
Packit db064d
};
Packit db064d
Packit db064d
static int int2ext_map_slb4018[37] = {
Packit db064d
	0,
Packit db064d
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db064d
	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
Packit db064d
};
Packit db064d
Packit db064d
static int int2ext_map_sfb4700x2[2][37] = {
Packit db064d
	{0,
Packit db064d
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db064d
	 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12},
Packit db064d
	{0,
Packit db064d
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit db064d
	 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6}
Packit db064d
};
Packit db064d
Packit db064d
/*	reference			{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
Packit db064d
Packit db064d
/* map internal ports to external ports if appropriate */
Packit db064d
static void voltaire_portmap(ibnd_port_t * port)
Packit db064d
{
Packit db064d
	int portnum = port->portnum;
Packit db064d
	int chipnum = 0;
Packit db064d
	ibnd_node_t *node = port->node;
Packit db064d
	int is_4700_line = is_line_4700(node);
Packit db064d
	int is_4700x2_spine = is_spine_4700x2(node);
Packit db064d
Packit db064d
	if (!node->ch_found || (!is_line(node) && !is_4700x2_spine)) {
Packit db064d
		port->ext_portnum = 0;
Packit db064d
		return;
Packit db064d
	}
Packit db064d
Packit db064d
	if (((is_4700_line || is_4700x2_spine) &&
Packit db064d
	     (portnum < 19 || portnum > 36)) ||
Packit db064d
	    ((!is_4700_line && !is_4700x2_spine) &&
Packit db064d
	     (portnum < 13 || portnum > 24))) {
Packit db064d
			port->ext_portnum = 0;
Packit db064d
		return;
Packit db064d
	}
Packit db064d
Packit db064d
	if (port->node->ch_anafanum < 1 || port->node->ch_anafanum > 2) {
Packit db064d
		port->ext_portnum = 0;
Packit db064d
		return;
Packit db064d
	}
Packit db064d
Packit db064d
	chipnum = port->node->ch_anafanum - 1;
Packit db064d
Packit db064d
	if (is_line_24(node))
Packit db064d
		port->ext_portnum = int2ext_map_slb24[chipnum][portnum];
Packit db064d
	else if (is_line_2024(node))
Packit db064d
		port->ext_portnum = int2ext_map_slb2024[chipnum][portnum];
Packit db064d
	/* sLB-4018: Only one asic per LB */
Packit db064d
	else if (is_4700_line)
Packit db064d
		port->ext_portnum = int2ext_map_slb4018[portnum];
Packit db064d
	/* sFB-4700X2 4X port */
Packit db064d
	else if (is_4700x2_spine)
Packit db064d
		port->ext_portnum = int2ext_map_sfb4700x2[chipnum][portnum];
Packit db064d
	else
Packit db064d
		port->ext_portnum = int2ext_map_slb8[chipnum][portnum];
Packit db064d
}
Packit db064d
Packit db064d
static int add_chassis(chassis_scan_t * chassis_scan)
Packit db064d
{
Packit db064d
	if (!(chassis_scan->current_chassis =
Packit db064d
	      calloc(1, sizeof(ibnd_chassis_t)))) {
Packit db064d
		IBND_ERROR("OOM: failed to allocate chassis object\n");
Packit db064d
		return -1;
Packit db064d
	}
Packit db064d
Packit db064d
	if (chassis_scan->first_chassis == NULL) {
Packit db064d
		chassis_scan->first_chassis = chassis_scan->current_chassis;
Packit db064d
		chassis_scan->last_chassis = chassis_scan->current_chassis;
Packit db064d
	} else {
Packit db064d
		chassis_scan->last_chassis->next =
Packit db064d
		    chassis_scan->current_chassis;
Packit db064d
		chassis_scan->last_chassis = chassis_scan->current_chassis;
Packit db064d
	}
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node)
Packit db064d
{
Packit db064d
	node->chassis = chassis;
Packit db064d
	node->next_chassis_node = chassis->nodes;
Packit db064d
	chassis->nodes = node;
Packit db064d
}
Packit db064d
Packit db064d
/*
Packit db064d
	Main grouping function
Packit db064d
	Algorithm:
Packit db064d
	1. pass on every Voltaire node
Packit db064d
	2. catch spine chip for every Voltaire node
Packit db064d
		2.1 build/interpolate chassis around this chip
Packit db064d
		2.2 go to 1.
Packit db064d
	3. pass on non Voltaire nodes (SystemImageGUID based grouping)
Packit db064d
	4. now group non Voltaire nodes by SystemImageGUID
Packit db064d
	Returns:
Packit db064d
	0 on success, -1 on failure
Packit db064d
*/
Packit db064d
int group_nodes(ibnd_fabric_t * fabric)
Packit db064d
{
Packit db064d
	ibnd_node_t *node;
Packit db064d
	int chassisnum = 0;
Packit db064d
	ibnd_chassis_t *chassis;
Packit db064d
	ibnd_chassis_t *ch, *ch_next;
Packit db064d
	chassis_scan_t chassis_scan;
Packit db064d
	int vendor_id;
Packit db064d
Packit db064d
	chassis_scan.first_chassis = NULL;
Packit db064d
	chassis_scan.current_chassis = NULL;
Packit db064d
	chassis_scan.last_chassis = NULL;
Packit db064d
Packit db064d
	/* first pass on switches and build for every Voltaire node */
Packit db064d
	/* an appropriate chassis record (slotnum and position) */
Packit db064d
	/* according to internal connectivity */
Packit db064d
	/* not very efficient but clear code so... */
Packit db064d
	for (node = fabric->switches; node; node = node->type_next) {
Packit db064d
Packit db064d
		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
Packit db064d
Packit db064d
		if (vendor_id == VTR_VENDOR_ID
Packit db064d
		    && fill_voltaire_chassis_record(node))
Packit db064d
			goto cleanup;
Packit db064d
		else if (vendor_id == MLX_VENDOR_ID
Packit db064d
			&& fill_mellanox_chassis_record(node))
Packit db064d
			goto cleanup;
Packit db064d
Packit db064d
	}
Packit db064d
Packit db064d
	/* separate every Voltaire chassis from each other and build linked list of them */
Packit db064d
	/* algorithm: catch spine and find all surrounding nodes */
Packit db064d
	for (node = fabric->switches; node; node = node->type_next) {
Packit db064d
		if (mad_get_field(node->info, 0,
Packit db064d
				  IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
Packit db064d
			continue;
Packit db064d
		if (!node->ch_found
Packit db064d
		    || (node->chassis && node->chassis->chassisnum)
Packit db064d
		    || !is_spine(node))
Packit db064d
			continue;
Packit db064d
		if (add_chassis(&chassis_scan))
Packit db064d
			goto cleanup;
Packit db064d
		chassis_scan.current_chassis->chassisnum = ++chassisnum;
Packit db064d
		if (build_chassis(node, chassis_scan.current_chassis))
Packit db064d
			goto cleanup;
Packit db064d
	}
Packit db064d
Packit db064d
	/* now make pass on nodes for chassis which are not Voltaire */
Packit db064d
	/* grouped by common SystemImageGUID */
Packit db064d
	for (node = fabric->nodes; node; node = node->next) {
Packit db064d
		if (mad_get_field(node->info, 0,
Packit db064d
				  IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
Packit db064d
			continue;
Packit db064d
		if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
Packit db064d
			chassis = find_chassisguid(fabric, node);
Packit db064d
			if (chassis)
Packit db064d
				chassis->nodecount++;
Packit db064d
			else {
Packit db064d
				/* Possible new chassis */
Packit db064d
				if (add_chassis(&chassis_scan))
Packit db064d
					goto cleanup;
Packit db064d
				chassis_scan.current_chassis->chassisguid =
Packit db064d
				    get_chassisguid(node);
Packit db064d
				chassis_scan.current_chassis->nodecount = 1;
Packit db064d
				if (!fabric->chassis)
Packit db064d
					fabric->chassis = chassis_scan.first_chassis;
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	/* now, make another pass to see which nodes are part of chassis */
Packit db064d
	/* (defined as chassis->nodecount > 1) */
Packit db064d
	for (node = fabric->nodes; node; node = node->next) {
Packit db064d
Packit db064d
		vendor_id = mad_get_field(node->info, 0,IB_NODE_VENDORID_F);
Packit db064d
Packit db064d
		if (vendor_id == VTR_VENDOR_ID)
Packit db064d
			continue;
Packit db064d
		if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
Packit db064d
			chassis = find_chassisguid(fabric, node);
Packit db064d
			if (chassis && chassis->nodecount > 1) {
Packit db064d
				if (!chassis->chassisnum)
Packit db064d
					chassis->chassisnum = ++chassisnum;
Packit db064d
				if (!node->ch_found) {
Packit db064d
					node->ch_found = 1;
Packit db064d
					add_node_to_chassis(chassis, node);
Packit db064d
				}
Packit db064d
				else if (vendor_id == MLX_VENDOR_ID){
Packit db064d
					insert_mellanox_line_and_spine(node, chassis);
Packit db064d
				}
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	fabric->chassis = chassis_scan.first_chassis;
Packit db064d
	return 0;
Packit db064d
Packit db064d
cleanup:
Packit db064d
	ch = chassis_scan.first_chassis;
Packit db064d
	while (ch) {
Packit db064d
		ch_next = ch->next;
Packit db064d
		free(ch);
Packit db064d
		ch = ch_next;
Packit db064d
	}
Packit db064d
	fabric->chassis = NULL;
Packit db064d
	return -1;
Packit db064d
}