summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-12-14 01:32:37 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-12-14 01:32:37 +0100
commit8a7fb8858fa87bce6f2f15ee2bbb77704b5fff4e (patch)
tree9d4ca182afc0d2f140afeb9d60ef5668776eb9d5
parent28008482a97c0ac70e648759fe37bad0633ed9f7 (diff)
downloadbird-8a7fb8858fa87bce6f2f15ee2bbb77704b5fff4e.tar
bird-8a7fb8858fa87bce6f2f15ee2bbb77704b5fff4e.zip
Finishes 'route reload' feature.
-rw-r--r--doc/bird.sgml18
-rw-r--r--doc/reply_codes3
-rw-r--r--nest/config.Y18
-rw-r--r--nest/proto.c48
-rw-r--r--nest/protocol.h7
-rw-r--r--nest/rt-table.c12
6 files changed, 78 insertions, 28 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 1f494cc..3905a29 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 e4330a2..4588182 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 dde20c5..dbb10ad 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 b23011d..4f352a6 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 e1adc52..21a1c1b 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 8efc0a6..df2834a 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)