summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/unix/krt.Y3
-rw-r--r--sysdep/unix/krt.c46
-rw-r--r--sysdep/unix/krt.h4
-rw-r--r--sysdep/unix/main.c9
4 files changed, 54 insertions, 8 deletions
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 469c136d..630cda38 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -17,7 +17,7 @@ CF_DEFINES
CF_DECLS
-CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, KRT_SOURCE, KRT_METRIC)
+CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC)
CF_GRAMMAR
@@ -46,6 +46,7 @@ kern_item:
#endif
}
| DEVICE ROUTES bool { THIS_KRT->devroutes = $3; }
+ | GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; }
;
/* Kernel interface protocol */
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 6fdef619..bff3001f 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -653,6 +653,13 @@ krt_got_route(struct krt_proto *p, rte *e)
return;
}
+ if (!p->ready)
+ {
+ /* We wait for the initial feed to have correct KRF_INSTALLED flag */
+ verdict = KRF_IGNORE;
+ goto sentenced;
+ }
+
old = net->routes;
if ((net->n.flags & KRF_INSTALLED) && rte_is_valid(old))
{
@@ -779,7 +786,9 @@ krt_prune(struct krt_proto *p)
if (KRT_CF->learn)
krt_learn_prune(p);
#endif
- p->initialized = 1;
+
+ if (p->ready)
+ p->initialized = 1;
}
void
@@ -852,7 +861,7 @@ krt_scan_timer_start(struct krt_proto *p)
krt_scan_count++;
- tm_start(krt_scan_timer, 0);
+ tm_start(krt_scan_timer, 1);
}
static void
@@ -867,6 +876,12 @@ krt_scan_timer_stop(struct krt_proto *p)
}
}
+static void
+krt_scan_timer_kick(struct krt_proto *p UNUSED)
+{
+ tm_start(krt_scan_timer, 0);
+}
+
#else
static void
@@ -885,7 +900,7 @@ static void
krt_scan_timer_start(struct krt_proto *p)
{
p->scan_timer = tm_new_set(p->p.pool, krt_scan, p, 0, KRT_CF->scan_time);
- tm_start(p->scan_timer, 0);
+ tm_start(p->scan_timer, 1);
}
static void
@@ -894,6 +909,12 @@ krt_scan_timer_stop(struct krt_proto *p)
tm_stop(p->scan_timer);
}
+static void
+krt_scan_timer_kick(struct krt_proto *p UNUSED)
+{
+ tm_start(p->scan_timer, 0);
+}
+
#endif
@@ -970,6 +991,16 @@ krt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
krt_replace_rte(p, net, new, old, eattrs);
}
+static void
+krt_feed_done(struct proto *P)
+{
+ struct krt_proto *p = (struct krt_proto *) P;
+
+ p->ready = 1;
+ krt_scan_timer_kick(p);
+}
+
+
static int
krt_rte_same(rte *a, rte *b)
{
@@ -992,6 +1023,7 @@ krt_init(struct proto_config *c)
p->p.accept_ra_types = RA_OPTIMAL;
p->p.import_control = krt_import_control;
p->p.rt_notify = krt_notify;
+ p->p.feed_done = krt_feed_done;
p->p.make_tmp_attrs = krt_make_tmp_attrs;
p->p.store_tmp_attrs = krt_store_tmp_attrs;
p->p.rte_same = krt_rte_same;
@@ -1015,6 +1047,9 @@ krt_start(struct proto *P)
krt_scan_timer_start(p);
+ if (P->gr_recovery && KRT_CF->graceful_restart)
+ P->gr_wait = 1;
+
return PS_UP;
}
@@ -1029,6 +1064,9 @@ krt_shutdown(struct proto *P)
if (p->initialized && !KRT_CF->persist)
krt_flush_routes(p);
+ p->ready = 0;
+ p->initialized = 0;
+
krt_sys_shutdown(p);
rem_node(&p->krt_node);
@@ -1045,7 +1083,7 @@ krt_reconfigure(struct proto *p, struct proto_config *new)
if (!krt_sys_reconfigure((struct krt_proto *) p, n, o))
return 0;
- /* persist needn't be the same */
+ /* persist, graceful restart need not be the same */
return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
}
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 99983ccd..2cd23165 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -48,6 +48,7 @@ struct krt_config {
int scan_time; /* How often we re-scan routes */
int learn; /* Learn routes from other sources */
int devroutes; /* Allow export of device routes */
+ int graceful_restart; /* Regard graceful restart recovery */
};
struct krt_proto {
@@ -63,7 +64,8 @@ struct krt_proto {
#endif
node krt_node; /* Node in krt_proto_list */
- int initialized; /* First scan has already been finished */
+ byte ready; /* Initial feed has been finished */
+ byte initialized; /* First scan has been finished */
};
extern pool *krt_pool;
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index e9217bc9..31094c52 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -602,7 +602,7 @@ signal_init(void)
* Parsing of command-line arguments
*/
-static char *opt_list = "c:dD:ps:P:u:g:f";
+static char *opt_list = "c:dD:ps:P:u:g:fR";
static int parse_and_exit;
char *bird_name;
static char *use_user;
@@ -612,7 +612,7 @@ static int run_in_foreground = 0;
static void
usage(void)
{
- fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f]\n", bird_name);
+ fprintf(stderr, "Usage: %s [-c <config-file>] [-d] [-D <debug-file>] [-p] [-s <control-socket>] [-P <pid-file>] [-u <user>] [-g <group>] [-f] [-R]\n", bird_name);
exit(1);
}
@@ -723,6 +723,9 @@ parse_args(int argc, char **argv)
case 'f':
run_in_foreground = 1;
break;
+ case 'R':
+ graceful_restart_recovery();
+ break;
default:
usage();
}
@@ -805,6 +808,8 @@ main(int argc, char **argv)
config_commit(conf, RECONFIG_HARD, 0);
+ graceful_restart_init();
+
#ifdef LOCAL_DEBUG
async_dump_flag = 1;
#endif