2 * Copyright (c) 2006,2007 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2008 Mellanox Technologies LTD. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 * Implementation of OpenSM unicast routing module which loads
38 * routes from the dump file
43 #endif /* HAVE_CONFIG_H */
49 #include <iba/ib_types.h>
50 #include <complib/cl_qmap.h>
51 #include <complib/cl_debug.h>
52 #include <opensm/osm_opensm.h>
53 #include <opensm/osm_switch.h>
54 #include <opensm/osm_log.h>
56 static uint16_t remap_lid(osm_opensm_t * p_osm, uint16_t lid, ib_net64_t guid)
59 uint16_t min_lid, max_lid;
62 p_port = osm_get_port_by_guid(&p_osm->subn, guid);
64 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
65 "cannot find port guid 0x%016" PRIx64
66 " , will use the same lid\n", cl_ntoh64(guid));
70 osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
71 if (min_lid <= lid && lid <= max_lid)
74 lmc = osm_port_get_lmc(p_port);
75 return min_lid + (lid & ((1 << lmc) - 1));
78 static void add_path(osm_opensm_t * p_osm,
79 osm_switch_t * p_sw, uint16_t lid, uint8_t port_num,
85 new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid;
86 old_port = osm_switch_get_port_by_lid(p_sw, new_lid);
87 if (old_port != OSM_NO_PATH && old_port != port_num) {
88 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
89 "LID collision is detected on switch "
90 "0x016%" PRIx64 ", will overwrite LID %u entry\n",
91 cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)),
95 p_sw->new_lft[new_lid] = port_num;
96 if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid &&
97 osm_get_switch_by_guid(&p_osm->subn, port_guid)))
98 osm_switch_count_path(p_sw, port_num);
100 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
101 "route 0x%04x(was 0x%04x) %u 0x%016" PRIx64
102 " is added to switch 0x%016" PRIx64 "\n",
103 new_lid, lid, port_num, cl_ntoh64(port_guid),
104 cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)));
107 static void add_lid_hops(osm_opensm_t * p_osm, osm_switch_t * p_sw,
108 uint16_t lid, ib_net64_t guid,
109 uint8_t hops[], unsigned len)
114 new_lid = guid ? remap_lid(p_osm, lid, guid) : lid;
115 if (len > p_sw->num_ports)
116 len = p_sw->num_ports;
118 for (i = 0; i < len; i++)
119 osm_switch_set_hops(p_sw, lid, i, hops[i]);
122 static int do_ucast_file_load(void *context)
127 ib_net64_t sw_guid, port_guid;
128 osm_opensm_t *p_osm = context;
134 file_name = p_osm->subn.opt.lfts_file;
136 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
137 "LFTs file name is not given; "
138 "using default routing algorithm\n");
142 file = fopen(file_name, "r");
144 OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6302: "
145 "cannot open ucast dump file \'%s\': %m\n", file_name);
152 while (fgets(line, sizeof(line) - 1, file) != NULL) {
163 if (!strncmp(p, "Multicast mlids", 15)) {
164 OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS,
166 "Multicast dump file detected; "
167 "skipping parsing. Using default "
168 "routing algorithm\n");
169 } else if (!strncmp(p, "Unicast lids", 12)) {
171 osm_ucast_mgr_set_fwd_table(&p_osm->sm.
173 q = strstr(p, " guid 0x");
175 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
176 "PARSE ERROR: %s:%u: "
177 "cannot parse switch definition\n",
182 sw_guid = strtoull(p, &q, 16);
183 if (q == p || !isspace(*q)) {
184 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
185 "PARSE ERROR: %s:%u: "
186 "cannot parse switch guid: \'%s\'\n",
187 file_name, lineno, p);
190 sw_guid = cl_hton64(sw_guid);
192 p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid);
194 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
195 "cannot find switch %016" PRIx64 "\n",
199 memset(p_sw->new_lft, OSM_NO_PATH,
200 IB_LID_UCAST_END_HO + 1);
201 } else if (p_sw && !strncmp(p, "0x", 2)) {
203 lid = (uint16_t) strtoul(p, &q, 16);
204 if (q == p || !isspace(*q)) {
205 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
206 "PARSE ERROR: %s:%u: "
207 "cannot parse lid: \'%s\'\n",
208 file_name, lineno, p);
214 port_num = (uint8_t) strtoul(p, &q, 10);
215 if (q == p || !isspace(*q)) {
216 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
217 "PARSE ERROR: %s:%u: "
218 "cannot parse port: \'%s\'\n",
219 file_name, lineno, p);
223 /* additionally try to exract guid */
224 q = strstr(p, " portguid 0x");
226 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
227 "PARSE WARNING: %s:%u: "
228 "cannot find port guid "
229 "(maybe broken dump): \'%s\'\n",
230 file_name, lineno, p);
234 port_guid = strtoull(p, &q, 16);
235 if (q == p || (!isspace(*q) && *q != ':')) {
236 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
237 "PARSE WARNING: %s:%u: "
238 "cannot parse port guid "
239 "(maybe broken dump): \'%s\'\n",
240 file_name, lineno, p);
244 port_guid = cl_hton64(port_guid);
245 add_path(p_osm, p_sw, lid, port_num, port_guid);
250 osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
256 static int do_lid_matrix_file_load(void *context)
263 osm_opensm_t *p_osm = context;
268 file_name = p_osm->subn.opt.lid_matrix_dump_file;
270 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
271 "lid matrix file name is not given; "
272 "using default lid matrix generation algorithm\n");
276 file = fopen(file_name, "r");
278 OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6305: "
279 "cannot open lid matrix file \'%s\': %m\n", file_name);
286 while (fgets(line, sizeof(line) - 1, file) != NULL) {
297 if (!strncmp(p, "Switch", 6)) {
298 q = strstr(p, " guid 0x");
300 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
301 "PARSE ERROR: %s:%u: "
302 "cannot parse switch definition\n",
307 guid = strtoull(p, &q, 16);
308 if (q == p || !isspace(*q)) {
309 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
310 "PARSE ERROR: %s:%u: "
311 "cannot parse switch guid: \'%s\'\n",
312 file_name, lineno, p);
315 guid = cl_hton64(guid);
317 p_sw = osm_get_switch_by_guid(&p_osm->subn, guid);
319 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
320 "cannot find switch %016" PRIx64 "\n",
324 } else if (p_sw && !strncmp(p, "0x", 2)) {
328 memset(hops, 0xff, sizeof(hops));
331 num = strtoul(p, &q, 16);
332 if (num > 0xffff || q == p ||
333 (*q != ':' && !isspace(*q))) {
334 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
335 "PARSE ERROR: %s:%u: "
336 "cannot parse lid: \'%s\'\n",
337 file_name, lineno, p);
340 /* Just checked the range, so casting is safe */
341 lid = (uint16_t) num;
343 while (isspace(*p) || *p == ':')
345 while (len < 256 && *p && *p != '#') {
346 num = strtoul(p, &q, 16);
347 if (num > 0xff || q == p) {
348 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
349 "PARSE ERROR: %s:%u: "
350 "cannot parse hops number: \'%s\'\n",
351 file_name, lineno, p);
354 /* Just checked the range, so casting is safe */
355 hops[len++] = (uint8_t) num;
360 /* additionally try to extract guid */
361 q = strstr(p, " portguid 0x");
363 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
364 "PARSE WARNING: %s:%u: "
365 "cannot find port guid "
366 "(maybe broken dump): \'%s\'\n",
367 file_name, lineno, p);
371 guid = strtoull(p, &q, 16);
372 if (q == p || !isspace(*q)) {
373 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
374 "PARSE WARNING: %s:%u: "
375 "cannot parse port guid "
376 "(maybe broken dump): \'%s\'\n",
377 file_name, lineno, p);
381 guid = cl_hton64(guid);
382 add_lid_hops(p_osm, p_sw, lid, guid, hops, len);
390 int osm_ucast_file_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
393 r->build_lid_matrices = do_lid_matrix_file_load;
394 r->ucast_build_fwd_tables = do_ucast_file_load;