Finishes 'route reload' feature.

This commit is contained in:
Ondrej Zajicek 2009-12-14 01:32:37 +01:00
parent 28008482a9
commit 8a7fb8858f
6 changed files with 78 additions and 28 deletions

View file

@ -497,6 +497,24 @@ This argument can be omitted if there exists only a single instance.
<tag>enable|disable|restart <m/name/|"<m/pattern/"|all</tag> <tag>enable|disable|restart <m/name/|"<m/pattern/"|all</tag>
Enable, disable or restart a given protocol instance, instances matching the <cf><m/pattern/</cf> or <cf/all/ instances. Enable, disable or restart a given protocol instance, instances matching the <cf><m/pattern/</cf> or <cf/all/ instances.
<tag>reload [in|out] <m/name/|"<m/pattern/"|all</tag>
Reload a given protocol instance, that means re-import routes
from the protocol instance and re-export preferred routes to
the instance. If <cf/in/ or <cf/out/ options are used, the
command is restricted to one direction (re-import or
re-export).
This command is useful if appropriate filters have changed but
the protocol instance was not restarted (or reloaded),
therefore it still propagates the old set of routes. For example
when <cf/configure soft/ command was used to change filters.
Re-export always succeeds, but re-import is protocol-dependent
and might fail (for example, if BGP neighbor does not support
route-refresh extension). In that case, re-export is also
skipped.
<tag/down/ <tag/down/
Shut BIRD down. Shut BIRD down.

View file

@ -23,6 +23,7 @@ Reply codes of BIRD command-line interface
0012 Restarted 0012 Restarted
0013 Status report 0013 Status report
0014 Route count 0014 Route count
0015 Reloading
1000 BIRD version 1000 BIRD version
1001 Interface list 1001 Interface list
@ -40,6 +41,7 @@ Reply codes of BIRD command-line interface
1013 Show ospf neighbors 1013 Show ospf neighbors
1014 Show ospf 1014 Show ospf
1015 Show ospf interface 1015 Show ospf interface
1016 Show ospf state/topology
8000 Reply too long 8000 Reply too long
8001 Route not found 8001 Route not found
@ -47,6 +49,7 @@ Reply codes of BIRD command-line interface
8003 No protocols match 8003 No protocols match
8004 Stopped due to reconfiguration 8004 Stopped due to reconfiguration
8005 Protocol is down => cannot dump 8005 Protocol is down => cannot dump
8006 Reload failed
9000 Command too long 9000 Command too long
9001 Parse error 9001 Parse error

View file

@ -45,7 +45,7 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION) CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
CF_KEYWORDS(RELOAD, REFEED) CF_KEYWORDS(RELOAD, IN, OUT)
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE) RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
@ -438,17 +438,17 @@ echo_size:
; ;
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]]) CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
{ proto_xxable($2, 0); } ; { proto_xxable($2, XX_DISABLE); } ;
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]]) CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
{ proto_xxable($2, 1); } ; { proto_xxable($2, XX_ENABLE); } ;
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]]) CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
{ proto_xxable($2, 2); } ; { proto_xxable($2, XX_RESTART); } ;
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]]) CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
{ proto_xxable($2, 3); } ; { proto_xxable($2, XX_RELOAD); } ;
CF_CLI(REFEED, proto_patt, <protocol> | \"<pattern>\" | all, [[Refeed protocol BROKEN]]) CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
{ proto_xxable($2, 4); } ; { proto_xxable($3, XX_RELOAD_IN); } ;
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
{ proto_xxable($3, XX_RELOAD_OUT); } ;
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging]]) CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging]])
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging]]) CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging]])

View file

@ -586,6 +586,11 @@ proto_schedule_feed(struct proto *p, int initial)
DBG("%s: Scheduling meal\n", p->name); DBG("%s: Scheduling meal\n", p->name);
p->core_state = FS_FEEDING; p->core_state = FS_FEEDING;
p->refeeding = !initial; p->refeeding = !initial;
/* Hack: reset exp_routes during refeed, and do not decrease it later */
if (!initial)
p->stats.exp_routes = 0;
proto_relink(p); proto_relink(p);
p->attn->hook = initial ? proto_feed_initial : proto_feed_more; p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
ev_schedule(p->attn); ev_schedule(p->attn);
@ -825,7 +830,7 @@ proto_xxable(char *pattern, int xx)
cnt++; cnt++;
switch (xx) switch (xx)
{ {
case 0: case XX_DISABLE:
if (p->disabled) if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name); cli_msg(-8, "%s: already disabled", p->name);
else else
@ -835,7 +840,8 @@ proto_xxable(char *pattern, int xx)
proto_rethink_goal(p); proto_rethink_goal(p);
} }
break; break;
case 1:
case XX_ENABLE:
if (!p->disabled) if (!p->disabled)
cli_msg(-10, "%s: already enabled", p->name); cli_msg(-10, "%s: already enabled", p->name);
else else
@ -845,7 +851,8 @@ proto_xxable(char *pattern, int xx)
proto_rethink_goal(p); proto_rethink_goal(p);
} }
break; break;
case 2:
case XX_RESTART:
if (p->disabled) if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name); cli_msg(-8, "%s: already disabled", p->name);
else else
@ -857,24 +864,29 @@ proto_xxable(char *pattern, int xx)
cli_msg(-12, "%s: restarted", p->name); cli_msg(-12, "%s: restarted", p->name);
} }
break; break;
case 3:
// FIXME change msg number case XX_RELOAD:
case XX_RELOAD_IN:
case XX_RELOAD_OUT:
if (p->disabled) if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name);
else if (p->reload_routes && p->reload_routes(p))
cli_msg(-12, "%s: reloading", p->name);
else
cli_msg(-12, "%s: reload failed", p->name);
break;
case 4:
// FIXME change msg number
if (p->disabled)
cli_msg(-8, "%s: already disabled", p->name);
else
{ {
proto_request_feeding(p); cli_msg(-8, "%s: already disabled", p->name);
cli_msg(-12, "%s: reexport failed", p->name); break;
} }
/* 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; break;
default: default:

View file

@ -201,6 +201,13 @@ struct proto *proto_get_named(struct symbol *, struct protocol *);
void proto_xxable(char *, int); void proto_xxable(char *, int);
void proto_debug(char *, unsigned int); void proto_debug(char *, 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
static inline u32 static inline u32
proto_get_router_id(struct proto_config *pc) proto_get_router_id(struct proto_config *pc)
{ {

View file

@ -165,6 +165,8 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
rte *old0 = old; rte *old0 = old;
int ok; int ok;
int fast_exit_hack = 0;
if (new) if (new)
{ {
p->stats.exp_updates_received++; p->stats.exp_updates_received++;
@ -174,6 +176,7 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
{ {
p->stats.exp_updates_rejected++; p->stats.exp_updates_rejected++;
drop_reason = "out of scope"; drop_reason = "out of scope";
fast_exit_hack = 1;
} }
else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0) else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
{ {
@ -199,6 +202,11 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
else else
p->stats.exp_withdraws_received++; p->stats.exp_withdraws_received++;
/* Hack: This is here to prevent 'spurious withdraws'
for loopback addresses during reload. */
if (fast_exit_hack)
return;
/* /*
* This is a tricky part - we don't know whether route 'old' was * This is a tricky part - we don't know whether route 'old' was
* exported to protocol 'p' or was filtered by the export filter. * exported to protocol 'p' or was filtered by the export filter.
@ -245,9 +253,11 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
else else
p->stats.exp_withdraws_accepted++; p->stats.exp_withdraws_accepted++;
/* Hack: We do not decrease exp_routes during refeed, we instead
reset exp_routes at the start of refeed. */
if (new) if (new)
p->stats.exp_routes++; p->stats.exp_routes++;
if (old) if (old && !refeed)
p->stats.exp_routes--; p->stats.exp_routes--;
if (p->debug & D_ROUTES) if (p->debug & D_ROUTES)