blob: 5a34961e6b820eb2b61a307b44c99a794985fc0f [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#include <bcmos_system.h>
#include <bal_obj.h>
#include <bcmcli.h>
#include "bal_api_cli_helpers.h"
typedef enum
{
BCMBAL_APICLI_OUTPUT_STYLE_STD,
BCMBAL_APICLI_OUTPUT_STYLE_C_INIT
} bcmbal_apicli_output_style;
typedef struct
{
const bcmbal_apicli_type_descr *type;
void *data;
uint8_t bit;
} bcmbal_apicli_presence_mask_info;
static bcmos_errno bcmbal_apicli_dump_array(
bcmcli_session *session,
const bcmbal_apicli_type_descr *td,
void *data,
uint32_t size,
const char *name,
bcmbal_apicli_output_style style,
const bcmbal_apicli_presence_mask_info *presence_mask);
static bcmos_errno bcmbal_apicli_read_snum(
bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, int64_t *n)
{
switch (td->size)
{
case 1:
{
int8_t n1 = *(int8_t *)data;
*n = n1;
break;
}
case 2:
{
int16_t n2 = *(int16_t *)data;
*n = n2;
break;
}
case 4:
{
int32_t n4 = *(int32_t *)data;
*n = n4;
break;
}
case 8:
{
memcpy(n, data, sizeof(*n));
break;
}
default:
bcmcli_print(session, "*** number size %u is not supported\n", td->size);
return BCM_ERR_NOT_SUPPORTED;
}
return BCM_ERR_OK;
}
static bcmos_errno bcmbal_apicli_read_unum(
bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, uint64_t *n)
{
switch (td->size)
{
case 1:
{
uint8_t n1 = *(uint8_t *)data;
*n = n1;
break;
}
case 2:
{
uint16_t n2 = *(uint16_t *)data;
*n = n2;
break;
}
case 4:
{
uint32_t n4 = *(uint32_t *)data;
*n = n4;
break;
}
case 8:
{
memcpy(n, data, sizeof(*n));
break;
}
default:
bcmcli_print(session, "*** number size %u is not supported\n", td->size);
return BCM_ERR_NOT_SUPPORTED;
}
return BCM_ERR_OK;
}
static void bcmbal_apicli_strcat_upper(char *dest, uint32_t dest_len, const char *src, uint32_t src_len)
{
uint32_t src_idx;
uint32_t dest_idx;
for (dest_idx = 0; dest_idx < dest_len - 1; ++dest_idx)
{
if (dest[dest_idx] == '\0')
{
break;
}
}
for (src_idx = 0; src_idx < src_len && dest_idx < dest_len - 1; ++src_idx, ++dest_idx)
{
dest[dest_idx] = src[src_idx];
if (dest[dest_idx] >= 'a' && dest[dest_idx] <= 'z')
{
dest[dest_idx] = 'A' + (dest[dest_idx] - 'a');
}
}
dest[dest_idx] = '\0';
}
static const char *bcmbal_apicli_get_c_enum_id(const bcmbal_apicli_type_descr *td, const char *name)
{
static char full_name_buf[256];
full_name_buf[0] = '\0';
bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), td->name, strlen(td->name));
bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), "_", 1);
bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), name, strlen(name));
return full_name_buf;
}
static bcmos_errno bcmbal_apicli_dump_simple_data_type(
bcmcli_session *session,
const bcmbal_apicli_type_descr *td,
void *data,
const char *name,
bcmbal_apicli_output_style style)
{
bcmos_errno rc = BCM_ERR_OK;
switch (td->base_type)
{
case BCMBAL_APICLI_BASE_TYPE_ID_SNUM: /* signed number */
{
int64_t n = 0;
rc = bcmbal_apicli_read_snum(session, td, data, &n);
bcmcli_print(session, "%lld", (long long)n);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_UNUM: /* unsigned number */
{
uint64_t n = 0;
rc = bcmbal_apicli_read_unum(session, td, data, &n);
bcmcli_print(session, "%llu", (unsigned long long)n);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX: /* unsigned number printed in hex */
{
uint64_t n = 0;
rc = bcmbal_apicli_read_unum(session, td, data, &n);
bcmcli_print(session, "0x%llx", (unsigned long long)n);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_FLOAT: /* floating-point number */
{
if (td->size == sizeof(float))
{
bcmcli_print(session, "%f", *(float *)data);
}
else if (td->size == sizeof(double))
{
bcmcli_print(session, "%f", *(double *)data);
}
else
{
bcmcli_print(session, "*** floating-point number of width %u is not supported\n", td->size);
rc = BCM_ERR_NOT_SUPPORTED;
}
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_BOOL:
{
const char *no_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_FALSE" : "no";
const char *yes_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_TRUE" : "yes";
uint64_t n = 0;
rc = bcmbal_apicli_read_unum(session, td, data, &n);
bcmcli_print(session, "%s", n == 0 ? no_str : yes_str);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_STRING: /* string */
{
if (td->size == 0)
{
bcmcli_print(session, "\"%s\"", (char *)data);
}
else
{
/* we know the size of the buffer */
bcmcli_print(session, "\"%.*s\"", td->size, (char *)data);
}
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_IPV4: /* IPv4 address */
{
uint32_t ip;
memcpy(&ip, data, sizeof(ip));
bcmcli_print(
session,
style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "{ %d,%d,%d,%d }" : "%d.%d.%d.%d",
(ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_MAC: /* MAC address */
{
bcmos_mac_address mac;
memcpy(mac.u8, data, sizeof(mac.u8));
bcmcli_print(
session,
style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ?
"{{ 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x }}" :
"%02x:%02x:%02x:%02x:%02x:%02x",
mac.u8[0], mac.u8[1], mac.u8[2], mac.u8[3], mac.u8[4], mac.u8[5]);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_ENUM: /* enum */
{
uint64_t n = 0;
const char *s;
rc = bcmbal_apicli_read_unum(session, td, data, &n);
BUG_ON(td->x.e == NULL);
s = bcmcli_enum_stringval(td->x.e, (long)n);
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
s = bcmbal_apicli_get_c_enum_id(td, s);
}
bcmcli_print(session, "%s", s);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK:
{
uint64_t n = 0;
const char *s;
const char *none = NULL;
bcmcli_enum_val *value = td->x.e;
bcmos_bool first = BCMOS_TRUE;
BUG_ON(value == NULL);
rc = bcmbal_apicli_read_unum(session, td, data, &n);
while (value->name != NULL)
{
if (value->val == 0)
{
none = value->name;
}
if ((value->val & n) != 0)
{
s = value->name;
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
s = bcmbal_apicli_get_c_enum_id(td, s);
}
bcmcli_print(session, "%s%s", first ? "" : (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "|" : BCMCLI_ENUM_MASK_DEL_STR), s);
first = BCMOS_FALSE;
n -= value->val;
}
++value;
}
if (first)
{
bcmcli_print(session, "%s", (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT) || (NULL == none) ? "0" : none);
}
break;
}
default:
bcmcli_print(session, "*** type %d is not supported\n", (int)td->base_type);
rc = BCM_ERR_NOT_SUPPORTED;
break;
}
return rc;
}
/* calculate number of enum values */
static int bcmbal_apicli_get_num_enum_vals(const bcmcli_enum_val *vals)
{
const bcmcli_enum_val *v = vals;
while (v && v->name)
{
++v;
}
return (v - vals);
}
/* helper function to skip the "u." in front of union field names */
static inline const char *bcmbal_apicli_skip_union_prefix(const char *name)
{
if (name[0] == 'u' && name[1] == '.')
{
name += 2;
}
return name;
}
static bcmos_bool bcmbal_apicli_is_value_set(
bcmcli_session *session,
const bcmbal_apicli_presence_mask_info *presence_mask)
{
uint64_t pm_value_num = 0;
if (!presence_mask || !presence_mask->type)
{
/* no presence mask - all values are implicitly set */
return BCMOS_TRUE;
}
bcmbal_apicli_read_unum(session, presence_mask->type, presence_mask->data, &pm_value_num);
return ((pm_value_num >> presence_mask->bit) & 1) != 0;
}
/* Dump data type */
static bcmos_errno bcmbal_apicli_dump_data_type(
bcmcli_session *session,
const bcmbal_apicli_type_descr *td,
void *data,
const char *name,
uint32_t num_entries,
uint32_t entry_size,
bcmbal_apicli_output_style style,
const bcmbal_apicli_presence_mask_info *presence_mask)
{
bcmos_errno rc = BCM_ERR_OK;
switch (td->base_type)
{
case BCMBAL_APICLI_BASE_TYPE_ID_STRUCT:
{
uint16_t f;
char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
if (!td->x.s.num_fields)
return 0;
BUG_ON(!td->x.s.fields);
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, "{ ");
}
for (f = 0; f < td->x.s.num_fields; f++)
{
const bcmbal_apicli_field_descr *fld = &td->x.s.fields[f];
void *fdata = (void *)((long)data + fld->offset);
bcmbal_apicli_presence_mask_info field_pm = {};
if (((td->x.s.fields[0].flags & BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK) != 0) &&
style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
/* If the struct has a presence mask, skip the presence mask field itself, then record the position
* of the presence mask so we can check it later for each entry. */
if (f == 0)
{
continue;
}
field_pm.type = td->x.s.fields[0].type;
field_pm.data = (uint8_t *)data + td->x.s.fields[0].offset;
field_pm.bit = (uint8_t)(f - 1);
}
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT && f > 0)
{
bcmcli_print(session, ", ");
}
bcmcli_strncpy(full_name, name, sizeof(full_name));
bcmcli_strncat(full_name, ".", sizeof(full_name));
bcmcli_strncat(full_name, fld->name, sizeof(full_name));
rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, &field_pm);
}
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, " }");
}
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_UNION:
{
/* Print fields up to selector, then selector, then selected sub-structure */
uint16_t f;
char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
const bcmbal_apicli_field_descr *fld;
void *fdata;
int64_t selector_val = 0;
int num_union_vals;
if (!td->x.u.num_common_fields)
return 0;
BUG_ON(!td->x.u.common_fields);
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, "{ ");
}
/* Common fields, including selector */
for (f = 0; f <= td->x.u.classifier_idx && !rc; f++)
{
fld = &td->x.u.common_fields[f];
fdata = (void *)((long)data + fld->offset);
bcmcli_strncpy(full_name, name, sizeof(full_name));
if (fld->name && strlen(fld->name))
{
bcmcli_strncat(full_name, ".", sizeof(full_name));
bcmcli_strncat(full_name, fld->name, sizeof(full_name));
}
rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
if (f == td->x.u.classifier_idx)
{
rc = rc ? rc : bcmbal_apicli_read_snum(session, fld->type, fdata, &selector_val);
}
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, ", ");
}
}
if (rc)
{
bcmcli_print(session, "***internal error when dumping field %s\n",
td->x.u.common_fields[f].name);
return rc;
}
num_union_vals = bcmbal_apicli_get_num_enum_vals(td->x.u.common_fields[td->x.u.classifier_idx].type->x.e);
if ((unsigned)selector_val >= num_union_vals)
{
bcmcli_print(session, "***invalid union selector value %lld\n", (long long)selector_val);
return BCM_ERR_INTERNAL;
}
/* Common fields following selector */
for (; f < td->x.u.num_common_fields; f++)
{
fld = &td->x.u.common_fields[f];
fdata = (void *)((long)data + fld->offset);
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, ", ");
}
bcmcli_strncpy(full_name, name, sizeof(full_name));
if (fld->name && strlen(fld->name))
{
bcmcli_strncat(full_name, ".", sizeof(full_name));
bcmcli_strncat(full_name, fld->name, sizeof(full_name));
}
rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
}
/* Selected field */
fld = &td->x.u.union_fields[selector_val];
if (fld->type)
{
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, "{ .%s = ", bcmbal_apicli_skip_union_prefix(fld->name));
}
fdata = (void *)((long)data + fld->offset);
bcmcli_strncpy(full_name, name, sizeof(full_name));
if (fld->name && strlen(fld->name))
{
bcmcli_strncat(full_name, ".", sizeof(full_name));
bcmcli_strncat(full_name, fld->name, sizeof(full_name));
}
rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, " }");
}
}
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, " }");
}
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED: /* fixed array */
{
rc = bcmbal_apicli_dump_array(session, td->x.arr_fixed.elem_type, data, td->x.arr_fixed.size, name, style, presence_mask);
break;
}
case BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN: /* dynamic array that should be printed as buffer */
{
/* Read length */
uint32_t array_size;
long base_ptr;
switch (td->x.arr_dyn.len_size )
{
case 1: array_size = *(uint8_t *)data; break;
case 2: array_size = *(uint16_t *)data; break;
case 4: array_size = *(uint32_t *)data; break;
default:
bcmcli_print(session,
"*** %s: dyn array len_size %u is not supported\n", name, td->x.arr_dyn.len_size);
return BCM_ERR_NOT_SUPPORTED;
}
base_ptr = BCMOS_ROUND_UP((long)data + td->x.arr_dyn.len_size, sizeof(void *));
BUG_ON(!base_ptr);
data = *(void **)base_ptr;
rc = bcmbal_apicli_dump_array(session, td->x.arr_dyn.elem_type, data, array_size, name, style, presence_mask);
break;
}
default:
{
/* Finally! Simple type that maps to a single CLI parameter */
int n;
bcmbal_apicli_presence_mask_info local_pm;
/* If we have a single value and that value is not included in the presence mask, just skip it entirely */
if (num_entries == 1 && !bcmbal_apicli_is_value_set(session, presence_mask))
{
break;
}
if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
if (name)
{
bcmcli_print(session, " %s=", name);
}
if (!num_entries)
{
bcmcli_print(session, BCMCLI_ARRAY_EMPTY);
}
}
/* Dump simple value or array of simple values */
local_pm = presence_mask ? *presence_mask : (bcmbal_apicli_presence_mask_info){};
for (n = 0; n < num_entries; n++)
{
if (n)
{
bcmcli_print(session, ",");
}
/* If we have a presence mask, make sure to print a special token if the value is unset */
if (bcmbal_apicli_is_value_set(session, &local_pm))
{
rc = bcmbal_apicli_dump_simple_data_type(session, td, data, name, style);
}
else
{
bcmcli_print(session, BCMCLI_PARM_NO_VALUE);
}
data = (void *)((long)data + entry_size);
local_pm.data = (void *)((long)local_pm.data + entry_size);
}
if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, "\n");
}
break;
}
}
return rc;
}
/* Dump array */
static bcmos_errno bcmbal_apicli_dump_array(
bcmcli_session *session,
const bcmbal_apicli_type_descr *td,
void *data,
uint32_t size,
const char *name,
bcmbal_apicli_output_style style,
const bcmbal_apicli_presence_mask_info *presence_mask)
{
bcmos_errno rc = BCM_ERR_OK;
/* Print as buffer or element by element ? */
if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
{
bcmcli_print(session, "{ ");
rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
bcmcli_print(session, " }");
}
else if ((td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM ||
td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX) && td->size == 1)
{
if (bcmbal_apicli_is_value_set(session, presence_mask))
{
bcmcli_print(session, " %s=\n", name);
bcmcli_session_hexdump(session, data, 0, size, " ");
}
}
else
{
rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
}
return rc;
}
/* Dump property */
bcmos_errno bcmbal_apicli_dump_prop(bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
{
return bcmbal_apicli_dump_data_type(
session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_STD, NULL);
}
/* Dump a single property value in C initializer format */
bcmos_errno bcmbal_apicli_dump_prop_initializer(
bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
{
return bcmbal_apicli_dump_data_type(
session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_C_INIT, NULL);
}
/* Calculate property pointer given the group data pointer and property description */
static inline void *bcmbal_apicli_prop_data_ptr(void *group_ptr, const bcmbal_apicli_prop_descr *pd)
{
return (void *)((long)group_ptr + pd->offset);
}
/* Dump object data */
static bcmos_errno bcmbal_apicli_dump_data(bcmcli_session *session, bcmbal_obj *msg, void *data, uint32_t data_size)
{
uint16_t prop;
bcmos_errno rc = BCM_ERR_OK;
const bcmbal_apicli_prop_descr *pd;
bcmcli_print(session, "data:\n");
for (prop = 0;
bcmbal_apicli_object_property(msg->obj_type, msg->group, msg->subgroup, prop, &pd) == BCM_ERR_OK;
++prop)
{
void *prop_data = bcmbal_apicli_prop_data_ptr(data, pd);
if (!(msg->presence_mask & (1LL << prop)))
continue;
if (!prop_data)
{
continue;
}
BUG_ON(pd->offset > data_size);
rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
if (rc != BCM_ERR_OK)
{
break;
}
}
return rc;
}
/* Dump object key */
static bcmos_errno bcmbal_apicli_dump_key(bcmcli_session *session, bcmbal_obj *msg, void *key, uint32_t key_size)
{
uint16_t prop;
bcmos_errno rc = BCM_ERR_OK;
const bcmbal_apicli_prop_descr *pd;
bcmcli_print(session, "key:\n");
for (prop = 0;
bcmbal_apicli_object_property(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, prop, &pd) == BCM_ERR_OK;
++prop)
{
void *prop_data = bcmbal_apicli_prop_data_ptr(key, pd);
if (!prop_data)
{
continue;
}
BUG_ON(pd->offset > key_size);
rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
if (rc != BCM_ERR_OK)
{
break;
}
}
return rc;
}
const char *bcmbal_apicli_mgt_group_to_str(bcmbal_mgt_group group)
{
static const char *str_table[BCMBAL_MGT_GROUP__NUM_OF] =
{
[BCMBAL_MGT_GROUP_KEY] = "key",
[BCMBAL_MGT_GROUP_CFG] = "cfg",
[BCMBAL_MGT_GROUP_STAT] = "stat",
[BCMBAL_MGT_GROUP_AUTO] = "auto",
[BCMBAL_MGT_GROUP_AUTO_CFG] = "auto_cfg",
};
return (group >= BCMBAL_MGT_GROUP__NUM_OF) ? "<unknown>" : str_table[group];
}
/* Dump message */
bcmos_errno bcmbal_apicli_msg_dump(bcmcli_session *session, bcmbal_obj *msg)
{
bcmos_errno rc;
const char *name, *descr;
uint32_t key_size;
uint32_t key_offset;
uint32_t data_size = 0;
uint32_t data_offset;
void *key = NULL;
void *data = NULL;
rc = bcmbal_apicli_object_name(msg->obj_type, &name, &descr);
if (rc)
{
goto dump_error;
}
bcmcli_print(session, "object: ");
if (name)
{
bcmcli_print(session, "%s", name);
}
if (descr)
{
bcmcli_print(session, " - %s", descr);
}
bcmcli_print(session, "\n");
rc = bcmbal_apicli_object_struct_size(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, &key_size, &key_offset, &data_size, &data_offset);
rc = rc ? rc : bcmbal_apicli_object_struct_size(msg->obj_type, msg->group, msg->subgroup, &key_size, &key_offset, &data_size, &data_offset);
if (rc)
{
goto dump_error;
}
bcmcli_print(session, (msg->type & BCMBAL_OBJ_MSG_TYPE_GET) != 0 ? "get" : "set");
if ((msg->type & BCMBAL_OBJ_MSG_TYPE_CLEAR) != 0)
{
bcmcli_print(session, ",clear");
}
bcmcli_print(session, " %s ", bcmbal_apicli_mgt_group_to_str(msg->group));
if (msg->group != BCMBAL_MGT_GROUP_CFG &&
msg->group != BCMBAL_MGT_GROUP_STAT &&
msg->group != BCMBAL_MGT_GROUP_AUTO_CFG)
{
const char *sub_name, *sub_descr;
/* Get name of specific subgroup */
rc = bcmbal_apicli_object_subgroup_name(msg->obj_type, msg->group, msg->subgroup, &sub_name, &sub_descr);
if (rc)
{
goto dump_error;
}
bcmcli_print(session, "subgroup: %s-%s ", sub_name ? sub_name : "?", sub_descr ? sub_descr : "");
}
if (msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST)
{
bcmcli_print(session, "request\n");
}
else
{
bcmcli_print(session, "response: %s\n", bcmos_strerror(msg->status));
bcmcli_print(session, "is in-progress: %s\n", (msg->is_inprogress == BCMOS_TRUE) ? "yes" : "no");
}
if ((msg->group != BCMBAL_MGT_GROUP_AUTO_CFG) && key_size)
{
key = (void *)((long)msg + sizeof(bcmbal_obj));
rc = bcmbal_apicli_dump_key(session, msg, key, key_size);
if (rc)
{
goto dump_error;
}
}
if (data_size &&
( ((msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST) && (msg->type & BCMBAL_OBJ_MSG_TYPE_SET)) ||
((msg->dir == BCMBAL_OBJ_MSG_DIR_RESPONSE) && (msg->type & BCMBAL_OBJ_MSG_TYPE_GET)) ||
(msg->group == BCMBAL_MGT_GROUP_AUTO)
)
)
{
data = (void *)((long)msg + data_offset);
rc = bcmbal_apicli_dump_data(session, msg, data, data_size);
if (rc)
{
goto dump_error;
}
}
return BCM_ERR_OK;
dump_error:
bcmcli_print(session, "*** Object dump error %s (%d)\n", bcmos_strerror(rc), rc);
return rc;
}