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