]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_sa.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / opensm / osm_sa.c
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  **********************************************************************/
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  **********************************************************************/
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  **********************************************************************/
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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
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
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
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
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
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 }