]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/opensm/osm_subnet.c
MFV r354382,r354385: 10601 10757 Pool allocation classes
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / opensm / osm_subnet.c
1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
6  * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
7  * Copyright (c) 2009 HNR Consulting. All rights reserved.
8  * Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
9  * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
10  *
11  * This software is available to you under a choice of one of two
12  * licenses.  You may choose to be licensed under the terms of the GNU
13  * General Public License (GPL) Version 2, available from the file
14  * COPYING in the main directory of this source tree, or the
15  * OpenIB.org BSD license below:
16  *
17  *     Redistribution and use in source and binary forms, with or
18  *     without modification, are permitted provided that the following
19  *     conditions are met:
20  *
21  *      - Redistributions of source code must retain the above
22  *        copyright notice, this list of conditions and the following
23  *        disclaimer.
24  *
25  *      - Redistributions in binary form must reproduce the above
26  *        copyright notice, this list of conditions and the following
27  *        disclaimer in the documentation and/or other materials
28  *        provided with the distribution.
29  *
30  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
34  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
35  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
36  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37  * SOFTWARE.
38  *
39  */
40
41 /*
42  * Abstract:
43  *    Implementation of osm_subn_t.
44  * This object represents an IBA subnet.
45  * This object is part of the opensm family of objects.
46  */
47
48 #if HAVE_CONFIG_H
49 #  include <config.h>
50 #endif                          /* HAVE_CONFIG_H */
51
52 #include <string.h>
53 #include <stdio.h>
54 #include <stdarg.h>
55 #include <limits.h>
56 #include <errno.h>
57 #include <ctype.h>
58 #include <complib/cl_debug.h>
59 #include <complib/cl_log.h>
60 #include <opensm/osm_file_ids.h>
61 #define FILE_ID OSM_FILE_SUBNET_C
62 #include <opensm/osm_subnet.h>
63 #include <opensm/osm_opensm.h>
64 #include <opensm/osm_log.h>
65 #include <opensm/osm_madw.h>
66 #include <opensm/osm_port.h>
67 #include <opensm/osm_switch.h>
68 #include <opensm/osm_remote_sm.h>
69 #include <opensm/osm_partition.h>
70 #include <opensm/osm_node.h>
71 #include <opensm/osm_guid.h>
72 #include <opensm/osm_multicast.h>
73 #include <opensm/osm_inform.h>
74 #include <opensm/osm_console.h>
75 #include <opensm/osm_perfmgr.h>
76 #include <opensm/osm_congestion_control.h>
77 #include <opensm/osm_event_plugin.h>
78 #include <opensm/osm_qos_policy.h>
79 #include <opensm/osm_service.h>
80 #include <opensm/osm_db.h>
81 #include <opensm/osm_db_pack.h>
82
83 static const char null_str[] = "(null)";
84
85 #define OPT_OFFSET(opt) offsetof(osm_subn_opt_t, opt)
86 #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
87
88 typedef struct opt_rec {
89         const char *name;
90         unsigned long opt_offset;
91         void (*parse_fn)(osm_subn_t *p_subn, char *p_key, char *p_val_str,
92                          void *p_val1, void *p_val2,
93                          void (*)(osm_subn_t *, void *));
94         void (*setup_fn)(osm_subn_t *p_subn, void *p_val);
95         int  can_update;
96 } opt_rec_t;
97
98 static const char *module_name_str[] = {
99         "main.c",
100         "osm_console.c",
101         "osm_console_io.c",
102         "osm_db_files.c",
103         "osm_db_pack.c",
104         "osm_drop_mgr.c",
105         "osm_dump.c",
106         "osm_event_plugin.c",
107         "osm_guid_info_rcv.c",
108         "osm_guid_mgr.c",
109         "osm_helper.c",
110         "osm_inform.c",
111         "osm_lid_mgr.c",
112         "osm_lin_fwd_rcv.c",
113         "osm_link_mgr.c",
114         "osm_log.c",
115         "osm_mad_pool.c",
116         "osm_mcast_fwd_rcv.c",
117         "osm_mcast_mgr.c",
118         "osm_mcast_tbl.c",
119         "osm_mcm_port.c",
120         "osm_mesh.c",
121         "osm_mlnx_ext_port_info_rcv.c",
122         "osm_mtree.c",
123         "osm_multicast.c",
124         "osm_node.c",
125         "osm_node_desc_rcv.c",
126         "osm_node_info_rcv.c",
127         "osm_opensm.c",
128         "osm_perfmgr.c",
129         "osm_perfmgr_db.c",
130         "osm_pkey.c",
131         "osm_pkey_mgr.c",
132         "osm_pkey_rcv.c",
133         "osm_port.c",
134         "osm_port_info_rcv.c",
135         "osm_prtn.c",
136         "osm_prtn_config.c",
137         "osm_qos.c",
138         "osm_qos_parser_l.c",
139         "osm_qos_parser_y.c",
140         "osm_qos_policy.c",
141         "osm_remote_sm.c",
142         "osm_req.c",
143         "osm_resp.c",
144         "osm_router.c",
145         "osm_sa.c",
146         "osm_sa_class_port_info.c",
147         "osm_sa_guidinfo_record.c",
148         "osm_sa_informinfo.c",
149         "osm_sa_lft_record.c",
150         "osm_sa_link_record.c",
151         "osm_sa_mad_ctrl.c",
152         "osm_sa_mcmember_record.c",
153         "osm_sa_mft_record.c",
154         "osm_sa_multipath_record.c",
155         "osm_sa_node_record.c",
156         "osm_sa_path_record.c",
157         "osm_sa_pkey_record.c",
158         "osm_sa_portinfo_record.c",
159         "osm_sa_service_record.c",
160         "osm_sa_slvl_record.c",
161         "osm_sa_sminfo_record.c",
162         "osm_sa_sw_info_record.c",
163         "osm_sa_vlarb_record.c",
164         "osm_service.c",
165         "osm_slvl_map_rcv.c",
166         "osm_sm.c",
167         "osm_sminfo_rcv.c",
168         "osm_sm_mad_ctrl.c",
169         "osm_sm_state_mgr.c",
170         "osm_state_mgr.c",
171         "osm_subnet.c",
172         "osm_sw_info_rcv.c",
173         "osm_switch.c",
174         "osm_torus.c",
175         "osm_trap_rcv.c",
176         "osm_ucast_cache.c",
177         "osm_ucast_dnup.c",
178         "osm_ucast_file.c",
179         "osm_ucast_ftree.c",
180         "osm_ucast_lash.c",
181         "osm_ucast_mgr.c",
182         "osm_ucast_updn.c",
183         "osm_vendor_ibumad.c",
184         "osm_vl15intf.c",
185         "osm_vl_arb_rcv.c",
186         "st.c",
187         "osm_ucast_dfsssp.c",
188         "osm_congestion_control.c",
189         /* Add new module names here ... */
190         /* FILE_ID define in those modules must be identical to index here */
191         /* last FILE_ID is currently 89 */
192 };
193
194 #define MOD_NAME_STR_UNKNOWN_VAL (ARR_SIZE(module_name_str))
195
196 static int find_module_name(const char *name, uint8_t *file_id)
197 {
198         uint8_t i;
199
200         for (i = 0; i < MOD_NAME_STR_UNKNOWN_VAL; i++) {
201                 if (strcmp(name, module_name_str[i]) == 0) {
202                         if (file_id)
203                                 *file_id = i;
204                         return 0;
205                 }
206         }
207         return 1;
208 }
209
210 static void log_report(const char *fmt, ...)
211 {
212         char buf[128];
213         va_list args;
214         va_start(args, fmt);
215         vsnprintf(buf, sizeof(buf), fmt, args);
216         va_end(args);
217         printf("%s", buf);
218         cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
219 }
220
221 static void log_config_value(char *name, const char *fmt, ...)
222 {
223         char buf[128];
224         va_list args;
225         unsigned n;
226         va_start(args, fmt);
227         n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name);
228         if (n > sizeof(buf))
229                 n = sizeof(buf);
230         n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args);
231         if (n > sizeof(buf) - 2)
232                 n = sizeof(buf) - 2;
233         snprintf(buf + n, sizeof(buf) - n, "\n");
234         va_end(args);
235         printf("%s", buf);
236         cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
237 }
238
239 static void opts_setup_log_flags(osm_subn_t *p_subn, void *p_val)
240 {
241         p_subn->p_osm->log.level = *((uint8_t *) p_val);
242 }
243
244 static void opts_setup_force_log_flush(osm_subn_t *p_subn, void *p_val)
245 {
246         p_subn->p_osm->log.flush = *((boolean_t *) p_val);
247 }
248
249 static void opts_setup_accum_log_file(osm_subn_t *p_subn, void *p_val)
250 {
251         p_subn->p_osm->log.accum_log_file = *((boolean_t *) p_val);
252 }
253
254 static void opts_setup_log_max_size(osm_subn_t *p_subn, void *p_val)
255 {
256         uint32_t log_max_size = *((uint32_t *) p_val);
257
258         p_subn->p_osm->log.max_size = (unsigned long)log_max_size << 20; /* convert from MB to bytes */
259 }
260
261 static void opts_setup_sminfo_polling_timeout(osm_subn_t *p_subn, void *p_val)
262 {
263         osm_sm_t *p_sm = &p_subn->p_osm->sm;
264         uint32_t sminfo_polling_timeout = *((uint32_t *) p_val);
265
266         cl_timer_stop(&p_sm->polling_timer);
267         cl_timer_start(&p_sm->polling_timer, sminfo_polling_timeout);
268 }
269
270 static void opts_setup_sm_priority(osm_subn_t *p_subn, void *p_val)
271 {
272         osm_sm_t *p_sm = &p_subn->p_osm->sm;
273         uint8_t sm_priority = *((uint8_t *) p_val);
274
275         osm_set_sm_priority(p_sm, sm_priority);
276 }
277
278 static int opts_strtoul(uint32_t *val, IN char *p_val_str,
279                         IN char *p_key, uint32_t max_value)
280 {
281         char *endptr;
282         unsigned long int tmp_val;
283
284         errno = 0;
285         tmp_val = strtoul(p_val_str, &endptr, 0);
286         *val = tmp_val;
287         if (*p_val_str == '\0' || *endptr != '\0') {
288                 log_report("-E- Parsing error in field %s, expected "
289                            "numeric input received: %s\n", p_key, p_val_str);
290                 return -1;
291         }
292         if (tmp_val > max_value ||
293             ((tmp_val == ULONG_MAX) && errno == ERANGE)) {
294                 log_report("-E- Parsing error in field %s, value out of range\n", p_key);
295                 return -1;
296         }
297         return 0;
298 }
299
300 static int opts_strtoull(uint64_t *val, IN char *p_val_str,
301                          IN char *p_key, uint64_t max_value)
302 {
303         char *endptr;
304         unsigned long long int tmp_val;
305
306         errno = 0;
307         tmp_val = strtoull(p_val_str, &endptr, 0);
308         *val = tmp_val;
309         if (*p_val_str == '\0' || *endptr != '\0') {
310                 log_report("-E- Parsing error in field %s, expected "
311                            "numeric input received: %s\n", p_key, p_val_str);
312                 return -1;
313         }
314         if (tmp_val > max_value || (tmp_val == ULLONG_MAX && errno == ERANGE)) {
315                 log_report("-E- Parsing error in field %s, value out of range\n", p_key);
316                 return -1;
317         }
318         return 0;
319 }
320
321 static void opts_parse_net64(IN osm_subn_t *p_subn, IN char *p_key,
322                              IN char *p_val_str, void *p_v1, void *p_v2,
323                              void (*pfn)(osm_subn_t *, void *))
324 {
325         uint64_t *p_val1 = p_v1, *p_val2 = p_v2;
326         uint64_t val;
327
328         if (opts_strtoull(&val, p_val_str, p_key, UINT64_MAX))
329                 return;
330
331         if (cl_hton64(val) != *p_val1) {
332                 log_config_value(p_key, "0x%016" PRIx64, val);
333                 if (pfn)
334                         pfn(p_subn, &val);
335                 *p_val1 = *p_val2 = cl_ntoh64(val);
336         }
337 }
338
339 static void opts_parse_uint32(IN osm_subn_t *p_subn, IN char *p_key,
340                               IN char *p_val_str, void *p_v1, void *p_v2,
341                               void (*pfn)(osm_subn_t *, void *))
342 {
343         uint32_t *p_val1 = p_v1, *p_val2 = p_v2;
344         uint32_t val;
345
346         if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX))
347                 return;
348
349         if (val != *p_val1) {
350                 log_config_value(p_key, "%u", val);
351                 if (pfn)
352                         pfn(p_subn, &val);
353                 *p_val1 = *p_val2 = val;
354         }
355 }
356
357 static void opts_parse_net32(IN osm_subn_t *p_subn, IN char *p_key,
358                              IN char *p_val_str, void *p_v1, void *p_v2,
359                              void (*pfn)(osm_subn_t *, void *))
360 {
361         uint32_t *p_val1 = p_v1, *p_val2 = p_v2;
362         uint32_t val;
363
364         if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX))
365                 return;
366
367         if (cl_hton32(val) != *p_val1) {
368                 log_config_value(p_key, "%u", val);
369                 if (pfn)
370                         pfn(p_subn, &val);
371                 *p_val1 = *p_val2 = cl_hton32(val);
372         }
373 }
374
375 static void opts_parse_int32(IN osm_subn_t *p_subn, IN char *p_key,
376                              IN char *p_val_str, void *p_v1, void *p_v2,
377                              void (*pfn)(osm_subn_t *, void *))
378 {
379         int32_t *p_val1 = p_v1, *p_val2 = p_v2;
380         int32_t val = strtol(p_val_str, NULL, 0);
381
382         if (val != *p_val1) {
383                 log_config_value(p_key, "%d", val);
384                 if (pfn)
385                         pfn(p_subn, &val);
386                 *p_val1 = *p_val2 = val;
387         }
388 }
389
390 static void opts_parse_uint16(IN osm_subn_t *p_subn, IN char *p_key,
391                               IN char *p_val_str, void *p_v1, void *p_v2,
392                               void (*pfn)(osm_subn_t *, void *))
393 {
394         uint16_t *p_val1 = p_v1, *p_val2 = p_v2;
395         uint32_t tmp_val;
396
397         if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX))
398                 return;
399
400         uint16_t val = (uint16_t) tmp_val;
401         if (val != *p_val1) {
402                 log_config_value(p_key, "%u", val);
403                 if (pfn)
404                         pfn(p_subn, &val);
405                 *p_val1 = *p_val2 = val;
406         }
407 }
408
409 static void opts_parse_net16(IN osm_subn_t *p_subn, IN char *p_key,
410                              IN char *p_val_str, void *p_v1, void *p_v2,
411                              void (*pfn)(osm_subn_t *, void *))
412 {
413         uint16_t *p_val1 = p_v1, *p_val2 = p_v2;
414         uint32_t tmp_val;
415
416         if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX))
417                 return;
418
419         uint16_t val = (uint16_t) tmp_val;
420         if (cl_hton16(val) != *p_val1) {
421                 log_config_value(p_key, "0x%04x", val);
422                 if (pfn)
423                         pfn(p_subn, &val);
424                 *p_val1 = *p_val2 = cl_hton16(val);
425         }
426 }
427
428 static void opts_parse_uint8(IN osm_subn_t *p_subn, IN char *p_key,
429                              IN char *p_val_str, void *p_v1, void *p_v2,
430                              void (*pfn)(osm_subn_t *, void *))
431 {
432         uint8_t *p_val1 = p_v1, *p_val2 = p_v2;
433         uint32_t tmp_val;
434
435         if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT8_MAX))
436                 return;
437
438         uint8_t val = (uint8_t) tmp_val;
439         if (val != *p_val1) {
440                 log_config_value(p_key, "%u", val);
441                 if (pfn)
442                         pfn(p_subn, &val);
443                 *p_val1 = *p_val2 = val;
444         }
445 }
446
447 static void opts_parse_boolean(IN osm_subn_t *p_subn, IN char *p_key,
448                                IN char *p_val_str, void *p_v1, void *p_v2,
449                                void (*pfn)(osm_subn_t *, void *))
450 {
451         boolean_t *p_val1 = p_v1, *p_val2 = p_v2;
452         boolean_t val;
453
454         if (!p_val_str)
455                 return;
456
457         if (strcmp("TRUE", p_val_str))
458                 val = FALSE;
459         else
460                 val = TRUE;
461
462         if (val != *p_val1) {
463                 log_config_value(p_key, "%s", p_val_str);
464                 if (pfn)
465                         pfn(p_subn, &val);
466                 *p_val1 = *p_val2 = val;
467         }
468 }
469
470 static void opts_parse_charp(IN osm_subn_t *p_subn, IN char *p_key,
471                              IN char *p_val_str, void *p_v1, void *p_v2,
472                              void (*pfn)(osm_subn_t *, void *))
473 {
474         char **p_val1 = p_v1, **p_val2 = p_v2;
475         const char *current_str = *p_val1 ? *p_val1 : null_str;
476
477         if (p_val_str && strcmp(p_val_str, current_str)) {
478                 char *new;
479                 log_config_value(p_key, "%s", p_val_str);
480                 /* special case the "(null)" string */
481                 new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL;
482                 if (pfn)
483                         pfn(p_subn, new);
484                 if (*p_val1 && *p_val1 != *p_val2)
485                         free(*p_val1);
486                 if (*p_val2)
487                         free(*p_val2);
488                 *p_val1 = *p_val2 = new;
489         }
490 }
491
492 static void opts_parse_256bit(IN osm_subn_t *p_subn, IN char *p_key,
493                               IN char *p_val_str, void *p_v1, void *p_v2,
494                               void (*pfn)(osm_subn_t *, void *))
495 {
496         uint8_t *p_val1 = p_v1, *p_val2 = p_v2;
497         uint8_t val[IB_CC_PORT_MASK_DATA_SIZE] = { 0 };
498         char tmpbuf[3] = { 0 };
499         uint8_t tmpint;
500         int numdigits = 0;
501         int startindex;
502         char *strptr = p_val_str;
503         char *ptr;
504         int i;
505
506         /* parse like it's hypothetically a 256 bit integer code
507          *
508          * store "big endian"
509          */
510
511         if (!strncmp(strptr, "0x", 2) || !strncmp(strptr, "0X", 2))
512                 strptr+=2;
513
514         for (ptr = strptr; *ptr; ptr++) {
515                 if (!isxdigit(*ptr)) {
516                         log_report("invalid hex digit in bitmask\n");
517                         return;
518                 }
519                 numdigits++;
520         }
521
522         if (!numdigits) {
523                 log_report("invalid length bitmask\n");
524                 return;
525         }
526
527         /* max of 2 hex chars per byte */
528         if (numdigits > IB_CC_PORT_MASK_DATA_SIZE * 2)
529                 numdigits = IB_CC_PORT_MASK_DATA_SIZE * 2;
530
531         startindex = IB_CC_PORT_MASK_DATA_SIZE - ((numdigits - 1) / 2) - 1;
532
533         if (numdigits % 2) {
534                 memcpy(tmpbuf, strptr, 1);
535                 strptr += 1;
536         }
537         else {
538                 memcpy(tmpbuf, strptr, 2);
539                 strptr += 2;
540         }
541
542         tmpint = strtoul(tmpbuf, NULL, 16);
543         val[startindex] = tmpint;
544
545         for (i = (startindex + 1); i < IB_CC_PORT_MASK_DATA_SIZE; i++) {
546                 memcpy(tmpbuf, strptr, 2);
547                 strptr += 2;
548                 tmpint = strtoul(tmpbuf, NULL, 16);
549                 val[i] = tmpint;
550         }
551
552         if (memcmp(val, p_val1, IB_CC_PORT_MASK_DATA_SIZE)) {
553                 log_config_value(p_key, "%s", p_val_str);
554                 if (pfn)
555                         pfn(p_subn, val);
556                 memcpy(p_val1, val, IB_CC_PORT_MASK_DATA_SIZE);
557                 memcpy(p_val2, val, IB_CC_PORT_MASK_DATA_SIZE);
558         }
559
560 }
561
562 static void opts_parse_cct_entry(IN osm_subn_t *p_subn, IN char *p_key,
563                                  IN char *p_val_str, void *p_v1, void *p_v2,
564                                  void (*pfn)(osm_subn_t *, void *))
565 {
566         osm_cct_entry_t *p_cct1 = p_v1, *p_cct2 = p_v2;
567         osm_cct_entry_t cct;
568         char buf[512] = { 0 };
569         char *ptr;
570
571         strncpy(buf, p_val_str, 511);
572
573         if (!(ptr = strchr(buf, ':'))) {
574                 log_report("invalid CCT entry\n");
575                 return;
576         }
577
578         *ptr = '\0';
579         ptr++;
580
581         cct.shift = strtoul(buf, NULL, 0);
582         cct.multiplier = strtoul(ptr, NULL, 0);
583
584         if (cct.shift != p_cct1->shift
585             || cct.multiplier != p_cct1->multiplier) {
586                 log_config_value(p_key, "%s", p_val_str);
587                 if (pfn)
588                         pfn(p_subn, &cct);
589                 p_cct1->shift = p_cct2->shift = cct.shift;
590                 p_cct1->multiplier = p_cct2->multiplier = cct.multiplier;
591         }
592 }
593
594 static void opts_parse_cc_cct(IN osm_subn_t *p_subn, IN char *p_key,
595                               IN char *p_val_str, void *p_v1, void *p_v2,
596                               void (*pfn)(osm_subn_t *, void *))
597 {
598         osm_cct_t *p_val1 = p_v1, *p_val2 = p_v2;
599         const char *current_str = p_val1->input_str ? p_val1->input_str : null_str;
600
601         if (p_val_str && strcmp(p_val_str, current_str)) {
602                 osm_cct_t newcct;
603                 char *new;
604                 unsigned int len = 0;
605                 char *lasts;
606                 char *tok;
607                 char *ptr;
608
609                 /* special case the "(null)" string */
610                 new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL;
611
612                 if (!new) {
613                         log_config_value(p_key, "%s", p_val_str);
614                         if (pfn)
615                                 pfn(p_subn, NULL);
616                         memset(p_val1->entries, '\0', sizeof(p_val1->entries));
617                         memset(p_val2->entries, '\0', sizeof(p_val2->entries));
618                         p_val1->entries_len = p_val2->entries_len = 0;
619                         p_val1->input_str = p_val2->input_str = NULL;
620                         return;
621                 }
622
623                 memset(&newcct, '\0', sizeof(newcct));
624
625                 tok = strtok_r(new, ",", &lasts);
626                 while (tok && len < OSM_CCT_ENTRY_MAX) {
627
628                         if (!(ptr = strchr(tok, ':'))) {
629                                 log_report("invalid CCT entry\n");
630                                 free(new);
631                                 return;
632                         }
633                         *ptr = '\0';
634                         ptr++;
635
636                         newcct.entries[len].shift = strtoul(tok, NULL, 0);
637                         newcct.entries[len].multiplier = strtoul(ptr, NULL, 0);
638                         len++;
639                         tok = strtok_r(NULL, ",", &lasts);
640                 }
641
642                 free(new);
643
644                 newcct.entries_len = len;
645                 newcct.input_str = strdup(p_val_str);
646
647                 log_config_value(p_key, "%s", p_val_str);
648                 if (pfn)
649                         pfn(p_subn, &newcct);
650                 if (p_val1->input_str && p_val1->input_str != p_val2->input_str)
651                         free(p_val1->input_str);
652                 if (p_val2->input_str)
653                         free(p_val2->input_str);
654                 memcpy(p_val1->entries, newcct.entries, sizeof(newcct.entries));
655                 memcpy(p_val2->entries, newcct.entries, sizeof(newcct.entries));
656                 p_val1->entries_len = p_val2->entries_len = newcct.entries_len;
657                 p_val1->input_str = p_val2->input_str = newcct.input_str;
658         }
659 }
660
661 static int parse_ca_cong_common(char *p_val_str, uint8_t *sl, unsigned int *val_offset) {
662         char *new, *lasts, *sl_str, *val_str;
663         uint8_t sltmp;
664
665         new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL;
666         if (!new)
667                 return -1;
668
669         sl_str = strtok_r(new, " \t", &lasts);
670         val_str = strtok_r(NULL, " \t", &lasts);
671
672         if (!val_str) {
673                 log_report("value must be specified in addition to SL\n");
674                 free(new);
675                 return -1;
676         }
677
678         sltmp = strtoul(sl_str, NULL, 0);
679         if (sltmp >= IB_CA_CONG_ENTRY_DATA_SIZE) {
680                 log_report("invalid SL specified\n");
681                 free(new);
682                 return -1;
683         }
684
685         *sl = sltmp;
686         *val_offset = (unsigned int)(val_str - new);
687
688         free(new);
689         return 0;
690 }
691
692 static void opts_parse_ccti_timer(IN osm_subn_t *p_subn, IN char *p_key,
693                                   IN char *p_val_str, void *p_v1, void *p_v2,
694                                   void (*pfn)(osm_subn_t *, void *))
695 {
696         osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2;
697         unsigned int val_offset = 0;
698         uint8_t sl = 0;
699
700         if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0)
701                 return;
702
703         opts_parse_net16(p_subn, p_key, p_val_str + val_offset,
704                          &p_val1[sl].ccti_timer,
705                          &p_val2[sl].ccti_timer,
706                          pfn);
707 }
708
709 static void opts_parse_ccti_increase(IN osm_subn_t *p_subn, IN char *p_key,
710                                      IN char *p_val_str, void *p_v1, void *p_v2,
711                                      void (*pfn)(osm_subn_t *, void *))
712 {
713         osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2;
714         unsigned int val_offset = 0;
715         uint8_t sl = 0;
716
717         if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0)
718                 return;
719
720         opts_parse_uint8(p_subn, p_key, p_val_str + val_offset,
721                          &p_val1[sl].ccti_increase,
722                          &p_val2[sl].ccti_increase,
723                          pfn);
724 }
725
726 static void opts_parse_trigger_threshold(IN osm_subn_t *p_subn, IN char *p_key,
727                                          IN char *p_val_str, void *p_v1, void *p_v2,
728                                          void (*pfn)(osm_subn_t *, void *))
729 {
730         osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2;
731         unsigned int val_offset = 0;
732         uint8_t sl = 0;
733
734         if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0)
735                 return;
736
737         opts_parse_uint8(p_subn, p_key, p_val_str + val_offset,
738                          &p_val1[sl].trigger_threshold,
739                          &p_val2[sl].trigger_threshold,
740                          pfn);
741 }
742
743 static void opts_parse_ccti_min(IN osm_subn_t *p_subn, IN char *p_key,
744                                 IN char *p_val_str, void *p_v1, void *p_v2,
745                                 void (*pfn)(osm_subn_t *, void *))
746 {
747         osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2;
748         unsigned int val_offset = 0;
749         uint8_t sl = 0;
750
751         if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0)
752                 return;
753
754         opts_parse_uint8(p_subn, p_key, p_val_str + val_offset,
755                          &p_val1[sl].ccti_min,
756                          &p_val2[sl].ccti_min,
757                          pfn);
758 }
759
760 static const opt_rec_t opt_tbl[] = {
761         { "guid", OPT_OFFSET(guid), opts_parse_net64, NULL, 0 },
762         { "m_key", OPT_OFFSET(m_key), opts_parse_net64, NULL, 1 },
763         { "sm_key", OPT_OFFSET(sm_key), opts_parse_net64, NULL, 1 },
764         { "sa_key", OPT_OFFSET(sa_key), opts_parse_net64, NULL, 1 },
765         { "subnet_prefix", OPT_OFFSET(subnet_prefix), opts_parse_net64, NULL, 0 },
766         { "m_key_lease_period", OPT_OFFSET(m_key_lease_period), opts_parse_net16, NULL, 1 },
767         { "m_key_protection_level", OPT_OFFSET(m_key_protect_bits), opts_parse_uint8, NULL, 1 },
768         { "m_key_lookup", OPT_OFFSET(m_key_lookup), opts_parse_boolean, NULL, 1 },
769         { "sweep_interval", OPT_OFFSET(sweep_interval), opts_parse_uint32, NULL, 1 },
770         { "max_wire_smps", OPT_OFFSET(max_wire_smps), opts_parse_uint32, NULL, 1 },
771         { "max_wire_smps2", OPT_OFFSET(max_wire_smps2), opts_parse_uint32, NULL, 1 },
772         { "max_smps_timeout", OPT_OFFSET(max_smps_timeout), opts_parse_uint32, NULL, 1 },
773         { "console", OPT_OFFSET(console), opts_parse_charp, NULL, 0 },
774         { "console_port", OPT_OFFSET(console_port), opts_parse_uint16, NULL, 0 },
775         { "transaction_timeout", OPT_OFFSET(transaction_timeout), opts_parse_uint32, NULL, 0 },
776         { "transaction_retries", OPT_OFFSET(transaction_retries), opts_parse_uint32, NULL, 0 },
777         { "max_msg_fifo_timeout", OPT_OFFSET(max_msg_fifo_timeout), opts_parse_uint32, NULL, 1 },
778         { "sm_priority", OPT_OFFSET(sm_priority), opts_parse_uint8, opts_setup_sm_priority, 1 },
779         { "lmc", OPT_OFFSET(lmc), opts_parse_uint8, NULL, 0 },
780         { "lmc_esp0", OPT_OFFSET(lmc_esp0), opts_parse_boolean, NULL, 0 },
781         { "max_op_vls", OPT_OFFSET(max_op_vls), opts_parse_uint8, NULL, 1 },
782         { "force_link_speed", OPT_OFFSET(force_link_speed), opts_parse_uint8, NULL, 1 },
783         { "force_link_speed_ext", OPT_OFFSET(force_link_speed_ext), opts_parse_uint8, NULL, 1 },
784         { "fdr10", OPT_OFFSET(fdr10), opts_parse_uint8, NULL, 1 },
785         { "reassign_lids", OPT_OFFSET(reassign_lids), opts_parse_boolean, NULL, 1 },
786         { "ignore_other_sm", OPT_OFFSET(ignore_other_sm), opts_parse_boolean, NULL, 1 },
787         { "single_thread", OPT_OFFSET(single_thread), opts_parse_boolean, NULL, 0 },
788         { "disable_multicast", OPT_OFFSET(disable_multicast), opts_parse_boolean, NULL, 1 },
789         { "subnet_timeout", OPT_OFFSET(subnet_timeout), opts_parse_uint8, NULL, 1 },
790         { "packet_life_time", OPT_OFFSET(packet_life_time), opts_parse_uint8, NULL, 1 },
791         { "vl_stall_count", OPT_OFFSET(vl_stall_count), opts_parse_uint8, NULL, 1 },
792         { "leaf_vl_stall_count", OPT_OFFSET(leaf_vl_stall_count), opts_parse_uint8, NULL, 1 },
793         { "head_of_queue_lifetime", OPT_OFFSET(head_of_queue_lifetime), opts_parse_uint8, NULL, 1 },
794         { "leaf_head_of_queue_lifetime", OPT_OFFSET(leaf_head_of_queue_lifetime), opts_parse_uint8, NULL, 1 },
795         { "local_phy_errors_threshold", OPT_OFFSET(local_phy_errors_threshold), opts_parse_uint8, NULL, 1 },
796         { "overrun_errors_threshold", OPT_OFFSET(overrun_errors_threshold), opts_parse_uint8, NULL, 1 },
797         { "use_mfttop", OPT_OFFSET(use_mfttop), opts_parse_boolean, NULL, 1},
798         { "sminfo_polling_timeout", OPT_OFFSET(sminfo_polling_timeout), opts_parse_uint32, opts_setup_sminfo_polling_timeout, 1 },
799         { "polling_retry_number", OPT_OFFSET(polling_retry_number), opts_parse_uint32, NULL, 1 },
800         { "force_heavy_sweep", OPT_OFFSET(force_heavy_sweep), opts_parse_boolean, NULL, 1 },
801         { "port_prof_ignore_file", OPT_OFFSET(port_prof_ignore_file), opts_parse_charp, NULL, 0 },
802         { "hop_weights_file", OPT_OFFSET(hop_weights_file), opts_parse_charp, NULL, 0 },
803         { "dimn_ports_file", OPT_OFFSET(port_search_ordering_file), opts_parse_charp, NULL, 0 },
804         { "port_search_ordering_file", OPT_OFFSET(port_search_ordering_file), opts_parse_charp, NULL, 0 },
805         { "port_profile_switch_nodes", OPT_OFFSET(port_profile_switch_nodes), opts_parse_boolean, NULL, 1 },
806         { "sweep_on_trap", OPT_OFFSET(sweep_on_trap), opts_parse_boolean, NULL, 1 },
807         { "routing_engine", OPT_OFFSET(routing_engine_names), opts_parse_charp, NULL, 0 },
808         { "connect_roots", OPT_OFFSET(connect_roots), opts_parse_boolean, NULL, 1 },
809         { "use_ucast_cache", OPT_OFFSET(use_ucast_cache), opts_parse_boolean, NULL, 0 },
810         { "log_file", OPT_OFFSET(log_file), opts_parse_charp, NULL, 0 },
811         { "log_max_size", OPT_OFFSET(log_max_size), opts_parse_uint32, opts_setup_log_max_size, 1 },
812         { "log_flags", OPT_OFFSET(log_flags), opts_parse_uint8, opts_setup_log_flags, 1 },
813         { "force_log_flush", OPT_OFFSET(force_log_flush), opts_parse_boolean, opts_setup_force_log_flush, 1 },
814         { "accum_log_file", OPT_OFFSET(accum_log_file), opts_parse_boolean, opts_setup_accum_log_file, 1 },
815         { "partition_config_file", OPT_OFFSET(partition_config_file), opts_parse_charp, NULL, 0 },
816         { "no_partition_enforcement", OPT_OFFSET(no_partition_enforcement), opts_parse_boolean, NULL, 1 },
817         { "part_enforce", OPT_OFFSET(part_enforce), opts_parse_charp, NULL, 1 },
818         { "allow_both_pkeys", OPT_OFFSET(allow_both_pkeys), opts_parse_boolean, NULL, 0 },
819         { "sm_assigned_guid", OPT_OFFSET(sm_assigned_guid), opts_parse_uint8, NULL, 1 },
820         { "qos", OPT_OFFSET(qos), opts_parse_boolean, NULL, 1 },
821         { "qos_policy_file", OPT_OFFSET(qos_policy_file), opts_parse_charp, NULL, 0 },
822         { "suppress_sl2vl_mad_status_errors", OPT_OFFSET(suppress_sl2vl_mad_status_errors), opts_parse_boolean, NULL, 1 },
823         { "dump_files_dir", OPT_OFFSET(dump_files_dir), opts_parse_charp, NULL, 0 },
824         { "lid_matrix_dump_file", OPT_OFFSET(lid_matrix_dump_file), opts_parse_charp, NULL, 0 },
825         { "lfts_file", OPT_OFFSET(lfts_file), opts_parse_charp, NULL, 0 },
826         { "root_guid_file", OPT_OFFSET(root_guid_file), opts_parse_charp, NULL, 0 },
827         { "cn_guid_file", OPT_OFFSET(cn_guid_file), opts_parse_charp, NULL, 0 },
828         { "io_guid_file", OPT_OFFSET(io_guid_file), opts_parse_charp, NULL, 0 },
829         { "port_shifting", OPT_OFFSET(port_shifting), opts_parse_boolean, NULL, 1 },
830         { "scatter_ports", OPT_OFFSET(scatter_ports), opts_parse_uint32, NULL, 1 },
831         { "max_reverse_hops", OPT_OFFSET(max_reverse_hops), opts_parse_uint16, NULL, 0 },
832         { "ids_guid_file", OPT_OFFSET(ids_guid_file), opts_parse_charp, NULL, 0 },
833         { "guid_routing_order_file", OPT_OFFSET(guid_routing_order_file), opts_parse_charp, NULL, 0 },
834         { "guid_routing_order_no_scatter", OPT_OFFSET(guid_routing_order_no_scatter), opts_parse_boolean, NULL, 0 },
835         { "sa_db_file", OPT_OFFSET(sa_db_file), opts_parse_charp, NULL, 0 },
836         { "sa_db_dump", OPT_OFFSET(sa_db_dump), opts_parse_boolean, NULL, 1 },
837         { "torus_config", OPT_OFFSET(torus_conf_file), opts_parse_charp, NULL, 1 },
838         { "do_mesh_analysis", OPT_OFFSET(do_mesh_analysis), opts_parse_boolean, NULL, 1 },
839         { "exit_on_fatal", OPT_OFFSET(exit_on_fatal), opts_parse_boolean, NULL, 1 },
840         { "honor_guid2lid_file", OPT_OFFSET(honor_guid2lid_file), opts_parse_boolean, NULL, 1 },
841         { "daemon", OPT_OFFSET(daemon), opts_parse_boolean, NULL, 0 },
842         { "sm_inactive", OPT_OFFSET(sm_inactive), opts_parse_boolean, NULL, 1 },
843         { "babbling_port_policy", OPT_OFFSET(babbling_port_policy), opts_parse_boolean, NULL, 1 },
844         { "drop_event_subscriptions", OPT_OFFSET(drop_event_subscriptions), opts_parse_boolean, NULL, 1 },
845         { "ipoib_mcgroup_creation_validation", OPT_OFFSET(ipoib_mcgroup_creation_validation), opts_parse_boolean, NULL, 1 },
846         { "mcgroup_join_validation", OPT_OFFSET(mcgroup_join_validation), opts_parse_boolean, NULL, 1 },
847         { "use_optimized_slvl", OPT_OFFSET(use_optimized_slvl), opts_parse_boolean, NULL, 1 },
848         { "fsync_high_avail_files", OPT_OFFSET(fsync_high_avail_files), opts_parse_boolean, NULL, 1 },
849 #ifdef ENABLE_OSM_PERF_MGR
850         { "perfmgr", OPT_OFFSET(perfmgr), opts_parse_boolean, NULL, 0 },
851         { "perfmgr_redir", OPT_OFFSET(perfmgr_redir), opts_parse_boolean, NULL, 0 },
852         { "perfmgr_sweep_time_s", OPT_OFFSET(perfmgr_sweep_time_s), opts_parse_uint16, NULL, 0 },
853         { "perfmgr_max_outstanding_queries", OPT_OFFSET(perfmgr_max_outstanding_queries), opts_parse_uint32, NULL, 0 },
854         { "perfmgr_ignore_cas", OPT_OFFSET(perfmgr_ignore_cas), opts_parse_boolean, NULL, 0 },
855         { "event_db_dump_file", OPT_OFFSET(event_db_dump_file), opts_parse_charp, NULL, 0 },
856         { "perfmgr_rm_nodes", OPT_OFFSET(perfmgr_rm_nodes), opts_parse_boolean, NULL, 0 },
857         { "perfmgr_log_errors", OPT_OFFSET(perfmgr_log_errors), opts_parse_boolean, NULL, 0 },
858         { "perfmgr_query_cpi", OPT_OFFSET(perfmgr_query_cpi), opts_parse_boolean, NULL, 0 },
859         { "perfmgr_xmit_wait_log", OPT_OFFSET(perfmgr_xmit_wait_log), opts_parse_boolean, NULL, 0 },
860         { "perfmgr_xmit_wait_threshold", OPT_OFFSET(perfmgr_xmit_wait_threshold), opts_parse_uint32, NULL, 0 },
861 #endif                          /* ENABLE_OSM_PERF_MGR */
862         { "event_plugin_name", OPT_OFFSET(event_plugin_name), opts_parse_charp, NULL, 0 },
863         { "event_plugin_options", OPT_OFFSET(event_plugin_options), opts_parse_charp, NULL, 0 },
864         { "node_name_map_name", OPT_OFFSET(node_name_map_name), opts_parse_charp, NULL, 0 },
865         { "qos_max_vls", OPT_OFFSET(qos_options.max_vls), opts_parse_uint32, NULL, 1 },
866         { "qos_high_limit", OPT_OFFSET(qos_options.high_limit), opts_parse_int32, NULL, 1 },
867         { "qos_vlarb_high", OPT_OFFSET(qos_options.vlarb_high), opts_parse_charp, NULL, 1 },
868         { "qos_vlarb_low", OPT_OFFSET(qos_options.vlarb_low), opts_parse_charp, NULL, 1 },
869         { "qos_sl2vl", OPT_OFFSET(qos_options.sl2vl), opts_parse_charp, NULL, 1 },
870         { "qos_ca_max_vls", OPT_OFFSET(qos_ca_options.max_vls), opts_parse_uint32, NULL, 1 },
871         { "qos_ca_high_limit", OPT_OFFSET(qos_ca_options.high_limit), opts_parse_int32, NULL, 1 },
872         { "qos_ca_vlarb_high", OPT_OFFSET(qos_ca_options.vlarb_high), opts_parse_charp, NULL, 1 },
873         { "qos_ca_vlarb_low", OPT_OFFSET(qos_ca_options.vlarb_low), opts_parse_charp, NULL, 1 },
874         { "qos_ca_sl2vl", OPT_OFFSET(qos_ca_options.sl2vl), opts_parse_charp, NULL, 1 },
875         { "qos_sw0_max_vls", OPT_OFFSET(qos_sw0_options.max_vls), opts_parse_uint32, NULL, 1 },
876         { "qos_sw0_high_limit", OPT_OFFSET(qos_sw0_options.high_limit), opts_parse_int32, NULL, 1 },
877         { "qos_sw0_vlarb_high", OPT_OFFSET(qos_sw0_options.vlarb_high), opts_parse_charp, NULL, 1 },
878         { "qos_sw0_vlarb_low", OPT_OFFSET(qos_sw0_options.vlarb_low), opts_parse_charp, NULL, 1 },
879         { "qos_sw0_sl2vl", OPT_OFFSET(qos_sw0_options.sl2vl), opts_parse_charp, NULL, 1 },
880         { "qos_swe_max_vls", OPT_OFFSET(qos_swe_options.max_vls), opts_parse_uint32, NULL, 1 },
881         { "qos_swe_high_limit", OPT_OFFSET(qos_swe_options.high_limit), opts_parse_int32, NULL, 1 },
882         { "qos_swe_vlarb_high", OPT_OFFSET(qos_swe_options.vlarb_high), opts_parse_charp, NULL, 1 },
883         { "qos_swe_vlarb_low", OPT_OFFSET(qos_swe_options.vlarb_low), opts_parse_charp, NULL, 1 },
884         { "qos_swe_sl2vl", OPT_OFFSET(qos_swe_options.sl2vl), opts_parse_charp, NULL, 1 },
885         { "qos_rtr_max_vls", OPT_OFFSET(qos_rtr_options.max_vls), opts_parse_uint32, NULL, 1 },
886         { "qos_rtr_high_limit", OPT_OFFSET(qos_rtr_options.high_limit), opts_parse_int32, NULL, 1 },
887         { "qos_rtr_vlarb_high", OPT_OFFSET(qos_rtr_options.vlarb_high), opts_parse_charp, NULL, 1 },
888         { "qos_rtr_vlarb_low", OPT_OFFSET(qos_rtr_options.vlarb_low), opts_parse_charp, NULL, 1 },
889         { "qos_rtr_sl2vl", OPT_OFFSET(qos_rtr_options.sl2vl), opts_parse_charp, NULL, 1 },
890         { "congestion_control", OPT_OFFSET(congestion_control), opts_parse_boolean, NULL, 1 },
891         { "cc_key", OPT_OFFSET(cc_key), opts_parse_net64, NULL, 0},
892         { "cc_max_outstanding_mads", OPT_OFFSET(cc_max_outstanding_mads), opts_parse_uint32, NULL, 0 },
893         { "cc_sw_cong_setting_control_map", OPT_OFFSET(cc_sw_cong_setting_control_map), opts_parse_net32, NULL, 1},
894         { "cc_sw_cong_setting_victim_mask", OPT_OFFSET(cc_sw_cong_setting_victim_mask), opts_parse_256bit, NULL, 1},
895         { "cc_sw_cong_setting_credit_mask", OPT_OFFSET(cc_sw_cong_setting_credit_mask), opts_parse_256bit, NULL, 1},
896         { "cc_sw_cong_setting_threshold", OPT_OFFSET(cc_sw_cong_setting_threshold), opts_parse_uint8, NULL, 1},
897         { "cc_sw_cong_setting_packet_size", OPT_OFFSET(cc_sw_cong_setting_packet_size), opts_parse_uint8, NULL, 1},
898         { "cc_sw_cong_setting_credit_starvation_threshold", OPT_OFFSET(cc_sw_cong_setting_credit_starvation_threshold), opts_parse_uint8, NULL, 1},
899         { "cc_sw_cong_setting_credit_starvation_return_delay", OPT_OFFSET(cc_sw_cong_setting_credit_starvation_return_delay), opts_parse_cct_entry, NULL, 1},
900         { "cc_sw_cong_setting_marking_rate", OPT_OFFSET(cc_sw_cong_setting_marking_rate), opts_parse_net16, NULL, 1},
901         { "cc_ca_cong_setting_port_control", OPT_OFFSET(cc_ca_cong_setting_port_control), opts_parse_net16, NULL, 1},
902         { "cc_ca_cong_setting_control_map", OPT_OFFSET(cc_ca_cong_setting_control_map), opts_parse_net16, NULL, 1},
903         { "cc_ca_cong_setting_ccti_timer", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_timer, NULL, 1},
904         { "cc_ca_cong_setting_ccti_increase", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_increase, NULL, 1},
905         { "cc_ca_cong_setting_trigger_threshold", OPT_OFFSET(cc_ca_cong_entries), opts_parse_trigger_threshold, NULL, 1},
906         { "cc_ca_cong_setting_ccti_min", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_min, NULL, 1},
907         { "cc_cct", OPT_OFFSET(cc_cct), opts_parse_cc_cct, NULL, 1},
908         { "enable_quirks", OPT_OFFSET(enable_quirks), opts_parse_boolean, NULL, 1 },
909         { "no_clients_rereg", OPT_OFFSET(no_clients_rereg), opts_parse_boolean, NULL, 1 },
910         { "prefix_routes_file", OPT_OFFSET(prefix_routes_file), opts_parse_charp, NULL, 0 },
911         { "consolidate_ipv6_snm_req", OPT_OFFSET(consolidate_ipv6_snm_req), opts_parse_boolean, NULL, 1 },
912         { "lash_start_vl", OPT_OFFSET(lash_start_vl), opts_parse_uint8, NULL, 1 },
913         { "sm_sl", OPT_OFFSET(sm_sl), opts_parse_uint8, NULL, 1 },
914         { "log_prefix", OPT_OFFSET(log_prefix), opts_parse_charp, NULL, 1 },
915         { "per_module_logging_file", OPT_OFFSET(per_module_logging_file), opts_parse_charp, NULL, 0 },
916         { "quasi_ftree_indexing", OPT_OFFSET(quasi_ftree_indexing), opts_parse_boolean, NULL, 1 },
917         {0}
918 };
919
920 static int compar_mgids(const void *m1, const void *m2)
921 {
922         return memcmp(m1, m2, sizeof(ib_gid_t));
923 }
924
925 static void subn_validate_g2m(osm_subn_t *p_subn)
926 {
927         cl_qlist_t guids;
928         osm_db_guid_elem_t *p_item;
929         uint64_t mkey;
930         boolean_t valid_entry;
931
932         OSM_LOG_ENTER(&(p_subn->p_osm->log));
933         cl_qlist_init(&guids);
934
935         if (osm_db_guid2mkey_guids(p_subn->p_g2m, &guids)) {
936                 OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7506: "
937                         "could not get mkey guid list\n");
938                 goto Exit;
939         }
940
941         while ((p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids))
942                != (osm_db_guid_elem_t *) cl_qlist_end(&guids)) {
943                 valid_entry = TRUE;
944
945                 if (p_item->guid == 0) {
946                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
947                                 "ERR 7507: found invalid zero guid");
948                         valid_entry = FALSE;
949                 } else if (osm_db_guid2mkey_get(p_subn->p_g2m, p_item->guid,
950                                                 &mkey)) {
951                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
952                                 "ERR 7508: could not get mkey for guid:0x%016"
953                                 PRIx64 "\n", p_item->guid);
954                         valid_entry = FALSE;
955                 }
956
957                 if (valid_entry == FALSE) {
958                         if (osm_db_guid2mkey_delete(p_subn->p_g2m,
959                                                     p_item->guid))
960                                 OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
961                                         "ERR 7509: failed to delete entry for "
962                                         "guid:0x%016" PRIx64 "\n",
963                                         p_item->guid);
964                 }
965                 free(p_item);
966         }
967
968 Exit:
969         OSM_LOG_EXIT(&(p_subn->p_osm->log));
970 }
971
972 static void subn_validate_neighbor(osm_subn_t *p_subn)
973 {
974         cl_qlist_t entries;
975         osm_db_neighbor_elem_t *p_item;
976         boolean_t valid_entry;
977         uint64_t guid;
978         uint8_t port;
979
980         OSM_LOG_ENTER(&(p_subn->p_osm->log));
981         cl_qlist_init(&entries);
982
983         if (osm_db_neighbor_guids(p_subn->p_neighbor, &entries)) {
984                 OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7512: "
985                         "could not get neighbor entry list\n");
986                 goto Exit;
987         }
988
989         while ((p_item =
990                 (osm_db_neighbor_elem_t *) cl_qlist_remove_head(&entries))
991                != (osm_db_neighbor_elem_t *) cl_qlist_end(&entries)) {
992                 valid_entry = TRUE;
993
994                 OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_DEBUG,
995                         "Validating neighbor for guid:0x%016" PRIx64
996                         ", port %d\n",
997                         p_item->guid, p_item->portnum);
998                 if (p_item->guid == 0) {
999                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1000                                 "ERR 7513: found invalid zero guid\n");
1001                         valid_entry = FALSE;
1002                 } else if (p_item->portnum == 0) {
1003                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1004                                 "ERR 7514: found invalid zero port for "
1005                                 "guid: 0x%016" PRIx64 "\n",
1006                                 p_item->guid);
1007                         valid_entry = FALSE;
1008                 } else if (osm_db_neighbor_get(p_subn->p_neighbor,
1009                                                p_item->guid, p_item->portnum,
1010                                                &guid, &port)) {
1011                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1012                                 "ERR 7515: could not find neighbor for "
1013                                 "guid: 0x%016" PRIx64 ", port %d\n",
1014                                 p_item->guid, p_item->portnum);
1015                         valid_entry = FALSE;
1016                 } else if (guid == 0) {
1017                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1018                                 "ERR 7516: found invalid neighbor "
1019                                 "zero guid for guid: 0x%016" PRIx64
1020                                 ", port %d\n",
1021                                 p_item->guid, p_item->portnum);
1022                         valid_entry = FALSE;
1023                 } else if (port == 0) {
1024                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1025                                 "ERR 7517: found invalid neighbor "
1026                                 "zero port for guid: 0x%016" PRIx64
1027                                 ", port %d\n",
1028                                 p_item->guid, p_item->portnum);
1029                         valid_entry = FALSE;
1030                 } else if (osm_db_neighbor_get(p_subn->p_neighbor,
1031                                                guid, port, &guid, &port) ||
1032                            guid != p_item->guid || port != p_item->portnum) {
1033                         OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1034                                 "ERR 7518: neighbor does not point "
1035                                 "back at us (guid: 0x%016" PRIx64
1036                                 ", port %d)\n",
1037                                 p_item->guid, p_item->portnum);
1038                         valid_entry = FALSE;
1039                 }
1040
1041                 if (valid_entry == FALSE) {
1042                         if (osm_db_neighbor_delete(p_subn->p_neighbor,
1043                                                    p_item->guid,
1044                                                    p_item->portnum))
1045                                 OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR,
1046                                         "ERR 7519: failed to delete entry for "
1047                                         "guid:0x%016" PRIx64 " port:%u\n",
1048                                         p_item->guid, p_item->portnum);
1049                 }
1050                 free(p_item);
1051         }
1052
1053 Exit:
1054         OSM_LOG_EXIT(&(p_subn->p_osm->log));
1055 }
1056
1057 void osm_subn_construct(IN osm_subn_t * p_subn)
1058 {
1059         memset(p_subn, 0, sizeof(*p_subn));
1060         cl_ptr_vector_construct(&p_subn->port_lid_tbl);
1061         cl_qmap_init(&p_subn->sw_guid_tbl);
1062         cl_qmap_init(&p_subn->node_guid_tbl);
1063         cl_qmap_init(&p_subn->port_guid_tbl);
1064         cl_qmap_init(&p_subn->alias_port_guid_tbl);
1065         cl_qmap_init(&p_subn->assigned_guids_tbl);
1066         cl_qmap_init(&p_subn->sm_guid_tbl);
1067         cl_qlist_init(&p_subn->sa_sr_list);
1068         cl_qlist_init(&p_subn->sa_infr_list);
1069         cl_qlist_init(&p_subn->alias_guid_list);
1070         cl_qlist_init(&p_subn->prefix_routes_list);
1071         cl_qmap_init(&p_subn->rtr_guid_tbl);
1072         cl_qmap_init(&p_subn->prtn_pkey_tbl);
1073         cl_fmap_init(&p_subn->mgrp_mgid_tbl, compar_mgids);
1074 }
1075
1076 static void subn_destroy_qos_options(osm_qos_options_t *opt)
1077 {
1078         free(opt->vlarb_high);
1079         free(opt->vlarb_low);
1080         free(opt->sl2vl);
1081 }
1082
1083 static void subn_opt_destroy(IN osm_subn_opt_t * p_opt)
1084 {
1085         free(p_opt->console);
1086         free(p_opt->port_prof_ignore_file);
1087         free(p_opt->hop_weights_file);
1088         free(p_opt->port_search_ordering_file);
1089         free(p_opt->routing_engine_names);
1090         free(p_opt->log_file);
1091         free(p_opt->partition_config_file);
1092         free(p_opt->qos_policy_file);
1093         free(p_opt->dump_files_dir);
1094         free(p_opt->part_enforce);
1095         free(p_opt->lid_matrix_dump_file);
1096         free(p_opt->lfts_file);
1097         free(p_opt->root_guid_file);
1098         free(p_opt->cn_guid_file);
1099         free(p_opt->io_guid_file);
1100         free(p_opt->ids_guid_file);
1101         free(p_opt->guid_routing_order_file);
1102         free(p_opt->sa_db_file);
1103         free(p_opt->torus_conf_file);
1104 #ifdef ENABLE_OSM_PERF_MGR
1105         free(p_opt->event_db_dump_file);
1106 #endif /* ENABLE_OSM_PERF_MGR */
1107         free(p_opt->event_plugin_name);
1108         free(p_opt->event_plugin_options);
1109         free(p_opt->node_name_map_name);
1110         free(p_opt->prefix_routes_file);
1111         free(p_opt->log_prefix);
1112         subn_destroy_qos_options(&p_opt->qos_options);
1113         subn_destroy_qos_options(&p_opt->qos_ca_options);
1114         subn_destroy_qos_options(&p_opt->qos_sw0_options);
1115         subn_destroy_qos_options(&p_opt->qos_swe_options);
1116         subn_destroy_qos_options(&p_opt->qos_rtr_options);
1117         free(p_opt->cc_cct.input_str);
1118 }
1119
1120 void osm_subn_destroy(IN osm_subn_t * p_subn)
1121 {
1122         int i;
1123         osm_node_t *p_node, *p_next_node;
1124         osm_assigned_guids_t *p_assigned_guids, *p_next_assigned_guids;
1125         osm_alias_guid_t *p_alias_guid, *p_next_alias_guid;
1126         osm_port_t *p_port, *p_next_port;
1127         osm_switch_t *p_sw, *p_next_sw;
1128         osm_remote_sm_t *p_rsm, *p_next_rsm;
1129         osm_prtn_t *p_prtn, *p_next_prtn;
1130         osm_infr_t *p_infr, *p_next_infr;
1131         osm_svcr_t *p_svcr, *p_next_svcr;
1132
1133         /* it might be a good idea to de-allocate all known objects */
1134         p_next_node = (osm_node_t *) cl_qmap_head(&p_subn->node_guid_tbl);
1135         while (p_next_node !=
1136                (osm_node_t *) cl_qmap_end(&p_subn->node_guid_tbl)) {
1137                 p_node = p_next_node;
1138                 p_next_node = (osm_node_t *) cl_qmap_next(&p_node->map_item);
1139                 osm_node_delete(&p_node);
1140         }
1141
1142         p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_head(&p_subn->assigned_guids_tbl);
1143         while (p_next_assigned_guids !=
1144                (osm_assigned_guids_t *) cl_qmap_end(&p_subn->assigned_guids_tbl)) {
1145                 p_assigned_guids = p_next_assigned_guids;
1146                 p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_next(&p_assigned_guids->map_item);
1147                 osm_assigned_guids_delete(&p_assigned_guids);
1148         }
1149
1150         p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&p_subn->alias_port_guid_tbl);
1151         while (p_next_alias_guid !=
1152                (osm_alias_guid_t *) cl_qmap_end(&p_subn->alias_port_guid_tbl)) {
1153                 p_alias_guid = p_next_alias_guid;
1154                 p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid->map_item);
1155                 osm_alias_guid_delete(&p_alias_guid);
1156         }
1157
1158         while (cl_qlist_count(&p_subn->alias_guid_list))
1159                 osm_guid_work_obj_delete((osm_guidinfo_work_obj_t *) cl_qlist_remove_head(&p_subn->alias_guid_list));
1160
1161         p_next_port = (osm_port_t *) cl_qmap_head(&p_subn->port_guid_tbl);
1162         while (p_next_port !=
1163                (osm_port_t *) cl_qmap_end(&p_subn->port_guid_tbl)) {
1164                 p_port = p_next_port;
1165                 p_next_port = (osm_port_t *) cl_qmap_next(&p_port->map_item);
1166                 osm_port_delete(&p_port);
1167         }
1168
1169         p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
1170         while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
1171                 p_sw = p_next_sw;
1172                 p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
1173                 osm_switch_delete(&p_sw);
1174         }
1175
1176         p_next_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl);
1177         while (p_next_rsm !=
1178                (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) {
1179                 p_rsm = p_next_rsm;
1180                 p_next_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item);
1181                 free(p_rsm);
1182         }
1183
1184         p_next_prtn = (osm_prtn_t *) cl_qmap_head(&p_subn->prtn_pkey_tbl);
1185         while (p_next_prtn !=
1186                (osm_prtn_t *) cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
1187                 p_prtn = p_next_prtn;
1188                 p_next_prtn = (osm_prtn_t *) cl_qmap_next(&p_prtn->map_item);
1189                 osm_prtn_delete(p_subn, &p_prtn);
1190         }
1191
1192         cl_fmap_remove_all(&p_subn->mgrp_mgid_tbl);
1193
1194         for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
1195              i++)
1196                 if (p_subn->mboxes[i])
1197                         osm_mgrp_box_delete(p_subn->mboxes[i]);
1198
1199         p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list);
1200         while (p_next_infr !=
1201                (osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) {
1202                 p_infr = p_next_infr;
1203                 p_next_infr = (osm_infr_t *) cl_qlist_next(&p_infr->list_item);
1204                 osm_infr_delete(p_infr);
1205         }
1206
1207         p_next_svcr = (osm_svcr_t *) cl_qlist_head(&p_subn->sa_sr_list);
1208         while (p_next_svcr !=
1209                (osm_svcr_t *) cl_qlist_end(&p_subn->sa_sr_list)) {
1210                 p_svcr = p_next_svcr;
1211                 p_next_svcr = (osm_svcr_t *) cl_qlist_next(&p_svcr->list_item);
1212                 osm_svcr_delete(p_svcr);
1213         }
1214
1215         cl_ptr_vector_destroy(&p_subn->port_lid_tbl);
1216
1217         osm_qos_policy_destroy(p_subn->p_qos_policy);
1218
1219         while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
1220                 cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
1221                 free(item);
1222         }
1223
1224         subn_opt_destroy(&p_subn->opt);
1225         free(p_subn->opt.file_opts);
1226 }
1227
1228 ib_api_status_t osm_subn_init(IN osm_subn_t * p_subn, IN osm_opensm_t * p_osm,
1229                               IN const osm_subn_opt_t * p_opt)
1230 {
1231         cl_status_t status;
1232
1233         p_subn->p_osm = p_osm;
1234
1235         status = cl_ptr_vector_init(&p_subn->port_lid_tbl,
1236                                     OSM_SUBNET_VECTOR_MIN_SIZE,
1237                                     OSM_SUBNET_VECTOR_GROW_SIZE);
1238         if (status != CL_SUCCESS)
1239                 return status;
1240
1241         status = cl_ptr_vector_set_capacity(&p_subn->port_lid_tbl,
1242                                             OSM_SUBNET_VECTOR_CAPACITY);
1243         if (status != CL_SUCCESS)
1244                 return status;
1245
1246         /*
1247            LID zero is not valid.  NULL out this entry for the
1248            convenience of other code.
1249          */
1250         cl_ptr_vector_set(&p_subn->port_lid_tbl, 0, NULL);
1251
1252         p_subn->opt = *p_opt;
1253         p_subn->max_ucast_lid_ho = IB_LID_UCAST_END_HO;
1254         p_subn->max_mcast_lid_ho = IB_LID_MCAST_END_HO;
1255         p_subn->min_ca_mtu = IB_MAX_MTU;
1256         p_subn->min_ca_rate = IB_PATH_RECORD_RATE_300_GBS;
1257         p_subn->min_data_vls = IB_MAX_NUM_VLS - 1;
1258         p_subn->min_sw_data_vls = IB_MAX_NUM_VLS - 1;
1259         p_subn->ignore_existing_lfts = TRUE;
1260
1261         /* we assume master by default - so we only need to set it true if STANDBY */
1262         p_subn->coming_out_of_standby = FALSE;
1263         p_subn->sweeping_enabled = TRUE;
1264         p_subn->last_sm_port_state = 1;
1265
1266         /* Initialize the guid2mkey database */
1267         p_subn->p_g2m = osm_db_domain_init(&(p_osm->db), "guid2mkey");
1268         if (!p_subn->p_g2m) {
1269                 OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7510: "
1270                         "Error initializing Guid-to-MKey persistent database\n");
1271                 return IB_ERROR;
1272         }
1273
1274         if (osm_db_restore(p_subn->p_g2m)) {
1275 #ifndef __WIN__
1276                 /*
1277                  * When Windows is BSODing, it might corrupt files that
1278                  * were previously opened for writing, even if the files
1279                  * are closed, so we might see corrupted guid2mkey file.
1280                  */
1281                 if (p_subn->opt.exit_on_fatal) {
1282                         osm_log(&(p_osm->log), OSM_LOG_SYS,
1283                                 "FATAL: Error restoring Guid-to-Mkey "
1284                                 "persistent database\n");
1285                         return IB_ERROR;
1286                 } else
1287 #endif
1288                         OSM_LOG(&(p_osm->log), OSM_LOG_ERROR,
1289                                 "ERR 7511: Error restoring Guid-to-Mkey "
1290                                 "persistent database\n");
1291         }
1292
1293         subn_validate_g2m(p_subn);
1294
1295         /* Initialize the neighbor database */
1296         p_subn->p_neighbor = osm_db_domain_init(&(p_osm->db), "neighbors");
1297         if (!p_subn->p_neighbor) {
1298                 OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7520: Error "
1299                         "initializing neighbor link persistent database\n");
1300                 return IB_ERROR;
1301         }
1302
1303         if (osm_db_restore(p_subn->p_neighbor)) {
1304 #ifndef __WIN__
1305                 /*
1306                  * When Windows is BSODing, it might corrupt files that
1307                  * were previously opened for writing, even if the files
1308                  * are closed, so we might see corrupted neighbors file.
1309                  */
1310                 if (p_subn->opt.exit_on_fatal) {
1311                         osm_log(&(p_osm->log), OSM_LOG_SYS,
1312                                 "FATAL: Error restoring neighbor link "
1313                                 "persistent database\n");
1314                         return IB_ERROR;
1315                 } else
1316 #endif
1317                         OSM_LOG(&(p_osm->log), OSM_LOG_ERROR,
1318                                 "ERR 7521: Error restoring neighbor link "
1319                                 "persistent database\n");
1320         }
1321
1322         subn_validate_neighbor(p_subn);
1323
1324         return IB_SUCCESS;
1325 }
1326
1327 osm_port_t *osm_get_port_by_mad_addr(IN osm_log_t * p_log,
1328                                      IN const osm_subn_t * p_subn,
1329                                      IN osm_mad_addr_t * p_mad_addr)
1330 {
1331         osm_port_t *port = osm_get_port_by_lid(p_subn, p_mad_addr->dest_lid);
1332         if (!port)
1333                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7504: "
1334                         "Lid is out of range: %u\n",
1335                         cl_ntoh16(p_mad_addr->dest_lid));
1336
1337         return port;
1338 }
1339
1340 ib_api_status_t osm_get_gid_by_mad_addr(IN osm_log_t * p_log,
1341                                         IN const osm_subn_t * p_subn,
1342                                         IN osm_mad_addr_t * p_mad_addr,
1343                                         OUT ib_gid_t * p_gid)
1344 {
1345         const osm_port_t *p_port;
1346
1347         if (p_gid == NULL) {
1348                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7505: "
1349                         "Provided output GID is NULL\n");
1350                 return IB_INVALID_PARAMETER;
1351         }
1352
1353         p_port = osm_get_port_by_mad_addr(p_log, p_subn, p_mad_addr);
1354         if (!p_port)
1355                 return IB_INVALID_PARAMETER;
1356
1357         p_gid->unicast.interface_id = p_port->p_physp->port_guid;
1358         p_gid->unicast.prefix = p_subn->opt.subnet_prefix;
1359
1360         return IB_SUCCESS;
1361 }
1362
1363 osm_physp_t *osm_get_physp_by_mad_addr(IN osm_log_t * p_log,
1364                                        IN const osm_subn_t * p_subn,
1365                                        IN osm_mad_addr_t * p_mad_addr)
1366 {
1367         osm_port_t *p_port;
1368
1369         p_port = osm_get_port_by_mad_addr(p_log, p_subn, p_mad_addr);
1370         if (!p_port)
1371                 return NULL;
1372
1373         return p_port->p_physp;
1374 }
1375
1376 osm_switch_t *osm_get_switch_by_guid(IN const osm_subn_t * p_subn,
1377                                      IN ib_net64_t guid)
1378 {
1379         osm_switch_t *p_switch;
1380
1381         p_switch = (osm_switch_t *) cl_qmap_get(&(p_subn->sw_guid_tbl), guid);
1382         if (p_switch == (osm_switch_t *) cl_qmap_end(&(p_subn->sw_guid_tbl)))
1383                 p_switch = NULL;
1384         return p_switch;
1385 }
1386
1387 osm_node_t *osm_get_node_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid)
1388 {
1389         osm_node_t *p_node;
1390
1391         p_node = (osm_node_t *) cl_qmap_get(&(p_subn->node_guid_tbl), guid);
1392         if (p_node == (osm_node_t *) cl_qmap_end(&(p_subn->node_guid_tbl)))
1393                 p_node = NULL;
1394         return p_node;
1395 }
1396
1397 osm_port_t *osm_get_port_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid)
1398 {
1399         osm_port_t *p_port;
1400
1401         p_port = (osm_port_t *) cl_qmap_get(&(p_subn->port_guid_tbl), guid);
1402         if (p_port == (osm_port_t *) cl_qmap_end(&(p_subn->port_guid_tbl)))
1403                 p_port = NULL;
1404         return p_port;
1405 }
1406
1407 osm_alias_guid_t *osm_get_alias_guid_by_guid(IN osm_subn_t const *p_subn,
1408                                              IN ib_net64_t guid)
1409 {
1410         osm_alias_guid_t *p_alias_guid;
1411
1412         p_alias_guid = (osm_alias_guid_t *) cl_qmap_get(&(p_subn->alias_port_guid_tbl), guid);
1413         if (p_alias_guid == (osm_alias_guid_t *) cl_qmap_end(&(p_subn->alias_port_guid_tbl)))
1414                 return NULL;
1415         return p_alias_guid;
1416 }
1417
1418 osm_port_t *osm_get_port_by_alias_guid(IN osm_subn_t const *p_subn,
1419                                        IN ib_net64_t guid)
1420 {
1421         osm_alias_guid_t *p_alias_guid;
1422
1423         p_alias_guid = osm_get_alias_guid_by_guid(p_subn, guid);
1424         if (!p_alias_guid)
1425                 return NULL;
1426         return p_alias_guid->p_base_port;
1427 }
1428
1429 osm_assigned_guids_t *osm_assigned_guids_new(IN const ib_net64_t port_guid,
1430                                              IN const uint32_t num_guids)
1431 {
1432         osm_assigned_guids_t *p_assigned_guids;
1433
1434         p_assigned_guids = calloc(1, sizeof(*p_assigned_guids) +
1435                                      sizeof(ib_net64_t) * (num_guids - 1));
1436         if (p_assigned_guids)
1437                 p_assigned_guids->port_guid = port_guid;
1438         return p_assigned_guids;
1439 }
1440
1441 void osm_assigned_guids_delete(IN OUT osm_assigned_guids_t ** pp_assigned_guids)
1442 {
1443         free(*pp_assigned_guids);
1444         *pp_assigned_guids = NULL;
1445 }
1446
1447 osm_assigned_guids_t *osm_get_assigned_guids_by_guid(IN osm_subn_t const *p_subn,
1448                                                      IN ib_net64_t port_guid)
1449 {
1450         osm_assigned_guids_t *p_assigned_guids;
1451
1452         p_assigned_guids = (osm_assigned_guids_t *) cl_qmap_get(&(p_subn->assigned_guids_tbl), port_guid);
1453         if (p_assigned_guids == (osm_assigned_guids_t *) cl_qmap_end(&(p_subn->assigned_guids_tbl)))
1454                 return NULL;
1455         return p_assigned_guids;
1456 }
1457
1458 osm_port_t *osm_get_port_by_lid_ho(IN osm_subn_t const * subn, IN uint16_t lid)
1459 {
1460         if (lid < cl_ptr_vector_get_size(&subn->port_lid_tbl))
1461                 return cl_ptr_vector_get(&subn->port_lid_tbl, lid);
1462         return NULL;
1463 }
1464
1465 osm_mgrp_t *osm_get_mgrp_by_mgid(IN osm_subn_t * subn, IN ib_gid_t * mgid)
1466 {
1467         osm_mgrp_t *mgrp;
1468
1469         mgrp = (osm_mgrp_t *)cl_fmap_get(&subn->mgrp_mgid_tbl, mgid);
1470         if (mgrp != (osm_mgrp_t *)cl_fmap_end(&subn->mgrp_mgid_tbl))
1471                 return mgrp;
1472         return NULL;
1473 }
1474
1475 int is_mlnx_ext_port_info_supported(ib_net32_t vendid, ib_net16_t devid)
1476 {
1477         uint32_t vendid_ho;
1478         uint16_t devid_ho;
1479
1480         devid_ho = cl_ntoh16(devid);
1481         if ((devid_ho >= 0xc738 && devid_ho <= 0xc73b) || devid_ho == 0xcb20 ||
1482             devid_ho == 0xcf08 || devid == 0x1b02)
1483                 return 1;
1484         if (devid_ho >= 0x1003 && devid_ho <= 0x1017)
1485                 return 1;
1486
1487         vendid_ho = cl_ntoh32(vendid);
1488         if (vendid_ho == 0x119f) {
1489                 /* Bull Switch-X */
1490                 if (devid_ho == 0x1b02 || devid_ho == 0x1b50)
1491                         return 1;
1492                 /* Bull Switch-IB/IB2 */
1493                 if (devid_ho == 0x1ba0 ||
1494                     (devid_ho >= 0x1bd0 && devid_ho <= 0x1bd5))
1495                         return 1;
1496                 /* Bull Connect-X3 */
1497                 if (devid_ho == 0x1b33 || devid_ho == 0x1b73 ||
1498                     devid_ho == 0x1b40 || devid_ho == 0x1b41 ||
1499                     devid_ho == 0x1b60 || devid_ho == 0x1b61)
1500                         return 1;
1501                 /* Bull Connect-IB */
1502                 if (devid_ho == 0x1b83 ||
1503                     devid_ho == 0x1b93 || devid_ho == 0x1b94)
1504                         return 1;
1505                 /* Bull Connect-X4 */
1506                 if (devid_ho == 0x1bb4 || devid_ho == 0x1bb5 ||
1507                     devid_ho == 0x1bc4)
1508                         return 1;
1509         }
1510         return 0;
1511 }
1512
1513 static void subn_init_qos_options(osm_qos_options_t *opt, osm_qos_options_t *f)
1514 {
1515         opt->max_vls = 0;
1516         opt->high_limit = -1;
1517         if (opt->vlarb_high)
1518                 free(opt->vlarb_high);
1519         opt->vlarb_high = NULL;
1520         if (opt->vlarb_low)
1521                 free(opt->vlarb_low);
1522         opt->vlarb_low = NULL;
1523         if (opt->sl2vl)
1524                 free(opt->sl2vl);
1525         opt->sl2vl = NULL;
1526         if (f)
1527                 memcpy(f, opt, sizeof(*f));
1528 }
1529
1530 void osm_subn_set_default_opt(IN osm_subn_opt_t * p_opt)
1531 {
1532         memset(p_opt, 0, sizeof(osm_subn_opt_t));
1533         p_opt->guid = 0;
1534         p_opt->m_key = OSM_DEFAULT_M_KEY;
1535         p_opt->sm_key = OSM_DEFAULT_SM_KEY;
1536         p_opt->sa_key = OSM_DEFAULT_SA_KEY;
1537         p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
1538         p_opt->m_key_lease_period = 0;
1539         p_opt->m_key_protect_bits = 0;
1540         p_opt->m_key_lookup = TRUE;
1541         p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
1542         p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
1543         p_opt->max_wire_smps2 = p_opt->max_wire_smps;
1544         p_opt->console = strdup(OSM_DEFAULT_CONSOLE);
1545         p_opt->console_port = OSM_DEFAULT_CONSOLE_PORT;
1546         p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
1547         p_opt->transaction_retries = OSM_DEFAULT_RETRY_COUNT;
1548         p_opt->max_smps_timeout = 1000 * p_opt->transaction_timeout *
1549                                   p_opt->transaction_retries;
1550         /* by default we will consider waiting for 50x transaction timeout normal */
1551         p_opt->max_msg_fifo_timeout = 50 * OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
1552         p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
1553         p_opt->lmc = OSM_DEFAULT_LMC;
1554         p_opt->lmc_esp0 = FALSE;
1555         p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
1556         p_opt->force_link_speed = 15;
1557         p_opt->force_link_speed_ext = 31;
1558         p_opt->fdr10 = 1;
1559         p_opt->reassign_lids = FALSE;
1560         p_opt->ignore_other_sm = FALSE;
1561         p_opt->single_thread = FALSE;
1562         p_opt->disable_multicast = FALSE;
1563         p_opt->force_log_flush = FALSE;
1564         p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
1565         p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
1566         p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT;
1567         p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT;
1568         p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
1569         p_opt->leaf_head_of_queue_lifetime =
1570             OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
1571         p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
1572         p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
1573         p_opt->use_mfttop = TRUE;
1574         p_opt->sminfo_polling_timeout =
1575             OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
1576         p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER;
1577         p_opt->force_heavy_sweep = FALSE;
1578         p_opt->log_flags = OSM_LOG_DEFAULT_LEVEL;
1579         p_opt->honor_guid2lid_file = FALSE;
1580         p_opt->daemon = FALSE;
1581         p_opt->sm_inactive = FALSE;
1582         p_opt->babbling_port_policy = FALSE;
1583         p_opt->drop_event_subscriptions = FALSE;
1584         p_opt->ipoib_mcgroup_creation_validation = TRUE;
1585         p_opt->mcgroup_join_validation = TRUE;
1586         p_opt->use_optimized_slvl = FALSE;
1587         p_opt->fsync_high_avail_files = TRUE;
1588 #ifdef ENABLE_OSM_PERF_MGR
1589         p_opt->perfmgr = FALSE;
1590         p_opt->perfmgr_redir = TRUE;
1591         p_opt->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
1592         p_opt->perfmgr_max_outstanding_queries =
1593             OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
1594         p_opt->perfmgr_ignore_cas = FALSE;
1595         p_opt->event_db_dump_file = NULL; /* use default */
1596         p_opt->perfmgr_rm_nodes = TRUE;
1597         p_opt->perfmgr_log_errors = TRUE;
1598         p_opt->perfmgr_query_cpi = TRUE;
1599         p_opt->perfmgr_xmit_wait_log = FALSE;
1600         p_opt->perfmgr_xmit_wait_threshold = OSM_PERFMGR_DEFAULT_XMIT_WAIT_THRESHOLD;
1601 #endif                          /* ENABLE_OSM_PERF_MGR */
1602
1603         p_opt->event_plugin_name = NULL;
1604         p_opt->event_plugin_options = NULL;
1605         p_opt->node_name_map_name = NULL;
1606
1607         p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
1608         if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir))
1609                 p_opt->dump_files_dir = strdup(OSM_DEFAULT_TMP_DIR);
1610         else
1611                 p_opt->dump_files_dir = strdup(p_opt->dump_files_dir);
1612         p_opt->log_file = strdup(OSM_DEFAULT_LOG_FILE);
1613         p_opt->log_max_size = 0;
1614         p_opt->partition_config_file = strdup(OSM_DEFAULT_PARTITION_CONFIG_FILE);
1615         p_opt->no_partition_enforcement = FALSE;
1616         p_opt->part_enforce = strdup(OSM_PARTITION_ENFORCE_BOTH);
1617         p_opt->allow_both_pkeys = FALSE;
1618         p_opt->sm_assigned_guid = 0;
1619         p_opt->qos = FALSE;
1620         p_opt->qos_policy_file = strdup(OSM_DEFAULT_QOS_POLICY_FILE);
1621         p_opt->suppress_sl2vl_mad_status_errors = FALSE;
1622         p_opt->accum_log_file = TRUE;
1623         p_opt->port_prof_ignore_file = NULL;
1624         p_opt->hop_weights_file = NULL;
1625         p_opt->port_search_ordering_file = NULL;
1626         p_opt->port_profile_switch_nodes = FALSE;
1627         p_opt->sweep_on_trap = TRUE;
1628         p_opt->use_ucast_cache = FALSE;
1629         p_opt->routing_engine_names = NULL;
1630         p_opt->connect_roots = FALSE;
1631         p_opt->lid_matrix_dump_file = NULL;
1632         p_opt->lfts_file = NULL;
1633         p_opt->root_guid_file = NULL;
1634         p_opt->cn_guid_file = NULL;
1635         p_opt->io_guid_file = NULL;
1636         p_opt->port_shifting = FALSE;
1637         p_opt->scatter_ports = OSM_DEFAULT_SCATTER_PORTS;
1638         p_opt->max_reverse_hops = 0;
1639         p_opt->ids_guid_file = NULL;
1640         p_opt->guid_routing_order_file = NULL;
1641         p_opt->guid_routing_order_no_scatter = FALSE;
1642         p_opt->sa_db_file = NULL;
1643         p_opt->sa_db_dump = FALSE;
1644         p_opt->torus_conf_file = strdup(OSM_DEFAULT_TORUS_CONF_FILE);
1645         p_opt->do_mesh_analysis = FALSE;
1646         p_opt->exit_on_fatal = TRUE;
1647         p_opt->congestion_control = FALSE;
1648         p_opt->cc_key = OSM_DEFAULT_CC_KEY;
1649         p_opt->cc_max_outstanding_mads = OSM_CC_DEFAULT_MAX_OUTSTANDING_QUERIES;
1650         p_opt->enable_quirks = FALSE;
1651         p_opt->no_clients_rereg = FALSE;
1652         p_opt->prefix_routes_file = strdup(OSM_DEFAULT_PREFIX_ROUTES_FILE);
1653         p_opt->consolidate_ipv6_snm_req = FALSE;
1654         p_opt->lash_start_vl = 0;
1655         p_opt->sm_sl = OSM_DEFAULT_SL;
1656         p_opt->log_prefix = NULL;
1657         p_opt->per_module_logging_file = strdup(OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE);
1658         subn_init_qos_options(&p_opt->qos_options, NULL);
1659         subn_init_qos_options(&p_opt->qos_ca_options, NULL);
1660         subn_init_qos_options(&p_opt->qos_sw0_options, NULL);
1661         subn_init_qos_options(&p_opt->qos_swe_options, NULL);
1662         subn_init_qos_options(&p_opt->qos_rtr_options, NULL);
1663         p_opt->cc_cct.entries_len = 0;
1664         p_opt->cc_cct.input_str = NULL;
1665         p_opt->quasi_ftree_indexing = FALSE;
1666 }
1667
1668 static char *clean_val(char *val)
1669 {
1670         char *p = val;
1671         /* clean leading spaces */
1672         while (isspace(*p))
1673                 p++;
1674         val = p;
1675         if (!*val)
1676                 return val;
1677         /* clean trailing spaces */
1678         p = val + strlen(val) - 1;
1679         while (p > val && isspace(*p))
1680                 p--;
1681         p[1] = '\0';
1682         /* clean quotas */
1683         if ((*val == '\"' && *p == '\"') || (*val == '\'' && *p == '\'')) {
1684                 val++;
1685                 *p-- = '\0';
1686         }
1687         return val;
1688 }
1689
1690 static int subn_dump_qos_options(FILE * file, const char *set_name,
1691                                  const char *prefix, osm_qos_options_t * opt)
1692 {
1693         return fprintf(file, "# %s\n"
1694                        "%s_max_vls %u\n"
1695                        "%s_high_limit %d\n"
1696                        "%s_vlarb_high %s\n"
1697                        "%s_vlarb_low %s\n"
1698                        "%s_sl2vl %s\n",
1699                        set_name,
1700                        prefix, opt->max_vls,
1701                        prefix, opt->high_limit,
1702                        prefix, opt->vlarb_high,
1703                        prefix, opt->vlarb_low, prefix, opt->sl2vl);
1704 }
1705
1706 static ib_api_status_t append_prefix_route(IN osm_subn_t * p_subn,
1707                                            uint64_t prefix, uint64_t guid)
1708 {
1709         osm_prefix_route_t *route;
1710
1711         route = malloc(sizeof *route);
1712         if (! route) {
1713                 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "out of memory");
1714                 return IB_ERROR;
1715         }
1716
1717         route->prefix = cl_hton64(prefix);
1718         route->guid = cl_hton64(guid);
1719         cl_qlist_insert_tail(&p_subn->prefix_routes_list, &route->list_item);
1720         return IB_SUCCESS;
1721 }
1722
1723 static ib_api_status_t parse_prefix_routes_file(IN osm_subn_t * p_subn)
1724 {
1725         osm_log_t *log = &p_subn->p_osm->log;
1726         FILE *fp;
1727         char buf[1024];
1728         int line = 0;
1729         int errors = 0;
1730
1731         while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
1732                 cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
1733                 free(item);
1734         }
1735
1736         fp = fopen(p_subn->opt.prefix_routes_file, "r");
1737         if (! fp) {
1738                 if (errno == ENOENT)
1739                         return IB_SUCCESS;
1740
1741                 OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s",
1742                         p_subn->opt.prefix_routes_file, strerror(errno));
1743                 return IB_ERROR;
1744         }
1745
1746         while (fgets(buf, sizeof buf, fp) != NULL) {
1747                 char *p_prefix, *p_guid, *p_extra, *p_last, *p_end;
1748                 uint64_t prefix, guid;
1749
1750                 line++;
1751                 if (errors > 10)
1752                         break;
1753
1754                 p_prefix = strtok_r(buf, " \t\n", &p_last);
1755                 if (! p_prefix)
1756                         continue; /* ignore blank lines */
1757
1758                 if (*p_prefix == '#')
1759                         continue; /* ignore comment lines */
1760
1761                 p_guid = strtok_r(NULL, " \t\n", &p_last);
1762                 if (! p_guid) {
1763                         OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing GUID\n",
1764                                 p_subn->opt.prefix_routes_file, line);
1765                         errors++;
1766                         continue;
1767                 }
1768
1769                 p_extra = strtok_r(NULL, " \t\n", &p_last);
1770                 if (p_extra && *p_extra != '#') {
1771                         OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n",
1772                                 p_subn->opt.prefix_routes_file, line);
1773                 }
1774
1775                 if (strcmp(p_prefix, "*") == 0)
1776                         prefix = 0;
1777                 else {
1778                         prefix = strtoull(p_prefix, &p_end, 16);
1779                         if (*p_end != '\0') {
1780                                 OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal prefix: %s\n",
1781                                         p_subn->opt.prefix_routes_file, line, p_prefix);
1782                                 errors++;
1783                                 continue;
1784                         }
1785                 }
1786
1787                 if (strcmp(p_guid, "*") == 0)
1788                         guid = 0;
1789                 else {
1790                         guid = strtoull(p_guid, &p_end, 16);
1791                         if (*p_end != '\0' && *p_end != '#') {
1792                                 OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal GUID: %s\n",
1793                                         p_subn->opt.prefix_routes_file, line, p_guid);
1794                                 errors++;
1795                                 continue;
1796                         }
1797                 }
1798
1799                 if (append_prefix_route(p_subn, prefix, guid) != IB_SUCCESS) {
1800                         errors++;
1801                         break;
1802                 }
1803         }
1804
1805         fclose(fp);
1806         return (errors == 0) ? IB_SUCCESS : IB_ERROR;
1807 }
1808
1809 static ib_api_status_t insert_per_module_debug(IN osm_subn_t * p_subn,
1810                                                char *mod_name,
1811                                                osm_log_level_t level)
1812 {
1813         uint8_t index;
1814
1815         if (find_module_name(mod_name, &index)) {
1816                 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
1817                         "Module name %s not found\n", mod_name);
1818                 return IB_ERROR;
1819         }
1820         osm_set_log_per_module(&p_subn->p_osm->log, index, level);
1821         return IB_SUCCESS;
1822 }
1823
1824 static ib_api_status_t parse_per_mod_logging_file(IN osm_subn_t * p_subn)
1825 {
1826         osm_log_t *log = &p_subn->p_osm->log;
1827         FILE *fp;
1828         char buf[1024];
1829         int line = 0;
1830         int errors = 0;
1831
1832         osm_reset_log_per_module(log);
1833
1834         if (p_subn->opt.per_module_logging_file == NULL)
1835                 return IB_SUCCESS;
1836
1837         fp = fopen(p_subn->opt.per_module_logging_file, "r");
1838         if (!fp) {
1839                 if (errno == ENOENT)
1840                         return IB_SUCCESS;
1841
1842                 OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s",
1843                         p_subn->opt.per_module_logging_file, strerror(errno));
1844                 return IB_ERROR;
1845         }
1846
1847         while (fgets(buf, sizeof buf, fp) != NULL) {
1848                 char *p_mod_name, *p_level, *p_extra, *p_last;
1849                 osm_log_level_t level;
1850
1851                 line++;
1852                 if (errors > 10)
1853                         break;
1854
1855                 p_mod_name = strtok_r(buf, " =,\t\n", &p_last);
1856                 if (!p_mod_name)
1857                         continue; /* ignore blank lines */
1858
1859                 if (*p_mod_name == '#')
1860                         continue; /* ignore comment lines */
1861
1862                 p_level = strtok_r(NULL, " \t\n", &p_last);
1863                 if (!p_level) {
1864                         OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing log level\n",
1865                                 p_subn->opt.per_module_logging_file, line);
1866                         errors++;
1867                         continue;
1868                 }
1869                 p_extra = strtok_r(NULL, " \t\n", &p_last);
1870                 if (p_extra && *p_extra != '#') {
1871                         OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n",
1872                                 p_subn->opt.per_module_logging_file, line);
1873                 }
1874
1875                 level = strtoul(p_level, NULL, 0);
1876                 if (insert_per_module_debug(p_subn, p_mod_name, level) != IB_SUCCESS) {
1877                         errors++;
1878                         break;
1879                 }
1880         }
1881
1882         fclose(fp);
1883         return (errors == 0) ? IB_SUCCESS : IB_ERROR;
1884 }
1885
1886 static void subn_verify_max_vls(unsigned *max_vls, const char *prefix)
1887 {
1888         if (!*max_vls || *max_vls > 15) {
1889                 if (*max_vls)
1890                         log_report(" Invalid Cached Option: %s_max_vls=%u: "
1891                                    "Using Default = %u\n",
1892                                    prefix, *max_vls, OSM_DEFAULT_QOS_MAX_VLS);
1893                 *max_vls = 0;
1894         }
1895 }
1896
1897 static void subn_verify_high_limit(int *high_limit, const char *prefix)
1898 {
1899         if (*high_limit < 0 || *high_limit > 255) {
1900                 if (*high_limit > 255)
1901                         log_report(" Invalid Cached Option: %s_high_limit=%d: "
1902                                    "Using Default: %d\n",
1903                                    prefix, *high_limit,
1904                                    OSM_DEFAULT_QOS_HIGH_LIMIT);
1905                 *high_limit = -1;
1906         }
1907 }
1908
1909 static void subn_verify_vlarb(char **vlarb, const char *prefix,
1910                               const char *suffix)
1911 {
1912         char *str, *tok, *end, *ptr;
1913         int count = 0;
1914
1915         if (*vlarb == NULL)
1916                 return;
1917
1918         str = strdup(*vlarb);
1919
1920         tok = strtok_r(str, ",\n", &ptr);
1921         while (tok) {
1922                 char *vl_str, *weight_str;
1923
1924                 vl_str = tok;
1925                 weight_str = strchr(tok, ':');
1926
1927                 if (weight_str) {
1928                         long vl, weight;
1929
1930                         *weight_str = '\0';
1931                         weight_str++;
1932
1933                         vl = strtol(vl_str, &end, 0);
1934
1935                         if (*end)
1936                                 log_report(" Warning: Cached Option "
1937                                            "%s_vlarb_%s:vl=%s"
1938                                            " improperly formatted\n",
1939                                            prefix, suffix, vl_str);
1940                         else if (vl < 0 || vl > 14)
1941                                 log_report(" Warning: Cached Option "
1942                                            "%s_vlarb_%s:vl=%ld out of range\n",
1943                                            prefix, suffix, vl);
1944
1945                         weight = strtol(weight_str, &end, 0);
1946
1947                         if (*end)
1948                                 log_report(" Warning: Cached Option "
1949                                            "%s_vlarb_%s:weight=%s "
1950                                            "improperly formatted\n",
1951                                            prefix, suffix, weight_str);
1952                         else if (weight < 0 || weight > 255)
1953                                 log_report(" Warning: Cached Option "
1954                                            "%s_vlarb_%s:weight=%ld "
1955                                            "out of range\n",
1956                                            prefix, suffix, weight);
1957                 } else
1958                         log_report(" Warning: Cached Option "
1959                                    "%s_vlarb_%s:vl:weight=%s "
1960                                    "improperly formatted\n",
1961                                    prefix, suffix, tok);
1962
1963                 count++;
1964                 tok = strtok_r(NULL, ",\n", &ptr);
1965         }
1966
1967         if (count > 64)
1968                 log_report(" Warning: Cached Option %s_vlarb_%s: > 64 listed:"
1969                            " excess vl:weight pairs will be dropped\n",
1970                            prefix, suffix);
1971
1972         free(str);
1973 }
1974
1975 static void subn_verify_sl2vl(char **sl2vl, const char *prefix)
1976 {
1977         char *str, *tok, *end, *ptr;
1978         int count = 0;
1979
1980         if (*sl2vl == NULL)
1981                 return;
1982
1983         str = strdup(*sl2vl);
1984
1985         tok = strtok_r(str, ",\n", &ptr);
1986         while (tok) {
1987                 long vl = strtol(tok, &end, 0);
1988
1989                 if (*end)
1990                         log_report(" Warning: Cached Option %s_sl2vl:vl=%s "
1991                                    "improperly formatted\n", prefix, tok);
1992                 else if (vl < 0 || vl > 15)
1993                         log_report(" Warning: Cached Option %s_sl2vl:vl=%ld "
1994                                    "out of range\n", prefix, vl);
1995
1996                 count++;
1997                 tok = strtok_r(NULL, ",\n", &ptr);
1998         }
1999
2000         if (count < 16)
2001                 log_report(" Warning: Cached Option %s_sl2vl: < 16 VLs "
2002                            "listed\n", prefix);
2003         else if (count > 16)
2004                 log_report(" Warning: Cached Option %s_sl2vl: > 16 listed: "
2005                            "excess VLs will be dropped\n", prefix);
2006
2007         free(str);
2008 }
2009
2010 static void subn_verify_qos_set(osm_qos_options_t *set, const char *prefix)
2011 {
2012         subn_verify_max_vls(&set->max_vls, prefix);
2013         subn_verify_high_limit(&set->high_limit, prefix);
2014         subn_verify_vlarb(&set->vlarb_low, prefix, "low");
2015         subn_verify_vlarb(&set->vlarb_high, prefix, "high");
2016         subn_verify_sl2vl(&set->sl2vl, prefix);
2017 }
2018
2019 int osm_subn_verify_config(IN osm_subn_opt_t * p_opts)
2020 {
2021         if (p_opts->lmc > 7) {
2022                 log_report(" Invalid Cached Option Value:lmc = %u:"
2023                            "Using Default:%u\n", p_opts->lmc, OSM_DEFAULT_LMC);
2024                 p_opts->lmc = OSM_DEFAULT_LMC;
2025         }
2026
2027         if (15 < p_opts->sm_priority) {
2028                 log_report(" Invalid Cached Option Value:sm_priority = %u:"
2029                            "Using Default:%u\n",
2030                            p_opts->sm_priority, OSM_DEFAULT_SM_PRIORITY);
2031                 p_opts->sm_priority = OSM_DEFAULT_SM_PRIORITY;
2032         }
2033
2034         if ((15 < p_opts->force_link_speed) ||
2035             (p_opts->force_link_speed > 7 && p_opts->force_link_speed < 15)) {
2036                 log_report(" Invalid Cached Option Value:force_link_speed = %u:"
2037                            "Using Default:%u\n", p_opts->force_link_speed,
2038                            IB_PORT_LINK_SPEED_ENABLED_MASK);
2039                 p_opts->force_link_speed = IB_PORT_LINK_SPEED_ENABLED_MASK;
2040         }
2041
2042         if ((31 < p_opts->force_link_speed_ext) ||
2043             (p_opts->force_link_speed_ext > 3 && p_opts->force_link_speed_ext < 30)) {
2044                 log_report(" Invalid Cached Option Value:force_link_speed_ext = %u:"
2045                            "Using Default:%u\n", p_opts->force_link_speed_ext,
2046                            31);
2047                 p_opts->force_link_speed_ext = 31;
2048         }
2049
2050         if (2 < p_opts->fdr10) {
2051                 log_report(" Invalid Cached Option Value:fdr10 = %u:"
2052                            "Using Default:%u\n", p_opts->fdr10, 1);
2053                 p_opts->fdr10 = 1;
2054         }
2055
2056         if (p_opts->max_wire_smps == 0)
2057                 p_opts->max_wire_smps = 0x7FFFFFFF;
2058         else if (p_opts->max_wire_smps > 0x7FFFFFFF) {
2059                 log_report(" Invalid Cached Option Value: max_wire_smps = %u,"
2060                            " Using Default: %u\n",
2061                            p_opts->max_wire_smps, OSM_DEFAULT_SMP_MAX_ON_WIRE);
2062                 p_opts->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
2063         }
2064
2065         if (p_opts->max_wire_smps2 > 0x7FFFFFFF) {
2066                 log_report(" Invalid Cached Option Value: max_wire_smps2 = %u,"
2067                            " Using Default: %u",
2068                            p_opts->max_wire_smps2, p_opts->max_wire_smps);
2069                 p_opts->max_wire_smps2 = p_opts->max_wire_smps;
2070         }
2071
2072         if (strcmp(p_opts->console, OSM_DISABLE_CONSOLE)
2073             && strcmp(p_opts->console, OSM_LOCAL_CONSOLE)
2074 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
2075             && strcmp(p_opts->console, OSM_LOOPBACK_CONSOLE)
2076 #endif
2077 #ifdef ENABLE_OSM_CONSOLE_SOCKET
2078             && strcmp(p_opts->console, OSM_REMOTE_CONSOLE)
2079 #endif
2080             ) {
2081                 log_report(" Invalid Cached Option Value:console = %s"
2082                            ", Using Default:%s\n",
2083                            p_opts->console, OSM_DEFAULT_CONSOLE);
2084                 free(p_opts->console);
2085                 p_opts->console = strdup(OSM_DEFAULT_CONSOLE);
2086         }
2087
2088         if (p_opts->no_partition_enforcement == TRUE) {
2089                 strcpy(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OFF);
2090                 p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF;
2091         } else {
2092                 if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH) == 0)
2093                         p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH;
2094                 else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_IN) == 0)
2095                         p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_IN;
2096                 else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OUT) == 0)
2097                         p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OUT;
2098                 else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OFF) == 0)
2099                         p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF;
2100                 else {
2101                         log_report(" Invalid Cached Option Value:part_enforce = %s"
2102                                    ", Using Default:%s\n",
2103                                    p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH);
2104                         strcpy(p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH);
2105                         p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH;
2106                 }
2107         }
2108
2109         if (p_opts->qos) {
2110                 subn_verify_qos_set(&p_opts->qos_options, "qos");
2111                 subn_verify_qos_set(&p_opts->qos_ca_options, "qos_ca");
2112                 subn_verify_qos_set(&p_opts->qos_sw0_options, "qos_sw0");
2113                 subn_verify_qos_set(&p_opts->qos_swe_options, "qos_swe");
2114                 subn_verify_qos_set(&p_opts->qos_rtr_options, "qos_rtr");
2115         }
2116
2117 #ifdef ENABLE_OSM_PERF_MGR
2118         if (p_opts->perfmgr_sweep_time_s < 1) {
2119                 log_report(" Invalid Cached Option Value:perfmgr_sweep_time_s "
2120                            "= %u Using Default:%u\n",
2121                            p_opts->perfmgr_sweep_time_s,
2122                            OSM_PERFMGR_DEFAULT_SWEEP_TIME_S);
2123                 p_opts->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
2124         }
2125         if (p_opts->perfmgr_max_outstanding_queries < 1) {
2126                 log_report(" Invalid Cached Option Value:"
2127                            "perfmgr_max_outstanding_queries = %u"
2128                            " Using Default:%u\n",
2129                            p_opts->perfmgr_max_outstanding_queries,
2130                            OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES);
2131                 p_opts->perfmgr_max_outstanding_queries =
2132                     OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
2133         }
2134 #endif
2135
2136         if (p_opts->m_key_protect_bits > 3) {
2137                 log_report(" Invalid Cached Option Value:"
2138                            "m_key_protection_level = %u Setting to %u "
2139                            "instead\n", p_opts->m_key_protect_bits, 2);
2140                 p_opts->m_key_protect_bits = 2;
2141         }
2142         if (p_opts->m_key_protect_bits && p_opts->m_key_lease_period) {
2143                 if (!p_opts->sweep_interval) {
2144                         log_report(" Sweep disabled with protected mkey "
2145                                    "leases in effect; re-enabling sweeping "
2146                                    "with interval %u\n",
2147                                    cl_ntoh16(p_opts->m_key_lease_period) - 1);
2148                         p_opts->sweep_interval =
2149                                 cl_ntoh16(p_opts->m_key_lease_period) - 1;
2150                 }
2151                 if (p_opts->sweep_interval >=
2152                         cl_ntoh16(p_opts->m_key_lease_period)) {
2153                         log_report(" Sweep interval %u >= mkey lease period "
2154                                    "%u. Setting lease period to %u\n",
2155                                    p_opts->sweep_interval,
2156                                    cl_ntoh16(p_opts->m_key_lease_period),
2157                                    p_opts->sweep_interval + 1);
2158                         p_opts->m_key_lease_period =
2159                                 cl_hton16(p_opts->sweep_interval + 1);
2160                 }
2161         }
2162
2163         return 0;
2164 }
2165
2166 int osm_subn_parse_conf_file(const char *file_name, osm_subn_opt_t * p_opts)
2167 {
2168         char line[1024];
2169         FILE *opts_file;
2170         char *p_key, *p_val, *pound_sign;
2171         const opt_rec_t *r;
2172         void *p_field1, *p_field2;
2173         int token_matched;
2174
2175         opts_file = fopen(file_name, "r");
2176         if (!opts_file) {
2177                 if (errno == ENOENT)
2178                         return 1;
2179                 printf("cannot open file \'%s\': %s\n",
2180                        file_name, strerror(errno));
2181                 return -1;
2182         }
2183
2184         printf(" Reading Cached Option File: %s\n", file_name);
2185
2186         p_opts->config_file = file_name;
2187         if (!p_opts->file_opts && !(p_opts->file_opts = malloc(sizeof(*p_opts)))) {
2188                 fclose(opts_file);
2189                 return -1;
2190         }
2191         memcpy(p_opts->file_opts, p_opts, sizeof(*p_opts));
2192         p_opts->file_opts->file_opts = NULL;
2193
2194         while (fgets(line, 1023, opts_file) != NULL) {
2195                 pound_sign = strchr(line,'#');
2196                 token_matched = 0;
2197                 /* Truncate any comments. */
2198                 if (pound_sign)
2199                         *pound_sign = '\0';
2200
2201                 /* get the first token */
2202                 p_key = strtok_r(line, " \t\n", &p_val);
2203                 if (!p_key)
2204                         continue;
2205
2206                 p_val = clean_val(p_val);
2207
2208                 for (r = opt_tbl; r->name; r++) {
2209                         if (strcmp(r->name, p_key))
2210                                 continue;
2211
2212                         token_matched = 1;
2213                         p_field1 = (void *)p_opts->file_opts + r->opt_offset;
2214                         p_field2 = (void *)p_opts + r->opt_offset;
2215                         /* don't call setup function first time */
2216                         r->parse_fn(NULL, p_key, p_val, p_field1, p_field2,
2217                                     NULL);
2218                         break;
2219                 }
2220
2221                 if (!token_matched)
2222                         log_report(" Unrecognized token: \"%s\"\n", p_key);
2223         }
2224         fclose(opts_file);
2225
2226         osm_subn_verify_config(p_opts);
2227
2228         return 0;
2229 }
2230
2231 int osm_subn_rescan_conf_files(IN osm_subn_t * p_subn)
2232 {
2233         char line[1024];
2234         osm_subn_opt_t *p_opts = &p_subn->opt;
2235         const opt_rec_t *r;
2236         FILE *opts_file;
2237         char *p_key, *p_val, *pound_sign;
2238         void *p_field1, *p_field2;
2239         int token_matched;
2240
2241         if (!p_opts->config_file)
2242                 return 0;
2243
2244         opts_file = fopen(p_opts->config_file, "r");
2245         if (!opts_file) {
2246                 if (errno == ENOENT)
2247                         return 1;
2248                 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
2249                         "cannot open file \'%s\': %s\n",
2250                         p_opts->config_file, strerror(errno));
2251                 return -1;
2252         }
2253
2254         subn_init_qos_options(&p_opts->qos_options,
2255                               &p_opts->file_opts->qos_options);
2256         subn_init_qos_options(&p_opts->qos_ca_options,
2257                               &p_opts->file_opts->qos_ca_options);
2258         subn_init_qos_options(&p_opts->qos_sw0_options,
2259                               &p_opts->file_opts->qos_sw0_options);
2260         subn_init_qos_options(&p_opts->qos_swe_options,
2261                               &p_opts->file_opts->qos_swe_options);
2262         subn_init_qos_options(&p_opts->qos_rtr_options,
2263                               &p_opts->file_opts->qos_rtr_options);
2264
2265         while (fgets(line, 1023, opts_file) != NULL) {
2266                 pound_sign = strchr(line,'#');
2267                 token_matched = 0;
2268
2269                 /* Truncate any comments. */
2270                 if (pound_sign)
2271                         *pound_sign = '\0';
2272
2273                 /* get the first token */
2274                 p_key = strtok_r(line, " \t\n", &p_val);
2275                 if (!p_key)
2276                         continue;
2277
2278                 p_val = clean_val(p_val);
2279
2280                 for (r = opt_tbl; r->name; r++) {
2281                         if (strcmp(r->name, p_key))
2282                                 continue;
2283
2284                         token_matched = 1;
2285
2286                         if (!r->can_update)
2287                                 continue;
2288
2289                         p_field1 = (void *)p_opts->file_opts + r->opt_offset;
2290                         p_field2 = (void *)p_opts + r->opt_offset;
2291                         r->parse_fn(p_subn, p_key, p_val, p_field1, p_field2,
2292                                     r->setup_fn);
2293                         break;
2294                 }
2295                 if (!token_matched)
2296                        log_report(" Unrecognized token: \"%s\"\n", p_key);
2297         }
2298         fclose(opts_file);
2299
2300         osm_subn_verify_config(p_opts);
2301
2302         parse_prefix_routes_file(p_subn);
2303
2304         parse_per_mod_logging_file(p_subn);
2305
2306         return 0;
2307 }
2308
2309 void osm_subn_output_conf(FILE *out, IN osm_subn_opt_t * p_opts)
2310 {
2311         int cacongoutputcount = 0;
2312         int i;
2313
2314         fprintf(out,
2315                 "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
2316                 "# The port GUID on which the OpenSM is running\n"
2317                 "guid 0x%016" PRIx64 "\n\n"
2318                 "# M_Key value sent to all ports qualifying all Set(PortInfo)\n"
2319                 "m_key 0x%016" PRIx64 "\n\n"
2320                 "# The lease period used for the M_Key on this subnet in [sec]\n"
2321                 "m_key_lease_period %u\n\n"
2322                 "# The protection level used for the M_Key on this subnet\n"
2323                 "m_key_protection_level %u\n\n"
2324                 "# If TRUE, SM tries to determine the m_key of unknown ports from guid2mkey file\n"
2325                 "# If FALSE, SM won't try to determine the m_key of unknown ports.\n"
2326                 "# Preconfigured m_key will be used instead\n"
2327                 "m_key_lookup %s\n\n"
2328                 "# SM_Key value of the SM used for SM authentication\n"
2329                 "sm_key 0x%016" PRIx64 "\n\n"
2330                 "# SM_Key value to qualify rcv SA queries as 'trusted'\n"
2331                 "sa_key 0x%016" PRIx64 "\n\n"
2332                 "# Note that for both values above (sm_key and sa_key)\n"
2333                 "# OpenSM version 3.2.1 and below used the default value '1'\n"
2334                 "# in a host byte order, it is fixed now but you may need to\n"
2335                 "# change the values to interoperate with old OpenSM running\n"
2336                 "# on a little endian machine.\n\n"
2337                 "# Subnet prefix used on this subnet\n"
2338                 "subnet_prefix 0x%016" PRIx64 "\n\n"
2339                 "# The LMC value used on this subnet\n"
2340                 "lmc %u\n\n"
2341                 "# lmc_esp0 determines whether LMC value used on subnet is used for\n"
2342                 "# enhanced switch port 0. If TRUE, LMC value for subnet is used for\n"
2343                 "# ESP0. Otherwise, LMC value for ESP0s is 0.\n"
2344                 "lmc_esp0 %s\n\n"
2345                 "# sm_sl determines SMSL used for SM/SA communication\n"
2346                 "sm_sl %u\n\n"
2347                 "# The code of maximal time a packet can live in a switch\n"
2348                 "# The actual time is 4.096usec * 2^<packet_life_time>\n"
2349                 "# The value 0x14 disables this mechanism\n"
2350                 "packet_life_time 0x%02x\n\n"
2351                 "# The number of sequential packets dropped that cause the port\n"
2352                 "# to enter the VLStalled state. The result of setting this value to\n"
2353                 "# zero is undefined.\n"
2354                 "vl_stall_count 0x%02x\n\n"
2355                 "# The number of sequential packets dropped that cause the port\n"
2356                 "# to enter the VLStalled state. This value is for switch ports\n"
2357                 "# driving a CA or router port. The result of setting this value\n"
2358                 "# to zero is undefined.\n"
2359                 "leaf_vl_stall_count 0x%02x\n\n"
2360                 "# The code of maximal time a packet can wait at the head of\n"
2361                 "# transmission queue.\n"
2362                 "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
2363                 "# The value 0x14 disables this mechanism\n"
2364                 "head_of_queue_lifetime 0x%02x\n\n"
2365                 "# The maximal time a packet can wait at the head of queue on\n"
2366                 "# switch port connected to a CA or router port\n"
2367                 "leaf_head_of_queue_lifetime 0x%02x\n\n"
2368                 "# Limit the maximal operational VLs\n"
2369                 "max_op_vls %u\n\n"
2370                 "# Force PortInfo:LinkSpeedEnabled on switch ports\n"
2371                 "# If 0, don't modify PortInfo:LinkSpeedEnabled on switch port\n"
2372                 "# Otherwise, use value for PortInfo:LinkSpeedEnabled on switch port\n"
2373                 "# Values are (IB Spec 1.2.1, 14.2.5.6 Table 146 \"PortInfo\")\n"
2374                 "#    1: 2.5 Gbps\n"
2375                 "#    3: 2.5 or 5.0 Gbps\n"
2376                 "#    5: 2.5 or 10.0 Gbps\n"
2377                 "#    7: 2.5 or 5.0 or 10.0 Gbps\n"
2378                 "#    2,4,6,8-14 Reserved\n"
2379                 "#    Default 15: set to PortInfo:LinkSpeedSupported\n"
2380                 "force_link_speed %u\n\n"
2381                 "# Force PortInfo:LinkSpeedExtEnabled on ports\n"
2382                 "# If 0, don't modify PortInfo:LinkSpeedExtEnabled on port\n"
2383                 "# Otherwise, use value for PortInfo:LinkSpeedExtEnabled on port\n"
2384                 "# Values are (MgtWG RefID #4722)\n"
2385                 "#    1: 14.0625 Gbps\n"
2386                 "#    2: 25.78125 Gbps\n"
2387                 "#    3: 14.0625 Gbps or 25.78125 Gbps\n"
2388                 "#    30: Disable extended link speeds\n"
2389                 "#    Default 31: set to PortInfo:LinkSpeedExtSupported\n"
2390                 "force_link_speed_ext %u\n\n"
2391                 "# FDR10 on ports on devices that support FDR10\n"
2392                 "# Values are:\n"
2393                 "#    0: don't use fdr10 (no MLNX ExtendedPortInfo MADs)\n"
2394                 "#    Default 1: enable fdr10 when supported\n"
2395                 "#    2: disable fdr10 when supported\n"
2396                 "fdr10 %u\n\n"
2397                 "# The subnet_timeout code that will be set for all the ports\n"
2398                 "# The actual timeout is 4.096usec * 2^<subnet_timeout>\n"
2399                 "subnet_timeout %u\n\n"
2400                 "# Threshold of local phy errors for sending Trap 129\n"
2401                 "local_phy_errors_threshold 0x%02x\n\n"
2402                 "# Threshold of credit overrun errors for sending Trap 130\n"
2403                 "overrun_errors_threshold 0x%02x\n\n"
2404                 "# Use SwitchInfo:MulticastFDBTop if advertised in PortInfo:CapabilityMask\n"
2405                 "use_mfttop %s\n\n",
2406                 cl_ntoh64(p_opts->guid),
2407                 cl_ntoh64(p_opts->m_key),
2408                 cl_ntoh16(p_opts->m_key_lease_period),
2409                 p_opts->m_key_protect_bits,
2410                 p_opts->m_key_lookup ? "TRUE" : "FALSE",
2411                 cl_ntoh64(p_opts->sm_key),
2412                 cl_ntoh64(p_opts->sa_key),
2413                 cl_ntoh64(p_opts->subnet_prefix),
2414                 p_opts->lmc,
2415                 p_opts->lmc_esp0 ? "TRUE" : "FALSE",
2416                 p_opts->sm_sl,
2417                 p_opts->packet_life_time,
2418                 p_opts->vl_stall_count,
2419                 p_opts->leaf_vl_stall_count,
2420                 p_opts->head_of_queue_lifetime,
2421                 p_opts->leaf_head_of_queue_lifetime,
2422                 p_opts->max_op_vls,
2423                 p_opts->force_link_speed,
2424                 p_opts->force_link_speed_ext,
2425                 p_opts->fdr10,
2426                 p_opts->subnet_timeout,
2427                 p_opts->local_phy_errors_threshold,
2428                 p_opts->overrun_errors_threshold,
2429                 p_opts->use_mfttop ? "TRUE" : "FALSE");
2430
2431         fprintf(out,
2432                 "#\n# PARTITIONING OPTIONS\n#\n"
2433                 "# Partition configuration file to be used\n"
2434                 "partition_config_file %s\n\n"
2435                 "# Disable partition enforcement by switches (DEPRECATED)\n"
2436                 "# This option is DEPRECATED. Please use part_enforce instead\n"
2437                 "no_partition_enforcement %s\n\n"
2438                 "# Partition enforcement type (for switches)\n"
2439                 "# Values are both, out, in and off\n"
2440                 "# Default is both (outbound and inbound enforcement)\n"
2441                 "part_enforce %s\n\n"
2442                 "# Allow both full and limited membership on the same partition\n"
2443                 "allow_both_pkeys %s\n\n"
2444                 "# SM assigned GUID byte where GUID is formed from OpenFabrics OUI\n"
2445                 "# followed by 40 bits xy 00 ab cd ef where xy is the SM assigned GUID byte\n"
2446                 "# and ab cd ef is an SM autogenerated 24 bits\n"
2447                 "# SM assigned GUID byte should be configured as subnet unique\n"
2448                 "sm_assigned_guid 0x%02x\n\n",
2449                 p_opts->partition_config_file,
2450                 p_opts->no_partition_enforcement ? "TRUE" : "FALSE",
2451                 p_opts->part_enforce,
2452                 p_opts->allow_both_pkeys ? "TRUE" : "FALSE",
2453                 p_opts->sm_assigned_guid);
2454
2455         fprintf(out,
2456                 "#\n# SWEEP OPTIONS\n#\n"
2457                 "# The number of seconds between subnet sweeps (0 disables it)\n"
2458                 "sweep_interval %u\n\n"
2459                 "# If TRUE cause all lids to be reassigned\n"
2460                 "reassign_lids %s\n\n"
2461                 "# If TRUE forces every sweep to be a heavy sweep\n"
2462                 "force_heavy_sweep %s\n\n"
2463                 "# If TRUE every trap 128 and 144 will cause a heavy sweep.\n"
2464                 "# NOTE: successive identical traps (>10) are suppressed\n"
2465                 "sweep_on_trap %s\n\n",
2466                 p_opts->sweep_interval,
2467                 p_opts->reassign_lids ? "TRUE" : "FALSE",
2468                 p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
2469                 p_opts->sweep_on_trap ? "TRUE" : "FALSE");
2470
2471         fprintf(out,
2472                 "#\n# ROUTING OPTIONS\n#\n"
2473                 "# If TRUE count switches as link subscriptions\n"
2474                 "port_profile_switch_nodes %s\n\n",
2475                 p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
2476
2477         fprintf(out,
2478                 "# Name of file with port guids to be ignored by port profiling\n"
2479                 "port_prof_ignore_file %s\n\n", p_opts->port_prof_ignore_file ?
2480                 p_opts->port_prof_ignore_file : null_str);
2481
2482         fprintf(out,
2483                 "# The file holding routing weighting factors per output port\n"
2484                 "hop_weights_file %s\n\n",
2485                 p_opts->hop_weights_file ? p_opts->hop_weights_file : null_str);
2486
2487         fprintf(out,
2488                 "# The file holding non-default port order per switch for routing\n"
2489                 "port_search_ordering_file %s\n\n",
2490                 p_opts->port_search_ordering_file ?
2491                 p_opts->port_search_ordering_file : null_str);
2492
2493         fprintf(out,
2494                 "# Routing engine\n"
2495                 "# Multiple routing engines can be specified separated by\n"
2496                 "# commas so that specific ordering of routing algorithms will\n"
2497                 "# be tried if earlier routing engines fail.\n"
2498                 "# Supported engines: minhop, updn, dnup, file, ftree, lash,\n"
2499                 "#    dor, torus-2QoS, dfsssp, sssp\n"
2500                 "routing_engine %s\n\n", p_opts->routing_engine_names ?
2501                 p_opts->routing_engine_names : null_str);
2502
2503         fprintf(out,
2504                 "# Connect roots (use FALSE if unsure)\n"
2505                 "connect_roots %s\n\n",
2506                 p_opts->connect_roots ? "TRUE" : "FALSE");
2507
2508         fprintf(out,
2509                 "# Use unicast routing cache (use FALSE if unsure)\n"
2510                 "use_ucast_cache %s\n\n",
2511                 p_opts->use_ucast_cache ? "TRUE" : "FALSE");
2512
2513         fprintf(out,
2514                 "# Lid matrix dump file name\n"
2515                 "lid_matrix_dump_file %s\n\n", p_opts->lid_matrix_dump_file ?
2516                 p_opts->lid_matrix_dump_file : null_str);
2517
2518         fprintf(out,
2519                 "# LFTs file name\nlfts_file %s\n\n",
2520                 p_opts->lfts_file ? p_opts->lfts_file : null_str);
2521
2522         fprintf(out,
2523                 "# The file holding the root node guids (for fat-tree or Up/Down)\n"
2524                 "# One guid in each line\nroot_guid_file %s\n\n",
2525                 p_opts->root_guid_file ? p_opts->root_guid_file : null_str);
2526
2527         fprintf(out,
2528                 "# The file holding the fat-tree compute node guids\n"
2529                 "# One guid in each line\ncn_guid_file %s\n\n",
2530                 p_opts->cn_guid_file ? p_opts->cn_guid_file : null_str);
2531
2532         fprintf(out,
2533                 "# The file holding the fat-tree I/O node guids\n"
2534                 "# One guid in each line.\n"
2535                 "# If only io_guid file is provided, the rest of nodes\n"
2536                 "# are considered as compute nodes.\n"
2537                 "io_guid_file %s\n\n",
2538                 p_opts->io_guid_file ? p_opts->io_guid_file : null_str);
2539
2540         fprintf(out,
2541                 "# If TRUE enables alternative indexing policy for ftree routing\n"
2542                 "# in quasi-ftree topologies that can improve shift-pattern support.\n"
2543                 "# The switch indexing starts from root switch and leaf switches\n"
2544                 "# are termination points of BFS algorithm\n"
2545                 "# If FALSE, the indexing starts from leaf switch (default)\n"
2546                 "quasi_ftree_indexing %s\n\n",
2547                 p_opts->quasi_ftree_indexing ? "TRUE" : "FALSE");
2548
2549         fprintf(out,
2550                 "# Number of reverse hops allowed for I/O nodes\n"
2551                 "# Used for connectivity between I/O nodes connected to Top Switches\nmax_reverse_hops %d\n\n",
2552                 p_opts->max_reverse_hops);
2553
2554         fprintf(out,
2555                 "# The file holding the node ids which will be used by"
2556                 " Up/Down algorithm instead\n# of GUIDs (one guid and"
2557                 " id in each line)\nids_guid_file %s\n\n",
2558                 p_opts->ids_guid_file ? p_opts->ids_guid_file : null_str);
2559
2560         fprintf(out,
2561                 "# The file holding guid routing order guids (for MinHop and Up/Down)\n"
2562                 "guid_routing_order_file %s\n\n",
2563                 p_opts->guid_routing_order_file ? p_opts->guid_routing_order_file : null_str);
2564
2565         fprintf(out,
2566                 "# Do mesh topology analysis (for LASH algorithm)\n"
2567                 "do_mesh_analysis %s\n\n",
2568                 p_opts->do_mesh_analysis ? "TRUE" : "FALSE");
2569
2570         fprintf(out,
2571                 "# Starting VL for LASH algorithm\n"
2572                 "lash_start_vl %u\n\n",
2573                 p_opts->lash_start_vl);
2574
2575         fprintf(out,
2576                 "# Port Shifting (use FALSE if unsure)\n"
2577                 "port_shifting %s\n\n",
2578                 p_opts->port_shifting ? "TRUE" : "FALSE");
2579
2580         fprintf(out,
2581                 "# Assign ports in a random order instead of round-robin\n"
2582                 "# If zero disable (default), otherwise use the value as a random seed\n"
2583                 "scatter_ports %d\n\n",
2584                 p_opts->scatter_ports);
2585
2586         fprintf(out,
2587                 "# Don't use scatter for ports defined in\n"
2588                 "# guid_routing_order file\n"
2589                 "guid_routing_order_no_scatter %s\n\n",
2590                 p_opts->guid_routing_order_no_scatter ? "TRUE" : "FALSE");
2591
2592         fprintf(out,
2593                 "# SA database file name\nsa_db_file %s\n\n",
2594                 p_opts->sa_db_file ? p_opts->sa_db_file : null_str);
2595
2596         fprintf(out,
2597                 "# If TRUE causes OpenSM to dump SA database at the end of\n"
2598                 "# every light sweep, regardless of the verbosity level\n"
2599                 "sa_db_dump %s\n\n",
2600                 p_opts->sa_db_dump ? "TRUE" : "FALSE");
2601
2602         fprintf(out,
2603                 "# Torus-2QoS configuration file name\ntorus_config %s\n\n",
2604                 p_opts->torus_conf_file ? p_opts->torus_conf_file : null_str);
2605
2606         fprintf(out,
2607                 "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
2608                 "# SM priority used for deciding who is the master\n"
2609                 "# Range goes from 0 (lowest priority) to 15 (highest).\n"
2610                 "sm_priority %u\n\n"
2611                 "# If TRUE other SMs on the subnet should be ignored\n"
2612                 "ignore_other_sm %s\n\n"
2613                 "# Timeout in [msec] between two polls of active master SM\n"
2614                 "sminfo_polling_timeout %u\n\n"
2615                 "# Number of failing polls of remote SM that declares it dead\n"
2616                 "polling_retry_number %u\n\n"
2617                 "# If TRUE honor the guid2lid file when coming out of standby\n"
2618                 "# state, if such file exists and is valid\n"
2619                 "honor_guid2lid_file %s\n\n",
2620                 p_opts->sm_priority,
2621                 p_opts->ignore_other_sm ? "TRUE" : "FALSE",
2622                 p_opts->sminfo_polling_timeout,
2623                 p_opts->polling_retry_number,
2624                 p_opts->honor_guid2lid_file ? "TRUE" : "FALSE");
2625
2626         fprintf(out,
2627                 "#\n# TIMING AND THREADING OPTIONS\n#\n"
2628                 "# Maximum number of SMPs sent in parallel\n"
2629                 "max_wire_smps %u\n\n"
2630                 "# Maximum number of timeout based SMPs allowed to be outstanding\n"
2631                 "# A value less than or equal to max_wire_smps disables this mechanism\n"
2632                 "max_wire_smps2 %u\n\n"
2633                 "# The timeout in [usec] used for sending SMPs above max_wire_smps limit\n"
2634                 "# and below max_wire_smps2 limit\n"
2635                 "max_smps_timeout %u\n\n"
2636                 "# The maximum time in [msec] allowed for a transaction to complete\n"
2637                 "transaction_timeout %u\n\n"
2638                 "# The maximum number of retries allowed for a transaction to complete\n"
2639                 "transaction_retries %u\n\n"
2640                 "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
2641                 "# If there is more than one message in the queue and the last message\n"
2642                 "# stayed in the queue more than this value, any SA request will be\n"
2643                 "# immediately be dropped but BUSY status is not currently returned.\n"
2644                 "max_msg_fifo_timeout %u\n\n"
2645                 "# Use a single thread for handling SA queries\n"
2646                 "single_thread %s\n\n",
2647                 p_opts->max_wire_smps,
2648                 p_opts->max_wire_smps2,
2649                 p_opts->max_smps_timeout,
2650                 p_opts->transaction_timeout,
2651                 p_opts->transaction_retries,
2652                 p_opts->max_msg_fifo_timeout,
2653                 p_opts->single_thread ? "TRUE" : "FALSE");
2654
2655         fprintf(out,
2656                 "#\n# MISC OPTIONS\n#\n"
2657                 "# Daemon mode\n"
2658                 "daemon %s\n\n"
2659                 "# SM Inactive\n"
2660                 "sm_inactive %s\n\n"
2661                 "# Babbling Port Policy\n"
2662                 "babbling_port_policy %s\n\n"
2663                 "# Drop event subscriptions (InformInfo and ServiceRecord) on port removal and SM coming out of STANDBY\n"
2664                 "drop_event_subscriptions %s\n\n"
2665                 "# Validate IPoIB non-broadcast group creation parameters against\n"
2666                 "# broadcast group parameters per IETF RFC 4391 (default TRUE)\n"
2667                 "ipoib_mcgroup_creation_validation %s\n\n"
2668                 "# Validate multicast join parameters against multicast group\n"
2669                 "# parameters when MC group already exists\n"
2670                 "mcgroup_join_validation %s\n\n"
2671                 "# Use Optimized SLtoVLMapping programming if supported by device\n"
2672                 "use_optimized_slvl %s\n\n"
2673                 "# Sync in memory files used for high availability with storage\n"
2674                 "fsync_high_avail_files %s\n\n",
2675                 p_opts->daemon ? "TRUE" : "FALSE",
2676                 p_opts->sm_inactive ? "TRUE" : "FALSE",
2677                 p_opts->babbling_port_policy ? "TRUE" : "FALSE",
2678                 p_opts->drop_event_subscriptions ? "TRUE" : "FALSE",
2679                 p_opts->ipoib_mcgroup_creation_validation ? "TRUE" : "FALSE",
2680                 p_opts->mcgroup_join_validation ? "TRUE" : "FALSE",
2681                 p_opts->use_optimized_slvl ? "TRUE" : "FALSE",
2682                 p_opts->fsync_high_avail_files ? "TRUE" : "FALSE");
2683
2684 #ifdef ENABLE_OSM_PERF_MGR
2685         fprintf(out,
2686                 "#\n# Performance Manager Options\n#\n"
2687                 "# perfmgr enable\n"
2688                 "# PerfMgr is enabled if TRUE and disabled if FALSE (default FALSE)\n"
2689                 "perfmgr %s\n\n"
2690                 "# redirection enable\n"
2691                 "# Redirection supported if TRUE and not supported if FALSE (default TRUE)\n"
2692                 "perfmgr_redir %s\n\n"
2693                 "# sweep time in seconds (default %u seconds)\n"
2694                 "perfmgr_sweep_time_s %u\n\n"
2695                 "# Max outstanding queries (default %u)\n"
2696                 "perfmgr_max_outstanding_queries %u\n\n"
2697                 "# Ignore CAs on sweep (default FALSE)\n"
2698                 "perfmgr_ignore_cas %s\n\n"
2699                 "# Remove missing nodes from DB (default TRUE)\n"
2700                 "perfmgr_rm_nodes %s\n\n"
2701                 "# Log error counters to opensm.log (default TRUE)\n"
2702                 "perfmgr_log_errors %s\n\n"
2703                 "# Query PerfMgt Get(ClassPortInfo) for extended capabilities\n"
2704                 "# Extended capabilities include 64 bit extended counters\n"
2705                 "# and transmit wait support (default TRUE)\n"
2706                 "perfmgr_query_cpi %s\n\n"
2707                 "# Log xmit_wait errors (default FALSE)\n"
2708                 "perfmgr_xmit_wait_log %s\n\n"
2709                 "# If logging xmit_wait's; set threshold (default %u)\n"
2710                 "perfmgr_xmit_wait_threshold %u\n\n"
2711                 ,
2712                 p_opts->perfmgr ? "TRUE" : "FALSE",
2713                 p_opts->perfmgr_redir ? "TRUE" : "FALSE",
2714                 OSM_PERFMGR_DEFAULT_SWEEP_TIME_S,
2715                 p_opts->perfmgr_sweep_time_s,
2716                 OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES,
2717                 p_opts->perfmgr_max_outstanding_queries,
2718                 p_opts->perfmgr_ignore_cas ? "TRUE" : "FALSE",
2719                 p_opts->perfmgr_rm_nodes ? "TRUE" : "FALSE",
2720                 p_opts->perfmgr_log_errors ? "TRUE" : "FALSE",
2721                 p_opts->perfmgr_query_cpi ? "TRUE" : "FALSE",
2722                 p_opts->perfmgr_xmit_wait_log ? "TRUE" : "FALSE",
2723                 OSM_PERFMGR_DEFAULT_XMIT_WAIT_THRESHOLD,
2724                 p_opts->perfmgr_xmit_wait_threshold);
2725
2726         fprintf(out,
2727                 "#\n# Event DB Options\n#\n"
2728                 "# Dump file to dump the events to\n"
2729                 "event_db_dump_file %s\n\n", p_opts->event_db_dump_file ?
2730                 p_opts->event_db_dump_file : null_str);
2731 #endif                          /* ENABLE_OSM_PERF_MGR */
2732
2733         fprintf(out,
2734                 "#\n# Event Plugin Options\n#\n"
2735                 "# Event plugin name(s)\n"
2736                 "event_plugin_name %s\n\n"
2737                 "# Options string that would be passed to the plugin(s)\n"
2738                 "event_plugin_options %s\n\n",
2739                 p_opts->event_plugin_name ?
2740                 p_opts->event_plugin_name : null_str,
2741                 p_opts->event_plugin_options ?
2742                 p_opts->event_plugin_options : null_str);
2743
2744         fprintf(out,
2745                 "#\n# Node name map for mapping node's to more descriptive node descriptions\n"
2746                 "# (man ibnetdiscover for more information)\n#\n"
2747                 "node_name_map_name %s\n\n", p_opts->node_name_map_name ?
2748                 p_opts->node_name_map_name : null_str);
2749
2750         fprintf(out,
2751                 "#\n# DEBUG FEATURES\n#\n"
2752                 "# The log flags used\n"
2753                 "log_flags 0x%02x\n\n"
2754                 "# Force flush of the log file after each log message\n"
2755                 "force_log_flush %s\n\n"
2756                 "# Log file to be used\n"
2757                 "log_file %s\n\n"
2758                 "# Limit the size of the log file in MB. If overrun, log is restarted\n"
2759                 "log_max_size %u\n\n"
2760                 "# If TRUE will accumulate the log over multiple OpenSM sessions\n"
2761                 "accum_log_file %s\n\n"
2762                 "# Per module logging configuration file\n"
2763                 "# Each line in config file contains <module_name><separator><log_flags>\n"
2764                 "# where module_name is file name including .c\n"
2765                 "# separator is either = , space, or tab\n"
2766                 "# log_flags is the same flags as used in the coarse/overall logging\n"
2767                 "per_module_logging_file %s\n\n"
2768                 "# The directory to hold the file OpenSM dumps\n"
2769                 "dump_files_dir %s\n\n"
2770                 "# If TRUE enables new high risk options and hardware specific quirks\n"
2771                 "enable_quirks %s\n\n"
2772                 "# If TRUE disables client reregistration\n"
2773                 "no_clients_rereg %s\n\n"
2774                 "# If TRUE OpenSM should disable multicast support and\n"
2775                 "# no multicast routing is performed if TRUE\n"
2776                 "disable_multicast %s\n\n"
2777                 "# If TRUE opensm will exit on fatal initialization issues\n"
2778                 "exit_on_fatal %s\n\n" "# console [off|local"
2779 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
2780                 "|loopback"
2781 #endif
2782 #ifdef ENABLE_OSM_CONSOLE_SOCKET
2783                 "|socket]\n"
2784 #else
2785                 "]\n"
2786 #endif
2787                 "console %s\n\n"
2788                 "# Telnet port for console (default %d)\n"
2789                 "console_port %d\n\n",
2790                 p_opts->log_flags,
2791                 p_opts->force_log_flush ? "TRUE" : "FALSE",
2792                 p_opts->log_file,
2793                 p_opts->log_max_size,
2794                 p_opts->accum_log_file ? "TRUE" : "FALSE",
2795                 p_opts->per_module_logging_file ?
2796                         p_opts->per_module_logging_file : null_str,
2797                 p_opts->dump_files_dir,
2798                 p_opts->enable_quirks ? "TRUE" : "FALSE",
2799                 p_opts->no_clients_rereg ? "TRUE" : "FALSE",
2800                 p_opts->disable_multicast ? "TRUE" : "FALSE",
2801                 p_opts->exit_on_fatal ? "TRUE" : "FALSE",
2802                 p_opts->console,
2803                 OSM_DEFAULT_CONSOLE_PORT, p_opts->console_port);
2804
2805         fprintf(out,
2806                 "#\n# QoS OPTIONS\n#\n"
2807                 "# Enable QoS setup\n"
2808                 "qos %s\n\n"
2809                 "# QoS policy file to be used\n"
2810                 "qos_policy_file %s\n"
2811                 "# Supress QoS MAD status errors\n"
2812                 "suppress_sl2vl_mad_status_errors %s\n\n",
2813                 p_opts->qos ? "TRUE" : "FALSE", p_opts->qos_policy_file,
2814                 p_opts->suppress_sl2vl_mad_status_errors ? "TRUE" : "FALSE");
2815
2816         subn_dump_qos_options(out,
2817                               "QoS default options", "qos",
2818                               &p_opts->qos_options);
2819         fprintf(out, "\n");
2820         subn_dump_qos_options(out,
2821                               "QoS CA options", "qos_ca",
2822                               &p_opts->qos_ca_options);
2823         fprintf(out, "\n");
2824         subn_dump_qos_options(out,
2825                               "QoS Switch Port 0 options", "qos_sw0",
2826                               &p_opts->qos_sw0_options);
2827         fprintf(out, "\n");
2828         subn_dump_qos_options(out,
2829                               "QoS Switch external ports options", "qos_swe",
2830                               &p_opts->qos_swe_options);
2831         fprintf(out, "\n");
2832         subn_dump_qos_options(out,
2833                               "QoS Router ports options", "qos_rtr",
2834                               &p_opts->qos_rtr_options);
2835         fprintf(out, "\n");
2836
2837         fprintf(out,
2838                 "#\n# Congestion Control OPTIONS (EXPERIMENTAL)\n#\n\n"
2839                 "# Enable Congestion Control Configuration\n"
2840                 "congestion_control %s\n\n"
2841                 "# CCKey to use when configuring congestion control\n"
2842                 "# note that this does not configure a new CCkey, only the CCkey to use\n"
2843                 "cc_key 0x%016" PRIx64 "\n\n"
2844                 "# Congestion Control Max outstanding MAD\n"
2845                 "cc_max_outstanding_mads %u\n\n",
2846                 p_opts->congestion_control ? "TRUE" : "FALSE",
2847                 cl_ntoh64(p_opts->cc_key),
2848                 p_opts->cc_max_outstanding_mads);
2849
2850         fprintf(out,
2851                 "#\n# Congestion Control SwitchCongestionSetting options\n#\n"
2852                 "# Control Map - bitmask indicating which of the following are to be used\n"
2853                 "# bit 0 - victim mask\n"
2854                 "# bit 1 - credit mask\n"
2855                 "# bit 2 - threshold + packet size\n"
2856                 "# bit 3 - credit starvation threshold + return delay valid\n"
2857                 "# bit 4 - marking rate valid\n"
2858                 "cc_sw_cong_setting_control_map 0x%X\n\n",
2859                 cl_ntoh32(p_opts->cc_sw_cong_setting_control_map));
2860
2861         fprintf(out,
2862                 "# Victim Mask - 256 bit mask representing switch ports, mark packets with FECN\n"
2863                 "# whether they are the source or victim of congestion\n"
2864                 "# bit 0 - port 0 (enhanced port)\n"
2865                 "# bit 1 - port 1\n"
2866                 "# ...\n"
2867                 "# bit 254 - port 254\n"
2868                 "# bit 255 - reserved\n"
2869                 "cc_sw_cong_setting_victim_mask 0x");
2870
2871         for (i = 0; i < IB_CC_PORT_MASK_DATA_SIZE; i++)
2872                 fprintf(out, "%02X", p_opts->cc_sw_cong_setting_victim_mask[i]);
2873         fprintf(out, "\n\n");
2874
2875         fprintf(out,
2876                 "# Credit Mask - 256 bit mask representing switch ports to apply credit starvation\n"
2877                 "# bit 0 - port 0 (enhanced port)\n"
2878                 "# bit 1 - port 1\n"
2879                 "# ...\n"
2880                 "# bit 254 - port 254\n"
2881                 "# bit 255 - reserved\n"
2882                 "cc_sw_cong_setting_credit_mask 0x");
2883
2884         for (i = 0; i < IB_CC_PORT_MASK_DATA_SIZE; i++)
2885                 fprintf(out, "%02X", p_opts->cc_sw_cong_setting_credit_mask[i]);
2886         fprintf(out, "\n\n");
2887
2888         fprintf(out,
2889                 "# Threshold - value indicating aggressiveness of congestion marking\n"
2890                 "# 0x0 - none, 0x1 - loose, ..., 0xF - aggressive\n"
2891                 "cc_sw_cong_setting_threshold 0x%02X\n\n"
2892                 "# Packet Size - any packet less than this size will not be marked with a FECN\n"
2893                 "# units are in credits\n"
2894                 "cc_sw_cong_setting_packet_size %u\n\n"
2895                 "# Credit Starvation Threshold - value indicating aggressiveness of credit starvation\n"
2896                 "# 0x0 - none, 0x1 - loose, ..., 0xF - aggressive\n"
2897                 "cc_sw_cong_setting_credit_starvation_threshold 0x%02X\n\n"
2898                 "# Credit Starvation Return Delay - in CCT entry shift:multiplier format, see IB spec\n"
2899                 "cc_sw_cong_setting_credit_starvation_return_delay %u:%u\n\n"
2900                 "# Marking Rate - mean number of packets between markings\n"
2901                 "cc_sw_cong_setting_marking_rate %u\n\n",
2902                 p_opts->cc_sw_cong_setting_threshold,
2903                 p_opts->cc_sw_cong_setting_packet_size,
2904                 p_opts->cc_sw_cong_setting_credit_starvation_threshold,
2905                 p_opts->cc_sw_cong_setting_credit_starvation_return_delay.shift,
2906                 p_opts->cc_sw_cong_setting_credit_starvation_return_delay.multiplier,
2907                 cl_ntoh16(p_opts->cc_sw_cong_setting_marking_rate));
2908
2909         fprintf(out,
2910                 "#\n# Congestion Control CA Congestion Setting options\n#\n"
2911                 "# Port Control\n"
2912                 "# bit 0 = 0, QP based congestion control\n"
2913                 "# bit 0 = 1, SL/port based congestion control\n"
2914                 "cc_ca_cong_setting_port_control 0x%04X\n\n"
2915                 "# Control Map - 16 bit bitmask indicating which SLs should be configured\n"
2916                 "cc_ca_cong_setting_control_map 0x%04X\n\n",
2917                 cl_ntoh16(p_opts->cc_ca_cong_setting_port_control),
2918                 cl_ntoh16(p_opts->cc_ca_cong_setting_control_map));
2919
2920         fprintf(out,
2921                 "#\n# CA Congestion Setting Entries\n#\n"
2922                 "# Each of congestion control settings below configures the CA Congestion\n"
2923                 "# Settings for an individual SL.  The SL must be specified before the value.\n"
2924                 "# These options may be specified multiple times to configure different values\n"
2925                 "# for different SLs.\n"
2926                 "#\n"
2927                 "# ccti timer - when expires decrements 1 from the CCTI\n"
2928                 "# ccti increase - number to be added to the table index on receipt of a BECN\n"
2929                 "# trigger threshold - when the ccti is equal to this, an event is logged\n"
2930                 "# ccti min - the minimum value for the ccti.  This imposes a minimum rate\n"
2931                 "#            on the injection rate\n\n");
2932
2933         for (i = 0; i < IB_CA_CONG_ENTRY_DATA_SIZE; i++) {
2934                 /* Don't output unless one of the settings has been set, there's no need
2935                  * to output 16 chunks of this with all defaults of 0 */
2936                 if (p_opts->cc_ca_cong_entries[i].ccti_timer
2937                     || p_opts->cc_ca_cong_entries[i].ccti_increase
2938                     || p_opts->cc_ca_cong_entries[i].trigger_threshold
2939                     || p_opts->cc_ca_cong_entries[i].ccti_min) {
2940                         fprintf(out,
2941                                 "# SL = %u\n"
2942                                 "cc_ca_cong_setting_ccti_timer %u %u\n"
2943                                 "cc_ca_cong_setting_ccti_increase %u %u\n"
2944                                 "cc_ca_cong_setting_trigger_threshold %u %u\n"
2945                                 "cc_ca_cong_setting_ccti_min %u %u\n\n",
2946                                 i,
2947                                 i,
2948                                 cl_ntoh16(p_opts->cc_ca_cong_entries[i].ccti_timer),
2949                                 i,
2950                                 p_opts->cc_ca_cong_entries[i].ccti_increase,
2951                                 i,
2952                                 p_opts->cc_ca_cong_entries[i].trigger_threshold,
2953                                 i,
2954                                 p_opts->cc_ca_cong_entries[i].ccti_min);
2955                         cacongoutputcount++;
2956                 }
2957         }
2958
2959         /* If by chance all the CA Cong Settings are default, output at least 1 chunk
2960          * for illustration */
2961         if (!cacongoutputcount)
2962                 fprintf(out,
2963                         "# SL = 0\n"
2964                         "cc_ca_cong_setting_ccti_timer 0 %u\n"
2965                         "cc_ca_cong_setting_ccti_increase 0 %u\n"
2966                         "cc_ca_cong_setting_trigger_threshold 0 %u\n"
2967                         "cc_ca_cong_setting_ccti_min 0 %u\n\n",
2968                         cl_ntoh16(p_opts->cc_ca_cong_entries[0].ccti_timer),
2969                         p_opts->cc_ca_cong_entries[0].ccti_increase,
2970                         p_opts->cc_ca_cong_entries[0].trigger_threshold,
2971                         p_opts->cc_ca_cong_entries[0].ccti_min);
2972
2973         fprintf(out,
2974                 "#\n# Congestion Control Table\n#\n"
2975                 "# Comma separated list of CCT entries representing CCT.\n"
2976                 "# Format is shift:multipler,shift_multiplier,shift:multiplier,...\n"
2977                 "cc_cct ");
2978
2979         if (!p_opts->cc_cct.entries_len) {
2980                 fprintf(out, "%s\n", null_str);
2981         }
2982         else {
2983                 fprintf(out, "%u:%u",
2984                         p_opts->cc_cct.entries[0].shift,
2985                         p_opts->cc_cct.entries[0].multiplier);
2986                 for (i = 1; i < p_opts->cc_cct.entries_len; i++) {
2987                         fprintf(out, ",%u:%u",
2988                                 p_opts->cc_cct.entries[i].shift,
2989                                 p_opts->cc_cct.entries[i].multiplier);
2990                 }
2991                 fprintf(out, "\n");
2992         }
2993         fprintf(out, "\n");
2994
2995         fprintf(out,
2996                 "# Prefix routes file name\n"
2997                 "prefix_routes_file %s\n\n",
2998                 p_opts->prefix_routes_file);
2999
3000         fprintf(out,
3001                 "#\n# IPv6 Solicited Node Multicast (SNM) Options\n#\n"
3002                 "consolidate_ipv6_snm_req %s\n\n",
3003                 p_opts->consolidate_ipv6_snm_req ? "TRUE" : "FALSE");
3004
3005         fprintf(out, "# Log prefix\nlog_prefix %s\n\n", p_opts->log_prefix);
3006
3007         /* optional string attributes ... */
3008
3009 }
3010
3011 int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t * p_opts)
3012 {
3013         FILE *opts_file;
3014
3015         opts_file = fopen(file_name, "w");
3016         if (!opts_file) {
3017                 printf("cannot open file \'%s\' for writing: %s\n",
3018                         file_name, strerror(errno));
3019                 return -1;
3020         }
3021
3022         osm_subn_output_conf(opts_file, p_opts);
3023
3024         fclose(opts_file);
3025
3026         return 0;
3027 }