Implements eval command and minor CLI cleanups.
Implemented eval command can be used to evaluate expressions. The patch also documents echo command and allows to use log classes instead of integer as a mask for echo.
This commit is contained in:
parent
a0b176e3b2
commit
508d936078
8 changed files with 72 additions and 18 deletions
|
@ -282,7 +282,7 @@ protocol rip {
|
||||||
<tag>include "<m/filename/"</tag>
|
<tag>include "<m/filename/"</tag>
|
||||||
This statement causes inclusion of a new file. The maximal depth is set to 5.
|
This statement causes inclusion of a new file. The maximal depth is set to 5.
|
||||||
|
|
||||||
<tag>log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
|
<tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
|
||||||
Set logging of messages having the given class (either <cf/all/ or <cf/{
|
Set logging of messages having the given class (either <cf/all/ or <cf/{
|
||||||
error, trace }/ etc.) into selected destination (a file specified as a filename string,
|
error, trace }/ etc.) into selected destination (a file specified as a filename string,
|
||||||
syslog with optional name argument, or the stderr output). Classes are:
|
syslog with optional name argument, or the stderr output). Classes are:
|
||||||
|
@ -651,9 +651,6 @@ This argument can be omitted if there exists only a single instance.
|
||||||
<p>Here is a brief list of supported functions:
|
<p>Here is a brief list of supported functions:
|
||||||
|
|
||||||
<descrip>
|
<descrip>
|
||||||
<tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag>
|
|
||||||
Dump contents of internal data structures to the debugging output.
|
|
||||||
|
|
||||||
<tag>show status</tag>
|
<tag>show status</tag>
|
||||||
Show router status, that is BIRD version, uptime and time from last reconfiguration.
|
Show router status, that is BIRD version, uptime and time from last reconfiguration.
|
||||||
|
|
||||||
|
@ -812,6 +809,17 @@ This argument can be omitted if there exists only a single instance.
|
||||||
|
|
||||||
<tag>debug <m/protocol/|<m/pattern/|all all|off|{ states | routes | filters | events | packets }</tag>
|
<tag>debug <m/protocol/|<m/pattern/|all all|off|{ states | routes | filters | events | packets }</tag>
|
||||||
Control protocol debugging.
|
Control protocol debugging.
|
||||||
|
|
||||||
|
<tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag>
|
||||||
|
Dump contents of internal data structures to the debugging output.
|
||||||
|
|
||||||
|
<tag>echo all|off|{ <m/list of log classes/ } [ <m/buffer-size/ ]</tag>
|
||||||
|
Control echoing of log messages to the command-line output.
|
||||||
|
See <ref id="dsc-log" name="log option"> for a list of log classes.
|
||||||
|
|
||||||
|
<tag>eval <m/expr/</tag>
|
||||||
|
Evaluate given expression.
|
||||||
|
|
||||||
</descrip>
|
</descrip>
|
||||||
|
|
||||||
<chapt>Filters
|
<chapt>Filters
|
||||||
|
|
|
@ -31,6 +31,7 @@ Reply codes of BIRD command-line interface
|
||||||
0020 Configuration OK
|
0020 Configuration OK
|
||||||
0021 Undo requested
|
0021 Undo requested
|
||||||
0022 Undo scheduled
|
0022 Undo scheduled
|
||||||
|
0023 Evaluation of expression
|
||||||
|
|
||||||
1000 BIRD version
|
1000 BIRD version
|
||||||
1001 Interface list
|
1001 Interface list
|
||||||
|
@ -61,6 +62,7 @@ Reply codes of BIRD command-line interface
|
||||||
8005 Protocol is down => cannot dump
|
8005 Protocol is down => cannot dump
|
||||||
8006 Reload failed
|
8006 Reload failed
|
||||||
8007 Access denied
|
8007 Access denied
|
||||||
|
8008 Evaluation runtime error
|
||||||
|
|
||||||
9000 Command too long
|
9000 Command too long
|
||||||
9001 Parse error
|
9001 Parse error
|
||||||
|
|
|
@ -440,8 +440,6 @@ val_in_range(struct f_val v1, struct f_val v2)
|
||||||
return CMP_ERROR;
|
return CMP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void val_print(struct f_val v);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tree_node_print(struct f_tree *t, char **sep)
|
tree_node_print(struct f_tree *t, char **sep)
|
||||||
{
|
{
|
||||||
|
@ -474,7 +472,7 @@ tree_print(struct f_tree *t)
|
||||||
/*
|
/*
|
||||||
* val_print - format filter value
|
* val_print - format filter value
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
val_print(struct f_val v)
|
val_print(struct f_val v)
|
||||||
{
|
{
|
||||||
char buf2[1024];
|
char buf2[1024];
|
||||||
|
@ -558,6 +556,8 @@ static struct rate_limit rl_runtime_err;
|
||||||
#define TWOARGS_C TWOARGS \
|
#define TWOARGS_C TWOARGS \
|
||||||
if (v1.type != v2.type) \
|
if (v1.type != v2.type) \
|
||||||
runtime( "Can't operate with values of incompatible types" );
|
runtime( "Can't operate with values of incompatible types" );
|
||||||
|
#define ACCESS_RTE \
|
||||||
|
do { if (!f_rte) runtime("No route to access"); } while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* interpret
|
* interpret
|
||||||
|
@ -821,6 +821,7 @@ interpret(struct f_inst *what)
|
||||||
break;
|
break;
|
||||||
case 'a': /* rta access */
|
case 'a': /* rta access */
|
||||||
{
|
{
|
||||||
|
ACCESS_RTE;
|
||||||
struct rta *rta = (*f_rte)->attrs;
|
struct rta *rta = (*f_rte)->attrs;
|
||||||
res.type = what->aux;
|
res.type = what->aux;
|
||||||
switch(res.type) {
|
switch(res.type) {
|
||||||
|
@ -845,6 +846,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case P('a','S'):
|
case P('a','S'):
|
||||||
|
ACCESS_RTE;
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (what->aux != v1.type)
|
if (what->aux != v1.type)
|
||||||
runtime( "Attempt to set static attribute to incompatible type" );
|
runtime( "Attempt to set static attribute to incompatible type" );
|
||||||
|
@ -877,6 +879,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case P('e','a'): /* Access to extended attributes */
|
case P('e','a'): /* Access to extended attributes */
|
||||||
|
ACCESS_RTE;
|
||||||
{
|
{
|
||||||
eattr *e = NULL;
|
eattr *e = NULL;
|
||||||
if (!(f_flags & FF_FORCE_TMPATTR))
|
if (!(f_flags & FF_FORCE_TMPATTR))
|
||||||
|
@ -944,6 +947,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case P('e','S'):
|
case P('e','S'):
|
||||||
|
ACCESS_RTE;
|
||||||
ONEARG;
|
ONEARG;
|
||||||
{
|
{
|
||||||
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
|
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
|
||||||
|
@ -1021,10 +1025,12 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
|
ACCESS_RTE;
|
||||||
res.type = T_INT;
|
res.type = T_INT;
|
||||||
res.val.i = (*f_rte)->pref;
|
res.val.i = (*f_rte)->pref;
|
||||||
break;
|
break;
|
||||||
case P('P','S'):
|
case P('P','S'):
|
||||||
|
ACCESS_RTE;
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (v1.type != T_INT)
|
if (v1.type != T_INT)
|
||||||
runtime( "Can't set preference to non-integer" );
|
runtime( "Can't set preference to non-integer" );
|
||||||
|
@ -1246,6 +1252,7 @@ interpret(struct f_inst *what)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ACCESS_RTE;
|
||||||
v1.val.px.ip = (*f_rte)->net->n.prefix;
|
v1.val.px.ip = (*f_rte)->net->n.prefix;
|
||||||
v1.val.px.len = (*f_rte)->net->n.pxlen;
|
v1.val.px.len = (*f_rte)->net->n.pxlen;
|
||||||
|
|
||||||
|
@ -1478,22 +1485,27 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
||||||
return res.val.i;
|
return res.val.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct f_val
|
||||||
|
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
||||||
|
{
|
||||||
|
f_flags = 0;
|
||||||
|
f_tmp_attrs = NULL;
|
||||||
|
f_rte = NULL;
|
||||||
|
f_pool = tmp_pool;
|
||||||
|
|
||||||
|
log_reset();
|
||||||
|
return interpret(expr);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
f_eval_int(struct f_inst *expr)
|
f_eval_int(struct f_inst *expr)
|
||||||
{
|
{
|
||||||
/* Called independently in parse-time to eval expressions */
|
/* Called independently in parse-time to eval expressions */
|
||||||
struct f_val res;
|
struct f_val res = f_eval(expr, cfg_mem);
|
||||||
|
|
||||||
f_flags = 0;
|
|
||||||
f_tmp_attrs = NULL;
|
|
||||||
f_rte = NULL;
|
|
||||||
f_pool = cfg_mem;
|
|
||||||
|
|
||||||
log_reset();
|
|
||||||
res = interpret(expr);
|
|
||||||
|
|
||||||
if (res.type != T_INT)
|
if (res.type != T_INT)
|
||||||
cf_error("Integer expression expected");
|
cf_error("Integer expression expected");
|
||||||
|
|
||||||
return res.val.i;
|
return res.val.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,7 @@ struct ea_list;
|
||||||
struct rte;
|
struct rte;
|
||||||
|
|
||||||
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
|
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
|
||||||
|
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
||||||
int f_eval_int(struct f_inst *expr);
|
int f_eval_int(struct f_inst *expr);
|
||||||
u32 f_eval_asn(struct f_inst *expr);
|
u32 f_eval_asn(struct f_inst *expr);
|
||||||
|
|
||||||
|
@ -117,6 +118,8 @@ int i_same(struct f_inst *f1, struct f_inst *f2);
|
||||||
int val_compare(struct f_val v1, struct f_val v2);
|
int val_compare(struct f_val v1, struct f_val v2);
|
||||||
int tree_compare(const void *p1, const void *p2);
|
int tree_compare(const void *p1, const void *p2);
|
||||||
|
|
||||||
|
void val_print(struct f_val v);
|
||||||
|
|
||||||
#define F_NOP 0
|
#define F_NOP 0
|
||||||
#define F_NONL 1
|
#define F_NONL 1
|
||||||
#define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */
|
#define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */
|
||||||
|
|
20
nest/cmds.c
20
nest/cmds.c
|
@ -13,6 +13,7 @@
|
||||||
#include "nest/cmds.h"
|
#include "nest/cmds.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
#include "filter/filter.h"
|
||||||
|
|
||||||
extern int shutting_down;
|
extern int shutting_down;
|
||||||
extern int configuring;
|
extern int configuring;
|
||||||
|
@ -90,3 +91,22 @@ cmd_show_memory(void)
|
||||||
print_size("Total:", rmemsize(&root_pool));
|
print_size("Total:", rmemsize(&root_pool));
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const char *log_buffer_ptr;
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_eval(struct f_inst *expr)
|
||||||
|
{
|
||||||
|
struct f_val v = f_eval(expr, this_cli->parser_pool);
|
||||||
|
log_reset();
|
||||||
|
|
||||||
|
if (v.type == T_RETURN)
|
||||||
|
{
|
||||||
|
cli_msg(8008, "runtime error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
val_print(v);
|
||||||
|
cli_msg(23, "%s", log_buffer_ptr);
|
||||||
|
log_reset();
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ struct sym_show_data {
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct f_inst;
|
||||||
|
|
||||||
void cmd_show_status(void);
|
void cmd_show_status(void);
|
||||||
void cmd_show_symbols(struct sym_show_data *sym);
|
void cmd_show_symbols(struct sym_show_data *sym);
|
||||||
void cmd_show_memory(void);
|
void cmd_show_memory(void);
|
||||||
|
void cmd_eval(struct f_inst *expr);
|
||||||
|
|
|
@ -612,7 +612,11 @@ CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
|
||||||
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
|
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
|
||||||
{ protos_dump_all(); cli_msg(0, ""); } ;
|
{ protos_dump_all(); cli_msg(0, ""); } ;
|
||||||
|
|
||||||
CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Configure echoing of log messages]]) {
|
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
|
||||||
|
{ cmd_eval($2); } ;
|
||||||
|
|
||||||
|
CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
|
||||||
|
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) {
|
||||||
cli_set_log_echo(this_cli, $2, $3);
|
cli_set_log_echo(this_cli, $2, $3);
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
} ;
|
} ;
|
||||||
|
@ -620,7 +624,7 @@ CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Config
|
||||||
echo_mask:
|
echo_mask:
|
||||||
ALL { $$ = ~0; }
|
ALL { $$ = ~0; }
|
||||||
| OFF { $$ = 0; }
|
| OFF { $$ = 0; }
|
||||||
| NUM
|
| '{' log_mask_list '}' { $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
echo_size:
|
echo_size:
|
||||||
|
|
|
@ -70,6 +70,8 @@ static char log_buffer[LOG_BUFFER_SIZE];
|
||||||
static char *log_buffer_pos;
|
static char *log_buffer_pos;
|
||||||
static int log_buffer_remains;
|
static int log_buffer_remains;
|
||||||
|
|
||||||
|
const char *log_buffer_ptr = log_buffer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* log_reset - reset the log buffer
|
* log_reset - reset the log buffer
|
||||||
|
|
Loading…
Reference in a new issue