xref: /illumos-gate/usr/src/uts/common/io/ib/mgt/ibmf/ibmf_saa_utils.c (revision 5e989a96186a37eb528fb7bb4d28a150874ec799)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/kmem.h>
30 #include <sys/sunddi.h>
31 #include <sys/ib/mgt/ibmf/ibmf_saa_impl.h>
32 #include <sys/ib/mgt/ibmf/ibmf_saa_utils.h>
33 
34 #define	IBMF_SAA_HDR_SIZE			20
35 #define	IBMF_SAA_DEFAULT_RID_SIZE		4
36 #define	IBMF_SAA_PARTITION_RID_SIZE		5
37 #define	IBMF_SAA_INFORMINFO_RID_SIZE		18
38 
39 #define	IB_MAD_NOTICE_SIZE			80
40 #define	IB_MAD_CLASSPORTINFO_SIZE		72
41 #define	IB_MAD_INFORMINFO_SIZE			36
42 
43 #define	SM_TRAP_DATA_DETAILS_SIZE		54
44 #define	SM_NODEINFO_SIZE			40
45 #define	SM_NODEDESC_SIZE			64
46 #define	SM_PORTINFO_SIZE			54
47 #define	SM_SLTOVL_SIZE				8
48 #define	SM_SWITCHINFO_SIZE			17
49 #define	SM_LINEARFDB_SIZE			64
50 #define	SM_RANDOMFDB_SIZE			64
51 #define	SM_MULTICASTFDB_SIZE			64
52 #define	SM_SMINFO_SIZE				21
53 #define	SM_GUIDINFO_SIZE			64
54 #define	SM_PARTITION_SIZE			64
55 #define	SM_VLARB_SIZE				64
56 
57 #define	IBMF_SAA_NODE_RECORD_SIZE		108
58 #define	IBMF_SAA_PORTINFO_RECORD_SIZE		58
59 #define	IBMF_SAA_SLTOVL_RECORD_SIZE		16
60 #define	IBMF_SAA_SWITCHINFO_RECORD_SIZE		21
61 #define	IBMF_SAA_LINEARFDB_RECORD_SIZE		72
62 #define	IBMF_SAA_RANDOMFDB_RECORD_SIZE		72
63 #define	IBMF_SAA_MULTICASTFDB_RECORD_SIZE	72
64 #define	IBMF_SAA_SMINFO_RECORD_SIZE		25
65 #define	IBMF_SAA_INFORMINFO_RECORD_SIZE		60
66 #define	IBMF_SAA_LINK_RECORD_SIZE		6
67 #define	IBMF_SAA_GUIDINFO_RECORD_SIZE		72
68 #define	IBMF_SAA_SERVICE_RECORD_SIZE		176
69 #define	IBMF_SAA_PARTITION_RECORD_SIZE		72
70 #define	IBMF_SAA_PATH_RECORD_SIZE		64
71 #define	IBMF_SAA_VLARB_RECORD_SIZE		72
72 #define	IBMF_SAA_MCMEMBER_RECORD_SIZE		52
73 #define	IBMF_SAA_TRACE_RECORD_SIZE		46
74 #define	IBMF_SAA_MULTIPATH_RECORD_SIZE		24
75 #define	IBMF_SAA_SERVICEASSN_RECORD_SIZE	80
76 
77 extern	int	ibmf_trace_level;
78 
79 /* These functions have only been tested on a big-endian system */
80 static void ibmf_saa_classportinfo_parse_buffer(uchar_t *buffer, void *record);
81 static void ibmf_saa_notice_parse_buffer(uchar_t *buffer, void *record);
82 static void ibmf_saa_informinfo_parse_buffer(uchar_t *buffer, void *record);
83 static void ibmf_saa_node_record_parse_buffer(uchar_t *buffer, void *record);
84 static void ibmf_saa_portinfo_record_parse_buffer(uchar_t *buffer,
85     void *record);
86 static void ibmf_saa_SLtoVLmapping_record_parse_buffer(uchar_t *buffer,
87     void *record);
88 static void ibmf_saa_switchinfo_record_parse_buffer(uchar_t *buffer,
89     void *record);
90 static void ibmf_saa_linearft_record_parse_buffer(uchar_t *buffer,
91     void *record);
92 static void ibmf_saa_randomft_record_parse_buffer(uchar_t *buffer,
93     void *record);
94 static void ibmf_saa_multicastft_record_parse_buffer(uchar_t *buffer,
95     void *record);
96 static void ibmf_saa_sminfo_record_parse_buffer(uchar_t *buffer, void *record);
97 static void ibmf_saa_informinfo_record_parse_buffer(uchar_t *buffer,
98     void *record);
99 static void ibmf_saa_link_record_parse_buffer(uchar_t *buffer, void *record);
100 static void ibmf_saa_guidinfo_record_parse_buffer(uchar_t *buffer,
101     void *record);
102 static void ibmf_saa_service_record_parse_buffer(uchar_t *buffer, void *record);
103 static void ibmf_saa_partition_record_parse_buffer(uchar_t *buffer,
104     void *record);
105 static void ibmf_saa_path_record_parse_buffer(uchar_t *buffer, void *record);
106 static void ibmf_saa_vlarb_record_parse_buffer(uchar_t *buffer, void *record);
107 static void ibmf_saa_mcmember_record_parse_buffer(uchar_t *buffer,
108     void *record);
109 static void ibmf_saa_trace_record_parse_buffer(uchar_t *buffer, void *record);
110 static void ibmf_saa_multipath_record_parse_buffer(uchar_t *buffer,
111     void *record);
112 static void ibmf_saa_service_assn_record_parse_buffer(uchar_t *buffer,
113     void *record);
114 
115 static void ibmf_saa_classportinfo_to_buf(void *record, uchar_t *buffer);
116 static void ibmf_saa_notice_to_buf(void *record, uchar_t *buffer);
117 static void ibmf_saa_informinfo_to_buf(void *record, uchar_t *buffer);
118 static void ibmf_saa_node_record_to_buf(void *record, uchar_t *buffer);
119 static void ibmf_saa_portinfo_record_to_buf(void *record, uchar_t *buffer);
120 static void ibmf_saa_SLtoVLmapping_record_to_buf(void *record, uchar_t *buffer);
121 static void ibmf_saa_switchinfo_record_to_buf(void *record, uchar_t *buffer);
122 static void ibmf_saa_linearft_record_to_buf(void *record, uchar_t *buffer);
123 static void ibmf_saa_randomft_record_to_buf(void *record, uchar_t *buffer);
124 static void ibmf_saa_multicastft_record_to_buf(void *record, uchar_t *buffer);
125 static void ibmf_saa_sminfo_record_to_buf(void *record, uchar_t *buffer);
126 static void ibmf_saa_informinfo_record_to_buf(void *record, uchar_t *buffer);
127 static void ibmf_saa_link_record_to_buf(void *record, uchar_t *buffer);
128 static void ibmf_saa_guidinfo_record_to_buf(void *record, uchar_t *buffer);
129 static void ibmf_saa_service_record_to_buf(void *record, uchar_t *buffer);
130 static void ibmf_saa_partition_record_to_buf(void *record, uchar_t *buffer);
131 static void ibmf_saa_path_record_to_buf(void *record, uchar_t *buffer);
132 static void ibmf_saa_vlarb_record_to_buf(void *record, uchar_t *buffer);
133 static void ibmf_saa_mcmember_record_to_buf(void *record, uchar_t *buffer);
134 static void ibmf_saa_multipath_record_to_buf(void *record, uchar_t *buffer);
135 static void ibmf_saa_service_assn_record_to_buf(void *record, uchar_t *buffer);
136 
137 /*
138  * *_record_parse_buffer functions:
139  *
140  * Each of these functions parses a buffer containing a single SA record.
141  * The function copies the buffer into a structure taking care of any padding
142  * and byte-endianness issues.  There is one function for each of the 22
143  * attributes (Table 155).
144  *
145  * ibmf_utils_unpack_data() must be called for each structure in the structure
146  * since Solaris will align the internal structure on a 64-bit boundary, even if
147  * the first element is a 32-bit value.
148  *
149  * Input Arguments
150  * buffer	pointer character array containing raw data
151  *
152  * Output Arguments
153  * record	pointer to the SA attribute structure
154  *
155  * Returns	void
156  */
157 
158 static void
159 ibmf_saa_classportinfo_parse_buffer(uchar_t *buffer, void *record)
160 {
161 	ib_mad_classportinfo_t	*cpi = (ib_mad_classportinfo_t *)record;
162 
163 	ibmf_utils_unpack_data("2csl2Ll2s2l2Ll2s2l", buffer,
164 	    IB_MAD_CLASSPORTINFO_SIZE, cpi, sizeof (ib_mad_classportinfo_t));
165 }
166 
167 static void
168 ibmf_saa_notice_parse_buffer(uchar_t *buffer, void *record)
169 {
170 	ib_mad_notice_t		*notice = (ib_mad_notice_t *)record;
171 
172 	ibmf_utils_unpack_data("4c3s54c2L", buffer, IB_MAD_NOTICE_SIZE,
173 	    notice, sizeof (ib_mad_notice_t));
174 }
175 
176 static void
177 ibmf_saa_informinfo_parse_buffer(uchar_t *buffer, void *record)
178 {
179 	ib_mad_informinfo_t	*informinfo = (ib_mad_informinfo_t *)record;
180 
181 	ibmf_utils_unpack_data("2L3s2c2s2l", buffer, IB_MAD_INFORMINFO_SIZE,
182 	    informinfo, sizeof (ib_mad_informinfo_t));
183 }
184 
185 static void
186 ibmf_saa_node_record_parse_buffer(uchar_t *buffer, void *record)
187 {
188 	sa_node_record_t	*node_record = (sa_node_record_t *)record;
189 
190 	/* first get record identifier information */
191 	ibmf_utils_unpack_data("2s", buffer, IBMF_SAA_DEFAULT_RID_SIZE,
192 	    node_record, 4);
193 
194 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
195 
196 	/* next get node info */
197 	ibmf_utils_unpack_data("4c3L2s2l", buffer, SM_NODEINFO_SIZE,
198 	    &node_record->NodeInfo, sizeof (sm_nodeinfo_t));
199 
200 	buffer += SM_NODEINFO_SIZE;
201 
202 	ibmf_utils_unpack_data("64c", buffer, SM_NODEDESC_SIZE,
203 	    &node_record->NodeDescription, sizeof (sm_nodedesc_t));
204 }
205 
206 static void
207 ibmf_saa_portinfo_record_parse_buffer(uchar_t *buffer, void *record)
208 {
209 
210 	sa_portinfo_record_t	*portinfo_record =
211 	    (sa_portinfo_record_t *)record;
212 
213 	/* first get record identifier information */
214 	ibmf_utils_unpack_data("s2c", buffer, IBMF_SAA_DEFAULT_RID_SIZE,
215 	    portinfo_record, 4);
216 
217 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
218 
219 	/* next get portinfo info */
220 	ibmf_utils_unpack_data("LLsslss16c3s4c", buffer, SM_PORTINFO_SIZE,
221 	    &portinfo_record->PortInfo, sizeof (sm_portinfo_t));
222 }
223 
224 static void
225 ibmf_saa_SLtoVLmapping_record_parse_buffer(uchar_t *buffer, void *record)
226 {
227 
228 	sa_SLtoVLmapping_record_t	*SLtoVLmapping_record =
229 	    (sa_SLtoVLmapping_record_t *)record;
230 
231 	/* first get record identifier information (plus 4 bytes reserved) */
232 	ibmf_utils_unpack_data("s2cl", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
233 	    SLtoVLmapping_record, 8);
234 
235 	/* SLtoVL mapping has 4 reserved bytes between RID and attribute */
236 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
237 
238 	/* next get SLtoVLmapping info */
239 	ibmf_utils_unpack_data("8c", buffer, SM_SLTOVL_SIZE,
240 	    &SLtoVLmapping_record->SLtoVLMappingTable,
241 	    sizeof (sm_SLtoVL_mapping_table_t));
242 }
243 
244 static void
245 ibmf_saa_switchinfo_record_parse_buffer(uchar_t *buffer, void *record)
246 {
247 
248 	sa_switchinfo_record_t	*switchinfo_record =
249 	    (sa_switchinfo_record_t *)record;
250 
251 	/* first get record identifier information */
252 	ibmf_utils_unpack_data("2s", buffer, IBMF_SAA_DEFAULT_RID_SIZE,
253 	    switchinfo_record, 4);
254 
255 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
256 
257 	/* next get switchinfo info */
258 	ibmf_utils_unpack_data("4s4c2sc", buffer, SM_SWITCHINFO_SIZE,
259 	    &switchinfo_record->SwitchInfo, sizeof (sm_switchinfo_t));
260 
261 }
262 
263 static void
264 ibmf_saa_linearft_record_parse_buffer(uchar_t *buffer, void *record)
265 {
266 
267 	sa_linearft_record_t	*linearft_record =
268 	    (sa_linearft_record_t *)record;
269 
270 	/* first get record identifier information (plus 4 bytes reserved) */
271 	ibmf_utils_unpack_data("2sl", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
272 	    linearft_record, 8);
273 
274 	/* LFT has 4 reserved bytes between RID and attribute */
275 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
276 
277 	/* next get linearft info */
278 	ibmf_utils_unpack_data("64c", buffer, SM_LINEARFDB_SIZE,
279 	    &linearft_record->LinearFT, sizeof (sm_linear_forwarding_table_t));
280 }
281 
282 static void
283 ibmf_saa_randomft_record_parse_buffer(uchar_t *buffer, void *record)
284 {
285 
286 	sa_randomft_record_t	*randomft_record =
287 	    (sa_randomft_record_t *)record;
288 
289 	/* first get record identifier information (plus 4 bytes reserved) */
290 	ibmf_utils_unpack_data("2sl", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
291 	    randomft_record, 8);
292 
293 	/* RFT has 4 reserved bytes between RID and attribute */
294 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
295 
296 	/* next get randomft info */
297 	ibmf_utils_unpack_data("64c", buffer, SM_RANDOMFDB_SIZE,
298 	    &randomft_record->RandomFT, sizeof (sm_random_forwarding_table_t));
299 }
300 
301 static void
302 ibmf_saa_multicastft_record_parse_buffer(uchar_t *buffer, void *record)
303 {
304 
305 	sa_multicastft_record_t	*multicastft_record =
306 	    (sa_multicastft_record_t *)record;
307 
308 	/* first get record identifier information (plus 4 bytes reserved) */
309 	ibmf_utils_unpack_data("2sl", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
310 	    multicastft_record, 8);
311 
312 	/* MFT has 4 reserved bytes between RID and attribute */
313 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
314 
315 	/* next get multicastft info */
316 	ibmf_utils_unpack_data("32s", buffer, SM_MULTICASTFDB_SIZE,
317 	    &multicastft_record->MulticastFT,
318 	    sizeof (sm_multicast_forwarding_table_t));
319 }
320 
321 static void
322 ibmf_saa_sminfo_record_parse_buffer(uchar_t *buffer, void *record)
323 {
324 
325 	sa_sminfo_record_t	*sminfo_record =
326 	    (sa_sminfo_record_t *)record;
327 
328 	/* first get record identifier information */
329 	ibmf_utils_unpack_data("2s", buffer, IBMF_SAA_DEFAULT_RID_SIZE,
330 	    sminfo_record, 4);
331 
332 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
333 
334 	/* next get sminfo info */
335 	ibmf_utils_unpack_data("2Llc", buffer, SM_SMINFO_SIZE,
336 	    &sminfo_record->SMInfo,
337 	    sizeof (sm_sminfo_t));
338 }
339 
340 static void
341 ibmf_saa_informinfo_record_parse_buffer(uchar_t *buffer, void *record)
342 {
343 
344 	sa_informinfo_record_t	*informinfo_record =
345 	    (sa_informinfo_record_t *)record;
346 
347 	/* first get record identifier information */
348 	ibmf_utils_unpack_data("2Ls", buffer, IBMF_SAA_INFORMINFO_RID_SIZE,
349 	    informinfo_record, 18);
350 
351 	/* InformInfo has 6 reserved bytes between RID and attribute */
352 	buffer += IBMF_SAA_INFORMINFO_RID_SIZE + 6;
353 
354 	/* next get informinfo info */
355 	ibmf_utils_unpack_data("2L3s2c2s2l", buffer, IB_MAD_INFORMINFO_SIZE,
356 	    &informinfo_record->InformInfo,
357 	    sizeof (ib_mad_informinfo_t));
358 }
359 
360 static void
361 ibmf_saa_link_record_parse_buffer(uchar_t *buffer, void *record)
362 {
363 
364 	sa_link_record_t	*link_record = (sa_link_record_t *)record;
365 
366 	ibmf_utils_unpack_data("s2cs", buffer, IBMF_SAA_LINK_RECORD_SIZE,
367 	    link_record, sizeof (sa_link_record_t));
368 }
369 
370 static void
371 ibmf_saa_guidinfo_record_parse_buffer(uchar_t *buffer, void *record)
372 {
373 
374 	sa_guidinfo_record_t	*guidinfo_record =
375 	    (sa_guidinfo_record_t *)record;
376 
377 	/* first get record identifier information (plus 4 bytes reserved) */
378 	ibmf_utils_unpack_data("s2cl", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
379 	    guidinfo_record, 8);
380 
381 	/* GUIDInfo has 4 reserved bytes between RID and attribute */
382 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
383 
384 	/* next get guidinfo info */
385 	ibmf_utils_unpack_data("8L", buffer, SM_GUIDINFO_SIZE,
386 	    &guidinfo_record->GUIDInfo, sizeof (sm_guidinfo_t));
387 }
388 
389 static void
390 ibmf_saa_service_record_parse_buffer(uchar_t *buffer, void *record)
391 {
392 
393 	sa_service_record_t	*service_record = (sa_service_record_t *)record;
394 
395 	ibmf_utils_unpack_data("3L2sl2L64c16c8s4l2L", buffer,
396 	    IBMF_SAA_SERVICE_RECORD_SIZE, service_record,
397 	    sizeof (sa_service_record_t));
398 }
399 
400 static void
401 ibmf_saa_partition_record_parse_buffer(uchar_t *buffer, void *record)
402 {
403 
404 	sa_pkey_table_record_t	*partition_record =
405 	    (sa_pkey_table_record_t *)record;
406 
407 	/* first get record identifier information (plus 4 bytes reserved) */
408 	ibmf_utils_unpack_data("2s4c", buffer, IBMF_SAA_PARTITION_RID_SIZE + 3,
409 	    partition_record, 8);
410 
411 	/* Partition record has 3 reserved bytes between RID and attribute */
412 	buffer += IBMF_SAA_PARTITION_RID_SIZE + 3;
413 
414 	/* next get partition info */
415 	ibmf_utils_unpack_data("32s",  buffer, SM_PARTITION_SIZE,
416 	    &partition_record->P_KeyTable, sizeof (sm_pkey_table_t));
417 }
418 
419 static void
420 ibmf_saa_path_record_parse_buffer(uchar_t *buffer, void *record)
421 {
422 
423 	sa_path_record_t	*path_record = (sa_path_record_t *)record;
424 
425 	ibmf_utils_unpack_data("2l4L2sl2c2s4c", buffer,
426 	    IBMF_SAA_PATH_RECORD_SIZE, path_record, sizeof (sa_path_record_t));
427 }
428 
429 static void
430 ibmf_saa_vlarb_record_parse_buffer(uchar_t *buffer, void *record)
431 {
432 
433 	sa_VLarb_table_record_t	*VLarb_table_record =
434 	    (sa_VLarb_table_record_t *)record;
435 
436 	/* first get record identifier information (plus 4 bytes reserved) */
437 	ibmf_utils_unpack_data("s2c", buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4,
438 	    VLarb_table_record, 8);
439 
440 	/* VLarb record has 4 reserved bytes between RID and attribute */
441 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
442 
443 	/* next get VLarb_table info */
444 	ibmf_utils_unpack_data("64c", buffer, SM_VLARB_SIZE,
445 	    &VLarb_table_record->VLArbTable,
446 	    sizeof (sm_VLarb_table_t));
447 }
448 
449 static void
450 ibmf_saa_mcmember_record_parse_buffer(uchar_t *buffer, void *record)
451 {
452 
453 	sa_mcmember_record_t	*mcmember_record =
454 	    (sa_mcmember_record_t *)record;
455 
456 	ibmf_utils_unpack_data("4Lls2cs2c2l", buffer,
457 	    IBMF_SAA_MCMEMBER_RECORD_SIZE,
458 	    mcmember_record, sizeof (sa_mcmember_record_t));
459 }
460 
461 static void
462 ibmf_saa_trace_record_parse_buffer(uchar_t *buffer, void *record)
463 {
464 
465 	sa_trace_record_t	*trace_record =
466 	    (sa_trace_record_t *)record;
467 
468 	ibmf_utils_unpack_data("Ls2c4L2c", buffer,
469 	    IBMF_SAA_TRACE_RECORD_SIZE,
470 	    trace_record, sizeof (sa_trace_record_t));
471 }
472 
473 /*
474  * ibmf_saa_multipath_record_parse_buffer:
475  *
476  * First unpack the standard part of the multipath record.  Then find the number
477  * of gids and unpack those.  This function will probably never be called as the
478  * ibmf_saa should not receive any multipath records.  It's in here for
479  * completeness.
480  */
481 static void ibmf_saa_multipath_record_parse_buffer(uchar_t *buffer,
482     void *record)
483 {
484 	char			gid_str[20];
485 	uint16_t		num_gids;
486 
487 	sa_multipath_record_t	*multipath_record =
488 		(sa_multipath_record_t *)record;
489 
490 	ibmf_utils_unpack_data("l2c2s14c", buffer,
491 	    IBMF_SAA_MULTIPATH_RECORD_SIZE, multipath_record,
492 	    sizeof (sa_multipath_record_t));
493 
494 	num_gids = multipath_record->SGIDCount + multipath_record->DGIDCount;
495 
496 	(void) sprintf(gid_str, "%dL", 2 * num_gids);
497 
498 	ibmf_utils_unpack_data(gid_str, buffer + IBMF_SAA_MULTIPATH_RECORD_SIZE,
499 	    sizeof (ib_gid_t) * num_gids,
500 	    multipath_record + sizeof (sa_multipath_record_t),
501 	    sizeof (ib_gid_t) * num_gids);
502 
503 }
504 
505 static void
506 ibmf_saa_service_assn_record_parse_buffer(uchar_t *buffer, void *record)
507 {
508 
509 	sa_service_assn_record_t	*service_assn_record =
510 	    (sa_service_assn_record_t *)record;
511 
512 	ibmf_utils_unpack_data("2L64c", buffer,
513 	    IBMF_SAA_SERVICEASSN_RECORD_SIZE,
514 	    service_assn_record, sizeof (sa_service_assn_record_t));
515 }
516 
517 void
518 ibmf_saa_gid_trap_parse_buffer(uchar_t *buffer, sm_trap_64_t *sm_trap_64)
519 {
520 
521 	ibmf_utils_unpack_data("6c2L32c", buffer, SM_TRAP_DATA_DETAILS_SIZE,
522 	    sm_trap_64, sizeof (sm_trap_64_t));
523 }
524 
525 void
526 ibmf_saa_capmask_chg_trap_parse_buffer(uchar_t *buffer,
527     sm_trap_144_t *sm_trap_144)
528 {
529 
530 	ibmf_utils_unpack_data("2cs2cl44c", buffer, SM_TRAP_DATA_DETAILS_SIZE,
531 	    sm_trap_144, sizeof (sm_trap_144_t));
532 }
533 
534 void
535 ibmf_saa_sysimg_guid_chg_trap_parse_buffer(uchar_t *buffer,
536     sm_trap_145_t *sm_trap_145)
537 {
538 
539 	ibmf_utils_unpack_data("2cs2cL44c", buffer, SM_TRAP_DATA_DETAILS_SIZE,
540 	    sm_trap_145, sizeof (sm_trap_145_t));
541 }
542 
543 /*
544  * *_record_to_buf functions:
545  *
546  * Each of these functions copies a single SA record out of a structure and into
547  * a buffer for sending on the wire.  The function will take care of any padding
548  * and byte-endianness isues.  There is one function for each of the 22
549  * attributes (Table 155).
550  *
551  * ibmf_utils_pack_data() must be called for each structure in the structure
552  * since Solaris will align the internal structure on a 64-bit boundary, even if
553  * the first element is a 32-bit value.
554  *
555  * Input Arguments
556  * record	pointer to the structure to be parsed
557  *
558  * Output Arguments
559  * buffer	pointer to array to place the data in (allocated by caller)
560  *
561  * Returns	void
562  */
563 
564 static void
565 ibmf_saa_classportinfo_to_buf(void *record, uchar_t *buffer)
566 {
567 	ib_mad_classportinfo_t	*cpi = (ib_mad_classportinfo_t *)record;
568 
569 	ibmf_utils_pack_data("2csl2Ll2s2l2Ll2s2l",
570 	    cpi, sizeof (ib_mad_classportinfo_t),
571 	    buffer, IB_MAD_CLASSPORTINFO_SIZE);
572 }
573 
574 static void
575 ibmf_saa_notice_to_buf(void *record, uchar_t *buffer)
576 {
577 	ib_mad_notice_t		*notice = (ib_mad_notice_t *)record;
578 
579 	ibmf_utils_pack_data("4c3s54c2L", notice, sizeof (ib_mad_notice_t),
580 	    buffer, IB_MAD_NOTICE_SIZE);
581 }
582 
583 static void
584 ibmf_saa_informinfo_to_buf(void *record, uchar_t *buffer)
585 {
586 	ib_mad_informinfo_t	*informinfo = (ib_mad_informinfo_t *)record;
587 
588 	ibmf_utils_pack_data("2L3s2c2s2l", informinfo,
589 	    sizeof (ib_mad_informinfo_t), buffer, IB_MAD_INFORMINFO_SIZE);
590 }
591 
592 static void
593 ibmf_saa_node_record_to_buf(void *record, uchar_t *buffer)
594 {
595 
596 	sa_node_record_t	*node_record = (sa_node_record_t *)record;
597 
598 	/* first get record identifier information */
599 	ibmf_utils_pack_data("2s", node_record, 4, buffer,
600 	    IBMF_SAA_DEFAULT_RID_SIZE);
601 
602 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
603 
604 	/* next get node info */
605 	ibmf_utils_pack_data("4c3L2s2l", &node_record->NodeInfo,
606 	    sizeof (sm_nodeinfo_t), buffer, SM_NODEINFO_SIZE);
607 
608 	buffer += SM_NODEINFO_SIZE;
609 
610 	/* next get node description */
611 	ibmf_utils_pack_data("64c", &node_record->NodeDescription,
612 	    sizeof (sm_nodedesc_t), buffer, SM_NODEDESC_SIZE);
613 
614 }
615 
616 static void
617 ibmf_saa_portinfo_record_to_buf(void *record, uchar_t *buffer)
618 {
619 
620 	sa_portinfo_record_t	*portinfo_record =
621 	    (sa_portinfo_record_t *)record;
622 
623 	/* first get record identifier information */
624 	ibmf_utils_pack_data("s2c", portinfo_record, 4, buffer,
625 	    IBMF_SAA_DEFAULT_RID_SIZE);
626 
627 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
628 
629 	/* next get portinfo info */
630 	ibmf_utils_pack_data("LLsslss16c3s4c",
631 	    &portinfo_record->PortInfo, sizeof (sm_portinfo_t), buffer,
632 	    SM_PORTINFO_SIZE);
633 
634 }
635 
636 static void
637 ibmf_saa_SLtoVLmapping_record_to_buf(void *record, uchar_t *buffer)
638 {
639 
640 	sa_SLtoVLmapping_record_t	*SLtoVLmapping_record =
641 	    (sa_SLtoVLmapping_record_t *)record;
642 
643 	/* first get record identifier information (plus 4 bytes reserved) */
644 	ibmf_utils_pack_data("s2cl", SLtoVLmapping_record, 8, buffer,
645 	    IBMF_SAA_DEFAULT_RID_SIZE + 4);
646 
647 	/* SLtoVL mapping has 4 reserved bytes between RID and attribute */
648 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
649 
650 	/* next get SLtoVLmapping info */
651 	ibmf_utils_pack_data("8c", &SLtoVLmapping_record->SLtoVLMappingTable,
652 	    sizeof (sm_SLtoVL_mapping_table_t), buffer, SM_SLTOVL_SIZE);
653 }
654 
655 static void
656 ibmf_saa_switchinfo_record_to_buf(void *record, uchar_t *buffer)
657 {
658 
659 	sa_switchinfo_record_t	*switchinfo_record =
660 	    (sa_switchinfo_record_t *)record;
661 
662 	/* first get record identifier information */
663 	ibmf_utils_pack_data("2s", switchinfo_record, 4, buffer,
664 	    IBMF_SAA_DEFAULT_RID_SIZE);
665 
666 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
667 
668 	/* next get switchinfo info */
669 	ibmf_utils_pack_data("4s4c2sc", &switchinfo_record->SwitchInfo,
670 	    sizeof (sm_switchinfo_t), buffer, SM_SWITCHINFO_SIZE);
671 
672 }
673 
674 static void
675 ibmf_saa_linearft_record_to_buf(void *record, uchar_t *buffer)
676 {
677 
678 	sa_linearft_record_t	*linearft_record =
679 	    (sa_linearft_record_t *)record;
680 
681 	/* first get record identifier information (plus 4 bytes reserved) */
682 	ibmf_utils_pack_data("2sl", linearft_record, 8, buffer,
683 	    IBMF_SAA_DEFAULT_RID_SIZE + 4);
684 
685 	/* LFT has 4 reserved bytes between RID and attribute */
686 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
687 
688 	/* next get linearft info */
689 	ibmf_utils_pack_data("64c", &linearft_record->LinearFT,
690 	    sizeof (sm_linear_forwarding_table_t), buffer, SM_LINEARFDB_SIZE);
691 }
692 
693 static void
694 ibmf_saa_randomft_record_to_buf(void *record, uchar_t *buffer)
695 {
696 
697 	sa_randomft_record_t	*randomft_record =
698 	    (sa_randomft_record_t *)record;
699 
700 	/* first get record identifier information (plus 4 bytes reserved) */
701 	ibmf_utils_pack_data("2sl", randomft_record, 8, buffer,
702 	    IBMF_SAA_DEFAULT_RID_SIZE + 4);
703 
704 	/* RFT has 4 reserved bytes between RID and attribute */
705 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
706 
707 	/* next get randomft info */
708 	ibmf_utils_pack_data("64c", &randomft_record->RandomFT,
709 	    sizeof (sm_random_forwarding_table_t), buffer, SM_RANDOMFDB_SIZE);
710 }
711 
712 static void
713 ibmf_saa_multicastft_record_to_buf(void *record, uchar_t *buffer)
714 {
715 
716 	sa_multicastft_record_t	*multicastft_record =
717 	    (sa_multicastft_record_t *)record;
718 
719 	/* first get record identifier information (plus 4 bytes reserved) */
720 	ibmf_utils_pack_data("2sl", multicastft_record, 8, buffer,
721 	    IBMF_SAA_DEFAULT_RID_SIZE + 4);
722 
723 	/* MFT has 4 reserved bytes between RID and attribute */
724 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
725 
726 	/* next get multicastft info */
727 	ibmf_utils_pack_data("32s", &multicastft_record->MulticastFT,
728 	    sizeof (sm_multicast_forwarding_table_t), buffer,
729 	    SM_MULTICASTFDB_SIZE);
730 }
731 
732 static void
733 ibmf_saa_sminfo_record_to_buf(void *record, uchar_t *buffer)
734 {
735 
736 	sa_sminfo_record_t	*sminfo_record =
737 	    (sa_sminfo_record_t *)record;
738 
739 	/* first get record identifier information */
740 	ibmf_utils_pack_data("2s", sminfo_record, 4, buffer,
741 	    IBMF_SAA_DEFAULT_RID_SIZE);
742 
743 	buffer += IBMF_SAA_DEFAULT_RID_SIZE;
744 
745 	/* next get sminfo info */
746 	ibmf_utils_pack_data("2Llc", &sminfo_record->SMInfo,
747 	    sizeof (sm_sminfo_t), buffer, SM_SMINFO_SIZE);
748 }
749 
750 static void
751 ibmf_saa_informinfo_record_to_buf(void *record, uchar_t *buffer)
752 {
753 
754 	sa_informinfo_record_t	*informinfo_record =
755 	    (sa_informinfo_record_t *)record;
756 
757 	/* first get record identifier information */
758 	ibmf_utils_pack_data("2Ls", informinfo_record, 18, buffer,
759 	    IBMF_SAA_INFORMINFO_RID_SIZE);
760 
761 	/* InformInfo has 6 reserved bytes between RID and attribute */
762 	buffer += IBMF_SAA_INFORMINFO_RID_SIZE + 6;
763 
764 	/* next get informinfo info */
765 	ibmf_utils_pack_data("2L3s2c2s2l", &informinfo_record->InformInfo,
766 	    sizeof (ib_mad_informinfo_t), buffer, IB_MAD_INFORMINFO_SIZE);
767 }
768 
769 static void
770 ibmf_saa_link_record_to_buf(void *record, uchar_t *buffer)
771 {
772 
773 	sa_link_record_t	*link_record = (sa_link_record_t *)record;
774 
775 	ibmf_utils_pack_data("s2cs", link_record,
776 	    sizeof (sa_link_record_t), buffer, IBMF_SAA_LINK_RECORD_SIZE);
777 }
778 
779 static void
780 ibmf_saa_guidinfo_record_to_buf(void *record, uchar_t *buffer)
781 {
782 
783 	sa_guidinfo_record_t	*guidinfo_record =
784 	    (sa_guidinfo_record_t *)record;
785 
786 	/* first get record identifier information (plus 4 bytes reserved) */
787 	ibmf_utils_pack_data("s2cl", guidinfo_record,
788 	    8, buffer, IBMF_SAA_DEFAULT_RID_SIZE + 4);
789 
790 	/* GUIDInfo has 4 reserved bytes between RID and attribute */
791 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
792 
793 	/* next get guidinfo info */
794 	ibmf_utils_pack_data("8L", &guidinfo_record->GUIDInfo,
795 	    sizeof (sm_guidinfo_t), buffer, SM_GUIDINFO_SIZE);
796 }
797 
798 static void
799 ibmf_saa_service_record_to_buf(void *record, uchar_t *buffer)
800 {
801 
802 	sa_service_record_t	*service_record = (sa_service_record_t *)record;
803 
804 	ibmf_utils_pack_data("3L2sl2L64c16c8s4l2L", service_record,
805 	    sizeof (sa_service_record_t), buffer, IBMF_SAA_SERVICE_RECORD_SIZE);
806 }
807 
808 static void
809 ibmf_saa_partition_record_to_buf(void *record, uchar_t *buffer)
810 {
811 
812 	sa_pkey_table_record_t	*partition_record =
813 	    (sa_pkey_table_record_t *)record;
814 
815 	/* first get record identifier information (plus 4 bytes reserved) */
816 	ibmf_utils_pack_data("2s4c", partition_record, 8, buffer,
817 	    IBMF_SAA_PARTITION_RID_SIZE	+ 3);
818 
819 	/*  Partition record has 3 reserved bytes between RID and attribute */
820 	buffer += IBMF_SAA_PARTITION_RID_SIZE + 3;
821 
822 	/* next get partition info */
823 	ibmf_utils_pack_data("32s", &partition_record->P_KeyTable,
824 	    sizeof (sm_pkey_table_t), buffer, SM_PARTITION_SIZE);
825 }
826 
827 static void
828 ibmf_saa_path_record_to_buf(void *record, uchar_t *buffer)
829 {
830 
831 	sa_path_record_t	*path_record = (sa_path_record_t *)record;
832 
833 	ibmf_utils_pack_data("2l4L2sl2c2s4c", path_record,
834 	    sizeof (sa_path_record_t), buffer, IBMF_SAA_PATH_RECORD_SIZE);
835 }
836 
837 static void
838 ibmf_saa_vlarb_record_to_buf(void *record, uchar_t *buffer)
839 {
840 
841 	sa_VLarb_table_record_t	*VLarb_table_record =
842 	    (sa_VLarb_table_record_t *)record;
843 
844 	/* first get record identifier information (plus 4 bytes reserved) */
845 	ibmf_utils_pack_data("s2c", VLarb_table_record, 8, buffer,
846 	    IBMF_SAA_DEFAULT_RID_SIZE + 4);
847 
848 	/*  VLarb record has 4 reserved bytes between RID and attribute */
849 	buffer += IBMF_SAA_DEFAULT_RID_SIZE + 4;
850 
851 	/* next get VLarb_table info */
852 	ibmf_utils_pack_data("64c", &VLarb_table_record->VLArbTable,
853 	    sizeof (sm_VLarb_table_t), buffer, SM_VLARB_SIZE);
854 }
855 
856 
857 static void
858 ibmf_saa_mcmember_record_to_buf(void *record, uchar_t *buffer)
859 {
860 
861 	sa_mcmember_record_t	*mcmember_record =
862 	    (sa_mcmember_record_t *)record;
863 
864 	ibmf_utils_pack_data("4Lls2cs2c2l", mcmember_record,
865 	    sizeof (sa_mcmember_record_t),
866 	    buffer, IBMF_SAA_MCMEMBER_RECORD_SIZE);
867 }
868 
869 static void ibmf_saa_multipath_record_to_buf(void *record, uchar_t *buffer)
870 {
871 	char			gid_str[20];
872 	uint16_t		num_gids;
873 	sa_multipath_record_t	*multipath_record =
874 		(sa_multipath_record_t *)record;
875 
876 	num_gids = multipath_record->SGIDCount + multipath_record->DGIDCount;
877 
878 	(void) sprintf(gid_str, "l2c2s14c%dL", 2 * num_gids);
879 
880 	ibmf_utils_pack_data(gid_str, multipath_record,
881 	    sizeof (sa_multipath_record_t) + sizeof (ib_gid_t) * num_gids,
882 	    buffer,
883 	    IBMF_SAA_MULTIPATH_RECORD_SIZE + sizeof (ib_gid_t) * num_gids);
884 }
885 
886 static void
887 ibmf_saa_service_assn_record_to_buf(void *record, uchar_t *buffer)
888 {
889 
890 	sa_service_assn_record_t	*service_assn_record =
891 	    (sa_service_assn_record_t *)record;
892 
893 	ibmf_utils_pack_data("2L64c", service_assn_record,
894 	    sizeof (sa_service_assn_record_t),
895 	    buffer, IBMF_SAA_SERVICEASSN_RECORD_SIZE);
896 }
897 
898 int
899 ibmf_saa_utils_pack_sa_hdr(ib_sa_hdr_t *sa_hdr, void **packed_class_hdr,
900     size_t *packed_class_hdr_len, int km_sleep_flag)
901 {
902 
903 	*packed_class_hdr = kmem_zalloc(IBMF_SAA_HDR_SIZE, km_sleep_flag);
904 	if (*packed_class_hdr == NULL) {
905 
906 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L1,
907 		    ibmf_saa_utils_pack_sa_hdr_err,
908 		    IBMF_TNF_ERROR, "", "ibmf_saa_utils_pack_sa_hdr: "
909 		    "could not allocate memory for header\n");
910 
911 		return (IBMF_NO_MEMORY);
912 	}
913 
914 	ibmf_utils_pack_data("LssL", sa_hdr, sizeof (ib_sa_hdr_t),
915 	    (uchar_t *)*packed_class_hdr, IBMF_SAA_HDR_SIZE);
916 
917 	*packed_class_hdr_len = IBMF_SAA_HDR_SIZE;
918 
919 	return (IBMF_SUCCESS);
920 }
921 
922 int
923 ibmf_saa_utils_unpack_sa_hdr(void *packed_class_hdr,
924     size_t packed_class_hdr_len, ib_sa_hdr_t **sa_hdr, int km_sleep_flag)
925 {
926 	if (packed_class_hdr_len != IBMF_SAA_HDR_SIZE) {
927 
928 		IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L1,
929 		    ibmf_saa_utils_unpack_sa_hdr_err,
930 		    IBMF_TNF_ERROR, "", "ibmf_saa_utils_unpack_sa_hdr: %s,"
931 		    " sa_class_hdr_len = %d, pkt_class_hdr_len = %d\n",
932 		    tnf_string, msg, "invalid class hdr length for SA packet",
933 		    tnf_int, sa_class_hdr_len, IBMF_SAA_HDR_SIZE,
934 		    tnf_int, pkt_class_hdr_len, packed_class_hdr_len);
935 
936 		return (IBMF_REQ_INVALID);
937 	}
938 
939 	*sa_hdr = kmem_zalloc(sizeof (ib_sa_hdr_t), km_sleep_flag);
940 	if (*sa_hdr == NULL) {
941 
942 		IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L1,
943 		    ibmf_saa_utils_unpack_sa_hdr_err,
944 		    IBMF_TNF_ERROR, "", "ibmf_saa_utils_unpack_sa_hdr: "
945 		    "could not allocate memory for header\n");
946 
947 		return (IBMF_NO_MEMORY);
948 	}
949 
950 	ibmf_utils_unpack_data("LssL", (uchar_t *)packed_class_hdr,
951 	    IBMF_SAA_HDR_SIZE, *sa_hdr, sizeof (ib_sa_hdr_t));
952 
953 	return (IBMF_SUCCESS);
954 }
955 
956 /*
957  * ibmf_saa_utils_pack_payload:
958  *
959  * Takes a pointer to an array of sa record structures.  For each element packs
960  * the structure into a character buffer removing any padding and account for
961  * endianness issues.
962  *
963  */
964 int
965 ibmf_saa_utils_pack_payload(uchar_t *structs_payload, size_t
966     structs_payload_length, uint16_t attr_id, void **buf_payloadp,
967     size_t *buf_payload_lengthp, int km_sleep_flag)
968 {
969 
970 	int	i;
971 	int	struct_size, buf_size;
972 	int	num_records;
973 	void	(*pack_data_fn)(void *, uchar_t *);
974 
975 	if (structs_payload_length == 0) {
976 
977 		*buf_payload_lengthp = NULL;
978 		*buf_payloadp = NULL;
979 
980 		return (IBMF_SUCCESS);
981 	}
982 
983 	ASSERT(structs_payload != NULL);
984 
985 	/* trace records should never be sent (or packed) by ibmf_saa */
986 	ASSERT(attr_id != SA_TRACERECORD_ATTRID);
987 
988 	switch (attr_id) {
989 		case SA_CLASSPORTINFO_ATTRID:
990 			struct_size = sizeof (ib_mad_classportinfo_t);
991 			buf_size = IB_MAD_CLASSPORTINFO_SIZE;
992 			pack_data_fn = ibmf_saa_classportinfo_to_buf;
993 			break;
994 		case SA_NOTICE_ATTRID:
995 			struct_size = sizeof (ib_mad_notice_t);
996 			buf_size = IB_MAD_NOTICE_SIZE;
997 			pack_data_fn = ibmf_saa_notice_to_buf;
998 			break;
999 		case SA_INFORMINFO_ATTRID:
1000 			struct_size = sizeof (ib_mad_informinfo_t);
1001 			buf_size = IB_MAD_INFORMINFO_SIZE;
1002 			pack_data_fn = ibmf_saa_informinfo_to_buf;
1003 			break;
1004 		case SA_NODERECORD_ATTRID:
1005 			struct_size = sizeof (sa_node_record_t);
1006 			buf_size = IBMF_SAA_NODE_RECORD_SIZE;
1007 			pack_data_fn = ibmf_saa_node_record_to_buf;
1008 			break;
1009 		case SA_PORTINFORECORD_ATTRID:
1010 			struct_size = sizeof (sa_portinfo_record_t);
1011 			buf_size = IBMF_SAA_PORTINFO_RECORD_SIZE;
1012 			pack_data_fn = ibmf_saa_portinfo_record_to_buf;
1013 			break;
1014 		case SA_SLTOVLRECORD_ATTRID:
1015 			struct_size = sizeof (sa_SLtoVLmapping_record_t);
1016 			buf_size = IBMF_SAA_SLTOVL_RECORD_SIZE;
1017 			pack_data_fn = ibmf_saa_SLtoVLmapping_record_to_buf;
1018 			break;
1019 		case SA_SWITCHINFORECORD_ATTRID:
1020 			struct_size = sizeof (sa_switchinfo_record_t);
1021 			buf_size = IBMF_SAA_SWITCHINFO_RECORD_SIZE;
1022 			pack_data_fn = ibmf_saa_switchinfo_record_to_buf;
1023 			break;
1024 		case SA_LINEARFDBRECORD_ATTRID:
1025 			struct_size = sizeof (sa_linearft_record_t);
1026 			buf_size = IBMF_SAA_LINEARFDB_RECORD_SIZE;
1027 			pack_data_fn = ibmf_saa_linearft_record_to_buf;
1028 			break;
1029 		case SA_RANDOMFDBRECORD_ATTRID:
1030 			struct_size = sizeof (sa_randomft_record_t);
1031 			buf_size = IBMF_SAA_RANDOMFDB_RECORD_SIZE;
1032 			pack_data_fn = ibmf_saa_randomft_record_to_buf;
1033 			break;
1034 		case SA_MULTICASTFDBRECORD_ATTRID:
1035 			struct_size = sizeof (sa_multicastft_record_t);
1036 			buf_size = IBMF_SAA_MULTICASTFDB_RECORD_SIZE;
1037 			pack_data_fn = ibmf_saa_multicastft_record_to_buf;
1038 			break;
1039 		case SA_SMINFORECORD_ATTRID:
1040 			struct_size = sizeof (sa_sminfo_record_t);
1041 			buf_size = IBMF_SAA_SMINFO_RECORD_SIZE;
1042 			pack_data_fn = ibmf_saa_sminfo_record_to_buf;
1043 			break;
1044 		case SA_INFORMINFORECORD_ATTRID:
1045 			struct_size = sizeof (sa_informinfo_record_t);
1046 			buf_size = IBMF_SAA_INFORMINFO_RECORD_SIZE;
1047 			pack_data_fn = ibmf_saa_informinfo_record_to_buf;
1048 			break;
1049 		case SA_LINKRECORD_ATTRID:
1050 			struct_size = sizeof (sa_link_record_t);
1051 			buf_size = IBMF_SAA_LINK_RECORD_SIZE;
1052 			pack_data_fn = ibmf_saa_link_record_to_buf;
1053 			break;
1054 		case SA_GUIDINFORECORD_ATTRID:
1055 			struct_size = sizeof (sa_guidinfo_record_t);
1056 			buf_size = IBMF_SAA_GUIDINFO_RECORD_SIZE;
1057 			pack_data_fn = ibmf_saa_guidinfo_record_to_buf;
1058 			break;
1059 		case SA_SERVICERECORD_ATTRID:
1060 			struct_size = sizeof (sa_service_record_t);
1061 			buf_size = IBMF_SAA_SERVICE_RECORD_SIZE;
1062 			pack_data_fn = ibmf_saa_service_record_to_buf;
1063 			break;
1064 		case SA_PARTITIONRECORD_ATTRID:
1065 			struct_size = sizeof (sa_pkey_table_record_t);
1066 			buf_size = IBMF_SAA_PARTITION_RECORD_SIZE;
1067 			pack_data_fn = ibmf_saa_partition_record_to_buf;
1068 			break;
1069 		case SA_PATHRECORD_ATTRID:
1070 			struct_size = sizeof (sa_path_record_t);
1071 			buf_size = IBMF_SAA_PATH_RECORD_SIZE;
1072 			pack_data_fn = ibmf_saa_path_record_to_buf;
1073 			break;
1074 		case SA_VLARBRECORD_ATTRID:
1075 			struct_size = sizeof (sa_VLarb_table_record_t);
1076 			buf_size = IBMF_SAA_VLARB_RECORD_SIZE;
1077 			pack_data_fn = ibmf_saa_vlarb_record_to_buf;
1078 			break;
1079 		case SA_MCMEMBERRECORD_ATTRID:
1080 			struct_size = sizeof (sa_mcmember_record_t);
1081 			buf_size = IBMF_SAA_MCMEMBER_RECORD_SIZE;
1082 			pack_data_fn = ibmf_saa_mcmember_record_to_buf;
1083 			break;
1084 		case SA_MULTIPATHRECORD_ATTRID:
1085 			/*
1086 			 * array is of size 1 since multipath can be request
1087 			 * only; data size greater than multipath_record_t
1088 			 * size is due to gids at the end
1089 			 */
1090 			struct_size = structs_payload_length;
1091 			buf_size = IBMF_SAA_MULTIPATH_RECORD_SIZE +
1092 			    struct_size - sizeof (sa_multipath_record_t);
1093 			pack_data_fn = ibmf_saa_multipath_record_to_buf;
1094 			break;
1095 		case SA_SERVICEASSNRECORD_ATTRID:
1096 			struct_size = sizeof (sa_service_assn_record_t);
1097 			buf_size = IBMF_SAA_SERVICEASSN_RECORD_SIZE;
1098 			pack_data_fn = ibmf_saa_service_assn_record_to_buf;
1099 			break;
1100 		default:
1101 
1102 			/* don't know about structure; do bcopy */
1103 			*buf_payload_lengthp = structs_payload_length;
1104 			*buf_payloadp = kmem_zalloc(*buf_payload_lengthp,
1105 			    km_sleep_flag);
1106 			if (*buf_payloadp == NULL) {
1107 
1108 				*buf_payload_lengthp = 0;
1109 				return (IBMF_NO_MEMORY);
1110 			}
1111 
1112 			bcopy(structs_payload, *buf_payloadp,
1113 			    *buf_payload_lengthp);
1114 
1115 			return (IBMF_SUCCESS);
1116 	}
1117 
1118 	*buf_payload_lengthp = structs_payload_length / struct_size * buf_size;
1119 	num_records = structs_payload_length / struct_size;
1120 	*buf_payloadp = kmem_zalloc(*buf_payload_lengthp, km_sleep_flag);
1121 	if (*buf_payloadp == NULL) {
1122 
1123 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L1,
1124 		    ibmf_saa_utils_pack_payload_err,
1125 		    IBMF_TNF_ERROR, "", "ibmf_saa_utils_pack_payload: %s,"
1126 		    " size = %d\n",
1127 		    tnf_string, msg, "could not allocate memory for payload",
1128 		    tnf_int, size, *buf_payload_lengthp);
1129 
1130 		*buf_payload_lengthp = 0;
1131 		return (IBMF_NO_MEMORY);
1132 	}
1133 
1134 	for (i = 0; i < num_records; i++) {
1135 
1136 		pack_data_fn(
1137 		    (void *)((uchar_t *)structs_payload + i * struct_size),
1138 		    ((uchar_t *)*buf_payloadp + i * buf_size));
1139 	}
1140 
1141 	return (IBMF_SUCCESS);
1142 }
1143 
1144 
1145 /*
1146  * ibmf_saa_utils_unpack_payload:
1147  *
1148  * Unpacks a buffer of data received over the wire and places into an array of
1149  * structure in host format.
1150  *
1151  * for getResp() ibmf always reports payload length as 200 bytes
1152  * (MAD_SIZE - headers).  To keep the client from having to determine the actual
1153  * length of the one attribute (since we do it here) the is_get_resp parameter
1154  * indicates that there is one attribute in the buffer.
1155  */
1156 int
1157 ibmf_saa_utils_unpack_payload(uchar_t *buf_payload, size_t buf_payload_length,
1158     uint16_t attr_id, void **structs_payloadp, size_t *structs_payload_lengthp,
1159     uint16_t attr_offset, boolean_t is_get_resp, int km_sleep_flag)
1160 {
1161 
1162 	int	i;
1163 	int	struct_size, buf_size;
1164 	int	num_records;
1165 	void	(*unpack_data_fn)(uchar_t *, void *);
1166 	int	bytes_between_recs;
1167 
1168 	if (buf_payload_length == 0) {
1169 
1170 		*structs_payload_lengthp = 0;
1171 		*structs_payloadp = NULL;
1172 
1173 		return (IBMF_SUCCESS);
1174 	}
1175 
1176 	switch (attr_id) {
1177 		case SA_CLASSPORTINFO_ATTRID:
1178 			struct_size = sizeof (ib_mad_classportinfo_t);
1179 			buf_size = IB_MAD_CLASSPORTINFO_SIZE;
1180 			unpack_data_fn = ibmf_saa_classportinfo_parse_buffer;
1181 			break;
1182 		case SA_NOTICE_ATTRID:
1183 			struct_size = sizeof (ib_mad_notice_t);
1184 			buf_size = IB_MAD_NOTICE_SIZE;
1185 			unpack_data_fn = ibmf_saa_notice_parse_buffer;
1186 			break;
1187 		case SA_INFORMINFO_ATTRID:
1188 			struct_size = sizeof (ib_mad_informinfo_t);
1189 			buf_size = IB_MAD_INFORMINFO_SIZE;
1190 			unpack_data_fn = ibmf_saa_informinfo_parse_buffer;
1191 			break;
1192 		case SA_NODERECORD_ATTRID:
1193 			struct_size = sizeof (sa_node_record_t);
1194 			buf_size = IBMF_SAA_NODE_RECORD_SIZE;
1195 			unpack_data_fn = ibmf_saa_node_record_parse_buffer;
1196 			break;
1197 		case SA_PORTINFORECORD_ATTRID:
1198 			struct_size = sizeof (sa_portinfo_record_t);
1199 			buf_size = IBMF_SAA_PORTINFO_RECORD_SIZE;
1200 			unpack_data_fn = ibmf_saa_portinfo_record_parse_buffer;
1201 			break;
1202 		case SA_SLTOVLRECORD_ATTRID:
1203 			struct_size = sizeof (sa_SLtoVLmapping_record_t);
1204 			buf_size = IBMF_SAA_SLTOVL_RECORD_SIZE;
1205 			unpack_data_fn =
1206 			    ibmf_saa_SLtoVLmapping_record_parse_buffer;
1207 			break;
1208 		case SA_SWITCHINFORECORD_ATTRID:
1209 			struct_size = sizeof (sa_switchinfo_record_t);
1210 			buf_size = IBMF_SAA_SWITCHINFO_RECORD_SIZE;
1211 			unpack_data_fn =
1212 			    ibmf_saa_switchinfo_record_parse_buffer;
1213 			break;
1214 		case SA_LINEARFDBRECORD_ATTRID:
1215 			struct_size = sizeof (sa_linearft_record_t);
1216 			buf_size = IBMF_SAA_LINEARFDB_RECORD_SIZE;
1217 			unpack_data_fn = ibmf_saa_linearft_record_parse_buffer;
1218 			break;
1219 		case SA_RANDOMFDBRECORD_ATTRID:
1220 			struct_size = sizeof (sa_randomft_record_t);
1221 			buf_size = IBMF_SAA_RANDOMFDB_RECORD_SIZE;
1222 			unpack_data_fn = ibmf_saa_randomft_record_parse_buffer;
1223 			break;
1224 		case SA_MULTICASTFDBRECORD_ATTRID:
1225 			struct_size = sizeof (sa_multicastft_record_t);
1226 			buf_size = IBMF_SAA_MULTICASTFDB_RECORD_SIZE;
1227 			unpack_data_fn =
1228 			    ibmf_saa_multicastft_record_parse_buffer;
1229 			break;
1230 		case SA_SMINFORECORD_ATTRID:
1231 			struct_size = sizeof (sa_sminfo_record_t);
1232 			buf_size = IBMF_SAA_SMINFO_RECORD_SIZE;
1233 			unpack_data_fn = ibmf_saa_sminfo_record_parse_buffer;
1234 			break;
1235 		case SA_INFORMINFORECORD_ATTRID:
1236 			struct_size = sizeof (sa_informinfo_record_t);
1237 			buf_size = IBMF_SAA_INFORMINFO_RECORD_SIZE;
1238 			unpack_data_fn =
1239 			    ibmf_saa_informinfo_record_parse_buffer;
1240 			break;
1241 		case SA_LINKRECORD_ATTRID:
1242 			struct_size = sizeof (sa_link_record_t);
1243 			buf_size = IBMF_SAA_LINK_RECORD_SIZE;
1244 			unpack_data_fn = ibmf_saa_link_record_parse_buffer;
1245 			break;
1246 		case SA_GUIDINFORECORD_ATTRID:
1247 			struct_size = sizeof (sa_guidinfo_record_t);
1248 			buf_size = IBMF_SAA_GUIDINFO_RECORD_SIZE;
1249 			unpack_data_fn = ibmf_saa_guidinfo_record_parse_buffer;
1250 			break;
1251 		case SA_SERVICERECORD_ATTRID:
1252 			struct_size = sizeof (sa_service_record_t);
1253 			buf_size = IBMF_SAA_SERVICE_RECORD_SIZE;
1254 			unpack_data_fn = ibmf_saa_service_record_parse_buffer;
1255 			break;
1256 		case SA_PARTITIONRECORD_ATTRID:
1257 			struct_size = sizeof (sa_pkey_table_record_t);
1258 			buf_size = IBMF_SAA_PARTITION_RECORD_SIZE;
1259 			unpack_data_fn =
1260 			    ibmf_saa_partition_record_parse_buffer;
1261 			break;
1262 		case SA_PATHRECORD_ATTRID:
1263 			struct_size = sizeof (sa_path_record_t);
1264 			buf_size = IBMF_SAA_PATH_RECORD_SIZE;
1265 			unpack_data_fn = ibmf_saa_path_record_parse_buffer;
1266 			break;
1267 		case SA_VLARBRECORD_ATTRID:
1268 			struct_size = sizeof (sa_VLarb_table_record_t);
1269 			buf_size = IBMF_SAA_VLARB_RECORD_SIZE;
1270 			unpack_data_fn = ibmf_saa_vlarb_record_parse_buffer;
1271 			break;
1272 		case SA_MCMEMBERRECORD_ATTRID:
1273 			struct_size = sizeof (sa_mcmember_record_t);
1274 			buf_size = IBMF_SAA_MCMEMBER_RECORD_SIZE;
1275 			unpack_data_fn = ibmf_saa_mcmember_record_parse_buffer;
1276 			break;
1277 		case SA_TRACERECORD_ATTRID:
1278 			struct_size = sizeof (sa_trace_record_t);
1279 			buf_size = IBMF_SAA_TRACE_RECORD_SIZE;
1280 			unpack_data_fn = ibmf_saa_trace_record_parse_buffer;
1281 			break;
1282 		case SA_MULTIPATHRECORD_ATTRID:
1283 			/*
1284 			 * array is of size 1 since multipath can be request
1285 			 * only; data size greater than multipath_record_t
1286 			 * size is due to gids at the end
1287 			 */
1288 			buf_size = buf_payload_length;
1289 			struct_size = sizeof (sa_multipath_record_t) +
1290 			    buf_size - IBMF_SAA_MULTIPATH_RECORD_SIZE;
1291 			unpack_data_fn = ibmf_saa_multipath_record_parse_buffer;
1292 			break;
1293 		case SA_SERVICEASSNRECORD_ATTRID:
1294 			struct_size = sizeof (sa_service_assn_record_t);
1295 			buf_size = IBMF_SAA_SERVICEASSN_RECORD_SIZE;
1296 			unpack_data_fn =
1297 			    ibmf_saa_service_assn_record_parse_buffer;
1298 			break;
1299 		default:
1300 			/* don't know about structure; do bcopy */
1301 
1302 			*structs_payload_lengthp = buf_payload_length;
1303 			*structs_payloadp = kmem_zalloc(
1304 			    *structs_payload_lengthp, km_sleep_flag);
1305 			if (*structs_payloadp == NULL) {
1306 
1307 				*structs_payload_lengthp = 0;
1308 				return (IBMF_NO_MEMORY);
1309 			}
1310 
1311 			bcopy(buf_payload, *structs_payloadp,
1312 			    *structs_payload_lengthp);
1313 
1314 			return (IBMF_SUCCESS);
1315 	}
1316 
1317 	/* compute distance between successive records */
1318 	if (attr_offset > 0) {
1319 
1320 		if ((attr_offset * 8) < buf_size) {
1321 
1322 			IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L1,
1323 			    ibmf_saa_utils_unpack_payload, IBMF_TNF_ERROR, "",
1324 			    "ibmf_saa_utils_unpack_payload: %s, attr_offset = "
1325 			    "%d, attr_size = %d\n",
1326 			    tnf_string, msg, "attribute offset times 8 is less"
1327 			    " than attribute size",
1328 			    tnf_int, attr_offset, attr_offset,
1329 			    tnf_int, attr_size, buf_size);
1330 
1331 			return (IBMF_TRANS_FAILURE);
1332 		}
1333 
1334 		bytes_between_recs = attr_offset * 8;
1335 	} else {
1336 		bytes_between_recs = buf_size;
1337 	}
1338 
1339 	if (is_get_resp == B_TRUE) {
1340 
1341 		buf_payload_length = buf_size;
1342 		num_records = 1;
1343 	} else {
1344 
1345 		num_records = buf_payload_length / bytes_between_recs;
1346 	}
1347 
1348 	*structs_payload_lengthp = num_records * struct_size;
1349 
1350 	*structs_payloadp = kmem_zalloc(*structs_payload_lengthp,
1351 	    km_sleep_flag);
1352 	if (*structs_payloadp == NULL) {
1353 
1354 		IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L1,
1355 		    ibmf_saa_utils_unpack_payload_err,
1356 		    IBMF_TNF_ERROR, "", "ibmf_saa_utils_unpack_payload: %s,"
1357 		    " size = %d\n",
1358 		    tnf_string, msg, "could not allocate memory for payload",
1359 		    tnf_int, size, *structs_payload_lengthp);
1360 
1361 		*structs_payload_lengthp = 0;
1362 		return (IBMF_NO_MEMORY);
1363 	}
1364 
1365 
1366 	for (i = 0; i < num_records; i++) {
1367 
1368 		unpack_data_fn(
1369 		    (uchar_t *)buf_payload + (i * bytes_between_recs),
1370 		    (void *)((uchar_t *)*structs_payloadp + i *
1371 		    struct_size));
1372 	}
1373 
1374 	return (IBMF_SUCCESS);
1375 }
1376