]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/opensm/osm_ucast_file.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / opensm / osm_ucast_file.c
1 /*
2  * Copyright (c) 2006,2007 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2008      Mellanox Technologies LTD. All rights reserved.
4  *
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:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
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.
23  *
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
31  * SOFTWARE.
32  *
33  */
34
35 /*
36  * Abstract:
37  *    Implementation of OpenSM unicast routing module which loads
38  *    routes from the dump file
39  */
40
41 #if HAVE_CONFIG_H
42 #  include <config.h>
43 #endif                          /* HAVE_CONFIG_H */
44
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
48
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>
55
56 static uint16_t remap_lid(osm_opensm_t * p_osm, uint16_t lid, ib_net64_t guid)
57 {
58         osm_port_t *p_port;
59         uint16_t min_lid, max_lid;
60         uint8_t lmc;
61
62         p_port = osm_get_port_by_guid(&p_osm->subn, guid);
63         if (!p_port) {
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));
67                 return lid;
68         }
69
70         osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid);
71         if (min_lid <= lid && lid <= max_lid)
72                 return lid;
73
74         lmc = osm_port_get_lmc(p_port);
75         return min_lid + (lid & ((1 << lmc) - 1));
76 }
77
78 static void add_path(osm_opensm_t * p_osm,
79                      osm_switch_t * p_sw, uint16_t lid, uint8_t port_num,
80                      ib_net64_t port_guid)
81 {
82         uint16_t new_lid;
83         uint8_t old_port;
84
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)),
92                         new_lid);
93         }
94
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);
99
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)));
105 }
106
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)
110 {
111         uint16_t new_lid;
112         uint8_t i;
113
114         new_lid = guid ? remap_lid(p_osm, lid, guid) : lid;
115         if (len > p_sw->num_ports)
116                 len = p_sw->num_ports;
117
118         for (i = 0; i < len; i++)
119                 osm_switch_set_hops(p_sw, lid, i, hops[i]);
120 }
121
122 static int do_ucast_file_load(void *context)
123 {
124         char line[1024];
125         char *file_name;
126         FILE *file;
127         ib_net64_t sw_guid, port_guid;
128         osm_opensm_t *p_osm = context;
129         osm_switch_t *p_sw;
130         uint16_t lid;
131         uint8_t port_num;
132         unsigned lineno;
133
134         file_name = p_osm->subn.opt.lfts_file;
135         if (!file_name) {
136                 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
137                         "LFTs file name is not given; "
138                         "using default routing algorithm\n");
139                 return 1;
140         }
141
142         file = fopen(file_name, "r");
143         if (!file) {
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);
146                 return -1;
147         }
148
149         lineno = 0;
150         p_sw = NULL;
151
152         while (fgets(line, sizeof(line) - 1, file) != NULL) {
153                 char *p, *q;
154                 lineno++;
155
156                 p = line;
157                 while (isspace(*p))
158                         p++;
159
160                 if (*p == '#')
161                         continue;
162
163                 if (!strncmp(p, "Multicast mlids", 15)) {
164                         OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS,
165                                 "ERR 6303: "
166                                 "Multicast dump file detected; "
167                                 "skipping parsing. Using default "
168                                 "routing algorithm\n");
169                 } else if (!strncmp(p, "Unicast lids", 12)) {
170                         if (p_sw)
171                                 osm_ucast_mgr_set_fwd_table(&p_osm->sm.
172                                                             ucast_mgr, p_sw);
173                         q = strstr(p, " guid 0x");
174                         if (!q) {
175                                 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
176                                         "PARSE ERROR: %s:%u: "
177                                         "cannot parse switch definition\n",
178                                         file_name, lineno);
179                                 return -1;
180                         }
181                         p = q + 8;
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);
188                                 return -1;
189                         }
190                         sw_guid = cl_hton64(sw_guid);
191
192                         p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid);
193                         if (!p_sw) {
194                                 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
195                                         "cannot find switch %016" PRIx64 "\n",
196                                         cl_ntoh64(sw_guid));
197                                 continue;
198                         }
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)) {
202                         p += 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);
209                                 return -1;
210                         }
211                         p = q;
212                         while (isspace(*p))
213                                 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);
220                                 return -1;
221                         }
222                         p = q;
223                         /* additionally try to exract guid */
224                         q = strstr(p, " portguid 0x");
225                         if (!q) {
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);
231                                 port_guid = 0;
232                         } else {
233                                 p = q + 12;
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);
241                                         port_guid = 0;
242                                 }
243                         }
244                         port_guid = cl_hton64(port_guid);
245                         add_path(p_osm, p_sw, lid, port_num, port_guid);
246                 }
247         }
248
249         if (p_sw)
250                 osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
251
252         fclose(file);
253         return 0;
254 }
255
256 static int do_lid_matrix_file_load(void *context)
257 {
258         char line[1024];
259         uint8_t hops[256];
260         char *file_name;
261         FILE *file;
262         ib_net64_t guid;
263         osm_opensm_t *p_osm = context;
264         osm_switch_t *p_sw;
265         unsigned lineno;
266         uint16_t lid;
267
268         file_name = p_osm->subn.opt.lid_matrix_dump_file;
269         if (!file_name) {
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");
273                 return 1;
274         }
275
276         file = fopen(file_name, "r");
277         if (!file) {
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);
280                 return -1;
281         }
282
283         lineno = 0;
284         p_sw = NULL;
285
286         while (fgets(line, sizeof(line) - 1, file) != NULL) {
287                 char *p, *q;
288                 lineno++;
289
290                 p = line;
291                 while (isspace(*p))
292                         p++;
293
294                 if (*p == '#')
295                         continue;
296
297                 if (!strncmp(p, "Switch", 6)) {
298                         q = strstr(p, " guid 0x");
299                         if (!q) {
300                                 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
301                                         "PARSE ERROR: %s:%u: "
302                                         "cannot parse switch definition\n",
303                                         file_name, lineno);
304                                 return -1;
305                         }
306                         p = q + 8;
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);
313                                 return -1;
314                         }
315                         guid = cl_hton64(guid);
316
317                         p_sw = osm_get_switch_by_guid(&p_osm->subn, guid);
318                         if (!p_sw) {
319                                 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
320                                         "cannot find switch %016" PRIx64 "\n",
321                                         cl_ntoh64(guid));
322                                 continue;
323                         }
324                 } else if (p_sw && !strncmp(p, "0x", 2)) {
325                         unsigned long num;
326                         unsigned len = 0;
327
328                         memset(hops, 0xff, sizeof(hops));
329
330                         p += 2;
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);
338                                 return -1;
339                         }
340                         /* Just checked the range, so casting is safe */
341                         lid = (uint16_t) num;
342                         p = q;
343                         while (isspace(*p) || *p == ':')
344                                 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);
352                                         return -1;
353                                 }
354                                 /* Just checked the range, so casting is safe */
355                                 hops[len++] = (uint8_t) num;
356                                 p = q;
357                                 while (isspace(*p))
358                                         p++;
359                         }
360                         /* additionally try to extract guid */
361                         q = strstr(p, " portguid 0x");
362                         if (!q) {
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);
368                                 guid = 0;
369                         } else {
370                                 p = q + 12;
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);
378                                         guid = 0;
379                                 }
380                         }
381                         guid = cl_hton64(guid);
382                         add_lid_hops(p_osm, p_sw, lid, guid, hops, len);
383                 }
384         }
385
386         fclose(file);
387         return 0;
388 }
389
390 int osm_ucast_file_setup(struct osm_routing_engine *r, osm_opensm_t *osm)
391 {
392         r->context = osm;
393         r->build_lid_matrices = do_lid_matrix_file_load;
394         r->ucast_build_fwd_tables = do_ucast_file_load;
395         return 0;
396 }