Skip to content

Commit

Permalink
lib: add error reference system
Browse files Browse the repository at this point in the history
* Add zlog_* function to log with a reference code
* Add ability to track reference cards for errors to ferr.[ch]
* Assign some reference code ranges

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
  • Loading branch information
qlyoung committed Jun 13, 2018
1 parent e789c03 commit 781f42c
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
100 changes: 100 additions & 0 deletions lib/ferr.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@
#include "vty.h"
#include "jhash.h"
#include "memory.h"
#include "hash.h"
#include "command.h"

DEFINE_MTYPE_STATIC(LIB, ERRINFO, "error information")

/*
* Thread-specific key for temporary storage of allocated ferr.
*/
static pthread_key_t errkey;

static void ferr_free(void *arg)
Expand All @@ -46,6 +51,101 @@ static void err_key_fini(void)
pthread_key_delete(errkey);
}

/*
* Global shared hash table holding reference text for all defined errors.
*/
pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER;
struct hash *refs;

static int ferr_hash_cmp(const void *a, const void *b)
{
const struct ferr_ref *f_a = a;
const struct ferr_ref *f_b = b;

return f_a->code == f_b->code;
}

static inline unsigned int ferr_hash_key(void *a)
{
struct ferr_ref *f = a;

return f->code;
}

void ferr_ref_add(struct ferr_ref *ref)
{
pthread_mutex_lock(&refs_mtx);
{
hash_get(refs, ref, hash_alloc_intern);
}
pthread_mutex_unlock(&refs_mtx);
}

struct ferr_ref *ferr_ref_get(uint32_t code)
{
struct ferr_ref holder;
struct ferr_ref *ref;

holder.code = code;
pthread_mutex_lock(&refs_mtx);
{
ref = hash_lookup(refs, &holder);
}
pthread_mutex_unlock(&refs_mtx);

return ref;
}

void ferr_ref_display(struct vty *vty, uint32_t code)
{
struct ferr_ref *ref = ferr_ref_get(code);

if (!ref) {
vty_out(vty, "Code %d - Unknown\n", code);
return;
}

vty_out(vty, "Error Code %d - %s\n", code, ref->title);
vty_out(vty, "--------------------------------------\n");
vty_out(vty, "\nDescription:\n%s\n\nRecommendation:\n%s\n\n",
ref->description, ref->suggestion);
}

DEFUN_NOSH(show_error_code,
show_error_code_cmd,
"show error (0-4294967296)",
SHOW_STR
"Information on errors\n"
"Error code to get info about\n")
{
uint32_t arg = strtoul(argv[2]->arg, NULL, 10);

ferr_ref_display(vty, arg);
return CMD_SUCCESS;
}

void ferr_ref_init(void)
{
pthread_mutex_lock(&refs_mtx);
{
refs = hash_create(ferr_hash_key, ferr_hash_cmp,
"Error Reference Texts");
}
pthread_mutex_unlock(&refs_mtx);

install_element(VIEW_NODE, &show_error_code_cmd);
}

void ferr_ref_fini(void)
{
pthread_mutex_lock(&refs_mtx);
{
hash_free(refs);
refs = NULL;
}
pthread_mutex_unlock(&refs_mtx);
}

const struct ferr *ferr_get_last(ferr_r errval)
{
struct ferr *last_error = pthread_getspecific(errkey);
Expand Down
30 changes: 30 additions & 0 deletions lib/ferr.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <limits.h>
#include <errno.h>

#include "vty.h"

/* return type when this error indication stuff is used.
*
* guaranteed to have boolean evaluation to "false" when OK, "true" when error
Expand Down Expand Up @@ -93,6 +95,34 @@ struct ferr {
char pathname[PATH_MAX];
};

/* Numeric ranges assigned to daemons for use as error codes. */
#define LIB_FERR_START 0x01000001
#define LIB_FERR_END 0x01FFFFFF
#define BGP_FERR_START 0x02000000
#define BGP_FERR_END 0x02FFFFFF
#define OSPF_FERR_START 0x03000001
#define OSPF_FERR_END 0x03FFFFFF
#define ZEBRA_FERR_START 0x04000001
#define ZEBRA_FERR_END 0x04FFFFFF

struct ferr_ref {
/* Unique error code displayed to end user as a reference. -1 means
* this is an uncoded error that does not have reference material. */
uint32_t code;
/* Ultra brief title */
const char *title;
/* Brief description of error */
const char *description;
/* Remedial suggestion */
const char *suggestion;
};

void ferr_ref_add(struct ferr_ref *ref);
struct ferr_ref *ferr_ref_get(uint32_t code);
void ferr_ref_display(struct vty *, uint32_t code);
void ferr_ref_init(void);
void ferr_ref_fini(void);

/* get error details.
*
* NB: errval/ferr_r does NOT carry the full error information. It's only
Expand Down
5 changes: 5 additions & 0 deletions lib/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ extern void zlog_info(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
extern void zlog_notice(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);
extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2);

/* For logs which have error codes associated with them */
#define zlog_ferr(ferr_id, format, ...) \
zlog_err("[EC %d] " format, ferr_id, ##__VA_ARGS__)


extern void zlog_thread_info(int log_level);

/* Set logging level for the given destination. If the log_level
Expand Down
16 changes: 16 additions & 0 deletions vtysh/vtysh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,21 @@ DEFUN (vtysh_show_debugging_hashtable,
"Hashtable statistics for %s:\n");
}

DEFUN (vtysh_show_error_code,
vtysh_show_error_code_cmd,
"show error (0-4294967296)",
SHOW_STR
"Information on errors\n"
"Error code to get info about\n")
{
char cmd[256];

snprintf(cmd, sizeof(cmd), "do show error %s", argv[2]->arg);

/* FIXME: Needs to determine which daemon to send to via code ranges */
return show_per_daemon(cmd, "");
}

/* Memory */
DEFUN (vtysh_show_memory,
vtysh_show_memory_cmd,
Expand Down Expand Up @@ -3707,6 +3722,7 @@ void vtysh_init_vty(void)

/* debugging */
install_element(VIEW_NODE, &vtysh_show_debugging_cmd);
install_element(VIEW_NODE, &vtysh_show_error_code_cmd);
install_element(VIEW_NODE, &vtysh_show_debugging_hashtable_cmd);
install_element(ENABLE_NODE, &vtysh_debug_all_cmd);
install_element(CONFIG_NODE, &vtysh_debug_all_cmd);
Expand Down

0 comments on commit 781f42c

Please sign in to comment.