summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO4
-rw-r--r--doc/reply_codes6
-rw-r--r--nest/config.Y14
-rw-r--r--nest/iface.c4
-rw-r--r--nest/proto.c91
-rw-r--r--nest/protocol.h7
6 files changed, 101 insertions, 25 deletions
diff --git a/TODO b/TODO
index b998bc24..7f36a571 100644
--- a/TODO
+++ b/TODO
@@ -28,6 +28,7 @@ Core
- config: useless rules when protocols disabled
- config: remove protocol startup priority hacks?
- config: better datetime format
+- config: avoid upper case in default protocol names
- krt: rescan interfaces when route addition fails?
- krt: does PERSIST mode have any sense if kernel syncer is shut down as last?
@@ -39,14 +40,11 @@ Core
Commands
~~~~~~~~
-shutdown # order system shutdown
-configure [<file>]
show <name> # show everything you know about symbol <name>
rip ??? [<name>]
ospf ??? [<name>]
static ??? [<name>]
symbols
-(disable|enable|restart) <protocol> # or ALL?
- showing of routing table as seen by given protocol
- showing of deleted routing tables and filters
diff --git a/doc/reply_codes b/doc/reply_codes
index 93c3d515..b6a1c045 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -16,6 +16,11 @@ Reply codes of BIRD command-line interface
0005 Reconfiguration already in progress, queueing
0006 Reconfiguration ignored, shutting down
0007 Shutdown ordered
+0008 Already disabled
+0009 Disabled
+0010 Already enabled
+0011 Enabled
+0012 Restarted
1000 BIRD version
1001 Interface list
@@ -31,6 +36,7 @@ Reply codes of BIRD command-line interface
8000 Reply too long
8001 Route not found
8002 Configuration file error
+8003 No protocols match
9000 Command too long
9001 Parse error
diff --git a/nest/config.Y b/nest/config.Y
index b90b77df..0cb11080 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -30,6 +30,7 @@ CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIREC
%type <s> optsym
%type <ra> r_args
%type <i> echo_mask echo_size
+%type <t> proto_patt
CF_GRAMMAR
@@ -287,6 +288,19 @@ echo_size:
}
;
+CF_CLI(DISABLE, proto_patt, <protocol> | <pattern> | all, [[Disable protocol]])
+{ proto_xxable($2, 0); } ;
+CF_CLI(ENABLE, proto_patt, <protocol> | <pattern> | all, [[Enable protocol]])
+{ proto_xxable($2, 1); } ;
+CF_CLI(RESTART, proto_patt, <protocol> | <pattern> | all, [[Restart protocol]])
+{ proto_xxable($2, 2); } ;
+
+proto_patt:
+ SYM { $$ = $1->name; }
+ | ALL { $$ = "*"; }
+ | TEXT
+ ;
+
CF_CODE
CF_END
diff --git a/nest/iface.c b/nest/iface.c
index 4f12365c..bf73b46f 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -278,7 +278,7 @@ ifa_notify_change(unsigned c, struct ifa *a)
struct proto *p;
debug("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
- WALK_LIST(p, proto_list)
+ WALK_LIST(p, active_proto_list)
if (p->ifa_notify)
p->ifa_notify(p, c, a);
}
@@ -307,7 +307,7 @@ if_notify_change(unsigned c, struct iface *i)
ifa_notify_change(IF_CHANGE_DOWN, a);
}
- WALK_LIST(p, proto_list)
+ WALK_LIST(p, active_proto_list)
if (p->if_notify)
p->if_notify(p, c, i);
diff --git a/nest/proto.c b/nest/proto.c
index 84b9cd82..e4214ea8 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -15,6 +15,7 @@
#include "lib/resource.h"
#include "lib/lists.h"
#include "lib/event.h"
+#include "lib/string.h"
#include "conf/conf.h"
#include "nest/route.h"
#include "nest/iface.h"
@@ -24,8 +25,15 @@
static pool *proto_pool;
list protocol_list;
-list proto_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)
+
+list active_proto_list;
static list inactive_proto_list;
static list initial_proto_list;
static list flush_proto_list;
@@ -64,7 +72,7 @@ proto_relink(struct proto *p)
switch (p->core_state)
{
case FS_HAPPY:
- l = &proto_list;
+ l = &active_proto_list;
break;
case FS_FLUSHING:
l = &flush_proto_list;
@@ -153,6 +161,7 @@ protos_preconfig(struct config *c)
struct protocol *p;
init_list(&proto_list);
+ init_list(&active_proto_list);
init_list(&inactive_proto_list);
init_list(&initial_proto_list);
init_list(&flush_proto_list);
@@ -194,6 +203,7 @@ proto_init(struct proto_config *c)
q->proto_state = PS_DOWN;
q->core_state = FS_HUNGRY;
proto_enqueue(&initial_proto_list, q);
+ add_tail(&proto_list, &q->glob_node);
/*
* HACK ALERT! In case of multiple kernel routing tables,
* the kernel syncer acts as multiple protocols which cooperate
@@ -282,6 +292,7 @@ proto_rethink_goal(struct proto *p)
DBG("%s has shut down for reconfiguration\n", p->name);
config_del_obstacle(p->cf->global);
rem_node(&p->n);
+ rem_node(&p->glob_node);
mb_free(p);
if (!nc)
return;
@@ -303,8 +314,8 @@ proto_rethink_goal(struct proto *p)
if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
{
DBG("Kicking %s up\n", p->name);
- ASSERT(q->startup_counter > 0);
- q->startup_counter--;
+ if (q->startup_counter > 0) /* FIXME: Kill the startup counter hack! */
+ q->startup_counter--;
proto_init_instance(p);
proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
}
@@ -326,7 +337,7 @@ protos_dump_all(void)
debug("Protocols:\n");
- WALK_LIST(p, proto_list)
+ WALK_LIST(p, active_proto_list)
{
debug(" protocol %s (pri=%d): state %s/%s\n", p->name, p->proto->priority,
p_states[p->proto_state], c_states[p->core_state]);
@@ -343,6 +354,8 @@ protos_dump_all(void)
debug(" inactive %s: state %s/%s\n", p->name, p_states[p->proto_state], c_states[p->core_state]);
WALK_LIST(p, initial_proto_list)
debug(" initial %s\n", p->name);
+ WALK_LIST(p, flush_proto_list)
+ debug(" flushing %s\n", p->name);
}
void
@@ -514,15 +527,6 @@ proto_do_show(struct proto *p, int verbose)
}
}
-static void
-proto_do_show_list(list *l, int verbose)
-{
- struct proto *p;
-
- WALK_LIST(p, *l)
- proto_do_show(p, verbose);
-}
-
void
proto_show(struct symbol *s, int verbose)
{
@@ -536,9 +540,9 @@ proto_show(struct symbol *s, int verbose)
proto_do_show(((struct proto_config *)s->def)->proto, verbose);
else
{
- proto_do_show_list(&proto_list, verbose);
- proto_do_show_list(&flush_proto_list, verbose);
- proto_do_show_list(&inactive_proto_list, verbose);
+ WALK_PROTO_LIST(p)
+ proto_do_show(p, verbose);
+ WALK_PROTO_LIST_END;
}
cli_msg(0, "");
}
@@ -559,7 +563,7 @@ proto_get_named(struct symbol *sym, struct protocol *pr)
else
{
p = NULL;
- WALK_LIST(q, proto_list)
+ WALK_LIST(q, active_proto_list)
if (q->proto == pr)
{
if (p)
@@ -571,3 +575,54 @@ 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 0:
+ if (p->disabled)
+ cli_msg(-8, "%s: already disabled", p->name);
+ else
+ {
+ cli_msg(-9, "%s: disabled", p->name);
+ p->disabled = 1;
+ }
+ break;
+ case 1:
+ if (!p->disabled)
+ cli_msg(-10, "%s: already enabled", p->name);
+ else
+ {
+ cli_msg(-11, "%s: enabled", p->name);
+ p->disabled = 0;
+ }
+ break;
+ case 2:
+ if (p->disabled)
+ cli_msg(-8, "%s: already disabled", p->name);
+ else
+ {
+ p->disabled = 1;
+ proto_rethink_goal(p);
+ p->disabled = 0;
+ cli_msg(-12, "%s: restarted", p->name);
+ }
+ break;
+ default:
+ ASSERT(0);
+ }
+ proto_rethink_goal(p);
+ }
+ WALK_PROTO_LIST_END;
+ if (!cnt)
+ cli_msg(8003, "No protocols match");
+ else
+ cli_msg(0, "");
+}
diff --git a/nest/protocol.h b/nest/protocol.h
index 7c14f972..d5b5810a 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -87,7 +87,8 @@ struct proto_config {
};
struct proto {
- node n;
+ node n; /* Node in *_proto_list */
+ node glob_node; /* Node in global proto_list */
struct protocol *proto; /* Protocol */
struct proto_config *cf; /* Configuration data */
struct proto_config *cf_new; /* Configuration we want to switch to after shutdown (NULL=delete) */
@@ -151,10 +152,12 @@ struct proto {
void proto_build(struct proto_config *);
void *proto_new(struct proto_config *, unsigned size);
void *proto_config_new(struct protocol *, unsigned size);
+
void proto_show(struct symbol *, int);
struct proto *proto_get_named(struct symbol *, struct protocol *);
+void proto_xxable(char *, int);
-extern list proto_list;
+extern list active_proto_list;
/*
* Each protocol instance runs two different state machines: