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