/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (C) 2012-2017 Tokyo Institute of Technology. All rights reserved. * Copyright (c) 2019 Fabriscale Technologies AS. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ /* * Abstract: * Implementation of osm_opensm_t. * This object represents the opensm super object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_OPENSM_C #include #include #include #include #include #include #include #include #include #include /* * built-in routing engine setup functions */ extern int osm_ucast_minhop_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_updn_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dnup_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_file_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_ftree_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_lash_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dor_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_torus2QoS_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_nue_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_sssp_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dfsssp_setup(struct osm_routing_engine *, osm_opensm_t *); /* * Local types */ typedef struct builtin_routing_engine_module { const char *name; osm_routing_engine_type_t type; int (*setup)(struct osm_routing_engine *re, struct osm_opensm *osm); } builtin_routing_engine_module_t; typedef struct routing_engine_module { char *name; osm_routing_engine_type_t type; int (*setup)(struct osm_routing_engine *re, struct osm_opensm *osm); void *context; } routing_engine_module_t; /* * Local variables */ static const char *unknown_routing_engine_name = "unknown"; static cl_list_t routing_modules; static osm_routing_engine_type_t last_external_routing_engine_type = OSM_ROUTING_ENGINE_TYPE_EXTERNAL; static builtin_routing_engine_module_t static_routing_modules[] = { { "none", OSM_ROUTING_ENGINE_TYPE_NONE, NULL }, { "minhop", OSM_ROUTING_ENGINE_TYPE_MINHOP, osm_ucast_minhop_setup }, { "updn", OSM_ROUTING_ENGINE_TYPE_UPDN, osm_ucast_updn_setup }, { "dnup", OSM_ROUTING_ENGINE_TYPE_DNUP, osm_ucast_dnup_setup }, { "file", OSM_ROUTING_ENGINE_TYPE_FILE, osm_ucast_file_setup }, { "ftree", OSM_ROUTING_ENGINE_TYPE_FTREE, osm_ucast_ftree_setup }, { "lash", OSM_ROUTING_ENGINE_TYPE_LASH, osm_ucast_lash_setup }, { "dor", OSM_ROUTING_ENGINE_TYPE_DOR, osm_ucast_dor_setup }, { "torus-2QoS", OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS, osm_ucast_torus2QoS_setup }, { "nue", OSM_ROUTING_ENGINE_TYPE_NUE, osm_ucast_nue_setup }, { "dfsssp", OSM_ROUTING_ENGINE_TYPE_DFSSSP, osm_ucast_dfsssp_setup }, { "sssp", OSM_ROUTING_ENGINE_TYPE_SSSP, osm_ucast_sssp_setup } }; /* * Forward declarations */ static cl_status_t _match_routing_engine_type( IN const void *const p_object, IN void *context); static cl_status_t _match_routing_engine_str( IN const void *const p_object, IN void *context); static void append_routing_engine( osm_opensm_t *osm, struct osm_routing_engine *routing_engine); static struct osm_routing_engine *setup_routing_engine( osm_opensm_t *osm, const char *name); static void dump_routing_engine( IN void *const p_object, IN void *context); static void dump_routing_engines( IN osm_opensm_t *osm); static void setup_routing_engines( osm_opensm_t *osm, const char *engine_names); static cl_status_t register_builtin_routing_engine( IN osm_opensm_t *osm, IN const builtin_routing_engine_module_t *module); static cl_status_t register_routing_engine( IN osm_opensm_t *osm, IN const routing_engine_module_t *module); static void destroy_routing_engines( osm_opensm_t *osm); static void __free_routing_module( void *p_object, void *context); static const char *routing_engine_type( IN osm_routing_engine_type_t type); /** ========================================================================= */ cl_status_t osm_register_external_routing_engine( IN osm_opensm_t *osm, IN const external_routing_engine_module_t *module, IN void *context) { cl_status_t status; routing_engine_module_t *copy = NULL; if (!osm || !module) return CL_INVALID_PARAMETER; OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "Assign type '%d' to external routing engine with name: \'%s\'\n", last_external_routing_engine_type, module->name); copy = (routing_engine_module_t *) malloc(sizeof(routing_engine_module_t)); if (!copy) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "memory allocation failed\n"); return CL_INSUFFICIENT_MEMORY; } copy->name = strdup(module->name); if (!copy->name) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "memory allocation failed\n"); __free_routing_module(copy, NULL); return CL_INSUFFICIENT_MEMORY; } copy->setup = module->setup; copy->type = last_external_routing_engine_type++; copy->context = context; status = register_routing_engine(osm, copy); if (status != CL_SUCCESS) __free_routing_module(copy, NULL); return status; } cl_status_t register_builtin_routing_engine( IN osm_opensm_t *osm, IN const builtin_routing_engine_module_t *module) { cl_status_t status; routing_engine_module_t *copy; if (!osm || !module) return CL_INVALID_PARAMETER; copy = (routing_engine_module_t *) malloc(sizeof(routing_engine_module_t)); if (!copy) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "memory allocation failed\n"); return CL_INSUFFICIENT_MEMORY; } copy->name = strdup(module->name); if (!copy->name) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "memory allocation failed\n"); __free_routing_module(copy, NULL); return CL_INSUFFICIENT_MEMORY; } copy->setup = module->setup; copy->type = module->type; copy->context = NULL; status = register_routing_engine(osm, copy); if (status != CL_SUCCESS) __free_routing_module(copy, NULL); return status; } cl_status_t register_routing_engine( IN osm_opensm_t *osm, IN const routing_engine_module_t *module) { cl_status_t status; osm_routing_engine_type_t existing_type, new_type; const char *existing_routing_engine_type, *new_routing_engine_type; const char *existing_routing_engine_name, *new_name; new_type = module->type; new_name = module->name; new_routing_engine_type = routing_engine_type(new_type); /* check if another routine engine has already been registered with the same name */ existing_type = osm_routing_engine_type(new_name); if (existing_type != OSM_ROUTING_ENGINE_TYPE_UNKNOWN) { existing_routing_engine_type = routing_engine_type(existing_type); OSM_LOG(&osm->log, OSM_LOG_ERROR, "Failed to register %s routing engine with name \'%s\': " "%s routing engine with same name was already registered with type: '%d'\n", new_routing_engine_type, new_name, existing_routing_engine_type, existing_type); return CL_DUPLICATE; } /* check if another routine engine has already been registed with the same type */ existing_routing_engine_name = osm_routing_engine_type_str(new_type); if (strcmp(existing_routing_engine_name, unknown_routing_engine_name) != 0) { existing_type = new_type; existing_routing_engine_type = routing_engine_type(existing_type); OSM_LOG(&osm->log, OSM_LOG_ERROR, "Failed to register %s routing engine with name \'%s\': " "%s routing engine with type '%d' " "was already registered with name: \'%s\'\n", new_routing_engine_type, new_name, existing_routing_engine_type, existing_type, existing_routing_engine_name); return CL_DUPLICATE; } OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "Register %s routine engine with name: \'%s\' and type: '%d'\n", new_routing_engine_type, new_name, new_type); status = cl_list_insert_tail(&routing_modules, module); return status; } static cl_status_t _match_routing_engine_type( IN const void *const p_object, IN void *context) { osm_routing_engine_type_t type; routing_engine_module_t *module; type = (osm_routing_engine_type_t) context; module = (routing_engine_module_t *) p_object; return module->type == type ? CL_SUCCESS : CL_NOT_FOUND; } const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type) { cl_list_iterator_t iter; routing_engine_module_t *module; iter = cl_list_find_from_head( &routing_modules, _match_routing_engine_type, (void *)type); if (iter != cl_list_end(&routing_modules)) { module = (routing_engine_module_t *) cl_list_obj(iter); return module->name; } return unknown_routing_engine_name; } static cl_status_t _match_routing_engine_str( IN const void *const p_object, IN void *context) { const char *name = (char *) context; routing_engine_module_t *module; name = (char *) context; module = (routing_engine_module_t *) p_object; /* For legacy reasons, consider a NULL pointer and the string * "null" as the minhop routing engine. */ if (!name || !strcasecmp(name, "null")) name = "minhop"; if (strcasecmp(module->name, name) == 0) return CL_SUCCESS; else return CL_NOT_FOUND; } osm_routing_engine_type_t osm_routing_engine_type(IN const char *str) { cl_list_iterator_t iter; routing_engine_module_t *module; iter = cl_list_find_from_head( &routing_modules, _match_routing_engine_str, (void *)str); if (iter != cl_list_end(&routing_modules)) { module = (routing_engine_module_t *) cl_list_obj(iter); return module->type; } return OSM_ROUTING_ENGINE_TYPE_UNKNOWN; } static void append_routing_engine(osm_opensm_t *osm, struct osm_routing_engine *routing_engine) { struct osm_routing_engine *r; routing_engine->next = NULL; if (!osm->routing_engine_list) { osm->routing_engine_list = routing_engine; return; } r = osm->routing_engine_list; while (r->next) r = r->next; r->next = routing_engine; } static struct osm_routing_engine *setup_routing_engine(osm_opensm_t *osm, const char *name) { struct osm_routing_engine *re; routing_engine_module_t *m; cl_list_iterator_t iter; if (!strcmp(name, "no_fallback")) { osm->no_fallback_routing_engine = TRUE; return NULL; } for (iter = cl_list_head(&routing_modules); iter != cl_list_end(&routing_modules); iter = cl_list_next(iter)) { m = (routing_engine_module_t *)cl_list_obj(iter); if (!strcmp(m->name, name)) { re = malloc(sizeof(struct osm_routing_engine)); if (!re) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "memory allocation failed\n"); return NULL; } memset(re, 0, sizeof(struct osm_routing_engine)); re->name = m->name; re->context = m->context; OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "setup of routing engine \'%s\' ...\n", name); re->type = osm_routing_engine_type(m->name); if (m->setup(re, osm)) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "setup of routing" " engine \'%s\' failed\n", name); free(re); return NULL; } OSM_LOG(&osm->log, OSM_LOG_DEBUG, "\'%s\' routing engine set up\n", re->name); if (re->type == OSM_ROUTING_ENGINE_TYPE_MINHOP) osm->default_routing_engine = re; return re; } } OSM_LOG(&osm->log, OSM_LOG_ERROR, "cannot find or setup routing engine \'%s\'\n", name); return NULL; } static void setup_routing_engines(osm_opensm_t *osm, const char *engine_names) { char *name, *str, *p; struct osm_routing_engine *re; dump_routing_engines(osm); if (engine_names && *engine_names) { str = strdup(engine_names); name = strtok_r(str, ", \t\n", &p); while (name && *name) { re = setup_routing_engine(osm, name); if (re) append_routing_engine(osm, re); else OSM_LOG(&osm->log, OSM_LOG_ERROR, "Failed to setup routing engine \'%s\'\n", name); name = strtok_r(NULL, ", \t\n", &p); } free(str); } if (!osm->default_routing_engine) setup_routing_engine(osm, "minhop"); } static void dump_routing_engine(IN void *const p_object, IN void *context) { osm_opensm_t *osm; routing_engine_module_t *module; osm = (osm_opensm_t *) context; module = (routing_engine_module_t *) p_object; OSM_LOG(&osm->log, OSM_LOG_VERBOSE, " name: %s - Type: %d\n", module->name, module->type); } static void dump_routing_engines(IN osm_opensm_t *osm) { cl_list_apply_func( &routing_modules, dump_routing_engine, (void *) osm); } static const char *routing_engine_type(IN osm_routing_engine_type_t type) { return type < OSM_ROUTING_ENGINE_TYPE_UNKNOWN ? "built-in" : "external"; } void osm_routing_modules_construct(IN osm_opensm_t *p_osm) { size_t i, len; len = sizeof(static_routing_modules) / sizeof(builtin_routing_engine_module_t); cl_list_construct(&routing_modules); cl_list_init(&routing_modules, len); for (i = 0; i < len; i++) { register_builtin_routing_engine( p_osm, &(static_routing_modules[i])); } } static void __free_routing_module(void *p_object, void *context) { routing_engine_module_t *p_module; p_module = (routing_engine_module_t *) p_object; if (p_module) { if (p_module->name) free(p_module->name); free(p_module); } } void osm_routing_modules_destroy(IN osm_opensm_t *p_osm) { cl_list_apply_func(&routing_modules, __free_routing_module, p_osm); cl_list_remove_all(&routing_modules); cl_list_destroy(&routing_modules); } void osm_opensm_construct(IN osm_opensm_t * p_osm) { memset(p_osm, 0, sizeof(*p_osm)); p_osm->osm_version = OSM_VERSION; osm_routing_modules_construct(p_osm); osm_subn_construct(&p_osm->subn); osm_db_construct(&p_osm->db); osm_log_construct(&p_osm->log); } void osm_opensm_construct_finish(IN osm_opensm_t * p_osm) { osm_sm_construct(&p_osm->sm); osm_sa_construct(&p_osm->sa); osm_mad_pool_construct(&p_osm->mad_pool); p_osm->mad_pool_constructed = TRUE; osm_vl15_construct(&p_osm->vl15); p_osm->vl15_constructed = TRUE; } static void destroy_routing_engines(osm_opensm_t *osm) { struct osm_routing_engine *r, *next; next = osm->routing_engine_list; while (next) { r = next; next = r->next; if (r != osm->default_routing_engine) { if (r->destroy) r->destroy(r->context); free(r); } else /* do not free default_routing_engine */ r->next = NULL; } osm->routing_engine_list = NULL; r = osm->default_routing_engine; if (r) { if (r->destroy) r->destroy(r->context); free(r); osm->default_routing_engine = NULL; } } static void destroy_plugins(osm_opensm_t *osm) { osm_epi_plugin_t *p; /* remove from the list, and destroy it */ while (!cl_is_qlist_empty(&osm->plugin_list)){ p = (osm_epi_plugin_t *)cl_qlist_remove_head(&osm->plugin_list); /* plugin is responsible for freeing its own resources */ osm_epi_destroy(p); } } void osm_opensm_destroy(IN osm_opensm_t * p_osm) { /* in case of shutdown through exit proc - no ^C */ osm_exit_flag = TRUE; /* * First of all, clear the is_sm bit. */ if (p_osm->sm.mad_ctrl.h_bind) osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, FALSE); #ifdef ENABLE_OSM_PERF_MGR /* Shutdown the PerfMgr */ osm_perfmgr_shutdown(&p_osm->perfmgr); #endif /* ENABLE_OSM_PERF_MGR */ osm_congestion_control_shutdown(&p_osm->cc); /* shut down the SM * - make sure the SM sweeper thread exited * - unbind from QP0 messages */ osm_sm_shutdown(&p_osm->sm); /* shut down the SA * - unbind from QP1 messages */ osm_sa_shutdown(&p_osm->sa); /* cleanup all messages on VL15 fifo that were not sent yet */ osm_vl15_shutdown(&p_osm->vl15, &p_osm->mad_pool); /* shut down the dispatcher - so no new messages cross */ cl_disp_shutdown(&p_osm->disp); if (p_osm->sa_set_disp_initialized) cl_disp_shutdown(&p_osm->sa_set_disp); /* dump SA DB */ if ((p_osm->sm.p_subn->sm_state == IB_SMINFO_STATE_MASTER) && p_osm->subn.opt.sa_db_dump) osm_sa_db_file_dump(p_osm); /* do the destruction in reverse order as init */ destroy_routing_engines(p_osm); destroy_plugins(p_osm); osm_sa_destroy(&p_osm->sa); osm_sm_destroy(&p_osm->sm); osm_routing_modules_destroy(p_osm); #ifdef ENABLE_OSM_PERF_MGR osm_perfmgr_destroy(&p_osm->perfmgr); #endif /* ENABLE_OSM_PERF_MGR */ osm_congestion_control_destroy(&p_osm->cc); } void osm_opensm_destroy_finish(IN osm_opensm_t * p_osm) { osm_db_destroy(&p_osm->db); if (p_osm->vl15_constructed && p_osm->mad_pool_constructed) osm_vl15_destroy(&p_osm->vl15, &p_osm->mad_pool); if (p_osm->mad_pool_constructed) osm_mad_pool_destroy(&p_osm->mad_pool); p_osm->vl15_constructed = FALSE; p_osm->mad_pool_constructed = FALSE; osm_vendor_delete(&p_osm->p_vendor); osm_subn_destroy(&p_osm->subn); cl_disp_destroy(&p_osm->disp); if (p_osm->sa_set_disp_initialized) cl_disp_destroy(&p_osm->sa_set_disp); #ifdef HAVE_LIBPTHREAD pthread_cond_destroy(&p_osm->stats.cond); pthread_mutex_destroy(&p_osm->stats.mutex); #else cl_event_destroy(&p_osm->stats.event); #endif if (p_osm->node_name_map) close_node_name_map(p_osm->node_name_map); cl_plock_destroy(&p_osm->lock); osm_log_destroy(&p_osm->log); } static void load_plugins(osm_opensm_t *osm, const char *plugin_names) { osm_epi_plugin_t *epi; char *p_names, *name, *p; p_names = strdup(plugin_names); name = strtok_r(p_names, ", \t\n", &p); while (name && *name) { epi = osm_epi_construct(osm, name); if (!epi) osm_log_v2(&osm->log, OSM_LOG_ERROR, FILE_ID, "ERR 1000: cannot load plugin \'%s\'\n", name); else cl_qlist_insert_tail(&osm->plugin_list, &epi->list); name = strtok_r(NULL, " \t\n", &p); } free(p_names); } ib_api_status_t osm_opensm_init(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt) { ib_api_status_t status; /* Can't use log macros here, since we're initializing the log */ osm_opensm_construct(p_osm); if (p_opt->daemon) p_osm->log.daemon = 1; status = osm_log_init_v2(&p_osm->log, p_opt->force_log_flush, p_opt->log_flags, p_opt->log_file, p_opt->log_max_size, p_opt->accum_log_file); if (status != IB_SUCCESS) return status; p_osm->log.log_prefix = p_opt->log_prefix; /* If there is a log level defined - add the OSM_VERSION to it */ osm_log_v2(&p_osm->log, osm_log_get_level(&p_osm->log) & (OSM_LOG_SYS ^ 0xFF), FILE_ID, "%s\n", p_osm->osm_version); /* Write the OSM_VERSION to the SYS_LOG */ osm_log_v2(&p_osm->log, OSM_LOG_SYS, FILE_ID, "%s\n", p_osm->osm_version); /* Format Waived */ OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "[\n"); /* Format Waived */ status = cl_plock_init(&p_osm->lock); if (status != IB_SUCCESS) goto Exit; #ifdef HAVE_LIBPTHREAD pthread_mutex_init(&p_osm->stats.mutex, NULL); pthread_cond_init(&p_osm->stats.cond, NULL); #else status = cl_event_init(&p_osm->stats.event, FALSE); if (status != IB_SUCCESS) goto Exit; #endif if (p_opt->single_thread) { OSM_LOG(&p_osm->log, OSM_LOG_INFO, "Forcing single threaded dispatcher\n"); status = cl_disp_init(&p_osm->disp, 1, "opensm"); } else { /* * Normal behavior is to initialize the dispatcher with * one thread per CPU, as specified by a thread count of '0'. */ status = cl_disp_init(&p_osm->disp, 0, "opensm"); } if (status != IB_SUCCESS) goto Exit; /* Unless OpenSM runs in single threaded mode, we create new single * threaded dispatcher for SA Set and Delete requets. */ p_osm->sa_set_disp_initialized = FALSE; if (!p_opt->single_thread) { status = cl_disp_init(&p_osm->sa_set_disp, 1, "subnadmin_set"); if (status != IB_SUCCESS) goto Exit; p_osm->sa_set_disp_initialized = TRUE; } /* the DB is in use by subn so init before */ status = osm_db_init(&p_osm->db, &p_osm->log); if (status != IB_SUCCESS) goto Exit; status = osm_subn_init(&p_osm->subn, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; p_osm->p_vendor = osm_vendor_new(&p_osm->log, p_opt->transaction_timeout); if (p_osm->p_vendor == NULL) status = IB_INSUFFICIENT_RESOURCES; Exit: OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n"); /* Format Waived */ return status; } ib_api_status_t osm_opensm_init_finish(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt) { ib_api_status_t status; osm_opensm_construct_finish(p_osm); p_osm->subn.sm_port_guid = p_opt->guid; status = osm_mad_pool_init(&p_osm->mad_pool); if (status != IB_SUCCESS) goto Exit; status = osm_vl15_init(&p_osm->vl15, p_osm->p_vendor, &p_osm->log, &p_osm->stats, &p_osm->subn, p_opt->max_wire_smps, p_opt->max_wire_smps2, p_opt->max_smps_timeout); if (status != IB_SUCCESS) goto Exit; status = osm_sm_init(&p_osm->sm, &p_osm->subn, &p_osm->db, p_osm->p_vendor, &p_osm->mad_pool, &p_osm->vl15, &p_osm->log, &p_osm->stats, &p_osm->disp, &p_osm->lock); if (status != IB_SUCCESS) goto Exit; status = osm_sa_init(&p_osm->sm, &p_osm->sa, &p_osm->subn, p_osm->p_vendor, &p_osm->mad_pool, &p_osm->log, &p_osm->stats, &p_osm->disp, p_opt->single_thread ? NULL : &p_osm->sa_set_disp, &p_osm->lock); if (status != IB_SUCCESS) goto Exit; cl_qlist_init(&p_osm->plugin_list); if (p_opt->event_plugin_name) load_plugins(p_osm, p_opt->event_plugin_name); #ifdef ENABLE_OSM_PERF_MGR status = osm_perfmgr_init(&p_osm->perfmgr, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; #endif /* ENABLE_OSM_PERF_MGR */ status = osm_congestion_control_init(&p_osm->cc, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; p_osm->no_fallback_routing_engine = FALSE; setup_routing_engines(p_osm, p_opt->routing_engine_names); p_osm->routing_engine_used = NULL; p_osm->node_name_map = open_node_name_map(p_opt->node_name_map_name); Exit: OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n"); /* Format Waived */ return status; } ib_api_status_t osm_opensm_bind(IN osm_opensm_t * p_osm, IN ib_net64_t guid) { ib_api_status_t status; OSM_LOG_ENTER(&p_osm->log); status = osm_sm_bind(&p_osm->sm, guid); if (status != IB_SUCCESS) goto Exit; status = osm_sa_bind(&p_osm->sa, guid); if (status != IB_SUCCESS) goto Exit; #ifdef ENABLE_OSM_PERF_MGR status = osm_perfmgr_bind(&p_osm->perfmgr, guid); if (status != IB_SUCCESS) goto Exit; #endif /* ENABLE_OSM_PERF_MGR */ status = osm_congestion_control_bind(&p_osm->cc, guid); if (status != IB_SUCCESS) goto Exit; /* setting IS_SM in capability mask */ OSM_LOG(&p_osm->log, OSM_LOG_INFO, "Setting IS_SM on port 0x%016" PRIx64 "\n", cl_ntoh64(guid)); osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, TRUE); Exit: OSM_LOG_EXIT(&p_osm->log); return status; } void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id, void *event_data) { cl_list_item_t *item; for (item = cl_qlist_head(&osm->plugin_list); !osm_exit_flag && item != cl_qlist_end(&osm->plugin_list); item = cl_qlist_next(item)) { osm_epi_plugin_t *p = (osm_epi_plugin_t *)item; if (p->impl->report) p->impl->report(p->plugin_data, event_id, event_data); } }