From f14a4becbe77cfb3c2e4243d6fc383b0acd8956f Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 16 Jan 2000 23:30:06 +0000 Subject: [PATCH] Reworked proto lists -- each proto is now in two lists: the global one (proto_list) and per-type one (original lists). A lot of things simplified. Implemented `disable', `enable' and `restart' CLI commands. --- TODO | 4 +-- doc/reply_codes | 6 ++++ nest/config.Y | 14 ++++++++ nest/iface.c | 4 +-- nest/proto.c | 91 +++++++++++++++++++++++++++++++++++++++---------- nest/protocol.h | 7 ++-- 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 [] show # show everything you know about symbol rip ??? [] ospf ??? [] static ??? [] symbols -(disable|enable|restart) # 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 optsym %type r_args %type echo_mask echo_size +%type proto_patt CF_GRAMMAR @@ -287,6 +288,19 @@ echo_size: } ; +CF_CLI(DISABLE, proto_patt, | | all, [[Disable protocol]]) +{ proto_xxable($2, 0); } ; +CF_CLI(ENABLE, proto_patt, | | all, [[Enable protocol]]) +{ proto_xxable($2, 1); } ; +CF_CLI(RESTART, proto_patt, | | 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: