summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2014-03-20 14:07:12 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2014-03-20 14:07:12 +0100
commit0c791f873aeb7c1052c97db7da4fe23873d69603 (patch)
tree48496c5965cb6e9f54d7863827c35054c3697c19 /sysdep/unix
parent4e398e34bf140baf73fe8dceaf81078fb343f65a (diff)
BGP graceful restart support.
Also significant core protocol state changes needed for that, global graceful restart recovery state and kernel proto support for recovery.
Diffstat (limited to 'sysdep/unix')
-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