Commit e304fd4b authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements pattern match for 'show protocols' command.

And generally consolidates protocol commands.
parent dfd48621
......@@ -33,6 +33,7 @@
#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "filter/filter.h"
#include "conf/conf.h"
#include "conf/cf-parse.tab.h"
......
......@@ -42,6 +42,7 @@ CF_DECLS
void *g;
bird_clock_t time;
struct prefix px;
struct proto_spec ps;
struct timeformat *tf;
}
......
......@@ -59,7 +59,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT)
%type <s> optsym
%type <ra> r_args
%type <i> echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport
%type <t> proto_patt
%type <ps> proto_patt proto_patt2
CF_GRAMMAR
......@@ -324,11 +324,11 @@ CF_CLI_HELP(SHOW, ..., [[Show status information]])
CF_CLI(SHOW STATUS,,, [[Show router status]])
{ cmd_show_status(); } ;
CF_CLI(SHOW PROTOCOLS, optsym, [<name>], [[Show routing protocols]])
{ proto_show($3, 0); } ;
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
{ proto_apply_cmd($3, proto_cmd_show, 0); } ;
CF_CLI(SHOW PROTOCOLS ALL, optsym, [<name>], [[Show routing protocol details]])
{ proto_show($4, 1); } ;
CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocol details]])
{ proto_apply_cmd($4, proto_cmd_show, 1); } ;
optsym:
SYM
......@@ -459,34 +459,39 @@ echo_size:
;
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
{ proto_xxable($2, XX_DISABLE); } ;
{ proto_apply_cmd($2, proto_cmd_disable, 0); } ;
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
{ proto_xxable($2, XX_ENABLE); } ;
{ proto_apply_cmd($2, proto_cmd_enable, 0); } ;
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
{ proto_xxable($2, XX_RESTART); } ;
{ proto_apply_cmd($2, proto_cmd_restart, 0); } ;
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
{ proto_xxable($2, XX_RELOAD); } ;
{ proto_apply_cmd($2, proto_cmd_reload, CMD_RELOAD); } ;
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
{ proto_xxable($3, XX_RELOAD_IN); } ;
{ proto_apply_cmd($3, proto_cmd_reload, CMD_RELOAD_IN); } ;
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
{ proto_xxable($3, XX_RELOAD_OUT); } ;
{ proto_apply_cmd($3, proto_cmd_reload, CMD_RELOAD_OUT); } ;
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging via BIRD logs]])
{ proto_debug($2, 0, $3); }
;
{ proto_apply_cmd($2, proto_cmd_debug, $3); } ;
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]])
{ proto_debug($2, 1, $3); }
;
{ proto_apply_cmd($2, proto_cmd_mrtdump, $3); } ;
proto_patt:
SYM { $$ = $1->name; }
| ALL { $$ = "*"; }
| TEXT
SYM { $$.ptr = $1; $$.patt = 0; }
| ALL { $$.ptr = NULL; $$.patt = 1; }
| TEXT { $$.ptr = $1; $$.patt = 1; }
;
proto_patt2:
SYM { $$.ptr = $1; $$.patt = 0; }
| { $$.ptr = NULL; $$.patt = 1; }
| TEXT { $$.ptr = $1; $$.patt = 1; }
;
CF_CODE
CF_END
......@@ -25,12 +25,6 @@ static pool *proto_pool;
static list protocol_list;
static list proto_list;
#define WALK_PROTO_LIST(p) do { \
node *nn; \
WALK_LIST(nn, proto_list) { \
struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
#define WALK_PROTO_LIST_END } } while(0)
#define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0)
list active_proto_list;
......@@ -847,11 +841,15 @@ proto_do_show_pipe_stats(struct proto *p)
s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
}
static void
proto_do_show(struct proto *p, int verbose)
void
proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
{
byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
/* First protocol - show header */
if (!cnt)
cli_msg(-2002, "name proto table state since info");
buf[0] = 0;
if (p->proto->get_status)
p->proto->get_status(p, buf);
......@@ -886,25 +884,136 @@ proto_do_show(struct proto *p, int verbose)
}
void
proto_show(struct symbol *s, int verbose)
proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
{
if (s && s->class != SYM_PROTO)
if (p->disabled)
{
cli_msg(9002, "%s is not a protocol", s->name);
cli_msg(-8, "%s: already disabled", p->name);
return;
}
cli_msg(-2002, "name proto table state since info");
if (s)
proto_do_show(((struct proto_config *)s->def)->proto, verbose);
else
log(L_INFO "Disabling protocol %s", p->name);
p->disabled = 1;
proto_rethink_goal(p);
cli_msg(-9, "%s: disabled", p->name);
}
void
proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
{
if (!p->disabled)
{
cli_msg(-10, "%s: already enabled", p->name);
return;
}
log(L_INFO "Enabling protocol %s", p->name);
p->disabled = 0;
proto_rethink_goal(p);
cli_msg(-11, "%s: enabled", p->name);
}
void
proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
{
if (p->disabled)
{
cli_msg(-8, "%s: already disabled", p->name);
return;
}
log(L_INFO "Restarting protocol %s", p->name);
p->disabled = 1;
proto_rethink_goal(p);
p->disabled = 0;
proto_rethink_goal(p);
cli_msg(-12, "%s: restarted", p->name);
}
void
proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
{
if (p->disabled)
{
cli_msg(-8, "%s: already disabled", p->name);
return;
}
/* If the protocol in not UP, it has no routes */
if (p->proto_state != PS_UP)
return;
log(L_INFO "Reloading protocol %s", p->name);
/* re-importing routes */
if (dir != CMD_RELOAD_OUT)
if (! (p->reload_routes && p->reload_routes(p)))
{
cli_msg(-8006, "%s: reload failed", p->name);
return;
}
/* re-exporting routes */
if (dir != CMD_RELOAD_IN)
proto_request_feeding(p);
cli_msg(-15, "%s: reloading", p->name);
}
void
proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED)
{
p->debug = mask;
}
void
proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED)
{
p->mrtdump = mask;
}
static void
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
{
if (s->class != SYM_PROTO)
{
WALK_PROTO_LIST(p)
proto_do_show(p, verbose);
WALK_PROTO_LIST_END;
cli_msg(9002, "%s is not a protocol", s->name);
return;
}
cmd(((struct proto_config *)s->def)->proto, arg, 0);
cli_msg(0, "");
}
static void
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
{
int cnt = 0;
node *nn;
WALK_LIST(nn, proto_list)
{
struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
if (!patt || patmatch(patt, p->name))
cmd(p, arg, cnt++);
}
if (!cnt)
cli_msg(8003, "No protocols match");
else
cli_msg(0, "");
}
void
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
{
if (ps.patt)
proto_apply_cmd_patt(ps.ptr, cmd, arg);
else
proto_apply_cmd_symbol(ps.ptr, cmd, arg);
}
struct proto *
proto_get_named(struct symbol *sym, struct protocol *pr)
{
......@@ -933,112 +1042,3 @@ proto_get_named(struct symbol *sym, struct protocol *pr)
}
return p;
}
void
proto_xxable(char *pattern, int xx)
{
int cnt = 0;
WALK_PROTO_LIST(p)
if (patmatch(pattern, p->name))
{
cnt++;
switch (xx)
{
case XX_DISABLE:
if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name);
else
{
log(L_INFO "Disabling protocol %s", p->name);
p->disabled = 1;
proto_rethink_goal(p);
cli_msg(-9, "%s: disabled", p->name);
}
break;
case XX_ENABLE:
if (!p->disabled)
cli_msg(-10, "%s: already enabled", p->name);
else
{
log(L_INFO "Enabling protocol %s", p->name);
p->disabled = 0;
proto_rethink_goal(p);
cli_msg(-11, "%s: enabled", p->name);
}
break;
case XX_RESTART:
if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name);
else
{
log(L_INFO "Restarting protocol %s", p->name);
p->disabled = 1;
proto_rethink_goal(p);
p->disabled = 0;
proto_rethink_goal(p);
cli_msg(-12, "%s: restarted", p->name);
}
break;
case XX_RELOAD:
case XX_RELOAD_IN:
case XX_RELOAD_OUT:
if (p->disabled)
{
cli_msg(-8, "%s: already disabled", p->name);
break;
}
/* If the protocol in not UP, it has no routes */
if (p->proto_state != PS_UP)
break;
log(L_INFO "Reloading protocol %s", p->name);
/* re-importing routes */
if (xx != XX_RELOAD_OUT)
if (! (p->reload_routes && p->reload_routes(p)))
{
cli_msg(-8006, "%s: reload failed", p->name);
break;
}
/* re-exporting routes */
if (xx != XX_RELOAD_IN)
proto_request_feeding(p);
cli_msg(-15, "%s: reloading", p->name);
break;
default:
ASSERT(0);
}
}
WALK_PROTO_LIST_END;
if (!cnt)
cli_msg(8003, "No protocols match");
else
cli_msg(0, "");
}
void
proto_debug(char *pattern, int which, unsigned int mask)
{
int cnt = 0;
WALK_PROTO_LIST(p)
if (patmatch(pattern, p->name))
{
cnt++;
if (which == 0)
p->debug = mask;
else
p->mrtdump = mask;
}
WALK_PROTO_LIST_END;
if (!cnt)
cli_msg(8003, "No protocols match");
else
cli_msg(0, "");
}
......@@ -195,21 +195,30 @@ struct proto {
/* Hic sunt protocol-specific data */
};
struct proto_spec {
void *ptr;
int patt;
};
void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, unsigned size);
void proto_request_feeding(struct proto *p);
void proto_show(struct symbol *, int);
void proto_cmd_show(struct proto *, unsigned int, int);
void proto_cmd_disable(struct proto *, unsigned int, int);
void proto_cmd_enable(struct proto *, unsigned int, int);
void proto_cmd_restart(struct proto *, unsigned int, int);
void proto_cmd_reload(struct proto *, unsigned int, int);
void proto_cmd_debug(struct proto *, unsigned int, int);
void proto_cmd_mrtdump(struct proto *, unsigned int, int);
void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg);
struct proto *proto_get_named(struct symbol *, struct protocol *);
void proto_xxable(char *, int);
void proto_debug(char *, int, unsigned int);
#define XX_DISABLE 0
#define XX_ENABLE 1
#define XX_RESTART 2
#define XX_RELOAD 3
#define XX_RELOAD_IN 4
#define XX_RELOAD_OUT 5
#define CMD_RELOAD 0
#define CMD_RELOAD_IN 1
#define CMD_RELOAD_OUT 2
static inline u32
proto_get_router_id(struct proto_config *pc)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment