diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2021-05-31 15:27:51 +0200 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2021-07-05 16:43:02 +0200 |
commit | 1051417011b98dcebba527e0c9053db6fc7c6e30 (patch) | |
tree | 4e07b4e25d3de792d20c6a78eb095b45a77ae731 /ospfd/ospfd.c | |
parent | ospfd: rename the graceful restart header (diff) | |
download | frr-1051417011b98dcebba527e0c9053db6fc7c6e30.tar.xz frr-1051417011b98dcebba527e0c9053db6fc7c6e30.zip |
ospfd: introduce support for Graceful Restart (restarting mode)
RFC 3623 specifies the Graceful Restart enhancement to the OSPF
routing protocol. This PR implements support for the restarting mode,
whereas the helper mode was implemented by #6811.
This work is based on #6782, which implemented the pre-restart part
and settled the foundations for the post-restart part (behavioral
changes, GR exit conditions, and on-exit actions).
Here's a quick summary of how the GR restarting mode works:
* GR can be enabled on a per-instance basis using the `graceful-restart
[grace-period (1-1800)]` command;
* To perform a graceful shutdown, the `graceful-restart prepare ospf`
EXEC-level command needs to be issued before restarting the ospfd
daemon (there's no specific requirement on how the daemon should
be restarted);
* `graceful-restart prepare ospf` will initiate the graceful restart
for all GR-enabled instances by taking the following actions:
o Flooding Grace-LSAs over all interfaces
o Freezing the OSPF routes in the RIB
o Saving the end of the grace period in non-volatile memory (a JSON
file stored in `$frr_statedir`)
* Once ospfd is started again, it will follow the procedures
described in RFC 3623 until it detects it's time to exit the graceful
restart (either successfully or unsuccessfully).
Testing done:
* New topotest featuring a multi-area OSPF topology (including stub
and NSSA areas);
* Successful interop tests against IOS-XR routers acting as helpers.
Co-authored-by: GalaxyGorilla <sascha@netdef.org>
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ospfd/ospfd.c')
-rw-r--r-- | ospfd/ospfd.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a4b50e0c3..3226d6644 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -420,6 +420,12 @@ static struct ospf *ospf_new(unsigned short instance, const char *name) thread_add_read(master, ospf_read, new, new->fd, &new->t_read); + /* + * Read from non-volatile memory whether this instance is performing a + * graceful restart or not. + */ + ospf_gr_nvm_read(new); + return new; } @@ -708,7 +714,8 @@ static void ospf_finish_final(struct ospf *ospf) ospf_opaque_finish(); - ospf_flush_self_originated_lsas_now(ospf); + if (!ospf->gr_info.prepare_in_progress) + ospf_flush_self_originated_lsas_now(ospf); /* Unregister redistribution */ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { @@ -805,6 +812,7 @@ static void ospf_finish_final(struct ospf *ospf) OSPF_TIMER_OFF(ospf->t_sr_update); OSPF_TIMER_OFF(ospf->t_default_routemap_timer); OSPF_TIMER_OFF(ospf->t_external_aggr); + OSPF_TIMER_OFF(ospf->gr_info.t_grace_period); LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa) ospf_discard_from_db(ospf, ospf->lsdb, lsa); @@ -826,7 +834,8 @@ static void ospf_finish_final(struct ospf *ospf) if (ospf->old_table) ospf_route_table_free(ospf->old_table); if (ospf->new_table) { - ospf_route_delete(ospf, ospf->new_table); + if (!ospf->gr_info.prepare_in_progress) + ospf_route_delete(ospf, ospf->new_table); ospf_route_table_free(ospf->new_table); } if (ospf->old_rtrs) @@ -834,11 +843,13 @@ static void ospf_finish_final(struct ospf *ospf) if (ospf->new_rtrs) ospf_rtrs_free(ospf->new_rtrs); if (ospf->new_external_route) { - ospf_route_delete(ospf, ospf->new_external_route); + if (!ospf->gr_info.prepare_in_progress) + ospf_route_delete(ospf, ospf->new_external_route); ospf_route_table_free(ospf->new_external_route); } if (ospf->old_external_route) { - ospf_route_delete(ospf, ospf->old_external_route); + if (!ospf->gr_info.prepare_in_progress) + ospf_route_delete(ospf, ospf->old_external_route); ospf_route_table_free(ospf->old_external_route); } if (ospf->external_lsas) { |