2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_opensm_t.
39 * This object represents the opensm super object.
40 * This object is part of the opensm family of objects.
45 #endif /* HAVE_CONFIG_H */
50 #include <complib/cl_dispatcher.h>
51 #include <complib/cl_passivelock.h>
52 #include <vendor/osm_vendor_api.h>
53 #include <opensm/osm_version.h>
54 #include <opensm/osm_base.h>
55 #include <opensm/osm_opensm.h>
56 #include <opensm/osm_log.h>
57 #include <opensm/osm_subnet.h>
58 #include <opensm/osm_sm.h>
59 #include <opensm/osm_vl15intf.h>
60 #include <opensm/osm_event_plugin.h>
62 struct routing_engine_module {
64 int (*setup) (struct osm_routing_engine *, osm_opensm_t *);
67 extern int osm_ucast_minhop_setup(struct osm_routing_engine *, osm_opensm_t *);
68 extern int osm_ucast_updn_setup(struct osm_routing_engine *, osm_opensm_t *);
69 extern int osm_ucast_file_setup(struct osm_routing_engine *, osm_opensm_t *);
70 extern int osm_ucast_ftree_setup(struct osm_routing_engine *, osm_opensm_t *);
71 extern int osm_ucast_lash_setup(struct osm_routing_engine *, osm_opensm_t *);
72 extern int osm_ucast_dor_setup(struct osm_routing_engine *, osm_opensm_t *);
74 const static struct routing_engine_module routing_modules[] = {
75 {"minhop", osm_ucast_minhop_setup},
76 {"updn", osm_ucast_updn_setup},
77 {"file", osm_ucast_file_setup},
78 {"ftree", osm_ucast_ftree_setup},
79 {"lash", osm_ucast_lash_setup},
80 {"dor", osm_ucast_dor_setup},
84 /**********************************************************************
85 **********************************************************************/
86 const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type)
89 case OSM_ROUTING_ENGINE_TYPE_NONE:
91 case OSM_ROUTING_ENGINE_TYPE_MINHOP:
93 case OSM_ROUTING_ENGINE_TYPE_UPDN:
95 case OSM_ROUTING_ENGINE_TYPE_FILE:
97 case OSM_ROUTING_ENGINE_TYPE_FTREE:
99 case OSM_ROUTING_ENGINE_TYPE_LASH:
101 case OSM_ROUTING_ENGINE_TYPE_DOR:
109 /**********************************************************************
110 **********************************************************************/
111 osm_routing_engine_type_t osm_routing_engine_type(IN const char *str)
113 /* For legacy reasons, consider a NULL pointer and the string
114 * "null" as the minhop routing engine.
116 if (!str || !strcasecmp(str, "null")
117 || !strcasecmp(str, "minhop"))
118 return OSM_ROUTING_ENGINE_TYPE_MINHOP;
119 else if (!strcasecmp(str, "none"))
120 return OSM_ROUTING_ENGINE_TYPE_NONE;
121 else if (!strcasecmp(str, "updn"))
122 return OSM_ROUTING_ENGINE_TYPE_UPDN;
123 else if (!strcasecmp(str, "file"))
124 return OSM_ROUTING_ENGINE_TYPE_FILE;
125 else if (!strcasecmp(str, "ftree"))
126 return OSM_ROUTING_ENGINE_TYPE_FTREE;
127 else if (!strcasecmp(str, "lash"))
128 return OSM_ROUTING_ENGINE_TYPE_LASH;
129 else if (!strcasecmp(str, "dor"))
130 return OSM_ROUTING_ENGINE_TYPE_DOR;
132 return OSM_ROUTING_ENGINE_TYPE_UNKNOWN;
135 /**********************************************************************
136 **********************************************************************/
137 static void append_routing_engine(osm_opensm_t *osm,
138 struct osm_routing_engine *routing_engine)
140 struct osm_routing_engine *r;
142 routing_engine->next = NULL;
144 if (!osm->routing_engine_list) {
145 osm->routing_engine_list = routing_engine;
149 r = osm->routing_engine_list;
153 r->next = routing_engine;
156 static void setup_routing_engine(osm_opensm_t *osm, const char *name)
158 struct osm_routing_engine *re;
159 const struct routing_engine_module *m;
161 for (m = routing_modules; m->name && *m->name; m++) {
162 if (!strcmp(m->name, name)) {
163 re = malloc(sizeof(struct osm_routing_engine));
165 OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
166 "memory allocation failed\n");
169 memset(re, 0, sizeof(struct osm_routing_engine));
172 if (m->setup(re, osm)) {
173 OSM_LOG(&osm->log, OSM_LOG_VERBOSE,
175 " engine \'%s\' failed\n", name);
178 OSM_LOG(&osm->log, OSM_LOG_DEBUG,
179 "\'%s\' routing engine set up\n", re->name);
180 append_routing_engine(osm, re);
185 OSM_LOG(&osm->log, OSM_LOG_ERROR,
186 "cannot find or setup routing engine \'%s\'", name);
189 static void setup_routing_engines(osm_opensm_t *osm, const char *engine_names)
191 char *name, *str, *p;
193 if (!engine_names || !*engine_names) {
194 setup_routing_engine(osm, "minhop");
198 str = strdup(engine_names);
199 name = strtok_r(str, ", \t\n", &p);
200 while (name && *name) {
201 setup_routing_engine(osm, name);
202 name = strtok_r(NULL, ", \t\n", &p);
206 if (!osm->routing_engine_list)
207 setup_routing_engine(osm, "minhop");
210 /**********************************************************************
211 **********************************************************************/
212 void osm_opensm_construct(IN osm_opensm_t * const p_osm)
214 memset(p_osm, 0, sizeof(*p_osm));
215 p_osm->osm_version = OSM_VERSION;
216 osm_subn_construct(&p_osm->subn);
217 osm_sm_construct(&p_osm->sm);
218 osm_sa_construct(&p_osm->sa);
219 osm_db_construct(&p_osm->db);
220 osm_mad_pool_construct(&p_osm->mad_pool);
221 osm_vl15_construct(&p_osm->vl15);
222 osm_log_construct(&p_osm->log);
225 /**********************************************************************
226 **********************************************************************/
227 static void destroy_routing_engines(osm_opensm_t *osm)
229 struct osm_routing_engine *r, *next;
231 next = osm->routing_engine_list;
236 r->delete(r->context);
241 /**********************************************************************
242 **********************************************************************/
243 static void destroy_plugins(osm_opensm_t *osm)
246 /* remove from the list, and destroy it */
247 while (!cl_is_qlist_empty(&osm->plugin_list)){
248 p = (osm_epi_plugin_t *)cl_qlist_remove_head(&osm->plugin_list);
249 /* plugin is responsible for freeing its own resources */
254 void osm_opensm_destroy(IN osm_opensm_t * const p_osm)
256 /* in case of shutdown through exit proc - no ^C */
257 osm_exit_flag = TRUE;
260 * First of all, clear the is_sm bit.
262 if (p_osm->sm.mad_ctrl.h_bind)
263 osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, FALSE);
265 #ifdef ENABLE_OSM_PERF_MGR
266 /* Shutdown the PerfMgr */
267 osm_perfmgr_shutdown(&p_osm->perfmgr);
268 #endif /* ENABLE_OSM_PERF_MGR */
271 * - unbind from QP1 messages
273 osm_sa_shutdown(&p_osm->sa);
276 * - make sure the SM sweeper thread exited
277 * - unbind from QP0 messages
279 osm_sm_shutdown(&p_osm->sm);
281 /* cleanup all messages on VL15 fifo that were not sent yet */
282 osm_vl15_shutdown(&p_osm->vl15, &p_osm->mad_pool);
284 /* shut down the dispatcher - so no new messages cross */
285 cl_disp_shutdown(&p_osm->disp);
288 osm_sa_db_file_dump(p_osm);
290 /* do the destruction in reverse order as init */
291 destroy_plugins(p_osm);
292 destroy_routing_engines(p_osm);
293 osm_sa_destroy(&p_osm->sa);
294 osm_sm_destroy(&p_osm->sm);
295 #ifdef ENABLE_OSM_PERF_MGR
296 osm_perfmgr_destroy(&p_osm->perfmgr);
297 #endif /* ENABLE_OSM_PERF_MGR */
298 osm_db_destroy(&p_osm->db);
299 osm_vl15_destroy(&p_osm->vl15, &p_osm->mad_pool);
300 osm_mad_pool_destroy(&p_osm->mad_pool);
301 osm_vendor_delete(&p_osm->p_vendor);
302 osm_subn_destroy(&p_osm->subn);
303 cl_disp_destroy(&p_osm->disp);
304 #ifdef HAVE_LIBPTHREAD
305 pthread_cond_destroy(&p_osm->stats.cond);
306 pthread_mutex_destroy(&p_osm->stats.mutex);
308 cl_event_destroy(&p_osm->stats.event);
310 close_node_name_map(p_osm->node_name_map);
312 cl_plock_destroy(&p_osm->lock);
314 osm_log_destroy(&p_osm->log);
317 static void load_plugins(osm_opensm_t *osm, const char *plugin_names)
319 osm_epi_plugin_t *epi;
320 char *p_names, *name, *p;
322 p_names = strdup(plugin_names);
323 name = strtok_r(p_names, " \t\n", &p);
324 while (name && *name) {
325 epi = osm_epi_construct(osm, name);
327 osm_log(&osm->log, OSM_LOG_ERROR,
328 "cannot load plugin \'%s\'\n", name);
330 cl_qlist_insert_tail(&osm->plugin_list, &epi->list);
331 name = strtok_r(NULL, " \t\n", &p);
336 /**********************************************************************
337 **********************************************************************/
339 osm_opensm_init(IN osm_opensm_t * const p_osm,
340 IN const osm_subn_opt_t * const p_opt)
342 ib_api_status_t status;
344 /* Can't use log macros here, since we're initializing the log */
345 osm_opensm_construct(p_osm);
348 p_osm->log.daemon = 1;
350 status = osm_log_init_v2(&p_osm->log, p_opt->force_log_flush,
351 p_opt->log_flags, p_opt->log_file,
352 p_opt->log_max_size, p_opt->accum_log_file);
353 if (status != IB_SUCCESS)
356 /* If there is a log level defined - add the OSM_VERSION to it */
358 osm_log_get_level(&p_osm->log) & (OSM_LOG_SYS ^ 0xFF), "%s\n",
360 /* Write the OSM_VERSION to the SYS_LOG */
361 osm_log(&p_osm->log, OSM_LOG_SYS, "%s\n", p_osm->osm_version); /* Format Waived */
363 OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "[\n"); /* Format Waived */
365 status = cl_plock_init(&p_osm->lock);
366 if (status != IB_SUCCESS)
369 #ifdef HAVE_LIBPTHREAD
370 pthread_mutex_init(&p_osm->stats.mutex, NULL);
371 pthread_cond_init(&p_osm->stats.cond, NULL);
373 status = cl_event_init(&p_osm->stats.event, FALSE);
374 if (status != IB_SUCCESS)
378 if (p_opt->single_thread) {
379 OSM_LOG(&p_osm->log, OSM_LOG_INFO,
380 "Forcing single threaded dispatcher\n");
381 status = cl_disp_init(&p_osm->disp, 1, "opensm");
384 * Normal behavior is to initialize the dispatcher with
385 * one thread per CPU, as specified by a thread count of '0'.
387 status = cl_disp_init(&p_osm->disp, 0, "opensm");
389 if (status != IB_SUCCESS)
392 status = osm_subn_init(&p_osm->subn, p_osm, p_opt);
393 if (status != IB_SUCCESS)
397 osm_vendor_new(&p_osm->log, p_opt->transaction_timeout);
398 if (p_osm->p_vendor == NULL) {
399 status = IB_INSUFFICIENT_RESOURCES;
403 status = osm_mad_pool_init(&p_osm->mad_pool);
404 if (status != IB_SUCCESS)
407 status = osm_vl15_init(&p_osm->vl15, p_osm->p_vendor,
408 &p_osm->log, &p_osm->stats,
409 p_opt->max_wire_smps);
410 if (status != IB_SUCCESS)
413 /* the DB is in use by the SM and SA so init before */
414 status = osm_db_init(&p_osm->db, &p_osm->log);
415 if (status != IB_SUCCESS)
418 status = osm_sm_init(&p_osm->sm, &p_osm->subn, &p_osm->db,
419 p_osm->p_vendor, &p_osm->mad_pool, &p_osm->vl15,
420 &p_osm->log, &p_osm->stats, &p_osm->disp,
423 if (status != IB_SUCCESS)
426 status = osm_sa_init(&p_osm->sm, &p_osm->sa, &p_osm->subn,
427 p_osm->p_vendor, &p_osm->mad_pool, &p_osm->log,
428 &p_osm->stats, &p_osm->disp, &p_osm->lock);
430 if (status != IB_SUCCESS)
433 cl_qlist_init(&p_osm->plugin_list);
435 if (p_opt->event_plugin_name)
436 load_plugins(p_osm, p_opt->event_plugin_name);
438 #ifdef ENABLE_OSM_PERF_MGR
439 status = osm_perfmgr_init(&p_osm->perfmgr, p_osm, p_opt);
440 if (status != IB_SUCCESS)
442 #endif /* ENABLE_OSM_PERF_MGR */
444 setup_routing_engines(p_osm, p_opt->routing_engine_names);
446 p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_NONE;
448 p_osm->node_name_map = open_node_name_map(p_opt->node_name_map_name);
451 OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n"); /* Format Waived */
455 /**********************************************************************
456 **********************************************************************/
458 osm_opensm_bind(IN osm_opensm_t * const p_osm, IN const ib_net64_t guid)
460 ib_api_status_t status;
462 OSM_LOG_ENTER(&p_osm->log);
464 status = osm_sm_bind(&p_osm->sm, guid);
465 if (status != IB_SUCCESS)
468 status = osm_sa_bind(&p_osm->sa, guid);
469 if (status != IB_SUCCESS)
472 #ifdef ENABLE_OSM_PERF_MGR
473 status = osm_perfmgr_bind(&p_osm->perfmgr, guid);
474 if (status != IB_SUCCESS)
476 #endif /* ENABLE_OSM_PERF_MGR */
479 OSM_LOG_EXIT(&p_osm->log);
483 /**********************************************************************
484 **********************************************************************/
485 void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id,
488 cl_list_item_t *item;
490 for (item = cl_qlist_head(&osm->plugin_list);
491 item != cl_qlist_end(&osm->plugin_list);
492 item = cl_qlist_next(item)) {
493 osm_epi_plugin_t *p = (osm_epi_plugin_t *)item;
495 p->impl->report(p->plugin_data, event_id, event_data);