summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2018-06-14 01:08:30 +0200
committerQuentin Young <qlyoung@cumulusnetworks.com>2018-08-14 22:02:05 +0200
commit7b526b616873cf360e690955e2ab36c2d9f04507 (patch)
treea7ccaad148df14e41604537dbdce156ff2b1c844 /lib
parentdoc: Add missing flowspec.rst to distribution tar file (diff)
downloadfrr-7b526b616873cf360e690955e2ab36c2d9f04507.tar.xz
frr-7b526b616873cf360e690955e2ab36c2d9f04507.zip
lib: add error reference system
* 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>
Diffstat (limited to 'lib')
-rw-r--r--lib/ferr.c100
-rw-r--r--lib/ferr.h30
-rw-r--r--lib/log.h5
3 files changed, 135 insertions, 0 deletions
diff --git a/lib/ferr.c b/lib/ferr.c
index 45574520a..ccf2f853e 100644
--- a/lib/ferr.c
+++ b/lib/ferr.c
@@ -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)
@@ -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);
diff --git a/lib/ferr.h b/lib/ferr.h
index 2f100c1b0..5efdc6bd6 100644
--- a/lib/ferr.h
+++ b/lib/ferr.h
@@ -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
@@ -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
diff --git a/lib/log.h b/lib/log.h
index 07eb6d5bd..a2546298a 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -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