|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (C) 2012-2017 Tokyo Institute of Technology. All rights reserved.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* This software is available to you under a choice of one of two
|
|
Packit |
13e616 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
13e616 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
13e616 |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
13e616 |
* OpenIB.org BSD license below:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
13e616 |
* without modification, are permitted provided that the following
|
|
Packit |
13e616 |
* conditions are met:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions of source code must retain the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer in the documentation and/or other materials
|
|
Packit |
13e616 |
* provided with the distribution.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
13e616 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
13e616 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
13e616 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
13e616 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
13e616 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
13e616 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
13e616 |
* SOFTWARE.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Abstract:
|
|
Packit |
13e616 |
* Implementation of osm_physp_t.
|
|
Packit |
13e616 |
* This object represents an Infiniband Port.
|
|
Packit |
13e616 |
* This object is part of the opensm family of objects.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_PORT_C
|
|
Packit |
13e616 |
#include <opensm/osm_port.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_madw.h>
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_db_pack.h>
|
|
Packit |
13e616 |
#include <opensm/osm_sm.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_construct(IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
memset(p_physp, 0, sizeof(*p_physp));
|
|
Packit |
13e616 |
osm_dr_path_construct(&p_physp->dr_path);
|
|
Packit |
13e616 |
cl_ptr_vector_construct(&p_physp->slvl_by_port);
|
|
Packit |
13e616 |
osm_pkey_tbl_construct(&p_physp->pkeys);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_destroy(IN osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
size_t num_slvl, i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* the physp might be uninitialized */
|
|
Packit |
13e616 |
if (p_physp->port_guid) {
|
|
Packit |
13e616 |
if (p_physp->p_guids)
|
|
Packit |
13e616 |
free(p_physp->p_guids);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* free the SL2VL Tables */
|
|
Packit |
13e616 |
num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port);
|
|
Packit |
13e616 |
for (i = 0; i < num_slvl; i++)
|
|
Packit |
13e616 |
free(cl_ptr_vector_get(&p_physp->slvl_by_port, i));
|
|
Packit |
13e616 |
cl_ptr_vector_destroy(&p_physp->slvl_by_port);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* free the P_Key Tables */
|
|
Packit |
13e616 |
osm_pkey_tbl_destroy(&p_physp->pkeys);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(p_physp, 0, sizeof(*p_physp));
|
|
Packit |
13e616 |
osm_dr_path_construct(&p_physp->dr_path); /* clear dr_path */
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_init(IN osm_physp_t * p_physp, IN ib_net64_t port_guid,
|
|
Packit |
13e616 |
IN uint8_t port_num, IN const struct osm_node *p_node,
|
|
Packit |
13e616 |
IN osm_bind_handle_t h_bind, IN uint8_t hop_count,
|
|
Packit |
13e616 |
IN const uint8_t * p_initial_path)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t num_slvl, i;
|
|
Packit |
13e616 |
ib_slvl_table_t *p_slvl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_physp_construct(p_physp);
|
|
Packit |
13e616 |
p_physp->port_guid = port_guid;
|
|
Packit |
13e616 |
p_physp->port_num = port_num;
|
|
Packit |
13e616 |
p_physp->healthy = TRUE;
|
|
Packit |
13e616 |
p_physp->need_update = 2;
|
|
Packit |
13e616 |
p_physp->p_node = (struct osm_node *)p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_dr_path_init(&p_physp->dr_path, hop_count, p_initial_path);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* allocate enough SL2VL tables */
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
/* we need node num ports + 1 SL2VL tables */
|
|
Packit |
13e616 |
num_slvl = osm_node_get_num_physp(p_node) + 1;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
/* An end node - we need only one SL2VL */
|
|
Packit |
13e616 |
num_slvl = 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_ptr_vector_init(&p_physp->slvl_by_port, num_slvl, 1);
|
|
Packit |
13e616 |
for (i = 0; i < num_slvl; i++) {
|
|
Packit |
13e616 |
p_slvl = (ib_slvl_table_t *) malloc(sizeof(ib_slvl_table_t));
|
|
Packit |
13e616 |
if (!p_slvl)
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
memset(p_slvl, 0, sizeof(ib_slvl_table_t));
|
|
Packit |
13e616 |
cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* initialize the pkey table */
|
|
Packit |
13e616 |
osm_pkey_tbl_init(&p_physp->pkeys);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_port_delete(IN OUT osm_port_t ** pp_port)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
free(*pp_port);
|
|
Packit |
13e616 |
*pp_port = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni,
|
|
Packit |
13e616 |
IN osm_node_t * p_parent_node)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port = malloc(sizeof(*p_port));
|
|
Packit |
13e616 |
if (!p_port)
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(p_port, 0, sizeof(*p_port));
|
|
Packit |
13e616 |
cl_qlist_init(&p_port->mcm_list);
|
|
Packit |
13e616 |
p_port->p_node = (struct osm_node *)p_parent_node;
|
|
Packit |
13e616 |
port_guid = p_ni->port_guid;
|
|
Packit |
13e616 |
p_port->guid = port_guid;
|
|
Packit |
13e616 |
port_num = p_ni->node_type == IB_NODE_TYPE_SWITCH ?
|
|
Packit |
13e616 |
0 : ib_node_info_get_local_port_num(p_ni);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
Get the pointers to the physical node objects "owned" by this
|
|
Packit |
13e616 |
logical port GUID.
|
|
Packit |
13e616 |
For switches, port '0' is owned; for HCA's and routers,
|
|
Packit |
13e616 |
only the singular part that has this GUID is owned.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_parent_node, port_num);
|
|
Packit |
13e616 |
if (!p_physp) {
|
|
Packit |
13e616 |
free(p_port);
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(port_guid == osm_physp_get_port_guid(p_physp));
|
|
Packit |
13e616 |
p_port->p_physp = p_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return p_port;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_port_get_lid_range_ho(IN const osm_port_t * p_port,
|
|
Packit |
13e616 |
IN uint16_t * p_min_lid, IN uint16_t * p_max_lid)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint8_t lmc;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
*p_min_lid = cl_ntoh16(osm_port_get_base_lid(p_port));
|
|
Packit |
13e616 |
lmc = osm_port_get_lmc(p_port);
|
|
Packit |
13e616 |
*p_max_lid = (uint16_t) (*p_min_lid + (1 << lmc) - 1);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
uint8_t osm_physp_calc_link_mtu(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN uint8_t current_mtu)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
const osm_physp_t *p_remote_physp;
|
|
Packit |
13e616 |
uint8_t mtu;
|
|
Packit |
13e616 |
uint8_t remote_mtu;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if (p_remote_physp) {
|
|
Packit |
13e616 |
/* use the available MTU */
|
|
Packit |
13e616 |
mtu = ib_port_info_get_mtu_cap(&p_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
remote_mtu =
|
|
Packit |
13e616 |
ib_port_info_get_mtu_cap(&p_remote_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote port 0x%016" PRIx64 " port = %u : "
|
|
Packit |
13e616 |
"MTU = %u. This Port MTU: %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp),
|
|
Packit |
13e616 |
remote_mtu, mtu);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (mtu != remote_mtu) {
|
|
Packit |
13e616 |
if (mtu > remote_mtu)
|
|
Packit |
13e616 |
mtu = remote_mtu;
|
|
Packit |
13e616 |
if (mtu != current_mtu)
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"MTU mismatch between ports."
|
|
Packit |
13e616 |
"\n\t\t\t\tPort 0x%016" PRIx64 ", port %u"
|
|
Packit |
13e616 |
" and port 0x%016" PRIx64 ", port %u."
|
|
Packit |
13e616 |
"\n\t\t\t\tUsing lower MTU of %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid(p_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp),
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_remote_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp), mtu);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (mtu == 0) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG, "ERR 4101: "
|
|
Packit |
13e616 |
"Invalid MTU = 0. Forcing correction to 256\n");
|
|
Packit |
13e616 |
mtu = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return mtu;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
uint8_t osm_physp_calc_link_op_vls(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN const osm_subn_t * p_subn,
|
|
Packit |
13e616 |
IN const osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN uint8_t current_op_vls)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
const osm_physp_t *p_remote_physp;
|
|
Packit |
13e616 |
uint8_t op_vls;
|
|
Packit |
13e616 |
uint8_t remote_op_vls;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
if (p_remote_physp) {
|
|
Packit |
13e616 |
/* use the available VLCap */
|
|
Packit |
13e616 |
op_vls = ib_port_info_get_vl_cap(&p_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
remote_op_vls =
|
|
Packit |
13e616 |
ib_port_info_get_vl_cap(&p_remote_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote port 0x%016" PRIx64 " port = 0x%X : "
|
|
Packit |
13e616 |
"VL_CAP = %u. This port VL_CAP = %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp),
|
|
Packit |
13e616 |
remote_op_vls, op_vls);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (op_vls != remote_op_vls) {
|
|
Packit |
13e616 |
if (op_vls > remote_op_vls)
|
|
Packit |
13e616 |
op_vls = remote_op_vls;
|
|
Packit |
13e616 |
if (op_vls != current_op_vls)
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"OP_VLS mismatch between ports."
|
|
Packit |
13e616 |
"\n\t\t\t\tPort 0x%016" PRIx64 ", port 0x%X"
|
|
Packit |
13e616 |
" and port 0x%016" PRIx64 ", port 0x%X."
|
|
Packit |
13e616 |
"\n\t\t\t\tUsing lower OP_VLS of %u\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid(p_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_physp),
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_remote_physp)),
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp), op_vls);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
op_vls = ib_port_info_get_op_vls(&p_physp->port_info);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (op_vls == 0) {
|
|
Packit |
13e616 |
/* for non compliant implementations */
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n");
|
|
Packit |
13e616 |
op_vls = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* support user limitation of max_op_vls */
|
|
Packit |
13e616 |
if (op_vls > p_subn->opt.max_op_vls)
|
|
Packit |
13e616 |
op_vls = p_subn->opt.max_op_vls;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return op_vls;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static inline uint64_t ptr_to_key(void const *p)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint64_t k = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memcpy(&k, p, sizeof(void *));
|
|
Packit |
13e616 |
return k;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if 0
|
|
Packit |
13e616 |
static inline void *key_to_ptr(uint64_t k)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
void *p = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memcpy(&p, &k, sizeof(void *));
|
|
Packit |
13e616 |
return p;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
#endif
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/**********************************************************************
|
|
Packit |
13e616 |
Traverse the fabric from the SM node following the DR path given and
|
|
Packit |
13e616 |
add every phys port traversed to the map. Avoid tracking the first and
|
|
Packit |
13e616 |
last phys ports (going into the first switch and into the target port).
|
|
Packit |
13e616 |
**********************************************************************/
|
|
Packit |
13e616 |
static cl_status_t physp_get_dr_physp_set(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN osm_subn_t const *p_subn,
|
|
Packit |
13e616 |
IN osm_dr_path_t const *p_path,
|
|
Packit |
13e616 |
OUT cl_map_t * p_physp_map)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
uint8_t hop;
|
|
Packit |
13e616 |
cl_status_t status = CL_SUCCESS;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* find the OSM node */
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid);
|
|
Packit |
13e616 |
if (!p_port) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4103: "
|
|
Packit |
13e616 |
"Failed to find the SM own port by guid\n");
|
|
Packit |
13e616 |
status = CL_ERROR;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* get the node of the SM */
|
|
Packit |
13e616 |
p_node = p_port->p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
traverse the path adding the nodes to the table
|
|
Packit |
13e616 |
start after the first dummy hop and stop just before the
|
|
Packit |
13e616 |
last one
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
for (hop = 1; hop < p_path->hop_count - 1; hop++) {
|
|
Packit |
13e616 |
/* go out using the phys port of the path */
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* make sure we got a valid port and it has a remote port */
|
|
Packit |
13e616 |
if (!p_physp) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4104: "
|
|
Packit |
13e616 |
"DR Traversal stopped on invalid port at hop:%u\n",
|
|
Packit |
13e616 |
hop);
|
|
Packit |
13e616 |
status = CL_ERROR;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* we track the ports we go out along the path */
|
|
Packit |
13e616 |
if (hop > 1)
|
|
Packit |
13e616 |
cl_map_insert(p_physp_map, ptr_to_key(p_physp), NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Traversed through node: 0x%016" PRIx64
|
|
Packit |
13e616 |
" port:%u\n",
|
|
Packit |
13e616 |
cl_ntoh64(p_node->node_info.node_guid),
|
|
Packit |
13e616 |
p_path->path[hop]);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!(p_physp = osm_physp_get_remote(p_physp))) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4106: "
|
|
Packit |
13e616 |
"DR Traversal stopped on missing remote physp at hop:%u\n",
|
|
Packit |
13e616 |
hop);
|
|
Packit |
13e616 |
status = CL_ERROR;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = osm_physp_get_node_ptr(p_physp);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void physp_update_new_dr_path(IN osm_physp_t const *p_dest_physp,
|
|
Packit |
13e616 |
IN cl_map_t * p_visited_map,
|
|
Packit |
13e616 |
IN osm_bind_handle_t * h_bind)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_list_t tmpPortsList;
|
|
Packit |
13e616 |
osm_physp_t *p_physp, *p_src_physp = NULL;
|
|
Packit |
13e616 |
uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
|
|
Packit |
13e616 |
uint8_t i = 0;
|
|
Packit |
13e616 |
osm_dr_path_t *p_dr_path;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_construct(&tmpPortsList);
|
|
Packit |
13e616 |
cl_list_init(&tmpPortsList, 10);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_insert_head(&tmpPortsList, p_dest_physp);
|
|
Packit |
13e616 |
/* get the output port where we need to come from */
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
|
|
Packit |
13e616 |
ptr_to_key(p_dest_physp));
|
|
Packit |
13e616 |
while (p_physp != NULL) {
|
|
Packit |
13e616 |
cl_list_insert_head(&tmpPortsList, p_physp);
|
|
Packit |
13e616 |
/* get the input port through where we reached the output port */
|
|
Packit |
13e616 |
p_src_physp = p_physp;
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
|
|
Packit |
13e616 |
ptr_to_key(p_physp));
|
|
Packit |
13e616 |
/* if we reached a null p_physp - this means we are at the begining
|
|
Packit |
13e616 |
of the path. Break. */
|
|
Packit |
13e616 |
if (p_physp == NULL)
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
/* get the output port */
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_map_get(p_visited_map,
|
|
Packit |
13e616 |
ptr_to_key(p_physp));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(path_array, 0, sizeof(path_array));
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList);
|
|
Packit |
13e616 |
while (p_physp != NULL) {
|
|
Packit |
13e616 |
i++;
|
|
Packit |
13e616 |
path_array[i] = p_physp->port_num;
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (p_src_physp) {
|
|
Packit |
13e616 |
p_dr_path = osm_physp_get_dr_path_ptr(p_src_physp);
|
|
Packit |
13e616 |
osm_dr_path_init(p_dr_path, i, path_array);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_destroy(&tmpPortsList);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_replace_dr_path_with_alternate_dr_path(IN osm_log_t * p_log,
|
|
Packit |
13e616 |
IN osm_subn_t const
|
|
Packit |
13e616 |
*p_subn, IN osm_physp_t const
|
|
Packit |
13e616 |
*p_dest_physp,
|
|
Packit |
13e616 |
IN osm_bind_handle_t *
|
|
Packit |
13e616 |
h_bind)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_map_t physp_map;
|
|
Packit |
13e616 |
cl_map_t visited_map;
|
|
Packit |
13e616 |
osm_dr_path_t *p_dr_path;
|
|
Packit |
13e616 |
cl_list_t *p_currPortsList;
|
|
Packit |
13e616 |
cl_list_t *p_nextPortsList;
|
|
Packit |
13e616 |
osm_port_t *p_port;
|
|
Packit |
13e616 |
osm_physp_t *p_physp, *p_remote_physp;
|
|
Packit |
13e616 |
ib_net64_t port_guid;
|
|
Packit |
13e616 |
boolean_t next_list_is_full = TRUE, reached_dest = FALSE;
|
|
Packit |
13e616 |
uint8_t num_ports, port_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
|
|
Packit |
13e616 |
if (!p_nextPortsList)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
initialize the map of all port participating in current dr path
|
|
Packit |
13e616 |
not including first and last switches
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
cl_map_construct(&physp_map);
|
|
Packit |
13e616 |
cl_map_init(&physp_map, 4);
|
|
Packit |
13e616 |
cl_map_construct(&visited_map);
|
|
Packit |
13e616 |
cl_map_init(&visited_map, 4);
|
|
Packit |
13e616 |
p_dr_path = osm_physp_get_dr_path_ptr(p_dest_physp);
|
|
Packit |
13e616 |
physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
BFS from OSM port until we find the target physp but avoid
|
|
Packit |
13e616 |
going through mapped ports
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
cl_list_construct(p_nextPortsList);
|
|
Packit |
13e616 |
cl_list_init(p_nextPortsList, 10);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_guid = p_subn->sm_port_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(port_guid);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_port = osm_get_port_by_guid(p_subn, port_guid);
|
|
Packit |
13e616 |
if (!p_port) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4105: No SM port object\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
HACK: We are assuming SM is running on HCA, so when getting the default
|
|
Packit |
13e616 |
port we'll get the port connected to the rest of the subnet. If SM is
|
|
Packit |
13e616 |
running on SWITCH - we should try to get a dr path from all switch ports.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_physp = p_port->p_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_insert_tail(p_nextPortsList, p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (next_list_is_full == TRUE) {
|
|
Packit |
13e616 |
next_list_is_full = FALSE;
|
|
Packit |
13e616 |
p_currPortsList = p_nextPortsList;
|
|
Packit |
13e616 |
p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t));
|
|
Packit |
13e616 |
if (!p_nextPortsList) {
|
|
Packit |
13e616 |
p_nextPortsList = p_currPortsList;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
cl_list_construct(p_nextPortsList);
|
|
Packit |
13e616 |
cl_list_init(p_nextPortsList, 10);
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList);
|
|
Packit |
13e616 |
while (p_physp != NULL) {
|
|
Packit |
13e616 |
/* If we are in a switch - need to go out through all
|
|
Packit |
13e616 |
the other physical ports of the switch */
|
|
Packit |
13e616 |
num_ports = osm_node_get_num_physp(p_physp->p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (port_num = 1; port_num < num_ports; port_num++) {
|
|
Packit |
13e616 |
if (osm_node_get_type(p_physp->p_node) ==
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
p_remote_physp =
|
|
Packit |
13e616 |
osm_node_get_physp_ptr(p_physp->
|
|
Packit |
13e616 |
p_node,
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
/* this is HCA or router - the remote port is just the port connected
|
|
Packit |
13e616 |
on the other side */
|
|
Packit |
13e616 |
p_remote_physp =
|
|
Packit |
13e616 |
p_physp->p_remote_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
make sure that all of the following occurred:
|
|
Packit |
13e616 |
1. The port isn't NULL
|
|
Packit |
13e616 |
2. This is not the port we came from
|
|
Packit |
13e616 |
3. The port is not in the physp_map
|
|
Packit |
13e616 |
4. This port haven't been visited before
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_remote_physp &&
|
|
Packit |
13e616 |
p_remote_physp != p_physp &&
|
|
Packit |
13e616 |
cl_map_get(&physp_map,
|
|
Packit |
13e616 |
ptr_to_key(p_remote_physp))
|
|
Packit |
13e616 |
== NULL
|
|
Packit |
13e616 |
&& cl_map_get(&visited_map,
|
|
Packit |
13e616 |
ptr_to_key
|
|
Packit |
13e616 |
(p_remote_physp)) == NULL) {
|
|
Packit |
13e616 |
/* Insert the port into the visited_map, and save its source port */
|
|
Packit |
13e616 |
cl_map_insert(&visited_map,
|
|
Packit |
13e616 |
ptr_to_key
|
|
Packit |
13e616 |
(p_remote_physp),
|
|
Packit |
13e616 |
p_physp);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Is this the p_dest_physp? */
|
|
Packit |
13e616 |
if (p_remote_physp == p_dest_physp) {
|
|
Packit |
13e616 |
/* update the new dr path */
|
|
Packit |
13e616 |
physp_update_new_dr_path
|
|
Packit |
13e616 |
(p_dest_physp, &visited_map,
|
|
Packit |
13e616 |
h_bind);
|
|
Packit |
13e616 |
reached_dest = TRUE;
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* add the p_remote_physp to the nextPortsList */
|
|
Packit |
13e616 |
cl_list_insert_tail(p_nextPortsList,
|
|
Packit |
13e616 |
p_remote_physp);
|
|
Packit |
13e616 |
next_list_is_full = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *)
|
|
Packit |
13e616 |
cl_list_remove_head(p_currPortsList);
|
|
Packit |
13e616 |
if (reached_dest == TRUE) {
|
|
Packit |
13e616 |
/* free the rest of the currPortsList */
|
|
Packit |
13e616 |
while (p_physp != NULL)
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *)
|
|
Packit |
13e616 |
cl_list_remove_head
|
|
Packit |
13e616 |
(p_currPortsList);
|
|
Packit |
13e616 |
/* free the nextPortsList, if items were added to it */
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *)
|
|
Packit |
13e616 |
cl_list_remove_head(p_nextPortsList);
|
|
Packit |
13e616 |
while (p_physp != NULL)
|
|
Packit |
13e616 |
p_physp = (osm_physp_t *)
|
|
Packit |
13e616 |
cl_list_remove_head
|
|
Packit |
13e616 |
(p_nextPortsList);
|
|
Packit |
13e616 |
next_list_is_full = FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
cl_list_destroy(p_currPortsList);
|
|
Packit |
13e616 |
free(p_currPortsList);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* cleanup */
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
cl_list_destroy(p_nextPortsList);
|
|
Packit |
13e616 |
free(p_nextPortsList);
|
|
Packit |
13e616 |
cl_map_destroy(&physp_map);
|
|
Packit |
13e616 |
cl_map_destroy(&visited_map);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_link_is_healthy(IN const osm_physp_t * p_physp)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p_remote_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
p_remote_physp = p_physp->p_remote_physp;
|
|
Packit |
13e616 |
if (p_remote_physp != NULL)
|
|
Packit |
13e616 |
return ((p_physp->healthy) & (p_remote_physp->healthy));
|
|
Packit |
13e616 |
/* the other side is not known - consider the link as healthy */
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
boolean_t osm_link_is_throttled(IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN const boolean_t subn_has_fdr10_enabled)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p_remote;
|
|
Packit |
13e616 |
uint8_t speed_physp, speed_remote, width_physp, width_remote;
|
|
Packit |
13e616 |
uint8_t highest_speed, highest_width;
|
|
Packit |
13e616 |
boolean_t physp_has_extended_speeds_capability;
|
|
Packit |
13e616 |
boolean_t remote_has_extended_speeds_capability;
|
|
Packit |
13e616 |
ib_port_info_t *p_physp_info, *p_remote_info;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_physp);
|
|
Packit |
13e616 |
p_remote = p_physp->p_remote_physp;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* the other side is not known - consider the link as unthrottled */
|
|
Packit |
13e616 |
if (!p_remote)
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* only SP0 (and not Sw Ext.) have a valid CapabilityMask */
|
|
Packit |
13e616 |
if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
p_physp_info =
|
|
Packit |
13e616 |
&(osm_node_get_physp_ptr(p_physp->p_node, 0)->port_info);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
p_physp_info = &p_physp->port_info;
|
|
Packit |
13e616 |
if (osm_node_get_type(p_remote->p_node) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
p_remote_info =
|
|
Packit |
13e616 |
&(osm_node_get_physp_ptr(p_remote->p_node, 0)->port_info);
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
p_remote_info = &p_remote->port_info;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
physp_has_extended_speeds_capability =
|
|
Packit |
13e616 |
p_physp_info->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
|
|
Packit |
13e616 |
remote_has_extended_speeds_capability =
|
|
Packit |
13e616 |
p_remote_info->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* reset again to the original port_info */
|
|
Packit |
13e616 |
p_physp_info = &p_physp->port_info;
|
|
Packit |
13e616 |
p_remote_info = &p_remote->port_info;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* first determine the enabled link speed/width of both sides */
|
|
Packit |
13e616 |
speed_physp =
|
|
Packit |
13e616 |
(physp_has_extended_speeds_capability ?
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_ext_enabled(p_physp_info) << 4 : 0)
|
|
Packit |
13e616 |
+ (subn_has_fdr10_enabled ?
|
|
Packit |
13e616 |
(p_physp->ext_port_info.link_speed_enabled & FDR10) << 3 : 0)
|
|
Packit |
13e616 |
+ ib_port_info_get_link_speed_enabled(p_physp_info);
|
|
Packit |
13e616 |
width_physp = p_physp_info->link_width_enabled;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
speed_remote =
|
|
Packit |
13e616 |
(remote_has_extended_speeds_capability ?
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_ext_enabled(p_remote_info) << 4 : 0)
|
|
Packit |
13e616 |
+ (subn_has_fdr10_enabled ?
|
|
Packit |
13e616 |
(p_remote->ext_port_info.link_speed_enabled & FDR10) << 3 : 0)
|
|
Packit |
13e616 |
+ ib_port_info_get_link_speed_enabled(p_remote_info);
|
|
Packit |
13e616 |
width_remote = p_remote_info->link_width_enabled;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
highest_speed = ib_get_highest_link_speed(speed_physp & speed_remote);
|
|
Packit |
13e616 |
highest_width = ib_get_highest_link_width(width_physp & width_remote);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* and now determine the currently active link speed/width */
|
|
Packit |
13e616 |
speed_physp =
|
|
Packit |
13e616 |
(physp_has_extended_speeds_capability ?
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_ext_active(p_physp_info) << 4 : 0)
|
|
Packit |
13e616 |
+ (subn_has_fdr10_enabled ?
|
|
Packit |
13e616 |
(p_physp->ext_port_info.link_speed_active & FDR10) << 3 : 0)
|
|
Packit |
13e616 |
+ ib_port_info_get_link_speed_active(p_physp_info);
|
|
Packit |
13e616 |
speed_physp = ib_get_highest_link_speed(speed_physp);
|
|
Packit |
13e616 |
width_physp = p_physp_info->link_width_active;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
speed_remote =
|
|
Packit |
13e616 |
(remote_has_extended_speeds_capability ?
|
|
Packit |
13e616 |
ib_port_info_get_link_speed_ext_active(p_remote_info) << 4 : 0)
|
|
Packit |
13e616 |
+ (subn_has_fdr10_enabled ?
|
|
Packit |
13e616 |
(p_remote->ext_port_info.link_speed_active & FDR10) << 3 : 0)
|
|
Packit |
13e616 |
+ ib_port_info_get_link_speed_active(p_remote_info);
|
|
Packit |
13e616 |
speed_remote = ib_get_highest_link_speed(speed_remote);
|
|
Packit |
13e616 |
width_remote = p_remote_info->link_width_active;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* check if the link supports same speed in both directions
|
|
Packit |
13e616 |
and whether or not it runs at maximum speed/width which is
|
|
Packit |
13e616 |
enabled by both ends (if not then its considered 'throttled')
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (speed_physp != speed_remote || speed_physp != highest_speed ||
|
|
Packit |
13e616 |
width_physp != width_remote || width_physp != highest_width)
|
|
Packit |
13e616 |
return TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_set_pkey_tbl(IN osm_log_t * p_log, IN const osm_subn_t * p_subn,
|
|
Packit |
13e616 |
IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN ib_pkey_table_t * p_pkey_tbl,
|
|
Packit |
13e616 |
IN uint16_t block_num,
|
|
Packit |
13e616 |
IN boolean_t is_set)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t max_blocks;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_pkey_tbl);
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
(14.2.5.7) - the block number valid values are 0-2047, and are
|
|
Packit |
13e616 |
further limited by the size of the P_Key table specified by
|
|
Packit |
13e616 |
the PartitionCap on the node.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (!p_physp->p_node->sw || p_physp->port_num == 0)
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
The maximum blocks is defined in the node info: partition cap
|
|
Packit |
13e616 |
for CA, router, and switch management ports.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
max_blocks =
|
|
Packit |
13e616 |
(cl_ntoh16(p_physp->p_node->node_info.partition_cap) +
|
|
Packit |
13e616 |
IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
|
|
Packit |
13e616 |
/ IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
This is a switch, and not a management port. The maximum
|
|
Packit |
13e616 |
blocks is defined in the switch info: partition enforcement
|
|
Packit |
13e616 |
cap.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
max_blocks =
|
|
Packit |
13e616 |
(cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) +
|
|
Packit |
13e616 |
IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
|
|
Packit |
13e616 |
1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (block_num >= max_blocks) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4108: "
|
|
Packit |
13e616 |
"Got illegal update for block number:%u max:%u "
|
|
Packit |
13e616 |
"for GUID: %" PRIx64 " port number:%u\n",
|
|
Packit |
13e616 |
block_num, max_blocks,
|
|
Packit |
13e616 |
cl_ntoh64(p_physp->p_node->node_info.node_guid),
|
|
Packit |
13e616 |
p_physp->port_num);
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* decrement block received counter */
|
|
Packit |
13e616 |
if(!is_set)
|
|
Packit |
13e616 |
p_physp->pkeys.rcv_blocks_cnt--;
|
|
Packit |
13e616 |
osm_pkey_tbl_set(&p_physp->pkeys, block_num, p_pkey_tbl,
|
|
Packit |
13e616 |
p_subn->opt.allow_both_pkeys);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_alias_guid_t *osm_alias_guid_new(IN const ib_net64_t alias_guid,
|
|
Packit |
13e616 |
IN osm_port_t *p_base_port)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_alias_guid_t *p_alias_guid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_alias_guid = calloc(1, sizeof(*p_alias_guid));
|
|
Packit |
13e616 |
if (p_alias_guid) {
|
|
Packit |
13e616 |
p_alias_guid->alias_guid = alias_guid;
|
|
Packit |
13e616 |
p_alias_guid->p_base_port = p_base_port;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return p_alias_guid;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
free(*pp_alias_guid);
|
|
Packit |
13e616 |
*pp_alias_guid = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_physp_set_port_info(IN osm_physp_t * p_physp,
|
|
Packit |
13e616 |
IN const ib_port_info_t * p_pi,
|
|
Packit |
13e616 |
IN const struct osm_sm * p_sm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
CL_ASSERT(p_pi);
|
|
Packit |
13e616 |
CL_ASSERT(osm_physp_is_valid(p_physp));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) {
|
|
Packit |
13e616 |
/* If PortState is down, only copy PortState */
|
|
Packit |
13e616 |
/* and PortPhysicalState per C14-24-2.1 */
|
|
Packit |
13e616 |
ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN);
|
|
Packit |
13e616 |
ib_port_info_set_port_phys_state
|
|
Packit |
13e616 |
(ib_port_info_get_port_phys_state(p_pi),
|
|
Packit |
13e616 |
&p_physp->port_info);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
p_physp->port_info = *p_pi;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* The MKey in p_pi can only be considered valid if it's
|
|
Packit |
13e616 |
* for a HCA/router or switch port 0, and it's either
|
|
Packit |
13e616 |
* non-zero or the MKeyProtect bits are also zero.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if ((osm_node_get_type(p_physp->p_node) !=
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH || p_physp->port_num == 0) &&
|
|
Packit |
13e616 |
(p_pi->m_key != 0 || ib_port_info_get_mpb(p_pi) == 0))
|
|
Packit |
13e616 |
osm_db_guid2mkey_set(p_sm->p_subn->p_g2m,
|
|
Packit |
13e616 |
cl_ntoh64(p_physp->port_guid),
|
|
Packit |
13e616 |
cl_ntoh64(p_pi->m_key));
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|