summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_zebra.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2021-07-02 13:01:32 -0300
committerRenato Westphal <renato@opensourcerouting.org>2021-09-16 12:26:48 -0300
commit711650980337fad6f70fd1e3bc17bf21428b7a62 (patch)
tree0440d27c923db83330c8135337b130104c44bc6a /ospf6d/ospf6_zebra.c
parent1a898463a3a496ae1fa70562ea7addec9a435e49 (diff)
ospf6d: introduce support for Graceful Restart (restarting mode)
RFC 5187 specifies the Graceful Restart enhancement to the OSPFv3 routing protocol. This commit implements support for the GR restarting mode. 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 ipv6 ospf` EXEC-level command needs to be issued before restarting the ospf6d 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 ospf6d 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. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ospf6d/ospf6_zebra.c')
-rw-r--r--ospf6d/ospf6_zebra.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 5403e643dc..c2e91d09bb 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -40,6 +40,7 @@
#include "ospf6_zebra.h"
#include "ospf6d.h"
#include "ospf6_area.h"
+#include "ospf6_gr.h"
#include "lib/json.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance");
@@ -173,6 +174,36 @@ static int ospf6_zebra_if_address_update_delete(ZAPI_CALLBACK_ARGS)
return 0;
}
+static int ospf6_zebra_gr_update(struct ospf6 *ospf6, int command,
+ uint32_t stale_time)
+{
+ struct zapi_cap api;
+
+ if (!zclient || zclient->sock < 0 || !ospf6)
+ return 1;
+
+ memset(&api, 0, sizeof(struct zapi_cap));
+ api.cap = command;
+ api.stale_removal_time = stale_time;
+ api.vrf_id = ospf6->vrf_id;
+
+ (void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient,
+ &api);
+
+ return 0;
+}
+
+int ospf6_zebra_gr_enable(struct ospf6 *ospf6, uint32_t stale_time)
+{
+ return ospf6_zebra_gr_update(ospf6, ZEBRA_CLIENT_GR_CAPABILITIES,
+ stale_time);
+}
+
+int ospf6_zebra_gr_disable(struct ospf6 *ospf6)
+{
+ return ospf6_zebra_gr_update(ospf6, ZEBRA_CLIENT_GR_DISABLE, 0);
+}
+
static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
{
struct zapi_route api;
@@ -384,12 +415,30 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request,
void ospf6_zebra_route_update_add(struct ospf6_route *request,
struct ospf6 *ospf6)
{
+ if (ospf6->gr_info.restart_in_progress
+ || ospf6->gr_info.prepare_in_progress) {
+ if (IS_DEBUG_OSPF6_GR)
+ zlog_debug(
+ "Zebra: Graceful Restart in progress -- not installing %pFX",
+ &request->prefix);
+ return;
+ }
+
ospf6_zebra_route_update(ADD, request, ospf6);
}
void ospf6_zebra_route_update_remove(struct ospf6_route *request,
struct ospf6 *ospf6)
{
+ if (ospf6->gr_info.restart_in_progress
+ || ospf6->gr_info.prepare_in_progress) {
+ if (IS_DEBUG_OSPF6_GR)
+ zlog_debug(
+ "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
+ &request->prefix);
+ return;
+ }
+
ospf6_zebra_route_update(REM, request, ospf6);
}
@@ -398,6 +447,15 @@ void ospf6_zebra_add_discard(struct ospf6_route *request, struct ospf6 *ospf6)
struct zapi_route api;
struct prefix *dest = &request->prefix;
+ if (ospf6->gr_info.restart_in_progress
+ || ospf6->gr_info.prepare_in_progress) {
+ if (IS_DEBUG_OSPF6_GR)
+ zlog_debug(
+ "Zebra: Graceful Restart in progress -- not installing %pFX",
+ &request->prefix);
+ return;
+ }
+
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = ospf6->vrf_id;
@@ -426,6 +484,15 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request,
struct zapi_route api;
struct prefix *dest = &request->prefix;
+ if (ospf6->gr_info.restart_in_progress
+ || ospf6->gr_info.prepare_in_progress) {
+ if (IS_DEBUG_OSPF6_GR)
+ zlog_debug(
+ "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
+ &request->prefix);
+ return;
+ }
+
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = ospf6->vrf_id;