Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 103 additions & 4 deletions plugins/solidigm/solidigm-telemetry/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <json.h>
#include <stdint.h>
#include "config.h"

#define NOT_FOUND "NOT_FOUND"

// max 16 bit unsigned integer number 65535
#define MAX_16BIT_NUM_AS_STRING_SIZE 6

#define OBJ_NAME_PREFIX "UID_"
#define NLOG_OBJ_PREFIX OBJ_NAME_PREFIX "NLOG_"

static bool config_get_by_version(const struct json_object *obj, int version_major,
int version_minor, struct json_object **value)
static bool config_get_by_version(const struct json_object *obj,
int version_major, int version_minor,
struct json_object **value)
{
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
char str_subkey[MAX_16BIT_NUM_AS_STRING_SIZE];
Expand Down Expand Up @@ -58,6 +60,7 @@ bool sldm_config_get_struct_by_key_version(const struct json_object *config, cha
struct json_object **value)
{
struct json_object *token = NULL;

if (!json_object_object_get_ex(config, key, &token))
return false;
if (!config_get_by_version(token, version_major, version_minor, value))
Expand Down Expand Up @@ -90,7 +93,7 @@ const char *solidigm_config_get_nlog_obj_name(const struct json_object *config,
if (!json_object_object_get_ex(nlog_names, hex_header, &obj_name))
return NULL;
name = json_object_get_string(obj_name);
if ((!name) || (strncmp(NLOG_OBJ_PREFIX, name, strlen(NLOG_OBJ_PREFIX))))
if (!name || strncmp(NLOG_OBJ_PREFIX, name, strlen(NLOG_OBJ_PREFIX)))
return NULL;

return &name[strlen(OBJ_NAME_PREFIX)];
Expand All @@ -103,3 +106,99 @@ struct json_object *solidigm_config_get_nlog_formats(const struct json_object *c
json_object_object_get_ex(config, "NLOG_FORMATS", &nlog_formats);
return nlog_formats;
}

/* Enum value lookup helper functions */
static const char *find_enum_value_in_member_list(
struct json_object *enum_member_list,
uint64_t value)
{
if (!json_object_is_type(enum_member_list, json_type_array))
return UNKNOWN_ENUM_VALUE;

int enum_array_len = json_object_array_length(enum_member_list);

for (int j = 0; j < enum_array_len; j++) {
struct json_object *enum_item =
json_object_array_get_idx(enum_member_list, j);

if (!enum_item)
continue;

json_object_object_foreach(enum_item, key, val) {
(void)key; /* Suppress unused variable warning */
if (json_object_get_uint64(val) == value)
return key;
}
}
return UNKNOWN_ENUM_VALUE;
}

static bool is_target_enum_field(struct json_object *member,
const char *enum_field_name)
{
struct json_object *name_obj, *enum_obj;

if (!json_object_object_get_ex(member, "name", &name_obj) ||
!json_object_object_get_ex(member, "enum", &enum_obj))
return false;

const char *name = json_object_get_string(name_obj);
int is_enum = json_object_get_int(enum_obj);

return (strcmp(name, enum_field_name) == 0 && is_enum == 1);
}

static const char *search_enum_in_member(struct json_object *member,
const char *enum_field_name,
uint64_t value)
{
if (!is_target_enum_field(member, enum_field_name))
return NOT_FOUND;

/* Found the enum field, look for the value in its memberList */
struct json_object *enum_member_list;

if (!json_object_object_get_ex(member, "memberList", &enum_member_list))
return UNKNOWN_ENUM_VALUE;

return find_enum_value_in_member_list(enum_member_list, value);
}

const char *sldm_get_enum_label_by_value(struct json_object *struct_def,
const char *enum_field_name,
uint64_t value)
{
struct json_object *member_list;

if (!json_object_object_get_ex(struct_def, "memberList", &member_list))
return UNKNOWN_ENUM_VALUE;

if (!json_object_is_type(member_list, json_type_array))
return UNKNOWN_ENUM_VALUE;

int array_len = json_object_array_length(member_list);

for (int i = 0; i < array_len; i++) {
struct json_object *member =
json_object_array_get_idx(member_list, i);

if (!member)
continue;

/* Try to find enum in this member */
const char *result = search_enum_in_member(member,
enum_field_name,
value);

if (strcmp(result, NOT_FOUND) != 0)
return result; /* Found it or determined it's unknown */

/* If this member has nested members, search recursively */
result = sldm_get_enum_label_by_value(member, enum_field_name,
value);
if (strcmp(result, UNKNOWN_ENUM_VALUE) != 0)
return result;
}

return UNKNOWN_ENUM_VALUE;
}
4 changes: 4 additions & 0 deletions plugins/solidigm/solidigm-telemetry/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "util/json.h"

#define STR_HEX32_SIZE sizeof("0x00000000")
#define UNKNOWN_ENUM_VALUE "UNKNOWN_ENUM_VALUE"

bool sldm_config_get_struct_by_key_version(const struct json_object *config, char *key,
int version_major, int version_minor,
Expand All @@ -19,4 +20,7 @@ bool solidigm_config_get_struct_by_token_version(const struct json_object *obj,

const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token);
struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config);
const char *sldm_get_enum_label_by_value(struct json_object *struct_def,
const char *enum_field_name,
uint64_t value);

35 changes: 35 additions & 0 deletions plugins/solidigm/solidigm-telemetry/data-area.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "config.h"
#include "nlog.h"
#include "skht.h"
#include "side-trace.h"
#include <ctype.h>

#define SIGNED_int_PREFIX "int"
Expand Down Expand Up @@ -579,6 +580,40 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
toc->items[i].ContentSizeBytes - header_offset,
parsed_struct, toc_item);
}

// Check if this is a side trace object
struct json_object *obj_name = NULL;

if (json_object_object_get_ex(toc_item, "objName", &obj_name)) {
const char *obj_name_str =
json_object_get_string(obj_name);

if (obj_name_str &&
(strstr(obj_name_str, "sideTrace") ||
strstr(obj_name_str, "SideTrace") ||
strstr(obj_name_str, "SIDETRACE"))) {
/* This is a side trace object, parse it when
* configuration is available. We want to
* replace array member fwSideTrace by parsed
* entries.
*/
struct json_object *first_dic = NULL;

json_object_object_foreach(parsed_struct, key,
val) {
(void)key;
if (json_object_is_type(val,
json_type_object)) {
first_dic = val;
break;
}
}
sldm_parse_side_trace(tl, object_file_offset,
toc->items[i]
.ContentSizeBytes,
first_dic, toc_item);
}
}
}
}

Expand Down
1 change: 1 addition & 0 deletions plugins/solidigm/solidigm-telemetry/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ plugin_sources += [
'plugins/solidigm/solidigm-telemetry/skht.c',
'plugins/solidigm/solidigm-telemetry/debug-info.c',
'plugins/solidigm/solidigm-telemetry/uart-log.c',
'plugins/solidigm/solidigm-telemetry/side-trace.c',
]
Loading