diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2019-07-03 14:39:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-03 14:39:59 +0200 |
commit | 1df04926871d9c9029fc22037db799526b691e02 (patch) | |
tree | 578c50cb3e575b2f0c002f2d5893218246b4fa5a | |
parent | Merge pull request #4634 from mjstapp/vty_report_pids (diff) | |
parent | doc: Add a performance note for log filtering (diff) | |
download | frr-1df04926871d9c9029fc22037db799526b691e02.tar.xz frr-1df04926871d9c9029fc22037db799526b691e02.zip |
Run-time log filtering via vtysh commands (#4524)
Run-time log filtering via vtysh commands
-rw-r--r-- | doc/user/basic.rst | 28 | ||||
-rw-r--r-- | lib/command.h | 7 | ||||
-rw-r--r-- | lib/libfrr.c | 2 | ||||
-rw-r--r-- | lib/log.c | 195 | ||||
-rw-r--r-- | lib/log.h | 9 | ||||
-rw-r--r-- | lib/log_vty.c | 97 | ||||
-rw-r--r-- | lib/log_vty.h | 24 | ||||
-rw-r--r-- | lib/subdir.am | 4 | ||||
-rw-r--r-- | tests/topotests/bgp_multiview_topo1/README.md | 2 | ||||
-rw-r--r-- | tests/topotests/lib/topotest.py | 2 | ||||
-rw-r--r-- | tests/topotests/ospf6-topo1/README.md | 2 | ||||
-rw-r--r-- | vtysh/vtysh.c | 186 |
12 files changed, 496 insertions, 62 deletions
diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 3d3a75d4b..5509fd5f0 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -189,6 +189,29 @@ 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. +.. index:: + single: no log-filter WORD [DAEMON] + single: log-filter WORD [DAEMON] + +.. clicmd:: [no] log-filter WORD [DAEMON] + + 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. + + .. note:: + + Log filters help when you need to turn on debugs that cause significant + load on the system (enabling certain debugs can bring FRR to a halt). + Log filters prevent this but you should still expect a small performance + hit due to filtering each of all those logs. + +.. index:: log-filter clear [DAEMON] +.. clicmd:: log-filter clear [DAEMON] + + This command clears all current filters in the log-filter table. Can be + daemon independent. + .. index:: service password-encryption .. clicmd:: service password-encryption @@ -321,6 +344,11 @@ Terminal Mode Commands Shows the current configuration of the logging system. This includes the status of all logging destinations. +.. index:: show log-filter +.. clicmd:: show log-filter + + Shows the current log filters applied to each daemon. + .. index:: show memory .. clicmd:: show memory diff --git a/lib/command.h b/lib/command.h index fd8b56d62..de38563f9 100644 --- a/lib/command.h +++ b/lib/command.h @@ -396,6 +396,7 @@ struct cmd_node { #define SR_STR "Segment-Routing specific commands\n" #define WATCHFRR_STR "watchfrr information\n" #define ZEBRA_STR "Zebra information\n" +#define FILTER_LOG_STR "Filter Logs\n" #define CMD_VNI_RANGE "(1-16777215)" #define CONF_BACKUP_EXT ".sav" @@ -410,6 +411,12 @@ struct cmd_node { #define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nInterface name or neighbor tag\n" #define NEIGHBOR_ADDR_STR3 "Neighbor address\nIPv6 address\nInterface name\n" +/* Dameons lists */ +#define DAEMONS_STR \ + "For the zebra daemon\nFor the rip daemon\nFor the ripng daemon\nFor the ospf daemon\nFor the ospfv6 daemon\nFor the bgp daemon\nFor the isis daemon\nFor the pbr daemon\nFor the fabricd daemon\nFor the pim daemon\nFor the static daemon\nFor the sharpd daemon\nFor the vrrpd daemon\n" +#define DAEMONS_LIST \ + "<zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd|fabricd|pimd|staticd|sharpd|vrrpd>" + /* Prototypes. */ extern void install_node(struct cmd_node *, int (*)(struct vty *)); extern void install_default(enum node_type); diff --git a/lib/libfrr.c b/lib/libfrr.c index ed784fc73..3294a6129 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -31,6 +31,7 @@ #include "command.h" #include "version.h" #include "memory_vty.h" +#include "log_vty.h" #include "zclient.h" #include "log_int.h" #include "module.h" @@ -677,6 +678,7 @@ struct thread_master *frr_init(void) vty_init(master, di->log_always); memory_init(); + log_filter_cmd_init(); log_ref_init(); lib_error_init(); @@ -65,6 +65,110 @@ const char *zlog_priority[] = { "notifications", "informational", "debugging", NULL, }; +static char zlog_filters[ZLOG_FILTERS_MAX][ZLOG_FILTER_LENGTH_MAX + 1]; +static uint8_t zlog_filter_count; + +/* + * look for a match on the filter in the current filters, loglock must be held + */ +static int zlog_filter_lookup(const char *lookup) +{ + for (int i = 0; i < zlog_filter_count; i++) { + if (strncmp(lookup, zlog_filters[i], sizeof(zlog_filters[0])) + == 0) + return i; + } + return -1; +} + +void zlog_filter_clear(void) +{ + pthread_mutex_lock(&loglock); + zlog_filter_count = 0; + pthread_mutex_unlock(&loglock); +} + +int zlog_filter_add(const char *filter) +{ + pthread_mutex_lock(&loglock); + + int ret = 0; + + if (zlog_filter_count >= ZLOG_FILTERS_MAX) { + ret = 1; + goto done; + } + + if (zlog_filter_lookup(filter) != -1) { + /* Filter already present */ + ret = -1; + goto done; + } + + strlcpy(zlog_filters[zlog_filter_count], filter, + sizeof(zlog_filters[0])); + + if (zlog_filters[zlog_filter_count][0] == '\0') { + /* Filter was either empty or didn't get copied correctly */ + ret = -1; + goto done; + } + + zlog_filter_count++; + +done: + pthread_mutex_unlock(&loglock); + return ret; +} + +int zlog_filter_del(const char *filter) +{ + pthread_mutex_lock(&loglock); + + int found_idx = zlog_filter_lookup(filter); + int last_idx = zlog_filter_count - 1; + int ret = 0; + + if (found_idx == -1) { + /* Didn't find the filter to delete */ + ret = -1; + goto done; + } + + /* Adjust the filter array */ + memmove(zlog_filters[found_idx], zlog_filters[found_idx + 1], + (last_idx - found_idx) * sizeof(zlog_filters[0])); + + zlog_filter_count--; + +done: + pthread_mutex_unlock(&loglock); + return ret; +} + +/* Dump all filters to buffer, delimited by new line */ +int zlog_filter_dump(char *buf, size_t max_size) +{ + pthread_mutex_lock(&loglock); + + int ret = 0; + int len = 0; + + for (int i = 0; i < zlog_filter_count; i++) { + ret = snprintf(buf + len, max_size - len, " %s\n", + zlog_filters[i]); + len += ret; + if ((ret < 0) || ((size_t)len >= max_size)) { + len = -1; + goto done; + } + } + +done: + pthread_mutex_unlock(&loglock); + return len; +} + /* * write_wrapper * @@ -178,17 +282,32 @@ size_t quagga_timestamp(int timestamp_precision, char *buf, size_t buflen) return 0; } -/* Utility routine for current time printing. */ -static void time_print(FILE *fp, struct timestamp_control *ctl) +static inline void timestamp_control_render(struct timestamp_control *ctl) { if (!ctl->already_rendered) { ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf)); ctl->already_rendered = 1; } +} + +/* Utility routine for current time printing. */ +static void time_print(FILE *fp, struct timestamp_control *ctl) +{ + timestamp_control_render(ctl); fprintf(fp, "%s ", ctl->buf); } +static int time_print_buf(char *buf, int len, int max_size, + struct timestamp_control *ctl) +{ + timestamp_control_render(ctl); + + if (ctl->len + 1 >= (unsigned long)max_size) + return -1; + + return snprintf(buf + len, max_size - len, "%s ", ctl->buf); +} static void vzlog_file(struct zlog *zl, struct timestamp_control *tsctl, const char *proto_str, int record_priority, int priority, @@ -202,42 +321,92 @@ static void vzlog_file(struct zlog *zl, struct timestamp_control *tsctl, fflush(fp); } +/* Search a buf for the filter strings, loglock must be held */ +static int search_buf(const char *buf) +{ + char *found = NULL; + + for (int i = 0; i < zlog_filter_count; i++) { + found = strstr(buf, zlog_filters[i]); + if (found != NULL) + return 0; + } + + return -1; +} + +/* Filter out a log */ +static int vzlog_filter(struct zlog *zl, struct timestamp_control *tsctl, + const char *proto_str, int priority, const char *msg) +{ + int len = 0; + int ret = 0; + char buf[1024] = ""; + + ret = time_print_buf(buf, len, sizeof(buf), tsctl); + + len += ret; + if ((ret < 0) || ((size_t)len >= sizeof(buf))) + goto search; + + if (zl && zl->record_priority) + snprintf(buf + len, sizeof(buf) - len, "%s: %s: %s", + zlog_priority[priority], proto_str, msg); + else + snprintf(buf + len, sizeof(buf) - len, "%s: %s", proto_str, + msg); + +search: + return search_buf(buf); +} + /* va_list version of zlog. */ void vzlog(int priority, const char *format, va_list args) { pthread_mutex_lock(&loglock); - char proto_str[32]; + char proto_str[32] = ""; int original_errno = errno; - struct timestamp_control tsctl; + struct timestamp_control tsctl = {}; tsctl.already_rendered = 0; struct zlog *zl = zlog_default; char buf[256], *msg; - /* call external hook */ - hook_call(zebra_ext_log, priority, format, args); + if (zl == NULL) { + tsctl.precision = 0; + } else { + tsctl.precision = zl->timestamp_precision; + if (zl->instance) + sprintf(proto_str, "%s[%d]: ", zl->protoname, + zl->instance); + else + sprintf(proto_str, "%s: ", zl->protoname); + } msg = vasnprintfrr(MTYPE_TMP, buf, sizeof(buf), format, args); + /* If it doesn't match on a filter, do nothing with the debug log */ + if ((priority == LOG_DEBUG) && zlog_filter_count + && vzlog_filter(zl, &tsctl, proto_str, priority, msg)) { + pthread_mutex_unlock(&loglock); + goto out; + } + + /* call external hook */ + hook_call(zebra_ext_log, priority, format, args); + /* When zlog_default is also NULL, use stderr for logging. */ if (zl == NULL) { - tsctl.precision = 0; time_print(stderr, &tsctl); fprintf(stderr, "%s: %s\n", "unknown", msg); fflush(stderr); goto out; } - tsctl.precision = zl->timestamp_precision; /* Syslog output */ if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) syslog(priority | zlog_default->facility, "%s", msg); - if (zl->instance) - sprintf(proto_str, "%s[%d]: ", zl->protoname, zl->instance); - else - sprintf(proto_str, "%s: ", zl->protoname); - /* File output. */ if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) vzlog_file(zl, &tsctl, proto_str, zl->record_priority, priority, @@ -115,6 +115,15 @@ extern int zlog_reset_file(void); /* Rotate log. */ extern int zlog_rotate(void); +#define ZLOG_FILTERS_MAX 100 /* Max # of filters at once */ +#define ZLOG_FILTER_LENGTH_MAX 80 /* 80 character filter limit */ + +/* Add/Del/Dump log filters */ +extern void zlog_filter_clear(void); +extern int zlog_filter_add(const char *filter); +extern int zlog_filter_del(const char *filter); +extern int zlog_filter_dump(char *buf, size_t max_size); + const char *lookup_msg(const struct message *mz, int kz, const char *nf); /* Safe version of strerror -- never returns NULL. */ diff --git a/lib/log_vty.c b/lib/log_vty.c new file mode 100644 index 000000000..68d598f56 --- /dev/null +++ b/lib/log_vty.c @@ -0,0 +1,97 @@ +/* + * Logging - VTY code + * Copyright (C) 2019 Cumulus Networks, Inc. + * Stephen Worley + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "lib/log_vty.h" +#include "command.h" +#include "lib/vty.h" +#include "lib/log.h" +#ifndef VTYSH_EXTRACT_PL +#include "lib/log_vty_clippy.c" +#endif + +DEFPY (log_filter, + log_filter_cmd, + "[no] log-filter WORD$filter", + NO_STR + FILTER_LOG_STR + "String to filter by\n") +{ + int ret = 0; + + if (no) + ret = zlog_filter_del(filter); + else + ret = zlog_filter_add(filter); + + if (ret == 1) { + vty_out(vty, "%% filter table full\n"); + return CMD_WARNING; + } else if (ret != 0) { + vty_out(vty, "%% failed to %s log filter\n", + (no ? "remove" : "apply")); + return CMD_WARNING; + } + + vty_out(vty, " %s\n", filter); + return CMD_SUCCESS; +} + +/* Clear all log filters */ +DEFPY (log_filter_clear, + log_filter_clear_cmd, + "clear log-filter", + CLEAR_STR + FILTER_LOG_STR) +{ + zlog_filter_clear(); + return CMD_SUCCESS; +} + +/* Show log filter */ +DEFPY (show_log_filter, + show_log_filter_cmd, + "show log-filter", + SHOW_STR + FILTER_LOG_STR) +{ + char log_filters[ZLOG_FILTERS_MAX * (ZLOG_FILTER_LENGTH_MAX + 3)] = ""; + int len = 0; + + len = zlog_filter_dump(log_filters, sizeof(log_filters)); + + if (len == -1) { + vty_out(vty, "%% failed to get filters\n"); + return CMD_WARNING; + } + + if (len != 0) + vty_out(vty, "%s", log_filters); + + return CMD_SUCCESS; +} + +void log_filter_cmd_init(void) +{ + install_element(VIEW_NODE, &show_log_filter_cmd); + install_element(CONFIG_NODE, &log_filter_cmd); + install_element(CONFIG_NODE, &log_filter_clear_cmd); +} diff --git a/lib/log_vty.h b/lib/log_vty.h new file mode 100644 index 000000000..fa5627e4b --- /dev/null +++ b/lib/log_vty.h @@ -0,0 +1,24 @@ +/* + * Logging - VTY library + * Copyright (C) 2019 Cumulus Networks, Inc. + * Stephen Worley + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LOG_VTY_H__ +#define __LOG_VTY_H__ +extern void log_filter_cmd_init(void); +#endif /* __LOG_VTY_H__ */ diff --git a/lib/subdir.am b/lib/subdir.am index 8b6cbe2ae..3750d3620 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -42,6 +42,7 @@ lib_libfrr_la_SOURCES = \ lib/libfrr.c \ lib/linklist.c \ lib/log.c \ + lib/log_vty.c \ lib/md5.c \ lib/memory.c \ lib/memory_vty.c \ @@ -137,6 +138,8 @@ lib/northbound_cli_clippy.c: $(CLIPPY_DEPS) lib/northbound_cli.lo: lib/northbound_cli_clippy.c lib/vty_clippy.c: $(CLIPPY_DEPS) lib/vty.lo: lib/vty_clippy.c +lib/log_vty_clippy.c: $(CLIPPY_DEPS) +lib/log_vty.lo: lib/log_vty_clippy.c pkginclude_HEADERS += \ lib/agg_table.h \ @@ -179,6 +182,7 @@ pkginclude_HEADERS += \ lib/libospf.h \ lib/linklist.h \ lib/log.h \ + lib/log_vty.h \ lib/md5.h \ lib/memory.h \ lib/memory_vty.h \ diff --git a/tests/topotests/bgp_multiview_topo1/README.md b/tests/topotests/bgp_multiview_topo1/README.md index c5e615d25..2a2747344 100644 --- a/tests/topotests/bgp_multiview_topo1/README.md +++ b/tests/topotests/bgp_multiview_topo1/README.md @@ -94,7 +94,7 @@ Simplified `R1` config: Test is executed by running - vtysh -c "show log" | grep "Logging configuration for" + vtysh -c "show logging" | grep "Logging configuration for" on router `R1`. This should return the logging information for all daemons registered to Zebra and the list of running daemons is compared to the daemons started for this diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 86993665c..867f9f2f0 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -959,7 +959,7 @@ class Router(Node): global fatal_error - daemonsRunning = self.cmd('vtysh -c "show log" | grep "Logging configuration for"') + daemonsRunning = self.cmd('vtysh -c "show logging" | grep "Logging configuration for"') # Look for AddressSanitizer Errors in vtysh output and append to /tmp/AddressSanitzer.txt if found if checkAddressSanitizerError(daemonsRunning, self.name, "vtysh"): return "%s: vtysh killed by AddressSanitizer" % (self.name) diff --git a/tests/topotests/ospf6-topo1/README.md b/tests/topotests/ospf6-topo1/README.md index 28f68e8fa..526c019c6 100644 --- a/tests/topotests/ospf6-topo1/README.md +++ b/tests/topotests/ospf6-topo1/README.md @@ -102,7 +102,7 @@ Simplified `R3` config Test is executed by running - vtysh -c "show log" | grep "Logging configuration for" + vtysh -c "show logging" | grep "Logging configuration for" on each FRR router. This should return the logging information for all daemons registered to Zebra and the list of running daemons is compared to the daemons started for this test (`zebra` and `ospf6d`) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index c3aeb27eb..053848bfc 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -140,6 +140,21 @@ struct vtysh_client vtysh_client[] = { {.fd = -1, .name = "vrrpd", .flag = VTYSH_VRRPD, .next = NULL}, }; +/* Searches for client by name, returns index */ +static int vtysh_client_lookup(const char *name) +{ + int idx = -1; + + for (unsigned int i = 0; i < array_size(vtysh_client); i++) { + if (strmatch(vtysh_client[i].name, name)) { + idx = i; + break; + } + } + + return idx; +} + enum vtysh_write_integrated vtysh_write_integrated = WRITE_INTEGRATED_UNSPECIFIED; @@ -394,6 +409,23 @@ static int vtysh_client_execute(struct vtysh_client *head_client, return vtysh_client_run_all(head_client, line, 0, NULL, NULL); } +/* Execute by name */ +static int vtysh_client_execute_name(const char *name, const char *line) +{ + int ret = CMD_SUCCESS; + int idx_client = -1; + + idx_client = vtysh_client_lookup(name); + if (idx_client != -1) + ret = vtysh_client_execute(&vtysh_client[idx_client], line); + else { + vty_out(vty, "Client not found\n"); + ret = CMD_WARNING; + } + + return ret; +} + /* * Retrieve all running config from daemons and parse it with the vtysh config * parser. Returned output is not displayed to the user. @@ -2269,33 +2301,15 @@ DEFUN (vtysh_show_work_queues, DEFUN (vtysh_show_work_queues_daemon, vtysh_show_work_queues_daemon_cmd, - "show work-queues <zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd|fabricd|pimd|staticd>", + "show work-queues " DAEMONS_LIST, SHOW_STR "Work Queue information\n" - "For the zebra daemon\n" - "For the rip daemon\n" - "For the ripng daemon\n" - "For the ospf daemon\n" - "For the ospfv6 daemon\n" - "For the bgp daemon\n" - "For the isis daemon\n" - "For the pbr daemon\n" - "For the fabricd daemon\n" - "For the pim daemon\n" - "For the static daemon\n") + DAEMONS_STR) { int idx_protocol = 2; - unsigned int i; - int ret = CMD_SUCCESS; - - for (i = 0; i < array_size(vtysh_client); i++) { - if (strmatch(vtysh_client[i].name, argv[idx_protocol]->text)) - break; - } - ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n"); - - return ret; + return vtysh_client_execute_name(argv[idx_protocol]->text, + "show work-queues\n"); } DEFUNSH(VTYSH_ZEBRA, vtysh_link_params, vtysh_link_params_cmd, "link-params", @@ -2627,22 +2641,109 @@ DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password, return CMD_SUCCESS; } +/* Log filter */ +DEFUN (vtysh_log_filter, + vtysh_log_filter_cmd, + "[no] log-filter WORD ["DAEMONS_LIST"]", + NO_STR + FILTER_LOG_STR + "String to filter by\n" + DAEMONS_STR) +{ + char *filter = NULL; + char *daemon = NULL; + int found = 0; + int idx = 0; + int daemon_idx = 2; + int total_len = 0; + int len = 0; + + char line[ZLOG_FILTER_LENGTH_MAX + 20]; + + found = argv_find(argv, argc, "no", &idx); + if (found == 1) { + len = snprintf(line, sizeof(line), "no log-filter"); + daemon_idx += 1; + } else + len = snprintf(line, sizeof(line), "log-filter"); + + total_len += len; + + idx = 1; + found = argv_find(argv, argc, "WORD", &idx); + if (found != 1) { + vty_out(vty, "%% No filter string given\n"); + return CMD_WARNING; + } + filter = argv[idx]->arg; + + if (strnlen(filter, ZLOG_FILTER_LENGTH_MAX + 1) + > ZLOG_FILTER_LENGTH_MAX) { + vty_out(vty, "%% Filter is too long\n"); + return CMD_WARNING; + } + + len = snprintf(line + total_len, sizeof(line) - total_len, " %s\n", + filter); + + if ((len < 0) || (size_t)(total_len + len) > sizeof(line)) { + vty_out(vty, "%% Error buffering filter to daemons\n"); + return CMD_ERR_INCOMPLETE; + } + + if (argc >= (daemon_idx + 1)) + daemon = argv[daemon_idx]->text; + + if (daemon != NULL) { + vty_out(vty, "Applying log filter change to %s:\n", daemon); + return vtysh_client_execute_name(daemon, line); + } else + return show_per_daemon(line, + "Applying log filter change to %s:\n"); +} + +/* Clear log filters */ +DEFUN (vtysh_log_filter_clear, + vtysh_log_filter_clear_cmd, + "log-filter clear ["DAEMONS_LIST"]", + FILTER_LOG_STR + CLEAR_STR + DAEMONS_STR) +{ + char *daemon = NULL; + int daemon_idx = 2; + + char line[] = "clear log-filter\n"; + + if (argc >= (daemon_idx + 1)) + daemon = argv[daemon_idx]->text; + + if (daemon != NULL) { + vty_out(vty, "Clearing all filters applied to %s:\n", daemon); + return vtysh_client_execute_name(daemon, line); + } else + return show_per_daemon(line, + "Clearing all filters applied to %s:\n"); +} + +/* Show log filter */ +DEFUN (vtysh_show_log_filter, + vtysh_show_log_filter_cmd, + "show log-filter", + SHOW_STR + FILTER_LOG_STR) +{ + char line[] = "do show log-filter\n"; + + return show_per_daemon(line, "Log filters applied to %s:\n"); +} + DEFUN (vtysh_write_terminal, vtysh_write_terminal_cmd, - "write terminal [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd|staticd>]", + "write terminal ["DAEMONS_LIST"]", "Write running configuration to memory, network, or terminal\n" "Write to terminal\n" - "For the zebra daemon\n" - "For the rip daemon\n" - "For the ripng daemon\n" - "For the ospf daemon\n" - "For the ospfv6 daemon\n" - "For the ldpd daemon\n" - "For the bgp daemon\n" - "For the isis daemon\n" - "For the fabricd daemon\n" - "For the pim daemon\n" - "For the static daemon\n") + DAEMONS_STR) { unsigned int i; char line[] = "do write terminal\n"; @@ -2668,20 +2769,10 @@ DEFUN (vtysh_write_terminal, DEFUN (vtysh_show_running_config, vtysh_show_running_config_cmd, - "show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd|staticd>]", + "show running-config ["DAEMONS_LIST"]", SHOW_STR "Current operating configuration\n" - "For the zebra daemon\n" - "For the rip daemon\n" - "For the ripng daemon\n" - "For the ospf daemon\n" - "For the ospfv6 daemon\n" - "For the ldp daemon\n" - "For the bgp daemon\n" - "For the isis daemon\n" - "For the fabricd daemon\n" - "For the pim daemon\n" - "For the static daemon\n") + DAEMONS_STR) { return vtysh_write_terminal(self, vty, argc, argv); } @@ -3871,6 +3962,9 @@ void vtysh_init_vty(void) /* Logging */ install_element(VIEW_NODE, &vtysh_show_logging_cmd); + install_element(VIEW_NODE, &vtysh_show_log_filter_cmd); + install_element(CONFIG_NODE, &vtysh_log_filter_cmd); + install_element(CONFIG_NODE, &vtysh_log_filter_clear_cmd); install_element(CONFIG_NODE, &vtysh_log_stdout_cmd); install_element(CONFIG_NODE, &vtysh_log_stdout_level_cmd); install_element(CONFIG_NODE, &no_vtysh_log_stdout_cmd); |