|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2007 Simula Research Laboratory. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2007 Silicon Graphics Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2008,2009 System Fabric Works, Inc. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2009 HNR Consulting. All rights reserved.
|
|
Packit |
13e616 |
* Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* This software is available to you under a choice of one of two
|
|
Packit |
13e616 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
13e616 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
13e616 |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
13e616 |
* OpenIB.org BSD license below:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
13e616 |
* without modification, are permitted provided that the following
|
|
Packit |
13e616 |
* conditions are met:
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions of source code must retain the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
13e616 |
* copyright notice, this list of conditions and the following
|
|
Packit |
13e616 |
* disclaimer in the documentation and/or other materials
|
|
Packit |
13e616 |
* provided with the distribution.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
13e616 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
13e616 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
13e616 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
13e616 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
13e616 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
13e616 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
13e616 |
* SOFTWARE.
|
|
Packit |
13e616 |
*
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* Abstract:
|
|
Packit |
13e616 |
* Implementation of LASH algorithm Calculation functions
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#if HAVE_CONFIG_H
|
|
Packit |
13e616 |
# include <config.h>
|
|
Packit |
13e616 |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
#include <stdlib.h>
|
|
Packit |
13e616 |
#include <stdio.h>
|
|
Packit |
13e616 |
#include <errno.h>
|
|
Packit |
13e616 |
#include <complib/cl_debug.h>
|
|
Packit |
13e616 |
#include <complib/cl_qmap.h>
|
|
Packit |
13e616 |
#include <opensm/osm_file_ids.h>
|
|
Packit |
13e616 |
#define FILE_ID OSM_FILE_UCAST_LASH_C
|
|
Packit |
13e616 |
#include <opensm/osm_switch.h>
|
|
Packit |
13e616 |
#include <opensm/osm_opensm.h>
|
|
Packit |
13e616 |
#include <opensm/osm_log.h>
|
|
Packit |
13e616 |
#include <opensm/osm_mesh.h>
|
|
Packit |
13e616 |
#include <opensm/osm_ucast_lash.h>
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
typedef struct _reachable_dest {
|
|
Packit |
13e616 |
int switch_id;
|
|
Packit |
13e616 |
struct _reachable_dest *next;
|
|
Packit |
13e616 |
} reachable_dest_t;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void connect_switches(lash_t * p_lash, int sw1, int sw2, int phy_port_1)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
unsigned num = p_lash->switches[sw1]->node->num_links;
|
|
Packit |
13e616 |
switch_t *s1 = p_lash->switches[sw1];
|
|
Packit |
13e616 |
mesh_node_t *node = s1->node;
|
|
Packit |
13e616 |
switch_t *s2;
|
|
Packit |
13e616 |
link_t *l;
|
|
Packit |
13e616 |
unsigned int i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* if doing mesh analysis:
|
|
Packit |
13e616 |
* - do not consider connections to self
|
|
Packit |
13e616 |
* - collapse multiple connections between
|
|
Packit |
13e616 |
* pair of switches to a single locical link
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (p_lash->p_osm->subn.opt.do_mesh_analysis) {
|
|
Packit |
13e616 |
if (sw1 == sw2)
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* see if we are already linked to sw2 */
|
|
Packit |
13e616 |
for (i = 0; i < num; i++) {
|
|
Packit |
13e616 |
l = node->links[i];
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (node->links[i]->switch_id == sw2) {
|
|
Packit |
13e616 |
l->ports[l->num_ports++] = phy_port_1;
|
|
Packit |
13e616 |
return;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
l = node->links[num];
|
|
Packit |
13e616 |
l->switch_id = sw2;
|
|
Packit |
13e616 |
l->link_id = -1;
|
|
Packit |
13e616 |
l->ports[l->num_ports++] = phy_port_1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
s2 = p_lash->switches[sw2];
|
|
Packit |
13e616 |
for (i = 0; i < s2->node->num_links; i++) {
|
|
Packit |
13e616 |
if (s2->node->links[i]->switch_id == sw1) {
|
|
Packit |
13e616 |
s2->node->links[i]->link_id = num;
|
|
Packit |
13e616 |
l->link_id = i;
|
|
Packit |
13e616 |
break;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
node->num_links++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LASH connect: %d, %d, %d\n", sw1, sw2, phy_port_1);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static osm_switch_t *get_osm_switch_from_port(const osm_port_t * port)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_physp_t *p = port->p_physp;
|
|
Packit |
13e616 |
if (p->p_node->sw)
|
|
Packit |
13e616 |
return p->p_node->sw;
|
|
Packit |
13e616 |
else if (p->p_remote_physp && p->p_remote_physp->p_node->sw)
|
|
Packit |
13e616 |
return p->p_remote_physp->p_node->sw;
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int cycle_exists(cdg_vertex_t * start, cdg_vertex_t * current,
|
|
Packit |
13e616 |
cdg_vertex_t * prev, int visit_num)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
int i, new_visit_num;
|
|
Packit |
13e616 |
int cycle_found = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (current != NULL && current->visiting_number > 0) {
|
|
Packit |
13e616 |
if (visit_num > current->visiting_number && current->seen == 0) {
|
|
Packit |
13e616 |
cycle_found = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
if (current == NULL) {
|
|
Packit |
13e616 |
current = start;
|
|
Packit |
13e616 |
CL_ASSERT(prev == NULL);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
current->visiting_number = visit_num;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (prev != NULL) {
|
|
Packit |
13e616 |
prev->next = current;
|
|
Packit |
13e616 |
CL_ASSERT(prev->to == current->from);
|
|
Packit |
13e616 |
CL_ASSERT(prev->visiting_number > 0);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
new_visit_num = visit_num + 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < current->num_deps; i++) {
|
|
Packit |
13e616 |
cycle_found =
|
|
Packit |
13e616 |
cycle_exists(start, current->deps[i].v, current,
|
|
Packit |
13e616 |
new_visit_num);
|
|
Packit |
13e616 |
if (cycle_found == 1)
|
|
Packit |
13e616 |
i = current->num_deps;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
current->seen = 1;
|
|
Packit |
13e616 |
if (prev != NULL)
|
|
Packit |
13e616 |
prev->next = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return cycle_found;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static inline int get_next_switch(lash_t *p_lash, int sw, int link)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
return p_lash->switches[sw]->node->links[link]->switch_id;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void remove_semipermanent_depend_for_sp(lash_t * p_lash, int sw,
|
|
Packit |
13e616 |
int dest_switch, int lane)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches;
|
|
Packit |
13e616 |
cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
|
|
Packit |
13e616 |
int i_next_switch, output_link, i, next_link, i_next_next_switch,
|
|
Packit |
13e616 |
depend = 0;
|
|
Packit |
13e616 |
cdg_vertex_t *v;
|
|
Packit |
13e616 |
int __attribute__((unused)) found;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
i_next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (sw != dest_switch) {
|
|
Packit |
13e616 |
v = cdg_vertex_matrix[lane][sw][i_next_switch];
|
|
Packit |
13e616 |
CL_ASSERT(v != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (v->num_using_vertex == 1) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cdg_vertex_matrix[lane][sw][i_next_switch] = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
free(v);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
v->num_using_vertex--;
|
|
Packit |
13e616 |
if (i_next_switch != dest_switch) {
|
|
Packit |
13e616 |
next_link =
|
|
Packit |
13e616 |
switches[i_next_switch]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
i_next_next_switch = get_next_switch(p_lash, i_next_switch, next_link);
|
|
Packit |
13e616 |
found = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < v->num_deps; i++)
|
|
Packit |
13e616 |
if (v->deps[i].v ==
|
|
Packit |
13e616 |
cdg_vertex_matrix[lane][i_next_switch]
|
|
Packit |
13e616 |
[i_next_next_switch]) {
|
|
Packit |
13e616 |
found = 1;
|
|
Packit |
13e616 |
depend = i;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(found);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (v->deps[depend].num_used == 1) {
|
|
Packit |
13e616 |
for (i = depend;
|
|
Packit |
13e616 |
i < v->num_deps - 1; i++) {
|
|
Packit |
13e616 |
v->deps[i].v = v->deps[i + 1].v;
|
|
Packit |
13e616 |
v->deps[i].num_used =
|
|
Packit |
13e616 |
v->deps[i + 1].num_used;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
v->num_deps--;
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
v->deps[depend].num_used--;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw = i_next_switch;
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sw != dest_switch)
|
|
Packit |
13e616 |
i_next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
inline static void enqueue(cl_list_t * bfsq, switch_t * sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
CL_ASSERT(sw->q_state == UNQUEUED);
|
|
Packit |
13e616 |
sw->q_state = Q_MEMBER;
|
|
Packit |
13e616 |
cl_list_insert_tail(bfsq, sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
inline static void dequeue(cl_list_t * bfsq, switch_t ** sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
*sw = (switch_t *) cl_list_remove_head(bfsq);
|
|
Packit |
13e616 |
CL_ASSERT((*sw)->q_state == Q_MEMBER);
|
|
Packit |
13e616 |
(*sw)->q_state = MST_MEMBER;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int get_phys_connection(switch_t *sw, int switch_to)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned int i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < sw->node->num_links; i++)
|
|
Packit |
13e616 |
if (sw->node->links[i]->switch_id == switch_to)
|
|
Packit |
13e616 |
return i;
|
|
Packit |
13e616 |
return i;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void shortest_path(lash_t * p_lash, int ir)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches, *sw, *swi;
|
|
Packit |
13e616 |
unsigned int i;
|
|
Packit |
13e616 |
cl_list_t bfsq;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_construct(&bfsq);
|
|
Packit |
13e616 |
cl_list_init(&bfsq, 20);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
enqueue(&bfsq, switches[ir]);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (!cl_is_list_empty(&bfsq)) {
|
|
Packit |
13e616 |
dequeue(&bfsq, &sw);
|
|
Packit |
13e616 |
for (i = 0; i < sw->node->num_links; i++) {
|
|
Packit |
13e616 |
swi = switches[sw->node->links[i]->switch_id];
|
|
Packit |
13e616 |
if (swi->q_state == UNQUEUED) {
|
|
Packit |
13e616 |
enqueue(&bfsq, swi);
|
|
Packit |
13e616 |
sw->dij_channels[sw->used_channels++] = swi->id;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cl_list_destroy(&bfsq);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int generate_routing_func_for_mst(lash_t * p_lash, int sw_id,
|
|
Packit |
13e616 |
reachable_dest_t ** destinations)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
int i, next_switch;
|
|
Packit |
13e616 |
switch_t *sw = p_lash->switches[sw_id];
|
|
Packit |
13e616 |
int num_channels = sw->used_channels;
|
|
Packit |
13e616 |
reachable_dest_t *dest, *i_dest, *concat_dest = NULL, *prev;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_channels; i++) {
|
|
Packit |
13e616 |
next_switch = sw->dij_channels[i];
|
|
Packit |
13e616 |
if (generate_routing_func_for_mst(p_lash, next_switch, &dest))
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
i_dest = dest;
|
|
Packit |
13e616 |
prev = i_dest;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (i_dest != NULL) {
|
|
Packit |
13e616 |
if (sw->routing_table[i_dest->switch_id].out_link ==
|
|
Packit |
13e616 |
NONE)
|
|
Packit |
13e616 |
sw->routing_table[i_dest->switch_id].out_link =
|
|
Packit |
13e616 |
get_phys_connection(sw, next_switch);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
prev = i_dest;
|
|
Packit |
13e616 |
i_dest = i_dest->next;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(prev->next == NULL);
|
|
Packit |
13e616 |
prev->next = concat_dest;
|
|
Packit |
13e616 |
concat_dest = dest;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
i_dest = (reachable_dest_t *) malloc(sizeof(reachable_dest_t));
|
|
Packit |
13e616 |
if (!i_dest)
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
i_dest->switch_id = sw->id;
|
|
Packit |
13e616 |
i_dest->next = concat_dest;
|
|
Packit |
13e616 |
*destinations = i_dest;
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int generate_cdg_for_sp(lash_t * p_lash, int sw, int dest_switch,
|
|
Packit |
13e616 |
int lane)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches;
|
|
Packit |
13e616 |
cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
|
|
Packit |
13e616 |
int next_switch, output_link, j, exists;
|
|
Packit |
13e616 |
cdg_vertex_t *v, *prev = NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (sw != dest_switch) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cdg_vertex_matrix[lane][sw][next_switch] == NULL) {
|
|
Packit |
13e616 |
v = calloc(1, sizeof(*v) + (num_switches - 1) * sizeof(v->deps[0]));
|
|
Packit |
13e616 |
if (!v)
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
v->from = sw;
|
|
Packit |
13e616 |
v->to = next_switch;
|
|
Packit |
13e616 |
v->temp = 1;
|
|
Packit |
13e616 |
cdg_vertex_matrix[lane][sw][next_switch] = v;
|
|
Packit |
13e616 |
} else
|
|
Packit |
13e616 |
v = cdg_vertex_matrix[lane][sw][next_switch];
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
v->num_using_vertex++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (prev != NULL) {
|
|
Packit |
13e616 |
exists = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (j = 0; j < prev->num_deps; j++)
|
|
Packit |
13e616 |
if (prev->deps[j].v == v) {
|
|
Packit |
13e616 |
exists = 1;
|
|
Packit |
13e616 |
prev->deps[j].num_used++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (exists == 0) {
|
|
Packit |
13e616 |
prev->deps[prev->num_deps].v = v;
|
|
Packit |
13e616 |
prev->deps[prev->num_deps].num_used++;
|
|
Packit |
13e616 |
prev->num_deps++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(prev->num_deps < (int)num_switches);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (prev->temp == 0)
|
|
Packit |
13e616 |
prev->num_temp_depend++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw = next_switch;
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sw != dest_switch) {
|
|
Packit |
13e616 |
CL_ASSERT(output_link != NONE);
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
prev = v;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void set_temp_depend_to_permanent_for_sp(lash_t * p_lash, int sw,
|
|
Packit |
13e616 |
int dest_switch, int lane)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches;
|
|
Packit |
13e616 |
cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
|
|
Packit |
13e616 |
int next_switch, output_link;
|
|
Packit |
13e616 |
cdg_vertex_t *v;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (sw != dest_switch) {
|
|
Packit |
13e616 |
v = cdg_vertex_matrix[lane][sw][next_switch];
|
|
Packit |
13e616 |
CL_ASSERT(v != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (v->temp == 1)
|
|
Packit |
13e616 |
v->temp = 0;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
v->num_temp_depend = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw = next_switch;
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sw != dest_switch)
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void remove_temp_depend_for_sp(lash_t * p_lash, int sw, int dest_switch,
|
|
Packit |
13e616 |
int lane)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches;
|
|
Packit |
13e616 |
cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
|
|
Packit |
13e616 |
int next_switch, output_link, i;
|
|
Packit |
13e616 |
cdg_vertex_t *v;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (sw != dest_switch) {
|
|
Packit |
13e616 |
v = cdg_vertex_matrix[lane][sw][next_switch];
|
|
Packit |
13e616 |
CL_ASSERT(v != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (v->temp == 1) {
|
|
Packit |
13e616 |
cdg_vertex_matrix[lane][sw][next_switch] = NULL;
|
|
Packit |
13e616 |
free(v);
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
CL_ASSERT(v->num_temp_depend <= v->num_deps);
|
|
Packit |
13e616 |
v->num_deps = v->num_deps - v->num_temp_depend;
|
|
Packit |
13e616 |
v->num_temp_depend = 0;
|
|
Packit |
13e616 |
v->num_using_vertex--;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = v->num_deps; i < p_lash->num_switches - 1; i++)
|
|
Packit |
13e616 |
v->deps[i].num_used = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw = next_switch;
|
|
Packit |
13e616 |
output_link = switches[sw]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (sw != dest_switch)
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, sw, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int balance_virtual_lanes(lash_t * p_lash, unsigned lanes_needed)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix;
|
|
Packit |
13e616 |
int *num_mst_in_lane = p_lash->num_mst_in_lane;
|
|
Packit |
13e616 |
int ***virtual_location = p_lash->virtual_location;
|
|
Packit |
13e616 |
int min_filled_lane, max_filled_lane, trials;
|
|
Packit |
13e616 |
int old_min_filled_lane, old_max_filled_lane, new_num_min_lane,
|
|
Packit |
13e616 |
new_num_max_lane;
|
|
Packit |
13e616 |
unsigned int i, j;
|
|
Packit |
13e616 |
int src, dest, start, next_switch, output_link;
|
|
Packit |
13e616 |
int next_switch2, output_link2;
|
|
Packit |
13e616 |
int stop = 0, cycle_found;
|
|
Packit |
13e616 |
int cycle_found2;
|
|
Packit |
13e616 |
unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
max_filled_lane = 0;
|
|
Packit |
13e616 |
min_filled_lane = lanes_needed - 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
trials = num_mst_in_lane[max_filled_lane];
|
|
Packit |
13e616 |
if (lanes_needed == 1)
|
|
Packit |
13e616 |
stop = 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (stop == 0) {
|
|
Packit |
13e616 |
src = abs(rand()) % (num_switches);
|
|
Packit |
13e616 |
dest = abs(rand()) % (num_switches);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (virtual_location[src][dest][max_filled_lane] != 1) {
|
|
Packit |
13e616 |
start = dest;
|
|
Packit |
13e616 |
if (dest == num_switches - 1)
|
|
Packit |
13e616 |
dest = 0;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
dest++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
while (dest != start
|
|
Packit |
13e616 |
&& virtual_location[src][dest][max_filled_lane]
|
|
Packit |
13e616 |
!= 1) {
|
|
Packit |
13e616 |
if (dest == num_switches - 1)
|
|
Packit |
13e616 |
dest = 0;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
dest++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (virtual_location[src][dest][max_filled_lane] != 1) {
|
|
Packit |
13e616 |
if (src == num_switches - 1)
|
|
Packit |
13e616 |
src = 0;
|
|
Packit |
13e616 |
else
|
|
Packit |
13e616 |
src++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (generate_cdg_for_sp(p_lash, src, dest, min_filled_lane) ||
|
|
Packit |
13e616 |
generate_cdg_for_sp(p_lash, dest, src, min_filled_lane))
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link = p_lash->switches[src]->routing_table[dest].out_link;
|
|
Packit |
13e616 |
next_switch = get_next_switch(p_lash, src, output_link);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link2 = p_lash->switches[dest]->routing_table[src].out_link;
|
|
Packit |
13e616 |
next_switch2 = get_next_switch(p_lash, dest, output_link2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(cdg_vertex_matrix[min_filled_lane][src][next_switch] != NULL);
|
|
Packit |
13e616 |
CL_ASSERT(cdg_vertex_matrix[min_filled_lane][dest][next_switch2] != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cycle_found =
|
|
Packit |
13e616 |
cycle_exists(cdg_vertex_matrix[min_filled_lane][src][next_switch], NULL, NULL,
|
|
Packit |
13e616 |
1);
|
|
Packit |
13e616 |
cycle_found2 =
|
|
Packit |
13e616 |
cycle_exists(cdg_vertex_matrix[min_filled_lane][dest][next_switch2], NULL, NULL,
|
|
Packit |
13e616 |
1);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++)
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++)
|
|
Packit |
13e616 |
if (cdg_vertex_matrix[min_filled_lane][i][j] != NULL) {
|
|
Packit |
13e616 |
cdg_vertex_matrix[min_filled_lane][i][j]->visiting_number =
|
|
Packit |
13e616 |
0;
|
|
Packit |
13e616 |
cdg_vertex_matrix[min_filled_lane][i][j]->seen = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cycle_found == 1 || cycle_found2 == 1) {
|
|
Packit |
13e616 |
remove_temp_depend_for_sp(p_lash, src, dest, min_filled_lane);
|
|
Packit |
13e616 |
remove_temp_depend_for_sp(p_lash, dest, src, min_filled_lane);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
virtual_location[src][dest][max_filled_lane] = 2;
|
|
Packit |
13e616 |
virtual_location[dest][src][max_filled_lane] = 2;
|
|
Packit |
13e616 |
trials--;
|
|
Packit |
13e616 |
trials--;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash, src, dest, min_filled_lane);
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash, dest, src, min_filled_lane);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
num_mst_in_lane[max_filled_lane]--;
|
|
Packit |
13e616 |
num_mst_in_lane[max_filled_lane]--;
|
|
Packit |
13e616 |
num_mst_in_lane[min_filled_lane]++;
|
|
Packit |
13e616 |
num_mst_in_lane[min_filled_lane]++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
remove_semipermanent_depend_for_sp(p_lash, src, dest, max_filled_lane);
|
|
Packit |
13e616 |
remove_semipermanent_depend_for_sp(p_lash, dest, src, max_filled_lane);
|
|
Packit |
13e616 |
virtual_location[src][dest][max_filled_lane] = 0;
|
|
Packit |
13e616 |
virtual_location[dest][src][max_filled_lane] = 0;
|
|
Packit |
13e616 |
virtual_location[src][dest][min_filled_lane] = 1;
|
|
Packit |
13e616 |
virtual_location[dest][src][min_filled_lane] = 1;
|
|
Packit |
13e616 |
p_lash->switches[src]->routing_table[dest].lane = min_filled_lane + start_vl;
|
|
Packit |
13e616 |
p_lash->switches[dest]->routing_table[src].lane = min_filled_lane + start_vl;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (trials == 0)
|
|
Packit |
13e616 |
stop = 1;
|
|
Packit |
13e616 |
else {
|
|
Packit |
13e616 |
if (num_mst_in_lane[max_filled_lane] - num_mst_in_lane[min_filled_lane] <
|
|
Packit |
13e616 |
p_lash->balance_limit)
|
|
Packit |
13e616 |
stop = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
old_min_filled_lane = min_filled_lane;
|
|
Packit |
13e616 |
old_max_filled_lane = max_filled_lane;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
new_num_min_lane = MAX_INT;
|
|
Packit |
13e616 |
new_num_max_lane = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < lanes_needed; i++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (num_mst_in_lane[i] < new_num_min_lane) {
|
|
Packit |
13e616 |
new_num_min_lane = num_mst_in_lane[i];
|
|
Packit |
13e616 |
min_filled_lane = i;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (num_mst_in_lane[i] > new_num_max_lane) {
|
|
Packit |
13e616 |
new_num_max_lane = num_mst_in_lane[i];
|
|
Packit |
13e616 |
max_filled_lane = i;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (old_min_filled_lane != min_filled_lane) {
|
|
Packit |
13e616 |
trials = num_mst_in_lane[max_filled_lane];
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++)
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++)
|
|
Packit |
13e616 |
if (virtual_location[i][j][max_filled_lane] == 2)
|
|
Packit |
13e616 |
virtual_location[i][j][max_filled_lane] = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (old_max_filled_lane != max_filled_lane) {
|
|
Packit |
13e616 |
trials = num_mst_in_lane[max_filled_lane];
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++)
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++)
|
|
Packit |
13e616 |
if (virtual_location[i][j][old_max_filled_lane] == 2)
|
|
Packit |
13e616 |
virtual_location[i][j][old_max_filled_lane] = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static switch_t *switch_create(lash_t * p_lash, unsigned id, osm_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
unsigned num_ports = p_sw->num_ports;
|
|
Packit |
13e616 |
switch_t *sw;
|
|
Packit |
13e616 |
unsigned int i;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw = malloc(sizeof(*sw) + num_switches * sizeof(sw->routing_table[0]));
|
|
Packit |
13e616 |
if (!sw)
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(sw, 0, sizeof(*sw));
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
sw->routing_table[i].out_link = NONE;
|
|
Packit |
13e616 |
sw->routing_table[i].lane = NONE;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw->id = id;
|
|
Packit |
13e616 |
sw->dij_channels = malloc(num_ports * sizeof(int));
|
|
Packit |
13e616 |
if (!sw->dij_channels) {
|
|
Packit |
13e616 |
free(sw);
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
sw->p_sw = p_sw;
|
|
Packit |
13e616 |
p_sw->priv = sw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (osm_mesh_node_create(p_lash, sw)) {
|
|
Packit |
13e616 |
free(sw->dij_channels);
|
|
Packit |
13e616 |
free(sw);
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return sw;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void switch_delete(lash_t *p_lash, switch_t * sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (sw->dij_channels)
|
|
Packit |
13e616 |
free(sw->dij_channels);
|
|
Packit |
13e616 |
free(sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void delete_mesh_switches(lash_t *p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
if (p_lash->switches) {
|
|
Packit |
13e616 |
unsigned id;
|
|
Packit |
13e616 |
for (id = 0; ((int)id) < p_lash->num_switches; id++)
|
|
Packit |
13e616 |
if (p_lash->switches[id])
|
|
Packit |
13e616 |
osm_mesh_node_delete(p_lash,
|
|
Packit |
13e616 |
p_lash->switches[id]);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void free_lash_structures(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned int i, j, k;
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
delete_mesh_switches(p_lash);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* free cdg_vertex_matrix */
|
|
Packit |
13e616 |
for (i = 0; i < p_lash->vl_min; i++) {
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++) {
|
|
Packit |
13e616 |
for (k = 0; k < num_switches; k++)
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix[i][j][k])
|
|
Packit |
13e616 |
free(p_lash->cdg_vertex_matrix[i][j][k]);
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix[i][j])
|
|
Packit |
13e616 |
free(p_lash->cdg_vertex_matrix[i][j]);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix[i])
|
|
Packit |
13e616 |
free(p_lash->cdg_vertex_matrix[i]);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix)
|
|
Packit |
13e616 |
free(p_lash->cdg_vertex_matrix);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* free virtual_location */
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++) {
|
|
Packit |
13e616 |
if (p_lash->virtual_location[i][j])
|
|
Packit |
13e616 |
free(p_lash->virtual_location[i][j]);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (p_lash->virtual_location[i])
|
|
Packit |
13e616 |
free(p_lash->virtual_location[i]);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
if (p_lash->virtual_location)
|
|
Packit |
13e616 |
free(p_lash->virtual_location);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int init_lash_structures(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned vl_min = p_lash->vl_min;
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
int status = 0;
|
|
Packit |
13e616 |
unsigned int i, j, k;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* initialise cdg_vertex_matrix[num_layers][num_switches][num_switches] */
|
|
Packit |
13e616 |
p_lash->cdg_vertex_matrix =
|
|
Packit |
13e616 |
(cdg_vertex_t ****) malloc(vl_min * sizeof(cdg_vertex_t ***));
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
for (i = 0; i < vl_min; i++) {
|
|
Packit |
13e616 |
p_lash->cdg_vertex_matrix[i] =
|
|
Packit |
13e616 |
(cdg_vertex_t ***) malloc(num_switches *
|
|
Packit |
13e616 |
sizeof(cdg_vertex_t **));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix[i] == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < vl_min; i++) {
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++) {
|
|
Packit |
13e616 |
p_lash->cdg_vertex_matrix[i][j] =
|
|
Packit |
13e616 |
(cdg_vertex_t **) malloc(num_switches *
|
|
Packit |
13e616 |
sizeof(cdg_vertex_t *));
|
|
Packit |
13e616 |
if (p_lash->cdg_vertex_matrix[i][j] == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (k = 0; k < num_switches; k++)
|
|
Packit |
13e616 |
p_lash->cdg_vertex_matrix[i][j][k] = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* initialise virtual_location[num_switches][num_switches][num_layers],
|
|
Packit |
13e616 |
* default value = 0
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
p_lash->virtual_location =
|
|
Packit |
13e616 |
(int ***)malloc(num_switches * sizeof(int ***));
|
|
Packit |
13e616 |
if (p_lash->virtual_location == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
p_lash->virtual_location[i] =
|
|
Packit |
13e616 |
(int **)malloc(num_switches * sizeof(int **));
|
|
Packit |
13e616 |
if (p_lash->virtual_location[i] == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++) {
|
|
Packit |
13e616 |
p_lash->virtual_location[i][j] =
|
|
Packit |
13e616 |
(int *)malloc(vl_min * sizeof(int *));
|
|
Packit |
13e616 |
if (p_lash->virtual_location[i][j] == NULL)
|
|
Packit |
13e616 |
goto Exit_Mem_Error;
|
|
Packit |
13e616 |
for (k = 0; k < vl_min; k++)
|
|
Packit |
13e616 |
p_lash->virtual_location[i][j][k] = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* initialise num_mst_in_lane[num_switches], default 0 */
|
|
Packit |
13e616 |
memset(p_lash->num_mst_in_lane, 0,
|
|
Packit |
13e616 |
IB_MAX_NUM_VLS * sizeof(p_lash->num_mst_in_lane[0]));
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit_Mem_Error:
|
|
Packit |
13e616 |
status = -1;
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D01: "
|
|
Packit |
13e616 |
"Could not allocate required memory for LASH errno %d, errno %d for lack of memory\n",
|
|
Packit |
13e616 |
errno, ENOMEM);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int lash_core(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
unsigned num_switches = p_lash->num_switches;
|
|
Packit |
13e616 |
switch_t **switches = p_lash->switches;
|
|
Packit |
13e616 |
unsigned lanes_needed = 1;
|
|
Packit |
13e616 |
unsigned int i, j, k, dest_switch = 0;
|
|
Packit |
13e616 |
reachable_dest_t *dests, *idest;
|
|
Packit |
13e616 |
int cycle_found = 0;
|
|
Packit |
13e616 |
unsigned v_lane;
|
|
Packit |
13e616 |
int stop = 0, output_link, i_next_switch;
|
|
Packit |
13e616 |
int output_link2, i_next_switch2;
|
|
Packit |
13e616 |
int cycle_found2 = 0;
|
|
Packit |
13e616 |
int status = -1;
|
|
Packit |
13e616 |
int *switch_bitmap = NULL; /* Bitmap to check if we have processed this pair */
|
|
Packit |
13e616 |
unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->p_osm->subn.opt.do_mesh_analysis && osm_do_mesh_analysis(p_lash)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D05: Mesh analysis failed\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
shortest_path(p_lash, i);
|
|
Packit |
13e616 |
if (generate_routing_func_for_mst(p_lash, i, &dests)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D06: "
|
|
Packit |
13e616 |
"generate_routing_func_for_mst failed\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
idest = dests;
|
|
Packit |
13e616 |
while (idest != NULL) {
|
|
Packit |
13e616 |
dests = dests->next;
|
|
Packit |
13e616 |
free(idest);
|
|
Packit |
13e616 |
idest = dests;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++) {
|
|
Packit |
13e616 |
switches[j]->used_channels = 0;
|
|
Packit |
13e616 |
switches[j]->q_state = UNQUEUED;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch_bitmap = calloc(num_switches * num_switches, sizeof(int));
|
|
Packit |
13e616 |
if (!switch_bitmap) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D04: "
|
|
Packit |
13e616 |
"Failed allocating switch_bitmap - out of memory\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < num_switches; i++) {
|
|
Packit |
13e616 |
for (dest_switch = 0; dest_switch < num_switches; dest_switch++)
|
|
Packit |
13e616 |
if (dest_switch != i && switch_bitmap[i * num_switches + dest_switch] == 0) {
|
|
Packit |
13e616 |
v_lane = 0;
|
|
Packit |
13e616 |
stop = 0;
|
|
Packit |
13e616 |
while (v_lane < lanes_needed && stop == 0) {
|
|
Packit |
13e616 |
if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) ||
|
|
Packit |
13e616 |
generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 4D07: generate_cdg_for_sp failed\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
output_link =
|
|
Packit |
13e616 |
switches[i]->routing_table[dest_switch].out_link;
|
|
Packit |
13e616 |
output_link2 =
|
|
Packit |
13e616 |
switches[dest_switch]->routing_table[i].out_link;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
i_next_switch = get_next_switch(p_lash, i, output_link);
|
|
Packit |
13e616 |
i_next_switch2 = get_next_switch(p_lash, dest_switch, output_link2);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
CL_ASSERT(p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][i][i_next_switch] !=
|
|
Packit |
13e616 |
NULL);
|
|
Packit |
13e616 |
CL_ASSERT(p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][dest_switch]
|
|
Packit |
13e616 |
[i_next_switch2] != NULL);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
cycle_found =
|
|
Packit |
13e616 |
cycle_exists(p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][i]
|
|
Packit |
13e616 |
[i_next_switch], NULL, NULL, 1);
|
|
Packit |
13e616 |
cycle_found2 =
|
|
Packit |
13e616 |
cycle_exists(p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][dest_switch]
|
|
Packit |
13e616 |
[i_next_switch2], NULL, NULL, 1);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (j = 0; j < num_switches; j++)
|
|
Packit |
13e616 |
for (k = 0; k < num_switches; k++)
|
|
Packit |
13e616 |
if (p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][j][k] !=
|
|
Packit |
13e616 |
NULL) {
|
|
Packit |
13e616 |
p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][j]
|
|
Packit |
13e616 |
[k]->visiting_number = 0;
|
|
Packit |
13e616 |
p_lash->
|
|
Packit |
13e616 |
cdg_vertex_matrix[v_lane][j]
|
|
Packit |
13e616 |
[k]->seen = 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cycle_found == 1 || cycle_found2 == 1) {
|
|
Packit |
13e616 |
remove_temp_depend_for_sp(p_lash, i, dest_switch,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
remove_temp_depend_for_sp(p_lash, dest_switch, i,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
v_lane++;
|
|
Packit |
13e616 |
} else {
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash, i,
|
|
Packit |
13e616 |
dest_switch,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash,
|
|
Packit |
13e616 |
dest_switch, i,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
stop = 1;
|
|
Packit |
13e616 |
p_lash->num_mst_in_lane[v_lane]++;
|
|
Packit |
13e616 |
p_lash->num_mst_in_lane[v_lane]++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switches[i]->routing_table[dest_switch].lane = v_lane + start_vl;
|
|
Packit |
13e616 |
switches[dest_switch]->routing_table[i].lane = v_lane + start_vl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (cycle_found == 1 || cycle_found2 == 1) {
|
|
Packit |
13e616 |
if (++lanes_needed > p_lash->vl_min)
|
|
Packit |
13e616 |
goto Error_Not_Enough_Lanes;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) ||
|
|
Packit |
13e616 |
generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR,
|
|
Packit |
13e616 |
"ERR 4D08: generate_cdg_for_sp failed\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i,
|
|
Packit |
13e616 |
v_lane);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->num_mst_in_lane[v_lane]++;
|
|
Packit |
13e616 |
p_lash->num_mst_in_lane[v_lane]++;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
p_lash->virtual_location[i][dest_switch][v_lane] = 1;
|
|
Packit |
13e616 |
p_lash->virtual_location[dest_switch][i][v_lane] = 1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch_bitmap[i * num_switches + dest_switch] = 1;
|
|
Packit |
13e616 |
switch_bitmap[dest_switch * num_switches + i] = 1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < lanes_needed; i++)
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n",
|
|
Packit |
13e616 |
i, p_lash->num_mst_in_lane[i]);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"Lanes needed: %d, Balancing\n", lanes_needed);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (balance_virtual_lanes(p_lash, lanes_needed)) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D09: Balancing failed\n");
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (i = 0; i < lanes_needed; i++)
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n",
|
|
Packit |
13e616 |
i, p_lash->num_mst_in_lane[i]);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = 0;
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Error_Not_Enough_Lanes:
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D02: "
|
|
Packit |
13e616 |
"Lane requirements (%d) exceed available lanes (%d)"
|
|
Packit |
13e616 |
" with starting lane (%d)\n",
|
|
Packit |
13e616 |
lanes_needed, p_lash->vl_min, start_vl);
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
if (switch_bitmap)
|
|
Packit |
13e616 |
free(switch_bitmap);
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static unsigned get_lash_id(osm_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
return ((switch_t *) p_sw->priv)->id;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int get_next_port(switch_t *sw, int link)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
link_t *l = sw->node->links[link];
|
|
Packit |
13e616 |
int port = l->next_port++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
* note if not doing mesh analysis
|
|
Packit |
13e616 |
* then num_ports is always 1
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
if (l->next_port >= l->num_ports)
|
|
Packit |
13e616 |
l->next_port = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return l->ports[port];
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void populate_fwd_tbls(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
osm_subn_t *p_subn = &p_lash->p_osm->subn;
|
|
Packit |
13e616 |
osm_switch_t *p_sw, *p_next_sw, *p_dst_sw;
|
|
Packit |
13e616 |
osm_port_t *port;
|
|
Packit |
13e616 |
uint16_t max_lid_ho, lid;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Go through each switch individually */
|
|
Packit |
13e616 |
while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
|
|
Packit |
13e616 |
uint64_t current_guid;
|
|
Packit |
13e616 |
switch_t *sw;
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
max_lid_ho = p_sw->max_lid_ho;
|
|
Packit |
13e616 |
current_guid = p_sw->p_node->node_info.port_guid;
|
|
Packit |
13e616 |
sw = p_sw->priv;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
for (lid = 1; lid <= max_lid_ho; lid++) {
|
|
Packit |
13e616 |
port = osm_get_port_by_lid_ho(p_subn, lid);
|
|
Packit |
13e616 |
if (!port)
|
|
Packit |
13e616 |
continue;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_dst_sw = get_osm_switch_from_port(port);
|
|
Packit |
13e616 |
if (p_dst_sw == p_sw) {
|
|
Packit |
13e616 |
uint8_t egress_port = port->p_node->sw ? 0 :
|
|
Packit |
13e616 |
port->p_physp->p_remote_physp->port_num;
|
|
Packit |
13e616 |
p_sw->new_lft[lid] = egress_port;
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LASH fwd MY SRC SRC GUID 0x%016" PRIx64
|
|
Packit |
13e616 |
" src lash id (%d), src lid no (%u) src lash port (%d) "
|
|
Packit |
13e616 |
"DST GUID 0x%016" PRIx64
|
|
Packit |
13e616 |
" src lash id (%d), src lash port (%d)\n",
|
|
Packit |
13e616 |
cl_ntoh64(current_guid), -1, lid,
|
|
Packit |
13e616 |
egress_port, cl_ntoh64(current_guid),
|
|
Packit |
13e616 |
-1, egress_port);
|
|
Packit |
13e616 |
} else if (p_dst_sw) {
|
|
Packit |
13e616 |
unsigned dst_lash_switch_id =
|
|
Packit |
13e616 |
get_lash_id(p_dst_sw);
|
|
Packit |
13e616 |
uint8_t lash_egress_port =
|
|
Packit |
13e616 |
(uint8_t) sw->
|
|
Packit |
13e616 |
routing_table[dst_lash_switch_id].out_link;
|
|
Packit |
13e616 |
uint8_t physical_egress_port =
|
|
Packit |
13e616 |
get_next_port(sw, lash_egress_port);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw->new_lft[lid] = physical_egress_port;
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LASH fwd SRC GUID 0x%016" PRIx64
|
|
Packit |
13e616 |
" src lash id (%d), "
|
|
Packit |
13e616 |
"src lid no (%u) src lash port (%d) "
|
|
Packit |
13e616 |
"DST GUID 0x%016" PRIx64
|
|
Packit |
13e616 |
" src lash id (%d), src lash port (%d)\n",
|
|
Packit |
13e616 |
cl_ntoh64(current_guid), sw->id, lid,
|
|
Packit |
13e616 |
lash_egress_port,
|
|
Packit |
13e616 |
cl_ntoh64(p_dst_sw->p_node->node_info.
|
|
Packit |
13e616 |
port_guid),
|
|
Packit |
13e616 |
dst_lash_switch_id,
|
|
Packit |
13e616 |
physical_egress_port);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} /* for */
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void osm_lash_process_switch(lash_t * p_lash, osm_switch_t * p_sw)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
int i, port_count;
|
|
Packit |
13e616 |
osm_physp_t *p_current_physp, *p_remote_physp;
|
|
Packit |
13e616 |
unsigned switch_a_lash_id, switch_b_lash_id;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
switch_a_lash_id = get_lash_id(p_sw);
|
|
Packit |
13e616 |
port_count = osm_node_get_num_physp(p_sw->p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* starting at port 1, ignoring management port on switch */
|
|
Packit |
13e616 |
for (i = 1; i < port_count; i++) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i);
|
|
Packit |
13e616 |
if (p_current_physp) {
|
|
Packit |
13e616 |
p_remote_physp = p_current_physp->p_remote_physp;
|
|
Packit |
13e616 |
if (p_remote_physp && p_remote_physp->p_node->sw) {
|
|
Packit |
13e616 |
int physical_port_a_num =
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_current_physp);
|
|
Packit |
13e616 |
int physical_port_b_num =
|
|
Packit |
13e616 |
osm_physp_get_port_num(p_remote_physp);
|
|
Packit |
13e616 |
switch_b_lash_id =
|
|
Packit |
13e616 |
get_lash_id(p_remote_physp->p_node->sw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
connect_switches(p_lash, switch_a_lash_id,
|
|
Packit |
13e616 |
switch_b_lash_id,
|
|
Packit |
13e616 |
physical_port_a_num);
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_VERBOSE,
|
|
Packit |
13e616 |
"LASH SUCCESS connected G 0x%016" PRIx64
|
|
Packit |
13e616 |
" , lash_id(%u), P(%u) " " to G 0x%016"
|
|
Packit |
13e616 |
PRIx64 " , lash_id(%u) , P(%u)\n",
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_current_physp)),
|
|
Packit |
13e616 |
switch_a_lash_id, physical_port_a_num,
|
|
Packit |
13e616 |
cl_ntoh64(osm_physp_get_port_guid
|
|
Packit |
13e616 |
(p_remote_physp)),
|
|
Packit |
13e616 |
switch_b_lash_id, physical_port_b_num);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void lash_cleanup(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_subn_t *p_subn = &p_lash->p_osm->subn;
|
|
Packit |
13e616 |
osm_switch_t *p_next_sw, *p_sw;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* drop any existing references to old lash switches */
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
|
|
Packit |
13e616 |
while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
p_sw->priv = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->switches) {
|
|
Packit |
13e616 |
unsigned id;
|
|
Packit |
13e616 |
for (id = 0; ((int)id) < p_lash->num_switches; id++)
|
|
Packit |
13e616 |
if (p_lash->switches[id])
|
|
Packit |
13e616 |
switch_delete(p_lash, p_lash->switches[id]);
|
|
Packit |
13e616 |
free(p_lash->switches);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
p_lash->switches = NULL;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/*
|
|
Packit |
13e616 |
static int discover_network_properties()
|
|
Packit |
13e616 |
Traverse the topology of the network in order to determine
|
|
Packit |
13e616 |
- the maximum number of switches,
|
|
Packit |
13e616 |
- the minimum number of virtual layers
|
|
Packit |
13e616 |
*/
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int discover_network_properties(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
int i, id = 0;
|
|
Packit |
13e616 |
uint8_t vl_min;
|
|
Packit |
13e616 |
osm_subn_t *p_subn = &p_lash->p_osm->subn;
|
|
Packit |
13e616 |
osm_switch_t *p_next_sw, *p_sw;
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->switches = calloc(p_lash->num_switches, sizeof(switch_t *));
|
|
Packit |
13e616 |
if (!p_lash->switches)
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
vl_min = 5; /* set to a high value */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
|
|
Packit |
13e616 |
while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
|
|
Packit |
13e616 |
uint16_t port_count;
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->switches[id] = switch_create(p_lash, id, p_sw);
|
|
Packit |
13e616 |
if (!p_lash->switches[id])
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
id++;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
port_count = osm_node_get_num_physp(p_sw->p_node);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Note, ignoring port 0. management port */
|
|
Packit |
13e616 |
for (i = 1; i < port_count; i++) {
|
|
Packit |
13e616 |
osm_physp_t *p_current_physp =
|
|
Packit |
13e616 |
osm_node_get_physp_ptr(p_sw->p_node, i);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_current_physp
|
|
Packit |
13e616 |
&& p_current_physp->p_remote_physp) {
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
ib_port_info_t *p_port_info =
|
|
Packit |
13e616 |
&p_current_physp->port_info;
|
|
Packit |
13e616 |
uint8_t port_vl_min =
|
|
Packit |
13e616 |
ib_port_info_get_op_vls(p_port_info);
|
|
Packit |
13e616 |
if (port_vl_min && port_vl_min < vl_min)
|
|
Packit |
13e616 |
vl_min = port_vl_min;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
} /* for */
|
|
Packit |
13e616 |
} /* while */
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
vl_min = 1 << (vl_min - 1);
|
|
Packit |
13e616 |
if (vl_min > 15)
|
|
Packit |
13e616 |
vl_min = 15;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->p_osm->subn.opt.lash_start_vl >= vl_min) {
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D03: "
|
|
Packit |
13e616 |
"Start VL(%d) too high for min operational vl(%d)\n",
|
|
Packit |
13e616 |
p_lash->p_osm->subn.opt.lash_start_vl, vl_min);
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->vl_min = vl_min - p_lash->p_osm->subn.opt.lash_start_vl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG(p_log, OSM_LOG_INFO,
|
|
Packit |
13e616 |
"min operational vl(%d) start vl(%d) max_switches(%d)\n",
|
|
Packit |
13e616 |
p_lash->vl_min, p_lash->p_osm->subn.opt.lash_start_vl,
|
|
Packit |
13e616 |
p_lash->num_switches);
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void process_switches(lash_t * p_lash)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
osm_switch_t *p_sw, *p_next_sw;
|
|
Packit |
13e616 |
osm_subn_t *p_subn = &p_lash->p_osm->subn;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* Go through each switch and process it. i.e build the connection
|
|
Packit |
13e616 |
structure required by LASH */
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
|
|
Packit |
13e616 |
while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
|
|
Packit |
13e616 |
p_sw = p_next_sw;
|
|
Packit |
13e616 |
p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
osm_lash_process_switch(p_lash, p_sw);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static int lash_process(void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
lash_t *p_lash = context;
|
|
Packit |
13e616 |
osm_log_t *p_log = &p_lash->p_osm->log;
|
|
Packit |
13e616 |
int status = 0;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
OSM_LOG_ENTER(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->balance_limit = 6;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
/* everything starts here */
|
|
Packit |
13e616 |
lash_cleanup(p_lash);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = discover_network_properties(p_lash);
|
|
Packit |
13e616 |
if (status)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = init_lash_structures(p_lash);
|
|
Packit |
13e616 |
if (status)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
process_switches(p_lash);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
status = lash_core(p_lash);
|
|
Packit |
13e616 |
if (status)
|
|
Packit |
13e616 |
goto Exit;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
populate_fwd_tbls(p_lash);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
Exit:
|
|
Packit |
13e616 |
if (p_lash->vl_min)
|
|
Packit |
13e616 |
free_lash_structures(p_lash);
|
|
Packit |
13e616 |
OSM_LOG_EXIT(p_log);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return status;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static lash_t *lash_create(osm_opensm_t * p_osm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
lash_t *p_lash;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash = calloc(1, sizeof(lash_t));
|
|
Packit |
13e616 |
if (!p_lash)
|
|
Packit |
13e616 |
return NULL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_lash->p_osm = p_osm;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return p_lash;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static void lash_delete(void *context)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
lash_t *p_lash = context;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (p_lash->switches) {
|
|
Packit |
13e616 |
unsigned id;
|
|
Packit |
13e616 |
for (id = 0; ((int)id) < p_lash->num_switches; id++)
|
|
Packit |
13e616 |
if (p_lash->switches[id])
|
|
Packit |
13e616 |
switch_delete(p_lash, p_lash->switches[id]);
|
|
Packit |
13e616 |
free(p_lash->switches);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
free(p_lash);
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
static uint8_t get_lash_sl(void *context, uint8_t path_sl_hint,
|
|
Packit |
13e616 |
const ib_net16_t slid, const ib_net16_t dlid)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
unsigned dst_id;
|
|
Packit |
13e616 |
unsigned src_id;
|
|
Packit |
13e616 |
osm_port_t *p_src_port, *p_dst_port;
|
|
Packit |
13e616 |
osm_switch_t *p_sw;
|
|
Packit |
13e616 |
lash_t *p_lash = context;
|
|
Packit |
13e616 |
osm_opensm_t *p_osm = p_lash->p_osm;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
if (!(p_osm->routing_engine_used &&
|
|
Packit |
13e616 |
p_osm->routing_engine_used->type == OSM_ROUTING_ENGINE_TYPE_LASH))
|
|
Packit |
13e616 |
return OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_src_port = osm_get_port_by_lid(&p_osm->subn, slid);
|
|
Packit |
13e616 |
if (!p_src_port)
|
|
Packit |
13e616 |
return OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_dst_port = osm_get_port_by_lid(&p_osm->subn, dlid);
|
|
Packit |
13e616 |
if (!p_dst_port)
|
|
Packit |
13e616 |
return OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw = get_osm_switch_from_port(p_dst_port);
|
|
Packit |
13e616 |
if (!p_sw || !p_sw->priv)
|
|
Packit |
13e616 |
return OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
dst_id = get_lash_id(p_sw);
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
p_sw = get_osm_switch_from_port(p_src_port);
|
|
Packit |
13e616 |
if (!p_sw || !p_sw->priv)
|
|
Packit |
13e616 |
return OSM_DEFAULT_SL;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
src_id = get_lash_id(p_sw);
|
|
Packit |
13e616 |
if (src_id == dst_id)
|
|
Packit |
13e616 |
return p_osm->subn.opt.lash_start_vl;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return (uint8_t) ((switch_t *) p_sw->priv)->routing_table[dst_id].lane;
|
|
Packit |
13e616 |
}
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
int osm_ucast_lash_setup(struct osm_routing_engine *r, osm_opensm_t *p_osm)
|
|
Packit |
13e616 |
{
|
|
Packit |
13e616 |
lash_t *p_lash = lash_create(p_osm);
|
|
Packit |
13e616 |
if (!p_lash)
|
|
Packit |
13e616 |
return -1;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
r->context = p_lash;
|
|
Packit |
13e616 |
r->ucast_build_fwd_tables = lash_process;
|
|
Packit |
13e616 |
r->path_sl = get_lash_sl;
|
|
Packit |
13e616 |
r->destroy = lash_delete;
|
|
Packit |
13e616 |
|
|
Packit |
13e616 |
return 0;
|
|
Packit |
13e616 |
}
|