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 } 3028