Skip to content
Closed
21 changes: 16 additions & 5 deletions doc/user/basic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,17 @@ Basic Config Commands
is used to start the daemon then this command is turned on by default
and cannot be turned off and the [no] form of the command is dissallowed.

.. clicmd:: log-filter WORD [DAEMON]
.. clicmd:: log filtered-file [FILENAME [LEVEL]]

Configure a destination file for filtered logs with the
:clicmd:`log filter-text WORD` command.

.. clicmd:: log filter-text WORD

This command forces logs to be filtered on a specific string. A log message
will only be printed if it matches on one of the filters in the log-filter
table. Can be daemon independent.
table. The filter only applies to file logging targets configured with
:clicmd:`log filtered-file [FILENAME [LEVEL]]`.

.. note::

Expand All @@ -183,10 +189,15 @@ Basic Config Commands
Log filters prevent this but you should still expect a small performance
hit due to filtering each of all those logs.

.. clicmd:: log-filter clear [DAEMON]
.. note::

This setting is not saved to ``frr.conf`` and not shown in
:clicmd:`show running-config`. It is intended for ephemeral debugging
purposes only.

.. clicmd:: clear log filter-text

This command clears all current filters in the log-filter table. Can be
daemon independent.
This command clears all current filters in the log-filter table.

.. clicmd:: service password-encryption

Expand Down
81 changes: 44 additions & 37 deletions lib/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,13 +900,31 @@ enum node_type node_parent(enum node_type node)
/* Execute command by argument vline vector. */
static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
struct vty *vty,
const struct cmd_element **cmd)
const struct cmd_element **cmd,
unsigned int up_level)
{
struct list *argv_list;
enum matcher_rv status;
const struct cmd_element *matched_element = NULL;
unsigned int i;
int xpath_index = vty->xpath_index;
int node = vty->node;

struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node);
/* only happens for legacy split config file load; need to check for
* a match before calling node_exit handlers below
*/
for (i = 0; i < up_level; i++) {
if (node <= CONFIG_NODE)
return CMD_NO_LEVEL_UP;

node = node_parent(node);

if (xpath_index > 0
&& vty_check_node_for_xpath_decrement(node, vty->node))
xpath_index--;
}

struct graph *cmdgraph = cmd_node_graph(cmdvec, node);
status = command_match(cmdgraph, vline, &argv_list, &matched_element);

if (cmd)
Expand All @@ -926,12 +944,16 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
}
}

for (i = 0; i < up_level; i++)
cmd_exit(vty);

// build argv array from argv list
struct cmd_token **argv = XMALLOC(
MTYPE_TMP, argv_list->count * sizeof(struct cmd_token *));
struct listnode *ln;
struct cmd_token *token;
unsigned int i = 0;

i = 0;
for (ALL_LIST_ELEMENTS_RO(argv_list, ln, token))
argv[i++] = token;

Expand Down Expand Up @@ -1012,7 +1034,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
vector_lookup(vline, index));

ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED,
vty, cmd);
vty, cmd, 0);

vector_free(shifted_vline);
vty->node = onode;
Expand All @@ -1021,7 +1043,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
}

saved_ret = ret =
cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd);
cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0);

if (vtysh)
return saved_ret;
Expand All @@ -1038,7 +1060,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
onode))
vty->xpath_index--;
ret = cmd_execute_command_real(vline, FILTER_RELAXED,
vty, cmd);
vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
|| ret == CMD_NOT_MY_INSTANCE
|| ret == CMD_WARNING_CONFIG_FAILED)
Expand Down Expand Up @@ -1069,7 +1091,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
int cmd_execute_command_strict(vector vline, struct vty *vty,
const struct cmd_element **cmd)
{
return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd, 0);
}

/*
Expand Down Expand Up @@ -1220,6 +1242,7 @@ int command_config_read_one_line(struct vty *vty,
{
vector vline;
int ret;
unsigned up_level = 0;

vline = cmd_make_strvec(vty->buf);

Expand All @@ -1230,36 +1253,20 @@ int command_config_read_one_line(struct vty *vty,
/* Execute configuration command : this is strict match */
ret = cmd_execute_command_strict(vline, vty, cmd);

// Climb the tree and try the command again at each node
if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& vty->node != CONFIG_NODE) {
int saved_node = vty->node;
int saved_xpath_index = vty->xpath_index;

while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& vty->node > CONFIG_NODE) {
vty->node = node_parent(vty->node);
if (vty->xpath_index > 0
&& vty_check_node_for_xpath_decrement(vty->node,
saved_node))
vty->xpath_index--;
ret = cmd_execute_command_strict(vline, vty, cmd);
}

// If climbing the tree did not work then ignore the command and
// stay at the same node
if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING) {
vty->node = saved_node;
vty->xpath_index = saved_xpath_index;
}
}
/* The logic for trying parent nodes is in cmd_execute_command_real()
* since calling ->node_exit() correctly is a bit involved. This is
* also the only reason CMD_NO_LEVEL_UP exists.
*/
while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
&& !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
&& ret != CMD_SUCCESS && ret != CMD_WARNING
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& ret != CMD_NO_LEVEL_UP)
ret = cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd,
++up_level);

if (ret == CMD_NO_LEVEL_UP)
ret = CMD_ERR_NO_MATCH;

if (ret != CMD_SUCCESS &&
ret != CMD_WARNING &&
Expand Down
1 change: 1 addition & 0 deletions lib/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ struct cmd_node {
#define CMD_SUSPEND 12
#define CMD_WARNING_CONFIG_FAILED 13
#define CMD_NOT_MY_INSTANCE 14
#define CMD_NO_LEVEL_UP 15

/* Argc max counts. */
#define CMD_ARGC_MAX 256
Expand Down
4 changes: 4 additions & 0 deletions lib/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,11 @@ CPP_NOTICE("time to remove this CONFDATE block")
#define PRIx64 "Lx"

#else /* !_FRR_ATTRIBUTE_PRINTFRR */
#ifdef __NetBSD__
#define PRINTFRR(a, b) __attribute__((format(gnu_syslog, a, b)))
#else
#define PRINTFRR(a, b) __attribute__((format(printf, a, b)))
#endif

/* these should be typedefs, but might also be #define */
#ifdef uint64_t
Expand Down
10 changes: 7 additions & 3 deletions lib/log_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,14 @@ int zlog_filter_dump(char *buf, size_t max_size)
return len;
}

static int search_buf(const char *buf)
static int search_buf(const char *buf, size_t len)
{
char *found = NULL;

frr_with_mutex(&logfilterlock) {
for (int i = 0; i < zlog_filter_count; i++) {
found = strstr(buf, zlog_filters[i]);
found = memmem(buf, len, zlog_filters[i],
strlen(zlog_filters[i]));
if (found != NULL)
return 0;
}
Expand All @@ -131,10 +132,13 @@ static void zlog_filterfile_fd(struct zlog_target *zt, struct zlog_msg *msgs[],
{
struct zlog_msg *msgfilt[nmsgs];
size_t i, o = 0;
const char *text;
size_t text_len;

for (i = 0; i < nmsgs; i++) {
if (zlog_msg_prio(msgs[i]) >= LOG_DEBUG
&& search_buf(zlog_msg_text(msgs[i], NULL)) < 0)
&& (text = zlog_msg_text(msgs[i], &text_len))
&& search_buf(text, text_len) < 0)
continue;

msgfilt[o++] = msgs[i];
Expand Down
25 changes: 19 additions & 6 deletions lib/log_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define ZLOG_MAXLVL(a, b) MAX(a, b)

DEFINE_HOOK(zlog_rotate, (), ());
DEFINE_HOOK(zlog_cli_show, (struct vty * vty), (vty));

static const int log_default_lvl = LOG_DEBUG;

Expand All @@ -57,7 +58,7 @@ static struct zlog_cfg_filterfile zt_filterfile = {
},
};

static const char *zlog_progname;
const char *zlog_progname;
static const char *zlog_protoname;

static const struct facility_map {
Expand Down Expand Up @@ -94,7 +95,14 @@ static const char * const zlog_priority[] = {
"notifications", "informational", "debugging", NULL,
};

static const char *facility_name(int facility)
const char *zlog_priority_str(int priority)
{
if (priority > LOG_DEBUG)
return "???";
return zlog_priority[priority];
}

const char *facility_name(int facility)
{
const struct facility_map *fm;

Expand All @@ -104,7 +112,7 @@ static const char *facility_name(int facility)
return "";
}

static int facility_match(const char *str)
int facility_match(const char *str)
{
const struct facility_map *fm;

Expand Down Expand Up @@ -194,6 +202,8 @@ DEFUN_NOSH (show_logging,
vty_out(vty, "Record priority: %s\n",
(zt_file.record_priority ? "enabled" : "disabled"));
vty_out(vty, "Timestamp precision: %d\n", zt_file.ts_subsec);

hook_call(zlog_cli_show, vty);
return CMD_SUCCESS;
}

Expand Down Expand Up @@ -588,8 +598,9 @@ DEFUN (no_config_log_filterfile,

DEFPY (log_filter,
log_filter_cmd,
"[no] log-filter WORD$filter",
"[no] log filter-text WORD$filter",
NO_STR
"Logging control\n"
FILTER_LOG_STR
"String to filter by\n")
{
Expand All @@ -616,8 +627,9 @@ DEFPY (log_filter,
/* Clear all log filters */
DEFPY (log_filter_clear,
log_filter_clear_cmd,
"clear log-filter",
"clear log filter-text",
CLEAR_STR
"Logging control\n"
FILTER_LOG_STR)
{
zlog_filter_clear();
Expand All @@ -627,8 +639,9 @@ DEFPY (log_filter_clear,
/* Show log filter */
DEFPY (show_log_filter,
show_log_filter_cmd,
"show log-filter",
"show logging filter-text",
SHOW_STR
"Show current logging configuration\n"
FILTER_LOG_STR)
{
char log_filters[ZLOG_FILTERS_MAX * (ZLOG_FILTER_LENGTH_MAX + 3)] = "";
Expand Down
5 changes: 5 additions & 0 deletions lib/log_vty.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ extern void log_config_write(struct vty *vty);
extern int log_level_match(const char *s);
extern void log_show_syslog(struct vty *vty);

extern int facility_match(const char *str);
extern const char *facility_name(int facility);

DECLARE_HOOK(zlog_rotate, (), ());
extern void zlog_rotate(void);

DECLARE_HOOK(zlog_cli_show, (struct vty * vty), (vty));

#ifdef __cplusplus
}
#endif
Expand Down
Loading