|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit Service |
54dbc3 |
* Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
|
|
Packit Service |
54dbc3 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
* This software is available to you under a choice of one of two
|
|
Packit Service |
54dbc3 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit Service |
54dbc3 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit Service |
54dbc3 |
* COPYING in the main directory of this source tree, or the
|
|
Packit Service |
54dbc3 |
* OpenIB.org BSD license below:
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
* Redistribution and use in source and binary forms, with or
|
|
Packit Service |
54dbc3 |
* without modification, are permitted provided that the following
|
|
Packit Service |
54dbc3 |
* conditions are met:
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
* - Redistributions of source code must retain the above
|
|
Packit Service |
54dbc3 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
54dbc3 |
* disclaimer.
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
* - Redistributions in binary form must reproduce the above
|
|
Packit Service |
54dbc3 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
54dbc3 |
* disclaimer in the documentation and/or other materials
|
|
Packit Service |
54dbc3 |
* provided with the distribution.
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit Service |
54dbc3 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit Service |
54dbc3 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit Service |
54dbc3 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit Service |
54dbc3 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit Service |
54dbc3 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit Service |
54dbc3 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit Service |
54dbc3 |
* SOFTWARE.
|
|
Packit Service |
54dbc3 |
*
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
* Abstract:
|
|
Packit Service |
54dbc3 |
* Implementation of osm_ucast_mgr_t.
|
|
Packit Service |
54dbc3 |
* This file implements the Unicast Manager object.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
#if HAVE_CONFIG_H
|
|
Packit Service |
54dbc3 |
# include <config.h>
|
|
Packit Service |
54dbc3 |
#endif /* HAVE_CONFIG_H */
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
#include <stdio.h>
|
|
Packit Service |
54dbc3 |
#include <stdlib.h>
|
|
Packit Service |
54dbc3 |
#include <string.h>
|
|
Packit Service |
54dbc3 |
#include <ctype.h>
|
|
Packit Service |
54dbc3 |
#include <iba/ib_types.h>
|
|
Packit Service |
54dbc3 |
#include <complib/cl_qmap.h>
|
|
Packit Service |
54dbc3 |
#include <complib/cl_debug.h>
|
|
Packit Service |
54dbc3 |
#include <complib/cl_qlist.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_file_ids.h>
|
|
Packit Service |
54dbc3 |
#define FILE_ID OSM_FILE_UCAST_MGR_C
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_ucast_mgr.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_sm.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_log.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_node.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_switch.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_helper.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_msgdef.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_opensm.h>
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
memset(p_mgr, 0, sizeof(*p_mgr));
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_mgr->cache_valid)
|
|
Packit Service |
54dbc3 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ib_api_status_t osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr, IN osm_sm_t * sm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_construct(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_mgr->sm = sm;
|
|
Packit Service |
54dbc3 |
p_mgr->p_log = sm->p_log;
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn = sm->p_subn;
|
|
Packit Service |
54dbc3 |
p_mgr->p_lock = sm->p_lock;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (sm->p_subn->opt.use_ucast_cache)
|
|
Packit Service |
54dbc3 |
cl_qmap_init(&p_mgr->cache_sw_tbl);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return status;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
Add each switch's own and neighbor LIDs to its LID matrix
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_process_hop_0_1(IN cl_map_item_t * p_map_item,
|
|
Packit Service |
54dbc3 |
IN void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
osm_node_t *p_remote_node;
|
|
Packit Service |
54dbc3 |
uint16_t lid, remote_lid;
|
|
Packit Service |
54dbc3 |
uint8_t i;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
lid = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
|
|
Packit Service |
54dbc3 |
osm_switch_set_hops(p_sw, lid, 0, 0);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < p_sw->num_ports; i++) {
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, i);
|
|
Packit Service |
54dbc3 |
p_remote_node = (p && p->p_remote_physp) ?
|
|
Packit Service |
54dbc3 |
p->p_remote_physp->p_node : NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_remote_node && p_remote_node->sw &&
|
|
Packit Service |
54dbc3 |
p_remote_node != p_sw->p_node) {
|
|
Packit Service |
54dbc3 |
remote_lid = osm_node_get_base_lid(p_remote_node, 0);
|
|
Packit Service |
54dbc3 |
remote_lid = cl_ntoh16(remote_lid);
|
|
Packit Service |
54dbc3 |
osm_switch_set_hops(p_sw, remote_lid, i, p->hop_wf);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * p_mgr,
|
|
Packit Service |
54dbc3 |
IN osm_switch_t * p_this_sw,
|
|
Packit Service |
54dbc3 |
IN osm_switch_t * p_remote_sw,
|
|
Packit Service |
54dbc3 |
IN uint8_t port_num,
|
|
Packit Service |
54dbc3 |
IN uint8_t remote_port_num)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t *p_sw;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item;
|
|
Packit Service |
54dbc3 |
uint16_t lid_ho;
|
|
Packit Service |
54dbc3 |
uint16_t hops;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Node 0x%" PRIx64 ", remote node 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
", port %u, remote port %u\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)),
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)),
|
|
Packit Service |
54dbc3 |
port_num, remote_port_num);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p = osm_node_get_physp_ptr(p_this_sw->p_node, port_num);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
item != cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
p_sw = (osm_switch_t *) item;
|
|
Packit Service |
54dbc3 |
lid_ho = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0));
|
|
Packit Service |
54dbc3 |
hops = osm_switch_get_least_hops(p_remote_sw, lid_ho);
|
|
Packit Service |
54dbc3 |
if (hops == OSM_NO_PATH)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
hops += p->hop_wf;
|
|
Packit Service |
54dbc3 |
if (hops <
|
|
Packit Service |
54dbc3 |
osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) {
|
|
Packit Service |
54dbc3 |
if (osm_switch_set_hops
|
|
Packit Service |
54dbc3 |
(p_this_sw, lid_ho, port_num, (uint8_t) hops) != 0)
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A03: "
|
|
Packit Service |
54dbc3 |
"cannot set hops for lid %u at switch 0x%"
|
|
Packit Service |
54dbc3 |
PRIx64 "\n", lid_ho,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(p_this_sw->p_node)));
|
|
Packit Service |
54dbc3 |
p_mgr->some_hop_count_set = TRUE;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static struct osm_remote_node *find_and_add_remote_sys(osm_switch_t * sw,
|
|
Packit Service |
54dbc3 |
uint8_t port,
|
|
Packit Service |
54dbc3 |
boolean_t dor, struct
|
|
Packit Service |
54dbc3 |
osm_remote_guids_count
|
|
Packit Service |
54dbc3 |
*r)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
unsigned i;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port);
|
|
Packit Service |
54dbc3 |
osm_node_t *node = p->p_remote_physp->p_node;
|
|
Packit Service |
54dbc3 |
uint8_t rem_port = osm_physp_get_port_num(p->p_remote_physp);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 0; i < r->count; i++)
|
|
Packit Service |
54dbc3 |
if (r->guids[i].node == node)
|
|
Packit Service |
54dbc3 |
if (!dor || (r->guids[i].port == rem_port))
|
|
Packit Service |
54dbc3 |
return &r->guids[i];
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
r->guids[i].node = node;
|
|
Packit Service |
54dbc3 |
r->guids[i].forwarded_to = 0;
|
|
Packit Service |
54dbc3 |
r->guids[i].port = rem_port;
|
|
Packit Service |
54dbc3 |
r->count++;
|
|
Packit Service |
54dbc3 |
return &r->guids[i];
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr,
|
|
Packit Service |
54dbc3 |
IN osm_switch_t * p_sw,
|
|
Packit Service |
54dbc3 |
IN osm_port_t * p_port,
|
|
Packit Service |
54dbc3 |
IN unsigned lid_offset)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint16_t min_lid_ho;
|
|
Packit Service |
54dbc3 |
uint16_t max_lid_ho;
|
|
Packit Service |
54dbc3 |
uint16_t lid_ho;
|
|
Packit Service |
54dbc3 |
uint8_t port;
|
|
Packit Service |
54dbc3 |
boolean_t is_ignored_by_port_prof;
|
|
Packit Service |
54dbc3 |
ib_net64_t node_guid;
|
|
Packit Service |
54dbc3 |
unsigned start_from = 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* If the lids are zero - then there was some problem with
|
|
Packit Service |
54dbc3 |
* the initialization. Don't handle this port. */
|
|
Packit Service |
54dbc3 |
if (min_lid_ho == 0 || max_lid_ho == 0) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: "
|
|
Packit Service |
54dbc3 |
"Port 0x%" PRIx64 " (%s port %d) has LID 0. An "
|
|
Packit Service |
54dbc3 |
"initialization error occurred. Ignoring port\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_port_get_guid(p_port)),
|
|
Packit Service |
54dbc3 |
p_port->p_node->print_desc,
|
|
Packit Service |
54dbc3 |
p_port->p_physp->port_num);
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
lid_ho = min_lid_ho + lid_offset;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (lid_ho > max_lid_ho)
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (lid_offset && !p_mgr->is_dor)
|
|
Packit Service |
54dbc3 |
/* ignore potential overflow - it is handled in osm_switch.c */
|
|
Packit Service |
54dbc3 |
start_from =
|
|
Packit Service |
54dbc3 |
osm_switch_get_port_by_lid(p_sw, lid_ho - 1, OSM_NEW_LFT) + 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Processing port 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
" (\'%s\' port %u), LID %u [%u,%u]\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_port_get_guid(p_port)),
|
|
Packit Service |
54dbc3 |
p_port->p_node->print_desc, p_port->p_physp->port_num, lid_ho,
|
|
Packit Service |
54dbc3 |
min_lid_ho, max_lid_ho);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* TODO - This should be runtime error, not a CL_ASSERT() */
|
|
Packit Service |
54dbc3 |
CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
node_guid = osm_node_get_node_guid(p_sw->p_node);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
The lid matrix contains the number of hops to each
|
|
Packit Service |
54dbc3 |
lid from each port. From this information we determine
|
|
Packit Service |
54dbc3 |
how best to distribute the LID range across the ports
|
|
Packit Service |
54dbc3 |
that can reach those LIDs.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from,
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->ignore_existing_lfts,
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.lmc,
|
|
Packit Service |
54dbc3 |
p_mgr->is_dor,
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.port_shifting,
|
|
Packit Service |
54dbc3 |
!lid_offset && p_port->use_scatter,
|
|
Packit Service |
54dbc3 |
OSM_LFT);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (port == OSM_NO_PATH) {
|
|
Packit Service |
54dbc3 |
/* do not try to overwrite the ppro of non existing port ... */
|
|
Packit Service |
54dbc3 |
is_ignored_by_port_prof = TRUE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"No path to get to LID %u from switch 0x%" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
lid_ho, cl_ntoh64(node_guid));
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port);
|
|
Packit Service |
54dbc3 |
if (!p)
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Routing LID %u to port %u for switch 0x%" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
lid_ho, port, cl_ntoh64(node_guid));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
we would like to optionally ignore this port in equalization
|
|
Packit Service |
54dbc3 |
as in the case of the Mellanox Anafa Internal PCI TCA port
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
is_ignored_by_port_prof = p->is_prof_ignored;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
We also would ignore this route if the target lid is of
|
|
Packit Service |
54dbc3 |
a switch and the port_profile_switch_node is not TRUE
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (!p_mgr->p_subn->opt.port_profile_switch_nodes)
|
|
Packit Service |
54dbc3 |
is_ignored_by_port_prof |=
|
|
Packit Service |
54dbc3 |
(osm_node_get_type(p_port->p_node) ==
|
|
Packit Service |
54dbc3 |
IB_NODE_TYPE_SWITCH);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
We have selected the port for this LID.
|
|
Packit Service |
54dbc3 |
Write it to the forwarding tables.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
p_sw->new_lft[lid_ho] = port;
|
|
Packit Service |
54dbc3 |
if (!is_ignored_by_port_prof) {
|
|
Packit Service |
54dbc3 |
struct osm_remote_node *rem_node_used;
|
|
Packit Service |
54dbc3 |
osm_switch_count_path(p_sw, port);
|
|
Packit Service |
54dbc3 |
if (port > 0 && p_port->priv &&
|
|
Packit Service |
54dbc3 |
(rem_node_used = find_and_add_remote_sys(p_sw, port,
|
|
Packit Service |
54dbc3 |
p_mgr->is_dor,
|
|
Packit Service |
54dbc3 |
p_port->priv)))
|
|
Packit Service |
54dbc3 |
rem_node_used->forwarded_to++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
Exit:
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void alloc_ports_priv(osm_ucast_mgr_t * mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
|
|
Packit Service |
54dbc3 |
struct osm_remote_guids_count *r;
|
|
Packit Service |
54dbc3 |
osm_port_t *port;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item;
|
|
Packit Service |
54dbc3 |
unsigned lmc;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
port = (osm_port_t *) item;
|
|
Packit Service |
54dbc3 |
lmc = ib_port_info_get_lmc(&port->p_physp->port_info);
|
|
Packit Service |
54dbc3 |
r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
|
|
Packit Service |
54dbc3 |
if (!r) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: "
|
|
Packit Service |
54dbc3 |
"cannot allocate memory to track remote"
|
|
Packit Service |
54dbc3 |
" systems for lmc > 0\n");
|
|
Packit Service |
54dbc3 |
port->priv = NULL;
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc));
|
|
Packit Service |
54dbc3 |
port->priv = r;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void free_ports_priv(osm_ucast_mgr_t * mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl;
|
|
Packit Service |
54dbc3 |
osm_port_t *port;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item;
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
port = (osm_port_t *) item;
|
|
Packit Service |
54dbc3 |
if (port->priv) {
|
|
Packit Service |
54dbc3 |
free(port->priv);
|
|
Packit Service |
54dbc3 |
port->priv = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item,
|
|
Packit Service |
54dbc3 |
IN void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = context;
|
|
Packit Service |
54dbc3 |
osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
unsigned i, lids_per_port;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_sw && p_sw->p_node);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Processing switch 0x%" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* Initialize LIDs in buffer to invalid port number. */
|
|
Packit Service |
54dbc3 |
memset(p_sw->new_lft, OSM_NO_PATH, p_sw->max_lid_ho + 1);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
alloc_ports_priv(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Iterate through every port setting LID routes for each
|
|
Packit Service |
54dbc3 |
port based on base LID and LMC value.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
|
|
Packit Service |
54dbc3 |
for (i = 0; i < lids_per_port; i++) {
|
|
Packit Service |
54dbc3 |
cl_qlist_t *list = &p_mgr->port_order_list;
|
|
Packit Service |
54dbc3 |
cl_list_item_t *item;
|
|
Packit Service |
54dbc3 |
for (item = cl_qlist_head(list); item != cl_qlist_end(list);
|
|
Packit Service |
54dbc3 |
item = cl_qlist_next(item)) {
|
|
Packit Service |
54dbc3 |
osm_port_t *port = cl_item_obj(item, port, list_item);
|
|
Packit Service |
54dbc3 |
ucast_mgr_process_port(p_mgr, p_sw, port, i);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
free_ports_priv(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_process_neighbors(IN cl_map_item_t * p_map_item,
|
|
Packit Service |
54dbc3 |
IN void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t * p_mgr = context;
|
|
Packit Service |
54dbc3 |
osm_node_t *p_node;
|
|
Packit Service |
54dbc3 |
osm_node_t *p_remote_node;
|
|
Packit Service |
54dbc3 |
uint32_t port_num;
|
|
Packit Service |
54dbc3 |
uint8_t remote_port_num;
|
|
Packit Service |
54dbc3 |
uint32_t num_ports;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_node = p_sw->p_node;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_node);
|
|
Packit Service |
54dbc3 |
CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Processing switch with GUID 0x%" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(p_node)));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
num_ports = osm_node_get_num_physp(p_node);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Start with port 1 to skip the switch's management port.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
for (port_num = 1; port_num < num_ports; port_num++) {
|
|
Packit Service |
54dbc3 |
p_remote_node = osm_node_get_remote_node(p_node,
|
|
Packit Service |
54dbc3 |
(uint8_t) port_num,
|
|
Packit Service |
54dbc3 |
&remote_port_num);
|
|
Packit Service |
54dbc3 |
if (p_remote_node && p_remote_node->sw
|
|
Packit Service |
54dbc3 |
&& (p_remote_node != p_node)) {
|
|
Packit Service |
54dbc3 |
/* make sure the link is healthy. If it is not - don't
|
|
Packit Service |
54dbc3 |
propagate through it. */
|
|
Packit Service |
54dbc3 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit Service |
54dbc3 |
if (!p_physp || !osm_link_is_healthy(p_physp))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ucast_mgr_process_neighbor(p_mgr, p_sw,
|
|
Packit Service |
54dbc3 |
p_remote_node->sw,
|
|
Packit Service |
54dbc3 |
(uint8_t) port_num,
|
|
Packit Service |
54dbc3 |
remote_port_num);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int set_hop_wf(void *ctx, uint64_t guid, char *p)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *m = ctx;
|
|
Packit Service |
54dbc3 |
osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
|
|
Packit Service |
54dbc3 |
osm_physp_t *physp;
|
|
Packit Service |
54dbc3 |
unsigned port, hop_wf;
|
|
Packit Service |
54dbc3 |
char *e;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!node || !node->sw) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"switch with guid 0x%016" PRIx64 " is not found\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!p || !*p || !(port = strtoul(p, &e, 0)) || (p == e) ||
|
|
Packit Service |
54dbc3 |
port >= node->sw->num_ports) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"bad port specified for guid 0x%016" PRIx64 "\n", guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p = e + 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!*p || !(hop_wf = strtoul(p, &e, 0)) || p == e || hop_wf >= 0x100) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"bad hop weight factor specified for guid 0x%016" PRIx64
|
|
Packit Service |
54dbc3 |
"port %u\n", guid, port);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
physp = osm_node_get_physp_ptr(node, port);
|
|
Packit Service |
54dbc3 |
if (!physp)
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
physp->hop_wf = hop_wf;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void set_default_hop_wf(cl_map_item_t * p_map_item, void *ctx)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
int i;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < sw->num_ports; i++) {
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
|
|
Packit Service |
54dbc3 |
if (p)
|
|
Packit Service |
54dbc3 |
p->hop_wf = 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int set_search_ordering_ports(void *ctx, uint64_t guid, char *p)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_subn_t *p_subn = ctx;
|
|
Packit Service |
54dbc3 |
osm_node_t *node = osm_get_node_by_guid(p_subn, cl_hton64(guid));
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw;
|
|
Packit Service |
54dbc3 |
uint8_t *search_ordering_ports = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t port;
|
|
Packit Service |
54dbc3 |
unsigned int *ports = NULL;
|
|
Packit Service |
54dbc3 |
const int bpw = sizeof(*ports)*8;
|
|
Packit Service |
54dbc3 |
int words;
|
|
Packit Service |
54dbc3 |
int i = 1; /* port 0 maps to port 0 */
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!node || !(sw = node->sw)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"switch with guid 0x%016" PRIx64 " is not found\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (sw->search_ordering_ports) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"switch with guid 0x%016" PRIx64 " already listed\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
search_ordering_ports = malloc(sizeof(*search_ordering_ports)*sw->num_ports);
|
|
Packit Service |
54dbc3 |
if (!search_ordering_ports) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR 3A07: cannot allocate memory for search_ordering_ports\n");
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
memset(search_ordering_ports, 0, sizeof(*search_ordering_ports)*sw->num_ports);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* the ports array is for record keeping of which ports have
|
|
Packit Service |
54dbc3 |
* been seen */
|
|
Packit Service |
54dbc3 |
words = (sw->num_ports + bpw - 1)/bpw;
|
|
Packit Service |
54dbc3 |
ports = malloc(words*sizeof(*ports));
|
|
Packit Service |
54dbc3 |
if (!ports) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR 3A08: cannot allocate memory for ports\n");
|
|
Packit Service |
54dbc3 |
free(search_ordering_ports);
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
memset(ports, 0, words*sizeof(*ports));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while ((*p != '\0') && (*p != '#')) {
|
|
Packit Service |
54dbc3 |
char *e;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
port = strtoul(p, &e, 0);
|
|
Packit Service |
54dbc3 |
if ((p == e) || (port == 0) || (port >= sw->num_ports) ||
|
|
Packit Service |
54dbc3 |
!osm_node_get_physp_ptr(node, port)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"bad port %d specified for guid 0x%016" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
port, guid);
|
|
Packit Service |
54dbc3 |
free(search_ordering_ports);
|
|
Packit Service |
54dbc3 |
free(ports);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (ports[port/bpw] & (1u << (port%bpw))) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"port %d already specified for guid 0x%016" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
port, guid);
|
|
Packit Service |
54dbc3 |
free(search_ordering_ports);
|
|
Packit Service |
54dbc3 |
free(ports);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ports[port/bpw] |= (1u << (port%bpw));
|
|
Packit Service |
54dbc3 |
search_ordering_ports[i++] = port;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p = e;
|
|
Packit Service |
54dbc3 |
while (isspace(*p)) {
|
|
Packit Service |
54dbc3 |
p++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (i > 1) {
|
|
Packit Service |
54dbc3 |
for (port = 1; port < sw->num_ports; port++) {
|
|
Packit Service |
54dbc3 |
/* fill out the rest of the search_ordering_ports array
|
|
Packit Service |
54dbc3 |
* in sequence using the remaining unspecified
|
|
Packit Service |
54dbc3 |
* ports.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (!(ports[port/bpw] & (1u << (port%bpw)))) {
|
|
Packit Service |
54dbc3 |
search_ordering_ports[i++] = port;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
sw->search_ordering_ports = search_ordering_ports;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
free(search_ordering_ports);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
free(ports);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i;
|
|
Packit Service |
54dbc3 |
uint32_t iteration_max;
|
|
Packit Service |
54dbc3 |
cl_qmap_t *p_sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Starting switches' Min Hop Table Assignment\n");
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Set up the weighting factors for the routing.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(p_sw_guid_tbl, set_default_hop_wf, NULL);
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.hop_weights_file) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Fetching hop weight factor file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.hop_weights_file);
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_mgr->p_subn->opt.hop_weights_file,
|
|
Packit Service |
54dbc3 |
set_hop_wf, p_mgr)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: "
|
|
Packit Service |
54dbc3 |
"cannot parse hop_weights_file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.hop_weights_file);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Set the switch matrices for each switch's own port 0 LID(s)
|
|
Packit Service |
54dbc3 |
then set the lid matrices for the each switch's leaf nodes.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(p_sw_guid_tbl, ucast_mgr_process_hop_0_1, p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Get the switch matrices for each switch's neighbors.
|
|
Packit Service |
54dbc3 |
This process requires a number of iterations equal to
|
|
Packit Service |
54dbc3 |
the number of switches in the subnet minus 1.
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
In each iteration, a switch learns the lid/port/hop
|
|
Packit Service |
54dbc3 |
information (as contained by a switch's lid matrix) from
|
|
Packit Service |
54dbc3 |
its immediate neighbors. After each iteration, a switch
|
|
Packit Service |
54dbc3 |
(and it's neighbors) know more routing information than
|
|
Packit Service |
54dbc3 |
it did on the previous iteration.
|
|
Packit Service |
54dbc3 |
Thus, by repeatedly absorbing the routing information of
|
|
Packit Service |
54dbc3 |
neighbor switches, every switch eventually learns how to
|
|
Packit Service |
54dbc3 |
route all LIDs on the subnet.
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
Note that there may not be any switches in the subnet if
|
|
Packit Service |
54dbc3 |
we are in simple p2p configuration.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
iteration_max = cl_qmap_count(p_sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
If there are switches in the subnet, iterate until the lid
|
|
Packit Service |
54dbc3 |
matrix has been constructed. Otherwise, just immediately
|
|
Packit Service |
54dbc3 |
indicate we're done if no switches exist.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (iteration_max) {
|
|
Packit Service |
54dbc3 |
iteration_max--;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
we need to find out when the propagation of
|
|
Packit Service |
54dbc3 |
hop counts has relaxed. So this global variable
|
|
Packit Service |
54dbc3 |
is preset to 0 on each iteration and if
|
|
Packit Service |
54dbc3 |
if non of the switches was set will exit the
|
|
Packit Service |
54dbc3 |
while loop
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
p_mgr->some_hop_count_set = TRUE;
|
|
Packit Service |
54dbc3 |
for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set;
|
|
Packit Service |
54dbc3 |
i++) {
|
|
Packit Service |
54dbc3 |
p_mgr->some_hop_count_set = FALSE;
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(p_sw_guid_tbl,
|
|
Packit Service |
54dbc3 |
ucast_mgr_process_neighbors, p_mgr);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Min-hop propagated in %d steps\n", i);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t *p_sw;
|
|
Packit Service |
54dbc3 |
uint16_t lids;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl);
|
|
Packit Service |
54dbc3 |
lids = lids ? lids - 1 : 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {
|
|
Packit Service |
54dbc3 |
if (osm_switch_prepare_path_rebuild(p_sw, lids)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: "
|
|
Packit Service |
54dbc3 |
"cannot setup switch 0x%016" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (p_sw->search_ordering_ports) {
|
|
Packit Service |
54dbc3 |
free(p_sw->search_ordering_ports);
|
|
Packit Service |
54dbc3 |
p_sw->search_ordering_ports = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_subn->opt.port_search_ordering_file) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Fetching dimension ports file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_subn->opt.port_search_ordering_file);
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_subn->opt.port_search_ordering_file,
|
|
Packit Service |
54dbc3 |
set_search_ordering_ports, p_subn)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0F: "
|
|
Packit Service |
54dbc3 |
"cannot parse port_search_ordering_file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_subn->opt.port_search_ordering_file);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *m = ctx;
|
|
Packit Service |
54dbc3 |
osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!port) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"port guid not found: 0x%016" PRIx64 "\n", guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (port->flag) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"port guid specified multiple times 0x%016" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
|
|
Packit Service |
54dbc3 |
port->flag = 1;
|
|
Packit Service |
54dbc3 |
port->use_scatter = (m->p_subn->opt.guid_routing_order_no_scatter == TRUE) ? 0 : m->p_subn->opt.scatter_ports;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void add_port_to_order_list(cl_map_item_t * p_map_item, void *ctx)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_port_t *port = (osm_port_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *m = ctx;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!port->flag) {
|
|
Packit Service |
54dbc3 |
port->use_scatter = m->p_subn->opt.scatter_ports;
|
|
Packit Service |
54dbc3 |
cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
|
|
Packit Service |
54dbc3 |
} else
|
|
Packit Service |
54dbc3 |
port->flag = 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int mark_ignored_port(void *ctx, uint64_t guid, char *p)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *m = ctx;
|
|
Packit Service |
54dbc3 |
osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid));
|
|
Packit Service |
54dbc3 |
osm_physp_t *physp;
|
|
Packit Service |
54dbc3 |
unsigned port;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!node || !node->sw) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"switch with guid 0x%016" PRIx64 " is not found\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!p || !*p || !(port = strtoul(p, NULL, 0)) ||
|
|
Packit Service |
54dbc3 |
port >= node->sw->num_ports) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"bad port specified for guid 0x%016" PRIx64 "\n", guid);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
physp = osm_node_get_physp_ptr(node, port);
|
|
Packit Service |
54dbc3 |
if (!physp)
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
physp->is_prof_ignored = 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void clear_prof_ignore_flag(cl_map_item_t * p_map_item, void *ctx)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
int i;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < sw->num_ports; i++) {
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i);
|
|
Packit Service |
54dbc3 |
if (p)
|
|
Packit Service |
54dbc3 |
p->is_prof_ignored = 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void add_sw_endports_to_order_list(osm_switch_t * sw,
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t * m)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_port_t *port;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p;
|
|
Packit Service |
54dbc3 |
int i;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < sw->num_ports; i++) {
|
|
Packit Service |
54dbc3 |
p = osm_node_get_physp_ptr(sw->p_node, i);
|
|
Packit Service |
54dbc3 |
if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) {
|
|
Packit Service |
54dbc3 |
port = osm_get_port_by_guid(m->p_subn,
|
|
Packit Service |
54dbc3 |
p->p_remote_physp->
|
|
Packit Service |
54dbc3 |
port_guid);
|
|
Packit Service |
54dbc3 |
if (!port || port->flag)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
cl_qlist_insert_tail(&m->port_order_list,
|
|
Packit Service |
54dbc3 |
&port->list_item);
|
|
Packit Service |
54dbc3 |
port->flag = 1;
|
|
Packit Service |
54dbc3 |
port->use_scatter = m->p_subn->opt.scatter_ports;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void sw_count_endport_links(osm_switch_t * sw)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_physp_t *p;
|
|
Packit Service |
54dbc3 |
int i;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
sw->endport_links = 0;
|
|
Packit Service |
54dbc3 |
for (i = 1; i < sw->num_ports; i++) {
|
|
Packit Service |
54dbc3 |
p = osm_node_get_physp_ptr(sw->p_node, i);
|
|
Packit Service |
54dbc3 |
if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw)
|
|
Packit Service |
54dbc3 |
sw->endport_links++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int compar_sw_load(const void *s1, const void *s2)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
#define get_sw_endport_links(s) (*(osm_switch_t **)s)->endport_links
|
|
Packit Service |
54dbc3 |
return get_sw_endport_links(s2) - get_sw_endport_links(s1);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void sort_ports_by_switch_load(osm_ucast_mgr_t * m)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
int i, num = cl_qmap_count(&m->p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
void **s = malloc(num * sizeof(*s));
|
|
Packit Service |
54dbc3 |
if (!s) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_ERROR, "ERR 3A0C: "
|
|
Packit Service |
54dbc3 |
"No memory, skip by switch load sorting.\n");
|
|
Packit Service |
54dbc3 |
return;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
s[0] = cl_qmap_head(&m->p_subn->sw_guid_tbl);
|
|
Packit Service |
54dbc3 |
for (i = 1; i < num; i++)
|
|
Packit Service |
54dbc3 |
s[i] = cl_qmap_next(s[i - 1]);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 0; i < num; i++)
|
|
Packit Service |
54dbc3 |
sw_count_endport_links(s[i]);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
qsort(s, num, sizeof(*s), compar_sw_load);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 0; i < num; i++)
|
|
Packit Service |
54dbc3 |
add_sw_endports_to_order_list(s[i], m);
|
|
Packit Service |
54dbc3 |
free(s);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_mgr_build_lfts(osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cl_qlist_init(&p_mgr->port_order_list);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.guid_routing_order_file) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Fetching guid routing order file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.guid_routing_order_file);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file,
|
|
Packit Service |
54dbc3 |
add_guid_to_order_list, p_mgr))
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0D: "
|
|
Packit Service |
54dbc3 |
"cannot parse guid routing order file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.guid_routing_order_file);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
sort_ports_by_switch_load(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.port_prof_ignore_file) {
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
|
|
Packit Service |
54dbc3 |
clear_prof_ignore_flag, NULL);
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file,
|
|
Packit Service |
54dbc3 |
mark_ignored_port, p_mgr)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0E: "
|
|
Packit Service |
54dbc3 |
"cannot parse port prof ignore file \'%s\'\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.port_prof_ignore_file);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl,
|
|
Packit Service |
54dbc3 |
add_port_to_order_list, p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_process_tbl,
|
|
Packit Service |
54dbc3 |
p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qlist_remove_all(&p_mgr->port_order_list);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item,
|
|
Packit Service |
54dbc3 |
IN void *cxt)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = cxt;
|
|
Packit Service |
54dbc3 |
osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
|
|
Packit Service |
54dbc3 |
osm_node_t *p_node;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp;
|
|
Packit Service |
54dbc3 |
osm_dr_path_t *p_path;
|
|
Packit Service |
54dbc3 |
osm_madw_context_t context;
|
|
Packit Service |
54dbc3 |
ib_api_status_t status;
|
|
Packit Service |
54dbc3 |
ib_switch_info_t si;
|
|
Packit Service |
54dbc3 |
boolean_t set_swinfo_require = FALSE;
|
|
Packit Service |
54dbc3 |
uint16_t lin_top;
|
|
Packit Service |
54dbc3 |
uint8_t life_state;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_sw && p_sw->max_lid_ho);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_node = p_sw->p_node;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_node);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_mgr->max_lid < p_sw->max_lid_ho)
|
|
Packit Service |
54dbc3 |
p_mgr->max_lid = p_sw->max_lid_ho;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_physp = osm_node_get_physp_ptr(p_node, 0);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_physp);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Set the top of the unicast forwarding table.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
si = p_sw->switch_info;
|
|
Packit Service |
54dbc3 |
lin_top = cl_hton16(p_sw->max_lid_ho);
|
|
Packit Service |
54dbc3 |
if (lin_top != si.lin_top) {
|
|
Packit Service |
54dbc3 |
set_swinfo_require = TRUE;
|
|
Packit Service |
54dbc3 |
si.lin_top = lin_top;
|
|
Packit Service |
54dbc3 |
context.si_context.lft_top_change = TRUE;
|
|
Packit Service |
54dbc3 |
} else
|
|
Packit Service |
54dbc3 |
context.si_context.lft_top_change = FALSE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
life_state = si.life_state;
|
|
Packit Service |
54dbc3 |
ib_switch_info_set_life_time(&si, p_mgr->p_subn->opt.packet_life_time);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (life_state != si.life_state)
|
|
Packit Service |
54dbc3 |
set_swinfo_require = TRUE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (set_swinfo_require) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Setting switch FT top to LID %u\n", p_sw->max_lid_ho);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
context.si_context.light_sweep = FALSE;
|
|
Packit Service |
54dbc3 |
context.si_context.node_guid = osm_node_get_node_guid(p_node);
|
|
Packit Service |
54dbc3 |
context.si_context.set_method = TRUE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
|
|
Packit Service |
54dbc3 |
sizeof(si), IB_MAD_ATTR_SWITCH_INFO,
|
|
Packit Service |
54dbc3 |
0, FALSE,
|
|
Packit Service |
54dbc3 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit Service |
54dbc3 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (status != IB_SUCCESS)
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
|
|
Packit Service |
54dbc3 |
"Sending SwitchInfo attribute failed (%s)\n",
|
|
Packit Service |
54dbc3 |
ib_get_err_str(status));
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr,
|
|
Packit Service |
54dbc3 |
IN uint16_t block_id_ho)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_madw_context_t context;
|
|
Packit Service |
54dbc3 |
osm_dr_path_t *p_path;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp;
|
|
Packit Service |
54dbc3 |
ib_api_status_t status;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
Send linear forwarding table blocks to the switch
|
|
Packit Service |
54dbc3 |
as long as the switch indicates it has blocks needing
|
|
Packit Service |
54dbc3 |
configuration.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (!p_sw->new_lft) {
|
|
Packit Service |
54dbc3 |
/* any routing should provide the new_lft */
|
|
Packit Service |
54dbc3 |
CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
|
|
Packit Service |
54dbc3 |
p_mgr->cache_valid && !p_sw->need_update);
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_physp = osm_node_get_physp_ptr(p_sw->p_node, 0);
|
|
Packit Service |
54dbc3 |
if (!p_physp)
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_path = osm_physp_get_dr_path_ptr(p_physp);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
context.lft_context.node_guid = osm_node_get_node_guid(p_sw->p_node);
|
|
Packit Service |
54dbc3 |
context.lft_context.set_method = TRUE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!p_sw->need_update && !p_mgr->p_subn->need_update &&
|
|
Packit Service |
54dbc3 |
!memcmp(p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
|
|
Packit Service |
54dbc3 |
p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE,
|
|
Packit Service |
54dbc3 |
IB_SMP_DATA_SIZE))
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
* Zero the stored LFT block, so in case the MAD will end up
|
|
Packit Service |
54dbc3 |
* with error, we will resend it in the next sweep.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
memset(p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, 0,
|
|
Packit Service |
54dbc3 |
IB_SMP_DATA_SIZE);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Writing FT block %u to switch 0x%" PRIx64 "\n", block_id_ho,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(context.lft_context.node_guid));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
status = osm_req_set(p_mgr->sm, p_path,
|
|
Packit Service |
54dbc3 |
p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
|
|
Packit Service |
54dbc3 |
IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL,
|
|
Packit Service |
54dbc3 |
cl_hton32(block_id_ho), FALSE,
|
|
Packit Service |
54dbc3 |
ib_port_info_get_m_key(&p_physp->port_info),
|
|
Packit Service |
54dbc3 |
0, CL_DISP_MSGID_NONE, &context);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (status != IB_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A10: "
|
|
Packit Service |
54dbc3 |
"Sending linear fwd. tbl. block failed (%s)\n",
|
|
Packit Service |
54dbc3 |
ib_get_err_str(status));
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void ucast_mgr_pipeline_fwd_tbl(osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cl_qmap_t *tbl;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item;
|
|
Packit Service |
54dbc3 |
unsigned i, max_block = p_mgr->max_lid / IB_SMP_DATA_SIZE + 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
for (i = 0; i < max_block; i++)
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item))
|
|
Packit Service |
54dbc3 |
set_lft_block((osm_switch_t *)item, p_mgr, i);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
void osm_ucast_mgr_set_fwd_tables(osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
p_mgr->max_lid = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_set_fwd_top,
|
|
Packit Service |
54dbc3 |
p_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ucast_mgr_pipeline_fwd_tbl(p_mgr);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t * osm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
int ret;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"building routing with \'%s\' routing algorithm...\n", r->name);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* Set the before each lft build to keep the routes in place between sweeps */
|
|
Packit Service |
54dbc3 |
if (osm->subn.opt.scatter_ports)
|
|
Packit Service |
54dbc3 |
srandom(osm->subn.opt.scatter_ports);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!r->build_lid_matrices ||
|
|
Packit Service |
54dbc3 |
(ret = r->build_lid_matrices(r->context)) > 0)
|
|
Packit Service |
54dbc3 |
ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (ret < 0) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&osm->log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"%s: cannot build lid matrices\n", r->name);
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!r->ucast_build_fwd_tables ||
|
|
Packit Service |
54dbc3 |
(ret = r->ucast_build_fwd_tables(r->context)) > 0)
|
|
Packit Service |
54dbc3 |
ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (ret < 0) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(&osm->log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"%s: cannot build fwd tables\n", r->name);
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
osm->routing_engine_used = r;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_set_fwd_tables(&osm->sm.ucast_mgr);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_opensm_t *p_osm;
|
|
Packit Service |
54dbc3 |
struct osm_routing_engine *p_routing_eng;
|
|
Packit Service |
54dbc3 |
cl_qmap_t *p_sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
int failed = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
p_osm = p_mgr->p_subn->p_osm;
|
|
Packit Service |
54dbc3 |
p_routing_eng = p_osm->routing_engine_list;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
If there are no switches in the subnet, we are done.
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (cl_qmap_count(p_sw_guid_tbl) == 0 ||
|
|
Packit Service |
54dbc3 |
ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0)
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
failed = -1;
|
|
Packit Service |
54dbc3 |
p_osm->routing_engine_used = NULL;
|
|
Packit Service |
54dbc3 |
while (p_routing_eng) {
|
|
Packit Service |
54dbc3 |
failed = ucast_mgr_route(p_routing_eng, p_osm);
|
|
Packit Service |
54dbc3 |
if (!failed)
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
p_routing_eng = p_routing_eng->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!p_osm->routing_engine_used &&
|
|
Packit Service |
54dbc3 |
p_osm->no_fallback_routing_engine != TRUE) {
|
|
Packit Service |
54dbc3 |
/* If configured routing algorithm failed, use default MinHop */
|
|
Packit Service |
54dbc3 |
failed = ucast_mgr_route(p_osm->default_routing_engine, p_osm);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_osm->routing_engine_used) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"%s tables configured on all switches\n",
|
|
Packit Service |
54dbc3 |
osm_routing_engine_type_str(p_osm->
|
|
Packit Service |
54dbc3 |
routing_engine_used->type));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.use_ucast_cache)
|
|
Packit Service |
54dbc3 |
p_mgr->cache_valid = TRUE;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->subnet_initialization_error = TRUE;
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"No routing engine able to successfully configure "
|
|
Packit Service |
54dbc3 |
" switch tables on current fabric\n");
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
Exit:
|
|
Packit Service |
54dbc3 |
CL_PLOCK_RELEASE(p_mgr->p_lock);
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return failed;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_build_lid_matrices(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
return osm_ucast_mgr_build_lid_matrices(context);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_build_lfts(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
return ucast_mgr_build_lfts(context);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
r->context = &osm->sm.ucast_mgr;
|
|
Packit Service |
54dbc3 |
r->build_lid_matrices = ucast_build_lid_matrices;
|
|
Packit Service |
54dbc3 |
r->ucast_build_fwd_tables = ucast_build_lfts;
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int ucast_dor_build_lfts(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *mgr = context;
|
|
Packit Service |
54dbc3 |
int ret;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
mgr->is_dor = 1;
|
|
Packit Service |
54dbc3 |
ret = ucast_mgr_build_lfts(mgr);
|
|
Packit Service |
54dbc3 |
mgr->is_dor = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t * osm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
r->context = &osm->sm.ucast_mgr;
|
|
Packit Service |
54dbc3 |
r->build_lid_matrices = ucast_build_lid_matrices;
|
|
Packit Service |
54dbc3 |
r->ucast_build_fwd_tables = ucast_dor_build_lfts;
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int ucast_dummy_build_lid_matrices(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|