From 0c791f873aeb7c1052c97db7da4fe23873d69603 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 20 Mar 2014 14:07:12 +0100 Subject: BGP graceful restart support. Also significant core protocol state changes needed for that, global graceful restart recovery state and kernel proto support for recovery. --- sysdep/unix/krt.Y | 3 ++- sysdep/unix/krt.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- sysdep/unix/krt.h | 4 +++- sysdep/unix/main.c | 9 +++++++-- 4 files changed, 54 insertions(+), 8 deletions(-) (limited to 'sysdep') 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 ] [-d] [-D ] [-p] [-s ] [-P ] [-u ] [-g ] [-f]\n", bird_name); + fprintf(stderr, "Usage: %s [-c ] [-d] [-D ] [-p] [-s ] [-P ] [-u ] [-g ] [-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 -- cgit v1.2.3