131 lines
4.3 KiB
C
131 lines
4.3 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright (c) 2023 Solidigm.
|
|
*
|
|
* Author: leonardo.da.cunha@solidigm.com
|
|
*/
|
|
|
|
#include "nlog.h"
|
|
#include "config.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ccan/ilog/ilog.h"
|
|
|
|
#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)STATIC_ILOG_32(LOG_ENTRY_NUM_ARGS_MAX))) - 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;
|
|
}
|