|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2008-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2008-2009 Mellanox Technologies LTD. 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 OpenSM Cached Unicast Routing
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Environment:
|
|
Packit |
13e616 |
* Linux User Mode
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <string.h>
|
|
Packit |
13e616 |
#include <ctype.h>
|
|
Packit |
13e616 |
#include <errno.h>
|
|
Packit |
13e616 |
#include <iba/ib_types.h>
|
|
Packit |
13e616 |
#include <complib/cl_qmap.h>
|
|
Packit |
13e616 |
#include <complib/cl_pool.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_UCAST_CACHE_C
|
|
Packit |
13e616 |
#include <opensm/osm_opensm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_ucast_mgr.h>
|
|
Packit |
13e616 |
#include <opensm/osm_ucast_cache.h>
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_node.h>
|
|
Packit |
13e616 |
#include <opensm/osm_port.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
typedef struct cache_port {
|
|
Packit |
13e616 |
boolean_t is_leaf;
|
|
Packit |
13e616 |
uint16_t remote_lid_ho;
|
|
Packit |
13e616 |
} cache_port_t;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
typedef struct cache_switch {
|
|
Packit |
13e616 |
cl_map_item_t map_item;
|
|
Packit |
13e616 |
boolean_t dropped;
|
|
Packit |
13e616 |
uint16_t max_lid_ho;
|
|
Packit |
13e616 |
uint16_t num_hops;
|
|
Packit |
13e616 |
uint8_t **hops;
|
|
Packit |
13e616 |
uint8_t *lft;
|
|
Packit |
13e616 |
uint8_t num_ports;
|
|
Packit |
13e616 |
cache_port_t ports[0];
|
|
Packit |
13e616 |
} cache_switch_t;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static uint16_t cache_sw_get_base_lid_ho(cache_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
return p_sw->ports[0].remote_lid_ho;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static boolean_t cache_sw_is_leaf(cache_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
return p_sw->ports[0].is_leaf;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void cache_sw_set_leaf(cache_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
p_sw->ports[0].is_leaf = TRUE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static cache_switch_t *cache_sw_new(uint16_t lid_ho, unsigned num_ports)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw = malloc(sizeof(cache_switch_t) +
|
|
Packit |
13e616 |
num_ports * sizeof(cache_port_t));
|
|
Packit |
13e616 |
if (!p_cache_sw)
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(p_cache_sw, 0,
|
|
Packit |
13e616 |
sizeof(*p_cache_sw) + num_ports * sizeof(cache_port_t));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw->num_ports = num_ports;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* port[0] fields represent this switch details - lid and type */
|
|
Packit |
13e616 |
p_cache_sw->ports[0].remote_lid_ho = lid_ho;
|
|
Packit |
13e616 |
p_cache_sw->ports[0].is_leaf = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return p_cache_sw;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void cache_sw_destroy(cache_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_sw)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_sw->lft)
|
|
Packit |
13e616 |
free(p_sw->lft);
|
|
Packit |
13e616 |
if (p_sw->hops) {
|
|
Packit |
13e616 |
for (i = 0; i < p_sw->num_hops; i++)
|
|
Packit |
13e616 |
if (p_sw->hops[i])
|
|
Packit |
13e616 |
free(p_sw->hops[i]);
|
|
Packit |
13e616 |
free(p_sw->hops);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
free(p_sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static cache_switch_t *cache_get_sw(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw = (cache_switch_t *)
|
|
Packit |
13e616 |
cl_qmap_get(&p_mgr->cache_sw_tbl, lid_ho);
|
|
Packit |
13e616 |
if (p_cache_sw == (cache_switch_t *)
|
|
Packit |
13e616 |
cl_qmap_end(&p_mgr->cache_sw_tbl))
|
|
Packit |
13e616 |
p_cache_sw = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return p_cache_sw;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void cache_add_sw_link(osm_ucast_mgr_t * p_mgr, osm_physp_t *p,
|
|
Packit |
13e616 |
uint16_t remote_lid_ho, boolean_t is_ca)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw;
|
|
Packit |
13e616 |
uint16_t lid_ho = cl_ntoh16(osm_node_get_base_lid(p->p_node, 0));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!lid_ho || !remote_lid_ho || !p->port_num)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Caching switch port: lid %u [port %u] -> lid %u (%s)\n",
|
|
Packit |
13e616 |
lid_ho, p->port_num, remote_lid_ho, (is_ca) ? "CA/RTR" : "SW");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw = cache_get_sw(p_mgr, lid_ho);
|
|
Packit |
13e616 |
if (!p_cache_sw) {
|
|
Packit |
13e616 |
p_cache_sw = cache_sw_new(lid_ho, p->p_node->sw->num_ports);
|
|
Packit |
13e616 |
if (!p_cache_sw) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR AD01: Out of memory - cache is invalid\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
cl_qmap_insert(&p_mgr->cache_sw_tbl, lid_ho,
|
|
Packit |
13e616 |
&p_cache_sw->map_item);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p->port_num >= p_cache_sw->num_ports) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR AD02: Wrong switch? - cache is invalid\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (is_ca)
|
|
Packit |
13e616 |
cache_sw_set_leaf(p_cache_sw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_cache_sw->ports[p->port_num].remote_lid_ho == 0) {
|
|
Packit |
13e616 |
/* cache this link only if it hasn't been already cached */
|
|
Packit |
13e616 |
p_cache_sw->ports[p->port_num].remote_lid_ho = remote_lid_ho;
|
|
Packit |
13e616 |
p_cache_sw->ports[p->port_num].is_leaf = is_ca;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void cache_cleanup_switches(osm_ucast_mgr_t * p_mgr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_sw;
|
|
Packit |
13e616 |
cache_switch_t *p_next_sw;
|
|
Packit |
13e616 |
unsigned port_num;
|
|
Packit |
13e616 |
boolean_t found_port;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
while (p_next_sw !=
|
|
Packit |
13e616 |
(cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) {
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
found_port = FALSE;
|
|
Packit |
13e616 |
for (port_num = 1; port_num < p_sw->num_ports; port_num++)
|
|
Packit |
13e616 |
if (p_sw->ports[port_num].remote_lid_ho)
|
|
Packit |
13e616 |
found_port = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!found_port) {
|
|
Packit |
13e616 |
cl_qmap_remove_item(&p_mgr->cache_sw_tbl,
|
|
Packit |
13e616 |
&p_sw->map_item);
|
|
Packit |
13e616 |
cache_sw_destroy(p_sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
cache_check_link_change(osm_ucast_mgr_t * p_mgr,
|
|
Packit |
13e616 |
osm_physp_t * p_physp_1, osm_physp_t * p_physp_2)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
CL_ASSERT(p_physp_1 && p_physp_2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_physp_1->p_remote_physp && !p_physp_2->p_remote_physp)
|
|
Packit |
13e616 |
/* both ports were down - new link */
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* unicast cache cannot tolerate any link location change */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if ((p_physp_1->p_remote_physp &&
|
|
Packit |
13e616 |
p_physp_1->p_remote_physp->p_remote_physp) ||
|
|
Packit |
13e616 |
(p_physp_2->p_remote_physp &&
|
|
Packit |
13e616 |
p_physp_2->p_remote_physp->p_remote_physp)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Link location change discovered\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void cache_remove_port(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho,
|
|
Packit |
13e616 |
uint8_t port_num, uint16_t remote_lid_ho,
|
|
Packit |
13e616 |
boolean_t is_ca)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw = cache_get_sw(p_mgr, lid_ho);
|
|
Packit |
13e616 |
if (!p_cache_sw) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Found uncached switch/link (lid %u, port %u)\n",
|
|
Packit |
13e616 |
lid_ho, port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (port_num >= p_cache_sw->num_ports ||
|
|
Packit |
13e616 |
!p_cache_sw->ports[port_num].remote_lid_ho) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Found uncached switch link (lid %u, port %u)\n",
|
|
Packit |
13e616 |
lid_ho, port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_cache_sw->ports[port_num].remote_lid_ho != remote_lid_ho) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote lid change on switch lid %u, port %u "
|
|
Packit |
13e616 |
"(was %u, now %u)\n", lid_ho, port_num,
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].remote_lid_ho,
|
|
Packit |
13e616 |
remote_lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if ((p_cache_sw->ports[port_num].is_leaf && !is_ca) ||
|
|
Packit |
13e616 |
(!p_cache_sw->ports[port_num].is_leaf && is_ca)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote node type change on switch lid %u, port %u\n",
|
|
Packit |
13e616 |
lid_ho, port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"New link from lid %u, port %u to lid %u - "
|
|
Packit |
13e616 |
"found in cache\n", lid_ho, port_num, remote_lid_ho);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* the new link was cached - clean it from the cache */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].remote_lid_ho = 0;
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].is_leaf = FALSE;
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
} /* cache_remove_port() */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void
|
|
Packit |
13e616 |
cache_restore_ucast_info(osm_ucast_mgr_t * p_mgr,
|
|
Packit |
13e616 |
cache_switch_t * p_cache_sw, osm_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* when seting unicast info, the cached port
|
|
Packit |
13e616 |
should have all the required info */
|
|
Packit |
13e616 |
CL_ASSERT(p_cache_sw->max_lid_ho && p_cache_sw->lft &&
|
|
Packit |
13e616 |
p_cache_sw->num_hops && p_cache_sw->hops);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw->max_lid_ho = p_cache_sw->max_lid_ho;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_sw->new_lft)
|
|
Packit |
13e616 |
free(p_sw->new_lft);
|
|
Packit |
13e616 |
p_sw->new_lft = p_cache_sw->lft;
|
|
Packit |
13e616 |
p_cache_sw->lft = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw->num_hops = p_cache_sw->num_hops;
|
|
Packit |
13e616 |
p_cache_sw->num_hops = 0;
|
|
Packit |
13e616 |
if (p_sw->hops)
|
|
Packit |
13e616 |
free(p_sw->hops);
|
|
Packit |
13e616 |
p_sw->hops = p_cache_sw->hops;
|
|
Packit |
13e616 |
p_cache_sw->hops = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw->need_update = 2;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void ucast_cache_dump(osm_ucast_mgr_t * p_mgr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_sw;
|
|
Packit |
13e616 |
unsigned i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG))
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Dumping missing nodes/links as logged by unicast cache:\n");
|
|
Packit |
13e616 |
for (p_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
p_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
p_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"\t Switch lid %u %s%s\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_sw),
|
|
Packit |
13e616 |
(cache_sw_is_leaf(p_sw)) ? "[leaf switch] " : "",
|
|
Packit |
13e616 |
(p_sw->dropped) ? "[whole switch missing]" : "");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 1; i < p_sw->num_ports; i++)
|
|
Packit |
13e616 |
if (p_sw->ports[i].remote_lid_ho > 0)
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log,
|
|
Packit |
13e616 |
OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"\t - port %u -> lid %u %s\n",
|
|
Packit |
13e616 |
i, p_sw->ports[i].remote_lid_ho,
|
|
Packit |
13e616 |
(p_sw->ports[i].is_leaf) ?
|
|
Packit |
13e616 |
"[remote node is leaf]" : "");
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_ucast_cache_invalidate(osm_ucast_mgr_t * p_mgr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_sw;
|
|
Packit |
13e616 |
cache_switch_t *p_next_sw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_mgr->cache_valid = FALSE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
while (p_next_sw !=
|
|
Packit |
13e616 |
(cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) {
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
cache_sw_destroy(p_sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
cl_qmap_remove_all(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Unicast Cache invalidated\n");
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw;
|
|
Packit |
13e616 |
cache_switch_t *p_remote_cache_sw;
|
|
Packit |
13e616 |
unsigned port_num;
|
|
Packit |
13e616 |
unsigned max_ports;
|
|
Packit |
13e616 |
uint8_t remote_node_type;
|
|
Packit |
13e616 |
uint16_t lid_ho;
|
|
Packit |
13e616 |
uint16_t remote_lid_ho;
|
|
Packit |
13e616 |
osm_switch_t *p_sw;
|
|
Packit |
13e616 |
osm_switch_t *p_remote_sw;
|
|
Packit |
13e616 |
osm_node_t *p_node;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
osm_physp_t *p_remote_physp;
|
|
Packit |
13e616 |
osm_port_t *p_remote_port;
|
|
Packit |
13e616 |
cl_qmap_t *p_sw_tbl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* If there are no switches in the subnet, we are done */
|
|
Packit |
13e616 |
p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit |
13e616 |
if (cl_qmap_count(p_sw_tbl) == 0) {
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Scan all the physical switch ports in the subnet.
|
|
Packit |
13e616 |
* If the port need_update flag is on, check whether
|
|
Packit |
13e616 |
* it's just some node/port reset or a cached topology
|
|
Packit |
13e616 |
* change. Otherwise the cache is invalid.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
|
|
Packit |
13e616 |
p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl);
|
|
Packit |
13e616 |
p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_node = p_sw->p_node;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
|
|
Packit |
13e616 |
p_cache_sw = cache_get_sw(p_mgr, lid_ho);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
max_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* skip port 0 */
|
|
Packit |
13e616 |
for (port_num = 1; port_num < max_ports; port_num++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_physp || !p_physp->p_remote_physp ||
|
|
Packit |
13e616 |
!osm_physp_link_exists(p_physp,
|
|
Packit |
13e616 |
p_physp->p_remote_physp))
|
|
Packit |
13e616 |
/* no valid link */
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* While scanning all the physical ports in the subnet,
|
|
Packit |
13e616 |
* mark corresponding leaf switches in the cache.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_cache_sw &&
|
|
Packit |
13e616 |
!p_cache_sw->dropped &&
|
|
Packit |
13e616 |
!cache_sw_is_leaf(p_cache_sw) &&
|
|
Packit |
13e616 |
p_physp->p_remote_physp->p_node &&
|
|
Packit |
13e616 |
osm_node_get_type(p_physp->p_remote_physp->
|
|
Packit |
13e616 |
p_node) != IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
cache_sw_set_leaf(p_cache_sw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_physp->need_update)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Checking switch lid %u, port %u\n",
|
|
Packit |
13e616 |
lid_ho, port_num);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_physp = osm_physp_get_remote(p_physp);
|
|
Packit |
13e616 |
remote_node_type =
|
|
Packit |
13e616 |
osm_node_get_type(p_remote_physp->p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (remote_node_type == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
remote_lid_ho =
|
|
Packit |
13e616 |
cl_ntoh16(osm_node_get_base_lid
|
|
Packit |
13e616 |
(p_remote_physp->p_node, 0));
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
remote_lid_ho =
|
|
Packit |
13e616 |
cl_ntoh16(osm_node_get_base_lid
|
|
Packit |
13e616 |
(p_remote_physp->p_node,
|
|
Packit |
13e616 |
osm_physp_get_port_num
|
|
Packit |
13e616 |
(p_remote_physp)));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_cache_sw ||
|
|
Packit |
13e616 |
port_num >= p_cache_sw->num_ports ||
|
|
Packit |
13e616 |
!p_cache_sw->ports[port_num].remote_lid_ho) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* There is some uncached change on the port.
|
|
Packit |
13e616 |
* In general, the reasons might be as follows:
|
|
Packit |
13e616 |
* - switch reset
|
|
Packit |
13e616 |
* - port reset (or port down/up)
|
|
Packit |
13e616 |
* - quick connection location change
|
|
Packit |
13e616 |
* - new link (or new switch)
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* First two reasons allow cache usage, while
|
|
Packit |
13e616 |
* the last two reasons should invalidate cache.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* In case of quick connection location change,
|
|
Packit |
13e616 |
* cache would have been invalidated by
|
|
Packit |
13e616 |
* osm_ucast_cache_check_new_link() function.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* In case of new link between two known nodes,
|
|
Packit |
13e616 |
* cache also would have been invalidated by
|
|
Packit |
13e616 |
* osm_ucast_cache_check_new_link() function.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Another reason is cached link between two
|
|
Packit |
13e616 |
* known switches went back. In this case the
|
|
Packit |
13e616 |
* osm_ucast_cache_check_new_link() function would
|
|
Packit |
13e616 |
* clear both sides of the link from the cache
|
|
Packit |
13e616 |
* during the discovery process, so effectively
|
|
Packit |
13e616 |
* this would be equivalent to port reset.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* So three possible reasons remain:
|
|
Packit |
13e616 |
* - switch reset
|
|
Packit |
13e616 |
* - port reset (or port down/up)
|
|
Packit |
13e616 |
* - link of a new switch
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* To validate cache, we need to check only the
|
|
Packit |
13e616 |
* third reason - link of a new node/switch:
|
|
Packit |
13e616 |
* - If this is the local switch that is new,
|
|
Packit |
13e616 |
* then it should have (p_sw->need_update == 2).
|
|
Packit |
13e616 |
* - If the remote node is switch and it's new,
|
|
Packit |
13e616 |
* then it also should have
|
|
Packit |
13e616 |
* (p_sw->need_update == 2).
|
|
Packit |
13e616 |
* - If the remote node is CA/RTR and it's new,
|
|
Packit |
13e616 |
* then its port should have is_new flag on.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_sw->need_update == 2) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"New switch found (lid %u)\n",
|
|
Packit |
13e616 |
lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (remote_node_type == IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_sw =
|
|
Packit |
13e616 |
p_remote_physp->p_node->sw;
|
|
Packit |
13e616 |
if (p_remote_sw->need_update == 2) {
|
|
Packit |
13e616 |
/* this could also be case of
|
|
Packit |
13e616 |
switch coming back with an
|
|
Packit |
13e616 |
additional link that it
|
|
Packit |
13e616 |
didn't have before */
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log,
|
|
Packit |
13e616 |
OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"New switch/link found (lid %u)\n",
|
|
Packit |
13e616 |
remote_lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate
|
|
Packit |
13e616 |
(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Remote node is CA/RTR.
|
|
Packit |
13e616 |
* Get p_port of the remote node and
|
|
Packit |
13e616 |
* check its p_port->is_new flag.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_remote_port =
|
|
Packit |
13e616 |
osm_get_port_by_guid(p_mgr->p_subn,
|
|
Packit |
13e616 |
osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_remote_physp));
|
|
Packit |
13e616 |
if (!p_remote_port) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log,
|
|
Packit |
13e616 |
OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR AD04: No port was found for "
|
|
Packit |
13e616 |
"port GUID 0x%" PRIx64 "\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_remote_physp)));
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate
|
|
Packit |
13e616 |
(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (p_remote_port->is_new) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log,
|
|
Packit |
13e616 |
OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"New CA/RTR found (lid %u)\n",
|
|
Packit |
13e616 |
remote_lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate
|
|
Packit |
13e616 |
(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* The change on the port is cached.
|
|
Packit |
13e616 |
* In general, the reasons might be as follows:
|
|
Packit |
13e616 |
* - link between two known nodes went back
|
|
Packit |
13e616 |
* - one or more nodes went back, causing all
|
|
Packit |
13e616 |
* the links to reappear
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* If it was link that went back, then this case
|
|
Packit |
13e616 |
* would have been taken care of during the
|
|
Packit |
13e616 |
* discovery by osm_ucast_cache_check_new_link(),
|
|
Packit |
13e616 |
* so it's some node that went back.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if ((p_cache_sw->ports[port_num].is_leaf &&
|
|
Packit |
13e616 |
remote_node_type == IB_NODE_TYPE_SWITCH) ||
|
|
Packit |
13e616 |
(!p_cache_sw->ports[port_num].is_leaf &&
|
|
Packit |
13e616 |
remote_node_type != IB_NODE_TYPE_SWITCH)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote node type change on switch lid %u, port %u\n",
|
|
Packit |
13e616 |
lid_ho, port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_cache_sw->ports[port_num].remote_lid_ho !=
|
|
Packit |
13e616 |
remote_lid_ho) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Remote lid change on switch lid %u, port %u"
|
|
Packit |
13e616 |
"(was %u, now %u)\n",
|
|
Packit |
13e616 |
lid_ho, port_num,
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].
|
|
Packit |
13e616 |
remote_lid_ho, remote_lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* We don't care who is the node that has
|
|
Packit |
13e616 |
* reappeared in the subnet (local or remote).
|
|
Packit |
13e616 |
* What's important that the cached link matches
|
|
Packit |
13e616 |
* the real fabrics link.
|
|
Packit |
13e616 |
* Just clean it from cache.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].remote_lid_ho = 0;
|
|
Packit |
13e616 |
p_cache_sw->ports[port_num].is_leaf = FALSE;
|
|
Packit |
13e616 |
if (p_cache_sw->dropped) {
|
|
Packit |
13e616 |
cache_restore_ucast_info(p_mgr,
|
|
Packit |
13e616 |
p_cache_sw,
|
|
Packit |
13e616 |
p_sw);
|
|
Packit |
13e616 |
p_cache_sw->dropped = FALSE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Restored link from cache: lid %u, port %u to lid %u\n",
|
|
Packit |
13e616 |
lid_ho, port_num, remote_lid_ho);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Remove all the cached switches that
|
|
Packit |
13e616 |
have all their ports restored */
|
|
Packit |
13e616 |
cache_cleanup_switches(p_mgr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Done scanning all the physical switch ports in the subnet.
|
|
Packit |
13e616 |
* Now we need to check the other side:
|
|
Packit |
13e616 |
* Scan all the cached switches and their ports:
|
|
Packit |
13e616 |
* - If the cached switch is missing in the subnet
|
|
Packit |
13e616 |
* (dropped flag is on), check that it's a leaf switch.
|
|
Packit |
13e616 |
* If it's not a leaf, the cache is invalid, because
|
|
Packit |
13e616 |
* cache can tolerate only leaf switch removal.
|
|
Packit |
13e616 |
* - If the cached switch exists in fabric, check all
|
|
Packit |
13e616 |
* its cached ports. These cached ports represent
|
|
Packit |
13e616 |
* missing link in the fabric.
|
|
Packit |
13e616 |
* The missing links that can be tolerated are:
|
|
Packit |
13e616 |
* + link to missing CA/RTR
|
|
Packit |
13e616 |
* + link to missing leaf switch
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
|
|
Packit |
13e616 |
p_cache_sw =
|
|
Packit |
13e616 |
(cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_cache_sw->dropped) {
|
|
Packit |
13e616 |
if (!cache_sw_is_leaf(p_cache_sw)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Missing non-leaf switch (lid %u)\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw));
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Missing leaf switch (lid %u) - "
|
|
Packit |
13e616 |
"continuing validation\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw));
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) {
|
|
Packit |
13e616 |
if (!p_cache_sw->ports[port_num].remote_lid_ho)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_cache_sw->ports[port_num].is_leaf) {
|
|
Packit |
13e616 |
CL_ASSERT(cache_sw_is_leaf(p_cache_sw));
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Switch lid %u, port %u: missing link to CA/RTR - "
|
|
Packit |
13e616 |
"continuing validation\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_remote_cache_sw = cache_get_sw(p_mgr,
|
|
Packit |
13e616 |
p_cache_sw->
|
|
Packit |
13e616 |
ports[port_num].
|
|
Packit |
13e616 |
remote_lid_ho);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Switch lid %u, port %u: missing link to existing switch\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!cache_sw_is_leaf(p_remote_cache_sw)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Switch lid %u, port %u: missing link to non-leaf switch\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* At this point we know that the missing link is to
|
|
Packit |
13e616 |
* a leaf switch. However, one case deserves a special
|
|
Packit |
13e616 |
* treatment. If there was a link between two leaf
|
|
Packit |
13e616 |
* switches, then missing leaf switch might break
|
|
Packit |
13e616 |
* routing. It is possible that there are routes
|
|
Packit |
13e616 |
* that use leaf switches to get from switch to switch
|
|
Packit |
13e616 |
* and not just to get to the CAs behind the leaf switch.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (cache_sw_is_leaf(p_cache_sw) &&
|
|
Packit |
13e616 |
cache_sw_is_leaf(p_remote_cache_sw)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Switch lid %u, port %u: missing leaf-2-leaf link\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Switch lid %u, port %u: missing remote leaf switch - "
|
|
Packit |
13e616 |
"continuing validation\n",
|
|
Packit |
13e616 |
cache_sw_get_base_lid_ho(p_cache_sw),
|
|
Packit |
13e616 |
port_num);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n");
|
|
Packit |
13e616 |
ucast_cache_dump(p_mgr);
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
} /* osm_ucast_cache_validate() */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_ucast_cache_check_new_link(osm_ucast_mgr_t * p_mgr,
|
|
Packit |
13e616 |
osm_node_t * p_node_1, uint8_t port_num_1,
|
|
Packit |
13e616 |
osm_node_t * p_node_2, uint8_t port_num_2)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t lid_ho_1;
|
|
Packit |
13e616 |
uint16_t lid_ho_2;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cache_check_link_change(p_mgr,
|
|
Packit |
13e616 |
osm_node_get_physp_ptr(p_node_1, port_num_1),
|
|
Packit |
13e616 |
osm_node_get_physp_ptr(p_node_2, port_num_2));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH &&
|
|
Packit |
13e616 |
osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Found CA-2-CA link\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* for code simplicity, we want the first node to be switch */
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
osm_node_t *tmp_node = p_node_1;
|
|
Packit |
13e616 |
uint8_t tmp_port_num = port_num_1;
|
|
Packit |
13e616 |
p_node_1 = p_node_2;
|
|
Packit |
13e616 |
port_num_1 = port_num_2;
|
|
Packit |
13e616 |
p_node_2 = tmp_node;
|
|
Packit |
13e616 |
port_num_2 = tmp_port_num;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0));
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
lid_ho_2 =
|
|
Packit |
13e616 |
cl_ntoh16(osm_node_get_base_lid(p_node_2, port_num_2));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!lid_ho_1 || !lid_ho_2) {
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* No lid assigned, which means that one of the nodes is new.
|
|
Packit |
13e616 |
* Need to wait for lid manager to process this node.
|
|
Packit |
13e616 |
* The switches and their links will be checked later when
|
|
Packit |
13e616 |
* the whole cache validity will be verified.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Link port %u <-> %u reveals new node - cache will "
|
|
Packit |
13e616 |
"be validated later\n", port_num_1, port_num_2);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cache_remove_port(p_mgr, lid_ho_1, port_num_1, lid_ho_2,
|
|
Packit |
13e616 |
(osm_node_get_type(p_node_2) !=
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* if node_2 is a switch, the link should be cleaned from its cache */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH)
|
|
Packit |
13e616 |
cache_remove_port(p_mgr, lid_ho_2,
|
|
Packit |
13e616 |
port_num_2, lid_ho_1, FALSE);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
} /* osm_ucast_cache_check_new_link() */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_ucast_cache_add_link(osm_ucast_mgr_t * p_mgr,
|
|
Packit |
13e616 |
osm_physp_t * p_physp1, osm_physp_t * p_physp2)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_node_t *p_node_1 = p_physp1->p_node, *p_node_2 = p_physp2->p_node;
|
|
Packit |
13e616 |
uint16_t lid_ho_1, lid_ho_2;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH &&
|
|
Packit |
13e616 |
osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropping CA-2-CA link\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if ((osm_node_get_type(p_node_1) == IB_NODE_TYPE_SWITCH &&
|
|
Packit |
13e616 |
!osm_node_get_physp_ptr(p_node_1, 0)) ||
|
|
Packit |
13e616 |
(osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH &&
|
|
Packit |
13e616 |
!osm_node_get_physp_ptr(p_node_2, 0))) {
|
|
Packit |
13e616 |
/* we're caching a link when one of the nodes
|
|
Packit |
13e616 |
has already been dropped and cached */
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Port %u <-> port %u: port0 on one of the nodes "
|
|
Packit |
13e616 |
"has already been dropped and cached\n",
|
|
Packit |
13e616 |
p_physp1->port_num, p_physp2->port_num);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* One of the nodes is switch. Just for code
|
|
Packit |
13e616 |
simplicity, make sure that it's the first node. */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
osm_physp_t *tmp = p_physp1;
|
|
Packit |
13e616 |
p_physp1 = p_physp2;
|
|
Packit |
13e616 |
p_physp2 = tmp;
|
|
Packit |
13e616 |
p_node_1 = p_physp1->p_node;
|
|
Packit |
13e616 |
p_node_2 = p_physp2->p_node;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_node_1->sw) {
|
|
Packit |
13e616 |
/* something is wrong - we'd better not use cache */
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_node_2->sw) {
|
|
Packit |
13e616 |
/* something is wrong - we'd better not use cache */
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* lost switch-2-switch link - cache both sides */
|
|
Packit |
13e616 |
cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, FALSE);
|
|
Packit |
13e616 |
cache_add_sw_link(p_mgr, p_physp2, lid_ho_1, FALSE);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
lid_ho_2 = cl_ntoh16(osm_physp_get_base_lid(p_physp2));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* lost link to CA/RTR - cache only switch side */
|
|
Packit |
13e616 |
cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, TRUE);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
} /* osm_ucast_cache_add_link() */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
uint16_t lid_ho;
|
|
Packit |
13e616 |
uint8_t max_ports;
|
|
Packit |
13e616 |
uint8_t port_num;
|
|
Packit |
13e616 |
osm_physp_t *p_physp;
|
|
Packit |
13e616 |
cache_switch_t *p_cache_sw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!lid_ho) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"Skip caching. Switch dropped before "
|
|
Packit |
13e616 |
"it gets a valid lid.\n");
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Caching dropped switch lid %u\n", lid_ho);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_node->sw) {
|
|
Packit |
13e616 |
/* something is wrong - forget about cache */
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR AD03: no switch info for node lid %u - "
|
|
Packit |
13e616 |
"clearing cache\n", lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* unlink (add to cache) all the ports of this switch */
|
|
Packit |
13e616 |
max_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
for (port_num = 1; port_num < max_ports; port_num++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
if (!p_physp || !p_physp->p_remote_physp)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_ucast_cache_add_link(p_mgr, p_physp,
|
|
Packit |
13e616 |
p_physp->p_remote_physp);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* All the ports have been dropped (cached).
|
|
Packit |
13e616 |
* If one of the ports was connected to CA/RTR,
|
|
Packit |
13e616 |
* then the cached switch would be marked as leaf.
|
|
Packit |
13e616 |
* If it isn't, then the dropped switch isn't a leaf,
|
|
Packit |
13e616 |
* and cache can't handle it.
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw = cache_get_sw(p_mgr, lid_ho);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* p_cache_sw could be NULL if it has no remote phys ports */
|
|
Packit |
13e616 |
if (!p_cache_sw || !cache_sw_is_leaf(p_cache_sw)) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"Dropped non-leaf switch (lid %u)\n", lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw->dropped = TRUE;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_node->sw->num_hops || !p_node->sw->hops) {
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit |
13e616 |
"No LID matrices for switch lid %u\n", lid_ho);
|
|
Packit |
13e616 |
osm_ucast_cache_invalidate(p_mgr);
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* lid matrices */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_cache_sw->num_hops = p_node->sw->num_hops;
|
|
Packit |
13e616 |
p_node->sw->num_hops = 0;
|
|
Packit |
13e616 |
p_cache_sw->hops = p_node->sw->hops;
|
|
Packit |
13e616 |
p_node->sw->hops = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* linear forwarding table */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_node->sw->new_lft) {
|
|
Packit |
13e616 |
/* LFT buffer exists - we use it, because
|
|
Packit |
13e616 |
it is more updated than the switch's LFT */
|
|
Packit |
13e616 |
p_cache_sw->lft = p_node->sw->new_lft;
|
|
Packit |
13e616 |
p_node->sw->new_lft = NULL;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/* no LFT buffer, so we use the switch's LFT */
|
|
Packit |
13e616 |
p_cache_sw->lft = p_node->sw->lft;
|
|
Packit |
13e616 |
p_node->sw->lft = NULL;
|
|
Packit |
13e616 |
p_node->sw->lft_size = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
/* dropping CA/RTR: add to cache all the ports of this node */
|
|
Packit |
13e616 |
max_ports = osm_node_get_num_physp(p_node);
|
|
Packit |
13e616 |
for (port_num = 1; port_num < max_ports; port_num++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_physp = osm_node_get_physp_ptr(p_node, port_num);
|
|
Packit |
13e616 |
if (!p_physp || !p_physp->p_remote_physp)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(osm_node_get_type
|
|
Packit |
13e616 |
(p_physp->p_remote_physp->p_node) ==
|
|
Packit |
13e616 |
IB_NODE_TYPE_SWITCH);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_ucast_cache_add_link(p_mgr,
|
|
Packit |
13e616 |
p_physp->p_remote_physp,
|
|
Packit |
13e616 |
p_physp);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit |
13e616 |
} /* osm_ucast_cache_add_node() */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
int osm_ucast_cache_process(osm_ucast_mgr_t * p_mgr)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
cl_qmap_t *tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit |
13e616 |
cl_map_item_t *item;
|
|
Packit |
13e616 |
osm_switch_t *p_sw;
|
|
Packit |
13e616 |
uint16_t lft_size;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!p_mgr->p_subn->opt.use_ucast_cache)
|
|
Packit |
13e616 |
return 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ucast_cache_validate(p_mgr);
|
|
Packit |
13e616 |
if (!p_mgr->cache_valid)
|
|
Packit |
13e616 |
return 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"Configuring switch tables using cached routing\n");
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl);
|
|
Packit |
13e616 |
item = cl_qmap_next(item)) {
|
|
Packit |
13e616 |
p_sw = (osm_switch_t *) item;
|
|
Packit |
13e616 |
CL_ASSERT(p_sw->new_lft);
|
|
Packit |
13e616 |
if (!p_sw->lft) {
|
|
Packit |
13e616 |
lft_size = (p_sw->max_lid_ho / IB_SMP_DATA_SIZE + 1)
|
|
Packit |
13e616 |
* IB_SMP_DATA_SIZE;
|
|
Packit |
13e616 |
p_sw->lft = malloc(lft_size);
|
|
Packit |
13e616 |
if (!p_sw->lft)
|
|
Packit |
13e616 |
return IB_INSUFFICIENT_MEMORY;
|
|
Packit |
13e616 |
p_sw->lft_size = lft_size;
|
|
Packit |
13e616 |
memset(p_sw->lft, OSM_NO_PATH, p_sw->lft_size);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_ucast_mgr_set_fwd_tables(p_mgr);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|