diff options
-rw-r--r-- | doc/bird.sgml | 18 | ||||
-rw-r--r-- | doc/reply_codes | 3 | ||||
-rw-r--r-- | nest/config.Y | 18 | ||||
-rw-r--r-- | nest/proto.c | 48 | ||||
-rw-r--r-- | nest/protocol.h | 7 | ||||
-rw-r--r-- | nest/rt-table.c | 12 |
6 files changed, 78 insertions, 28 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 1f494cce..3905a29e 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -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> 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/ Shut BIRD down. diff --git a/doc/reply_codes b/doc/reply_codes index e4330a2e..4588182b 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -23,6 +23,7 @@ Reply codes of BIRD command-line interface 0012 Restarted 0013 Status report 0014 Route count +0015 Reloading 1000 BIRD version 1001 Interface list @@ -40,6 +41,7 @@ Reply codes of BIRD command-line interface 1013 Show ospf neighbors 1014 Show ospf 1015 Show ospf interface +1016 Show ospf state/topology 8000 Reply too long 8001 Route not found @@ -47,6 +49,7 @@ Reply codes of BIRD command-line interface 8003 No protocols match 8004 Stopped due to reconfiguration 8005 Protocol is down => cannot dump +8006 Reload failed 9000 Command too long 9001 Parse error diff --git a/nest/config.Y b/nest/config.Y index dde20c5a..dbb10ada 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -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(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) 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, 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]]) -{ proto_xxable($2, 0); } ; +{ proto_xxable($2, XX_DISABLE); } ; 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]]) -{ proto_xxable($2, 2); } ; +{ proto_xxable($2, XX_RESTART); } ; CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]]) -{ proto_xxable($2, 3); } ; -CF_CLI(REFEED, proto_patt, <protocol> | \"<pattern>\" | all, [[Refeed protocol BROKEN]]) -{ proto_xxable($2, 4); } ; - - +{ proto_xxable($2, XX_RELOAD); } ; +CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]]) +{ 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(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging]]) diff --git a/nest/proto.c b/nest/proto.c index b23011d7..4f352a6f 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -586,6 +586,11 @@ proto_schedule_feed(struct proto *p, int initial) DBG("%s: Scheduling meal\n", p->name); p->core_state = FS_FEEDING; 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); p->attn->hook = initial ? proto_feed_initial : proto_feed_more; ev_schedule(p->attn); @@ -825,7 +830,7 @@ proto_xxable(char *pattern, int xx) cnt++; switch (xx) { - case 0: + case XX_DISABLE: if (p->disabled) cli_msg(-8, "%s: already disabled", p->name); else @@ -835,7 +840,8 @@ proto_xxable(char *pattern, int xx) proto_rethink_goal(p); } break; - case 1: + + case XX_ENABLE: if (!p->disabled) cli_msg(-10, "%s: already enabled", p->name); else @@ -845,7 +851,8 @@ proto_xxable(char *pattern, int xx) proto_rethink_goal(p); } break; - case 2: + + case XX_RESTART: if (p->disabled) cli_msg(-8, "%s: already disabled", p->name); else @@ -857,24 +864,29 @@ proto_xxable(char *pattern, int xx) cli_msg(-12, "%s: restarted", p->name); } break; - case 3: - // FIXME change msg number - 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 + + case XX_RELOAD: + case XX_RELOAD_IN: + case XX_RELOAD_OUT: if (p->disabled) - cli_msg(-8, "%s: already disabled", p->name); - else { - proto_request_feeding(p); - cli_msg(-12, "%s: reexport failed", p->name); + cli_msg(-8, "%s: already disabled", 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; default: diff --git a/nest/protocol.h b/nest/protocol.h index e1adc525..21a1c1b4 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -201,6 +201,13 @@ struct proto *proto_get_named(struct symbol *, struct protocol *); void proto_xxable(char *, 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 proto_get_router_id(struct proto_config *pc) { diff --git a/nest/rt-table.c b/nest/rt-table.c index 8efc0a61..df2834a6 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -165,6 +165,8 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, rte *old0 = old; int ok; + int fast_exit_hack = 0; + if (new) { 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++; 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) { @@ -199,6 +202,11 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old, else 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 * 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 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) p->stats.exp_routes++; - if (old) + if (old && !refeed) p->stats.exp_routes--; if (p->debug & D_ROUTES) |