2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2014 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.
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 * Implementation of osm_sa_t.
40 * This object represents the Subnet Administration object.
41 * This object is part of the opensm family of objects.
46 #endif /* HAVE_CONFIG_H */
53 #include <sys/types.h>
55 #include <complib/cl_qmap.h>
56 #include <complib/cl_passivelock.h>
57 #include <complib/cl_debug.h>
58 #include <iba/ib_types.h>
59 #include <opensm/osm_file_ids.h>
60 #define FILE_ID OSM_FILE_SA_C
61 #include <opensm/osm_sa.h>
62 #include <opensm/osm_madw.h>
63 #include <opensm/osm_log.h>
64 #include <opensm/osm_subnet.h>
65 #include <opensm/osm_mad_pool.h>
66 #include <opensm/osm_msgdef.h>
67 #include <opensm/osm_opensm.h>
68 #include <opensm/osm_multicast.h>
69 #include <opensm/osm_inform.h>
70 #include <opensm/osm_service.h>
71 #include <opensm/osm_guid.h>
72 #include <opensm/osm_helper.h>
73 #include <vendor/osm_vendor_api.h>
75 #define OSM_SA_INITIAL_TID_VALUE 0xabc
77 extern void osm_cpi_rcv_process(IN void *context, IN void *data);
78 extern void osm_gir_rcv_process(IN void *context, IN void *data);
79 extern void osm_infr_rcv_process(IN void *context, IN void *data);
80 extern void osm_infir_rcv_process(IN void *context, IN void *data);
81 extern void osm_lftr_rcv_process(IN void *context, IN void *data);
82 extern void osm_lr_rcv_process(IN void *context, IN void *data);
83 extern void osm_mcmr_rcv_process(IN void *context, IN void *data);
84 extern void osm_mftr_rcv_process(IN void *context, IN void *data);
85 extern void osm_mpr_rcv_process(IN void *context, IN void *data);
86 extern void osm_nr_rcv_process(IN void *context, IN void *data);
87 extern void osm_pr_rcv_process(IN void *context, IN void *data);
88 extern void osm_pkey_rec_rcv_process(IN void *context, IN void *data);
89 extern void osm_pir_rcv_process(IN void *context, IN void *data);
90 extern void osm_sr_rcv_process(IN void *context, IN void *data);
91 extern void osm_slvl_rec_rcv_process(IN void *context, IN void *data);
92 extern void osm_smir_rcv_process(IN void *context, IN void *data);
93 extern void osm_sir_rcv_process(IN void *context, IN void *data);
94 extern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data);
95 extern void osm_sr_rcv_lease_cb(IN void *context);
97 void osm_sa_construct(IN osm_sa_t * p_sa)
99 memset(p_sa, 0, sizeof(*p_sa));
100 p_sa->state = OSM_SA_STATE_INIT;
101 p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE;
103 cl_timer_construct(&p_sa->sr_timer);
106 void osm_sa_shutdown(IN osm_sa_t * p_sa)
108 OSM_LOG_ENTER(p_sa->p_log);
110 cl_timer_stop(&p_sa->sr_timer);
112 /* unbind from the mad service */
113 osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl);
115 /* remove any registered dispatcher message */
116 cl_disp_unregister(p_sa->nr_disp_h);
117 cl_disp_unregister(p_sa->pir_disp_h);
118 cl_disp_unregister(p_sa->gir_disp_h);
119 cl_disp_unregister(p_sa->lr_disp_h);
120 cl_disp_unregister(p_sa->pr_disp_h);
121 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
122 cl_disp_unregister(p_sa->mpr_disp_h);
124 cl_disp_unregister(p_sa->smir_disp_h);
125 cl_disp_unregister(p_sa->mcmr_disp_h);
126 cl_disp_unregister(p_sa->sr_disp_h);
127 cl_disp_unregister(p_sa->infr_disp_h);
128 cl_disp_unregister(p_sa->infir_disp_h);
129 cl_disp_unregister(p_sa->vlarb_disp_h);
130 cl_disp_unregister(p_sa->slvl_disp_h);
131 cl_disp_unregister(p_sa->pkey_disp_h);
132 cl_disp_unregister(p_sa->lft_disp_h);
133 cl_disp_unregister(p_sa->sir_disp_h);
134 cl_disp_unregister(p_sa->mft_disp_h);
136 if (p_sa->p_set_disp) {
137 cl_disp_unregister(p_sa->mcmr_set_disp_h);
138 cl_disp_unregister(p_sa->infr_set_disp_h);
139 cl_disp_unregister(p_sa->sr_set_disp_h);
140 cl_disp_unregister(p_sa->gir_set_disp_h);
143 osm_sa_mad_ctrl_destroy(&p_sa->mad_ctrl);
145 OSM_LOG_EXIT(p_sa->p_log);
148 void osm_sa_destroy(IN osm_sa_t * p_sa)
150 OSM_LOG_ENTER(p_sa->p_log);
152 p_sa->state = OSM_SA_STATE_INIT;
154 cl_timer_destroy(&p_sa->sr_timer);
156 OSM_LOG_EXIT(p_sa->p_log);
159 ib_api_status_t osm_sa_init(IN osm_sm_t * p_sm, IN osm_sa_t * p_sa,
160 IN osm_subn_t * p_subn, IN osm_vendor_t * p_vendor,
161 IN osm_mad_pool_t * p_mad_pool,
162 IN osm_log_t * p_log, IN osm_stats_t * p_stats,
163 IN cl_dispatcher_t * p_disp,
164 IN cl_dispatcher_t * p_set_disp,
165 IN cl_plock_t * p_lock)
167 ib_api_status_t status;
169 OSM_LOG_ENTER(p_log);
172 p_sa->p_subn = p_subn;
173 p_sa->p_vendor = p_vendor;
174 p_sa->p_mad_pool = p_mad_pool;
176 p_sa->p_disp = p_disp;
177 p_sa->p_set_disp = p_set_disp;
178 p_sa->p_lock = p_lock;
180 p_sa->state = OSM_SA_STATE_READY;
182 status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl, p_sa, p_sa->p_mad_pool,
183 p_sa->p_vendor, p_subn, p_log, p_stats,
185 if (status != IB_SUCCESS)
188 status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa);
189 if (status != IB_SUCCESS)
192 status = IB_INSUFFICIENT_RESOURCES;
193 p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO,
194 osm_cpi_rcv_process, p_sa);
195 if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE)
198 p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD,
199 osm_nr_rcv_process, p_sa);
200 if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE)
203 p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD,
204 osm_pir_rcv_process, p_sa);
205 if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE)
208 p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD,
209 osm_gir_rcv_process, p_sa);
210 if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE)
213 p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD,
214 osm_lr_rcv_process, p_sa);
215 if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE)
218 p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD,
219 osm_pr_rcv_process, p_sa);
220 if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE)
223 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
225 cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD,
226 osm_mpr_rcv_process, p_sa);
227 if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE)
231 p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD,
232 osm_smir_rcv_process, p_sa);
233 if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE)
237 cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD,
238 osm_mcmr_rcv_process, p_sa);
239 if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE)
242 p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD,
243 osm_sr_rcv_process, p_sa);
244 if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE)
247 p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO,
248 osm_infr_rcv_process, p_sa);
249 if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE)
253 cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD,
254 osm_infir_rcv_process, p_sa);
255 if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE)
258 p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD,
259 osm_vlarb_rec_rcv_process, p_sa);
260 if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE)
264 cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD,
265 osm_slvl_rec_rcv_process, p_sa);
266 if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE)
270 cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD,
271 osm_pkey_rec_rcv_process, p_sa);
272 if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE)
275 p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD,
276 osm_lftr_rcv_process, p_sa);
277 if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE)
281 cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD,
282 osm_sir_rcv_process, p_sa);
283 if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE)
286 p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD,
287 osm_mftr_rcv_process, p_sa);
288 if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE)
292 * When p_set_disp is defined, it means that we use different dispatcher
293 * for SA Set requests, and we need to register handlers for it.
296 p_sa->gir_set_disp_h =
297 cl_disp_register(p_set_disp, OSM_MSG_MAD_GUIDINFO_RECORD,
298 osm_gir_rcv_process, p_sa);
299 if (p_sa->gir_set_disp_h == CL_DISP_INVALID_HANDLE)
302 p_sa->mcmr_set_disp_h =
303 cl_disp_register(p_set_disp, OSM_MSG_MAD_MCMEMBER_RECORD,
304 osm_mcmr_rcv_process, p_sa);
305 if (p_sa->mcmr_set_disp_h == CL_DISP_INVALID_HANDLE)
308 p_sa->sr_set_disp_h =
309 cl_disp_register(p_set_disp, OSM_MSG_MAD_SERVICE_RECORD,
310 osm_sr_rcv_process, p_sa);
311 if (p_sa->sr_set_disp_h == CL_DISP_INVALID_HANDLE)
314 p_sa->infr_set_disp_h =
315 cl_disp_register(p_set_disp, OSM_MSG_MAD_INFORM_INFO,
316 osm_infr_rcv_process, p_sa);
317 if (p_sa->infr_set_disp_h == CL_DISP_INVALID_HANDLE)
327 ib_api_status_t osm_sa_bind(IN osm_sa_t * p_sa, IN ib_net64_t port_guid)
329 ib_api_status_t status;
331 OSM_LOG_ENTER(p_sa->p_log);
333 status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid);
335 if (status != IB_SUCCESS) {
336 OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: "
337 "SA MAD Controller bind failed (%s)\n",
338 ib_get_err_str(status));
343 OSM_LOG_EXIT(p_sa->p_log);
347 ib_api_status_t osm_sa_send(osm_sa_t *sa, IN osm_madw_t * p_madw,
348 IN boolean_t resp_expected)
350 ib_api_status_t status;
352 cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent);
353 status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected);
354 if (status != IB_SUCCESS) {
355 cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent);
356 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: "
357 "osm_vendor_send failed, status = %s\n",
358 ib_get_err_str(status));
363 void osm_sa_send_error(IN osm_sa_t * sa, IN const osm_madw_t * p_madw,
364 IN ib_net16_t sa_status)
366 osm_madw_t *p_resp_madw;
367 ib_sa_mad_t *p_resp_sa_mad;
368 ib_sa_mad_t *p_sa_mad;
370 OSM_LOG_ENTER(sa->p_log);
372 /* avoid races - if we are exiting - exit */
374 OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
375 "Ignoring requested send after exit\n");
379 p_resp_madw = osm_mad_pool_get(sa->p_mad_pool,
380 p_madw->h_bind, MAD_BLOCK_SIZE,
383 if (p_resp_madw == NULL) {
384 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: "
385 "Unable to acquire response MAD\n");
389 p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
390 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
392 /* Copy the MAD header back into the response mad */
393 *p_resp_sa_mad = *p_sa_mad;
394 p_resp_sa_mad->status = sa_status;
396 if (p_resp_sa_mad->method == IB_MAD_METHOD_SET)
397 p_resp_sa_mad->method = IB_MAD_METHOD_GET;
398 else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE)
399 p_resp_sa_mad->attr_offset = 0;
401 p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
404 * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
406 p_resp_sa_mad->sm_key = 0;
409 * o15-0.2.7 - The PathRecord Attribute ID shall be used in
410 * the response (to a SubnAdmGetMulti(MultiPathRecord)
412 if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD)
413 p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
415 if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_FRAMES))
416 osm_dump_sa_mad_v2(sa->p_log, p_resp_sa_mad, FILE_ID, OSM_LOG_FRAMES);
418 osm_sa_send(sa, p_resp_madw, FALSE);
421 OSM_LOG_EXIT(sa->p_log);
424 void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
427 cl_list_item_t *item;
428 osm_madw_t *resp_madw;
429 ib_sa_mad_t *sa_mad, *resp_sa_mad;
431 #ifndef VENDOR_RMPP_SUPPORT
432 unsigned trim_num_rec;
436 sa_mad = osm_madw_get_sa_mad_ptr(madw);
437 num_rec = cl_qlist_count(list);
441 * If we do a SubnAdmGet and got more than one record it is an error!
443 if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
444 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
445 "Got %u records for SubnAdmGet(%s) comp_mask 0x%016" PRIx64
446 "from requester LID %u\n",
447 num_rec, ib_get_sa_attr_str(sa_mad->attr_id),
448 cl_ntoh64(sa_mad->comp_mask),
449 cl_ntoh16(madw->mad_addr.dest_lid));
450 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
454 #ifndef VENDOR_RMPP_SUPPORT
455 trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
456 if (trim_num_rec < num_rec) {
457 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
458 "Number of records:%u trimmed to:%u to fit in one MAD\n",
459 num_rec, trim_num_rec);
460 num_rec = trim_num_rec;
464 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec);
466 if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) {
467 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS);
472 * Get a MAD to reply. Address of Mad is in the received mad_wrapper
474 resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind,
475 num_rec * attr_size + IB_SA_MAD_HDR_SIZE,
478 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: "
479 "osm_mad_pool_get failed\n");
480 osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES);
484 resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw);
487 Copy the MAD header back into the response mad.
488 Set the 'R' bit and the payload length,
489 Then copy all records from the list into the response payload.
492 memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE);
493 if (resp_sa_mad->method == IB_MAD_METHOD_SET)
494 resp_sa_mad->method = IB_MAD_METHOD_GET;
495 resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
496 /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
497 resp_sa_mad->sm_key = 0;
499 /* Fill in the offset (paylen will be done by the rmpp SAR) */
500 resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0;
502 p = ib_sa_mad_get_payload_ptr(resp_sa_mad);
504 #ifndef VENDOR_RMPP_SUPPORT
505 /* we support only one packet RMPP - so we will set the first and
506 last flags for gettable */
507 if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) {
508 resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
509 resp_sa_mad->rmpp_flags =
510 IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST |
514 /* forcefully define the packet as RMPP one */
515 if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
516 resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
519 for (i = 0; i < num_rec; i++) {
520 item = cl_qlist_remove_head(list);
521 memcpy(p, ((osm_sa_item_t *)item)->resp.data, attr_size);
526 osm_dump_sa_mad_v2(sa->p_log, resp_sa_mad, FILE_ID, OSM_LOG_FRAMES);
527 osm_sa_send(sa, resp_madw, FALSE);
530 /* need to set the mem free ... */
531 item = cl_qlist_remove_head(list);
532 while (item != cl_qlist_end(list)) {
534 item = cl_qlist_remove_head(list);
543 struct opensm_dump_context {
549 opensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name,
550 void (*dump_func) (osm_opensm_t * p_osm, FILE * file))
557 snprintf(path, sizeof(path), "%s/%s",
558 p_osm->subn.opt.dump_files_dir, file_name);
560 snprintf(path_tmp, sizeof(path_tmp), "%s.tmp", path);
562 file = fopen(path_tmp, "w");
564 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C01: "
565 "cannot open file \'%s\': %s\n",
566 path_tmp, strerror(errno));
570 if (chmod(path_tmp, S_IRUSR | S_IWUSR)) {
571 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0C: "
572 "cannot change access permissions of file "
574 path_tmp, strerror(errno));
579 dump_func(p_osm, file);
581 if (p_osm->subn.opt.fsync_high_avail_files) {
582 if (fflush(file) == 0) {
586 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
587 "ERR 4C08: fsync() failed (%s) for %s\n",
588 strerror(errno), path_tmp);
590 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C09: "
591 "fileno() failed for %s\n", path_tmp);
593 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0A: "
594 "fflush() failed (%s) for %s\n",
595 strerror(errno), path_tmp);
600 status = rename(path_tmp, path);
602 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0B: "
603 "Failed to rename file:%s (err:%s)\n",
604 path_tmp, strerror(errno));
610 static void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt)
612 FILE *file = ((struct opensm_dump_context *)cxt)->file;
613 osm_mcm_alias_guid_t *p_mcm_alias_guid = (osm_mcm_alias_guid_t *) p_map_item;
615 fprintf(file, "mcm_port: "
616 "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " "
617 "scope_state=0x%02x proxy_join=0x%x" "\n\n",
618 cl_ntoh64(p_mcm_alias_guid->port_gid.unicast.prefix),
619 cl_ntoh64(p_mcm_alias_guid->port_gid.unicast.interface_id),
620 p_mcm_alias_guid->scope_state, p_mcm_alias_guid->proxy_join);
623 static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt)
625 struct opensm_dump_context dump_context;
626 osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
627 FILE *file = ((struct opensm_dump_context *)cxt)->file;
629 fprintf(file, "MC Group 0x%04x %s:"
630 " mgid=0x%016" PRIx64 ":0x%016" PRIx64
631 " port_gid=0x%016" PRIx64 ":0x%016" PRIx64
632 " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
633 " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
634 " scope_state=0x%02x proxy_join=0x%x" "\n\n",
635 cl_ntoh16(p_mgrp->mlid),
636 p_mgrp->well_known ? " (well known)" : "",
637 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
638 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
639 cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
640 cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
641 cl_ntoh32(p_mgrp->mcmember_rec.qkey),
642 cl_ntoh16(p_mgrp->mcmember_rec.mlid),
643 p_mgrp->mcmember_rec.mtu,
644 p_mgrp->mcmember_rec.tclass,
645 cl_ntoh16(p_mgrp->mcmember_rec.pkey),
646 p_mgrp->mcmember_rec.rate,
647 p_mgrp->mcmember_rec.pkt_life,
648 cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
649 p_mgrp->mcmember_rec.scope_state,
650 p_mgrp->mcmember_rec.proxy_join);
652 dump_context.p_osm = p_osm;
653 dump_context.file = file;
655 cl_qmap_apply_func(&p_mgrp->mcm_alias_port_tbl,
656 mcast_mgr_dump_one_port, &dump_context);
659 static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt)
661 FILE *file = ((struct opensm_dump_context *)cxt)->file;
662 osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
663 ib_inform_info_record_t *p_iir = &p_infr->inform_record;
665 fprintf(file, "InformInfo Record:"
666 " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
667 " subscriber_enum=0x%x"
669 " gid=0x%016" PRIx64 ":0x%016" PRIx64
670 " lid_range_begin=0x%x"
671 " lid_range_end=0x%x"
676 " qpn_resp_time_val=0x%x"
678 " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
679 " remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x"
681 cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
682 cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
683 cl_ntoh16(p_iir->subscriber_enum),
684 cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
685 cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
686 cl_ntoh16(p_iir->inform_info.lid_range_begin),
687 cl_ntoh16(p_iir->inform_info.lid_range_end),
688 p_iir->inform_info.is_generic,
689 p_iir->inform_info.subscribe,
690 cl_ntoh16(p_iir->inform_info.trap_type),
691 cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
692 cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
693 cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)),
694 cl_ntoh16(p_infr->report_addr.dest_lid),
695 p_infr->report_addr.path_bits,
696 p_infr->report_addr.static_rate,
697 cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
698 cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
699 p_infr->report_addr.addr_type.gsi.pkey_ix,
700 p_infr->report_addr.addr_type.gsi.service_level);
703 static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt)
705 FILE *file = ((struct opensm_dump_context *)cxt)->file;
706 osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item;
707 ib_service_record_t *p_sr = &p_svcr->service_record;
709 fprintf(file, "Service Record: id=0x%016" PRIx64
710 " gid=0x%016" PRIx64 ":0x%016" PRIx64
713 " key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
714 ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
716 " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
717 ":0x%02x%02x%02x%02x%02x%02x%02x%02x"
718 " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
719 " data32=0x%08x%08x:0x%08x%08x"
720 " data64=0x%016" PRIx64 ":0x%016" PRIx64
721 " modified_time=0x%x lease_period=0x%x\n\n",
722 cl_ntoh64(p_sr->service_id),
723 cl_ntoh64(p_sr->service_gid.unicast.prefix),
724 cl_ntoh64(p_sr->service_gid.unicast.interface_id),
725 cl_ntoh16(p_sr->service_pkey),
726 cl_ntoh32(p_sr->service_lease),
727 p_sr->service_key[0], p_sr->service_key[1],
728 p_sr->service_key[2], p_sr->service_key[3],
729 p_sr->service_key[4], p_sr->service_key[5],
730 p_sr->service_key[6], p_sr->service_key[7],
731 p_sr->service_key[8], p_sr->service_key[9],
732 p_sr->service_key[10], p_sr->service_key[11],
733 p_sr->service_key[12], p_sr->service_key[13],
734 p_sr->service_key[14], p_sr->service_key[15],
736 p_sr->service_data8[0], p_sr->service_data8[1],
737 p_sr->service_data8[2], p_sr->service_data8[3],
738 p_sr->service_data8[4], p_sr->service_data8[5],
739 p_sr->service_data8[6], p_sr->service_data8[7],
740 p_sr->service_data8[8], p_sr->service_data8[9],
741 p_sr->service_data8[10], p_sr->service_data8[11],
742 p_sr->service_data8[12], p_sr->service_data8[13],
743 p_sr->service_data8[14], p_sr->service_data8[15],
744 cl_ntoh16(p_sr->service_data16[0]),
745 cl_ntoh16(p_sr->service_data16[1]),
746 cl_ntoh16(p_sr->service_data16[2]),
747 cl_ntoh16(p_sr->service_data16[3]),
748 cl_ntoh16(p_sr->service_data16[4]),
749 cl_ntoh16(p_sr->service_data16[5]),
750 cl_ntoh16(p_sr->service_data16[6]),
751 cl_ntoh16(p_sr->service_data16[7]),
752 cl_ntoh32(p_sr->service_data32[0]),
753 cl_ntoh32(p_sr->service_data32[1]),
754 cl_ntoh32(p_sr->service_data32[2]),
755 cl_ntoh32(p_sr->service_data32[3]),
756 cl_ntoh64(p_sr->service_data64[0]),
757 cl_ntoh64(p_sr->service_data64[1]),
758 p_svcr->modified_time, p_svcr->lease_period);
761 static void sa_dump_one_port_guidinfo(cl_map_item_t * p_map_item, void *cxt)
763 FILE *file = ((struct opensm_dump_context *)cxt)->file;
764 osm_port_t *p_port = (osm_port_t *) p_map_item;
768 if (!p_port->p_physp->p_guids)
771 max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) /
772 GUID_TABLE_MAX_ENTRIES;
774 for (block_num = 0; block_num < max_block; block_num++) {
775 fprintf(file, "GUIDInfo Record:"
776 " base_guid=0x%016" PRIx64 " lid=0x%04x block_num=0x%x"
777 " guid0=0x%016" PRIx64 " guid1=0x%016" PRIx64
778 " guid2=0x%016" PRIx64 " guid3=0x%016" PRIx64
779 " guid4=0x%016" PRIx64 " guid5=0x%016" PRIx64
780 " guid6=0x%016" PRIx64 " guid7=0x%016" PRIx64
782 cl_ntoh64((*p_port->p_physp->p_guids)[0]),
783 cl_ntoh16(osm_port_get_base_lid(p_port)), block_num,
784 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES]),
785 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 1]),
786 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 2]),
787 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 3]),
788 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 4]),
789 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 5]),
790 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 6]),
791 cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 7]));
795 static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
797 struct opensm_dump_context dump_context;
800 dump_context.p_osm = p_osm;
801 dump_context.file = file;
802 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump guidinfo\n");
803 cl_qmap_apply_func(&p_osm->subn.port_guid_tbl,
804 sa_dump_one_port_guidinfo, &dump_context);
805 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast\n");
806 for (p_mgrp = (osm_mgrp_t *) cl_fmap_head(&p_osm->subn.mgrp_mgid_tbl);
807 p_mgrp != (osm_mgrp_t *) cl_fmap_end(&p_osm->subn.mgrp_mgid_tbl);
808 p_mgrp = (osm_mgrp_t *) cl_fmap_next(&p_mgrp->map_item))
809 sa_dump_one_mgrp(p_mgrp, &dump_context);
810 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform\n");
811 cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
812 sa_dump_one_inform, &dump_context);
813 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services\n");
814 cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
815 sa_dump_one_service, &dump_context);
818 int osm_sa_db_file_dump(osm_opensm_t * p_osm)
822 cl_plock_acquire(&p_osm->lock);
823 if (p_osm->sa.dirty) {
824 res = opensm_dump_to_file(
825 p_osm, "opensm-sa.dump", sa_dump_all_sa);
827 p_osm->sa.dirty = FALSE;
829 cl_plock_release(&p_osm->lock);
837 static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid,
838 ib_member_rec_t * p_mcm_rec)
840 ib_net64_t comp_mask;
843 cl_plock_excl_acquire(&p_osm->lock);
845 p_mgrp = osm_get_mgrp_by_mgid(&p_osm->subn, &p_mcm_rec->mgid);
847 if (p_mgrp->mlid == mlid) {
848 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
849 "mgrp %04x is already here.", cl_ntoh16(mlid));
852 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
853 "mlid %04x is already used by another MC group. Will "
854 "request clients reregistration.\n", cl_ntoh16(mlid));
859 comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
860 | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
861 if (!(p_mgrp = osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa,
864 p_mgrp->mlid != mlid) {
865 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
866 "cannot create MC group with mlid 0x%04x and mgid "
867 "0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid),
868 cl_ntoh64(p_mcm_rec->mgid.unicast.prefix),
869 cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id));
874 cl_plock_release(&p_osm->lock);
879 static int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr,
880 uint32_t modified_time, uint32_t lease_period)
885 cl_plock_excl_acquire(&p_osm->lock);
887 if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) {
888 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
889 "ServiceRecord already exists\n");
893 if (!(p_svcr = osm_svcr_new(sr))) {
894 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
895 "cannot allocate new service struct\n");
900 p_svcr->modified_time = modified_time;
901 p_svcr->lease_period = lease_period;
903 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n");
905 osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr);
907 if (lease_period != 0xffffffff)
908 cl_timer_trim(&p_osm->sa.sr_timer, 1000);
911 cl_plock_release(&p_osm->lock);
916 static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir,
917 osm_mad_addr_t * addr)
919 osm_infr_t infr, *p_infr;
922 infr.h_bind = p_osm->sa.mad_ctrl.h_bind;
923 infr.sa = &p_osm->sa;
924 /* other possible way to restore mad_addr partially is
925 to extract qpn from InformInfo and to find lid by gid */
926 infr.report_addr = *addr;
927 infr.inform_record = *iir;
929 cl_plock_excl_acquire(&p_osm->lock);
930 if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) {
931 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
932 "InformInfo Record already exists\n");
936 if (!(p_infr = osm_infr_new(&infr))) {
937 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
938 "cannot allocate new infr struct\n");
943 OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n");
945 osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr);
948 cl_plock_release(&p_osm->lock);
953 static int load_guidinfo(osm_opensm_t * p_osm, ib_net64_t base_guid,
954 ib_guidinfo_record_t *gir)
959 osm_alias_guid_t *p_alias_guid, *p_alias_guid_check;
961 cl_plock_excl_acquire(&p_osm->lock);
963 p_port = osm_get_port_by_guid(&p_osm->subn, base_guid);
967 if (!p_port->p_physp->p_guids) {
968 max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) /
969 GUID_TABLE_MAX_ENTRIES;
970 p_port->p_physp->p_guids = calloc(max_block * GUID_TABLE_MAX_ENTRIES,
972 if (!p_port->p_physp->p_guids) {
973 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
974 "cannot allocate GUID table for port "
975 "GUID 0x%" PRIx64 "\n",
976 cl_ntoh64(p_port->p_physp->port_guid));
981 for (i = 0; i < GUID_TABLE_MAX_ENTRIES; i++) {
982 if (!gir->guid_info.guid[i])
984 /* skip block 0 index 0 */
985 if (gir->block_num == 0 && i == 0)
987 if (gir->block_num * GUID_TABLE_MAX_ENTRIES + i >
988 p_port->p_physp->port_info.guid_cap)
991 p_alias_guid = osm_alias_guid_new(gir->guid_info.guid[i],
994 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
995 "Alias guid %d memory allocation failed"
996 " for port GUID 0x%" PRIx64 "\n",
997 gir->block_num * GUID_TABLE_MAX_ENTRIES + i,
998 cl_ntoh64(p_port->p_physp->port_guid));
1002 p_alias_guid_check =
1003 (osm_alias_guid_t *) cl_qmap_insert(&p_osm->subn.alias_port_guid_tbl,
1004 p_alias_guid->alias_guid,
1005 &p_alias_guid->map_item);
1006 if (p_alias_guid_check != p_alias_guid) {
1007 /* alias GUID is a duplicate */
1008 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
1009 "Duplicate alias port GUID 0x%" PRIx64
1010 " index %d base port GUID 0x%" PRIx64 "\n",
1011 cl_ntoh64(p_alias_guid->alias_guid),
1012 gir->block_num * GUID_TABLE_MAX_ENTRIES + i,
1013 cl_ntoh64(p_alias_guid->p_base_port->guid));
1014 osm_alias_guid_delete(&p_alias_guid);
1019 memcpy(&(*p_port->p_physp->p_guids)[gir->block_num * GUID_TABLE_MAX_ENTRIES],
1020 &gir->guid_info, sizeof(ib_guid_info_t));
1022 osm_queue_guidinfo(&p_osm->sa, p_port, gir->block_num);
1025 cl_plock_release(&p_osm->lock);
1030 #define UNPACK_FUNC(name,x) \
1031 static int unpack_##name##x(char *p, uint##x##_t *val_ptr) \
1034 unsigned long long num; \
1035 num = strtoull(p, &q, 16); \
1036 if (num > ~((uint##x##_t)0x0) \
1037 || q == p || (!isspace(*q) && *q != ':')) { \
1041 *val_ptr = cl_hton##x((uint##x##_t)num); \
1042 return (int)(q - p); \
1045 #define cl_hton8(x) (x)
1047 UNPACK_FUNC(net, 8);
1048 UNPACK_FUNC(net, 16);
1049 UNPACK_FUNC(net, 32);
1050 UNPACK_FUNC(net, 64);
1052 static int unpack_string(char *p, uint8_t * buf, unsigned len)
1057 if (*q == '\'' || *q == '\"')
1059 while (--len && *q && *q != delim)
1062 if (*q == delim && delim != ' ')
1064 return (int)(q - p);
1067 static int unpack_string64(char *p, uint8_t * buf)
1069 return unpack_string(p, buf, 64);
1072 #define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \
1073 p = strstr(p, name); \
1075 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
1076 "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \
1077 file_name, lineno, (name)); \
1081 p += strlen(name); \
1082 _ret = unpack_##x(p, (val_ptr)); \
1084 OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
1085 "PARSE ERROR: %s:%u: cannot parse "#x" value " \
1086 "after \"%s\"\n", file_name, lineno, (name)); \
1093 static void sa_db_file_load_handle_mgrp(osm_opensm_t * p_osm,
1094 osm_mgrp_t * p_mgrp)
1096 /* decide whether to delete the mgrp object or not */
1097 if (p_mgrp->full_members == 0 && !p_mgrp->well_known) {
1098 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
1099 "Closing MC group 0x%016" PRIx64 ":0x%016" PRIx64
1100 " - no full members were added to not well known "
1102 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
1103 cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id));
1104 osm_mgrp_cleanup(&p_osm->subn, p_mgrp);
1108 int osm_sa_db_file_load(osm_opensm_t * p_osm)
1114 osm_mgrp_t *p_next_mgrp = NULL;
1115 osm_mgrp_t *p_prev_mgrp = NULL;
1116 unsigned rereg_clients = 0;
1119 if (!p_osm->subn.first_time_master_sweep) {
1120 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
1121 "Not first sweep - skip SA DB restore\n");
1125 file_name = p_osm->subn.opt.sa_db_file;
1127 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
1128 "sa db file name is not specified. Skip restore\n");
1132 file = fopen(file_name, "r");
1134 OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: "
1135 "Can't open sa db file \'%s\'. Skip restoring\n",
1140 OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
1141 "Restoring SA DB from file \'%s\'\n",
1146 while (fgets(line, sizeof(line) - 1, file) != NULL) {
1159 if (!strncmp(p, "MC Group", 8)) {
1160 ib_member_rec_t mcm_rec;
1164 memset(&mcm_rec, 0, sizeof(mcm_rec));
1166 PARSE_AHEAD(p, net16, " 0x", &mlid);
1167 PARSE_AHEAD(p, net64, " mgid=0x",
1168 &mcm_rec.mgid.unicast.prefix);
1169 PARSE_AHEAD(p, net64, ":0x",
1170 &mcm_rec.mgid.unicast.interface_id);
1171 PARSE_AHEAD(p, net64, " port_gid=0x",
1172 &mcm_rec.port_gid.unicast.prefix);
1173 PARSE_AHEAD(p, net64, ":0x",
1174 &mcm_rec.port_gid.unicast.interface_id);
1175 PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey);
1176 PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid);
1177 PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu);
1178 PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass);
1179 PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey);
1180 PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate);
1181 PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life);
1182 PARSE_AHEAD(p, net32, " sl_flow_hop=0x",
1183 &mcm_rec.sl_flow_hop);
1184 PARSE_AHEAD(p, net8, " scope_state=0x",
1185 &mcm_rec.scope_state);
1186 PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
1187 mcm_rec.proxy_join = val;
1189 p_next_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec);
1192 if (cl_ntoh16(mlid) > p_osm->sm.mlids_init_max)
1193 p_osm->sm.mlids_init_max = cl_ntoh16(mlid);
1194 } else if (p_next_mgrp && !strncmp(p, "mcm_port", 8)) {
1195 ib_member_rec_t mcmr;
1200 PARSE_AHEAD(p, net64, " port_gid=0x",
1201 &mcmr.port_gid.unicast.prefix);
1202 PARSE_AHEAD(p, net64, ":0x",
1203 &mcmr.port_gid.unicast.interface_id);
1204 PARSE_AHEAD(p, net8, " scope_state=0x", &mcmr.scope_state);
1205 PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
1208 guid = mcmr.port_gid.unicast.interface_id;
1209 port = osm_get_port_by_alias_guid(&p_osm->subn, guid);
1211 cl_qmap_get(&p_next_mgrp->mcm_port_tbl, guid) ==
1212 cl_qmap_end(&p_next_mgrp->mcm_port_tbl) &&
1213 !osm_mgrp_add_port(&p_osm->subn, &p_osm->log,
1214 p_next_mgrp, port, &mcmr, proxy))
1216 } else if (!strncmp(p, "Service Record:", 15)) {
1217 ib_service_record_t s_rec;
1218 uint32_t modified_time, lease_period;
1221 memset(&s_rec, 0, sizeof(s_rec));
1223 PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id);
1224 PARSE_AHEAD(p, net64, " gid=0x",
1225 &s_rec.service_gid.unicast.prefix);
1226 PARSE_AHEAD(p, net64, ":0x",
1227 &s_rec.service_gid.unicast.interface_id);
1228 PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey);
1229 PARSE_AHEAD(p, net32, " lease=0x",
1230 &s_rec.service_lease);
1231 PARSE_AHEAD(p, net64, " key=0x",
1232 (ib_net64_t *) (&s_rec.service_key[0]));
1233 PARSE_AHEAD(p, net64, ":0x",
1234 (ib_net64_t *) (&s_rec.service_key[8]));
1235 PARSE_AHEAD(p, string64, " name=", s_rec.service_name);
1236 PARSE_AHEAD(p, net64, " data8=0x",
1237 (ib_net64_t *) (&s_rec.service_data8[0]));
1238 PARSE_AHEAD(p, net64, ":0x",
1239 (ib_net64_t *) (&s_rec.service_data8[8]));
1240 PARSE_AHEAD(p, net64, " data16=0x",
1241 (ib_net64_t *) (&s_rec.service_data16[0]));
1242 PARSE_AHEAD(p, net64, ":0x",
1243 (ib_net64_t *) (&s_rec.service_data16[4]));
1244 PARSE_AHEAD(p, net64, " data32=0x",
1245 (ib_net64_t *) (&s_rec.service_data32[0]));
1246 PARSE_AHEAD(p, net64, ":0x",
1247 (ib_net64_t *) (&s_rec.service_data32[2]));
1248 PARSE_AHEAD(p, net64, " data64=0x",
1249 &s_rec.service_data64[0]);
1250 PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]);
1251 PARSE_AHEAD(p, net32, " modified_time=0x",
1253 PARSE_AHEAD(p, net32, " lease_period=0x",
1256 if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time),
1257 cl_ntoh32(lease_period)))
1259 } else if (!strncmp(p, "InformInfo Record:", 18)) {
1260 ib_inform_info_record_t i_rec;
1261 osm_mad_addr_t rep_addr;
1265 memset(&i_rec, 0, sizeof(i_rec));
1266 memset(&rep_addr, 0, sizeof(rep_addr));
1268 PARSE_AHEAD(p, net64, " subscriber_gid=0x",
1269 &i_rec.subscriber_gid.unicast.prefix);
1270 PARSE_AHEAD(p, net64, ":0x",
1271 &i_rec.subscriber_gid.unicast.interface_id);
1272 PARSE_AHEAD(p, net16, " subscriber_enum=0x",
1273 &i_rec.subscriber_enum);
1274 PARSE_AHEAD(p, net64, " gid=0x",
1275 &i_rec.inform_info.gid.unicast.prefix);
1276 PARSE_AHEAD(p, net64, ":0x",
1277 &i_rec.inform_info.gid.unicast.
1279 PARSE_AHEAD(p, net16, " lid_range_begin=0x",
1280 &i_rec.inform_info.lid_range_begin);
1281 PARSE_AHEAD(p, net16, " lid_range_end=0x",
1282 &i_rec.inform_info.lid_range_end);
1283 PARSE_AHEAD(p, net8, " is_generic=0x",
1284 &i_rec.inform_info.is_generic);
1285 PARSE_AHEAD(p, net8, " subscribe=0x",
1286 &i_rec.inform_info.subscribe);
1287 PARSE_AHEAD(p, net16, " trap_type=0x",
1288 &i_rec.inform_info.trap_type);
1289 PARSE_AHEAD(p, net16, " trap_num=0x",
1290 &i_rec.inform_info.g_or_v.generic.trap_num);
1291 PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x",
1292 &i_rec.inform_info.g_or_v.generic.
1294 PARSE_AHEAD(p, net32, " node_type=0x",
1295 (uint32_t *) & i_rec.inform_info.g_or_v.
1298 PARSE_AHEAD(p, net16, " rep_addr: lid=0x",
1299 &rep_addr.dest_lid);
1300 PARSE_AHEAD(p, net8, " path_bits=0x",
1301 &rep_addr.path_bits);
1302 PARSE_AHEAD(p, net8, " static_rate=0x",
1303 &rep_addr.static_rate);
1304 PARSE_AHEAD(p, net32, " remote_qp=0x",
1305 &rep_addr.addr_type.gsi.remote_qp);
1306 PARSE_AHEAD(p, net32, " remote_qkey=0x",
1307 &rep_addr.addr_type.gsi.remote_qkey);
1308 PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16);
1309 rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16);
1310 PARSE_AHEAD(p, net8, " sl=0x",
1311 &rep_addr.addr_type.gsi.service_level);
1313 if (load_infr(p_osm, &i_rec, &rep_addr))
1315 } else if (!strncmp(p, "GUIDInfo Record:", 16)) {
1316 ib_guidinfo_record_t gi_rec;
1317 ib_net64_t base_guid;
1320 memset(&gi_rec, 0, sizeof(gi_rec));
1322 PARSE_AHEAD(p, net64, " base_guid=0x", &base_guid);
1323 PARSE_AHEAD(p, net16, " lid=0x", &gi_rec.lid);
1324 PARSE_AHEAD(p, net8, " block_num=0x",
1326 PARSE_AHEAD(p, net64, " guid0=0x",
1327 &gi_rec.guid_info.guid[0]);
1328 PARSE_AHEAD(p, net64, " guid1=0x",
1329 &gi_rec.guid_info.guid[1]);
1330 PARSE_AHEAD(p, net64, " guid2=0x",
1331 &gi_rec.guid_info.guid[2]);
1332 PARSE_AHEAD(p, net64, " guid3=0x",
1333 &gi_rec.guid_info.guid[3]);
1334 PARSE_AHEAD(p, net64, " guid4=0x",
1335 &gi_rec.guid_info.guid[4]);
1336 PARSE_AHEAD(p, net64, " guid5=0x",
1337 &gi_rec.guid_info.guid[5]);
1338 PARSE_AHEAD(p, net64, " guid6=0x",
1339 &gi_rec.guid_info.guid[6]);
1340 PARSE_AHEAD(p, net64, " guid7=0x",
1341 &gi_rec.guid_info.guid[7]);
1343 if (load_guidinfo(p_osm, base_guid, &gi_rec))
1348 * p_next_mgrp points to the multicast group now being parsed.
1349 * p_prev_mgrp points to the last multicast group we parsed.
1350 * We decide whether to keep or delete each multicast group
1351 * only when we finish parsing it's member records. if the
1352 * group has full members, or it is a "well known group" we
1355 if (p_prev_mgrp != p_next_mgrp) {
1357 sa_db_file_load_handle_mgrp(p_osm, p_prev_mgrp);
1358 p_prev_mgrp = p_next_mgrp;
1363 sa_db_file_load_handle_mgrp(p_osm, p_prev_mgrp);
1366 * If loading succeeded, do whatever 'no_clients_rereg' says.
1367 * If loading failed at some point, turn off the 'no_clients_rereg'
1368 * option (turn on re-registration requests).
1371 p_osm->subn.opt.no_clients_rereg = FALSE;
1373 /* We've just finished loading SA DB file - clear the "dirty" flag */
1374 p_osm->sa.dirty = FALSE;