1 /*
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34 
35 #if HAVE_CONFIG_H
36 #  include <config.h>
37 #endif /* HAVE_CONFIG_H */
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <inttypes.h>
44 #include <netinet/in.h>
45 
46 #include <mad.h>
47 #include <infiniband/common.h>
48 
49 void
mad_dump_int(char * buf,int bufsz,void * val,int valsz)50 mad_dump_int(char *buf, int bufsz, void *val, int valsz)
51 {
52 	switch (valsz) {
53 	case 1:
54 		snprintf(buf, bufsz, "%d", *(uint8_t *)val);
55 		break;
56 	case 2:
57 		snprintf(buf, bufsz, "%d", *(uint16_t *)val);
58 		break;
59 	case 3:
60 	case 4:
61 		snprintf(buf, bufsz, "%d", *(uint32_t *)val);
62 		break;
63 	case 5:
64 	case 6:
65 	case 7:
66 	case 8:
67 		snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *)val);
68 		break;
69 	default:
70 		IBWARN("bad int sz %d", valsz);
71 		buf[0] = 0;
72 	}
73 }
74 
75 void
mad_dump_uint(char * buf,int bufsz,void * val,int valsz)76 mad_dump_uint(char *buf, int bufsz, void *val, int valsz)
77 {
78 	switch (valsz) {
79 	case 1:
80 		snprintf(buf, bufsz, "%u", *(uint8_t *)val);
81 		break;
82 	case 2:
83 		snprintf(buf, bufsz, "%u", *(uint16_t *)val);
84 		break;
85 	case 3:
86 	case 4:
87 		snprintf(buf, bufsz, "%u", *(uint32_t *)val);
88 		break;
89 	case 5:
90 	case 6:
91 	case 7:
92 	case 8:
93 		snprintf(buf, bufsz, "%" PRIu64, *(uint64_t *)val);
94 		break;
95 	default:
96 		IBWARN("bad int sz %u", valsz);
97 		buf[0] = 0;
98 	}
99 }
100 
101 void
mad_dump_hex(char * buf,int bufsz,void * val,int valsz)102 mad_dump_hex(char *buf, int bufsz, void *val, int valsz)
103 {
104 	switch (valsz) {
105 	case 1:
106 		snprintf(buf, bufsz, "0x%02x", *(uint8_t *)val);
107 		break;
108 	case 2:
109 		snprintf(buf, bufsz, "0x%04x", *(uint16_t *)val);
110 		break;
111 	case 3:
112 		snprintf(buf, bufsz, "0x%06x", *(uint32_t *)val & 0xffffff);
113 		break;
114 	case 4:
115 		snprintf(buf, bufsz, "0x%08x", *(uint32_t *)val);
116 		break;
117 	case 5:
118 		snprintf(buf, bufsz, "0x%010" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffllu);
119 		break;
120 	case 6:
121 		snprintf(buf, bufsz, "0x%012" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffllu);
122 		break;
123 	case 7:
124 		snprintf(buf, bufsz, "0x%014" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffffllu);
125 		break;
126 	case 8:
127 		snprintf(buf, bufsz, "0x%016" PRIx64, *(uint64_t *)val);
128 		break;
129 	default:
130 		IBWARN("bad int sz %d", valsz);
131 		buf[0] = 0;
132 	}
133 }
134 
135 void
mad_dump_rhex(char * buf,int bufsz,void * val,int valsz)136 mad_dump_rhex(char *buf, int bufsz, void *val, int valsz)
137 {
138 	switch (valsz) {
139 	case 1:
140 		snprintf(buf, bufsz, "%02x", *(uint8_t *)val);
141 		break;
142 	case 2:
143 		snprintf(buf, bufsz, "%04x", *(uint16_t *)val);
144 		break;
145 	case 3:
146 		snprintf(buf, bufsz, "%06x", *(uint32_t *)val & 0xffffff);
147 		break;
148 	case 4:
149 		snprintf(buf, bufsz, "%08x", *(uint32_t *)val);
150 		break;
151 	case 5:
152 		snprintf(buf, bufsz, "%010" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffllu);
153 		break;
154 	case 6:
155 		snprintf(buf, bufsz, "%012" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffllu);
156 		break;
157 	case 7:
158 		snprintf(buf, bufsz, "%014" PRIx64, *(uint64_t *)val & (uint64_t) 0xffffffffffffffllu);
159 		break;
160 	case 8:
161 		snprintf(buf, bufsz, "%016" PRIx64, *(uint64_t *)val);
162 		break;
163 	default:
164 		IBWARN("bad int sz %d", valsz);
165 		buf[0] = 0;
166 	}
167 }
168 
169 void
mad_dump_linkwidth(char * buf,int bufsz,void * val,int valsz)170 mad_dump_linkwidth(char *buf, int bufsz, void *val, int valsz)
171 {
172 	int width = *(int *)val;
173 
174 	switch (width) {
175 	case 1:
176 		snprintf(buf, bufsz, "1X");
177 		break;
178 	case 2:
179 		snprintf(buf, bufsz, "4X");
180 		break;
181 	case 4:
182 		snprintf(buf, bufsz, "8X");
183 		break;
184 	case 8:
185 		snprintf(buf, bufsz, "12X");
186 		break;
187 	default:
188 		IBWARN("bad width %d", width);
189 		buf[0] = 0;
190 	}
191 }
192 
193 static void
dump_linkwidth(char * buf,int bufsz,int width)194 dump_linkwidth(char *buf, int bufsz, int width)
195 {
196 	int n = 0;
197 
198 	if (width & 0x1)
199 		n += snprintf(buf + n, bufsz - n, "1X or ");
200 	if (n < bufsz && (width & 0x2))
201 		n += snprintf(buf + n, bufsz - n, "4X or ");
202 	if (n < bufsz && (width & 0x4))
203 		n += snprintf(buf + n, bufsz - n, "8X or ");
204 	if (n < bufsz && (width & 0x8))
205 		n += snprintf(buf + n, bufsz - n, "12X or ");
206 
207 	if (n >= bufsz)
208 		return;
209 	else if (width == 0 || (width >> 4))
210 		snprintf(buf + n, bufsz - n, "undefined (%d)", width);
211 	else if (bufsz > 3)
212 		buf[n-4] = '\0';
213 }
214 
215 void
mad_dump_linkwidthsup(char * buf,int bufsz,void * val,int valsz)216 mad_dump_linkwidthsup(char *buf, int bufsz, void *val, int valsz)
217 {
218 	int width = *(int *)val;
219 
220 	dump_linkwidth(buf, bufsz, width);
221 
222 	switch(width) {
223 	case 1:
224 	case 3:
225 	case 7:
226 	case 11:
227 	case 15:
228 		break;
229 
230 	default:
231 		if (!(width >> 4))
232 			snprintf(buf + strlen(buf), bufsz - strlen(buf),
233 				 " (IBA extension)");
234 		break;
235 	}
236 }
237 
238 void
mad_dump_linkwidthen(char * buf,int bufsz,void * val,int valsz)239 mad_dump_linkwidthen(char *buf, int bufsz, void *val, int valsz)
240 {
241 	int width = *(int *)val;
242 
243 	dump_linkwidth(buf, bufsz, width);
244 }
245 
246 void
mad_dump_linkspeed(char * buf,int bufsz,void * val,int valsz)247 mad_dump_linkspeed(char *buf, int bufsz, void *val, int valsz)
248 {
249 	int speed = *(int *)val;
250 
251 	switch (speed) {
252 	case 1:
253 		snprintf(buf, bufsz, "2.5 Gbps");
254 		break;
255 	case 2:
256 		snprintf(buf, bufsz, "5.0 Gbps");
257 		break;
258 	case 4:
259 		snprintf(buf, bufsz, "10.0 Gbps");
260 		break;
261 	default:
262 		snprintf(buf, bufsz, "undefined (%d)", speed);
263 		break;
264 	}
265 }
266 
267 static void
dump_linkspeed(char * buf,int bufsz,int speed)268 dump_linkspeed(char *buf, int bufsz, int speed)
269 {
270 	int n = 0;
271 
272 	if (speed & 0x1)
273 		n += snprintf(buf + n, bufsz - n, "2.5 Gbps or ");
274 	if (n < bufsz && (speed & 0x2))
275 		n += snprintf(buf + n, bufsz - n, "5.0 Gbps or ");
276 	if (n < bufsz && (speed & 0x4))
277 		n += snprintf(buf + n, bufsz - n, "10.0 Gbps or ");
278 
279 	if (n >= bufsz)
280 		return;
281 	else if (speed == 0 || (speed >> 3)) {
282 		n += snprintf(buf + n, bufsz - n, "undefined (%d)", speed);
283 		if (n >= bufsz)
284 			return;
285 	} else if (bufsz > 3) {
286 		buf[n-4] = '\0';
287 		n -= 4;
288 	}
289 
290 	switch (speed) {
291 	case 1:
292 	case 3:
293 	case 5:
294 	case 7:
295 		break;
296 	default:
297 		if (!(speed >> 3))
298 			snprintf(buf + n, bufsz - n, " (IBA extension)");
299 		break;
300 	}
301 }
302 
303 void
mad_dump_linkspeedsup(char * buf,int bufsz,void * val,int valsz)304 mad_dump_linkspeedsup(char *buf, int bufsz, void *val, int valsz)
305 {
306 	int speed = *(int *)val;
307 
308 	dump_linkspeed(buf, bufsz, speed);
309 }
310 
311 void
mad_dump_linkspeeden(char * buf,int bufsz,void * val,int valsz)312 mad_dump_linkspeeden(char *buf, int bufsz, void *val, int valsz)
313 {
314 	int speed = *(int *)val;
315 
316 	dump_linkspeed(buf, bufsz, speed);
317 }
318 
319 void
mad_dump_portstate(char * buf,int bufsz,void * val,int valsz)320 mad_dump_portstate(char *buf, int bufsz, void *val, int valsz)
321 {
322 	int state = *(int *)val;
323 
324 	switch (state) {
325 	case 0:
326 		snprintf(buf, bufsz, "NoChange");
327 		break;
328 	case 1:
329 		snprintf(buf, bufsz, "Down");
330 		break;
331 	case 2:
332 		snprintf(buf, bufsz, "Initialize");
333 		break;
334 	case 3:
335 		snprintf(buf, bufsz, "Armed");
336 		break;
337 	case 4:
338 		snprintf(buf, bufsz, "Active");
339 		break;
340 	default:
341 		snprintf(buf, bufsz, "?(%d)", state);
342 	}
343 }
344 
345 void
mad_dump_linkdowndefstate(char * buf,int bufsz,void * val,int valsz)346 mad_dump_linkdowndefstate(char *buf, int bufsz, void *val, int valsz)
347 {
348 	int state = *(int *)val;
349 
350 	switch(state) {
351 	case 0:
352 		snprintf(buf, bufsz, "NoChange");
353 		break;
354 	case 1:
355 		snprintf(buf, bufsz, "Sleep");
356 		break;
357 	case 2:
358 		snprintf(buf, bufsz, "Polling");
359 		break;
360 	default:
361 		snprintf(buf, bufsz, "?(%d)", state);
362 		break;
363 	}
364 }
365 
366 void
mad_dump_physportstate(char * buf,int bufsz,void * val,int valsz)367 mad_dump_physportstate(char *buf, int bufsz, void *val, int valsz)
368 {
369 	int state = *(int *)val;
370 
371 	switch (state) {
372 	case 0:
373 		snprintf(buf, bufsz, "NoChange");
374 		break;
375 	case 1:
376 		snprintf(buf, bufsz, "Sleep");
377 		break;
378 	case 2:
379 		snprintf(buf, bufsz, "Polling");
380 		break;
381 	case 3:
382 		snprintf(buf, bufsz, "Disabled");
383 		break;
384 	case 4:
385 		snprintf(buf, bufsz, "PortConfigurationTraining");
386 		break;
387 	case 5:
388 		snprintf(buf, bufsz, "LinkUp");
389 		break;
390 	case 6:
391 		snprintf(buf, bufsz, "LinkErrorRecovery");
392 		break;
393 	case 7:
394 		snprintf(buf, bufsz, "PhyTest");
395 		break;
396 	default:
397 		snprintf(buf, bufsz, "?(%d)", state);
398 	}
399 }
400 
401 void
mad_dump_mtu(char * buf,int bufsz,void * val,int valsz)402 mad_dump_mtu(char *buf, int bufsz, void *val, int valsz)
403 {
404 	int mtu = *(int *)val;
405 
406 	switch (mtu) {
407 	case 1:
408 		snprintf(buf, bufsz, "256");
409 		break;
410 	case 2:
411 		snprintf(buf, bufsz, "512");
412 		break;
413 	case 3:
414 		snprintf(buf, bufsz, "1024");
415 		break;
416 	case 4:
417 		snprintf(buf, bufsz, "2048");
418 		break;
419 	case 5:
420 		snprintf(buf, bufsz, "4096");
421 		break;
422 	default:
423 		snprintf(buf, bufsz, "?(%d)", mtu);
424 		buf[0] = 0;
425 	}
426 }
427 
428 void
mad_dump_vlcap(char * buf,int bufsz,void * val,int valsz)429 mad_dump_vlcap(char *buf, int bufsz, void *val, int valsz)
430 {
431 	int vlcap = *(int *)val;
432 
433 	switch (vlcap) {
434 	case 1:
435 		snprintf(buf, bufsz, "VL0");
436 		break;
437 	case 2:
438 		snprintf(buf, bufsz, "VL0-1");
439 		break;
440 	case 3:
441 		snprintf(buf, bufsz, "VL0-3");
442 		break;
443 	case 4:
444 		snprintf(buf, bufsz, "VL0-7");
445 		break;
446 	case 5:
447 		snprintf(buf, bufsz, "VL0-14");
448 		break;
449 	default:
450 		snprintf(buf, bufsz, "?(%d)", vlcap);
451 	}
452 }
453 
454 void
mad_dump_opervls(char * buf,int bufsz,void * val,int valsz)455 mad_dump_opervls(char *buf, int bufsz, void *val, int valsz)
456 {
457 	int opervls = *(int *)val;
458 
459 	switch (opervls) {
460 	case 0:
461 		snprintf(buf, bufsz, "No change");
462 		break;
463 	case 1:
464 		snprintf(buf, bufsz, "VL0");
465 		break;
466 	case 2:
467 		snprintf(buf, bufsz, "VL0-1");
468 		break;
469 	case 3:
470 		snprintf(buf, bufsz, "VL0-3");
471 		break;
472 	case 4:
473 		snprintf(buf, bufsz, "VL0-7");
474 		break;
475 	case 5:
476 		snprintf(buf, bufsz, "VL0-14");
477 		break;
478 	default:
479 		snprintf(buf, bufsz, "?(%d)", opervls);
480 	}
481 }
482 
483 void
mad_dump_portcapmask(char * buf,int bufsz,void * val,int valsz)484 mad_dump_portcapmask(char *buf, int bufsz, void *val, int valsz)
485 {
486 	unsigned mask = *(unsigned *)val;
487 	char *s = buf;
488 
489 	s += sprintf(s, "0x%x\n", mask);
490 	if (mask & (1 << 1))
491 		s += sprintf(s, "\t\t\t\tIsSM\n");
492 	if (mask & (1 << 2))
493 		s += sprintf(s, "\t\t\t\tIsNoticeSupported\n");
494 	if (mask & (1 << 3))
495 		s += sprintf(s, "\t\t\t\tIsTrapSupported\n");
496 	if (mask & (1 << 5))
497 		s += sprintf(s, "\t\t\t\tIsAutomaticMigrationSupported\n");
498 	if (mask & (1 << 6))
499 		s += sprintf(s, "\t\t\t\tIsSLMappingSupported\n");
500 	if (mask & (1 << 7))
501 		s += sprintf(s, "\t\t\t\tIsMKeyNVRAM\n");
502 	if (mask & (1 << 8))
503 		s += sprintf(s, "\t\t\t\tIsPKeyNVRAM\n");
504 	if (mask & (1 << 9))
505 		s += sprintf(s, "\t\t\t\tIsLedInfoSupported\n");
506 	if (mask & (1 << 10))
507 		s += sprintf(s, "\t\t\t\tIsSMdisabled\n");
508 	if (mask & (1 << 11))
509 		s += sprintf(s, "\t\t\t\tIsSystemImageGUIDsupported\n");
510 	if (mask & (1 << 12))
511 		s += sprintf(s, "\t\t\t\tIsPkeySwitchExternalPortTrapSupported\n");
512 	if (mask & (1 << 16))
513 		s += sprintf(s, "\t\t\t\tIsCommunicatonManagementSupported\n");
514 	if (mask & (1 << 17))
515 		s += sprintf(s, "\t\t\t\tIsSNMPTunnelingSupported\n");
516 	if (mask & (1 << 18))
517 		s += sprintf(s, "\t\t\t\tIsReinitSupported\n");
518 	if (mask & (1 << 19))
519 		s += sprintf(s, "\t\t\t\tIsDeviceManagementSupported\n");
520 	if (mask & (1 << 20))
521 		s += sprintf(s, "\t\t\t\tIsVendorClassSupported\n");
522 	if (mask & (1 << 21))
523 		s += sprintf(s, "\t\t\t\tIsDRNoticeSupported\n");
524 	if (mask & (1 << 22))
525 		s += sprintf(s, "\t\t\t\tIsCapabilityMaskNoticeSupported\n");
526 	if (mask & (1 << 23))
527 		s += sprintf(s, "\t\t\t\tIsBootManagementSupported\n");
528 	if (mask & (1 << 24))
529 		s += sprintf(s, "\t\t\t\tIsLinkRoundTripLatencySupported\n");
530 	if (mask & (1 << 25))
531 		s += sprintf(s, "\t\t\t\tIsClientRegistrationSupported\n");
532 	if (mask & (1 << 26))
533 		s += sprintf(s, "\t\t\t\tIsOtherLocalChangesNoticeSupported\n");
534 	if (mask & (1 << 27))
535 		s += sprintf(s, "\t\t\t\tIsLinkSpeedWidthPairsTableSupported\n");
536 
537 	if (s != buf)
538 		*(--s) = 0;
539 }
540 
541 void
mad_dump_bitfield(char * buf,int bufsz,void * val,int valsz)542 mad_dump_bitfield(char *buf, int bufsz, void *val, int valsz)
543 {
544 	snprintf(buf, bufsz, "0x%x", *(uint32_t *)val);
545 }
546 
547 void
mad_dump_array(char * buf,int bufsz,void * val,int valsz)548 mad_dump_array(char *buf, int bufsz, void *val, int valsz)
549 {
550 	uint8_t *p = val, *e;
551 	char *s = buf;
552 
553 	if (bufsz < valsz*2)
554 		valsz = bufsz/2;
555 
556 	for (p = val, e = p + valsz; p < e; p++, s += 2)
557 		sprintf(s, "%02x", *p);
558 }
559 
560 void
mad_dump_string(char * buf,int bufsz,void * val,int valsz)561 mad_dump_string(char *buf, int bufsz, void *val, int valsz)
562 {
563 	if (bufsz < valsz)
564 		valsz = bufsz;
565 
566 	snprintf(buf, valsz, "'%s'", (char *)val);
567 }
568 
569 void
mad_dump_node_type(char * buf,int bufsz,void * val,int valsz)570 mad_dump_node_type(char *buf, int bufsz, void *val, int valsz)
571 {
572 	int nodetype = *(int*)val;
573 
574 	switch (nodetype) {
575  	case 1:
576 		snprintf(buf, bufsz, "Channel Adapter");
577 		break;
578  	case 2:
579 		snprintf(buf, bufsz, "Switch");
580 		break;
581  	case 3:
582 		snprintf(buf, bufsz, "Router");
583 		break;
584 	default:
585 		snprintf(buf, bufsz, "?(%d)?", nodetype);
586 		break;
587 	}
588 }
589 
590 #define IB_MAX_NUM_VLS 16
591 #define IB_MAX_NUM_VLS_TO_U8 ((IB_MAX_NUM_VLS)/2)
592 
593 typedef struct _ib_slvl_table {
594 	uint8_t vl_by_sl_num[IB_MAX_NUM_VLS_TO_U8];
595 } ib_slvl_table_t;
596 
597 static inline void
ib_slvl_get_i(ib_slvl_table_t * tbl,int i,uint8_t * vl)598 ib_slvl_get_i(ib_slvl_table_t *tbl, int i, uint8_t *vl)
599 {
600 	*vl = (tbl->vl_by_sl_num[i >> 1] >> ((!(i&1)) << 2)) & 0xf;
601 }
602 
603 #define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32
604 
605 typedef struct _ib_vl_arb_table {
606 	struct {
607 		uint8_t res_vl;
608 		uint8_t weight;
609 	} vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];
610 } __attribute__((packed)) ib_vl_arb_table_t;
611 
612 static inline void
ib_vl_arb_get_vl(uint8_t res_vl,uint8_t * const vl)613 ib_vl_arb_get_vl(uint8_t res_vl, uint8_t *const vl )
614 {
615 	*vl = res_vl & 0x0F;
616 }
617 
618 void
mad_dump_sltovl(char * buf,int bufsz,void * val,int valsz)619 mad_dump_sltovl(char *buf, int bufsz, void *val, int valsz)
620 {
621 	ib_slvl_table_t* p_slvl_tbl = val;
622 	uint8_t vl;
623 	int i, n = 0;
624 	n = snprintf(buf, bufsz, "|");
625 	for (i = 0; i < 16; i++) {
626 		ib_slvl_get_i(p_slvl_tbl, i, &vl);
627 		n += snprintf(buf + n, bufsz - n, "%2u|", vl);
628 		if (n >= bufsz)
629 			break;
630 	}
631 	snprintf(buf + n, bufsz - n, "\n");
632 }
633 
634 void
mad_dump_vlarbitration(char * buf,int bufsz,void * val,int num)635 mad_dump_vlarbitration(char *buf, int bufsz, void *val, int num)
636 {
637 	ib_vl_arb_table_t* p_vla_tbl = val;
638 	unsigned i, n;
639 	uint8_t vl;
640 
641 	num /= sizeof(p_vla_tbl->vl_entry[0]);
642 
643 	n = snprintf(buf, bufsz, "\nVL    : |");
644 	if (n >= bufsz)
645 		return;
646 	for (i = 0; i < num; i++) {
647 		ib_vl_arb_get_vl(p_vla_tbl->vl_entry[i].res_vl, &vl);
648 		n += snprintf(buf + n, bufsz - n, "0x%-2X|", vl);
649 		if (n >= bufsz)
650 			return;
651 	}
652 
653 	n += snprintf(buf + n, bufsz - n, "\nWEIGHT: |");
654 	if (n >= bufsz)
655 		return;
656 	for (i = 0; i < num; i++) {
657 		n += snprintf(buf + n, bufsz - n, "0x%-2X|",
658 			      p_vla_tbl->vl_entry[i].weight);
659 		if (n >= bufsz)
660 			return;
661 	}
662 
663 	snprintf(buf + n, bufsz - n, "\n");
664 }
665 
666 static int
_dump_fields(char * buf,int bufsz,void * data,int start,int end)667 _dump_fields(char *buf, int bufsz, void *data, int start, int end)
668 {
669 	char val[64];
670 	char *s = buf;
671 	int n, field;
672 
673 	for (field = start; field < end && bufsz > 0; field++) {
674 		mad_decode_field(data, field, val);
675 		if (!mad_dump_field(field, s, bufsz, val))
676 			return -1;
677 		n = strlen(s);
678 		s += n;
679 		*s++ = '\n';
680 		*s = 0;
681 		n++;
682 		bufsz -= n;
683 	}
684 
685 	return s - buf;
686 }
687 
688 void
mad_dump_nodedesc(char * buf,int bufsz,void * val,int valsz)689 mad_dump_nodedesc(char *buf, int bufsz, void *val, int valsz)
690 {
691 	strncpy(buf, val, bufsz);
692 
693 	if (valsz < bufsz)
694 		buf[valsz] = 0;
695 }
696 
697 void
mad_dump_nodeinfo(char * buf,int bufsz,void * val,int valsz)698 mad_dump_nodeinfo(char *buf, int bufsz, void *val, int valsz)
699 {
700 	_dump_fields(buf, bufsz, val, IB_NODE_FIRST_F, IB_NODE_LAST_F);
701 }
702 
703 void
mad_dump_portinfo(char * buf,int bufsz,void * val,int valsz)704 mad_dump_portinfo(char *buf, int bufsz, void *val, int valsz)
705 {
706 	_dump_fields(buf, bufsz, val, IB_PORT_FIRST_F, IB_PORT_LAST_F);
707 }
708 
709 void
mad_dump_portstates(char * buf,int bufsz,void * val,int valsz)710 mad_dump_portstates(char *buf, int bufsz, void *val, int valsz)
711 {
712 	_dump_fields(buf, bufsz, val, IB_PORT_STATE_F, IB_PORT_LINK_DOWN_DEF_F);
713 }
714 
715 void
mad_dump_switchinfo(char * buf,int bufsz,void * val,int valsz)716 mad_dump_switchinfo(char *buf, int bufsz, void *val, int valsz)
717 {
718 	_dump_fields(buf, bufsz, val, IB_SW_FIRST_F, IB_SW_LAST_F);
719 }
720 
721 void
mad_dump_perfcounters(char * buf,int bufsz,void * val,int valsz)722 mad_dump_perfcounters(char *buf, int bufsz, void *val, int valsz)
723 {
724 	_dump_fields(buf, bufsz, val, IB_PC_FIRST_F, IB_PC_LAST_F);
725 }
726 
727 void
mad_dump_perfcounters_ext(char * buf,int bufsz,void * val,int valsz)728 mad_dump_perfcounters_ext(char *buf, int bufsz, void *val, int valsz)
729 {
730 	_dump_fields(buf, bufsz, val, IB_PC_EXT_FIRST_F, IB_PC_EXT_LAST_F);
731 }
732 
733 /************************/
734 
735 char *
_mad_dump_val(ib_field_t * f,char * buf,int bufsz,void * val)736 _mad_dump_val(ib_field_t *f, char *buf, int bufsz, void *val)
737 {
738 	f->def_dump_fn(buf, bufsz, val, ALIGN(f->bitlen, 8) / 8);
739 	buf[bufsz - 1] = 0;
740 
741 	return buf;
742 }
743 
744 char *
_mad_dump_field(ib_field_t * f,char * name,char * buf,int bufsz,void * val)745 _mad_dump_field(ib_field_t *f, char *name, char *buf, int bufsz, void *val)
746 {
747 	char dots[128];
748 	int l, n;
749 
750 	if (bufsz <= 32)
751 		return 0;		/* buf too small */
752 
753 	if (!name)
754 		name = f->name;
755 
756 	l = strlen(name);
757 	if (l < 32) {
758 		memset(dots, '.', 32 - l);
759 		dots[32 - l] = 0;
760 	}
761 
762 	n = snprintf(buf, bufsz, "%s:%s", name, dots);
763 	_mad_dump_val(f, buf + n, bufsz - n, val);
764 	buf[bufsz - 1] = 0;
765 
766 	return buf;
767 }
768 
769 int
_mad_dump(ib_mad_dump_fn * fn,char * name,void * val,int valsz)770 _mad_dump(ib_mad_dump_fn *fn, char *name, void *val, int valsz)
771 {
772 	ib_field_t f = { .def_dump_fn = fn, .bitlen = valsz * 8};
773 	char buf[512];
774 
775 	return printf("%s\n", _mad_dump_field(&f, name, buf, sizeof buf, val));
776 }
777 
778 int
_mad_print_field(ib_field_t * f,char * name,void * val,int valsz)779 _mad_print_field(ib_field_t *f, char *name, void *val, int valsz)
780 {
781 	return _mad_dump(f->def_dump_fn, name ? name : f->name, val, valsz ? valsz : ALIGN(f->bitlen, 8) / 8);
782 }
783