Finishes 'route reload' feature.
This commit is contained in:
parent
28008482a9
commit
8a7fb8858f
6 changed files with 78 additions and 28 deletions
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]])
|
||||||
|
|
48
nest/proto.c
48
nest/proto.c
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue