|
Packit Service |
54dbc3 |
/*
|
|
Packit Service |
54dbc3 |
* Copyright (c) 2004-2008 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 |
* Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
|
|
Packit Service |
54dbc3 |
* Copyright (C) 2012-2017 Tokyo Institute of Technology. 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 OpenSM (deadlock-free) single-source-shortest-path routing
|
|
Packit Service |
54dbc3 |
* (with dijkstra algorithm)
|
|
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 <complib/cl_heap.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_file_ids.h>
|
|
Packit Service |
54dbc3 |
#define FILE_ID OSM_FILE_UCAST_DFSSSP_C
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_ucast_mgr.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_opensm.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_node.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_multicast.h>
|
|
Packit Service |
54dbc3 |
#include <opensm/osm_mcast_mgr.h>
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* "infinity" for dijkstra */
|
|
Packit Service |
54dbc3 |
#define INF 0x7FFFFFFF
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
enum {
|
|
Packit Service |
54dbc3 |
UNDISCOVERED = 0,
|
|
Packit Service |
54dbc3 |
DISCOVERED
|
|
Packit Service |
54dbc3 |
};
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
enum {
|
|
Packit Service |
54dbc3 |
UNKNOWN = 0,
|
|
Packit Service |
54dbc3 |
GRAY,
|
|
Packit Service |
54dbc3 |
BLACK,
|
|
Packit Service |
54dbc3 |
};
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
typedef struct link {
|
|
Packit Service |
54dbc3 |
uint64_t guid; /* guid of the neighbor behind the link */
|
|
Packit Service |
54dbc3 |
uint32_t from; /* base_index in the adjazenz list (start of the link) */
|
|
Packit Service |
54dbc3 |
uint8_t from_port; /* port on the base_side (needed for weight update to identify the correct link for multigraphs) */
|
|
Packit Service |
54dbc3 |
uint32_t to; /* index of the neighbor in the adjazenz list (end of the link) */
|
|
Packit Service |
54dbc3 |
uint8_t to_port; /* port on the side of the neighbor (needed for the LFT) */
|
|
Packit Service |
54dbc3 |
uint64_t weight; /* link weight */
|
|
Packit Service |
54dbc3 |
struct link *next;
|
|
Packit Service |
54dbc3 |
} link_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
typedef struct vertex {
|
|
Packit Service |
54dbc3 |
/* informations of the fabric */
|
|
Packit Service |
54dbc3 |
uint64_t guid;
|
|
Packit Service |
54dbc3 |
uint16_t lid; /* for lft filling */
|
|
Packit Service |
54dbc3 |
uint32_t num_hca; /* numbers of Hca/LIDs on the switch, for weight calculation */
|
|
Packit Service |
54dbc3 |
link_t *links;
|
|
Packit Service |
54dbc3 |
uint8_t hops;
|
|
Packit Service |
54dbc3 |
/* for dijkstra routing */
|
|
Packit Service |
54dbc3 |
link_t *used_link; /* link between the vertex discovered before and this vertex */
|
|
Packit Service |
54dbc3 |
uint64_t distance; /* distance from source to this vertex */
|
|
Packit Service |
54dbc3 |
uint8_t state;
|
|
Packit Service |
54dbc3 |
/* for the d-ary heap */
|
|
Packit Service |
54dbc3 |
size_t heap_index;
|
|
Packit Service |
54dbc3 |
/* for LFT writing and debug */
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw; /* selfpointer */
|
|
Packit Service |
54dbc3 |
boolean_t dropped; /* indicate dropped switches (w/ ucast cache) */
|
|
Packit Service |
54dbc3 |
} vertex_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
typedef struct vltable {
|
|
Packit Service |
54dbc3 |
uint64_t num_lids; /* size of the lids array */
|
|
Packit Service |
54dbc3 |
uint16_t *lids; /* sorted array of all lids in the subnet */
|
|
Packit Service |
54dbc3 |
uint8_t *vls; /* matrix form assignment lid X lid -> virtual lane */
|
|
Packit Service |
54dbc3 |
} vltable_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
typedef struct cdg_link {
|
|
Packit Service |
54dbc3 |
struct cdg_node *node;
|
|
Packit Service |
54dbc3 |
uint32_t num_pairs; /* number of src->dest pairs incremented in path adding step */
|
|
Packit Service |
54dbc3 |
uint32_t max_len; /* length of the srcdest array */
|
|
Packit Service |
54dbc3 |
uint32_t removed; /* number of pairs removed in path deletion step */
|
|
Packit Service |
54dbc3 |
uint32_t *srcdest_pairs;
|
|
Packit Service |
54dbc3 |
struct cdg_link *next;
|
|
Packit Service |
54dbc3 |
} cdg_link_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* struct for a node of a binary tree with additional parent pointer */
|
|
Packit Service |
54dbc3 |
typedef struct cdg_node {
|
|
Packit Service |
54dbc3 |
uint64_t channelID; /* unique key consist of src lid + port + dest lid + port */
|
|
Packit Service |
54dbc3 |
cdg_link_t *linklist; /* edges to adjazent nodes */
|
|
Packit Service |
54dbc3 |
uint8_t status; /* node status in cycle search to avoid recursive function */
|
|
Packit Service |
54dbc3 |
uint8_t visited; /* needed to traverse the binary tree */
|
|
Packit Service |
54dbc3 |
struct cdg_node *pre; /* to save the path in cycle detection algorithm */
|
|
Packit Service |
54dbc3 |
struct cdg_node *left, *right, *parent;
|
|
Packit Service |
54dbc3 |
} cdg_node_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
typedef struct dfsssp_context {
|
|
Packit Service |
54dbc3 |
osm_routing_engine_type_t routing_type;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr;
|
|
Packit Service |
54dbc3 |
vertex_t *adj_list;
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size;
|
|
Packit Service |
54dbc3 |
vltable_t *srcdest2vl_table;
|
|
Packit Service |
54dbc3 |
uint8_t *vl_split_count;
|
|
Packit Service |
54dbc3 |
} dfsssp_context_t;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**************** set initial values for structs **********************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
static inline void set_default_link(link_t * link)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
link->guid = 0;
|
|
Packit Service |
54dbc3 |
link->from = 0;
|
|
Packit Service |
54dbc3 |
link->from_port = 0;
|
|
Packit Service |
54dbc3 |
link->to = 0;
|
|
Packit Service |
54dbc3 |
link->to_port = 0;
|
|
Packit Service |
54dbc3 |
link->weight = 0;
|
|
Packit Service |
54dbc3 |
link->next = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static inline void set_default_vertex(vertex_t * vertex)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
vertex->guid = 0;
|
|
Packit Service |
54dbc3 |
vertex->lid = 0;
|
|
Packit Service |
54dbc3 |
vertex->num_hca = 0;
|
|
Packit Service |
54dbc3 |
vertex->links = NULL;
|
|
Packit Service |
54dbc3 |
vertex->hops = 0;
|
|
Packit Service |
54dbc3 |
vertex->used_link = NULL;
|
|
Packit Service |
54dbc3 |
vertex->distance = 0;
|
|
Packit Service |
54dbc3 |
vertex->state = UNDISCOVERED;
|
|
Packit Service |
54dbc3 |
vertex->heap_index = 0;
|
|
Packit Service |
54dbc3 |
vertex->sw = NULL;
|
|
Packit Service |
54dbc3 |
vertex->dropped = FALSE;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static inline void set_default_cdg_node(cdg_node_t * node)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
node->channelID = 0;
|
|
Packit Service |
54dbc3 |
node->linklist = NULL;
|
|
Packit Service |
54dbc3 |
node->status = UNKNOWN;
|
|
Packit Service |
54dbc3 |
node->visited = 0;
|
|
Packit Service |
54dbc3 |
node->pre = NULL;
|
|
Packit Service |
54dbc3 |
node->left = NULL;
|
|
Packit Service |
54dbc3 |
node->right = NULL;
|
|
Packit Service |
54dbc3 |
node->parent = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/************ helper functions to save src/dest X vl combination ******
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
/* compare function of two lids for stdlib qsort */
|
|
Packit Service |
54dbc3 |
static int cmp_lids(const void *l1, const void *l2)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
ib_net16_t lid1 = *((ib_net16_t *) l1), lid2 = *((ib_net16_t *) l2);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (lid1 < lid2)
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
else if (lid1 > lid2)
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* use stdlib to sort the lid array */
|
|
Packit Service |
54dbc3 |
static inline void vltable_sort_lids(vltable_t * vltable)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
qsort(vltable->lids, vltable->num_lids, sizeof(ib_net16_t), cmp_lids);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* use stdlib to get index of key in lid array;
|
|
Packit Service |
54dbc3 |
return -1 if lid isn't found in lids array
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static inline int64_t vltable_get_lidindex(ib_net16_t * key, vltable_t * vltable)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
ib_net16_t *found_lid = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
found_lid =
|
|
Packit Service |
54dbc3 |
(ib_net16_t *) bsearch(key, vltable->lids, vltable->num_lids,
|
|
Packit Service |
54dbc3 |
sizeof(ib_net16_t), cmp_lids);
|
|
Packit Service |
54dbc3 |
if (found_lid)
|
|
Packit Service |
54dbc3 |
return found_lid - vltable->lids;
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* get virtual lane from src lid X dest lid combination;
|
|
Packit Service |
54dbc3 |
return -1 for invalid lids
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int32_t vltable_get_vl(vltable_t * vltable, ib_net16_t slid, ib_net16_t dlid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
int64_t ind1 = vltable_get_lidindex(&slid, vltable);
|
|
Packit Service |
54dbc3 |
int64_t ind2 = vltable_get_lidindex(&dlid, vltable);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (ind1 > -1 && ind2 > -1)
|
|
Packit Service |
54dbc3 |
return (int32_t) (vltable->
|
|
Packit Service |
54dbc3 |
vls[ind1 + ind2 * vltable->num_lids]);
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* set a virtual lane in the matrix */
|
|
Packit Service |
54dbc3 |
static inline void vltable_insert(vltable_t * vltable, ib_net16_t slid,
|
|
Packit Service |
54dbc3 |
ib_net16_t dlid, uint8_t vl)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
int64_t ind1 = vltable_get_lidindex(&slid, vltable);
|
|
Packit Service |
54dbc3 |
int64_t ind2 = vltable_get_lidindex(&dlid, vltable);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (ind1 > -1 && ind2 > -1)
|
|
Packit Service |
54dbc3 |
vltable->vls[ind1 + ind2 * vltable->num_lids] = vl;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* change a number of lanes from lane xy to lane yz */
|
|
Packit Service |
54dbc3 |
static void vltable_change_vl(vltable_t * vltable, uint8_t from, uint8_t to,
|
|
Packit Service |
54dbc3 |
uint64_t count)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint64_t set = 0, stop = 0;
|
|
Packit Service |
54dbc3 |
uint64_t ind1 = 0, ind2 = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (ind1 = 0; ind1 < vltable->num_lids; ind1++) {
|
|
Packit Service |
54dbc3 |
for (ind2 = 0; ind2 < vltable->num_lids; ind2++) {
|
|
Packit Service |
54dbc3 |
if (set == count) {
|
|
Packit Service |
54dbc3 |
stop = 1;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (ind1 != ind2) {
|
|
Packit Service |
54dbc3 |
if (vltable->
|
|
Packit Service |
54dbc3 |
vls[ind1 + ind2 * vltable->num_lids] ==
|
|
Packit Service |
54dbc3 |
from) {
|
|
Packit Service |
54dbc3 |
vltable->vls[ind1 +
|
|
Packit Service |
54dbc3 |
ind2 * vltable->num_lids] =
|
|
Packit Service |
54dbc3 |
to;
|
|
Packit Service |
54dbc3 |
set++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (stop)
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void vltable_print(osm_ucast_mgr_t * p_mgr, vltable_t * vltable)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint64_t ind1 = 0, ind2 = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (ind1 = 0; ind1 < vltable->num_lids; ind1++) {
|
|
Packit Service |
54dbc3 |
for (ind2 = 0; ind2 < vltable->num_lids; ind2++) {
|
|
Packit Service |
54dbc3 |
if (ind1 != ind2) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" route from src_lid=%" PRIu16
|
|
Packit Service |
54dbc3 |
" to dest_lid=%" PRIu16 " on vl=%" PRIu8
|
|
Packit Service |
54dbc3 |
"\n", cl_ntoh16(vltable->lids[ind1]),
|
|
Packit Service |
54dbc3 |
cl_ntoh16(vltable->lids[ind2]),
|
|
Packit Service |
54dbc3 |
vltable->vls[ind1 +
|
|
Packit Service |
54dbc3 |
ind2 * vltable->num_lids]);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void vltable_dealloc(vltable_t ** vltable)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
if (*vltable) {
|
|
Packit Service |
54dbc3 |
if ((*vltable)->lids)
|
|
Packit Service |
54dbc3 |
free((*vltable)->lids);
|
|
Packit Service |
54dbc3 |
if ((*vltable)->vls)
|
|
Packit Service |
54dbc3 |
free((*vltable)->vls);
|
|
Packit Service |
54dbc3 |
free(*vltable);
|
|
Packit Service |
54dbc3 |
*vltable = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static int vltable_alloc(vltable_t ** vltable, uint64_t size)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
/* allocate VL table and indexing array */
|
|
Packit Service |
54dbc3 |
*vltable = (vltable_t *) malloc(sizeof(vltable_t));
|
|
Packit Service |
54dbc3 |
if (!(*vltable))
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
(*vltable)->num_lids = size;
|
|
Packit Service |
54dbc3 |
(*vltable)->lids = (ib_net16_t *) malloc(size * sizeof(ib_net16_t));
|
|
Packit Service |
54dbc3 |
if (!((*vltable)->lids))
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
(*vltable)->vls = (uint8_t *) malloc(size * size * sizeof(uint8_t));
|
|
Packit Service |
54dbc3 |
if (!((*vltable)->vls))
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
memset((*vltable)->vls, OSM_DEFAULT_SL, size * size);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
vltable_dealloc(vltable);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/************ helper functions to save/manage the channel dep. graph **
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
/* update the srcdest array;
|
|
Packit Service |
54dbc3 |
realloc array (double the size) if size is not large enough
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static void set_next_srcdest_pair(cdg_link_t * link, uint32_t srcdest)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t new_size = 0, start_size = 2;
|
|
Packit Service |
54dbc3 |
uint32_t *tmp = NULL, *tmp2 = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (link->num_pairs == 0) {
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs =
|
|
Packit Service |
54dbc3 |
(uint32_t *) malloc(start_size * sizeof(uint32_t));
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs[link->num_pairs] = srcdest;
|
|
Packit Service |
54dbc3 |
link->max_len = start_size;
|
|
Packit Service |
54dbc3 |
link->removed = 0;
|
|
Packit Service |
54dbc3 |
} else if (link->num_pairs == link->max_len) {
|
|
Packit Service |
54dbc3 |
new_size = link->max_len << 1;
|
|
Packit Service |
54dbc3 |
tmp = (uint32_t *) malloc(new_size * sizeof(uint32_t));
|
|
Packit Service |
54dbc3 |
tmp =
|
|
Packit Service |
54dbc3 |
memcpy(tmp, link->srcdest_pairs,
|
|
Packit Service |
54dbc3 |
link->max_len * sizeof(uint32_t));
|
|
Packit Service |
54dbc3 |
tmp2 = link->srcdest_pairs;
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs = tmp;
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs[link->num_pairs] = srcdest;
|
|
Packit Service |
54dbc3 |
free(tmp2);
|
|
Packit Service |
54dbc3 |
link->max_len = new_size;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs[link->num_pairs] = srcdest;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link->num_pairs++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static inline uint32_t get_next_srcdest_pair(cdg_link_t * link, uint32_t index)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
return link->srcdest_pairs[index];
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* traverse binary tree to find a node */
|
|
Packit Service |
54dbc3 |
static cdg_node_t *cdg_search(cdg_node_t * root, uint64_t channelID)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
while (root) {
|
|
Packit Service |
54dbc3 |
if (channelID < root->channelID)
|
|
Packit Service |
54dbc3 |
root = root->left;
|
|
Packit Service |
54dbc3 |
else if (channelID > root->channelID)
|
|
Packit Service |
54dbc3 |
root = root->right;
|
|
Packit Service |
54dbc3 |
else if (channelID == root->channelID)
|
|
Packit Service |
54dbc3 |
return root;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
return NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* insert new node into the binary tree */
|
|
Packit Service |
54dbc3 |
static void cdg_insert(cdg_node_t ** root, cdg_node_t * new_node)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_node_t *current = *root;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!current) {
|
|
Packit Service |
54dbc3 |
current = new_node;
|
|
Packit Service |
54dbc3 |
*root = current;
|
|
Packit Service |
54dbc3 |
return;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
if (new_node->channelID < current->channelID) {
|
|
Packit Service |
54dbc3 |
if (current->left) {
|
|
Packit Service |
54dbc3 |
current = current->left;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
current->left = new_node;
|
|
Packit Service |
54dbc3 |
new_node->parent = current;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else if (new_node->channelID > current->channelID) {
|
|
Packit Service |
54dbc3 |
if (current->right) {
|
|
Packit Service |
54dbc3 |
current = current->right;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
current->right = new_node;
|
|
Packit Service |
54dbc3 |
new_node->parent = current;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else if (new_node->channelID == current->channelID) {
|
|
Packit Service |
54dbc3 |
/* not really possible, maybe programming error */
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void cdg_node_dealloc(cdg_node_t * node)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_link_t *link = node->linklist, *tmp = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* dealloc linklist */
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
tmp = link;
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (tmp->num_pairs)
|
|
Packit Service |
54dbc3 |
free(tmp->srcdest_pairs);
|
|
Packit Service |
54dbc3 |
free(tmp);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* dealloc node */
|
|
Packit Service |
54dbc3 |
free(node);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void cdg_dealloc(cdg_node_t ** root)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_node_t *current = *root;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
if (current->left) {
|
|
Packit Service |
54dbc3 |
current = current->left;
|
|
Packit Service |
54dbc3 |
} else if (current->right) {
|
|
Packit Service |
54dbc3 |
current = current->right;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
if (current->parent == NULL) {
|
|
Packit Service |
54dbc3 |
cdg_node_dealloc(current);
|
|
Packit Service |
54dbc3 |
*root = NULL;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (current->parent->left == current) {
|
|
Packit Service |
54dbc3 |
current = current->parent;
|
|
Packit Service |
54dbc3 |
cdg_node_dealloc(current->left);
|
|
Packit Service |
54dbc3 |
current->left = NULL;
|
|
Packit Service |
54dbc3 |
} else if (current->parent->right == current) {
|
|
Packit Service |
54dbc3 |
current = current->parent;
|
|
Packit Service |
54dbc3 |
cdg_node_dealloc(current->right);
|
|
Packit Service |
54dbc3 |
current->right = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* search for a edge in the cdg which should be removed to break a cycle */
|
|
Packit Service |
54dbc3 |
static cdg_link_t *get_weakest_link_in_cycle(cdg_node_t * cycle)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_node_t *current = cycle, *node_with_weakest_link = NULL;
|
|
Packit Service |
54dbc3 |
cdg_link_t *link = NULL, *weakest_link = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
link = current->linklist;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
if (link->node->status == GRAY) {
|
|
Packit Service |
54dbc3 |
weakest_link = link;
|
|
Packit Service |
54dbc3 |
node_with_weakest_link = current;
|
|
Packit Service |
54dbc3 |
current = link->node;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (1) {
|
|
Packit Service |
54dbc3 |
current->status = UNKNOWN;
|
|
Packit Service |
54dbc3 |
link = current->linklist;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
if (link->node->status == GRAY) {
|
|
Packit Service |
54dbc3 |
if ((link->num_pairs - link->removed) <
|
|
Packit Service |
54dbc3 |
(weakest_link->num_pairs -
|
|
Packit Service |
54dbc3 |
weakest_link->removed)) {
|
|
Packit Service |
54dbc3 |
weakest_link = link;
|
|
Packit Service |
54dbc3 |
node_with_weakest_link = current;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
current = link->node;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* if complete cycle is traversed */
|
|
Packit Service |
54dbc3 |
if (current == cycle) {
|
|
Packit Service |
54dbc3 |
current->status = UNKNOWN;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (node_with_weakest_link->linklist == weakest_link) {
|
|
Packit Service |
54dbc3 |
node_with_weakest_link->linklist = weakest_link->next;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
link = node_with_weakest_link->linklist;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
if (link->next == weakest_link) {
|
|
Packit Service |
54dbc3 |
link->next = weakest_link->next;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return weakest_link;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* search for nodes in the cdg not yet reached in the cycle search process;
|
|
Packit Service |
54dbc3 |
(some nodes are unreachable, e.g. a node is a source or the cdg has not connected parts)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static cdg_node_t *get_next_cdg_node(cdg_node_t * root)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_node_t *current = root, *res = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
current->visited = 1;
|
|
Packit Service |
54dbc3 |
if (current->status == UNKNOWN) {
|
|
Packit Service |
54dbc3 |
res = current;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (current->left && !current->left->visited) {
|
|
Packit Service |
54dbc3 |
current = current->left;
|
|
Packit Service |
54dbc3 |
} else if (current->right && !current->right->visited) {
|
|
Packit Service |
54dbc3 |
current = current->right;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
if (current->left)
|
|
Packit Service |
54dbc3 |
current->left->visited = 0;
|
|
Packit Service |
54dbc3 |
if (current->right)
|
|
Packit Service |
54dbc3 |
current->right->visited = 0;
|
|
Packit Service |
54dbc3 |
if (current->parent == NULL)
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
current = current->parent;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* Clean up */
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
current->visited = 0;
|
|
Packit Service |
54dbc3 |
if (current->left)
|
|
Packit Service |
54dbc3 |
current->left->visited = 0;
|
|
Packit Service |
54dbc3 |
if (current->right)
|
|
Packit Service |
54dbc3 |
current->right->visited = 0;
|
|
Packit Service |
54dbc3 |
current = current->parent;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return res;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* make a DFS on the cdg to check for a cycle */
|
|
Packit Service |
54dbc3 |
static cdg_node_t *search_cycle_in_channel_dep_graph(cdg_node_t * cdg,
|
|
Packit Service |
54dbc3 |
cdg_node_t * start_node)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cdg_node_t *cycle = NULL;
|
|
Packit Service |
54dbc3 |
cdg_node_t *current = start_node, *next_node = NULL, *tmp = NULL;
|
|
Packit Service |
54dbc3 |
cdg_link_t *link = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
current->status = GRAY;
|
|
Packit Service |
54dbc3 |
link = current->linklist;
|
|
Packit Service |
54dbc3 |
next_node = NULL;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
if (link->node->status == UNKNOWN) {
|
|
Packit Service |
54dbc3 |
next_node = link->node;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (link->node->status == GRAY) {
|
|
Packit Service |
54dbc3 |
cycle = link->node;
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (next_node) {
|
|
Packit Service |
54dbc3 |
next_node->pre = current;
|
|
Packit Service |
54dbc3 |
current = next_node;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* found a sink in the graph, go to last node */
|
|
Packit Service |
54dbc3 |
current->status = BLACK;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* srcdest_pairs of this node aren't relevant, free the allocated memory */
|
|
Packit Service |
54dbc3 |
link = current->linklist;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
if (link->num_pairs)
|
|
Packit Service |
54dbc3 |
free(link->srcdest_pairs);
|
|
Packit Service |
54dbc3 |
link->srcdest_pairs = NULL;
|
|
Packit Service |
54dbc3 |
link->num_pairs = 0;
|
|
Packit Service |
54dbc3 |
link->removed = 0;
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (current->pre) {
|
|
Packit Service |
54dbc3 |
tmp = current;
|
|
Packit Service |
54dbc3 |
current = current->pre;
|
|
Packit Service |
54dbc3 |
tmp->pre = NULL;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* search for other subgraphs in cdg */
|
|
Packit Service |
54dbc3 |
current = get_next_cdg_node(cdg);
|
|
Packit Service |
54dbc3 |
if (!current)
|
|
Packit Service |
54dbc3 |
break; /* all relevant nodes traversed, no more cycles found */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
Exit:
|
|
Packit Service |
54dbc3 |
return cycle;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* calculate the path from source to destination port;
|
|
Packit Service |
54dbc3 |
new channels are added directly to the cdg
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int update_channel_dep_graph(cdg_node_t ** cdg_root,
|
|
Packit Service |
54dbc3 |
osm_port_t * src_port, uint16_t slid,
|
|
Packit Service |
54dbc3 |
osm_port_t * dest_port, uint16_t dlid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_node_t *local_node = NULL, *remote_node = NULL;
|
|
Packit Service |
54dbc3 |
uint16_t local_lid = 0, remote_lid = 0;
|
|
Packit Service |
54dbc3 |
uint32_t srcdest = 0;
|
|
Packit Service |
54dbc3 |
uint8_t local_port = 0, remote_port = 0;
|
|
Packit Service |
54dbc3 |
uint64_t channelID = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cdg_node_t *channel_head = NULL, *channel = NULL, *last_channel = NULL;
|
|
Packit Service |
54dbc3 |
cdg_link_t *linklist = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* set the identifier for the src/dest pair to save this on each edge of the cdg */
|
|
Packit Service |
54dbc3 |
srcdest = (((uint32_t) slid) << 16) + ((uint32_t) dlid);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
channel_head = (cdg_node_t *) malloc(sizeof(cdg_node_t));
|
|
Packit Service |
54dbc3 |
if (!channel_head)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
set_default_cdg_node(channel_head);
|
|
Packit Service |
54dbc3 |
last_channel = channel_head;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if src is a Hca, then the channel from Hca to switch would be a source in the graph
|
|
Packit Service |
54dbc3 |
sources can't be part of a cycle -> skip this channel
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(src_port->p_node,
|
|
Packit Service |
54dbc3 |
src_port->p_physp->port_num, &remote_port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (remote_node && remote_node->sw) {
|
|
Packit Service |
54dbc3 |
local_node = remote_node;
|
|
Packit Service |
54dbc3 |
local_port = local_node->sw->new_lft[dlid];
|
|
Packit Service |
54dbc3 |
/* sanity check: local_port must be set or routing is broken */
|
|
Packit Service |
54dbc3 |
if (local_port == OSM_NO_PATH)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
local_lid = cl_ntoh16(osm_node_get_base_lid(local_node, 0));
|
|
Packit Service |
54dbc3 |
/* each port belonging to a switch has lmc==0 -> get_base_lid is fine
|
|
Packit Service |
54dbc3 |
(local/remote port in this function are always part of a switch)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(local_node, local_port,
|
|
Packit Service |
54dbc3 |
&remote_port);
|
|
Packit Service |
54dbc3 |
/* if remote_node is a Hca, then the last channel from switch to Hca would be a sink in the cdg -> skip */
|
|
Packit Service |
54dbc3 |
if (!remote_node || !remote_node->sw)
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
remote_lid = cl_ntoh16(osm_node_get_base_lid(remote_node, 0));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
channelID =
|
|
Packit Service |
54dbc3 |
(((uint64_t) local_lid) << 48) +
|
|
Packit Service |
54dbc3 |
(((uint64_t) local_port) << 32) +
|
|
Packit Service |
54dbc3 |
(((uint64_t) remote_lid) << 16) + ((uint64_t) remote_port);
|
|
Packit Service |
54dbc3 |
channel = cdg_search(*cdg_root, channelID);
|
|
Packit Service |
54dbc3 |
if (channel) {
|
|
Packit Service |
54dbc3 |
/* check whether last channel has connection to this channel, i.e. subpath already exists in cdg */
|
|
Packit Service |
54dbc3 |
linklist = last_channel->linklist;
|
|
Packit Service |
54dbc3 |
while (linklist && linklist->node != channel
|
|
Packit Service |
54dbc3 |
&& linklist->next)
|
|
Packit Service |
54dbc3 |
linklist = linklist->next;
|
|
Packit Service |
54dbc3 |
/* if there is no connection, add one */
|
|
Packit Service |
54dbc3 |
if (linklist) {
|
|
Packit Service |
54dbc3 |
if (linklist->node == channel) {
|
|
Packit Service |
54dbc3 |
set_next_srcdest_pair(linklist,
|
|
Packit Service |
54dbc3 |
srcdest);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
linklist->next =
|
|
Packit Service |
54dbc3 |
(cdg_link_t *)
|
|
Packit Service |
54dbc3 |
malloc(sizeof(cdg_link_t));
|
|
Packit Service |
54dbc3 |
if (!linklist->next)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
linklist = linklist->next;
|
|
Packit Service |
54dbc3 |
linklist->node = channel;
|
|
Packit Service |
54dbc3 |
linklist->num_pairs = 0;
|
|
Packit Service |
54dbc3 |
linklist->srcdest_pairs = NULL;
|
|
Packit Service |
54dbc3 |
set_next_srcdest_pair(linklist,
|
|
Packit Service |
54dbc3 |
srcdest);
|
|
Packit Service |
54dbc3 |
linklist->next = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* either this is the first channel of the path, or the last channel was a new channel, or last channel was a sink */
|
|
Packit Service |
54dbc3 |
last_channel->linklist =
|
|
Packit Service |
54dbc3 |
(cdg_link_t *) malloc(sizeof(cdg_link_t));
|
|
Packit Service |
54dbc3 |
if (!last_channel->linklist)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->node = channel;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->num_pairs = 0;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->srcdest_pairs = NULL;
|
|
Packit Service |
54dbc3 |
set_next_srcdest_pair(last_channel->linklist,
|
|
Packit Service |
54dbc3 |
srcdest);
|
|
Packit Service |
54dbc3 |
last_channel->linklist->next = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* create new channel */
|
|
Packit Service |
54dbc3 |
channel = (cdg_node_t *) malloc(sizeof(cdg_node_t));
|
|
Packit Service |
54dbc3 |
if (!channel)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
set_default_cdg_node(channel);
|
|
Packit Service |
54dbc3 |
channel->channelID = channelID;
|
|
Packit Service |
54dbc3 |
cdg_insert(cdg_root, channel);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* go to end of link list of last channel */
|
|
Packit Service |
54dbc3 |
linklist = last_channel->linklist;
|
|
Packit Service |
54dbc3 |
while (linklist && linklist->next)
|
|
Packit Service |
54dbc3 |
linklist = linklist->next;
|
|
Packit Service |
54dbc3 |
if (linklist) {
|
|
Packit Service |
54dbc3 |
/* update last link of an existing channel */
|
|
Packit Service |
54dbc3 |
linklist->next =
|
|
Packit Service |
54dbc3 |
(cdg_link_t *) malloc(sizeof(cdg_link_t));
|
|
Packit Service |
54dbc3 |
if (!linklist->next)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
linklist = linklist->next;
|
|
Packit Service |
54dbc3 |
linklist->node = channel;
|
|
Packit Service |
54dbc3 |
linklist->num_pairs = 0;
|
|
Packit Service |
54dbc3 |
linklist->srcdest_pairs = NULL;
|
|
Packit Service |
54dbc3 |
set_next_srcdest_pair(linklist, srcdest);
|
|
Packit Service |
54dbc3 |
linklist->next = NULL;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* either this is the first channel of the path, or the last channel was a new channel, or last channel was a sink */
|
|
Packit Service |
54dbc3 |
last_channel->linklist =
|
|
Packit Service |
54dbc3 |
(cdg_link_t *) malloc(sizeof(cdg_link_t));
|
|
Packit Service |
54dbc3 |
if (!last_channel->linklist)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->node = channel;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->num_pairs = 0;
|
|
Packit Service |
54dbc3 |
last_channel->linklist->srcdest_pairs = NULL;
|
|
Packit Service |
54dbc3 |
set_next_srcdest_pair(last_channel->linklist,
|
|
Packit Service |
54dbc3 |
srcdest);
|
|
Packit Service |
54dbc3 |
last_channel->linklist->next = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
last_channel = channel;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (channel_head->linklist) {
|
|
Packit Service |
54dbc3 |
if (channel_head->linklist->srcdest_pairs)
|
|
Packit Service |
54dbc3 |
free(channel_head->linklist->srcdest_pairs);
|
|
Packit Service |
54dbc3 |
free(channel_head->linklist);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
free(channel_head);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
/* cleanup data and exit */
|
|
Packit Service |
54dbc3 |
if (channel_head) {
|
|
Packit Service |
54dbc3 |
if (channel_head->linklist)
|
|
Packit Service |
54dbc3 |
free(channel_head->linklist);
|
|
Packit Service |
54dbc3 |
free(channel_head);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* calculate the path from source to destination port;
|
|
Packit Service |
54dbc3 |
the links in the cdg representing this path are decremented to simulate the removal
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int remove_path_from_cdg(cdg_node_t ** cdg_root, osm_port_t * src_port,
|
|
Packit Service |
54dbc3 |
uint16_t slid, osm_port_t * dest_port,
|
|
Packit Service |
54dbc3 |
uint16_t dlid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_node_t *local_node = NULL, *remote_node = NULL;
|
|
Packit Service |
54dbc3 |
uint16_t local_lid = 0, remote_lid = 0;
|
|
Packit Service |
54dbc3 |
uint8_t local_port = 0, remote_port = 0;
|
|
Packit Service |
54dbc3 |
uint64_t channelID = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cdg_node_t *channel_head = NULL, *channel = NULL, *last_channel = NULL;
|
|
Packit Service |
54dbc3 |
cdg_link_t *linklist = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
channel_head = (cdg_node_t *) malloc(sizeof(cdg_node_t));
|
|
Packit Service |
54dbc3 |
if (!channel_head)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
set_default_cdg_node(channel_head);
|
|
Packit Service |
54dbc3 |
last_channel = channel_head;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if src is a Hca, then the channel from Hca to switch would be a source in the graph
|
|
Packit Service |
54dbc3 |
sources can't be part of a cycle -> skip this channel
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(src_port->p_node,
|
|
Packit Service |
54dbc3 |
src_port->p_physp->port_num, &remote_port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
while (remote_node && remote_node->sw) {
|
|
Packit Service |
54dbc3 |
local_node = remote_node;
|
|
Packit Service |
54dbc3 |
local_port = local_node->sw->new_lft[dlid];
|
|
Packit Service |
54dbc3 |
/* sanity check: local_port must be set or routing is broken */
|
|
Packit Service |
54dbc3 |
if (local_port == OSM_NO_PATH)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
local_lid = cl_ntoh16(osm_node_get_base_lid(local_node, 0));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(local_node, local_port,
|
|
Packit Service |
54dbc3 |
&remote_port);
|
|
Packit Service |
54dbc3 |
/* if remote_node is a Hca, then the last channel from switch to Hca would be a sink in the cdg -> skip */
|
|
Packit Service |
54dbc3 |
if (!remote_node || !remote_node->sw)
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
remote_lid = cl_ntoh16(osm_node_get_base_lid(remote_node, 0));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
channelID =
|
|
Packit Service |
54dbc3 |
(((uint64_t) local_lid) << 48) +
|
|
Packit Service |
54dbc3 |
(((uint64_t) local_port) << 32) +
|
|
Packit Service |
54dbc3 |
(((uint64_t) remote_lid) << 16) + ((uint64_t) remote_port);
|
|
Packit Service |
54dbc3 |
channel = cdg_search(*cdg_root, channelID);
|
|
Packit Service |
54dbc3 |
if (channel) {
|
|
Packit Service |
54dbc3 |
/* check whether last channel has connection to this channel, i.e. subpath already exists in cdg */
|
|
Packit Service |
54dbc3 |
linklist = last_channel->linklist;
|
|
Packit Service |
54dbc3 |
while (linklist && linklist->node != channel
|
|
Packit Service |
54dbc3 |
&& linklist->next)
|
|
Packit Service |
54dbc3 |
linklist = linklist->next;
|
|
Packit Service |
54dbc3 |
/* remove the srcdest from the link */
|
|
Packit Service |
54dbc3 |
if (linklist) {
|
|
Packit Service |
54dbc3 |
if (linklist->node == channel) {
|
|
Packit Service |
54dbc3 |
linklist->removed++;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* may happen if the link is missing (thru cycle detect algorithm) */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* may happen if the link is missing (thru cycle detect algorithm or last_channel==channel_head (dummy channel)) */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* must be an error, channels for the path are added before, so a missing channel would be a corrupt data structure */
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
last_channel = channel;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (channel_head->linklist)
|
|
Packit Service |
54dbc3 |
free(channel_head->linklist);
|
|
Packit Service |
54dbc3 |
free(channel_head);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
/* cleanup data and exit */
|
|
Packit Service |
54dbc3 |
if (channel_head) {
|
|
Packit Service |
54dbc3 |
if (channel_head->linklist)
|
|
Packit Service |
54dbc3 |
free(channel_head->linklist);
|
|
Packit Service |
54dbc3 |
free(channel_head);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/************ helper functions to generate an ordered list of ports ***
|
|
Packit Service |
54dbc3 |
************ (functions copied from osm_ucast_mgr.c and modified) ****
|
|
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 |
cl_qmap_t * guid_tbl,
|
|
Packit Service |
54dbc3 |
boolean_t add_guids)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_port_t *port;
|
|
Packit Service |
54dbc3 |
ib_net64_t port_guid;
|
|
Packit Service |
54dbc3 |
uint64_t sw_guid;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p;
|
|
Packit Service |
54dbc3 |
int i;
|
|
Packit Service |
54dbc3 |
boolean_t found;
|
|
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_guid = p->p_remote_physp->port_guid;
|
|
Packit Service |
54dbc3 |
/* check if link is healthy, otherwise ignore CA */
|
|
Packit Service |
54dbc3 |
if (!osm_link_is_healthy(p)) {
|
|
Packit Service |
54dbc3 |
sw_guid =
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(sw->p_node));
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"WRN AD40: ignoring CA due to unhealthy"
|
|
Packit Service |
54dbc3 |
" link from switch 0x%016" PRIx64
|
|
Packit Service |
54dbc3 |
" port %" PRIu8 " to CA 0x%016" PRIx64
|
|
Packit Service |
54dbc3 |
"\n", sw_guid, i, cl_ntoh64(port_guid));
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
port = osm_get_port_by_guid(m->p_subn, port_guid);
|
|
Packit Service |
54dbc3 |
if (!port)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
if (!cl_is_qmap_empty(guid_tbl)) {
|
|
Packit Service |
54dbc3 |
found = (cl_qmap_get(guid_tbl, port_guid)
|
|
Packit Service |
54dbc3 |
!= cl_qmap_end(guid_tbl));
|
|
Packit Service |
54dbc3 |
if ((add_guids && !found)
|
|
Packit Service |
54dbc3 |
|| (!add_guids && found))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (!cl_is_item_in_qlist(&m->port_order_list,
|
|
Packit Service |
54dbc3 |
&port->list_item))
|
|
Packit Service |
54dbc3 |
cl_qlist_insert_tail(&m->port_order_list,
|
|
Packit Service |
54dbc3 |
&port->list_item);
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"WRN AD37: guid 0x%016" PRIx64
|
|
Packit Service |
54dbc3 |
" already in list\n", port_guid);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void add_guid_to_order_list(uint64_t guid, osm_ucast_mgr_t * m)
|
|
Packit Service |
54dbc3 |
{
|
|
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 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!cl_is_item_in_qlist(&m->port_order_list, &port->list_item))
|
|
Packit Service |
54dbc3 |
cl_qlist_insert_tail(&m->port_order_list, &port->list_item);
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
OSM_LOG(m->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"WRN AD38: guid 0x%016" PRIx64 " already in list\n",
|
|
Packit Service |
54dbc3 |
guid);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* compare function of #Hca attached to a switch for stdlib qsort */
|
|
Packit Service |
54dbc3 |
static int cmp_num_hca(const void * l1, const void * l2)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
vertex_t *sw1 = *((vertex_t **) l1);
|
|
Packit Service |
54dbc3 |
vertex_t *sw2 = *((vertex_t **) l2);
|
|
Packit Service |
54dbc3 |
uint32_t num_hca1 = 0, num_hca2 = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (sw1)
|
|
Packit Service |
54dbc3 |
num_hca1 = sw1->num_hca;
|
|
Packit Service |
54dbc3 |
if (sw2)
|
|
Packit Service |
54dbc3 |
num_hca2 = sw2->num_hca;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (num_hca1 > num_hca2)
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
else if (num_hca1 < num_hca2)
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* use stdlib to sort the switch array depending on num_hca */
|
|
Packit Service |
54dbc3 |
static inline void sw_list_sort_by_num_hca(vertex_t ** sw_list,
|
|
Packit Service |
54dbc3 |
uint32_t sw_list_size)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
qsort(sw_list, sw_list_size, sizeof(vertex_t *), cmp_num_hca);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/************ helper functions to manage a map of CN and I/O guids ****
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
static int add_guid_to_map(void * cxt, uint64_t guid, char * p)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
cl_qmap_t *map = cxt;
|
|
Packit Service |
54dbc3 |
name_map_item_t *item;
|
|
Packit Service |
54dbc3 |
name_map_item_t *inserted_item;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
item = malloc(sizeof(*item));
|
|
Packit Service |
54dbc3 |
if (!item)
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
item->guid = cl_hton64(guid); /* internal: network byte order */
|
|
Packit Service |
54dbc3 |
item->name = NULL; /* name isn't needed */
|
|
Packit Service |
54dbc3 |
inserted_item = (name_map_item_t *) cl_qmap_insert(map, item->guid, &item->item);
|
|
Packit Service |
54dbc3 |
if (inserted_item != item)
|
|
Packit Service |
54dbc3 |
free(item);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void destroy_guid_map(cl_qmap_t * guid_tbl)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
name_map_item_t *p_guid = NULL, *p_next_guid = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_next_guid = (name_map_item_t *) cl_qmap_head(guid_tbl);
|
|
Packit Service |
54dbc3 |
while (p_next_guid != (name_map_item_t *) cl_qmap_end(guid_tbl)) {
|
|
Packit Service |
54dbc3 |
p_guid = p_next_guid;
|
|
Packit Service |
54dbc3 |
p_next_guid = (name_map_item_t *) cl_qmap_next(&p_guid->item);
|
|
Packit Service |
54dbc3 |
free(p_guid);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
cl_qmap_remove_all(guid_tbl);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/**********************************************************************
|
|
Packit Service |
54dbc3 |
**********************************************************************/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void dfsssp_print_graph(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list,
|
|
Packit Service |
54dbc3 |
uint32_t size)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, c = 0;
|
|
Packit Service |
54dbc3 |
link_t *link = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* index 0 is for the source in dijkstra -> ignore */
|
|
Packit Service |
54dbc3 |
for (i = 1; i < size; i++) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "adj_list[%" PRIu32 "]:\n",
|
|
Packit Service |
54dbc3 |
i);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" guid = 0x%" PRIx64 " lid = %" PRIu16 " (%s)\n",
|
|
Packit Service |
54dbc3 |
adj_list[i].guid, adj_list[i].lid,
|
|
Packit Service |
54dbc3 |
adj_list[i].sw->p_node->print_desc);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" num_hca = %" PRIu32 "\n", adj_list[i].num_hca);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
c = 1;
|
|
Packit Service |
54dbc3 |
for (link = adj_list[i].links; link != NULL;
|
|
Packit Service |
54dbc3 |
link = link->next, c++) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" link[%" PRIu32 "]:\n", c);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" to guid = 0x%" PRIx64 " (%s) port %"
|
|
Packit Service |
54dbc3 |
PRIu8 "\n", link->guid,
|
|
Packit Service |
54dbc3 |
adj_list[link->to].sw->p_node->print_desc,
|
|
Packit Service |
54dbc3 |
link->to_port);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" weight on this link = %" PRIu64 "\n",
|
|
Packit Service |
54dbc3 |
link->weight);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* predefine, to use this in next function */
|
|
Packit Service |
54dbc3 |
static void dfsssp_context_destroy(void *context);
|
|
Packit Service |
54dbc3 |
static int dijkstra(osm_ucast_mgr_t * p_mgr, cl_heap_t * p_heap,
|
|
Packit Service |
54dbc3 |
vertex_t * adj_list, uint32_t adj_list_size,
|
|
Packit Service |
54dbc3 |
osm_port_t * port, uint16_t lid);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* traverse subnet to gather information about the connected switches */
|
|
Packit Service |
54dbc3 |
static int dfsssp_build_graph(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) (dfsssp_ctx->p_mgr);
|
|
Packit Service |
54dbc3 |
boolean_t has_fdr10 = (1 == p_mgr->p_subn->opt.fdr10) ? TRUE : FALSE;
|
|
Packit Service |
54dbc3 |
cl_qmap_t *port_tbl = &p_mgr->p_subn->port_guid_tbl; /* 1 management port per switch + 1 or 2 ports for each Hca */
|
|
Packit Service |
54dbc3 |
osm_port_t *p_port = NULL;
|
|
Packit Service |
54dbc3 |
cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item = NULL;
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = NULL;
|
|
Packit Service |
54dbc3 |
osm_node_t *remote_node = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t port = 0, remote_port = 0;
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, j = 0, err = 0, undiscov = 0, max_num_undiscov = 0;
|
|
Packit Service |
54dbc3 |
uint64_t total_num_hca = 0;
|
|
Packit Service |
54dbc3 |
vertex_t *adj_list = NULL;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp = NULL;
|
|
Packit Service |
54dbc3 |
link_t *link = NULL, *head = NULL;
|
|
Packit Service |
54dbc3 |
uint32_t num_sw = 0, adj_list_size = 0;
|
|
Packit Service |
54dbc3 |
uint8_t lmc = 0;
|
|
Packit Service |
54dbc3 |
uint16_t sm_lid = 0;
|
|
Packit Service |
54dbc3 |
cl_heap_t heap;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Building graph for df-/sssp routing\n");
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if this pointer isn't NULL, this is a reroute step;
|
|
Packit Service |
54dbc3 |
old context will be destroyed (adj_list and srcdest2vl_table)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (dfsssp_ctx->adj_list)
|
|
Packit Service |
54dbc3 |
dfsssp_context_destroy(context);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* construct the generic heap opject to use it in dijkstra */
|
|
Packit Service |
54dbc3 |
cl_heap_construct(&heap;;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
num_sw = cl_qmap_count(sw_tbl);
|
|
Packit Service |
54dbc3 |
adj_list_size = num_sw + 1;
|
|
Packit Service |
54dbc3 |
/* allocate an adjazenz list (array), 0. element is reserved for the source (Hca) in the routing algo, others are switches */
|
|
Packit Service |
54dbc3 |
adj_list = (vertex_t *) malloc(adj_list_size * sizeof(vertex_t));
|
|
Packit Service |
54dbc3 |
if (!adj_list) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD02: cannot allocate memory for adj_list\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
for (i = 0; i < adj_list_size; i++)
|
|
Packit Service |
54dbc3 |
set_default_vertex(&adj_list[i]);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list = adj_list;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list_size = adj_list_size;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* count the total number of Hca / LIDs (for lmc>0) in the fabric;
|
|
Packit Service |
54dbc3 |
even include base/enhanced switch port 0; base SP0 will have lmc=0
|
|
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 |
p_port = (osm_port_t *) item;
|
|
Packit Service |
54dbc3 |
if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_CA ||
|
|
Packit Service |
54dbc3 |
osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH) {
|
|
Packit Service |
54dbc3 |
lmc = osm_port_get_lmc(p_port);
|
|
Packit Service |
54dbc3 |
total_num_hca += (1 << lmc);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
i = 1; /* fill adj_list -> start with index 1 */
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item), i++) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *) item;
|
|
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(sw->p_node)));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
adj_list[i].guid =
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(sw->p_node));
|
|
Packit Service |
54dbc3 |
adj_list[i].lid =
|
|
Packit Service |
54dbc3 |
cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0));
|
|
Packit Service |
54dbc3 |
adj_list[i].sw = sw;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
link = (link_t *) malloc(sizeof(link_t));
|
|
Packit Service |
54dbc3 |
if (!link) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD03: cannot allocate memory for a link\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
head = link;
|
|
Packit Service |
54dbc3 |
head->next = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* add SP0 to number of CA connected to a switch */
|
|
Packit Service |
54dbc3 |
lmc = osm_node_get_lmc(sw->p_node, 0);
|
|
Packit Service |
54dbc3 |
adj_list[i].num_hca += (1 << lmc);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* iterate over all ports in the switch, start with port 1 (port 0 is a management port) */
|
|
Packit Service |
54dbc3 |
for (port = 1; port < sw->num_ports; port++) {
|
|
Packit Service |
54dbc3 |
/* get the node behind the port */
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(sw->p_node, port,
|
|
Packit Service |
54dbc3 |
&remote_port);
|
|
Packit Service |
54dbc3 |
/* if there is no remote node on this port or it's the same switch -> try next port */
|
|
Packit Service |
54dbc3 |
if (!remote_node || remote_node->sw == sw)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
/* make sure the link is healthy */
|
|
Packit Service |
54dbc3 |
p_physp = osm_node_get_physp_ptr(sw->p_node, port);
|
|
Packit Service |
54dbc3 |
if (!p_physp || !osm_link_is_healthy(p_physp))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
/* if there is a Hca connected -> count and cycle */
|
|
Packit Service |
54dbc3 |
if (!remote_node->sw) {
|
|
Packit Service |
54dbc3 |
lmc = osm_node_get_lmc(remote_node, (uint32_t)remote_port);
|
|
Packit Service |
54dbc3 |
adj_list[i].num_hca += (1 << lmc);
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* filter out throttled links to improve performance */
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.avoid_throttled_links &&
|
|
Packit Service |
54dbc3 |
osm_link_is_throttled(p_physp, has_fdr10)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"Detected and ignoring throttled link:"
|
|
Packit Service |
54dbc3 |
" 0x%" PRIx64 "/P%" PRIu8
|
|
Packit Service |
54dbc3 |
" <--> 0x%" PRIx64 "/P%" PRIu8 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(sw->p_node)),
|
|
Packit Service |
54dbc3 |
port,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(remote_node)),
|
|
Packit Service |
54dbc3 |
remote_port);
|
|
Packit Service |
54dbc3 |
continue;
|
|
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 %" PRIu8 ", remote port %" PRIu8 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(sw->p_node)),
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(remote_node)),
|
|
Packit Service |
54dbc3 |
port, remote_port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
link->next = (link_t *) malloc(sizeof(link_t));
|
|
Packit Service |
54dbc3 |
if (!link->next) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD08: cannot allocate memory for a link\n");
|
|
Packit Service |
54dbc3 |
while (head) {
|
|
Packit Service |
54dbc3 |
link = head;
|
|
Packit Service |
54dbc3 |
head = head->next;
|
|
Packit Service |
54dbc3 |
free(link);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
set_default_link(link);
|
|
Packit Service |
54dbc3 |
link->guid =
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(remote_node));
|
|
Packit Service |
54dbc3 |
link->from = i;
|
|
Packit Service |
54dbc3 |
link->from_port = port;
|
|
Packit Service |
54dbc3 |
link->to_port = remote_port;
|
|
Packit Service |
54dbc3 |
link->weight = total_num_hca * total_num_hca; /* initialize with P^2 to force shortest paths */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
adj_list[i].links = head->next;
|
|
Packit Service |
54dbc3 |
free(head);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* connect the links with it's second adjacent node in the list */
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
link = adj_list[i].links;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
for (j = 1; j < adj_list_size; j++) {
|
|
Packit Service |
54dbc3 |
if (link->guid == adj_list[j].guid) {
|
|
Packit Service |
54dbc3 |
link->to = j;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* do one dry run to determine connectivity issues */
|
|
Packit Service |
54dbc3 |
sm_lid = p_mgr->p_subn->master_sm_base_lid;
|
|
Packit Service |
54dbc3 |
p_port = osm_get_port_by_lid(p_mgr->p_subn, sm_lid);
|
|
Packit Service |
54dbc3 |
err = dijkstra(p_mgr, &heap, adj_list, adj_list_size, p_port, sm_lid);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* if sm is running on a switch, then dijkstra doesn't
|
|
Packit Service |
54dbc3 |
initialize the used_link for this switch
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_CA)
|
|
Packit Service |
54dbc3 |
max_num_undiscov = 1;
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++)
|
|
Packit Service |
54dbc3 |
undiscov += (adj_list[i].used_link) ? 0 : 1;
|
|
Packit Service |
54dbc3 |
if (max_num_undiscov < undiscov) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD0C: unsupported network state (detached"
|
|
Packit Service |
54dbc3 |
" and inaccessible switches found; gracefully"
|
|
Packit Service |
54dbc3 |
" shutdown this routing engine)\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* delete the heap which is not needed anymore */
|
|
Packit Service |
54dbc3 |
cl_heap_destroy(&heap;;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* print the discovered graph */
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG))
|
|
Packit Service |
54dbc3 |
dfsssp_print_graph(p_mgr, adj_list, adj_list_size);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
if (cl_is_heap_inited(&heap))
|
|
Packit Service |
54dbc3 |
cl_heap_destroy(&heap;;
|
|
Packit Service |
54dbc3 |
dfsssp_context_destroy(context);
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void print_routes(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list,
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size, osm_port_t * port)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, j = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
if (adj_list[i].state == DISCOVERED) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Route from 0x%" PRIx64 " (%s) to 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
" (%s):\n", adj_list[i].guid,
|
|
Packit Service |
54dbc3 |
adj_list[i].sw->p_node->print_desc,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(port->p_node)),
|
|
Packit Service |
54dbc3 |
port->p_node->print_desc);
|
|
Packit Service |
54dbc3 |
j = i;
|
|
Packit Service |
54dbc3 |
while (adj_list[j].used_link) {
|
|
Packit Service |
54dbc3 |
if (j > 0) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
" (%s) routes thru port %" PRIu8
|
|
Packit Service |
54dbc3 |
"\n", adj_list[j].guid,
|
|
Packit Service |
54dbc3 |
adj_list[j].sw->p_node->
|
|
Packit Service |
54dbc3 |
print_desc,
|
|
Packit Service |
54dbc3 |
adj_list[j].used_link->to_port);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
" (%s) routes thru port %" PRIu8
|
|
Packit Service |
54dbc3 |
"\n", adj_list[j].guid,
|
|
Packit Service |
54dbc3 |
port->p_node->print_desc,
|
|
Packit Service |
54dbc3 |
adj_list[j].used_link->to_port);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
j = adj_list[j].used_link->from;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* callback function for the cl_heap to update the index */
|
|
Packit Service |
54dbc3 |
static void apply_index_update(const void * context, const size_t new_index)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
vertex_t *heap_elem = (vertex_t *) context;
|
|
Packit Service |
54dbc3 |
if (heap_elem)
|
|
Packit Service |
54dbc3 |
heap_elem->heap_index = new_index;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* dijkstra step from one source to all switches in the df-/sssp graph */
|
|
Packit Service |
54dbc3 |
static int dijkstra(osm_ucast_mgr_t * p_mgr, cl_heap_t * p_heap,
|
|
Packit Service |
54dbc3 |
vertex_t * adj_list, uint32_t adj_list_size,
|
|
Packit Service |
54dbc3 |
osm_port_t * port, uint16_t lid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, j = 0, index = 0;
|
|
Packit Service |
54dbc3 |
osm_node_t *remote_node = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t remote_port = 0;
|
|
Packit Service |
54dbc3 |
vertex_t *current = NULL;
|
|
Packit Service |
54dbc3 |
link_t *link = NULL;
|
|
Packit Service |
54dbc3 |
uint64_t guid = 0;
|
|
Packit Service |
54dbc3 |
cl_status_t ret = CL_SUCCESS;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* build an 4-ary heap to find the node with minimum distance */
|
|
Packit Service |
54dbc3 |
if (!cl_is_heap_inited(p_heap))
|
|
Packit Service |
54dbc3 |
ret = cl_heap_init(p_heap, adj_list_size, 4,
|
|
Packit Service |
54dbc3 |
&apply_index_update, NULL);
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
ret = cl_heap_resize(p_heap, adj_list_size);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD09: cannot allocate memory or resize heap\n");
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* reset all switches for new round with a new source for dijkstra */
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
adj_list[i].hops = 0;
|
|
Packit Service |
54dbc3 |
adj_list[i].used_link = NULL;
|
|
Packit Service |
54dbc3 |
adj_list[i].distance = INF;
|
|
Packit Service |
54dbc3 |
adj_list[i].state = UNDISCOVERED;
|
|
Packit Service |
54dbc3 |
ret = cl_heap_insert(p_heap, INF, &adj_list[i]);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD11: cl_heap_insert failed\n");
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if behind port is a Hca -> set adj_list[0] */
|
|
Packit Service |
54dbc3 |
if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_CA) {
|
|
Packit Service |
54dbc3 |
/* save old link to prevent many mallocs after set_default_... */
|
|
Packit Service |
54dbc3 |
link = adj_list[0].links;
|
|
Packit Service |
54dbc3 |
/* initialize adj_list[0] (the source for the routing, a Hca) */
|
|
Packit Service |
54dbc3 |
set_default_vertex(&adj_list[0]);
|
|
Packit Service |
54dbc3 |
adj_list[0].guid =
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(port->p_node));
|
|
Packit Service |
54dbc3 |
adj_list[0].lid = lid;
|
|
Packit Service |
54dbc3 |
index = 0;
|
|
Packit Service |
54dbc3 |
/* write saved link back to new adj_list[0] */
|
|
Packit Service |
54dbc3 |
adj_list[0].links = link;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* initialize link to neighbor for adj_list[0];
|
|
Packit Service |
54dbc3 |
make sure the link is healthy
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (port->p_physp && osm_link_is_healthy(port->p_physp)) {
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(port->p_node,
|
|
Packit Service |
54dbc3 |
port->p_physp->port_num,
|
|
Packit Service |
54dbc3 |
&remote_port);
|
|
Packit Service |
54dbc3 |
/* if there is no remote node on this port or it's the same Hca -> ignore */
|
|
Packit Service |
54dbc3 |
if (remote_node
|
|
Packit Service |
54dbc3 |
&& (osm_node_get_type(remote_node) ==
|
|
Packit Service |
54dbc3 |
IB_NODE_TYPE_SWITCH)) {
|
|
Packit Service |
54dbc3 |
if (!(adj_list[0].links)) {
|
|
Packit Service |
54dbc3 |
adj_list[0].links =
|
|
Packit Service |
54dbc3 |
(link_t *) malloc(sizeof(link_t));
|
|
Packit Service |
54dbc3 |
if (!(adj_list[0].links)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log,
|
|
Packit Service |
54dbc3 |
OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD07: cannot allocate memory for a link\n");
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
set_default_link(adj_list[0].links);
|
|
Packit Service |
54dbc3 |
adj_list[0].links->guid =
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(remote_node));
|
|
Packit Service |
54dbc3 |
adj_list[0].links->from_port =
|
|
Packit Service |
54dbc3 |
port->p_physp->port_num;
|
|
Packit Service |
54dbc3 |
adj_list[0].links->to_port = remote_port;
|
|
Packit Service |
54dbc3 |
adj_list[0].links->weight = 1;
|
|
Packit Service |
54dbc3 |
for (j = 1; j < adj_list_size; j++) {
|
|
Packit Service |
54dbc3 |
if (adj_list[0].links->guid ==
|
|
Packit Service |
54dbc3 |
adj_list[j].guid) {
|
|
Packit Service |
54dbc3 |
adj_list[0].links->to = j;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* if link is unhealthy then there's a severe issue */
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD0B: unsupported network state (CA with"
|
|
Packit Service |
54dbc3 |
" unhealthy link state discovered; should have"
|
|
Packit Service |
54dbc3 |
" been filtered out before already; gracefully"
|
|
Packit Service |
54dbc3 |
" shutdown this routing engine)\n");
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
ret = cl_heap_insert(p_heap, INF, &adj_list[0]);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD13: cl_heap_insert failed\n");
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* if behind port is a switch -> search switch in adj_list */
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* reset adj_list[0], if links=NULL reset was done before, then skip */
|
|
Packit Service |
54dbc3 |
if (adj_list[0].links) {
|
|
Packit Service |
54dbc3 |
free(adj_list[0].links);
|
|
Packit Service |
54dbc3 |
set_default_vertex(&adj_list[0]);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* search for the switch which is the source in this round */
|
|
Packit Service |
54dbc3 |
guid = cl_ntoh64(osm_node_get_node_guid(port->p_node));
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
if (guid == adj_list[i].guid) {
|
|
Packit Service |
54dbc3 |
index = i;
|
|
Packit Service |
54dbc3 |
break;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* source in dijkstra */
|
|
Packit Service |
54dbc3 |
adj_list[index].distance = 0;
|
|
Packit Service |
54dbc3 |
adj_list[index].state = DISCOVERED;
|
|
Packit Service |
54dbc3 |
adj_list[index].hops = 0; /* the source has hop count = 0 */
|
|
Packit Service |
54dbc3 |
ret = cl_heap_modify_key(p_heap, adj_list[index].distance,
|
|
Packit Service |
54dbc3 |
adj_list[index].heap_index);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD10: index out of bounds in cl_heap_modify_key\n");
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
current = (vertex_t *) cl_heap_extract_root(p_heap);
|
|
Packit Service |
54dbc3 |
while (current) {
|
|
Packit Service |
54dbc3 |
current->state = DISCOVERED;
|
|
Packit Service |
54dbc3 |
if (current->used_link) /* increment the number of hops to the source for each new node */
|
|
Packit Service |
54dbc3 |
current->hops =
|
|
Packit Service |
54dbc3 |
adj_list[current->used_link->from].hops + 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* add/update nodes which aren't discovered but accessible */
|
|
Packit Service |
54dbc3 |
for (link = current->links; link != NULL; link = link->next) {
|
|
Packit Service |
54dbc3 |
if ((adj_list[link->to].state != DISCOVERED)
|
|
Packit Service |
54dbc3 |
&& (current->distance + link->weight <
|
|
Packit Service |
54dbc3 |
adj_list[link->to].distance)) {
|
|
Packit Service |
54dbc3 |
adj_list[link->to].used_link = link;
|
|
Packit Service |
54dbc3 |
adj_list[link->to].distance =
|
|
Packit Service |
54dbc3 |
current->distance + link->weight;
|
|
Packit Service |
54dbc3 |
ret = cl_heap_modify_key(p_heap,
|
|
Packit Service |
54dbc3 |
adj_list[link->to].distance,
|
|
Packit Service |
54dbc3 |
adj_list[link->to].heap_index);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD12: index out of bounds in cl_heap_modify_key\n");
|
|
Packit Service |
54dbc3 |
return ret;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
current = (vertex_t *) cl_heap_extract_root(p_heap);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* update the linear forwarding tables of all switches with the informations
|
|
Packit Service |
54dbc3 |
from the last dijsktra step
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int update_lft(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list,
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size, osm_port_t * p_port, uint16_t lid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0;
|
|
Packit Service |
54dbc3 |
uint8_t port = 0;
|
|
Packit Service |
54dbc3 |
uint8_t hops = 0;
|
|
Packit Service |
54dbc3 |
osm_switch_t *p_sw = NULL;
|
|
Packit Service |
54dbc3 |
boolean_t is_ignored_by_port_prof = FALSE;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p = NULL;
|
|
Packit Service |
54dbc3 |
cl_status_t ret;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
/* if no route goes thru this switch -> cycle */
|
|
Packit Service |
54dbc3 |
if (!(adj_list[i].used_link))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_sw = adj_list[i].sw;
|
|
Packit Service |
54dbc3 |
hops = adj_list[i].hops;
|
|
Packit Service |
54dbc3 |
port = adj_list[i].used_link->to_port;
|
|
Packit Service |
54dbc3 |
/* the used_link is the link that was used in dijkstra to reach this node,
|
|
Packit Service |
54dbc3 |
so the to_port is the local port on this node
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (port == OSM_NO_PATH) { /* if clause shouldn't be possible in this routing, but who cares */
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD06: No path to get to LID %" PRIu16
|
|
Packit Service |
54dbc3 |
" from switch 0x%" PRIx64 "\n", lid,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
|
|
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 |
return 1;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Routing LID %" PRIu16 " to port %" PRIu8
|
|
Packit Service |
54dbc3 |
" for switch 0x%" PRIx64 "\n", lid, port,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p = osm_node_get_physp_ptr(p_sw->p_node, port);
|
|
Packit Service |
54dbc3 |
if (!p) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD0A: Physical port %d of Node GUID 0x%"
|
|
Packit Service |
54dbc3 |
PRIx64 "not found\n", port,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
return 1;
|
|
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 |
/* 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 |
/* to support lmc > 0 the functions alloc_ports_priv, free_ports_priv, find_and_add_remote_sys
|
|
Packit Service |
54dbc3 |
from minhop aren't needed cause osm_switch_recommend_path is implicitly calculated
|
|
Packit Service |
54dbc3 |
for each LID pair thru dijkstra;
|
|
Packit Service |
54dbc3 |
for each port the dijkstra algorithm calculates (max_lid_ho - min_lid_ho)-times maybe
|
|
Packit Service |
54dbc3 |
disjoint routes to spread the bandwidth -> diffent routes for one port and lmc>0
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* set port in LFT */
|
|
Packit Service |
54dbc3 |
p_sw->new_lft[lid] = port;
|
|
Packit Service |
54dbc3 |
if (!is_ignored_by_port_prof) {
|
|
Packit Service |
54dbc3 |
/* update the number of path routing thru this port */
|
|
Packit Service |
54dbc3 |
osm_switch_count_path(p_sw, port);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* set the hop count from this switch to the lid */
|
|
Packit Service |
54dbc3 |
ret = osm_switch_set_hops(p_sw, lid, port, hops);
|
|
Packit Service |
54dbc3 |
if (ret != CL_SUCCESS)
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD05: cannot set hops for LID %" PRIu16
|
|
Packit Service |
54dbc3 |
" at switch 0x%" PRIx64 "\n", lid,
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(p_sw->p_node)));
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* the function updates the multicast group membership information
|
|
Packit Service |
54dbc3 |
similar to create_mgrp_switch_map (osm_mcast_mgr.c)
|
|
Packit Service |
54dbc3 |
=> with it we can identify if a switch needs to be processed
|
|
Packit Service |
54dbc3 |
or not in update_mcft
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static void update_mgrp_membership(cl_qlist_t * port_list)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_mcast_work_obj_t *wobj = NULL;
|
|
Packit Service |
54dbc3 |
osm_port_t *port = NULL;
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = NULL;
|
|
Packit Service |
54dbc3 |
cl_list_item_t *i = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = cl_qlist_head(port_list); i != cl_qlist_end(port_list);
|
|
Packit Service |
54dbc3 |
i = cl_qlist_next(i)) {
|
|
Packit Service |
54dbc3 |
wobj = cl_item_obj(i, wobj, list_item);
|
|
Packit Service |
54dbc3 |
port = wobj->p_port;
|
|
Packit Service |
54dbc3 |
if (port->p_node->sw) {
|
|
Packit Service |
54dbc3 |
sw = port->p_node->sw;
|
|
Packit Service |
54dbc3 |
sw->is_mc_member = 1;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
sw = port->p_physp->p_remote_physp->p_node->sw;
|
|
Packit Service |
54dbc3 |
sw->num_of_mcm++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* reset is_mc_member and num_of_mcm for future computations */
|
|
Packit Service |
54dbc3 |
static void reset_mgrp_membership(vertex_t * adj_list, uint32_t adj_list_size)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
if (adj_list[i].dropped)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
adj_list[i].sw->is_mc_member = 0;
|
|
Packit Service |
54dbc3 |
adj_list[i].sw->num_of_mcm = 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* update the multicast forwarding tables of all switches with the informations
|
|
Packit Service |
54dbc3 |
from the previous dijsktra step for the current mlid
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int update_mcft(osm_sm_t * p_sm, vertex_t * adj_list,
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size, uint16_t mlid_ho,
|
|
Packit Service |
54dbc3 |
cl_qmap_t * port_map, osm_switch_t * root_sw)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0;
|
|
Packit Service |
54dbc3 |
uint8_t port = 0, remote_port = 0;
|
|
Packit Service |
54dbc3 |
uint8_t upstream_port = 0, downstream_port = 0;
|
|
Packit Service |
54dbc3 |
ib_net64_t guid = 0;
|
|
Packit Service |
54dbc3 |
osm_switch_t *p_sw = NULL;
|
|
Packit Service |
54dbc3 |
osm_node_t *remote_node = NULL;
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp = NULL;
|
|
Packit Service |
54dbc3 |
osm_mcast_tbl_t *p_tbl = NULL;
|
|
Packit Service |
54dbc3 |
vertex_t *curr_adj = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_sm->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
if (adj_list[i].dropped)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_sw = adj_list[i].sw;
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Processing switch 0x%016" PRIx64
|
|
Packit Service |
54dbc3 |
" (%s) for MLID 0x%X\n", cl_ntoh64(adj_list[i].guid),
|
|
Packit Service |
54dbc3 |
p_sw->p_node->print_desc, mlid_ho);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if a) the switch does not support mcast or
|
|
Packit Service |
54dbc3 |
b) no ports of this switch are part or the mcast group
|
|
Packit Service |
54dbc3 |
then cycle
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (osm_switch_supports_mcast(p_sw) == FALSE ||
|
|
Packit Service |
54dbc3 |
(p_sw->num_of_mcm == 0 && !(p_sw->is_mc_member)))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* add all ports of this sw to the mcast table,
|
|
Packit Service |
54dbc3 |
if they are part of the mcast grp
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (p_sw->is_mc_member)
|
|
Packit Service |
54dbc3 |
osm_mcast_tbl_set(p_tbl, mlid_ho, 0);
|
|
Packit Service |
54dbc3 |
for (port = 1; port < p_sw->num_ports; port++) {
|
|
Packit Service |
54dbc3 |
/* get the node behind the port */
|
|
Packit Service |
54dbc3 |
remote_node =
|
|
Packit Service |
54dbc3 |
osm_node_get_remote_node(p_sw->p_node, port,
|
|
Packit Service |
54dbc3 |
&remote_port);
|
|
Packit Service |
54dbc3 |
/* check if connected and its not the same switch */
|
|
Packit Service |
54dbc3 |
if (!remote_node || remote_node->sw == p_sw)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
/* make sure the link is healthy */
|
|
Packit Service |
54dbc3 |
p_physp = osm_node_get_physp_ptr(p_sw->p_node, port);
|
|
Packit Service |
54dbc3 |
if (!p_physp || !osm_link_is_healthy(p_physp))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
/* we don't add upstream ports in this step */
|
|
Packit Service |
54dbc3 |
if (osm_node_get_type(remote_node) != IB_NODE_TYPE_CA)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
guid = osm_physp_get_port_guid(osm_node_get_physp_ptr(
|
|
Packit Service |
54dbc3 |
remote_node,
|
|
Packit Service |
54dbc3 |
remote_port));
|
|
Packit Service |
54dbc3 |
if (cl_qmap_get(port_map, guid)
|
|
Packit Service |
54dbc3 |
!= cl_qmap_end(port_map))
|
|
Packit Service |
54dbc3 |
osm_mcast_tbl_set(p_tbl, mlid_ho, port);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* now we have to add the upstream port of 'this' switch and
|
|
Packit Service |
54dbc3 |
the downstream port of the next switch to the mcast table
|
|
Packit Service |
54dbc3 |
until we reach the root_sw
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
curr_adj = &adj_list[i];
|
|
Packit Service |
54dbc3 |
while (curr_adj->sw != root_sw) {
|
|
Packit Service |
54dbc3 |
/* the used_link is the link that was used in dijkstra to reach this node,
|
|
Packit Service |
54dbc3 |
so the to_port is the local (upstream) port on curr_adj->sw
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
upstream_port = curr_adj->used_link->to_port;
|
|
Packit Service |
54dbc3 |
osm_mcast_tbl_set(p_tbl, mlid_ho, upstream_port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* now we go one step in direction root_sw and add the
|
|
Packit Service |
54dbc3 |
downstream port for the spanning tree
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
downstream_port = curr_adj->used_link->from_port;
|
|
Packit Service |
54dbc3 |
p_tbl = osm_switch_get_mcast_tbl_ptr(
|
|
Packit Service |
54dbc3 |
adj_list[curr_adj->used_link->from].sw);
|
|
Packit Service |
54dbc3 |
osm_mcast_tbl_set(p_tbl, mlid_ho, downstream_port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
curr_adj = &adj_list[curr_adj->used_link->from];
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_sm->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* increment the edge weights of the df-/sssp graph which represent the number
|
|
Packit Service |
54dbc3 |
of paths on this link
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static void update_weights(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list,
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, j = 0;
|
|
Packit Service |
54dbc3 |
uint32_t additional_weight = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
/* if no route goes thru this switch -> cycle */
|
|
Packit Service |
54dbc3 |
if (!(adj_list[i].used_link))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
additional_weight = adj_list[i].num_hca;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
j = i;
|
|
Packit Service |
54dbc3 |
while (adj_list[j].used_link) {
|
|
Packit Service |
54dbc3 |
/* update the link from pre to this node */
|
|
Packit Service |
54dbc3 |
adj_list[j].used_link->weight += additional_weight;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
j = adj_list[j].used_link->from;
|
|
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 |
/* get the largest number of virtual lanes which is supported by all switches
|
|
Packit Service |
54dbc3 |
in the subnet
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static uint8_t get_avail_vl_in_subn(osm_ucast_mgr_t * p_mgr)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
uint32_t i = 0;
|
|
Packit Service |
54dbc3 |
uint8_t vls_avail = 0xFF, port_vls_avail = 0;
|
|
Packit Service |
54dbc3 |
cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item = NULL;
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* traverse all switches to get the number of available virtual lanes in the subnet */
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *) item;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* ignore management port 0 */
|
|
Packit Service |
54dbc3 |
for (i = 1; i < osm_node_get_num_physp(sw->p_node); i++) {
|
|
Packit Service |
54dbc3 |
osm_physp_t *p_physp =
|
|
Packit Service |
54dbc3 |
osm_node_get_physp_ptr(sw->p_node, i);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (p_physp && p_physp->p_remote_physp) {
|
|
Packit Service |
54dbc3 |
port_vls_avail =
|
|
Packit Service |
54dbc3 |
ib_port_info_get_op_vls(&p_physp->
|
|
Packit Service |
54dbc3 |
port_info);
|
|
Packit Service |
54dbc3 |
if (port_vls_avail
|
|
Packit Service |
54dbc3 |
&& port_vls_avail < vls_avail)
|
|
Packit Service |
54dbc3 |
vls_avail = port_vls_avail;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* ib_port_info_get_op_vls gives values 1 ... 5 (s. IBAS 14.2.5.6) */
|
|
Packit Service |
54dbc3 |
vls_avail = 1 << (vls_avail - 1);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* set boundaries (s. IBAS 3.5.7) */
|
|
Packit Service |
54dbc3 |
if (vls_avail > 15)
|
|
Packit Service |
54dbc3 |
vls_avail = 15;
|
|
Packit Service |
54dbc3 |
if (vls_avail < 1)
|
|
Packit Service |
54dbc3 |
vls_avail = 1;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return vls_avail;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* search for cycles in the channel dependency graph to identify possible
|
|
Packit Service |
54dbc3 |
deadlocks in the network;
|
|
Packit Service |
54dbc3 |
assign new virtual lanes to some paths to break the deadlocks
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int dfsssp_remove_deadlocks(dfsssp_context_t * dfsssp_ctx)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qlist_t *port_tbl = &p_mgr->port_order_list; /* 1 management port per switch + 1 or 2 ports for each Hca */
|
|
Packit Service |
54dbc3 |
cl_list_item_t *item1 = NULL, *item2 = NULL;
|
|
Packit Service |
54dbc3 |
osm_port_t *src_port = NULL, *dest_port = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, j = 0, err = 0;
|
|
Packit Service |
54dbc3 |
uint8_t vl = 0, test_vl = 0, vl_avail = 0, vl_needed = 1;
|
|
Packit Service |
54dbc3 |
double most_avg_paths = 0.0;
|
|
Packit Service |
54dbc3 |
cdg_node_t **cdg = NULL, *start_here = NULL, *cycle = NULL;
|
|
Packit Service |
54dbc3 |
cdg_link_t *weakest_link = NULL;
|
|
Packit Service |
54dbc3 |
uint32_t srcdest = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
vltable_t *srcdest2vl_table = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t lmc = 0;
|
|
Packit Service |
54dbc3 |
uint16_t slid = 0, dlid = 0, min_lid_ho = 0, max_lid_ho =
|
|
Packit Service |
54dbc3 |
0, min_lid_ho2 = 0, max_lid_ho2 = 0;;
|
|
Packit Service |
54dbc3 |
uint64_t *paths_per_vl = NULL;
|
|
Packit Service |
54dbc3 |
uint64_t from = 0, to = 0, count = 0;
|
|
Packit Service |
54dbc3 |
uint8_t *split_count = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t ntype = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Assign each src/dest pair a Virtual Lanes, to remove deadlocks in the routing\n");
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
vl_avail = get_avail_vl_in_subn(p_mgr);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"Virtual Lanes available: %" PRIu8 "\n", vl_avail);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
paths_per_vl = (uint64_t *) malloc(vl_avail * sizeof(uint64_t));
|
|
Packit Service |
54dbc3 |
if (!paths_per_vl) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD22: cannot allocate memory for paths_per_vl\n");
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
memset(paths_per_vl, 0, vl_avail * sizeof(uint64_t));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cdg = (cdg_node_t **) malloc(vl_avail * sizeof(cdg_node_t *));
|
|
Packit Service |
54dbc3 |
if (!cdg) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD23: cannot allocate memory for cdg\n");
|
|
Packit Service |
54dbc3 |
free(paths_per_vl);
|
|
Packit Service |
54dbc3 |
return 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
for (i = 0; i < vl_avail; i++)
|
|
Packit Service |
54dbc3 |
cdg[i] = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
count = 0;
|
|
Packit Service |
54dbc3 |
/* count all ports (also multiple LIDs) of type CA or SP0 for size of VL table */
|
|
Packit Service |
54dbc3 |
for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item1 = cl_qlist_next(item1)) {
|
|
Packit Service |
54dbc3 |
dest_port = (osm_port_t *)cl_item_obj(item1, dest_port,
|
|
Packit Service |
54dbc3 |
list_item);
|
|
Packit Service |
54dbc3 |
ntype = osm_node_get_type(dest_port->p_node);
|
|
Packit Service |
54dbc3 |
if (ntype == IB_NODE_TYPE_CA || ntype == IB_NODE_TYPE_SWITCH) {
|
|
Packit Service |
54dbc3 |
/* only SP0 with SLtoVLMapping support will be processed */
|
|
Packit Service |
54dbc3 |
if (ntype == IB_NODE_TYPE_SWITCH
|
|
Packit Service |
54dbc3 |
&& !(dest_port->p_physp->port_info.capability_mask
|
|
Packit Service |
54dbc3 |
& IB_PORT_CAP_HAS_SL_MAP))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
lmc = osm_port_get_lmc(dest_port);
|
|
Packit Service |
54dbc3 |
count += (1 << lmc);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* allocate VL table and indexing array */
|
|
Packit Service |
54dbc3 |
err = vltable_alloc(&srcdest2vl_table, count);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD26: cannot allocate memory for srcdest2vl_table\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
i = 0;
|
|
Packit Service |
54dbc3 |
/* fill lids into indexing array */
|
|
Packit Service |
54dbc3 |
for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item1 = cl_qlist_next(item1)) {
|
|
Packit Service |
54dbc3 |
dest_port = (osm_port_t *)cl_item_obj(item1, dest_port,
|
|
Packit Service |
54dbc3 |
list_item);
|
|
Packit Service |
54dbc3 |
ntype = osm_node_get_type(dest_port->p_node);
|
|
Packit Service |
54dbc3 |
if (ntype == IB_NODE_TYPE_CA || ntype == IB_NODE_TYPE_SWITCH) {
|
|
Packit Service |
54dbc3 |
/* only SP0 with SLtoVLMapping support will be processed */
|
|
Packit Service |
54dbc3 |
if (ntype == IB_NODE_TYPE_SWITCH
|
|
Packit Service |
54dbc3 |
&& !(dest_port->p_physp->port_info.capability_mask
|
|
Packit Service |
54dbc3 |
& IB_PORT_CAP_HAS_SL_MAP))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
osm_port_get_lid_range_ho(dest_port, &min_lid_ho,
|
|
Packit Service |
54dbc3 |
&max_lid_ho);
|
|
Packit Service |
54dbc3 |
for (dlid = min_lid_ho; dlid <= max_lid_ho; dlid++, i++)
|
|
Packit Service |
54dbc3 |
srcdest2vl_table->lids[i] = cl_hton16(dlid);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* sort lids */
|
|
Packit Service |
54dbc3 |
vltable_sort_lids(srcdest2vl_table);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
test_vl = 0;
|
|
Packit Service |
54dbc3 |
/* fill cdg[0] with routes from each src/dest port combination for all Hca/SP0 in the subnet */
|
|
Packit Service |
54dbc3 |
for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item1 = cl_qlist_next(item1)) {
|
|
Packit Service |
54dbc3 |
dest_port = (osm_port_t *)cl_item_obj(item1, dest_port,
|
|
Packit Service |
54dbc3 |
list_item);
|
|
Packit Service |
54dbc3 |
ntype = osm_node_get_type(dest_port->p_node);
|
|
Packit Service |
54dbc3 |
if ((ntype != IB_NODE_TYPE_CA && ntype != IB_NODE_TYPE_SWITCH)
|
|
Packit Service |
54dbc3 |
|| !(dest_port->p_physp->port_info.capability_mask
|
|
Packit Service |
54dbc3 |
& IB_PORT_CAP_HAS_SL_MAP))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (item2 = cl_qlist_head(port_tbl);
|
|
Packit Service |
54dbc3 |
item2 != cl_qlist_end(port_tbl);
|
|
Packit Service |
54dbc3 |
item2 = cl_qlist_next(item2)) {
|
|
Packit Service |
54dbc3 |
src_port = (osm_port_t *)cl_item_obj(item2, src_port,
|
|
Packit Service |
54dbc3 |
list_item);
|
|
Packit Service |
54dbc3 |
ntype = osm_node_get_type(src_port->p_node);
|
|
Packit Service |
54dbc3 |
if ((ntype != IB_NODE_TYPE_CA
|
|
Packit Service |
54dbc3 |
&& ntype != IB_NODE_TYPE_SWITCH)
|
|
Packit Service |
54dbc3 |
|| !(src_port->p_physp->port_info.capability_mask
|
|
Packit Service |
54dbc3 |
& IB_PORT_CAP_HAS_SL_MAP))
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (src_port != dest_port) {
|
|
Packit Service |
54dbc3 |
/* iterate over LIDs of src and dest port */
|
|
Packit Service |
54dbc3 |
osm_port_get_lid_range_ho(src_port, &min_lid_ho,
|
|
Packit Service |
54dbc3 |
&max_lid_ho);
|
|
Packit Service |
54dbc3 |
for (slid = min_lid_ho; slid <= max_lid_ho;
|
|
Packit Service |
54dbc3 |
slid++) {
|
|
Packit Service |
54dbc3 |
osm_port_get_lid_range_ho
|
|
Packit Service |
54dbc3 |
(dest_port, &min_lid_ho2,
|
|
Packit Service |
54dbc3 |
&max_lid_ho2);
|
|
Packit Service |
54dbc3 |
for (dlid = min_lid_ho2;
|
|
Packit Service |
54dbc3 |
dlid <= max_lid_ho2;
|
|
Packit Service |
54dbc3 |
dlid++) {
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* try to add the path to cdg[0] */
|
|
Packit Service |
54dbc3 |
err =
|
|
Packit Service |
54dbc3 |
update_channel_dep_graph
|
|
Packit Service |
54dbc3 |
(&(cdg[test_vl]),
|
|
Packit Service |
54dbc3 |
src_port, slid,
|
|
Packit Service |
54dbc3 |
dest_port, dlid);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->
|
|
Packit Service |
54dbc3 |
p_log,
|
|
Packit Service |
54dbc3 |
OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD14: cannot allocate memory for cdg node or link in update_channel_dep_graph(...)\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* add the <s,d> combination / corresponding virtual lane to the VL table */
|
|
Packit Service |
54dbc3 |
vltable_insert
|
|
Packit Service |
54dbc3 |
(srcdest2vl_table,
|
|
Packit Service |
54dbc3 |
cl_hton16(slid),
|
|
Packit Service |
54dbc3 |
cl_hton16(dlid),
|
|
Packit Service |
54dbc3 |
test_vl);
|
|
Packit Service |
54dbc3 |
paths_per_vl[test_vl]++;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->srcdest2vl_table = srcdest2vl_table;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* test all cdg for cycles and break the cycles by moving paths on the weakest link to the next cdg */
|
|
Packit Service |
54dbc3 |
for (test_vl = 0; test_vl < vl_avail - 1; test_vl++) {
|
|
Packit Service |
54dbc3 |
start_here = cdg[test_vl];
|
|
Packit Service |
54dbc3 |
while (start_here) {
|
|
Packit Service |
54dbc3 |
cycle =
|
|
Packit Service |
54dbc3 |
search_cycle_in_channel_dep_graph(cdg[test_vl],
|
|
Packit Service |
54dbc3 |
start_here);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (cycle) {
|
|
Packit Service |
54dbc3 |
vl_needed = test_vl + 2;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* calc weakest link n cycle */
|
|
Packit Service |
54dbc3 |
weakest_link = get_weakest_link_in_cycle(cycle);
|
|
Packit Service |
54dbc3 |
if (!weakest_link) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD27: something went wrong in get_weakest_link_in_cycle(...)\n");
|
|
Packit Service |
54dbc3 |
err = 1;
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
paths_per_vl[test_vl] -=
|
|
Packit Service |
54dbc3 |
weakest_link->num_pairs;
|
|
Packit Service |
54dbc3 |
paths_per_vl[test_vl + 1] +=
|
|
Packit Service |
54dbc3 |
weakest_link->num_pairs;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* move all <s,d> paths on this link to the next cdg */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < weakest_link->num_pairs; i++) {
|
|
Packit Service |
54dbc3 |
srcdest =
|
|
Packit Service |
54dbc3 |
get_next_srcdest_pair(weakest_link,
|
|
Packit Service |
54dbc3 |
i);
|
|
Packit Service |
54dbc3 |
slid = (uint16_t) (srcdest >> 16);
|
|
Packit Service |
54dbc3 |
dlid =
|
|
Packit Service |
54dbc3 |
(uint16_t) ((srcdest << 16) >> 16);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* only move if not moved in a previous step */
|
|
Packit Service |
54dbc3 |
if (test_vl !=
|
|
Packit Service |
54dbc3 |
(uint8_t)
|
|
Packit Service |
54dbc3 |
vltable_get_vl(srcdest2vl_table,
|
|
Packit Service |
54dbc3 |
cl_hton16(slid),
|
|
Packit Service |
54dbc3 |
cl_hton16(dlid))) {
|
|
Packit Service |
54dbc3 |
/* this path has been moved
|
|
Packit Service |
54dbc3 |
before -> don't count
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
paths_per_vl[test_vl]++;
|
|
Packit Service |
54dbc3 |
paths_per_vl[test_vl + 1]--;
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
src_port =
|
|
Packit Service |
54dbc3 |
osm_get_port_by_lid(p_mgr->p_subn,
|
|
Packit Service |
54dbc3 |
cl_hton16
|
|
Packit Service |
54dbc3 |
(slid));
|
|
Packit Service |
54dbc3 |
dest_port =
|
|
Packit Service |
54dbc3 |
osm_get_port_by_lid(p_mgr->p_subn,
|
|
Packit Service |
54dbc3 |
cl_hton16
|
|
Packit Service |
54dbc3 |
(dlid));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* remove path from current cdg / vl */
|
|
Packit Service |
54dbc3 |
err =
|
|
Packit Service |
54dbc3 |
remove_path_from_cdg(&
|
|
Packit Service |
54dbc3 |
(cdg[test_vl]),
|
|
Packit Service |
54dbc3 |
src_port, slid,
|
|
Packit Service |
54dbc3 |
dest_port,
|
|
Packit Service |
54dbc3 |
dlid);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log,
|
|
Packit Service |
54dbc3 |
OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD44: something went wrong in remove_path_from_cdg(...)\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* add path to next cdg / vl */
|
|
Packit Service |
54dbc3 |
err =
|
|
Packit Service |
54dbc3 |
update_channel_dep_graph(&
|
|
Packit Service |
54dbc3 |
(cdg
|
|
Packit Service |
54dbc3 |
[test_vl +
|
|
Packit Service |
54dbc3 |
1]),
|
|
Packit Service |
54dbc3 |
src_port,
|
|
Packit Service |
54dbc3 |
slid,
|
|
Packit Service |
54dbc3 |
dest_port,
|
|
Packit Service |
54dbc3 |
dlid);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log,
|
|
Packit Service |
54dbc3 |
OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD14: cannot allocate memory for cdg node or link in update_channel_dep_graph(...)\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
vltable_insert(srcdest2vl_table,
|
|
Packit Service |
54dbc3 |
cl_hton16(slid),
|
|
Packit Service |
54dbc3 |
cl_hton16(dlid),
|
|
Packit Service |
54dbc3 |
test_vl + 1);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (weakest_link->num_pairs)
|
|
Packit Service |
54dbc3 |
free(weakest_link->srcdest_pairs);
|
|
Packit Service |
54dbc3 |
if (weakest_link)
|
|
Packit Service |
54dbc3 |
free(weakest_link);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
start_here = cycle;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* test the last avail cdg for a cycle;
|
|
Packit Service |
54dbc3 |
if there is one, than vl_needed > vl_avail
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
start_here = cdg[vl_avail - 1];
|
|
Packit Service |
54dbc3 |
if (start_here) {
|
|
Packit Service |
54dbc3 |
cycle =
|
|
Packit Service |
54dbc3 |
search_cycle_in_channel_dep_graph(cdg[vl_avail - 1],
|
|
Packit Service |
54dbc3 |
start_here);
|
|
Packit Service |
54dbc3 |
if (cycle) {
|
|
Packit Service |
54dbc3 |
vl_needed = vl_avail + 1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"Virtual Lanes needed: %" PRIu8 "\n", vl_needed);
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_INFO)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"Paths per VL (before balancing):\n");
|
|
Packit Service |
54dbc3 |
for (i = 0; i < vl_avail; i++)
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
" %" PRIu32 ". lane: %" PRIu64 "\n", i,
|
|
Packit Service |
54dbc3 |
paths_per_vl[i]);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Balancing the paths on the available Virtual Lanes\n");
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* optimal balancing virtual lanes, under condition: no additional cycle checks;
|
|
Packit Service |
54dbc3 |
sl/vl != 0 might be assigned to loopback packets (i.e. slid/dlid on the
|
|
Packit Service |
54dbc3 |
same port for lmc>0), but thats no problem, see IBAS 10.2.2.3
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
split_count = (uint8_t *) calloc(vl_avail, sizeof(uint8_t));
|
|
Packit Service |
54dbc3 |
if (!split_count) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD24: cannot allocate memory for split_count, skip balancing\n");
|
|
Packit Service |
54dbc3 |
err = 1;
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* initial state: paths for VLs won't be separated */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < ((vl_needed < vl_avail) ? vl_needed : vl_avail); i++)
|
|
Packit Service |
54dbc3 |
split_count[i] = 1;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->vl_split_count = split_count;
|
|
Packit Service |
54dbc3 |
/* balancing is necessary if we have empty VLs */
|
|
Packit Service |
54dbc3 |
if (vl_needed < vl_avail) {
|
|
Packit Service |
54dbc3 |
/* split paths of VLs until we find an equal distribution */
|
|
Packit Service |
54dbc3 |
for (i = vl_needed; i < vl_avail; i++) {
|
|
Packit Service |
54dbc3 |
/* find VL with most paths in it */
|
|
Packit Service |
54dbc3 |
vl = 0;
|
|
Packit Service |
54dbc3 |
most_avg_paths = 0.0;
|
|
Packit Service |
54dbc3 |
for (test_vl = 0; test_vl < vl_needed; test_vl++) {
|
|
Packit Service |
54dbc3 |
if (most_avg_paths <
|
|
Packit Service |
54dbc3 |
((double)paths_per_vl[test_vl] /
|
|
Packit Service |
54dbc3 |
split_count[test_vl])) {
|
|
Packit Service |
54dbc3 |
vl = test_vl;
|
|
Packit Service |
54dbc3 |
most_avg_paths =
|
|
Packit Service |
54dbc3 |
(double)paths_per_vl[test_vl] /
|
|
Packit Service |
54dbc3 |
split_count[test_vl];
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
split_count[vl]++;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* change the VL assignment depending on split_count for
|
|
Packit Service |
54dbc3 |
all VLs except VL 0
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
for (from = vl_needed - 1; from > 0; from--) {
|
|
Packit Service |
54dbc3 |
/* how much space needed for others? */
|
|
Packit Service |
54dbc3 |
to = 0;
|
|
Packit Service |
54dbc3 |
for (i = 0; i < from; i++)
|
|
Packit Service |
54dbc3 |
to += split_count[i];
|
|
Packit Service |
54dbc3 |
count = paths_per_vl[from];
|
|
Packit Service |
54dbc3 |
vltable_change_vl(srcdest2vl_table, from, to, count);
|
|
Packit Service |
54dbc3 |
/* change also the information within the split_count
|
|
Packit Service |
54dbc3 |
array; this is important for fast calculation later
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
split_count[to] = split_count[from];
|
|
Packit Service |
54dbc3 |
split_count[from] = 0;
|
|
Packit Service |
54dbc3 |
paths_per_vl[to] = paths_per_vl[from];
|
|
Packit Service |
54dbc3 |
paths_per_vl[from] = 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
} else if (vl_needed > vl_avail) {
|
|
Packit Service |
54dbc3 |
/* routing not possible, a further development would be the LASH-TOR approach (update: LASH-TOR isn't possible, there is a mistake in the theory) */
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD25: Not enough VLs available (avail=%d, needed=%d); Stopping dfsssp routing!\n",
|
|
Packit Service |
54dbc3 |
vl_avail, vl_needed);
|
|
Packit Service |
54dbc3 |
err = 1;
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* else { no balancing } */
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Virtual Lanes per src/dest combination after balancing:\n");
|
|
Packit Service |
54dbc3 |
vltable_print(p_mgr, srcdest2vl_table);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_INFO)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"Approx. #paths per VL (after balancing):\n");
|
|
Packit Service |
54dbc3 |
j = 0;
|
|
Packit Service |
54dbc3 |
count = 1; /* to prevent div. by 0 */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < vl_avail; i++) {
|
|
Packit Service |
54dbc3 |
if (split_count[i] > 0) {
|
|
Packit Service |
54dbc3 |
j = i;
|
|
Packit Service |
54dbc3 |
count = split_count[i];
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
" %" PRIu32 ". lane: %" PRIu64 "\n", i,
|
|
Packit Service |
54dbc3 |
paths_per_vl[j] / count);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
free(paths_per_vl);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* deallocate channel dependency graphs */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < vl_avail; i++)
|
|
Packit Service |
54dbc3 |
cdg_dealloc(&cdg[i]);
|
|
Packit Service |
54dbc3 |
free(cdg);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
free(paths_per_vl);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
for (i = 0; i < vl_avail; i++)
|
|
Packit Service |
54dbc3 |
cdg_dealloc(&cdg[i]);
|
|
Packit Service |
54dbc3 |
free(cdg);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
vltable_dealloc(&srcdest2vl_table);
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->srcdest2vl_table = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return err;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* meta function which calls subfunctions for dijkstra, update lft and weights,
|
|
Packit Service |
54dbc3 |
(and remove deadlocks) to calculate the routing for the subnet
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static int dfsssp_do_dijkstra_routing(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr;
|
|
Packit Service |
54dbc3 |
vertex_t *adj_list = (vertex_t *) dfsssp_ctx->adj_list;
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size = dfsssp_ctx->adj_list_size;
|
|
Packit Service |
54dbc3 |
cl_heap_t heap;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
vertex_t **sw_list = NULL;
|
|
Packit Service |
54dbc3 |
uint32_t sw_list_size = 0;
|
|
Packit Service |
54dbc3 |
uint64_t guid = 0;
|
|
Packit Service |
54dbc3 |
cl_qlist_t *qlist = NULL;
|
|
Packit Service |
54dbc3 |
cl_list_item_t *qlist_item = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
|
|
Packit Service |
54dbc3 |
cl_qmap_t cn_tbl, io_tbl, *p_mixed_tbl = NULL;
|
|
Packit Service |
54dbc3 |
cl_map_item_t *item = NULL;
|
|
Packit Service |
54dbc3 |
osm_switch_t *sw = NULL;
|
|
Packit Service |
54dbc3 |
osm_port_t *port = NULL;
|
|
Packit Service |
54dbc3 |
uint32_t i = 0, err = 0;
|
|
Packit Service |
54dbc3 |
uint16_t lid = 0, min_lid_ho = 0, max_lid_ho = 0;
|
|
Packit Service |
54dbc3 |
uint8_t lmc = 0;
|
|
Packit Service |
54dbc3 |
boolean_t cn_nodes_provided = FALSE, io_nodes_provided = FALSE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"Calculating shortest path from all Hca/switches to all\n");
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qmap_init(&cn_tbl);
|
|
Packit Service |
54dbc3 |
cl_qmap_init(&io_tbl);
|
|
Packit Service |
54dbc3 |
p_mixed_tbl = &cn_tbl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
cl_qlist_init(&p_mgr->port_order_list);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* reset the new_lft for each switch */
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *) item;
|
|
Packit Service |
54dbc3 |
/* initialize LIDs in buffer to invalid port number */
|
|
Packit Service |
54dbc3 |
memset(sw->new_lft, OSM_NO_PATH, sw->max_lid_ho + 1);
|
|
Packit Service |
54dbc3 |
/* initialize LFT and hop count for bsp0/esp0 of the switch */
|
|
Packit Service |
54dbc3 |
min_lid_ho = cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0));
|
|
Packit Service |
54dbc3 |
lmc = osm_node_get_lmc(sw->p_node, 0);
|
|
Packit Service |
54dbc3 |
for (i = min_lid_ho; i < min_lid_ho + (1 << lmc); i++) {
|
|
Packit Service |
54dbc3 |
/* for each switch the port to the 'self'lid is the management port 0 */
|
|
Packit Service |
54dbc3 |
sw->new_lft[i] = 0;
|
|
Packit Service |
54dbc3 |
/* the hop count to the 'self'lid is 0 for each switch */
|
|
Packit Service |
54dbc3 |
osm_switch_set_hops(sw, i, 0, 0);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* construct the generic heap opject to use it in dijkstra */
|
|
Packit Service |
54dbc3 |
cl_heap_construct(&heap;;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* we need an intermediate array of pointers to switches in adj_list;
|
|
Packit Service |
54dbc3 |
this array will be sorted in respect to num_hca (descending)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
sw_list_size = adj_list_size - 1;
|
|
Packit Service |
54dbc3 |
sw_list = (vertex_t **)malloc(sw_list_size * sizeof(vertex_t *));
|
|
Packit Service |
54dbc3 |
if (!sw_list) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD29: cannot allocate memory for sw_list in dfsssp_do_dijkstra_routing\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
memset(sw_list, 0, sw_list_size * sizeof(vertex_t *));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* fill the array with references to the 'real' sw in adj_list */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < sw_list_size; i++)
|
|
Packit Service |
54dbc3 |
sw_list[i] = &(adj_list[i + 1]);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* sort the sw_list in descending order */
|
|
Packit Service |
54dbc3 |
sw_list_sort_by_num_hca(sw_list, sw_list_size);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* parse compute node guid file, if provided by the user */
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.cn_guid_file) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Parsing compute nodes from file %s\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.cn_guid_file);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_mgr->p_subn->opt.cn_guid_file,
|
|
Packit Service |
54dbc3 |
add_guid_to_map, &cn_tbl)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD33: Problem parsing compute node guid file\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (cl_is_qmap_empty(&cn_tbl))
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"WRN AD34: compute node guids file contains no valid guids\n");
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
cn_nodes_provided = TRUE;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* parse I/O guid file, if provided by the user */
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.io_guid_file) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Parsing I/O nodes from file %s\n",
|
|
Packit Service |
54dbc3 |
p_mgr->p_subn->opt.io_guid_file);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (parse_node_map(p_mgr->p_subn->opt.io_guid_file,
|
|
Packit Service |
54dbc3 |
add_guid_to_map, &io_tbl)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD35: Problem parsing I/O guid file\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (cl_is_qmap_empty(&io_tbl))
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"WRN AD36: I/O node guids file contains no valid guids\n");
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
io_nodes_provided = TRUE;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* if we mix Hca/Tca/SP0 during the dijkstra routing, we might end up
|
|
Packit Service |
54dbc3 |
in rare cases with a bad balancing for Hca<->Hca connections, i.e.
|
|
Packit Service |
54dbc3 |
some inter-switch links get oversubscribed with paths;
|
|
Packit Service |
54dbc3 |
therefore: add Hca ports first to ensure good Hca<->Hca balancing
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (cn_nodes_provided) {
|
|
Packit Service |
54dbc3 |
for (i = 0; i < adj_list_size - 1; i++) {
|
|
Packit Service |
54dbc3 |
if (sw_list[i] && sw_list[i]->sw) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *)(sw_list[i]->sw);
|
|
Packit Service |
54dbc3 |
add_sw_endports_to_order_list(sw, p_mgr,
|
|
Packit Service |
54dbc3 |
&cn_tbl, TRUE);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD30: corrupted sw_list array in dfsssp_do_dijkstra_routing\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* then: add Tca ports to ensure good Hca->Tca balancing and separate
|
|
Packit Service |
54dbc3 |
paths towards I/O nodes on the same switch (if possible)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (io_nodes_provided) {
|
|
Packit Service |
54dbc3 |
for (i = 0; i < adj_list_size - 1; i++) {
|
|
Packit Service |
54dbc3 |
if (sw_list[i] && sw_list[i]->sw) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *)(sw_list[i]->sw);
|
|
Packit Service |
54dbc3 |
add_sw_endports_to_order_list(sw, p_mgr,
|
|
Packit Service |
54dbc3 |
&io_tbl, TRUE);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD32: corrupted sw_list array in dfsssp_do_dijkstra_routing\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* then: add anything else, such as administration nodes, ... */
|
|
Packit Service |
54dbc3 |
if (cn_nodes_provided && io_nodes_provided) {
|
|
Packit Service |
54dbc3 |
cl_qmap_merge(&cn_tbl, &io_tbl);
|
|
Packit Service |
54dbc3 |
} else if (io_nodes_provided) {
|
|
Packit Service |
54dbc3 |
p_mixed_tbl = &io_tbl;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
for (i = 0; i < adj_list_size - 1; i++) {
|
|
Packit Service |
54dbc3 |
if (sw_list[i] && sw_list[i]->sw) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *)(sw_list[i]->sw);
|
|
Packit Service |
54dbc3 |
add_sw_endports_to_order_list(sw, p_mgr, p_mixed_tbl,
|
|
Packit Service |
54dbc3 |
FALSE);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD39: corrupted sw_list array in dfsssp_do_dijkstra_routing\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
/* last: add SP0 afterwards which have lower priority for balancing */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < sw_list_size; i++) {
|
|
Packit Service |
54dbc3 |
if (sw_list[i] && sw_list[i]->sw) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *)(sw_list[i]->sw);
|
|
Packit Service |
54dbc3 |
guid = cl_ntoh64(osm_node_get_node_guid(sw->p_node));
|
|
Packit Service |
54dbc3 |
add_guid_to_order_list(guid, p_mgr);
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD31: corrupted sw_list array in dfsssp_do_dijkstra_routing\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* the intermediate array lived long enough */
|
|
Packit Service |
54dbc3 |
free(sw_list);
|
|
Packit Service |
54dbc3 |
sw_list = NULL;
|
|
Packit Service |
54dbc3 |
/* same is true for the compute node and I/O guid map */
|
|
Packit Service |
54dbc3 |
destroy_guid_map(&cn_tbl);
|
|
Packit Service |
54dbc3 |
cn_nodes_provided = FALSE;
|
|
Packit Service |
54dbc3 |
destroy_guid_map(&io_tbl);
|
|
Packit Service |
54dbc3 |
io_nodes_provided = FALSE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* do the routing for the each Hca in the subnet and each switch
|
|
Packit Service |
54dbc3 |
in the subnet (to add the routes to base/enhanced SP0)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
qlist = &p_mgr->port_order_list;
|
|
Packit Service |
54dbc3 |
for (qlist_item = cl_qlist_head(qlist);
|
|
Packit Service |
54dbc3 |
qlist_item != cl_qlist_end(qlist);
|
|
Packit Service |
54dbc3 |
qlist_item = cl_qlist_next(qlist_item)) {
|
|
Packit Service |
54dbc3 |
port = (osm_port_t *)cl_item_obj(qlist_item, port, list_item);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* calculate shortest path with dijkstra from node to all switches/Hca */
|
|
Packit Service |
54dbc3 |
if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_CA) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Processing Hca with GUID 0x%" PRIx64 "\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid
|
|
Packit Service |
54dbc3 |
(port->p_node)));
|
|
Packit Service |
54dbc3 |
} else if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_SWITCH) {
|
|
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
|
|
Packit Service |
54dbc3 |
(port->p_node)));
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* we don't handle routers, in case they show up */
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* distribute the LID range across the ports that can reach those LIDs
|
|
Packit Service |
54dbc3 |
to have disjoint paths for one destination port with lmc>0;
|
|
Packit Service |
54dbc3 |
for switches with bsp0: min=max; with esp0: max>min if lmc>0
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
osm_port_get_lid_range_ho(port, &min_lid_ho,
|
|
Packit Service |
54dbc3 |
&max_lid_ho);
|
|
Packit Service |
54dbc3 |
for (lid = min_lid_ho; lid <= max_lid_ho; lid++) {
|
|
Packit Service |
54dbc3 |
/* do dijkstra from this Hca/LID/SP0 to each switch */
|
|
Packit Service |
54dbc3 |
err =
|
|
Packit Service |
54dbc3 |
dijkstra(p_mgr, &heap, adj_list, adj_list_size,
|
|
Packit Service |
54dbc3 |
port, lid);
|
|
Packit Service |
54dbc3 |
if (err)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG))
|
|
Packit Service |
54dbc3 |
print_routes(p_mgr, adj_list, adj_list_size,
|
|
Packit Service |
54dbc3 |
port);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* make an update for the linear forwarding tables of the switches */
|
|
Packit Service |
54dbc3 |
err =
|
|
Packit Service |
54dbc3 |
update_lft(p_mgr, adj_list, adj_list_size, port, lid);
|
|
Packit Service |
54dbc3 |
if (err)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* add weights for calculated routes to adjust the weights for the next cycle */
|
|
Packit Service |
54dbc3 |
update_weights(p_mgr, adj_list, adj_list_size);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG))
|
|
Packit Service |
54dbc3 |
dfsssp_print_graph(p_mgr, adj_list,
|
|
Packit Service |
54dbc3 |
adj_list_size);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* try deadlock removal only for the dfsssp routing (not for the sssp case, which is a subset of the dfsssp algorithm) */
|
|
Packit Service |
54dbc3 |
if (dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_DFSSSP) {
|
|
Packit Service |
54dbc3 |
/* remove potential deadlocks by assigning different virtual lanes to src/dest paths and balance the lanes */
|
|
Packit Service |
54dbc3 |
err = dfsssp_remove_deadlocks(dfsssp_ctx);
|
|
Packit Service |
54dbc3 |
if (err)
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
} else if (dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_SSSP) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_INFO,
|
|
Packit Service |
54dbc3 |
"SSSP routing specified -> skipping deadlock removal thru dfsssp_remove_deadlocks(...)\n");
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD28: wrong routing engine specified in dfsssp_ctx\n");
|
|
Packit Service |
54dbc3 |
goto ERROR;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* list not needed after the dijkstra steps and deadlock removal */
|
|
Packit Service |
54dbc3 |
cl_qlist_remove_all(&p_mgr->port_order_list);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* delete the heap which is not needed anymore */
|
|
Packit Service |
54dbc3 |
cl_heap_destroy(&heap;;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* print the new_lft for each switch after routing is done */
|
|
Packit Service |
54dbc3 |
if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) {
|
|
Packit Service |
54dbc3 |
for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl);
|
|
Packit Service |
54dbc3 |
item = cl_qmap_next(item)) {
|
|
Packit Service |
54dbc3 |
sw = (osm_switch_t *) item;
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
"Summary of the (new) LFT for switch 0x%" PRIx64
|
|
Packit Service |
54dbc3 |
" (%s):\n",
|
|
Packit Service |
54dbc3 |
cl_ntoh64(osm_node_get_node_guid(sw->p_node)),
|
|
Packit Service |
54dbc3 |
sw->p_node->print_desc);
|
|
Packit Service |
54dbc3 |
for (i = 0; i < sw->max_lid_ho + 1; i++)
|
|
Packit Service |
54dbc3 |
if (sw->new_lft[i] != OSM_NO_PATH) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
|
|
Packit Service |
54dbc3 |
" for LID=%" PRIu32
|
|
Packit Service |
54dbc3 |
" use port=%" PRIu8 "\n", i,
|
|
Packit Service |
54dbc3 |
sw->new_lft[i]);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(p_mgr->p_log);
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
ERROR:
|
|
Packit Service |
54dbc3 |
if (!cl_is_qlist_empty(&p_mgr->port_order_list))
|
|
Packit Service |
54dbc3 |
cl_qlist_remove_all(&p_mgr->port_order_list);
|
|
Packit Service |
54dbc3 |
if (cn_nodes_provided)
|
|
Packit Service |
54dbc3 |
destroy_guid_map(&cn_tbl);
|
|
Packit Service |
54dbc3 |
if (io_nodes_provided)
|
|
Packit Service |
54dbc3 |
destroy_guid_map(&io_tbl);
|
|
Packit Service |
54dbc3 |
if (sw_list)
|
|
Packit Service |
54dbc3 |
free(sw_list);
|
|
Packit Service |
54dbc3 |
if (cl_is_heap_inited(&heap))
|
|
Packit Service |
54dbc3 |
cl_heap_destroy(&heap;;
|
|
Packit Service |
54dbc3 |
return -1;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* meta function which calls subfunctions for finding the optimal switch
|
|
Packit Service |
54dbc3 |
for the spanning tree, performing a dijkstra step with this sw as root,
|
|
Packit Service |
54dbc3 |
and calculating the mcast table for MLID
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static ib_api_status_t dfsssp_do_mcast_routing(void * context,
|
|
Packit Service |
54dbc3 |
osm_mgrp_box_t * mbox)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr;
|
|
Packit Service |
54dbc3 |
osm_sm_t *sm = (osm_sm_t *) p_mgr->sm;
|
|
Packit Service |
54dbc3 |
vertex_t *adj_list = (vertex_t *) dfsssp_ctx->adj_list;
|
|
Packit Service |
54dbc3 |
uint32_t adj_list_size = dfsssp_ctx->adj_list_size;
|
|
Packit Service |
54dbc3 |
cl_qlist_t mcastgrp_port_list;
|
|
Packit Service |
54dbc3 |
cl_qmap_t mcastgrp_port_map;
|
|
Packit Service |
54dbc3 |
osm_switch_t *root_sw = NULL, *p_sw = NULL;
|
|
Packit Service |
54dbc3 |
osm_port_t *port = NULL;
|
|
Packit Service |
54dbc3 |
ib_net16_t lid = 0;
|
|
Packit Service |
54dbc3 |
uint32_t err = 0, num_ports = 0, i = 0;
|
|
Packit Service |
54dbc3 |
ib_net64_t guid = 0;
|
|
Packit Service |
54dbc3 |
ib_api_status_t status = IB_SUCCESS;
|
|
Packit Service |
54dbc3 |
cl_heap_t heap;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
OSM_LOG_ENTER(sm->p_log);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* using the ucast cache feature with dfsssp might mean that a leaf sw
|
|
Packit Service |
54dbc3 |
got removed (and got back) without calling dfsssp_build_graph
|
|
Packit Service |
54dbc3 |
and therefore the adj_list (and pointers to osm's internal switches)
|
|
Packit Service |
54dbc3 |
could be outdated (here we have no knowledge if it has happened, so
|
|
Packit Service |
54dbc3 |
unfortunately a check is necessary... still better than rebuilding
|
|
Packit Service |
54dbc3 |
adj_list every time we arrive here)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (p_mgr->p_subn->opt.use_ucast_cache && p_mgr->cache_valid) {
|
|
Packit Service |
54dbc3 |
for (i = 1; i < adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
guid = cl_hton64(adj_list[i].guid);
|
|
Packit Service |
54dbc3 |
p_sw = osm_get_switch_by_guid(p_mgr->p_subn, guid);
|
|
Packit Service |
54dbc3 |
if (p_sw) {
|
|
Packit Service |
54dbc3 |
/* check if switch came back from the dead */
|
|
Packit Service |
54dbc3 |
if (adj_list[i].dropped)
|
|
Packit Service |
54dbc3 |
adj_list[i].dropped = FALSE;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* verify that sw object has not been moved
|
|
Packit Service |
54dbc3 |
(this can happen for a leaf switch, if it
|
|
Packit Service |
54dbc3 |
was dropped and came back later without a
|
|
Packit Service |
54dbc3 |
rerouting), otherwise we have to update
|
|
Packit Service |
54dbc3 |
dfsssp's internal switch list with the new
|
|
Packit Service |
54dbc3 |
sw pointer
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (p_sw == adj_list[i].sw)
|
|
Packit Service |
54dbc3 |
continue;
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
adj_list[i].sw = p_sw;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
/* if a switch from adj_list is not in the
|
|
Packit Service |
54dbc3 |
sw_guid_tbl anymore, then the only reason is
|
|
Packit Service |
54dbc3 |
that it was a leaf switch and opensm dropped
|
|
Packit Service |
54dbc3 |
it without calling a rerouting
|
|
Packit Service |
54dbc3 |
-> calling dijkstra is no problem, since it
|
|
Packit Service |
54dbc3 |
is a leaf and different from root_sw
|
|
Packit Service |
54dbc3 |
-> only update_mcft and reset_mgrp_membership
|
|
Packit Service |
54dbc3 |
need to be aware of these dropped switches
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (!adj_list[i].dropped)
|
|
Packit Service |
54dbc3 |
adj_list[i].dropped = TRUE;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* construct the generic heap opject to use it in dijkstra */
|
|
Packit Service |
54dbc3 |
cl_heap_construct(&heap;;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* create a map and a list of all ports which are member in the mcast
|
|
Packit Service |
54dbc3 |
group; map for searching elements and list for iteration
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (osm_mcast_make_port_list_and_map(&mcastgrp_port_list,
|
|
Packit Service |
54dbc3 |
&mcastgrp_port_map, mbox)) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD50: "
|
|
Packit Service |
54dbc3 |
"Insufficient memory to make port list\n");
|
|
Packit Service |
54dbc3 |
status = IB_ERROR;
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
num_ports = cl_qlist_count(&mcastgrp_port_list);
|
|
Packit Service |
54dbc3 |
if (num_ports < 2) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
|
|
Packit Service |
54dbc3 |
"MLID 0x%X has %u members - nothing to do\n",
|
|
Packit Service |
54dbc3 |
mbox->mlid, num_ports);
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* find the root switch for the spanning tree, which has the smallest
|
|
Packit Service |
54dbc3 |
hops count to all LIDs in the mcast group
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
root_sw = osm_mcast_mgr_find_root_switch(sm, &mcastgrp_port_list);
|
|
Packit Service |
54dbc3 |
if (!root_sw) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD51: "
|
|
Packit Service |
54dbc3 |
"Unable to locate a suitable switch for group 0x%X\n",
|
|
Packit Service |
54dbc3 |
mbox->mlid);
|
|
Packit Service |
54dbc3 |
status = IB_ERROR;
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* a) start one dijkstra step from the root switch to generate a
|
|
Packit Service |
54dbc3 |
spanning tree
|
|
Packit Service |
54dbc3 |
b) this might be a bit of an overkill to span the whole
|
|
Packit Service |
54dbc3 |
network, if there are only a few ports in the mcast group, but
|
|
Packit Service |
54dbc3 |
its only one dijkstra step for each mcast group and we did many
|
|
Packit Service |
54dbc3 |
steps before in the ucast routing for each LID in the subnet;
|
|
Packit Service |
54dbc3 |
c) we can use the subnet structure from the ucast routing, and
|
|
Packit Service |
54dbc3 |
don't even have to reset the link weights (=> therefore the mcast
|
|
Packit Service |
54dbc3 |
spanning tree will use less 'growded' links in the network)
|
|
Packit Service |
54dbc3 |
d) the mcast dfsssp algorithm will not change the link weights
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
lid = osm_node_get_base_lid(root_sw->p_node, 0);
|
|
Packit Service |
54dbc3 |
port = osm_get_port_by_lid(sm->p_subn, lid);
|
|
Packit Service |
54dbc3 |
err = dijkstra(p_mgr, &heap, adj_list, adj_list_size, port, lid);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD52: "
|
|
Packit Service |
54dbc3 |
"Dijkstra step for mcast failed for group 0x%X\n",
|
|
Packit Service |
54dbc3 |
mbox->mlid);
|
|
Packit Service |
54dbc3 |
status = IB_ERROR;
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* set mcast group membership again for update_mcft
|
|
Packit Service |
54dbc3 |
(unfortunately: osm_mcast_mgr_find_root_switch resets it)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
update_mgrp_membership(&mcastgrp_port_list);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* update the mcast forwarding tables of the switches */
|
|
Packit Service |
54dbc3 |
err = update_mcft(sm, adj_list, adj_list_size, mbox->mlid,
|
|
Packit Service |
54dbc3 |
&mcastgrp_port_map, root_sw);
|
|
Packit Service |
54dbc3 |
if (err) {
|
|
Packit Service |
54dbc3 |
OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD53: "
|
|
Packit Service |
54dbc3 |
"Update of mcast forwarding tables failed for group 0x%X\n",
|
|
Packit Service |
54dbc3 |
mbox->mlid);
|
|
Packit Service |
54dbc3 |
status = IB_ERROR;
|
|
Packit Service |
54dbc3 |
goto Exit;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
Exit:
|
|
Packit Service |
54dbc3 |
if (cl_is_heap_inited(&heap))
|
|
Packit Service |
54dbc3 |
cl_heap_destroy(&heap;;
|
|
Packit Service |
54dbc3 |
reset_mgrp_membership(adj_list, adj_list_size);
|
|
Packit Service |
54dbc3 |
osm_mcast_drop_port_list(&mcastgrp_port_list);
|
|
Packit Service |
54dbc3 |
OSM_LOG_EXIT(sm->p_log);
|
|
Packit Service |
54dbc3 |
return status;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* called from extern in QP creation process to gain the the service level and
|
|
Packit Service |
54dbc3 |
the virtual lane respectively for a <s,d> pair
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
static uint8_t get_dfsssp_sl(void *context, uint8_t hint_for_default_sl,
|
|
Packit Service |
54dbc3 |
const ib_net16_t slid, const ib_net16_t dlid)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context;
|
|
Packit Service |
54dbc3 |
osm_port_t *src_port, *dest_port;
|
|
Packit Service |
54dbc3 |
vltable_t *srcdest2vl_table = NULL;
|
|
Packit Service |
54dbc3 |
uint8_t *vl_split_count = NULL;
|
|
Packit Service |
54dbc3 |
osm_ucast_mgr_t *p_mgr = NULL;
|
|
Packit Service |
54dbc3 |
int32_t res = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (dfsssp_ctx
|
|
Packit Service |
54dbc3 |
&& dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_DFSSSP) {
|
|
Packit Service |
54dbc3 |
p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr;
|
|
Packit Service |
54dbc3 |
srcdest2vl_table = (vltable_t *) (dfsssp_ctx->srcdest2vl_table);
|
|
Packit Service |
54dbc3 |
vl_split_count = (uint8_t *) (dfsssp_ctx->vl_split_count);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return hint_for_default_sl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
src_port = osm_get_port_by_lid(p_mgr->p_subn, slid);
|
|
Packit Service |
54dbc3 |
if (!src_port)
|
|
Packit Service |
54dbc3 |
return hint_for_default_sl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
dest_port = osm_get_port_by_lid(p_mgr->p_subn, dlid);
|
|
Packit Service |
54dbc3 |
if (!dest_port)
|
|
Packit Service |
54dbc3 |
return hint_for_default_sl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (!srcdest2vl_table)
|
|
Packit Service |
54dbc3 |
return hint_for_default_sl;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
res = vltable_get_vl(srcdest2vl_table, slid, dlid);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* we will randomly distribute the traffic over multiple VLs if
|
|
Packit Service |
54dbc3 |
necessary for good balancing; therefore vl_split_count provides
|
|
Packit Service |
54dbc3 |
the number of VLs to use for certain traffic
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
if (res > -1) {
|
|
Packit Service |
54dbc3 |
if (vl_split_count[res] > 1)
|
|
Packit Service |
54dbc3 |
return (uint8_t) (res + rand()%(vl_split_count[res]));
|
|
Packit Service |
54dbc3 |
else
|
|
Packit Service |
54dbc3 |
return (uint8_t) res;
|
|
Packit Service |
54dbc3 |
} else
|
|
Packit Service |
54dbc3 |
return hint_for_default_sl;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static dfsssp_context_t *dfsssp_context_create(osm_opensm_t * p_osm,
|
|
Packit Service |
54dbc3 |
osm_routing_engine_type_t
|
|
Packit Service |
54dbc3 |
routing_type)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* allocate memory */
|
|
Packit Service |
54dbc3 |
dfsssp_ctx = (dfsssp_context_t *) malloc(sizeof(dfsssp_context_t));
|
|
Packit Service |
54dbc3 |
if (dfsssp_ctx) {
|
|
Packit Service |
54dbc3 |
/* set initial values */
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->routing_type = routing_type;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->p_mgr = (osm_ucast_mgr_t *) & (p_osm->sm.ucast_mgr);
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list = NULL;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list_size = 0;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->srcdest2vl_table = NULL;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->vl_split_count = NULL;
|
|
Packit Service |
54dbc3 |
} else {
|
|
Packit Service |
54dbc3 |
OSM_LOG(p_osm->sm.ucast_mgr.p_log, OSM_LOG_ERROR,
|
|
Packit Service |
54dbc3 |
"ERR AD04: cannot allocate memory for dfsssp_ctx in dfsssp_context_create\n");
|
|
Packit Service |
54dbc3 |
return NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return dfsssp_ctx;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void dfsssp_context_destroy(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context;
|
|
Packit Service |
54dbc3 |
vertex_t *adj_list = (vertex_t *) (dfsssp_ctx->adj_list);
|
|
Packit Service |
54dbc3 |
uint32_t i = 0;
|
|
Packit Service |
54dbc3 |
link_t *link = NULL, *tmp = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* free adj_list */
|
|
Packit Service |
54dbc3 |
for (i = 0; i < dfsssp_ctx->adj_list_size; i++) {
|
|
Packit Service |
54dbc3 |
link = adj_list[i].links;
|
|
Packit Service |
54dbc3 |
while (link) {
|
|
Packit Service |
54dbc3 |
tmp = link;
|
|
Packit Service |
54dbc3 |
link = link->next;
|
|
Packit Service |
54dbc3 |
free(tmp);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
free(adj_list);
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list = NULL;
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->adj_list_size = 0;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* free srcdest2vl table and the split count information table
|
|
Packit Service |
54dbc3 |
(can be done, because dfsssp_context_destroy is called after
|
|
Packit Service |
54dbc3 |
osm_get_dfsssp_sl)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
vltable_dealloc(&(dfsssp_ctx->srcdest2vl_table));
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->srcdest2vl_table = NULL;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
if (dfsssp_ctx->vl_split_count) {
|
|
Packit Service |
54dbc3 |
free(dfsssp_ctx->vl_split_count);
|
|
Packit Service |
54dbc3 |
dfsssp_ctx->vl_split_count = NULL;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
static void delete(void *context)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
if (!context)
|
|
Packit Service |
54dbc3 |
return;
|
|
Packit Service |
54dbc3 |
dfsssp_context_destroy(context);
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
free(context);
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_dfsssp_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
/* create context container and add ucast management object */
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_context =
|
|
Packit Service |
54dbc3 |
dfsssp_context_create(p_osm, OSM_ROUTING_ENGINE_TYPE_DFSSSP);
|
|
Packit Service |
54dbc3 |
if (!dfsssp_context) {
|
|
Packit Service |
54dbc3 |
return 1; /* alloc failed -> skip this routing */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* reset function pointers to dfsssp routines */
|
|
Packit Service |
54dbc3 |
r->context = (void *)dfsssp_context;
|
|
Packit Service |
54dbc3 |
r->build_lid_matrices = dfsssp_build_graph;
|
|
Packit Service |
54dbc3 |
r->ucast_build_fwd_tables = dfsssp_do_dijkstra_routing;
|
|
Packit Service |
54dbc3 |
r->mcast_build_stree = dfsssp_do_mcast_routing;
|
|
Packit Service |
54dbc3 |
r->path_sl = get_dfsssp_sl;
|
|
Packit Service |
54dbc3 |
r->destroy = delete;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* we initialize with the current time to achieve a 'good' randomized
|
|
Packit Service |
54dbc3 |
assignment in get_dfsssp_sl(...)
|
|
Packit Service |
54dbc3 |
*/
|
|
Packit Service |
54dbc3 |
srand(time(NULL));
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
int osm_ucast_sssp_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm)
|
|
Packit Service |
54dbc3 |
{
|
|
Packit Service |
54dbc3 |
/* create context container and add ucast management object */
|
|
Packit Service |
54dbc3 |
dfsssp_context_t *dfsssp_context =
|
|
Packit Service |
54dbc3 |
dfsssp_context_create(p_osm, OSM_ROUTING_ENGINE_TYPE_SSSP);
|
|
Packit Service |
54dbc3 |
if (!dfsssp_context) {
|
|
Packit Service |
54dbc3 |
return 1; /* alloc failed -> skip this routing */
|
|
Packit Service |
54dbc3 |
}
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
/* reset function pointers to sssp routines */
|
|
Packit Service |
54dbc3 |
r->context = (void *)dfsssp_context;
|
|
Packit Service |
54dbc3 |
r->build_lid_matrices = dfsssp_build_graph;
|
|
Packit Service |
54dbc3 |
r->ucast_build_fwd_tables = dfsssp_do_dijkstra_routing;
|
|
Packit Service |
54dbc3 |
r->mcast_build_stree = dfsssp_do_mcast_routing;
|
|
Packit Service |
54dbc3 |
r->destroy = delete;
|
|
Packit Service |
54dbc3 |
|
|
Packit Service |
54dbc3 |
return 0;
|
|
Packit Service |
54dbc3 |
}
|