xref: /trueos/contrib/ofed/management/opensm/opensm/osm_sa.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
2  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 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  *
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:
12  *
13  *     Redistribution and use in source and binary forms, with or
14  *     without modification, are permitted provided that the following
15  *     conditions are met:
16  *
17  *      - Redistributions of source code must retain the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer.
20  *
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.
25  *
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
33  * SOFTWARE.
34  *
35  */
36 
37 /*
38  * Abstract:
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.
42  */
43 
44 #if HAVE_CONFIG_H
45 #  include <config.h>
46 #endif				/* HAVE_CONFIG_H */
47 
48 #include <string.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <complib/cl_qmap.h>
55 #include <complib/cl_passivelock.h>
56 #include <complib/cl_debug.h>
57 #include <iba/ib_types.h>
58 #include <opensm/osm_sa.h>
59 #include <opensm/osm_madw.h>
60 #include <opensm/osm_log.h>
61 #include <opensm/osm_subnet.h>
62 #include <opensm/osm_mad_pool.h>
63 #include <opensm/osm_msgdef.h>
64 #include <opensm/osm_opensm.h>
65 #include <opensm/osm_multicast.h>
66 #include <opensm/osm_inform.h>
67 #include <opensm/osm_service.h>
68 #include <opensm/osm_helper.h>
69 #include <vendor/osm_vendor_api.h>
70 
71 #define  OSM_SA_INITIAL_TID_VALUE 0xabc
72 
73 extern void osm_cpi_rcv_process(IN void *context, IN void *data);
74 extern void osm_gir_rcv_process(IN void *context, IN void *data);
75 extern void osm_infr_rcv_process(IN void *context, IN void *data);
76 extern void osm_infir_rcv_process(IN void *context, IN void *data);
77 extern void osm_lftr_rcv_process(IN void *context, IN void *data);
78 extern void osm_lr_rcv_process(IN void *context, IN void *data);
79 extern void osm_mcmr_rcv_process(IN void *context, IN void *data);
80 extern void osm_mftr_rcv_process(IN void *context, IN void *data);
81 extern void osm_mpr_rcv_process(IN void *context, IN void *data);
82 extern void osm_nr_rcv_process(IN void *context, IN void *data);
83 extern void osm_pr_rcv_process(IN void *context, IN void *data);
84 extern void osm_pkey_rec_rcv_process(IN void *context, IN void *data);
85 extern void osm_pir_rcv_process(IN void *context, IN void *data);
86 extern void osm_sr_rcv_process(IN void *context, IN void *data);
87 extern void osm_slvl_rec_rcv_process(IN void *context, IN void *data);
88 extern void osm_smir_rcv_process(IN void *context, IN void *data);
89 extern void osm_sir_rcv_process(IN void *context, IN void *data);
90 extern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data);
91 extern void osm_sr_rcv_lease_cb(IN void *context);
92 
93 /**********************************************************************
94  **********************************************************************/
osm_sa_construct(IN osm_sa_t * const p_sa)95 void osm_sa_construct(IN osm_sa_t * const p_sa)
96 {
97 	memset(p_sa, 0, sizeof(*p_sa));
98 	p_sa->state = OSM_SA_STATE_INIT;
99 	p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE;
100 
101 	cl_timer_construct(&p_sa->sr_timer);
102 }
103 
104 /**********************************************************************
105  **********************************************************************/
osm_sa_shutdown(IN osm_sa_t * const p_sa)106 void osm_sa_shutdown(IN osm_sa_t * const p_sa)
107 {
108 	ib_api_status_t status;
109 	OSM_LOG_ENTER(p_sa->p_log);
110 
111 	cl_timer_stop(&p_sa->sr_timer);
112 
113 	/* unbind from the mad service */
114 	status = osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl);
115 
116 	/* remove any registered dispatcher message */
117 	cl_disp_unregister(p_sa->nr_disp_h);
118 	cl_disp_unregister(p_sa->pir_disp_h);
119 	cl_disp_unregister(p_sa->gir_disp_h);
120 	cl_disp_unregister(p_sa->lr_disp_h);
121 	cl_disp_unregister(p_sa->pr_disp_h);
122 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
123 	cl_disp_unregister(p_sa->mpr_disp_h);
124 #endif
125 	cl_disp_unregister(p_sa->smir_disp_h);
126 	cl_disp_unregister(p_sa->mcmr_disp_h);
127 	cl_disp_unregister(p_sa->sr_disp_h);
128 	cl_disp_unregister(p_sa->infr_disp_h);
129 	cl_disp_unregister(p_sa->infir_disp_h);
130 	cl_disp_unregister(p_sa->vlarb_disp_h);
131 	cl_disp_unregister(p_sa->slvl_disp_h);
132 	cl_disp_unregister(p_sa->pkey_disp_h);
133 	cl_disp_unregister(p_sa->lft_disp_h);
134 	cl_disp_unregister(p_sa->sir_disp_h);
135 	cl_disp_unregister(p_sa->mft_disp_h);
136 	osm_sa_mad_ctrl_destroy(&p_sa->mad_ctrl);
137 
138 	OSM_LOG_EXIT(p_sa->p_log);
139 }
140 
141 /**********************************************************************
142  **********************************************************************/
osm_sa_destroy(IN osm_sa_t * const p_sa)143 void osm_sa_destroy(IN osm_sa_t * const p_sa)
144 {
145 	OSM_LOG_ENTER(p_sa->p_log);
146 
147 	p_sa->state = OSM_SA_STATE_INIT;
148 
149 	cl_timer_destroy(&p_sa->sr_timer);
150 
151 	OSM_LOG_EXIT(p_sa->p_log);
152 }
153 
154 /**********************************************************************
155  **********************************************************************/
156 ib_api_status_t
osm_sa_init(IN osm_sm_t * const p_sm,IN osm_sa_t * const p_sa,IN osm_subn_t * const p_subn,IN osm_vendor_t * const p_vendor,IN osm_mad_pool_t * const p_mad_pool,IN osm_log_t * const p_log,IN osm_stats_t * const p_stats,IN cl_dispatcher_t * const p_disp,IN cl_plock_t * const p_lock)157 osm_sa_init(IN osm_sm_t * const p_sm,
158 	    IN osm_sa_t * const p_sa,
159 	    IN osm_subn_t * const p_subn,
160 	    IN osm_vendor_t * const p_vendor,
161 	    IN osm_mad_pool_t * const p_mad_pool,
162 	    IN osm_log_t * const p_log,
163 	    IN osm_stats_t * const p_stats,
164 	    IN cl_dispatcher_t * const p_disp, IN cl_plock_t * const p_lock)
165 {
166 	ib_api_status_t status = IB_SUCCESS;
167 
168 	OSM_LOG_ENTER(p_log);
169 
170 	p_sa->sm = p_sm;
171 	p_sa->p_subn = p_subn;
172 	p_sa->p_vendor = p_vendor;
173 	p_sa->p_mad_pool = p_mad_pool;
174 	p_sa->p_log = p_log;
175 	p_sa->p_disp = p_disp;
176 	p_sa->p_lock = p_lock;
177 
178 	p_sa->state = OSM_SA_STATE_READY;
179 
180 	status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl,
181 				      p_sa,
182 				      p_sa->p_mad_pool,
183 				      p_sa->p_vendor,
184 				      p_subn, p_log, p_stats, p_disp);
185 	if (status != IB_SUCCESS)
186 		goto Exit;
187 
188 	status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa);
189 	if (status != IB_SUCCESS)
190 		goto Exit;
191 
192 	p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO,
193 					    osm_cpi_rcv_process, p_sa);
194 	if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE)
195 		goto Exit;
196 
197 	p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD,
198 					   osm_nr_rcv_process, p_sa);
199 	if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE)
200 		goto Exit;
201 
202 	p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD,
203 					    osm_pir_rcv_process, p_sa);
204 	if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE)
205 		goto Exit;
206 
207 	p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD,
208 					    osm_gir_rcv_process, p_sa);
209 	if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE)
210 		goto Exit;
211 
212 	p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD,
213 					   osm_lr_rcv_process, p_sa);
214 	if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE)
215 		goto Exit;
216 
217 	p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD,
218 					   osm_pr_rcv_process, p_sa);
219 	if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE)
220 		goto Exit;
221 
222 #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
223 	p_sa->mpr_disp_h =
224 	    cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD,
225 			     osm_mpr_rcv_process, p_sa);
226 	if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE)
227 		goto Exit;
228 #endif
229 
230 	p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD,
231 					     osm_smir_rcv_process, p_sa);
232 	if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE)
233 		goto Exit;
234 
235 	p_sa->mcmr_disp_h =
236 	    cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD,
237 			     osm_mcmr_rcv_process, p_sa);
238 	if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE)
239 		goto Exit;
240 
241 	p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD,
242 					   osm_sr_rcv_process, p_sa);
243 	if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE)
244 		goto Exit;
245 
246 	p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO,
247 					     osm_infr_rcv_process, p_sa);
248 	if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE)
249 		goto Exit;
250 
251 	p_sa->infir_disp_h =
252 	    cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD,
253 			     osm_infir_rcv_process, p_sa);
254 	if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE)
255 		goto Exit;
256 
257 	p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD,
258 					      osm_vlarb_rec_rcv_process, p_sa);
259 	if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE)
260 		goto Exit;
261 
262 	p_sa->slvl_disp_h =
263 	    cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD,
264 			     osm_slvl_rec_rcv_process, p_sa);
265 	if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE)
266 		goto Exit;
267 
268 	p_sa->pkey_disp_h =
269 	    cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD,
270 			     osm_pkey_rec_rcv_process, p_sa);
271 	if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE)
272 		goto Exit;
273 
274 	p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD,
275 					    osm_lftr_rcv_process, p_sa);
276 	if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE)
277 		goto Exit;
278 
279 	p_sa->sir_disp_h =
280 	    cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD,
281 			     osm_sir_rcv_process, p_sa);
282 	if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE)
283 		goto Exit;
284 
285 	p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD,
286 					    osm_mftr_rcv_process, p_sa);
287 	if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE)
288 		goto Exit;
289 
290 Exit:
291 	OSM_LOG_EXIT(p_log);
292 	return (status);
293 }
294 
295 /**********************************************************************
296  **********************************************************************/
297 ib_api_status_t
osm_sa_bind(IN osm_sa_t * const p_sa,IN const ib_net64_t port_guid)298 osm_sa_bind(IN osm_sa_t * const p_sa, IN const ib_net64_t port_guid)
299 {
300 	ib_api_status_t status;
301 
302 	OSM_LOG_ENTER(p_sa->p_log);
303 
304 	status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid);
305 
306 	if (status != IB_SUCCESS) {
307 		OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: "
308 			"SA MAD Controller bind failed (%s)\n",
309 			ib_get_err_str(status));
310 		goto Exit;
311 	}
312 
313 Exit:
314 	OSM_LOG_EXIT(p_sa->p_log);
315 	return (status);
316 }
317 
osm_sa_send(osm_sa_t * sa,IN osm_madw_t * const p_madw,IN boolean_t const resp_expected)318 ib_api_status_t osm_sa_send(osm_sa_t *sa,
319 			    IN osm_madw_t * const p_madw,
320 			    IN boolean_t const resp_expected)
321 {
322 	ib_api_status_t status;
323 
324 	cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent);
325 	status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected);
326 	if (status != IB_SUCCESS) {
327 		cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent);
328 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: "
329 			"osm_vendor_send failed, status = %s\n",
330 			ib_get_err_str(status));
331 	}
332 	return status;
333 }
334 
335 void
osm_sa_send_error(IN osm_sa_t * sa,IN const osm_madw_t * const p_madw,IN const ib_net16_t sa_status)336 osm_sa_send_error(IN osm_sa_t * sa,
337 		  IN const osm_madw_t * const p_madw,
338 		  IN const ib_net16_t sa_status)
339 {
340 	osm_madw_t *p_resp_madw;
341 	ib_sa_mad_t *p_resp_sa_mad;
342 	ib_sa_mad_t *p_sa_mad;
343 
344 	OSM_LOG_ENTER(sa->p_log);
345 
346 	/* avoid races - if we are exiting - exit */
347 	if (osm_exit_flag) {
348 		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
349 			"Ignoring requested send after exit\n");
350 		goto Exit;
351 	}
352 
353 	p_resp_madw = osm_mad_pool_get(sa->p_mad_pool,
354 				       p_madw->h_bind, MAD_BLOCK_SIZE,
355 				       &p_madw->mad_addr);
356 
357 	if (p_resp_madw == NULL) {
358 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: "
359 			"Unable to acquire response MAD\n");
360 		goto Exit;
361 	}
362 
363 	p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
364 	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
365 
366 	/*  Copy the MAD header back into the response mad */
367 	*p_resp_sa_mad = *p_sa_mad;
368 	p_resp_sa_mad->status = sa_status;
369 
370 	if (p_resp_sa_mad->method == IB_MAD_METHOD_SET)
371 		p_resp_sa_mad->method = IB_MAD_METHOD_GET;
372 	else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE)
373 		p_resp_sa_mad->attr_offset = 0;
374 
375 	p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
376 
377 	/*
378 	 * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
379 	 */
380 	p_resp_sa_mad->sm_key = 0;
381 
382 	/*
383 	 * o15-0.2.7 - The PathRecord Attribute ID shall be used in
384 	 * the response (to a SubnAdmGetMulti(MultiPathRecord)
385 	 */
386 	if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD)
387 		p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
388 
389 	if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES))
390 		osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES);
391 
392 	osm_sa_send(sa, p_resp_madw, FALSE);
393 
394 Exit:
395 	OSM_LOG_EXIT(sa->p_log);
396 }
397 
osm_sa_respond(osm_sa_t * sa,osm_madw_t * madw,size_t attr_size,cl_qlist_t * list)398 void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
399 		    cl_qlist_t *list)
400 {
401 	struct item_data {
402 		cl_list_item_t list;
403 		char data[0];
404 	};
405 	cl_list_item_t *item;
406 	osm_madw_t *resp_madw;
407 	ib_sa_mad_t *sa_mad, *resp_sa_mad;
408 	unsigned num_rec, i;
409 #ifndef VENDOR_RMPP_SUPPORT
410 	unsigned trim_num_rec;
411 #endif
412 	void *p;
413 
414 	sa_mad = osm_madw_get_sa_mad_ptr(madw);
415 	num_rec = cl_qlist_count(list);
416 
417 	/*
418 	 * C15-0.1.30:
419 	 * If we do a SubnAdmGet and got more than one record it is an error!
420 	 */
421 	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
422 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
423 			"Got more than one record for SubnAdmGet (%u)\n",
424 			num_rec);
425 		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
426 		goto Exit;
427 	}
428 
429 #ifndef VENDOR_RMPP_SUPPORT
430 	trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
431 	if (trim_num_rec < num_rec) {
432 		OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
433 			"Number of records:%u trimmed to:%u to fit in one MAD\n",
434 			num_rec, trim_num_rec);
435 		num_rec = trim_num_rec;
436 	}
437 #endif
438 
439 	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec);
440 
441 	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) {
442 		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS);
443 		goto Exit;
444 	}
445 
446 	/*
447 	 * Get a MAD to reply. Address of Mad is in the received mad_wrapper
448 	 */
449 	resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind,
450 				     num_rec * attr_size + IB_SA_MAD_HDR_SIZE,
451 				     &madw->mad_addr);
452 	if (!resp_madw) {
453 		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: "
454 			"osm_mad_pool_get failed\n");
455 		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES);
456 		goto Exit;
457 	}
458 
459 	resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw);
460 
461 	/*
462 	   Copy the MAD header back into the response mad.
463 	   Set the 'R' bit and the payload length,
464 	   Then copy all records from the list into the response payload.
465 	 */
466 
467 	memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE);
468 	if (resp_sa_mad->method == IB_MAD_METHOD_SET)
469 		resp_sa_mad->method = IB_MAD_METHOD_GET;
470 	resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
471 	/* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
472 	resp_sa_mad->sm_key = 0;
473 
474 	/* Fill in the offset (paylen will be done by the rmpp SAR) */
475 	resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0;
476 
477 	p = ib_sa_mad_get_payload_ptr(resp_sa_mad);
478 
479 #ifndef VENDOR_RMPP_SUPPORT
480 	/* we support only one packet RMPP - so we will set the first and
481 	   last flags for gettable */
482 	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) {
483 		resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
484 		resp_sa_mad->rmpp_flags =
485 		    IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST |
486 		    IB_RMPP_FLAG_ACTIVE;
487 	}
488 #else
489 	/* forcefully define the packet as RMPP one */
490 	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
491 		resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
492 #endif
493 
494 	for (i = 0; i < num_rec; i++) {
495 		item = cl_qlist_remove_head(list);
496 		memcpy(p, ((struct item_data *)item)->data, attr_size);
497 		p += attr_size;
498 		free(item);
499 	}
500 
501 	osm_sa_send(sa, resp_madw, FALSE);
502 
503 	osm_dump_sa_mad(sa->p_log, resp_sa_mad, OSM_LOG_FRAMES);
504 Exit:
505 	/* need to set the mem free ... */
506 	item = cl_qlist_remove_head(list);
507 	while (item != cl_qlist_end(list)) {
508 		free(item);
509 		item = cl_qlist_remove_head(list);
510 	}
511 }
512 
513 /**********************************************************************
514  **********************************************************************/
515 /*
516  *  SA DB Dumper
517  *
518  */
519 
520 struct opensm_dump_context {
521 	osm_opensm_t *p_osm;
522 	FILE *file;
523 };
524 
525 static int
opensm_dump_to_file(osm_opensm_t * p_osm,const char * file_name,void (* dump_func)(osm_opensm_t * p_osm,FILE * file))526 opensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name,
527 		    void (*dump_func) (osm_opensm_t * p_osm, FILE * file))
528 {
529 	char path[1024];
530 	FILE *file;
531 
532 	snprintf(path, sizeof(path), "%s/%s",
533 		 p_osm->subn.opt.dump_files_dir, file_name);
534 
535 	file = fopen(path, "w");
536 	if (!file) {
537 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C01: "
538 			"cannot open file \'%s\': %s\n",
539 			file_name, strerror(errno));
540 		return -1;
541 	}
542 
543 	chmod(path, S_IRUSR | S_IWUSR);
544 
545 	dump_func(p_osm, file);
546 
547 	fclose(file);
548 	return 0;
549 }
550 
mcast_mgr_dump_one_port(cl_map_item_t * p_map_item,void * cxt)551 static void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt)
552 {
553 	FILE *file = ((struct opensm_dump_context *)cxt)->file;
554 	osm_mcm_port_t *p_mcm_port = (osm_mcm_port_t *) p_map_item;
555 
556 	fprintf(file, "mcm_port: "
557 		"port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " "
558 		"scope_state=0x%02x proxy_join=0x%x" "\n\n",
559 		cl_ntoh64(p_mcm_port->port_gid.unicast.prefix),
560 		cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id),
561 		p_mcm_port->scope_state, p_mcm_port->proxy_join);
562 }
563 
sa_dump_one_mgrp(osm_mgrp_t * p_mgrp,void * cxt)564 static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt)
565 {
566 	struct opensm_dump_context dump_context;
567 	osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
568 	FILE *file = ((struct opensm_dump_context *)cxt)->file;
569 
570 	fprintf(file, "MC Group 0x%04x %s:"
571 		" mgid=0x%016" PRIx64 ":0x%016" PRIx64
572 		" port_gid=0x%016" PRIx64 ":0x%016" PRIx64
573 		" qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
574 		" pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
575 		" scope_state=0x%02x proxy_join=0x%x" "\n\n",
576 		cl_ntoh16(p_mgrp->mlid),
577 		p_mgrp->well_known ? " (well known)" : "",
578 		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
579 		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
580 		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
581 		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
582 		cl_ntoh32(p_mgrp->mcmember_rec.qkey),
583 		cl_ntoh16(p_mgrp->mcmember_rec.mlid),
584 		p_mgrp->mcmember_rec.mtu,
585 		p_mgrp->mcmember_rec.tclass,
586 		cl_ntoh16(p_mgrp->mcmember_rec.pkey),
587 		p_mgrp->mcmember_rec.rate,
588 		p_mgrp->mcmember_rec.pkt_life,
589 		cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
590 		p_mgrp->mcmember_rec.scope_state,
591 		p_mgrp->mcmember_rec.proxy_join);
592 
593 	dump_context.p_osm = p_osm;
594 	dump_context.file = file;
595 
596 	cl_qmap_apply_func(&p_mgrp->mcm_port_tbl,
597 			   mcast_mgr_dump_one_port, &dump_context);
598 }
599 
sa_dump_one_inform(cl_list_item_t * p_list_item,void * cxt)600 static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt)
601 {
602 	FILE *file = ((struct opensm_dump_context *)cxt)->file;
603 	osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
604 	ib_inform_info_record_t *p_iir = &p_infr->inform_record;
605 
606 	fprintf(file, "InformInfo Record:"
607 		" subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
608 		" subscriber_enum=0x%x"
609 		" InformInfo:"
610 		" gid=0x%016" PRIx64 ":0x%016" PRIx64
611 		" lid_range_begin=0x%x"
612 		" lid_range_end=0x%x"
613 		" is_generic=0x%x"
614 		" subscribe=0x%x"
615 		" trap_type=0x%x"
616 		" trap_num=0x%x"
617 		" qpn_resp_time_val=0x%x"
618 		" node_type=0x%06x"
619 		" rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
620 		" remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x"
621 		"\n\n",
622 		cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
623 		cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
624 		cl_ntoh16(p_iir->subscriber_enum),
625 		cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
626 		cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
627 		cl_ntoh16(p_iir->inform_info.lid_range_begin),
628 		cl_ntoh16(p_iir->inform_info.lid_range_end),
629 		p_iir->inform_info.is_generic,
630 		p_iir->inform_info.subscribe,
631 		cl_ntoh16(p_iir->inform_info.trap_type),
632 		cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
633 		cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
634 		cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)),
635 		cl_ntoh16(p_infr->report_addr.dest_lid),
636 		p_infr->report_addr.path_bits,
637 		p_infr->report_addr.static_rate,
638 		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
639 		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
640 		p_infr->report_addr.addr_type.gsi.pkey_ix,
641 		p_infr->report_addr.addr_type.gsi.service_level);
642 }
643 
sa_dump_one_service(cl_list_item_t * p_list_item,void * cxt)644 static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt)
645 {
646 	FILE *file = ((struct opensm_dump_context *)cxt)->file;
647 	osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item;
648 	ib_service_record_t *p_sr = &p_svcr->service_record;
649 
650 	fprintf(file, "Service Record: id=0x%016" PRIx64
651 		" gid=0x%016" PRIx64 ":0x%016" PRIx64
652 		" pkey=0x%x"
653 		" lease=0x%x"
654 		" key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
655 		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
656 		" name=\'%s\'"
657 		" data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
658 		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
659 		" data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
660 		" data32=0x%08x%08x:0x%08x%08x"
661 		" data64=0x%016" PRIx64 ":0x%016" PRIx64
662 		" modified_time=0x%x lease_period=0x%x\n\n",
663 		cl_ntoh64(p_sr->service_id),
664 		cl_ntoh64(p_sr->service_gid.unicast.prefix),
665 		cl_ntoh64(p_sr->service_gid.unicast.interface_id),
666 		cl_ntoh16(p_sr->service_pkey),
667 		cl_ntoh32(p_sr->service_lease),
668 		p_sr->service_key[0], p_sr->service_key[1],
669 		p_sr->service_key[2], p_sr->service_key[3],
670 		p_sr->service_key[4], p_sr->service_key[5],
671 		p_sr->service_key[6], p_sr->service_key[7],
672 		p_sr->service_key[8], p_sr->service_key[9],
673 		p_sr->service_key[10], p_sr->service_key[11],
674 		p_sr->service_key[12], p_sr->service_key[13],
675 		p_sr->service_key[14], p_sr->service_key[15],
676 		p_sr->service_name,
677 		p_sr->service_data8[0], p_sr->service_data8[1],
678 		p_sr->service_data8[2], p_sr->service_data8[3],
679 		p_sr->service_data8[4], p_sr->service_data8[5],
680 		p_sr->service_data8[6], p_sr->service_data8[7],
681 		p_sr->service_data8[8], p_sr->service_data8[9],
682 		p_sr->service_data8[10], p_sr->service_data8[11],
683 		p_sr->service_data8[12], p_sr->service_data8[13],
684 		p_sr->service_data8[14], p_sr->service_data8[15],
685 		cl_ntoh16(p_sr->service_data16[0]),
686 		cl_ntoh16(p_sr->service_data16[1]),
687 		cl_ntoh16(p_sr->service_data16[2]),
688 		cl_ntoh16(p_sr->service_data16[3]),
689 		cl_ntoh16(p_sr->service_data16[4]),
690 		cl_ntoh16(p_sr->service_data16[5]),
691 		cl_ntoh16(p_sr->service_data16[6]),
692 		cl_ntoh16(p_sr->service_data16[7]),
693 		cl_ntoh32(p_sr->service_data32[0]),
694 		cl_ntoh32(p_sr->service_data32[1]),
695 		cl_ntoh32(p_sr->service_data32[2]),
696 		cl_ntoh32(p_sr->service_data32[3]),
697 		cl_ntoh64(p_sr->service_data64[0]),
698 		cl_ntoh64(p_sr->service_data64[1]),
699 		p_svcr->modified_time, p_svcr->lease_period);
700 }
701 
sa_dump_all_sa(osm_opensm_t * p_osm,FILE * file)702 static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file)
703 {
704 	struct opensm_dump_context dump_context;
705 	osm_mgrp_t *p_mgrp;
706 	int i;
707 
708 	dump_context.p_osm = p_osm;
709 	dump_context.file = file;
710 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast:\n");
711 	cl_plock_acquire(&p_osm->lock);
712 	for (i = 0; i <= p_osm->subn.max_mcast_lid_ho - IB_LID_MCAST_START_HO;
713 	     i++) {
714 		p_mgrp = p_osm->subn.mgroups[i];
715 		if (p_mgrp)
716 			sa_dump_one_mgrp(p_mgrp, &dump_context);
717 	}
718 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform:\n");
719 	cl_qlist_apply_func(&p_osm->subn.sa_infr_list,
720 			    sa_dump_one_inform, &dump_context);
721 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services:\n");
722 	cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
723 			    sa_dump_one_service, &dump_context);
724 	cl_plock_release(&p_osm->lock);
725 }
726 
osm_sa_db_file_dump(osm_opensm_t * p_osm)727 int osm_sa_db_file_dump(osm_opensm_t * p_osm)
728 {
729 	return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa);
730 }
731 
732 /*
733  *  SA DB Loader
734  */
load_mcgroup(osm_opensm_t * p_osm,ib_net16_t mlid,ib_member_rec_t * p_mcm_rec,unsigned well_known)735 static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid,
736 				ib_member_rec_t * p_mcm_rec,
737 				unsigned well_known)
738 {
739 	ib_net64_t comp_mask;
740 	osm_mgrp_t *p_mgrp;
741 
742 	cl_plock_excl_acquire(&p_osm->lock);
743 
744 	p_mgrp = osm_get_mgrp_by_mlid(&p_osm->subn, mlid);
745 	if (p_mgrp) {
746 		if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
747 			    sizeof(ib_gid_t))) {
748 			OSM_LOG(&p_osm->log, OSM_LOG_DEBUG,
749 				"mgrp %04x is already here.", cl_ntoh16(mlid));
750 			goto _out;
751 		}
752 		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
753 			"mlid %04x is already used by another MC group. Will "
754 			"request clients reregistration.\n", cl_ntoh16(mlid));
755 		p_mgrp = NULL;
756 		goto _out;
757 	}
758 
759 	comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
760 	    | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL;
761 	if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa,
762 						 comp_mask, p_mcm_rec,
763 						 &p_mgrp) != IB_SUCCESS ||
764 	    !p_mgrp || p_mgrp->mlid != mlid) {
765 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
766 			"cannot create MC group with mlid 0x%04x and mgid "
767 			"0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid),
768 			cl_ntoh64(p_mcm_rec->mgid.unicast.prefix),
769 			cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id));
770 		p_mgrp = NULL;
771 	} else if (well_known)
772 		p_mgrp->well_known = TRUE;
773 
774 _out:
775 	cl_plock_release(&p_osm->lock);
776 
777 	return p_mgrp;
778 }
779 
load_svcr(osm_opensm_t * p_osm,ib_service_record_t * sr,uint32_t modified_time,uint32_t lease_period)780 static int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr,
781 		     uint32_t modified_time, uint32_t lease_period)
782 {
783 	osm_svcr_t *p_svcr;
784 	int ret = 0;
785 
786 	cl_plock_excl_acquire(&p_osm->lock);
787 
788 	if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) {
789 		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
790 			"ServiceRecord already exists\n");
791 		goto _out;
792 	}
793 
794 	if (!(p_svcr = osm_svcr_new(sr))) {
795 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
796 			"cannot allocate new service struct\n");
797 		ret = -1;
798 		goto _out;
799 	}
800 
801 	p_svcr->modified_time = modified_time;
802 	p_svcr->lease_period = lease_period;
803 
804 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n");
805 
806 	osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr);
807 
808 	if (lease_period != 0xffffffff)
809 		cl_timer_trim(&p_osm->sa.sr_timer, 1000);
810 
811 _out:
812 	cl_plock_release(&p_osm->lock);
813 
814 	return ret;
815 }
816 
load_infr(osm_opensm_t * p_osm,ib_inform_info_record_t * iir,osm_mad_addr_t * addr)817 static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir,
818 		     osm_mad_addr_t * addr)
819 {
820 	osm_infr_t infr, *p_infr;
821 	int ret = 0;
822 
823 	infr.h_bind = p_osm->sa.mad_ctrl.h_bind;
824 	infr.sa = &p_osm->sa;
825 	/* other possible way to restore mad_addr partially is
826 	   to extract qpn from InformInfo and to find lid by gid */
827 	infr.report_addr = *addr;
828 	infr.inform_record = *iir;
829 
830 	cl_plock_excl_acquire(&p_osm->lock);
831 	if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) {
832 		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
833 			"InformInfo Record already exists\n");
834 		goto _out;
835 	}
836 
837 	if (!(p_infr = osm_infr_new(&infr))) {
838 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
839 			"cannot allocate new infr struct\n");
840 		ret = -1;
841 		goto _out;
842 	}
843 
844 	OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n");
845 
846 	osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr);
847 
848 _out:
849 	cl_plock_release(&p_osm->lock);
850 
851 	return ret;
852 }
853 
854 #define UNPACK_FUNC(name,x) \
855 static int unpack_##name##x(char *p, uint##x##_t *val_ptr) \
856 { \
857 	char *q; \
858 	unsigned long long num; \
859 	num = strtoull(p, &q, 16); \
860 	if (num > ~((uint##x##_t)0x0) \
861 	    || q == p || (!isspace(*q) && *q != ':')) { \
862 		*val_ptr = 0; \
863 		return -1; \
864 	} \
865 	*val_ptr = cl_hton##x((uint##x##_t)num); \
866 	return (int)(q - p); \
867 }
868 
869 #define cl_hton8(x) (x)
870 
871 UNPACK_FUNC(net, 8);
872 UNPACK_FUNC(net, 16);
873 UNPACK_FUNC(net, 32);
874 UNPACK_FUNC(net, 64);
875 
unpack_string(char * p,uint8_t * buf,unsigned len)876 static int unpack_string(char *p, uint8_t * buf, unsigned len)
877 {
878 	char *q = p;
879 	char delim = ' ';
880 
881 	if (*q == '\'' || *q == '\"')
882 		delim = *q++;
883 	while (--len && *q && *q != delim)
884 		*buf++ = *q++;
885 	*buf = '\0';
886 	if (*q == delim && delim != ' ')
887 		q++;
888 	return (int)(q - p);
889 }
890 
unpack_string64(char * p,uint8_t * buf)891 static int unpack_string64(char *p, uint8_t * buf)
892 {
893 	return unpack_string(p, buf, 64);
894 }
895 
896 #define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \
897 	p = strstr(p, name); \
898 	if (!p) { \
899 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
900 			"PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \
901 			file_name, lineno, (name)); \
902 		ret = -2; \
903 		goto _error; \
904 	} \
905 	p += strlen(name); \
906 	_ret = unpack_##x(p, (val_ptr)); \
907 	if (_ret < 0) { \
908 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \
909 			"PARSE ERROR: %s:%u: cannot parse "#x" value " \
910 			"after \"%s\"\n", file_name, lineno, (name)); \
911 		ret = _ret; \
912 		goto _error; \
913 	} \
914 	p += _ret; \
915 }
916 
osm_sa_db_file_load(osm_opensm_t * p_osm)917 int osm_sa_db_file_load(osm_opensm_t * p_osm)
918 {
919 	char line[1024];
920 	char *file_name;
921 	FILE *file;
922 	int ret = 0;
923 	osm_mgrp_t *p_mgrp = NULL;
924 	unsigned rereg_clients = 0;
925 	unsigned lineno;
926 
927 	file_name = p_osm->subn.opt.sa_db_file;
928 	if (!file_name) {
929 		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
930 			"sa db file name is not specifed. Skip restore\n");
931 		return 0;
932 	}
933 
934 	file = fopen(file_name, "r");
935 	if (!file) {
936 		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: "
937 			"cannot open sa db file \'%s\'. Skip restoring\n",
938 			file_name);
939 		return -1;
940 	}
941 
942 	lineno = 0;
943 
944 	while (fgets(line, sizeof(line) - 1, file) != NULL) {
945 		char *p;
946 		uint8_t val;
947 
948 		lineno++;
949 
950 		p = line;
951 		while (isspace(*p))
952 			p++;
953 
954 		if (*p == '#')
955 			continue;
956 
957 		if (!strncmp(p, "MC Group", 8)) {
958 			ib_member_rec_t mcm_rec;
959 			ib_net16_t mlid;
960 			unsigned well_known = 0;
961 
962 			p_mgrp = NULL;
963 			memset(&mcm_rec, 0, sizeof(mcm_rec));
964 
965 			PARSE_AHEAD(p, net16, " 0x", &mlid);
966 			if (strstr(p, "well known"))
967 				well_known = 1;
968 			PARSE_AHEAD(p, net64, " mgid=0x",
969 				    &mcm_rec.mgid.unicast.prefix);
970 			PARSE_AHEAD(p, net64, ":0x",
971 				    &mcm_rec.mgid.unicast.interface_id);
972 			PARSE_AHEAD(p, net64, " port_gid=0x",
973 				    &mcm_rec.port_gid.unicast.prefix);
974 			PARSE_AHEAD(p, net64, ":0x",
975 				    &mcm_rec.port_gid.unicast.interface_id);
976 			PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey);
977 			PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid);
978 			PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu);
979 			PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass);
980 			PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey);
981 			PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate);
982 			PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life);
983 			PARSE_AHEAD(p, net32, " sl_flow_hop=0x",
984 				    &mcm_rec.sl_flow_hop);
985 			PARSE_AHEAD(p, net8, " scope_state=0x",
986 				    &mcm_rec.scope_state);
987 			PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
988 			mcm_rec.proxy_join = val;
989 
990 			p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec,
991 					      well_known);
992 			if (!p_mgrp)
993 				rereg_clients = 1;
994 		} else if (p_mgrp && !strncmp(p, "mcm_port", 8)) {
995 			ib_gid_t port_gid;
996 			ib_net64_t guid;
997 			uint8_t scope_state;
998 			boolean_t proxy_join;
999 
1000 			PARSE_AHEAD(p, net64, " port_gid=0x",
1001 				    &port_gid.unicast.prefix);
1002 			PARSE_AHEAD(p, net64, ":0x",
1003 				    &port_gid.unicast.interface_id);
1004 			PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state);
1005 			PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
1006 			proxy_join = val;
1007 
1008 			guid = port_gid.unicast.interface_id;
1009 			if (cl_qmap_get(&p_mgrp->mcm_port_tbl,
1010 					port_gid.unicast.interface_id) ==
1011 			    cl_qmap_end(&p_mgrp->mcm_port_tbl))
1012 				osm_mgrp_add_port(&p_osm->subn, &p_osm->log,
1013 						  p_mgrp, &port_gid,
1014 						  scope_state, proxy_join);
1015 		} else if (!strncmp(p, "Service Record:", 15)) {
1016 			ib_service_record_t s_rec;
1017 			uint32_t modified_time, lease_period;
1018 
1019 			p_mgrp = NULL;
1020 			memset(&s_rec, 0, sizeof(s_rec));
1021 
1022 			PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id);
1023 			PARSE_AHEAD(p, net64, " gid=0x",
1024 				    &s_rec.service_gid.unicast.prefix);
1025 			PARSE_AHEAD(p, net64, ":0x",
1026 				    &s_rec.service_gid.unicast.interface_id);
1027 			PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey);
1028 			PARSE_AHEAD(p, net32, " lease=0x",
1029 				    &s_rec.service_lease);
1030 			PARSE_AHEAD(p, net64, " key=0x",
1031 				    (ib_net64_t *) (&s_rec.service_key[0]));
1032 			PARSE_AHEAD(p, net64, ":0x",
1033 				    (ib_net64_t *) (&s_rec.service_key[8]));
1034 			PARSE_AHEAD(p, string64, " name=", s_rec.service_name);
1035 			PARSE_AHEAD(p, net64, " data8=0x",
1036 				    (ib_net64_t *) (&s_rec.service_data8[0]));
1037 			PARSE_AHEAD(p, net64, ":0x",
1038 				    (ib_net64_t *) (&s_rec.service_data8[8]));
1039 			PARSE_AHEAD(p, net64, " data16=0x",
1040 				    (ib_net64_t *) (&s_rec.service_data16[0]));
1041 			PARSE_AHEAD(p, net64, ":0x",
1042 				    (ib_net64_t *) (&s_rec.service_data16[4]));
1043 			PARSE_AHEAD(p, net64, " data32=0x",
1044 				    (ib_net64_t *) (&s_rec.service_data32[0]));
1045 			PARSE_AHEAD(p, net64, ":0x",
1046 				    (ib_net64_t *) (&s_rec.service_data32[2]));
1047 			PARSE_AHEAD(p, net64, " data64=0x",
1048 				    &s_rec.service_data64[0]);
1049 			PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]);
1050 			PARSE_AHEAD(p, net32, " modified_time=0x",
1051 				    &modified_time);
1052 			PARSE_AHEAD(p, net32, " lease_period=0x",
1053 				    &lease_period);
1054 
1055 			if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time),
1056 				      cl_ntoh32(lease_period)))
1057 				rereg_clients = 1;
1058 		} else if (!strncmp(p, "InformInfo Record:", 18)) {
1059 			ib_inform_info_record_t i_rec;
1060 			osm_mad_addr_t rep_addr;
1061 			ib_net16_t val16;
1062 
1063 			p_mgrp = NULL;
1064 			memset(&i_rec, 0, sizeof(i_rec));
1065 			memset(&rep_addr, 0, sizeof(rep_addr));
1066 
1067 			PARSE_AHEAD(p, net64, " subscriber_gid=0x",
1068 				    &i_rec.subscriber_gid.unicast.prefix);
1069 			PARSE_AHEAD(p, net64, ":0x",
1070 				    &i_rec.subscriber_gid.unicast.interface_id);
1071 			PARSE_AHEAD(p, net16, " subscriber_enum=0x",
1072 				    &i_rec.subscriber_enum);
1073 			PARSE_AHEAD(p, net64, " gid=0x",
1074 				    &i_rec.inform_info.gid.unicast.prefix);
1075 			PARSE_AHEAD(p, net64, ":0x",
1076 				    &i_rec.inform_info.gid.unicast.
1077 				    interface_id);
1078 			PARSE_AHEAD(p, net16, " lid_range_begin=0x",
1079 				    &i_rec.inform_info.lid_range_begin);
1080 			PARSE_AHEAD(p, net16, " lid_range_end=0x",
1081 				    &i_rec.inform_info.lid_range_end);
1082 			PARSE_AHEAD(p, net8, " is_generic=0x",
1083 				    &i_rec.inform_info.is_generic);
1084 			PARSE_AHEAD(p, net8, " subscribe=0x",
1085 				    &i_rec.inform_info.subscribe);
1086 			PARSE_AHEAD(p, net16, " trap_type=0x",
1087 				    &i_rec.inform_info.trap_type);
1088 			PARSE_AHEAD(p, net16, " trap_num=0x",
1089 				    &i_rec.inform_info.g_or_v.generic.trap_num);
1090 			PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x",
1091 				    &i_rec.inform_info.g_or_v.generic.
1092 				    qpn_resp_time_val);
1093 			PARSE_AHEAD(p, net32, " node_type=0x",
1094 				    (uint32_t *) & i_rec.inform_info.g_or_v.
1095 				    generic.reserved2);
1096 
1097 			PARSE_AHEAD(p, net16, " rep_addr: lid=0x",
1098 				    &rep_addr.dest_lid);
1099 			PARSE_AHEAD(p, net8, " path_bits=0x",
1100 				    &rep_addr.path_bits);
1101 			PARSE_AHEAD(p, net8, " static_rate=0x",
1102 				    &rep_addr.static_rate);
1103 			PARSE_AHEAD(p, net32, " remote_qp=0x",
1104 				    &rep_addr.addr_type.gsi.remote_qp);
1105 			PARSE_AHEAD(p, net32, " remote_qkey=0x",
1106 				    &rep_addr.addr_type.gsi.remote_qkey);
1107 			PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16);
1108 			rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16);
1109 			PARSE_AHEAD(p, net8, " sl=0x",
1110 				    &rep_addr.addr_type.gsi.service_level);
1111 
1112 			if (load_infr(p_osm, &i_rec, &rep_addr))
1113 				rereg_clients = 1;
1114 		}
1115 	}
1116 
1117 	if (!rereg_clients)
1118 		p_osm->subn.opt.no_clients_rereg = TRUE;
1119 
1120 _error:
1121 	fclose(file);
1122 	return ret;
1123 }
1124