blob: 5a34961e6b820eb2b61a307b44c99a794985fc0f [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include <bcmos_system.h>
31#include <bal_obj.h>
32#include <bcmcli.h>
33#include "bal_api_cli_helpers.h"
34
35typedef enum
36{
37 BCMBAL_APICLI_OUTPUT_STYLE_STD,
38 BCMBAL_APICLI_OUTPUT_STYLE_C_INIT
39} bcmbal_apicli_output_style;
40
41typedef struct
42{
43 const bcmbal_apicli_type_descr *type;
44 void *data;
45 uint8_t bit;
46} bcmbal_apicli_presence_mask_info;
47
48static bcmos_errno bcmbal_apicli_dump_array(
49 bcmcli_session *session,
50 const bcmbal_apicli_type_descr *td,
51 void *data,
52 uint32_t size,
53 const char *name,
54 bcmbal_apicli_output_style style,
55 const bcmbal_apicli_presence_mask_info *presence_mask);
56
57static bcmos_errno bcmbal_apicli_read_snum(
58 bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, int64_t *n)
59{
60 switch (td->size)
61 {
62 case 1:
63 {
64 int8_t n1 = *(int8_t *)data;
65 *n = n1;
66 break;
67 }
68 case 2:
69 {
70 int16_t n2 = *(int16_t *)data;
71 *n = n2;
72 break;
73 }
74 case 4:
75 {
76 int32_t n4 = *(int32_t *)data;
77 *n = n4;
78 break;
79 }
80 case 8:
81 {
82 memcpy(n, data, sizeof(*n));
83 break;
84 }
85 default:
86 bcmcli_print(session, "*** number size %u is not supported\n", td->size);
87 return BCM_ERR_NOT_SUPPORTED;
88 }
89 return BCM_ERR_OK;
90}
91
92static bcmos_errno bcmbal_apicli_read_unum(
93 bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, uint64_t *n)
94{
95 switch (td->size)
96 {
97 case 1:
98 {
99 uint8_t n1 = *(uint8_t *)data;
100 *n = n1;
101 break;
102 }
103 case 2:
104 {
105 uint16_t n2 = *(uint16_t *)data;
106 *n = n2;
107 break;
108 }
109 case 4:
110 {
111 uint32_t n4 = *(uint32_t *)data;
112 *n = n4;
113 break;
114 }
115 case 8:
116 {
117 memcpy(n, data, sizeof(*n));
118 break;
119 }
120 default:
121 bcmcli_print(session, "*** number size %u is not supported\n", td->size);
122 return BCM_ERR_NOT_SUPPORTED;
123 }
124 return BCM_ERR_OK;
125}
126
127static void bcmbal_apicli_strcat_upper(char *dest, uint32_t dest_len, const char *src, uint32_t src_len)
128{
129 uint32_t src_idx;
130 uint32_t dest_idx;
131
132 for (dest_idx = 0; dest_idx < dest_len - 1; ++dest_idx)
133 {
134 if (dest[dest_idx] == '\0')
135 {
136 break;
137 }
138 }
139
140 for (src_idx = 0; src_idx < src_len && dest_idx < dest_len - 1; ++src_idx, ++dest_idx)
141 {
142 dest[dest_idx] = src[src_idx];
143 if (dest[dest_idx] >= 'a' && dest[dest_idx] <= 'z')
144 {
145 dest[dest_idx] = 'A' + (dest[dest_idx] - 'a');
146 }
147 }
148
149 dest[dest_idx] = '\0';
150}
151
152static const char *bcmbal_apicli_get_c_enum_id(const bcmbal_apicli_type_descr *td, const char *name)
153{
154 static char full_name_buf[256];
155 full_name_buf[0] = '\0';
156 bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), td->name, strlen(td->name));
157 bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), "_", 1);
158 bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), name, strlen(name));
159 return full_name_buf;
160}
161
162static bcmos_errno bcmbal_apicli_dump_simple_data_type(
163 bcmcli_session *session,
164 const bcmbal_apicli_type_descr *td,
165 void *data,
166 const char *name,
167 bcmbal_apicli_output_style style)
168{
169 bcmos_errno rc = BCM_ERR_OK;
170
171 switch (td->base_type)
172 {
173 case BCMBAL_APICLI_BASE_TYPE_ID_SNUM: /* signed number */
174 {
175 int64_t n = 0;
176 rc = bcmbal_apicli_read_snum(session, td, data, &n);
177 bcmcli_print(session, "%lld", (long long)n);
178 break;
179 }
180
181 case BCMBAL_APICLI_BASE_TYPE_ID_UNUM: /* unsigned number */
182 {
183 uint64_t n = 0;
184 rc = bcmbal_apicli_read_unum(session, td, data, &n);
185 bcmcli_print(session, "%llu", (unsigned long long)n);
186 break;
187 }
188
189 case BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX: /* unsigned number printed in hex */
190 {
191 uint64_t n = 0;
192 rc = bcmbal_apicli_read_unum(session, td, data, &n);
193 bcmcli_print(session, "0x%llx", (unsigned long long)n);
194 break;
195 }
196
197 case BCMBAL_APICLI_BASE_TYPE_ID_FLOAT: /* floating-point number */
198 {
199 if (td->size == sizeof(float))
200 {
201 bcmcli_print(session, "%f", *(float *)data);
202 }
203 else if (td->size == sizeof(double))
204 {
205 bcmcli_print(session, "%f", *(double *)data);
206 }
207 else
208 {
209 bcmcli_print(session, "*** floating-point number of width %u is not supported\n", td->size);
210 rc = BCM_ERR_NOT_SUPPORTED;
211 }
212 break;
213 }
214
215 case BCMBAL_APICLI_BASE_TYPE_ID_BOOL:
216 {
217 const char *no_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_FALSE" : "no";
218 const char *yes_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_TRUE" : "yes";
219 uint64_t n = 0;
220 rc = bcmbal_apicli_read_unum(session, td, data, &n);
221 bcmcli_print(session, "%s", n == 0 ? no_str : yes_str);
222 break;
223 }
224
225 case BCMBAL_APICLI_BASE_TYPE_ID_STRING: /* string */
226 {
227 if (td->size == 0)
228 {
229 bcmcli_print(session, "\"%s\"", (char *)data);
230 }
231 else
232 {
233 /* we know the size of the buffer */
234 bcmcli_print(session, "\"%.*s\"", td->size, (char *)data);
235 }
236 break;
237 }
238
239 case BCMBAL_APICLI_BASE_TYPE_ID_IPV4: /* IPv4 address */
240 {
241 uint32_t ip;
242 memcpy(&ip, data, sizeof(ip));
243 bcmcli_print(
244 session,
245 style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "{ %d,%d,%d,%d }" : "%d.%d.%d.%d",
246 (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
247 break;
248 }
249
250 case BCMBAL_APICLI_BASE_TYPE_ID_MAC: /* MAC address */
251 {
252 bcmos_mac_address mac;
253 memcpy(mac.u8, data, sizeof(mac.u8));
254 bcmcli_print(
255 session,
256 style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ?
257 "{{ 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x }}" :
258 "%02x:%02x:%02x:%02x:%02x:%02x",
259 mac.u8[0], mac.u8[1], mac.u8[2], mac.u8[3], mac.u8[4], mac.u8[5]);
260 break;
261 }
262
263 case BCMBAL_APICLI_BASE_TYPE_ID_ENUM: /* enum */
264 {
265 uint64_t n = 0;
266 const char *s;
267 rc = bcmbal_apicli_read_unum(session, td, data, &n);
268 BUG_ON(td->x.e == NULL);
269 s = bcmcli_enum_stringval(td->x.e, (long)n);
270 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
271 {
272 s = bcmbal_apicli_get_c_enum_id(td, s);
273 }
274 bcmcli_print(session, "%s", s);
275 break;
276 }
277
278 case BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK:
279 {
280 uint64_t n = 0;
281 const char *s;
282 const char *none = NULL;
283 bcmcli_enum_val *value = td->x.e;
284 bcmos_bool first = BCMOS_TRUE;
285 BUG_ON(value == NULL);
286 rc = bcmbal_apicli_read_unum(session, td, data, &n);
287 while (value->name != NULL)
288 {
289 if (value->val == 0)
290 {
291 none = value->name;
292 }
293 if ((value->val & n) != 0)
294 {
295 s = value->name;
296 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
297 {
298 s = bcmbal_apicli_get_c_enum_id(td, s);
299 }
300 bcmcli_print(session, "%s%s", first ? "" : (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "|" : BCMCLI_ENUM_MASK_DEL_STR), s);
301 first = BCMOS_FALSE;
302 n -= value->val;
303 }
304 ++value;
305 }
306 if (first)
307 {
308 bcmcli_print(session, "%s", (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT) || (NULL == none) ? "0" : none);
309 }
310 break;
311 }
312
313 default:
314 bcmcli_print(session, "*** type %d is not supported\n", (int)td->base_type);
315 rc = BCM_ERR_NOT_SUPPORTED;
316 break;
317 }
318 return rc;
319}
320
321
322/* calculate number of enum values */
323static int bcmbal_apicli_get_num_enum_vals(const bcmcli_enum_val *vals)
324{
325 const bcmcli_enum_val *v = vals;
326 while (v && v->name)
327 {
328 ++v;
329 }
330 return (v - vals);
331}
332
333/* helper function to skip the "u." in front of union field names */
334static inline const char *bcmbal_apicli_skip_union_prefix(const char *name)
335{
336 if (name[0] == 'u' && name[1] == '.')
337 {
338 name += 2;
339 }
340 return name;
341}
342
343static bcmos_bool bcmbal_apicli_is_value_set(
344 bcmcli_session *session,
345 const bcmbal_apicli_presence_mask_info *presence_mask)
346{
347 uint64_t pm_value_num = 0;
348 if (!presence_mask || !presence_mask->type)
349 {
350 /* no presence mask - all values are implicitly set */
351 return BCMOS_TRUE;
352 }
353 bcmbal_apicli_read_unum(session, presence_mask->type, presence_mask->data, &pm_value_num);
354 return ((pm_value_num >> presence_mask->bit) & 1) != 0;
355}
356
357/* Dump data type */
358static bcmos_errno bcmbal_apicli_dump_data_type(
359 bcmcli_session *session,
360 const bcmbal_apicli_type_descr *td,
361 void *data,
362 const char *name,
363 uint32_t num_entries,
364 uint32_t entry_size,
365 bcmbal_apicli_output_style style,
366 const bcmbal_apicli_presence_mask_info *presence_mask)
367{
368 bcmos_errno rc = BCM_ERR_OK;
369
370 switch (td->base_type)
371 {
372 case BCMBAL_APICLI_BASE_TYPE_ID_STRUCT:
373 {
374 uint16_t f;
375 char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
376 if (!td->x.s.num_fields)
377 return 0;
378 BUG_ON(!td->x.s.fields);
379 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
380 {
381 bcmcli_print(session, "{ ");
382 }
383 for (f = 0; f < td->x.s.num_fields; f++)
384 {
385 const bcmbal_apicli_field_descr *fld = &td->x.s.fields[f];
386 void *fdata = (void *)((long)data + fld->offset);
387 bcmbal_apicli_presence_mask_info field_pm = {};
388 if (((td->x.s.fields[0].flags & BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK) != 0) &&
389 style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
390 {
391 /* If the struct has a presence mask, skip the presence mask field itself, then record the position
392 * of the presence mask so we can check it later for each entry. */
393 if (f == 0)
394 {
395 continue;
396 }
397
398 field_pm.type = td->x.s.fields[0].type;
399 field_pm.data = (uint8_t *)data + td->x.s.fields[0].offset;
400 field_pm.bit = (uint8_t)(f - 1);
401 }
402 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT && f > 0)
403 {
404 bcmcli_print(session, ", ");
405 }
406 bcmcli_strncpy(full_name, name, sizeof(full_name));
407 bcmcli_strncat(full_name, ".", sizeof(full_name));
408 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
409 rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, &field_pm);
410 }
411 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
412 {
413 bcmcli_print(session, " }");
414 }
415 break;
416 }
417
418 case BCMBAL_APICLI_BASE_TYPE_ID_UNION:
419 {
420 /* Print fields up to selector, then selector, then selected sub-structure */
421 uint16_t f;
422 char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
423 const bcmbal_apicli_field_descr *fld;
424 void *fdata;
425 int64_t selector_val = 0;
426 int num_union_vals;
427
428 if (!td->x.u.num_common_fields)
429 return 0;
430 BUG_ON(!td->x.u.common_fields);
431 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
432 {
433 bcmcli_print(session, "{ ");
434 }
435 /* Common fields, including selector */
436 for (f = 0; f <= td->x.u.classifier_idx && !rc; f++)
437 {
438 fld = &td->x.u.common_fields[f];
439 fdata = (void *)((long)data + fld->offset);
440
441 bcmcli_strncpy(full_name, name, sizeof(full_name));
442 if (fld->name && strlen(fld->name))
443 {
444 bcmcli_strncat(full_name, ".", sizeof(full_name));
445 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
446 }
447 rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
448 if (f == td->x.u.classifier_idx)
449 {
450 rc = rc ? rc : bcmbal_apicli_read_snum(session, fld->type, fdata, &selector_val);
451 }
452 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
453 {
454 bcmcli_print(session, ", ");
455 }
456 }
457 if (rc)
458 {
459 bcmcli_print(session, "***internal error when dumping field %s\n",
460 td->x.u.common_fields[f].name);
461 return rc;
462 }
463
464 num_union_vals = bcmbal_apicli_get_num_enum_vals(td->x.u.common_fields[td->x.u.classifier_idx].type->x.e);
465 if ((unsigned)selector_val >= num_union_vals)
466 {
467 bcmcli_print(session, "***invalid union selector value %lld\n", (long long)selector_val);
468 return BCM_ERR_INTERNAL;
469 }
470
471 /* Common fields following selector */
472 for (; f < td->x.u.num_common_fields; f++)
473 {
474 fld = &td->x.u.common_fields[f];
475 fdata = (void *)((long)data + fld->offset);
476
477 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
478 {
479 bcmcli_print(session, ", ");
480 }
481 bcmcli_strncpy(full_name, name, sizeof(full_name));
482 if (fld->name && strlen(fld->name))
483 {
484 bcmcli_strncat(full_name, ".", sizeof(full_name));
485 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
486 }
487 rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
488 }
489
490 /* Selected field */
491 fld = &td->x.u.union_fields[selector_val];
492 if (fld->type)
493 {
494 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
495 {
496 bcmcli_print(session, "{ .%s = ", bcmbal_apicli_skip_union_prefix(fld->name));
497 }
498 fdata = (void *)((long)data + fld->offset);
499
500 bcmcli_strncpy(full_name, name, sizeof(full_name));
501 if (fld->name && strlen(fld->name))
502 {
503 bcmcli_strncat(full_name, ".", sizeof(full_name));
504 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
505 }
506 rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
507 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
508 {
509 bcmcli_print(session, " }");
510 }
511 }
512 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
513 {
514 bcmcli_print(session, " }");
515 }
516 break;
517 }
518
519 case BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED: /* fixed array */
520 {
521 rc = bcmbal_apicli_dump_array(session, td->x.arr_fixed.elem_type, data, td->x.arr_fixed.size, name, style, presence_mask);
522 break;
523 }
524
525 case BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN: /* dynamic array that should be printed as buffer */
526 {
527 /* Read length */
528 uint32_t array_size;
529 long base_ptr;
530
531 switch (td->x.arr_dyn.len_size )
532 {
533 case 1: array_size = *(uint8_t *)data; break;
534 case 2: array_size = *(uint16_t *)data; break;
535 case 4: array_size = *(uint32_t *)data; break;
536 default:
537 bcmcli_print(session,
538 "*** %s: dyn array len_size %u is not supported\n", name, td->x.arr_dyn.len_size);
539 return BCM_ERR_NOT_SUPPORTED;
540 }
541 base_ptr = BCMOS_ROUND_UP((long)data + td->x.arr_dyn.len_size, sizeof(void *));
542 BUG_ON(!base_ptr);
543 data = *(void **)base_ptr;
544 rc = bcmbal_apicli_dump_array(session, td->x.arr_dyn.elem_type, data, array_size, name, style, presence_mask);
545 break;
546 }
547
548 default:
549 {
550 /* Finally! Simple type that maps to a single CLI parameter */
551 int n;
552 bcmbal_apicli_presence_mask_info local_pm;
553
554 /* If we have a single value and that value is not included in the presence mask, just skip it entirely */
555 if (num_entries == 1 && !bcmbal_apicli_is_value_set(session, presence_mask))
556 {
557 break;
558 }
559
560 if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
561 {
562 if (name)
563 {
564 bcmcli_print(session, " %s=", name);
565 }
566 if (!num_entries)
567 {
568 bcmcli_print(session, BCMCLI_ARRAY_EMPTY);
569 }
570 }
571
572 /* Dump simple value or array of simple values */
573 local_pm = presence_mask ? *presence_mask : (bcmbal_apicli_presence_mask_info){};
574 for (n = 0; n < num_entries; n++)
575 {
576 if (n)
577 {
578 bcmcli_print(session, ",");
579 }
580
581 /* If we have a presence mask, make sure to print a special token if the value is unset */
582 if (bcmbal_apicli_is_value_set(session, &local_pm))
583 {
584 rc = bcmbal_apicli_dump_simple_data_type(session, td, data, name, style);
585 }
586 else
587 {
588 bcmcli_print(session, BCMCLI_PARM_NO_VALUE);
589 }
590
591 data = (void *)((long)data + entry_size);
592 local_pm.data = (void *)((long)local_pm.data + entry_size);
593 }
594 if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
595 {
596 bcmcli_print(session, "\n");
597 }
598 break;
599 }
600 }
601 return rc;
602}
603
604/* Dump array */
605static bcmos_errno bcmbal_apicli_dump_array(
606 bcmcli_session *session,
607 const bcmbal_apicli_type_descr *td,
608 void *data,
609 uint32_t size,
610 const char *name,
611 bcmbal_apicli_output_style style,
612 const bcmbal_apicli_presence_mask_info *presence_mask)
613{
614 bcmos_errno rc = BCM_ERR_OK;
615
616 /* Print as buffer or element by element ? */
617 if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
618 {
619 bcmcli_print(session, "{ ");
620 rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
621 bcmcli_print(session, " }");
622 }
623 else if ((td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM ||
624 td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX) && td->size == 1)
625 {
626 if (bcmbal_apicli_is_value_set(session, presence_mask))
627 {
628 bcmcli_print(session, " %s=\n", name);
629 bcmcli_session_hexdump(session, data, 0, size, " ");
630 }
631 }
632 else
633 {
634 rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
635 }
636 return rc;
637}
638
639/* Dump property */
640bcmos_errno bcmbal_apicli_dump_prop(bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
641{
642 return bcmbal_apicli_dump_data_type(
643 session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_STD, NULL);
644}
645
646/* Dump a single property value in C initializer format */
647bcmos_errno bcmbal_apicli_dump_prop_initializer(
648 bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
649{
650 return bcmbal_apicli_dump_data_type(
651 session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_C_INIT, NULL);
652}
653
654/* Calculate property pointer given the group data pointer and property description */
655static inline void *bcmbal_apicli_prop_data_ptr(void *group_ptr, const bcmbal_apicli_prop_descr *pd)
656{
657 return (void *)((long)group_ptr + pd->offset);
658}
659
660/* Dump object data */
661static bcmos_errno bcmbal_apicli_dump_data(bcmcli_session *session, bcmbal_obj *msg, void *data, uint32_t data_size)
662{
663 uint16_t prop;
664 bcmos_errno rc = BCM_ERR_OK;
665 const bcmbal_apicli_prop_descr *pd;
666
667 bcmcli_print(session, "data:\n");
668 for (prop = 0;
669 bcmbal_apicli_object_property(msg->obj_type, msg->group, msg->subgroup, prop, &pd) == BCM_ERR_OK;
670 ++prop)
671 {
672 void *prop_data = bcmbal_apicli_prop_data_ptr(data, pd);
673 if (!(msg->presence_mask & (1LL << prop)))
674 continue;
675 if (!prop_data)
676 {
677 continue;
678 }
679 BUG_ON(pd->offset > data_size);
680 rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
681 if (rc != BCM_ERR_OK)
682 {
683 break;
684 }
685 }
686 return rc;
687}
688
689/* Dump object key */
690static bcmos_errno bcmbal_apicli_dump_key(bcmcli_session *session, bcmbal_obj *msg, void *key, uint32_t key_size)
691{
692 uint16_t prop;
693 bcmos_errno rc = BCM_ERR_OK;
694 const bcmbal_apicli_prop_descr *pd;
695
696 bcmcli_print(session, "key:\n");
697 for (prop = 0;
698 bcmbal_apicli_object_property(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, prop, &pd) == BCM_ERR_OK;
699 ++prop)
700 {
701 void *prop_data = bcmbal_apicli_prop_data_ptr(key, pd);
702 if (!prop_data)
703 {
704 continue;
705 }
706 BUG_ON(pd->offset > key_size);
707 rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
708 if (rc != BCM_ERR_OK)
709 {
710 break;
711 }
712 }
713 return rc;
714}
715
716const char *bcmbal_apicli_mgt_group_to_str(bcmbal_mgt_group group)
717{
718 static const char *str_table[BCMBAL_MGT_GROUP__NUM_OF] =
719 {
720 [BCMBAL_MGT_GROUP_KEY] = "key",
721 [BCMBAL_MGT_GROUP_CFG] = "cfg",
722 [BCMBAL_MGT_GROUP_STAT] = "stat",
723 [BCMBAL_MGT_GROUP_AUTO] = "auto",
724 [BCMBAL_MGT_GROUP_AUTO_CFG] = "auto_cfg",
725 };
726 return (group >= BCMBAL_MGT_GROUP__NUM_OF) ? "<unknown>" : str_table[group];
727}
728
729/* Dump message */
730bcmos_errno bcmbal_apicli_msg_dump(bcmcli_session *session, bcmbal_obj *msg)
731{
732 bcmos_errno rc;
733 const char *name, *descr;
734 uint32_t key_size;
735 uint32_t key_offset;
736 uint32_t data_size = 0;
737 uint32_t data_offset;
738 void *key = NULL;
739 void *data = NULL;
740
741 rc = bcmbal_apicli_object_name(msg->obj_type, &name, &descr);
742 if (rc)
743 {
744 goto dump_error;
745 }
746
747 bcmcli_print(session, "object: ");
748 if (name)
749 {
750 bcmcli_print(session, "%s", name);
751 }
752 if (descr)
753 {
754 bcmcli_print(session, " - %s", descr);
755 }
756 bcmcli_print(session, "\n");
757 rc = bcmbal_apicli_object_struct_size(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, &key_size, &key_offset, &data_size, &data_offset);
758 rc = rc ? rc : bcmbal_apicli_object_struct_size(msg->obj_type, msg->group, msg->subgroup, &key_size, &key_offset, &data_size, &data_offset);
759 if (rc)
760 {
761 goto dump_error;
762 }
763
764 bcmcli_print(session, (msg->type & BCMBAL_OBJ_MSG_TYPE_GET) != 0 ? "get" : "set");
765 if ((msg->type & BCMBAL_OBJ_MSG_TYPE_CLEAR) != 0)
766 {
767 bcmcli_print(session, ",clear");
768 }
769 bcmcli_print(session, " %s ", bcmbal_apicli_mgt_group_to_str(msg->group));
770
771 if (msg->group != BCMBAL_MGT_GROUP_CFG &&
772 msg->group != BCMBAL_MGT_GROUP_STAT &&
773 msg->group != BCMBAL_MGT_GROUP_AUTO_CFG)
774 {
775 const char *sub_name, *sub_descr;
776 /* Get name of specific subgroup */
777 rc = bcmbal_apicli_object_subgroup_name(msg->obj_type, msg->group, msg->subgroup, &sub_name, &sub_descr);
778 if (rc)
779 {
780 goto dump_error;
781 }
782 bcmcli_print(session, "subgroup: %s-%s ", sub_name ? sub_name : "?", sub_descr ? sub_descr : "");
783 }
784 if (msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST)
785 {
786 bcmcli_print(session, "request\n");
787 }
788 else
789 {
790 bcmcli_print(session, "response: %s\n", bcmos_strerror(msg->status));
791 bcmcli_print(session, "is in-progress: %s\n", (msg->is_inprogress == BCMOS_TRUE) ? "yes" : "no");
792 }
793
794 if ((msg->group != BCMBAL_MGT_GROUP_AUTO_CFG) && key_size)
795 {
796 key = (void *)((long)msg + sizeof(bcmbal_obj));
797 rc = bcmbal_apicli_dump_key(session, msg, key, key_size);
798 if (rc)
799 {
800 goto dump_error;
801 }
802 }
803 if (data_size &&
804 ( ((msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST) && (msg->type & BCMBAL_OBJ_MSG_TYPE_SET)) ||
805 ((msg->dir == BCMBAL_OBJ_MSG_DIR_RESPONSE) && (msg->type & BCMBAL_OBJ_MSG_TYPE_GET)) ||
806 (msg->group == BCMBAL_MGT_GROUP_AUTO)
807 )
808 )
809 {
810 data = (void *)((long)msg + data_offset);
811 rc = bcmbal_apicli_dump_data(session, msg, data, data_size);
812 if (rc)
813 {
814 goto dump_error;
815 }
816 }
817 return BCM_ERR_OK;
818
819dump_error:
820 bcmcli_print(session, "*** Object dump error %s (%d)\n", bcmos_strerror(rc), rc);
821 return rc;
822}
823