Skip to content

Commit 0d4aaa3

Browse files
lgdacunhigaw
authored andcommitted
plugin/solidigm: Additional product Telemetry parsing support.
New skhT telemetry structure support. Signed-off-by: Leonardo da Cunha <[email protected]>
1 parent 2236f57 commit 0d4aaa3

File tree

11 files changed

+912
-43
lines changed

11 files changed

+912
-43
lines changed

plugins/solidigm/solidigm-nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#include "cmd.h"
1515

16-
#define SOLIDIGM_PLUGIN_VERSION "1.12"
16+
#define SOLIDIGM_PLUGIN_VERSION "1.13"
1717

1818
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
1919
COMMAND_LIST(

plugins/solidigm/solidigm-telemetry/config.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,34 @@ static bool config_get_by_version(const struct json_object *obj, int version_maj
2727

2828
if (!json_object_object_get_ex(obj, str_key, &major_obj))
2929
return false;
30-
if (!json_object_object_get_ex(major_obj, str_subkey, value))
30+
if (!json_object_object_get_ex(major_obj, str_subkey, value))
3131
return false;
3232
return value != NULL;
3333
}
3434

35-
bool solidigm_config_get_struct_by_token_version(const struct json_object *config, int token_id,
35+
bool sldm_config_get_struct_by_key_version(const struct json_object *config, char *key,
3636
int version_major, int version_minor,
3737
struct json_object **value)
3838
{
3939
struct json_object *token = NULL;
40-
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
41-
42-
snprintf(str_key, sizeof(str_key), "%d", token_id);
43-
if (!json_object_object_get_ex(config, str_key, &token))
40+
if (!json_object_object_get_ex(config, key, &token))
4441
return false;
45-
if (!config_get_by_version(token, version_major, version_minor, value))
42+
if (!config_get_by_version(token, version_major, version_minor, value))
4643
return false;
4744
return value != NULL;
4845
}
4946

47+
bool solidigm_config_get_struct_by_token_version(const struct json_object *config, int token_id,
48+
int version_major, int version_minor,
49+
struct json_object **value)
50+
{
51+
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
52+
53+
snprintf(str_key, sizeof(str_key), "%d", token_id);
54+
return sldm_config_get_struct_by_key_version(config, str_key,
55+
version_major, version_minor, value);
56+
}
57+
5058
const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token)
5159
{
5260
struct json_object *nlog_names = NULL;

plugins/solidigm/solidigm-telemetry/config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
#define STR_HEX32_SIZE sizeof("0x00000000")
1111

12+
bool sldm_config_get_struct_by_key_version(const struct json_object *config, char *key,
13+
int version_major, int version_minor,
14+
struct json_object **value);
1215
bool solidigm_config_get_struct_by_token_version(const struct json_object *obj,
1316
int key, int subkey,
1417
int subsubkey,

plugins/solidigm/solidigm-telemetry/data-area.c

Lines changed: 130 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,55 @@
1111
#include "data-area.h"
1212
#include "config.h"
1313
#include "nlog.h"
14+
#include "skht.h"
1415
#include <ctype.h>
1516

16-
#define SIGNED_INT_PREFIX "int"
17-
#define BITS_IN_BYTE 8
17+
#define SIGNED_int_PREFIX "int"
18+
#define SIGNED_INT_PREFIX "INT"
1819

1920
#define MAX_WARNING_SIZE 1024
2021
#define MAX_ARRAY_RANK 16
2122
#define NLOG_HEADER_ID 101
2223

24+
static bool uint8_array_to_string(const struct telemetry_log *tl,
25+
uint64_t offset_bit, uint32_t size_bit,
26+
uint32_t array_size,
27+
struct json_object **str_obj)
28+
{
29+
uint32_t offset_byte = (uint32_t)offset_bit / NUM_BITS_IN_BYTE;
30+
31+
if (size_bit != 8) {
32+
*str_obj = json_object_new_string(
33+
"Error: Only UINT8 arrays can be converted to strings");
34+
return false;
35+
}
36+
37+
if (offset_byte > (tl->log_size - array_size)) {
38+
char err_msg[MAX_WARNING_SIZE];
39+
40+
snprintf(err_msg, MAX_WARNING_SIZE,
41+
"String offset greater than binary size (%u > %zu).",
42+
offset_byte, tl->log_size);
43+
*str_obj = json_object_new_string(err_msg);
44+
return false;
45+
}
46+
47+
// Get direct pointer to the UINT8 array in the telemetry log
48+
const uint8_t *data_ptr = (const uint8_t *)tl->log + offset_byte;
49+
50+
// Calculate actual string length (stopping at null terminator if found)
51+
size_t actual_length = 0;
52+
53+
for (actual_length = 0; actual_length < array_size; actual_length++) {
54+
if (data_ptr[actual_length] == '\0')
55+
break;
56+
}
57+
58+
// Create JSON string directly from the data without intermediate buffer
59+
*str_obj = json_object_new_string_len((const char *)data_ptr, actual_length);
60+
61+
return true;
62+
}
2363

2464
static void reverse_string(char *buff, size_t len)
2565
{
@@ -54,23 +94,23 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
5494

5595
return false;
5696
}
57-
additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0;
58-
offset_byte = (uint32_t)offset_bit / BITS_IN_BYTE;
97+
additional_size_byte = (size_bit - 1) ? (size_bit - 1) / NUM_BITS_IN_BYTE : 0;
98+
offset_byte = (uint32_t)offset_bit / NUM_BITS_IN_BYTE;
5999

60100
if (offset_byte > (tl->log_size - additional_size_byte)) {
61101
char err_msg[MAX_WARNING_SIZE];
62102

63103
snprintf(err_msg, MAX_WARNING_SIZE,
64-
"Value offset greater than binary size (%u > %zu).",
65-
offset_byte, tl->log_size);
104+
"Value offset greater than binary size (%u + %u > %zu).",
105+
offset_byte, additional_size_byte, tl->log_size);
66106
*val_obj = json_object_new_string(err_msg);
67107

68108
return false;
69109
}
70110

71-
offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * BITS_IN_BYTE));
111+
offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * NUM_BITS_IN_BYTE));
72112

73-
if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) {
113+
if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * NUM_BITS_IN_BYTE)) {
74114
char err_msg[MAX_WARNING_SIZE];
75115

76116
snprintf(err_msg, MAX_WARNING_SIZE,
@@ -96,17 +136,19 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
96136
return true;
97137
}
98138

99-
static int telemetry_log_structure_parse(const struct telemetry_log *tl,
100-
struct json_object *struct_def,
101-
uint64_t parent_offset_bit,
102-
struct json_object *output,
103-
struct json_object *metadata)
139+
int sldm_telemetry_structure_parse(const struct telemetry_log *tl,
140+
struct json_object *struct_def,
141+
uint64_t parent_offset_bit,
142+
struct json_object *output,
143+
struct json_object *metadata)
104144
{
105145
struct json_object *obj_arraySizeArray = NULL;
106146
struct json_object *obj = NULL;
107147
struct json_object *obj_memberList;
108148
struct json_object *major_dimension = NULL;
109149
struct json_object *sub_output;
150+
struct json_object *obj_arraySizeIndicator = NULL;
151+
bool force_array = false;
110152
bool is_enumeration = false;
111153
bool has_member_list;
112154
const char *type = "";
@@ -115,7 +157,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
115157
uint64_t offset_bit;
116158
uint32_t size_bit;
117159
uint64_t linear_array_pos_bit;
118-
uint32_t array_size_dimension[MAX_ARRAY_RANK];
160+
uint32_t array_size_dimension[MAX_ARRAY_RANK] = { 0 };
119161

120162
if (!json_object_object_get_ex(struct_def, "name", &obj)) {
121163
SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s",
@@ -186,6 +228,26 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
186228
array_size_dimension[i] = json_object_get_int(dimension);
187229
major_dimension = dimension;
188230
}
231+
232+
// Check for arraySizeIndicator property to support dynamic array sizes
233+
if (json_object_object_get_ex(struct_def, "arraySizeIndicator", &obj_arraySizeIndicator)) {
234+
const char *indicator_name = json_object_get_string(obj_arraySizeIndicator);
235+
236+
force_array = true; // Force array output even if size is 1
237+
238+
// Look for the indicator property in the parent object (output)
239+
if (indicator_name && output) {
240+
struct json_object *parent_prop = NULL;
241+
242+
if (json_object_object_get_ex(output, indicator_name, &parent_prop)) {
243+
// Get the dynamic array size from the parent property
244+
uint32_t dynamic_size = json_object_get_int(parent_prop);
245+
246+
array_size_dimension[0] = dynamic_size;
247+
}
248+
}
249+
}
250+
189251
if (array_rank > 1) {
190252
uint32_t linear_pos_per_index = array_size_dimension[0];
191253
uint32_t prev_index_offset_bit = 0;
@@ -214,8 +276,8 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
214276
offset = parent_offset_bit + prev_index_offset_bit;
215277

216278
json_object_array_add(dimension_output, sub_array);
217-
telemetry_log_structure_parse(tl, struct_def,
218-
offset, sub_array, NULL);
279+
sldm_telemetry_structure_parse(tl, struct_def,
280+
offset, sub_array, NULL);
219281
prev_index_offset_bit += linear_pos_per_index * size_bit;
220282
}
221283

@@ -228,7 +290,23 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
228290
linear_array_pos_bit = 0;
229291
sub_output = output;
230292

231-
if (array_size_dimension[0] > 1) {
293+
if (array_size_dimension[0] > 1 || force_array) {
294+
// Check if this is a UINT8 array that should be treated as a string
295+
if (strcmp(type, "UINT8") == 0 && !force_array) {
296+
// Handle UINT8 arrays as strings
297+
struct json_object *str_obj = NULL;
298+
uint64_t offset = parent_offset_bit + offset_bit;
299+
300+
if (uint8_array_to_string(tl, offset, size_bit,
301+
array_size_dimension[0], &str_obj)) {
302+
json_object_object_add(output, name, str_obj);
303+
return 0;
304+
}
305+
306+
// If string conversion failed, fall back to normal array processing
307+
json_object_put(str_obj);
308+
}
309+
232310
sub_output = json_create_array();
233311
if (json_object_get_type(output) == json_type_array)
234312
json_object_array_add(output, sub_output);
@@ -238,13 +316,16 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
238316

239317
for (uint32_t j = 0; j < array_size_dimension[0]; j++) {
240318
if (is_enumeration || !has_member_list) {
241-
bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1);
319+
bool is_signed = !strncmp(type, SIGNED_int_PREFIX,
320+
sizeof(SIGNED_int_PREFIX)-1) ||
321+
!strncmp(type, SIGNED_INT_PREFIX,
322+
sizeof(SIGNED_INT_PREFIX)-1);
242323
struct json_object *val_obj;
243324
uint64_t offset;
244325

245326
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
246327
if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) {
247-
if (array_size_dimension[0] > 1)
328+
if (array_size_dimension[0] > 1 || force_array)
248329
json_object_array_put_idx(sub_output, j, val_obj);
249330
else
250331
json_object_object_add(sub_output, name, val_obj);
@@ -256,10 +337,10 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
256337
json_free_object(val_obj);
257338
}
258339
} else {
259-
struct json_object *sub_sub_output = json_create_object();
340+
struct json_object *sub_sub_output = json_object_new_object();
260341
int num_members;
261342

262-
if (array_size_dimension[0] > 1)
343+
if (array_size_dimension[0] > 1 || force_array)
263344
json_object_array_put_idx(sub_output, j, sub_sub_output);
264345
else
265346
json_object_add_value_object(sub_output, name, sub_sub_output);
@@ -270,8 +351,8 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
270351
uint64_t offset;
271352

272353
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
273-
telemetry_log_structure_parse(tl, member, offset,
274-
sub_sub_output, NULL);
354+
sldm_telemetry_structure_parse(tl, member, offset,
355+
sub_sub_output, NULL);
275356
}
276357
}
277358
linear_array_pos_bit += size_bit;
@@ -393,9 +474,13 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
393474
bool has_struct;
394475
const char *nlog_name = NULL;
395476
uint32_t header_offset = sizeof(const struct telemetry_object_header);
477+
struct json_object *tele_obj_item;
478+
struct json_object *parsed_struct;
479+
struct json_object *obj_hasTelemObjHdr = NULL;
480+
uint64_t object_file_offset;
396481

397482
if ((char *)&toc->items[i] >
398-
(((char *)toc) + da_size - sizeof(const struct toc_item))) {
483+
(((char *)toc) + da_size - sizeof(const struct toc_item))) {
399484
SOLIDIGM_LOG_WARNING(
400485
"Warning: Data Area %d, Table of Contents item %d crossed Data Area size.",
401486
da, i);
@@ -409,7 +494,7 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
409494
continue;
410495
}
411496

412-
toc_item = json_create_object();
497+
toc_item = json_object_new_object();
413498
json_object_array_add(toc_array, toc_item);
414499
json_object_add_value_uint(toc_item, "dataArea", da);
415500
json_object_add_value_uint(toc_item, "dataAreaIndex", i);
@@ -443,16 +528,14 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
443528
header->versionMinor,
444529
&structure_definition);
445530
}
446-
struct json_object *tele_obj_item = json_create_object();
531+
tele_obj_item = json_object_new_object();
447532

448533
json_object_array_add(tele_obj_array, tele_obj_item);
449534
json_object_get(toc_item);
450535
json_object_add_value_object(tele_obj_item, "metadata", toc_item);
451-
struct json_object *parsed_struct = json_create_object();
536+
parsed_struct = json_object_new_object();
452537

453538
json_object_add_value_object(tele_obj_item, "objectData", parsed_struct);
454-
struct json_object *obj_hasTelemObjHdr = NULL;
455-
uint64_t object_file_offset;
456539

457540
if (json_object_object_get_ex(structure_definition,
458541
"hasTelemObjHdr",
@@ -464,8 +547,8 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
464547
}
465548
object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset;
466549
if (has_struct) {
467-
telemetry_log_structure_parse(tl, structure_definition,
468-
BITS_IN_BYTE * object_file_offset,
550+
sldm_telemetry_structure_parse(tl, structure_definition,
551+
NUM_BITS_IN_BYTE * object_file_offset,
469552
parsed_struct, toc_item);
470553
}
471554
// NLOGs have different parser from other Telemetry objects
@@ -478,7 +561,7 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
478561
if (json_object_object_get_ex(structure_definition, "sizeBit",
479562
&header_sizeBits))
480563
header_offset = json_object_get_int(header_sizeBits) /
481-
BITS_IN_BYTE;
564+
NUM_BITS_IN_BYTE;
482565
// Overwrite nlogName with correct type
483566
if (json_object_object_get_ex(parsed_struct, "nlogSelect",
484567
&header_nlogSelect) &&
@@ -510,17 +593,18 @@ void solidigm_telemetry_log_da1_check_ocp(struct telemetry_log *tl)
510593
const uint64_t ocp_telemetry_uuid[] = {0xBC73719D87E64EFA, 0xBA560A9C3043424C};
511594
const uint64_t *log_uuid = (uint64_t *) &tl->log->data_area[16];
512595

513-
tl->is_ocp = tl->log_size >= (&tl->log->data_area[32] - (uint8_t *) tl->log) &&
596+
tl->is_ocp = tl->log_size >= (size_t)(&tl->log->data_area[32] - (uint8_t *) tl->log) &&
514597
log_uuid[0] == ocp_telemetry_uuid[0] && log_uuid[1] == ocp_telemetry_uuid[1];
515598
}
516599

517600
int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
518601
enum nvme_telemetry_da last_da)
519602
{
520-
struct json_object *tele_obj_array = json_create_array();
521-
struct json_object *toc_array = json_create_array();
603+
struct json_object *tele_obj_array = NULL;
604+
struct json_object *toc_array = NULL;
522605

523606
solidigm_telemetry_log_da1_check_ocp(tl);
607+
sldm_telemetry_da2_check_skhT(tl);
524608
solidigm_telemetry_log_header_parse(tl);
525609
solidigm_telemetry_log_cod_parse(tl);
526610
if (tl->configuration) {
@@ -529,6 +613,17 @@ int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl,
529613
if (tl->is_ocp)
530614
first_da = NVME_TELEMETRY_DA_3;
531615

616+
if (tl->is_skhT) {
617+
if (last_da >= NVME_TELEMETRY_DA_2)
618+
sldm_telemetry_skhT_parse(tl);
619+
if (last_da >= NVME_TELEMETRY_DA_3)
620+
sldm_telemetry_sktT_segment_parse(tl, toc_array,
621+
tele_obj_array);
622+
return 0;
623+
}
624+
625+
tele_obj_array = json_create_array();
626+
toc_array = json_create_array();
532627
json_object_add_value_array(tl->root, "tableOfContents", toc_array);
533628
json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array);
534629

0 commit comments

Comments
 (0)