1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
6*d6b92ffaSHans Petter Selasky *
7*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
8*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
9*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
10*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
11*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
12*d6b92ffaSHans Petter Selasky *
13*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
14*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
15*d6b92ffaSHans Petter Selasky * conditions are met:
16*d6b92ffaSHans Petter Selasky *
17*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
18*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
19*d6b92ffaSHans Petter Selasky * disclaimer.
20*d6b92ffaSHans Petter Selasky *
21*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
22*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
23*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
24*d6b92ffaSHans Petter Selasky * provided with the distribution.
25*d6b92ffaSHans Petter Selasky *
26*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*d6b92ffaSHans Petter Selasky * SOFTWARE.
34*d6b92ffaSHans Petter Selasky *
35*d6b92ffaSHans Petter Selasky */
36*d6b92ffaSHans Petter Selasky
37*d6b92ffaSHans Petter Selasky /*
38*d6b92ffaSHans Petter Selasky * Abstract:
39*d6b92ffaSHans Petter Selasky * Implementation of Up Down Algorithm using ranking & Min Hop
40*d6b92ffaSHans Petter Selasky * Calculation functions
41*d6b92ffaSHans Petter Selasky */
42*d6b92ffaSHans Petter Selasky
43*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
44*d6b92ffaSHans Petter Selasky # include <config.h>
45*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
46*d6b92ffaSHans Petter Selasky
47*d6b92ffaSHans Petter Selasky #include <stdlib.h>
48*d6b92ffaSHans Petter Selasky #include <ctype.h>
49*d6b92ffaSHans Petter Selasky #include <complib/cl_debug.h>
50*d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h>
51*d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
52*d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_UCAST_UPDN_C
53*d6b92ffaSHans Petter Selasky #include <opensm/osm_switch.h>
54*d6b92ffaSHans Petter Selasky #include <opensm/osm_opensm.h>
55*d6b92ffaSHans Petter Selasky #include <opensm/osm_ucast_mgr.h>
56*d6b92ffaSHans Petter Selasky
57*d6b92ffaSHans Petter Selasky /* //////////////////////////// */
58*d6b92ffaSHans Petter Selasky /* Local types */
59*d6b92ffaSHans Petter Selasky /* //////////////////////////// */
60*d6b92ffaSHans Petter Selasky
61*d6b92ffaSHans Petter Selasky /* direction */
62*d6b92ffaSHans Petter Selasky typedef enum updn_switch_dir {
63*d6b92ffaSHans Petter Selasky UP = 0,
64*d6b92ffaSHans Petter Selasky DOWN
65*d6b92ffaSHans Petter Selasky } updn_switch_dir_t;
66*d6b92ffaSHans Petter Selasky
67*d6b92ffaSHans Petter Selasky /* updn structure */
68*d6b92ffaSHans Petter Selasky typedef struct updn {
69*d6b92ffaSHans Petter Selasky unsigned num_roots;
70*d6b92ffaSHans Petter Selasky osm_opensm_t *p_osm;
71*d6b92ffaSHans Petter Selasky } updn_t;
72*d6b92ffaSHans Petter Selasky
73*d6b92ffaSHans Petter Selasky struct updn_node {
74*d6b92ffaSHans Petter Selasky cl_list_item_t list;
75*d6b92ffaSHans Petter Selasky osm_switch_t *sw;
76*d6b92ffaSHans Petter Selasky uint64_t id;
77*d6b92ffaSHans Petter Selasky updn_switch_dir_t dir;
78*d6b92ffaSHans Petter Selasky unsigned rank;
79*d6b92ffaSHans Petter Selasky unsigned visited;
80*d6b92ffaSHans Petter Selasky };
81*d6b92ffaSHans Petter Selasky
82*d6b92ffaSHans Petter Selasky /* This function returns direction based on rank and guid info of current &
83*d6b92ffaSHans Petter Selasky remote ports */
updn_get_dir(unsigned cur_rank,unsigned rem_rank,uint64_t cur_id,uint64_t rem_id)84*d6b92ffaSHans Petter Selasky static updn_switch_dir_t updn_get_dir(unsigned cur_rank, unsigned rem_rank,
85*d6b92ffaSHans Petter Selasky uint64_t cur_id, uint64_t rem_id)
86*d6b92ffaSHans Petter Selasky {
87*d6b92ffaSHans Petter Selasky /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect
88*d6b92ffaSHans Petter Selasky directly, but in case they are we assign to root node an UP direction to allow UPDN to discover
89*d6b92ffaSHans Petter Selasky the subnet correctly (and not from the point of view of the last root node).
90*d6b92ffaSHans Petter Selasky */
91*d6b92ffaSHans Petter Selasky if (!cur_rank && !rem_rank)
92*d6b92ffaSHans Petter Selasky return UP;
93*d6b92ffaSHans Petter Selasky
94*d6b92ffaSHans Petter Selasky if (cur_rank < rem_rank)
95*d6b92ffaSHans Petter Selasky return DOWN;
96*d6b92ffaSHans Petter Selasky else if (cur_rank > rem_rank)
97*d6b92ffaSHans Petter Selasky return UP;
98*d6b92ffaSHans Petter Selasky else {
99*d6b92ffaSHans Petter Selasky /* Equal rank, decide by id number, bigger == UP direction */
100*d6b92ffaSHans Petter Selasky if (cur_id > rem_id)
101*d6b92ffaSHans Petter Selasky return UP;
102*d6b92ffaSHans Petter Selasky else
103*d6b92ffaSHans Petter Selasky return DOWN;
104*d6b92ffaSHans Petter Selasky }
105*d6b92ffaSHans Petter Selasky }
106*d6b92ffaSHans Petter Selasky
107*d6b92ffaSHans Petter Selasky /**********************************************************************
108*d6b92ffaSHans Petter Selasky * This function does the bfs of min hop table calculation by guid index
109*d6b92ffaSHans Petter Selasky * as a starting point.
110*d6b92ffaSHans Petter Selasky **********************************************************************/
updn_bfs_by_node(IN osm_log_t * p_log,IN osm_subn_t * p_subn,IN osm_switch_t * p_sw)111*d6b92ffaSHans Petter Selasky static int updn_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn,
112*d6b92ffaSHans Petter Selasky IN osm_switch_t * p_sw)
113*d6b92ffaSHans Petter Selasky {
114*d6b92ffaSHans Petter Selasky uint8_t pn, pn_rem;
115*d6b92ffaSHans Petter Selasky cl_qlist_t list;
116*d6b92ffaSHans Petter Selasky uint16_t lid;
117*d6b92ffaSHans Petter Selasky struct updn_node *u;
118*d6b92ffaSHans Petter Selasky updn_switch_dir_t next_dir, current_dir;
119*d6b92ffaSHans Petter Selasky
120*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_log);
121*d6b92ffaSHans Petter Selasky
122*d6b92ffaSHans Petter Selasky lid = osm_node_get_base_lid(p_sw->p_node, 0);
123*d6b92ffaSHans Petter Selasky lid = cl_ntoh16(lid);
124*d6b92ffaSHans Petter Selasky osm_switch_set_hops(p_sw, lid, 0, 0);
125*d6b92ffaSHans Petter Selasky
126*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_DEBUG,
127*d6b92ffaSHans Petter Selasky "Starting from switch - port GUID 0x%" PRIx64 " lid %u\n",
128*d6b92ffaSHans Petter Selasky cl_ntoh64(p_sw->p_node->node_info.port_guid), lid);
129*d6b92ffaSHans Petter Selasky
130*d6b92ffaSHans Petter Selasky u = p_sw->priv;
131*d6b92ffaSHans Petter Selasky u->dir = UP;
132*d6b92ffaSHans Petter Selasky
133*d6b92ffaSHans Petter Selasky /* Update list with the new element */
134*d6b92ffaSHans Petter Selasky cl_qlist_init(&list);
135*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&list, &u->list);
136*d6b92ffaSHans Petter Selasky
137*d6b92ffaSHans Petter Selasky /* BFS the list till no next element */
138*d6b92ffaSHans Petter Selasky while (!cl_is_qlist_empty(&list)) {
139*d6b92ffaSHans Petter Selasky u = (struct updn_node *)cl_qlist_remove_head(&list);
140*d6b92ffaSHans Petter Selasky u->visited = 0; /* cleanup */
141*d6b92ffaSHans Petter Selasky current_dir = u->dir;
142*d6b92ffaSHans Petter Selasky /* Go over all ports of the switch and find unvisited remote nodes */
143*d6b92ffaSHans Petter Selasky for (pn = 1; pn < u->sw->num_ports; pn++) {
144*d6b92ffaSHans Petter Selasky osm_node_t *p_remote_node;
145*d6b92ffaSHans Petter Selasky struct updn_node *rem_u;
146*d6b92ffaSHans Petter Selasky uint8_t current_min_hop, remote_min_hop,
147*d6b92ffaSHans Petter Selasky set_hop_return_value;
148*d6b92ffaSHans Petter Selasky osm_switch_t *p_remote_sw;
149*d6b92ffaSHans Petter Selasky
150*d6b92ffaSHans Petter Selasky p_remote_node =
151*d6b92ffaSHans Petter Selasky osm_node_get_remote_node(u->sw->p_node, pn,
152*d6b92ffaSHans Petter Selasky &pn_rem);
153*d6b92ffaSHans Petter Selasky /* If no remote node OR remote node is not a SWITCH
154*d6b92ffaSHans Petter Selasky continue to next pn */
155*d6b92ffaSHans Petter Selasky if (!p_remote_node || !p_remote_node->sw)
156*d6b92ffaSHans Petter Selasky continue;
157*d6b92ffaSHans Petter Selasky /* Fetch remote guid only after validation of remote node */
158*d6b92ffaSHans Petter Selasky p_remote_sw = p_remote_node->sw;
159*d6b92ffaSHans Petter Selasky rem_u = p_remote_sw->priv;
160*d6b92ffaSHans Petter Selasky /* Decide which direction to mark it (UP/DOWN) */
161*d6b92ffaSHans Petter Selasky next_dir = updn_get_dir(u->rank, rem_u->rank,
162*d6b92ffaSHans Petter Selasky u->id, rem_u->id);
163*d6b92ffaSHans Petter Selasky
164*d6b92ffaSHans Petter Selasky /* Check if this is a legal step : the only illegal step is going
165*d6b92ffaSHans Petter Selasky from DOWN to UP */
166*d6b92ffaSHans Petter Selasky if ((current_dir == DOWN) && (next_dir == UP)) {
167*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_DEBUG,
168*d6b92ffaSHans Petter Selasky "Avoiding move from 0x%016" PRIx64
169*d6b92ffaSHans Petter Selasky " to 0x%016" PRIx64 "\n",
170*d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)),
171*d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_remote_node)));
172*d6b92ffaSHans Petter Selasky /* Illegal step */
173*d6b92ffaSHans Petter Selasky continue;
174*d6b92ffaSHans Petter Selasky }
175*d6b92ffaSHans Petter Selasky /* Set MinHop value for the current lid */
176*d6b92ffaSHans Petter Selasky current_min_hop = osm_switch_get_least_hops(u->sw, lid);
177*d6b92ffaSHans Petter Selasky /* Check hop count if better insert into list && update
178*d6b92ffaSHans Petter Selasky the remote node Min Hop Table */
179*d6b92ffaSHans Petter Selasky remote_min_hop =
180*d6b92ffaSHans Petter Selasky osm_switch_get_hop_count(p_remote_sw, lid, pn_rem);
181*d6b92ffaSHans Petter Selasky if (current_min_hop + 1 < remote_min_hop) {
182*d6b92ffaSHans Petter Selasky set_hop_return_value =
183*d6b92ffaSHans Petter Selasky osm_switch_set_hops(p_remote_sw, lid,
184*d6b92ffaSHans Petter Selasky pn_rem,
185*d6b92ffaSHans Petter Selasky current_min_hop + 1);
186*d6b92ffaSHans Petter Selasky if (set_hop_return_value) {
187*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AA01: "
188*d6b92ffaSHans Petter Selasky "Invalid value returned from set min hop is: %d\n",
189*d6b92ffaSHans Petter Selasky set_hop_return_value);
190*d6b92ffaSHans Petter Selasky }
191*d6b92ffaSHans Petter Selasky /* Check if remote port has already been visited */
192*d6b92ffaSHans Petter Selasky if (!rem_u->visited) {
193*d6b92ffaSHans Petter Selasky /* Insert updn_switch item into the list */
194*d6b92ffaSHans Petter Selasky rem_u->dir = next_dir;
195*d6b92ffaSHans Petter Selasky rem_u->visited = 1;
196*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&list,
197*d6b92ffaSHans Petter Selasky &rem_u->list);
198*d6b92ffaSHans Petter Selasky }
199*d6b92ffaSHans Petter Selasky }
200*d6b92ffaSHans Petter Selasky }
201*d6b92ffaSHans Petter Selasky }
202*d6b92ffaSHans Petter Selasky
203*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_log);
204*d6b92ffaSHans Petter Selasky return 0;
205*d6b92ffaSHans Petter Selasky }
206*d6b92ffaSHans Petter Selasky
207*d6b92ffaSHans Petter Selasky /* NOTE : PLS check if we need to decide that the first */
208*d6b92ffaSHans Petter Selasky /* rank is a SWITCH for BFS purpose */
updn_subn_rank(IN updn_t * p_updn)209*d6b92ffaSHans Petter Selasky static int updn_subn_rank(IN updn_t * p_updn)
210*d6b92ffaSHans Petter Selasky {
211*d6b92ffaSHans Petter Selasky osm_switch_t *p_sw;
212*d6b92ffaSHans Petter Selasky osm_physp_t *p_physp, *p_remote_physp;
213*d6b92ffaSHans Petter Selasky cl_qlist_t list;
214*d6b92ffaSHans Petter Selasky cl_map_item_t *item;
215*d6b92ffaSHans Petter Selasky struct updn_node *u, *remote_u;
216*d6b92ffaSHans Petter Selasky uint8_t num_ports, port_num;
217*d6b92ffaSHans Petter Selasky osm_log_t *p_log = &p_updn->p_osm->log;
218*d6b92ffaSHans Petter Selasky unsigned max_rank = 0;
219*d6b92ffaSHans Petter Selasky
220*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_log);
221*d6b92ffaSHans Petter Selasky cl_qlist_init(&list);
222*d6b92ffaSHans Petter Selasky
223*d6b92ffaSHans Petter Selasky /* add all roots to the list */
224*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
225*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
226*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
227*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *)item;
228*d6b92ffaSHans Petter Selasky u = p_sw->priv;
229*d6b92ffaSHans Petter Selasky if (!u->rank)
230*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&list, &u->list);
231*d6b92ffaSHans Petter Selasky }
232*d6b92ffaSHans Petter Selasky
233*d6b92ffaSHans Petter Selasky /* BFS the list till it's empty */
234*d6b92ffaSHans Petter Selasky while (!cl_is_qlist_empty(&list)) {
235*d6b92ffaSHans Petter Selasky u = (struct updn_node *)cl_qlist_remove_head(&list);
236*d6b92ffaSHans Petter Selasky /* Go over all remote nodes and rank them (if not already visited) */
237*d6b92ffaSHans Petter Selasky p_sw = u->sw;
238*d6b92ffaSHans Petter Selasky num_ports = p_sw->num_ports;
239*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_DEBUG,
240*d6b92ffaSHans Petter Selasky "Handling switch GUID 0x%" PRIx64 "\n",
241*d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
242*d6b92ffaSHans Petter Selasky for (port_num = 1; port_num < num_ports; port_num++) {
243*d6b92ffaSHans Petter Selasky ib_net64_t port_guid;
244*d6b92ffaSHans Petter Selasky
245*d6b92ffaSHans Petter Selasky /* Current port fetched in order to get remote side */
246*d6b92ffaSHans Petter Selasky p_physp =
247*d6b92ffaSHans Petter Selasky osm_node_get_physp_ptr(p_sw->p_node, port_num);
248*d6b92ffaSHans Petter Selasky
249*d6b92ffaSHans Petter Selasky if (!p_physp)
250*d6b92ffaSHans Petter Selasky continue;
251*d6b92ffaSHans Petter Selasky
252*d6b92ffaSHans Petter Selasky p_remote_physp = p_physp->p_remote_physp;
253*d6b92ffaSHans Petter Selasky
254*d6b92ffaSHans Petter Selasky /*
255*d6b92ffaSHans Petter Selasky make sure that all the following occur on p_remote_physp:
256*d6b92ffaSHans Petter Selasky 1. The port isn't NULL
257*d6b92ffaSHans Petter Selasky 2. It is a switch
258*d6b92ffaSHans Petter Selasky */
259*d6b92ffaSHans Petter Selasky if (p_remote_physp && p_remote_physp->p_node->sw) {
260*d6b92ffaSHans Petter Selasky remote_u = p_remote_physp->p_node->sw->priv;
261*d6b92ffaSHans Petter Selasky port_guid = p_remote_physp->port_guid;
262*d6b92ffaSHans Petter Selasky
263*d6b92ffaSHans Petter Selasky if (remote_u->rank > u->rank + 1) {
264*d6b92ffaSHans Petter Selasky remote_u->rank = u->rank + 1;
265*d6b92ffaSHans Petter Selasky max_rank = remote_u->rank;
266*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&list,
267*d6b92ffaSHans Petter Selasky &remote_u->list);
268*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_DEBUG,
269*d6b92ffaSHans Petter Selasky "Rank of port GUID 0x%" PRIx64
270*d6b92ffaSHans Petter Selasky " = %u\n", cl_ntoh64(port_guid),
271*d6b92ffaSHans Petter Selasky remote_u->rank);
272*d6b92ffaSHans Petter Selasky }
273*d6b92ffaSHans Petter Selasky }
274*d6b92ffaSHans Petter Selasky }
275*d6b92ffaSHans Petter Selasky }
276*d6b92ffaSHans Petter Selasky
277*d6b92ffaSHans Petter Selasky /* Print Summary of ranking */
278*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_VERBOSE,
279*d6b92ffaSHans Petter Selasky "Subnet ranking completed. Max Node Rank = %d\n", max_rank);
280*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_log);
281*d6b92ffaSHans Petter Selasky return 0;
282*d6b92ffaSHans Petter Selasky }
283*d6b92ffaSHans Petter Selasky
284*d6b92ffaSHans Petter Selasky /* hack: preserve min hops entries to any other root switches */
updn_clear_non_root_hops(updn_t * updn,osm_switch_t * sw)285*d6b92ffaSHans Petter Selasky static void updn_clear_non_root_hops(updn_t * updn, osm_switch_t * sw)
286*d6b92ffaSHans Petter Selasky {
287*d6b92ffaSHans Petter Selasky osm_port_t *port;
288*d6b92ffaSHans Petter Selasky unsigned i;
289*d6b92ffaSHans Petter Selasky
290*d6b92ffaSHans Petter Selasky for (i = 0; i < sw->num_hops; i++)
291*d6b92ffaSHans Petter Selasky if (sw->hops[i]) {
292*d6b92ffaSHans Petter Selasky port = osm_get_port_by_lid_ho(&updn->p_osm->subn, i);
293*d6b92ffaSHans Petter Selasky if (!port || !port->p_node->sw
294*d6b92ffaSHans Petter Selasky || ((struct updn_node *)port->p_node->sw->priv)->
295*d6b92ffaSHans Petter Selasky rank != 0)
296*d6b92ffaSHans Petter Selasky memset(sw->hops[i], 0xff, sw->num_ports);
297*d6b92ffaSHans Petter Selasky }
298*d6b92ffaSHans Petter Selasky }
299*d6b92ffaSHans Petter Selasky
updn_set_min_hop_table(IN updn_t * p_updn)300*d6b92ffaSHans Petter Selasky static int updn_set_min_hop_table(IN updn_t * p_updn)
301*d6b92ffaSHans Petter Selasky {
302*d6b92ffaSHans Petter Selasky osm_subn_t *p_subn = &p_updn->p_osm->subn;
303*d6b92ffaSHans Petter Selasky osm_log_t *p_log = &p_updn->p_osm->log;
304*d6b92ffaSHans Petter Selasky osm_switch_t *p_sw;
305*d6b92ffaSHans Petter Selasky cl_map_item_t *item;
306*d6b92ffaSHans Petter Selasky
307*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_log);
308*d6b92ffaSHans Petter Selasky
309*d6b92ffaSHans Petter Selasky /* Go over all the switches in the subnet - for each init their Min Hop
310*d6b92ffaSHans Petter Selasky Table */
311*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_VERBOSE,
312*d6b92ffaSHans Petter Selasky "Init Min Hop Table of all switches [\n");
313*d6b92ffaSHans Petter Selasky
314*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
315*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
316*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
317*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *)item;
318*d6b92ffaSHans Petter Selasky /* Clear Min Hop Table */
319*d6b92ffaSHans Petter Selasky if (p_subn->opt.connect_roots)
320*d6b92ffaSHans Petter Selasky updn_clear_non_root_hops(p_updn, p_sw);
321*d6b92ffaSHans Petter Selasky else
322*d6b92ffaSHans Petter Selasky osm_switch_clear_hops(p_sw);
323*d6b92ffaSHans Petter Selasky }
324*d6b92ffaSHans Petter Selasky
325*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_VERBOSE,
326*d6b92ffaSHans Petter Selasky "Init Min Hop Table of all switches ]\n");
327*d6b92ffaSHans Petter Selasky
328*d6b92ffaSHans Petter Selasky /* Now do the BFS for each port in the subnet */
329*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_VERBOSE,
330*d6b92ffaSHans Petter Selasky "BFS through all port guids in the subnet [\n");
331*d6b92ffaSHans Petter Selasky
332*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
333*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
334*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
335*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *)item;
336*d6b92ffaSHans Petter Selasky updn_bfs_by_node(p_log, p_subn, p_sw);
337*d6b92ffaSHans Petter Selasky }
338*d6b92ffaSHans Petter Selasky
339*d6b92ffaSHans Petter Selasky OSM_LOG(p_log, OSM_LOG_VERBOSE,
340*d6b92ffaSHans Petter Selasky "BFS through all port guids in the subnet ]\n");
341*d6b92ffaSHans Petter Selasky /* Cleanup */
342*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_log);
343*d6b92ffaSHans Petter Selasky return 0;
344*d6b92ffaSHans Petter Selasky }
345*d6b92ffaSHans Petter Selasky
updn_build_lid_matrices(IN updn_t * p_updn)346*d6b92ffaSHans Petter Selasky static int updn_build_lid_matrices(IN updn_t * p_updn)
347*d6b92ffaSHans Petter Selasky {
348*d6b92ffaSHans Petter Selasky int status;
349*d6b92ffaSHans Petter Selasky
350*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(&p_updn->p_osm->log);
351*d6b92ffaSHans Petter Selasky
352*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE,
353*d6b92ffaSHans Petter Selasky "Ranking all port guids in the list\n");
354*d6b92ffaSHans Petter Selasky if (!p_updn->num_roots) {
355*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0A: "
356*d6b92ffaSHans Petter Selasky "No guids were provided or number of guids is 0\n");
357*d6b92ffaSHans Petter Selasky status = -1;
358*d6b92ffaSHans Petter Selasky goto _exit;
359*d6b92ffaSHans Petter Selasky }
360*d6b92ffaSHans Petter Selasky
361*d6b92ffaSHans Petter Selasky /* Check if it's not a switched subnet */
362*d6b92ffaSHans Petter Selasky if (cl_is_qmap_empty(&p_updn->p_osm->subn.sw_guid_tbl)) {
363*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0B: "
364*d6b92ffaSHans Petter Selasky "This is not a switched subnet, cannot perform UPDN algorithm\n");
365*d6b92ffaSHans Petter Selasky status = -1;
366*d6b92ffaSHans Petter Selasky goto _exit;
367*d6b92ffaSHans Petter Selasky }
368*d6b92ffaSHans Petter Selasky
369*d6b92ffaSHans Petter Selasky /* Rank the subnet switches */
370*d6b92ffaSHans Petter Selasky if (updn_subn_rank(p_updn)) {
371*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0E: "
372*d6b92ffaSHans Petter Selasky "Failed to assign ranks\n");
373*d6b92ffaSHans Petter Selasky status = -1;
374*d6b92ffaSHans Petter Selasky goto _exit;
375*d6b92ffaSHans Petter Selasky }
376*d6b92ffaSHans Petter Selasky
377*d6b92ffaSHans Petter Selasky /* After multiple ranking need to set Min Hop Table by UpDn algorithm */
378*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE,
379*d6b92ffaSHans Petter Selasky "Setting all switches' Min Hop Table\n");
380*d6b92ffaSHans Petter Selasky status = updn_set_min_hop_table(p_updn);
381*d6b92ffaSHans Petter Selasky
382*d6b92ffaSHans Petter Selasky _exit:
383*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(&p_updn->p_osm->log);
384*d6b92ffaSHans Petter Selasky return status;
385*d6b92ffaSHans Petter Selasky }
386*d6b92ffaSHans Petter Selasky
create_updn_node(osm_switch_t * sw)387*d6b92ffaSHans Petter Selasky static struct updn_node *create_updn_node(osm_switch_t * sw)
388*d6b92ffaSHans Petter Selasky {
389*d6b92ffaSHans Petter Selasky struct updn_node *u;
390*d6b92ffaSHans Petter Selasky
391*d6b92ffaSHans Petter Selasky u = malloc(sizeof(*u));
392*d6b92ffaSHans Petter Selasky if (!u)
393*d6b92ffaSHans Petter Selasky return NULL;
394*d6b92ffaSHans Petter Selasky memset(u, 0, sizeof(*u));
395*d6b92ffaSHans Petter Selasky u->sw = sw;
396*d6b92ffaSHans Petter Selasky u->id = cl_ntoh64(osm_node_get_node_guid(sw->p_node));
397*d6b92ffaSHans Petter Selasky u->rank = 0xffffffff;
398*d6b92ffaSHans Petter Selasky return u;
399*d6b92ffaSHans Petter Selasky }
400*d6b92ffaSHans Petter Selasky
delete_updn_node(struct updn_node * u)401*d6b92ffaSHans Petter Selasky static void delete_updn_node(struct updn_node *u)
402*d6b92ffaSHans Petter Selasky {
403*d6b92ffaSHans Petter Selasky u->sw->priv = NULL;
404*d6b92ffaSHans Petter Selasky free(u);
405*d6b92ffaSHans Petter Selasky }
406*d6b92ffaSHans Petter Selasky
407*d6b92ffaSHans Petter Selasky /* Find Root nodes automatically by Min Hop Table info */
updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn)408*d6b92ffaSHans Petter Selasky static void updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn)
409*d6b92ffaSHans Petter Selasky {
410*d6b92ffaSHans Petter Selasky osm_opensm_t *p_osm = p_updn->p_osm;
411*d6b92ffaSHans Petter Selasky osm_switch_t *p_sw;
412*d6b92ffaSHans Petter Selasky osm_port_t *p_port;
413*d6b92ffaSHans Petter Selasky osm_physp_t *p_physp;
414*d6b92ffaSHans Petter Selasky cl_map_item_t *item;
415*d6b92ffaSHans Petter Selasky double thd1, thd2;
416*d6b92ffaSHans Petter Selasky unsigned i, cas_num = 0;
417*d6b92ffaSHans Petter Selasky unsigned *cas_per_sw;
418*d6b92ffaSHans Petter Selasky uint16_t lid_ho;
419*d6b92ffaSHans Petter Selasky
420*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(&p_osm->log);
421*d6b92ffaSHans Petter Selasky
422*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
423*d6b92ffaSHans Petter Selasky "Current number of ports in the subnet is %d\n",
424*d6b92ffaSHans Petter Selasky cl_qmap_count(&p_osm->subn.port_guid_tbl));
425*d6b92ffaSHans Petter Selasky
426*d6b92ffaSHans Petter Selasky lid_ho = (uint16_t) cl_ptr_vector_get_size(&p_updn->p_osm->subn.port_lid_tbl) + 1;
427*d6b92ffaSHans Petter Selasky cas_per_sw = malloc(lid_ho * sizeof(*cas_per_sw));
428*d6b92ffaSHans Petter Selasky if (!cas_per_sw) {
429*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR AA14: "
430*d6b92ffaSHans Petter Selasky "cannot alloc mem for CAs per switch counter array\n");
431*d6b92ffaSHans Petter Selasky goto _exit;
432*d6b92ffaSHans Petter Selasky }
433*d6b92ffaSHans Petter Selasky memset(cas_per_sw, 0, lid_ho * sizeof(*cas_per_sw));
434*d6b92ffaSHans Petter Selasky
435*d6b92ffaSHans Petter Selasky /* Find the Maximum number of CAs (and routers) for histogram normalization */
436*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
437*d6b92ffaSHans Petter Selasky "Finding the number of CAs and storing them in cl_map\n");
438*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.port_guid_tbl);
439*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.port_guid_tbl);
440*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
441*d6b92ffaSHans Petter Selasky p_port = (osm_port_t *)item;
442*d6b92ffaSHans Petter Selasky if (!p_port->p_node->sw) {
443*d6b92ffaSHans Petter Selasky p_physp = p_port->p_physp->p_remote_physp;
444*d6b92ffaSHans Petter Selasky if (!p_physp || !p_physp->p_node->sw)
445*d6b92ffaSHans Petter Selasky continue;
446*d6b92ffaSHans Petter Selasky lid_ho = osm_node_get_base_lid(p_physp->p_node, 0);
447*d6b92ffaSHans Petter Selasky lid_ho = cl_ntoh16(lid_ho);
448*d6b92ffaSHans Petter Selasky cas_per_sw[lid_ho]++;
449*d6b92ffaSHans Petter Selasky cas_num++;
450*d6b92ffaSHans Petter Selasky }
451*d6b92ffaSHans Petter Selasky }
452*d6b92ffaSHans Petter Selasky
453*d6b92ffaSHans Petter Selasky thd1 = cas_num * 0.9;
454*d6b92ffaSHans Petter Selasky thd2 = cas_num * 0.05;
455*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
456*d6b92ffaSHans Petter Selasky "Found %u CAs and RTRs, %u SWs in the subnet. "
457*d6b92ffaSHans Petter Selasky "Thresholds are thd1 = %f && thd2 = %f\n",
458*d6b92ffaSHans Petter Selasky cas_num, cl_qmap_count(&p_osm->subn.sw_guid_tbl), thd1, thd2);
459*d6b92ffaSHans Petter Selasky
460*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
461*d6b92ffaSHans Petter Selasky "Passing through all switches to collect Min Hop info\n");
462*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
463*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
464*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
465*d6b92ffaSHans Petter Selasky unsigned hop_hist[IB_SUBNET_PATH_HOPS_MAX];
466*d6b92ffaSHans Petter Selasky uint16_t max_lid_ho;
467*d6b92ffaSHans Petter Selasky uint8_t hop_val;
468*d6b92ffaSHans Petter Selasky uint16_t numHopBarsOverThd1 = 0;
469*d6b92ffaSHans Petter Selasky uint16_t numHopBarsOverThd2 = 0;
470*d6b92ffaSHans Petter Selasky
471*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *) item;
472*d6b92ffaSHans Petter Selasky
473*d6b92ffaSHans Petter Selasky memset(hop_hist, 0, sizeof(hop_hist));
474*d6b92ffaSHans Petter Selasky
475*d6b92ffaSHans Petter Selasky max_lid_ho = p_sw->max_lid_ho;
476*d6b92ffaSHans Petter Selasky for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++)
477*d6b92ffaSHans Petter Selasky if (cas_per_sw[lid_ho]) {
478*d6b92ffaSHans Petter Selasky hop_val =
479*d6b92ffaSHans Petter Selasky osm_switch_get_least_hops(p_sw, lid_ho);
480*d6b92ffaSHans Petter Selasky if (hop_val >= IB_SUBNET_PATH_HOPS_MAX)
481*d6b92ffaSHans Petter Selasky continue;
482*d6b92ffaSHans Petter Selasky
483*d6b92ffaSHans Petter Selasky hop_hist[hop_val] += cas_per_sw[lid_ho];
484*d6b92ffaSHans Petter Selasky }
485*d6b92ffaSHans Petter Selasky
486*d6b92ffaSHans Petter Selasky /* Now recognize the spines by requiring one bar to be
487*d6b92ffaSHans Petter Selasky above 90% of the number of CAs and RTRs */
488*d6b92ffaSHans Petter Selasky for (i = 0; i < IB_SUBNET_PATH_HOPS_MAX; i++) {
489*d6b92ffaSHans Petter Selasky if (hop_hist[i] > thd1)
490*d6b92ffaSHans Petter Selasky numHopBarsOverThd1++;
491*d6b92ffaSHans Petter Selasky if (hop_hist[i] > thd2)
492*d6b92ffaSHans Petter Selasky numHopBarsOverThd2++;
493*d6b92ffaSHans Petter Selasky }
494*d6b92ffaSHans Petter Selasky
495*d6b92ffaSHans Petter Selasky /* If thd conditions are valid - rank the root node */
496*d6b92ffaSHans Petter Selasky if (numHopBarsOverThd1 == 1 && numHopBarsOverThd2 == 1) {
497*d6b92ffaSHans Petter Selasky OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
498*d6b92ffaSHans Petter Selasky "Ranking GUID 0x%" PRIx64 " as root node\n",
499*d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
500*d6b92ffaSHans Petter Selasky ((struct updn_node *)p_sw->priv)->rank = 0;
501*d6b92ffaSHans Petter Selasky p_updn->num_roots++;
502*d6b92ffaSHans Petter Selasky }
503*d6b92ffaSHans Petter Selasky }
504*d6b92ffaSHans Petter Selasky
505*d6b92ffaSHans Petter Selasky free(cas_per_sw);
506*d6b92ffaSHans Petter Selasky _exit:
507*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(&p_osm->log);
508*d6b92ffaSHans Petter Selasky return;
509*d6b92ffaSHans Petter Selasky }
510*d6b92ffaSHans Petter Selasky
dump_roots(cl_map_item_t * item,FILE * file,void * cxt)511*d6b92ffaSHans Petter Selasky static void dump_roots(cl_map_item_t *item, FILE *file, void *cxt)
512*d6b92ffaSHans Petter Selasky {
513*d6b92ffaSHans Petter Selasky osm_switch_t *sw = (osm_switch_t *)item;
514*d6b92ffaSHans Petter Selasky if (!((struct updn_node *)sw->priv)->rank)
515*d6b92ffaSHans Petter Selasky fprintf(file, "0x%" PRIx64 "\n",
516*d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(sw->p_node)));
517*d6b92ffaSHans Petter Selasky }
518*d6b92ffaSHans Petter Selasky
update_id(void * cxt,uint64_t guid,char * p)519*d6b92ffaSHans Petter Selasky static int update_id(void *cxt, uint64_t guid, char *p)
520*d6b92ffaSHans Petter Selasky {
521*d6b92ffaSHans Petter Selasky osm_opensm_t *osm = cxt;
522*d6b92ffaSHans Petter Selasky osm_switch_t *sw;
523*d6b92ffaSHans Petter Selasky uint64_t id;
524*d6b92ffaSHans Petter Selasky char *e;
525*d6b92ffaSHans Petter Selasky
526*d6b92ffaSHans Petter Selasky sw = osm_get_switch_by_guid(&osm->subn, cl_hton64(guid));
527*d6b92ffaSHans Petter Selasky if (!sw) {
528*d6b92ffaSHans Petter Selasky OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
529*d6b92ffaSHans Petter Selasky "switch with guid 0x%" PRIx64 " is not found\n", guid);
530*d6b92ffaSHans Petter Selasky return 0;
531*d6b92ffaSHans Petter Selasky }
532*d6b92ffaSHans Petter Selasky
533*d6b92ffaSHans Petter Selasky id = strtoull(p, &e, 0);
534*d6b92ffaSHans Petter Selasky if (*e && !isspace(*e)) {
535*d6b92ffaSHans Petter Selasky OSM_LOG(&osm->log, OSM_LOG_ERROR,
536*d6b92ffaSHans Petter Selasky "ERR AA05: cannot parse node id \'%s\'", p);
537*d6b92ffaSHans Petter Selasky return -1;
538*d6b92ffaSHans Petter Selasky }
539*d6b92ffaSHans Petter Selasky
540*d6b92ffaSHans Petter Selasky OSM_LOG(&osm->log, OSM_LOG_DEBUG,
541*d6b92ffaSHans Petter Selasky "update node 0x%" PRIx64 " id to 0x%" PRIx64 "\n", guid, id);
542*d6b92ffaSHans Petter Selasky
543*d6b92ffaSHans Petter Selasky ((struct updn_node *)sw->priv)->id = id;
544*d6b92ffaSHans Petter Selasky
545*d6b92ffaSHans Petter Selasky return 0;
546*d6b92ffaSHans Petter Selasky }
547*d6b92ffaSHans Petter Selasky
rank_root_node(void * cxt,uint64_t guid,char * p)548*d6b92ffaSHans Petter Selasky static int rank_root_node(void *cxt, uint64_t guid, char *p)
549*d6b92ffaSHans Petter Selasky {
550*d6b92ffaSHans Petter Selasky updn_t *updn = cxt;
551*d6b92ffaSHans Petter Selasky osm_switch_t *sw;
552*d6b92ffaSHans Petter Selasky
553*d6b92ffaSHans Petter Selasky sw = osm_get_switch_by_guid(&updn->p_osm->subn, cl_hton64(guid));
554*d6b92ffaSHans Petter Selasky if (!sw) {
555*d6b92ffaSHans Petter Selasky OSM_LOG(&updn->p_osm->log, OSM_LOG_VERBOSE,
556*d6b92ffaSHans Petter Selasky "switch with guid 0x%" PRIx64 " is not found\n", guid);
557*d6b92ffaSHans Petter Selasky return 0;
558*d6b92ffaSHans Petter Selasky }
559*d6b92ffaSHans Petter Selasky
560*d6b92ffaSHans Petter Selasky OSM_LOG(&updn->p_osm->log, OSM_LOG_DEBUG,
561*d6b92ffaSHans Petter Selasky "Ranking root port GUID 0x%" PRIx64 "\n", guid);
562*d6b92ffaSHans Petter Selasky
563*d6b92ffaSHans Petter Selasky ((struct updn_node *)sw->priv)->rank = 0;
564*d6b92ffaSHans Petter Selasky updn->num_roots++;
565*d6b92ffaSHans Petter Selasky
566*d6b92ffaSHans Petter Selasky return 0;
567*d6b92ffaSHans Petter Selasky }
568*d6b92ffaSHans Petter Selasky
569*d6b92ffaSHans Petter Selasky /* UPDN callback function */
updn_lid_matrices(void * ctx)570*d6b92ffaSHans Petter Selasky static int updn_lid_matrices(void *ctx)
571*d6b92ffaSHans Petter Selasky {
572*d6b92ffaSHans Petter Selasky updn_t *p_updn = ctx;
573*d6b92ffaSHans Petter Selasky cl_map_item_t *item;
574*d6b92ffaSHans Petter Selasky osm_switch_t *p_sw;
575*d6b92ffaSHans Petter Selasky int ret = 0;
576*d6b92ffaSHans Petter Selasky
577*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(&p_updn->p_osm->log);
578*d6b92ffaSHans Petter Selasky
579*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
580*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
581*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
582*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *)item;
583*d6b92ffaSHans Petter Selasky p_sw->priv = create_updn_node(p_sw);
584*d6b92ffaSHans Petter Selasky if (!p_sw->priv) {
585*d6b92ffaSHans Petter Selasky OSM_LOG(&(p_updn->p_osm->log), OSM_LOG_ERROR, "ERR AA0C: "
586*d6b92ffaSHans Petter Selasky "cannot create updn node\n");
587*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(&p_updn->p_osm->log);
588*d6b92ffaSHans Petter Selasky return -1;
589*d6b92ffaSHans Petter Selasky }
590*d6b92ffaSHans Petter Selasky }
591*d6b92ffaSHans Petter Selasky
592*d6b92ffaSHans Petter Selasky /* First setup root nodes */
593*d6b92ffaSHans Petter Selasky p_updn->num_roots = 0;
594*d6b92ffaSHans Petter Selasky
595*d6b92ffaSHans Petter Selasky if (p_updn->p_osm->subn.opt.root_guid_file) {
596*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
597*d6b92ffaSHans Petter Selasky "UPDN - Fetching root nodes from file \'%s\'\n",
598*d6b92ffaSHans Petter Selasky p_updn->p_osm->subn.opt.root_guid_file);
599*d6b92ffaSHans Petter Selasky
600*d6b92ffaSHans Petter Selasky ret = parse_node_map(p_updn->p_osm->subn.opt.root_guid_file,
601*d6b92ffaSHans Petter Selasky rank_root_node, p_updn);
602*d6b92ffaSHans Petter Selasky if (ret) {
603*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA02: "
604*d6b92ffaSHans Petter Selasky "cannot parse root guids file \'%s\'\n",
605*d6b92ffaSHans Petter Selasky p_updn->p_osm->subn.opt.root_guid_file);
606*d6b92ffaSHans Petter Selasky osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
607*d6b92ffaSHans Petter Selasky updn_find_root_nodes_by_min_hop(p_updn);
608*d6b92ffaSHans Petter Selasky } else if (p_updn->p_osm->subn.opt.connect_roots &&
609*d6b92ffaSHans Petter Selasky p_updn->num_roots > 1)
610*d6b92ffaSHans Petter Selasky osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
611*d6b92ffaSHans Petter Selasky } else {
612*d6b92ffaSHans Petter Selasky osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr);
613*d6b92ffaSHans Petter Selasky updn_find_root_nodes_by_min_hop(p_updn);
614*d6b92ffaSHans Petter Selasky }
615*d6b92ffaSHans Petter Selasky
616*d6b92ffaSHans Petter Selasky if (p_updn->p_osm->subn.opt.ids_guid_file) {
617*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
618*d6b92ffaSHans Petter Selasky "UPDN - update node ids from file \'%s\'\n",
619*d6b92ffaSHans Petter Selasky p_updn->p_osm->subn.opt.ids_guid_file);
620*d6b92ffaSHans Petter Selasky
621*d6b92ffaSHans Petter Selasky ret = parse_node_map(p_updn->p_osm->subn.opt.ids_guid_file,
622*d6b92ffaSHans Petter Selasky update_id, p_updn->p_osm);
623*d6b92ffaSHans Petter Selasky if (ret)
624*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA03: "
625*d6b92ffaSHans Petter Selasky "cannot parse node ids file \'%s\'\n",
626*d6b92ffaSHans Petter Selasky p_updn->p_osm->subn.opt.ids_guid_file);
627*d6b92ffaSHans Petter Selasky }
628*d6b92ffaSHans Petter Selasky
629*d6b92ffaSHans Petter Selasky /* Only if there are assigned root nodes do the algorithm, otherwise perform do nothing */
630*d6b92ffaSHans Petter Selasky if (p_updn->num_roots) {
631*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG,
632*d6b92ffaSHans Petter Selasky "activating UPDN algorithm\n");
633*d6b92ffaSHans Petter Selasky ret = updn_build_lid_matrices(p_updn);
634*d6b92ffaSHans Petter Selasky } else {
635*d6b92ffaSHans Petter Selasky OSM_LOG(&p_updn->p_osm->log, OSM_LOG_INFO,
636*d6b92ffaSHans Petter Selasky "disabling UPDN algorithm, no root nodes were found\n");
637*d6b92ffaSHans Petter Selasky ret = -1;
638*d6b92ffaSHans Petter Selasky }
639*d6b92ffaSHans Petter Selasky
640*d6b92ffaSHans Petter Selasky if (OSM_LOG_IS_ACTIVE_V2(&p_updn->p_osm->log, OSM_LOG_ROUTING))
641*d6b92ffaSHans Petter Selasky osm_dump_qmap_to_file(p_updn->p_osm, "opensm-updn-roots.dump",
642*d6b92ffaSHans Petter Selasky &p_updn->p_osm->subn.sw_guid_tbl,
643*d6b92ffaSHans Petter Selasky dump_roots, NULL);
644*d6b92ffaSHans Petter Selasky
645*d6b92ffaSHans Petter Selasky for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl);
646*d6b92ffaSHans Petter Selasky item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl);
647*d6b92ffaSHans Petter Selasky item = cl_qmap_next(item)) {
648*d6b92ffaSHans Petter Selasky p_sw = (osm_switch_t *) item;
649*d6b92ffaSHans Petter Selasky delete_updn_node(p_sw->priv);
650*d6b92ffaSHans Petter Selasky }
651*d6b92ffaSHans Petter Selasky
652*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(&p_updn->p_osm->log);
653*d6b92ffaSHans Petter Selasky return ret;
654*d6b92ffaSHans Petter Selasky }
655*d6b92ffaSHans Petter Selasky
updn_delete(void * context)656*d6b92ffaSHans Petter Selasky static void updn_delete(void *context)
657*d6b92ffaSHans Petter Selasky {
658*d6b92ffaSHans Petter Selasky free(context);
659*d6b92ffaSHans Petter Selasky }
660*d6b92ffaSHans Petter Selasky
osm_ucast_updn_setup(struct osm_routing_engine * r,osm_opensm_t * osm)661*d6b92ffaSHans Petter Selasky int osm_ucast_updn_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
662*d6b92ffaSHans Petter Selasky {
663*d6b92ffaSHans Petter Selasky updn_t *updn;
664*d6b92ffaSHans Petter Selasky
665*d6b92ffaSHans Petter Selasky updn = malloc(sizeof(updn_t));
666*d6b92ffaSHans Petter Selasky if (!updn)
667*d6b92ffaSHans Petter Selasky return -1;
668*d6b92ffaSHans Petter Selasky memset(updn, 0, sizeof(updn_t));
669*d6b92ffaSHans Petter Selasky
670*d6b92ffaSHans Petter Selasky updn->p_osm = osm;
671*d6b92ffaSHans Petter Selasky
672*d6b92ffaSHans Petter Selasky r->context = updn;
673*d6b92ffaSHans Petter Selasky r->destroy = updn_delete;
674*d6b92ffaSHans Petter Selasky r->build_lid_matrices = updn_lid_matrices;
675*d6b92ffaSHans Petter Selasky
676*d6b92ffaSHans Petter Selasky return 0;
677*d6b92ffaSHans Petter Selasky }
678