From 511ce8a656c22fd33677c1353551365d1423fa1d Mon Sep 17 00:00:00 2001 From: "leonardo.da.cunha" Date: Fri, 21 Apr 2023 17:19:50 -0700 Subject: [PATCH] plugins/solidigm: Added NLog support to Telemetry parsing. Telemetry Reason Identifier fields changed to start with lower case. Signed-off-by: leonardo.da.cunha --- plugins/solidigm/solidigm-nvme.h | 2 +- plugins/solidigm/solidigm-telemetry/cod.c | 2 +- plugins/solidigm/solidigm-telemetry/config.c | 44 +++++- plugins/solidigm/solidigm-telemetry/config.h | 8 +- .../solidigm/solidigm-telemetry/data-area.c | 84 +++++++---- plugins/solidigm/solidigm-telemetry/header.c | 60 +++++--- .../solidigm/solidigm-telemetry/meson.build | 1 + plugins/solidigm/solidigm-telemetry/nlog.c | 130 ++++++++++++++++++ plugins/solidigm/solidigm-telemetry/nlog.h | 11 ++ 9 files changed, 290 insertions(+), 52 deletions(-) create mode 100644 plugins/solidigm/solidigm-telemetry/nlog.c create mode 100644 plugins/solidigm/solidigm-telemetry/nlog.h diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h index 9d653069..bb56aeb1 100644 --- a/plugins/solidigm/solidigm-nvme.h +++ b/plugins/solidigm/solidigm-nvme.h @@ -13,7 +13,7 @@ #include "cmd.h" -#define SOLIDIGM_PLUGIN_VERSION "0.11" +#define SOLIDIGM_PLUGIN_VERSION "0.12" PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION), COMMAND_LIST( diff --git a/plugins/solidigm/solidigm-telemetry/cod.c b/plugins/solidigm/solidigm-telemetry/cod.c index 12cf42bb..58a6e709 100644 --- a/plugins/solidigm/solidigm-telemetry/cod.c +++ b/plugins/solidigm/solidigm-telemetry/cod.c @@ -118,7 +118,7 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl) return; if (!json_object_object_get_ex(telemetry_header, "reasonIdentifier", &reason_id)) return; - if (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset)) + if (!json_object_object_get_ex(reason_id, "oemDataMapOffset", &COD_offset)) return; uint64_t offset = json_object_get_int(COD_offset); diff --git a/plugins/solidigm/solidigm-telemetry/config.c b/plugins/solidigm/solidigm-telemetry/config.c index 51117031..cc2a8bb0 100644 --- a/plugins/solidigm/solidigm-telemetry/config.c +++ b/plugins/solidigm/solidigm-telemetry/config.c @@ -4,13 +4,17 @@ * * Author: leonardo.da.cunha@solidigm.com */ -#include -#include "util/json.h" + #include +#include +#include "config.h" // max 16 bit unsigned integer nummber 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) { @@ -28,17 +32,45 @@ static bool config_get_by_version(const struct json_object *obj, int version_maj return value != NULL; } -bool solidigm_config_get_by_token_version(const struct json_object *obj, int token_id, +bool solidigm_config_get_struct_by_token_version(const struct json_object *config, int token_id, int version_major, int version_minor, struct json_object **value) { - struct json_object *token_obj = NULL; + struct json_object *token = NULL; char str_key[MAX_16BIT_NUM_AS_STRING_SIZE]; snprintf(str_key, sizeof(str_key), "%d", token_id); - if (!json_object_object_get_ex(obj, str_key, &token_obj)) + if (!json_object_object_get_ex(config, str_key, &token)) return false; - if (!config_get_by_version(token_obj, version_major, version_minor, value)) + if (!config_get_by_version(token, version_major, version_minor, value)) return false; return value != NULL; } + +const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token) +{ + struct json_object *nlog_names = NULL; + struct json_object *obj_name; + char hex_header[STR_HEX32_SIZE]; + const char *name; + + if (!json_object_object_get_ex(config, "TELEMETRY_OBJECT_UIDS", &nlog_names)) + return NULL; + snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", token); + + if (!json_object_object_get_ex(nlog_names, hex_header, &obj_name)) + return NULL; + name = json_object_get_string(obj_name); + if (strncmp(NLOG_OBJ_PREFIX, name, strlen(NLOG_OBJ_PREFIX))) + return NULL; + + return &name[strlen(OBJ_NAME_PREFIX)]; +} + +struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config) +{ + struct json_object *nlog_formats = NULL; + + json_object_object_get_ex(config, "NLOG_FORMATS", &nlog_formats); + return nlog_formats; +} diff --git a/plugins/solidigm/solidigm-telemetry/config.h b/plugins/solidigm/solidigm-telemetry/config.h index 30e61ffb..4e56ba3b 100644 --- a/plugins/solidigm/solidigm-telemetry/config.h +++ b/plugins/solidigm/solidigm-telemetry/config.h @@ -7,7 +7,13 @@ #include #include "util/json.h" -bool solidigm_config_get_by_token_version(const struct json_object *obj, +#define STR_HEX32_SIZE sizeof("0x00000000") + +bool solidigm_config_get_struct_by_token_version(const struct json_object *obj, int key, int subkey, int subsubkey, struct json_object **value); + +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); + diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c index 31f7836c..93ea0fff 100644 --- a/plugins/solidigm/solidigm-telemetry/data-area.c +++ b/plugins/solidigm/solidigm-telemetry/data-area.c @@ -10,6 +10,7 @@ #include "cod.h" #include "data-area.h" #include "config.h" +#include "nlog.h" #include #define SIGNED_INT_PREFIX "int" @@ -302,6 +303,27 @@ static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl, return 0; } +static int telemetry_log_nlog_parse(const struct telemetry_log *tl, struct json_object *formats, + uint64_t nlog_file_offset, uint64_t nlog_size, + struct json_object *output, struct json_object *metadata) +{ + /* boundary check */ + if (tl->log_size < (nlog_file_offset + nlog_size)) { + const char *name = ""; + int media_bank = -1; + struct json_object *jobj; + + if (json_object_object_get_ex(metadata, "objName", &jobj)) + name = json_object_get_string(jobj); + if (json_object_object_get_ex(metadata, "mediaBankId", &jobj)) + media_bank = json_object_get_int(jobj); + SOLIDIGM_LOG_WARNING("%s:%d do not fit this log dump.", name, media_bank); + return -1; + } + return solidigm_nlog_parse(((char *) tl->log) + nlog_file_offset, + nlog_size, formats, metadata, output); +} + struct toc_item { uint32_t OffsetBytes; uint32_t ContentSizeBytes; @@ -328,7 +350,6 @@ struct telemetry_object_header { uint8_t Reserved[3]; }; - static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, enum nvme_telemetry_da da, struct json_object *toc_array, @@ -340,18 +361,22 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, char *payload; uint32_t da_offset; uint32_t da_size; + struct json_object *nlog_formats; if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size)) return; toc = (struct table_of_contents *)(((char *)tl->log) + da_offset); payload = (char *) tl->log; + nlog_formats = solidigm_config_get_nlog_formats(tl->configuration); for (int i = 0; i < toc->header.TableOfContentsCount; i++) { struct json_object *structure_definition = NULL; struct json_object *toc_item; uint32_t obj_offset; bool has_struct; + const char *nlog_name = NULL; + uint32_t header_offset = sizeof(const struct telemetry_object_header); if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) { SOLIDIGM_LOG_WARNING("Warning: Data Area %d, " @@ -381,38 +406,49 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, json_object_add_value_uint(toc_item, "objectId", header->Token); json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId); - has_struct = solidigm_config_get_by_token_version(tl->configuration, + has_struct = solidigm_config_get_struct_by_token_version(tl->configuration, header->Token, header->versionMajor, header->versionMinor, &structure_definition); + if (!has_struct) { + if (!nlog_formats) + continue; + nlog_name = solidigm_config_get_nlog_obj_name(tl->configuration, + header->Token); + if (!nlog_name) + continue; + } + struct json_object *tele_obj_item = json_create_object(); - if (has_struct) { - struct json_object *tele_obj_item = json_create_object(); - - json_object_array_add(tele_obj_array, tele_obj_item); - json_object_get(toc_item); - json_object_add_value_object(tele_obj_item, "metadata", toc_item); - struct json_object *parsed_struct = json_create_object(); - - json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); - struct json_object *obj_hasTelemObjHdr = NULL; - uint32_t header_offset = sizeof(const struct telemetry_object_header); - uint64_t file_offset; + json_object_array_add(tele_obj_array, tele_obj_item); + json_object_get(toc_item); + json_object_add_value_object(tele_obj_item, "metadata", toc_item); + struct json_object *parsed_struct = json_create_object(); - if (json_object_object_get_ex(structure_definition, - "hasTelemObjHdr", - &obj_hasTelemObjHdr)) { - bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); + json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); + struct json_object *obj_hasTelemObjHdr = NULL; + uint64_t object_file_offset; - if (hasHeader) - header_offset = 0; - } + if (json_object_object_get_ex(structure_definition, + "hasTelemObjHdr", + &obj_hasTelemObjHdr)) { + bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); - file_offset = ((uint64_t)da_offset) + obj_offset + header_offset; + if (hasHeader) + header_offset = 0; + } + object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset; + if (has_struct) { telemetry_log_structure_parse(tl, structure_definition, - BITS_IN_BYTE * file_offset, - parsed_struct, toc_item); + BITS_IN_BYTE * object_file_offset, + parsed_struct, toc_item); + } else if (nlog_formats) { + json_object_object_add(toc_item, "objName", + json_object_new_string(nlog_name)); + telemetry_log_nlog_parse(tl, nlog_formats, object_file_offset, + toc->items[i].ContentSizeBytes - header_offset, + parsed_struct, toc_item); } } } diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c index 2f2684af..bd488ae5 100644 --- a/plugins/solidigm/solidigm-telemetry/header.c +++ b/plugins/solidigm/solidigm-telemetry/header.c @@ -69,12 +69,18 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl, struct json_object *reserved; ri = (struct reason_indentifier_1_0 *) tl->log->rsnident; - json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion))); - json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); + json_object_object_add(reason_id, "firmwareVersion", + json_object_new_string_len(ri->FirmwareVersion, + sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "bootloaderVersion", + json_object_new_string_len(ri->BootloaderVersion, + sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved", reserved); + json_object_add_value_array(reason_id, "reserved", reserved); for ( int i=0; i < sizeof(ri->Reserved); i++) { struct json_object *val = json_object_new_int(ri->Reserved[i]); json_object_array_add(reserved, val); @@ -88,15 +94,24 @@ static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl, struct json_object *reserved; ri = (struct reason_indentifier_1_1 *) tl->log->rsnident; - json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion))); - json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); - json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); - json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); - json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); + json_object_object_add(reason_id, "firmwareVersion", + json_object_new_string_len(ri->FirmwareVersion, + sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "bootloaderVersion", + json_object_new_string_len(ri->BootloaderVersion, + sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "oemDataMapOffset", + le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "telemetryMajorVersion", + le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "telemetryMinorVersion", + le16_to_cpu(ri->TelemetryMinorVersion)); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved", reserved); + json_object_add_value_array(reason_id, "reserved", reserved); for (int i = 0; i < sizeof(ri->Reserved); i++) { struct json_object *val = json_object_new_int(ri->Reserved[i]); json_object_array_add(reserved, val); @@ -112,21 +127,26 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl, ri = (struct reason_indentifier_1_2 *) tl->log->rsnident; - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); - json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); - json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); - json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); - json_object_add_value_uint(reason_id, "ProductFamilyId", ri->ProductFamilyId); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "oemDataMapOffset", + le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "telemetryMajorVersion", + le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "telemetryMinorVersion", + le16_to_cpu(ri->TelemetryMinorVersion)); + json_object_add_value_uint(reason_id, "productFamilyId", ri->ProductFamilyId); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved2", reserved); + json_object_add_value_array(reason_id, "reserved2", reserved); for (int i = 0; i < sizeof(ri->Reserved2); i++) { struct json_object *val = json_object_new_int(ri->Reserved2[i]); json_object_array_add(reserved, val); } dp_reserved = json_create_array(); - json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved); + json_object_add_value_array(reason_id, "dualPortReserved", dp_reserved); for (int i = 0; i < sizeof(ri->DualPortReserved); i++) { struct json_object *val = json_object_new_int(ri->DualPortReserved[i]); json_object_array_add(dp_reserved, val); @@ -143,7 +163,9 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t json_object_add_value_uint(reason_id, "versionMajor", version_major); json_object_add_value_uint(reason_id, "versionMinor", version_minor); json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode)); - json_object_add_value_object(reason_id, "DriveStatus", json_object_new_string_len(ri1_0->DriveStatus, sizeof(ri1_0->DriveStatus))); + json_object_add_value_object(reason_id, "driveStatus", + json_object_new_string_len(ri1_0->DriveStatus, + sizeof(ri1_0->DriveStatus))); if (version_major == 1) { switch (version_minor) { case 0: diff --git a/plugins/solidigm/solidigm-telemetry/meson.build b/plugins/solidigm/solidigm-telemetry/meson.build index 53ab452c..96273b70 100644 --- a/plugins/solidigm/solidigm-telemetry/meson.build +++ b/plugins/solidigm/solidigm-telemetry/meson.build @@ -3,4 +3,5 @@ sources += [ 'plugins/solidigm/solidigm-telemetry/header.c', 'plugins/solidigm/solidigm-telemetry/config.c', 'plugins/solidigm/solidigm-telemetry/data-area.c', + 'plugins/solidigm/solidigm-telemetry/nlog.c', ] diff --git a/plugins/solidigm/solidigm-telemetry/nlog.c b/plugins/solidigm/solidigm-telemetry/nlog.c new file mode 100644 index 00000000..43b8918f --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/nlog.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "nlog.h" +#include "config.h" +#include +#include +#include + +#define LOG_ENTRY_HEADER_SIZE 1 +#define LOG_ENTRY_TIMESTAMP_SIZE 2 +#define LOG_ENTRY_NUM_ARGS_MAX 8 +#define LOG_ENTRY_MAX_SIZE (LOG_ENTRY_HEADER_SIZE + LOG_ENTRY_TIMESTAMP_SIZE + \ + LOG_ENTRY_NUM_ARGS_MAX) +#define NUM_ARGS_MASK ((1 << ((int)log2(LOG_ENTRY_NUM_ARGS_MAX)+1)) - 1) +#define MAX_HEADER_MISMATCH_TRACK 10 + +static int formats_find(struct json_object *formats, uint32_t val, struct json_object **format) +{ + char hex_header[STR_HEX32_SIZE]; + + snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", val); + return json_object_object_get_ex(formats, hex_header, format); +} + +static uint32_t nlog_get_pos(const uint32_t *nlog, const uint32_t nlog_size, int pos) +{ + return nlog[pos % nlog_size]; +} + +static uint32_t nlog_get_events(const uint32_t *nlog, const uint32_t nlog_size, int start_offset, + struct json_object *formats, struct json_object *events, uint32_t *tail_mismatches) +{ + uint32_t event_count = 0; + int last_bad_header_pos = nlog_size + 1; // invalid nlog offset + uint32_t tail_count = 0; + + for (int i = nlog_size - start_offset - 1; i >= -start_offset; i--) { + struct json_object *format; + uint32_t header = nlog_get_pos(nlog, nlog_size, i); + uint32_t num_data; + + if (header == 0 || !formats_find(formats, header, &format)) { + if (event_count > 0) { + //check if fould circular buffer tail + if (i != (last_bad_header_pos - 1)) { + if (tail_mismatches && + (tail_count < MAX_HEADER_MISMATCH_TRACK)) + tail_mismatches[tail_count] = header; + tail_count++; + } + last_bad_header_pos = i; + } + continue; + } + num_data = header & NUM_ARGS_MASK; + if (events) { + struct json_object *event = json_object_new_array(); + struct json_object *param = json_object_new_array(); + uint32_t val = nlog_get_pos(nlog, nlog_size, i - 1); + + json_object_array_add(events, event); + json_object_array_add(event, json_object_new_int64(val)); + val = nlog_get_pos(nlog, nlog_size, i - 2); + json_object_array_add(event, json_object_new_int64(val)); + json_object_array_add(event, json_object_new_int64(header)); + json_object_array_add(event, param); + for (uint32_t j = 0; j < num_data; j++) { + val = nlog_get_pos(nlog, nlog_size, i - 3 - j); + json_object_array_add(param, json_object_new_int64(val)); + } + json_object_get(format); + json_object_array_add(event, format); + } + i -= 2 + num_data; + event_count++; + } + return tail_count; +} + +int solidigm_nlog_parse(const char *buffer, uint64_t buff_size, struct json_object *formats, + struct json_object *metadata, struct json_object *output) +{ + uint32_t smaller_tail_count = UINT32_MAX; + int best_offset = 0; + uint32_t offset_tail_mismatches[LOG_ENTRY_MAX_SIZE][MAX_HEADER_MISMATCH_TRACK]; + struct json_object *events = json_object_new_array(); + const uint32_t *nlog = (uint32_t *)buffer; + const uint32_t nlog_size = buff_size / sizeof(uint32_t); + + for (int i = 0; i < LOG_ENTRY_MAX_SIZE; i++) { + uint32_t tail_count = nlog_get_events(nlog, nlog_size, i, formats, NULL, + offset_tail_mismatches[i]); + if (tail_count < smaller_tail_count) { + best_offset = i; + smaller_tail_count = tail_count; + } + if (tail_count == 0) + break; + } + if (smaller_tail_count > 1) { + const char *name = ""; + int media_bank = -1; + char str_mismatches[(STR_HEX32_SIZE + 1) * MAX_HEADER_MISMATCH_TRACK]; + int pos = 0; + int show_mismatch_num = smaller_tail_count < MAX_HEADER_MISMATCH_TRACK ? + smaller_tail_count : MAX_HEADER_MISMATCH_TRACK; + struct json_object *jobj; + + if (json_object_object_get_ex(metadata, "objName", &jobj)) + name = json_object_get_string(jobj); + if (json_object_object_get_ex(metadata, "mediaBankId", &jobj)) + media_bank = json_object_get_int(jobj); + + for (int i = 0; i < show_mismatch_num; i++) + pos += snprintf(&str_mismatches[pos], STR_HEX32_SIZE + 1, "0x%08X ", + offset_tail_mismatches[best_offset][i]); + + SOLIDIGM_LOG_WARNING("%s:%d with %d header mismatches ( %s). Configuration file may be missing format headers.", + name, media_bank, smaller_tail_count, str_mismatches); + } + nlog_get_events(nlog, nlog_size, best_offset, formats, events, NULL); + + json_object_object_add(output, "events", events); + return 0; +} diff --git a/plugins/solidigm/solidigm-telemetry/nlog.h b/plugins/solidigm/solidigm-telemetry/nlog.h new file mode 100644 index 00000000..f33aa454 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/nlog.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include "telemetry-log.h" + +int solidigm_nlog_parse(const char *buffer, uint64_t bufer_size, + struct json_object *formats, struct json_object *metadata, + struct json_object *output); -- 2.49.0