From 423d4812848375a9556cc9024db42e2d843a47e9 Mon Sep 17 00:00:00 2001 From: Praveen Chaudhary Date: Thu, 17 Oct 2019 07:08:13 -0700 Subject: [PATCH] [FRR]: Patch for kernel level graceful restart. (#3621) * [FRR]: Patch for kernel level graceful restart. Original Patch in FRR master: https://github.com/FRRouting/frr/pull/4301 * Rename 0007-zebra-kernel-level-graceful-restart.patch to 0008-zebra-kernel-level-graceful-restart.patch --- ...-zebra-kernel-level-graceful-restart.patch | 227 ++++++++++++++++++ src/sonic-frr/patch/series | 1 + 2 files changed, 228 insertions(+) create mode 100644 src/sonic-frr/patch/0008-zebra-kernel-level-graceful-restart.patch diff --git a/src/sonic-frr/patch/0008-zebra-kernel-level-graceful-restart.patch b/src/sonic-frr/patch/0008-zebra-kernel-level-graceful-restart.patch new file mode 100644 index 000000000000..e2a68a3507b4 --- /dev/null +++ b/src/sonic-frr/patch/0008-zebra-kernel-level-graceful-restart.patch @@ -0,0 +1,227 @@ + + zebra: Add kernel level graceful restart + + + + Add the a `--graceful_restart X` flag to zebra start that + now creates a timer that pops in X seconds and will go + through and remove all routes that are older than startup. + + If graceful_restart is not specified then we will just pop + a timer that cleans everything up immediately. + + Signed-off-by: Praveen Chaudhary + Signed-off-by: Donald Sharp + +diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst +index f38db9d24..40d894929 100644 +--- a/doc/user/zebra.rst ++++ b/doc/user/zebra.rst +@@ -23,9 +23,12 @@ Besides the common invocation options (:ref:`common-invocation-options`), the + Runs in batch mode. *zebra* parses configuration file and terminates + immediately. + +-.. option:: -k, --keep_kernel ++.. option:: -K TIME, --graceful_restart TIME + +- When zebra starts up, don't delete old self inserted routes. ++ If this option is specified, the graceful restart time is TIME seconds. ++ Zebra, when started, will read in routes. Those routes that Zebra ++ identifies that it was the originator of will be swept in TIME seconds. ++ If no time is specified then we will sweep those routes immediately. + + .. option:: -r, --retain + +diff --git a/zebra/main.c b/zebra/main.c +index 184e798bd..3d1d156ad 100644 +--- a/zebra/main.c ++++ b/zebra/main.c +@@ -74,8 +74,7 @@ int retain_mode = 0; + /* Allow non-quagga entities to delete quagga routes */ + int allow_delete = 0; + +-/* Don't delete kernel route. */ +-int keep_kernel_mode = 0; ++int graceful_restart; + + bool v6_rr_semantics = false; + +@@ -89,12 +88,12 @@ uint32_t nl_rcvbufsize = 4194304; + struct option longopts[] = { + {"batch", no_argument, NULL, 'b'}, + {"allow_delete", no_argument, NULL, 'a'}, +- {"keep_kernel", no_argument, NULL, 'k'}, + {"socket", required_argument, NULL, 'z'}, + {"ecmp", required_argument, NULL, 'e'}, + {"label_socket", no_argument, NULL, 'l'}, + {"retain", no_argument, NULL, 'r'}, + {"vrfdefaultname", required_argument, NULL, 'o'}, ++ {"graceful_restart", required_argument, NULL, 'K'}, + #ifdef HAVE_NETLINK + {"vrfwnetns", no_argument, NULL, 'n'}, + {"nl-bufsize", required_argument, NULL, 's'}, +@@ -264,13 +263,14 @@ int main(int argc, char **argv) + char *netlink_fuzzing = NULL; + #endif /* HANDLE_NETLINK_FUZZING */ + ++ graceful_restart = 0; + vrf_configure_backend(VRF_BACKEND_VRF_LITE); + logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS); + + frr_preinit(&zebra_di, argc, argv); + + frr_opt_add( +- "bakz:e:l:o:r" ++ "baz:e:l:o:rK:" + #ifdef HAVE_NETLINK + "s:n" + #endif +@@ -282,24 +282,24 @@ int main(int argc, char **argv) + #endif /* HANDLE_NETLINK_FUZZING */ + , + longopts, +- " -b, --batch Runs in batch mode\n" +- " -a, --allow_delete Allow other processes to delete zebra routes\n" +- " -z, --socket Set path of zebra socket\n" +- " -e, --ecmp Specify ECMP to use.\n" +- " -l, --label_socket Socket to external label manager\n" +- " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n" +- " -r, --retain When program terminates, retain added route by zebra.\n" +- " -o, --vrfdefaultname Set default VRF name.\n" ++ " -b, --batch Runs in batch mode\n" ++ " -a, --allow_delete Allow other processes to delete zebra routes\n" ++ " -z, --socket Set path of zebra socket\n" ++ " -e, --ecmp Specify ECMP to use.\n" ++ " -l, --label_socket Socket to external label manager\n" ++ " -r, --retain When program terminates, retain added route by zebra.\n" ++ " -o, --vrfdefaultname Set default VRF name.\n" ++ " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n" + #ifdef HAVE_NETLINK +- " -n, --vrfwnetns Use NetNS as VRF backend\n" +- " -s, --nl-bufsize Set netlink receive buffer size\n" +- " --v6-rr-semantics Use v6 RR semantics\n" ++ " -n, --vrfwnetns Use NetNS as VRF backend\n" ++ " -s, --nl-bufsize Set netlink receive buffer size\n" ++ " --v6-rr-semantics Use v6 RR semantics\n" + #endif /* HAVE_NETLINK */ + #if defined(HANDLE_ZAPI_FUZZING) +- " -c Bypass normal startup and use this file for testing of zapi\n" ++ " -c Bypass normal startup and use this file for testing of zapi\n" + #endif /* HANDLE_ZAPI_FUZZING */ + #if defined(HANDLE_NETLINK_FUZZING) +- " -w Bypass normal startup and use this file for testing of netlink input\n" ++ " -w Bypass normal startup and use this file for testing of netlink input\n" + #endif /* HANDLE_NETLINK_FUZZING */ + ); + +@@ -318,9 +318,6 @@ int main(int argc, char **argv) + case 'a': + allow_delete = 1; + break; +- case 'k': +- keep_kernel_mode = 1; +- break; + case 'e': + multipath_num = atoi(optarg); + if (multipath_num > MULTIPATH_NUM +@@ -350,6 +347,9 @@ int main(int argc, char **argv) + case 'r': + retain_mode = 1; + break; ++ case 'K': ++ graceful_restart = atoi(optarg); ++ break; + #ifdef HAVE_NETLINK + case 's': + nl_rcvbufsize = atoi(optarg); +@@ -437,9 +437,9 @@ int main(int argc, char **argv) + * will be equal to the current getpid(). To know about such routes, + * we have to have route_read() called before. + */ +- if (!keep_kernel_mode) +- rib_sweep_route(); +- ++ zrouter.startup_time = monotime(NULL); ++ thread_add_timer(zrouter.master, rib_sweep_route, ++ NULL, graceful_restart, NULL); + /* Needed for BSD routing socket. */ + pid = getpid(); + +diff --git a/zebra/rib.h b/zebra/rib.h +index 9fe42aef3..69850f3a0 100644 +--- a/zebra/rib.h ++++ b/zebra/rib.h +@@ -351,7 +351,7 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, + extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event); + extern void rib_update_table(struct route_table *table, + rib_update_event_t event); +-extern void rib_sweep_route(void); ++extern int rib_sweep_route(struct thread *t); + extern void rib_sweep_table(struct route_table *table); + extern void rib_close_table(struct route_table *table); + extern void rib_init(void); +diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c +index 555127b09..b6afcdc8c 100644 +--- a/zebra/zebra_rib.c ++++ b/zebra/zebra_rib.c +@@ -3145,6 +3145,7 @@ void rib_sweep_table(struct route_table *table) + + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + RNODE_FOREACH_RE_SAFE (rn, re, next) { ++ + if (IS_ZEBRA_DEBUG_RIB) + route_entry_dump(&rn->p, NULL, re); + +@@ -3154,6 +3155,14 @@ void rib_sweep_table(struct route_table *table) + if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE)) + continue; + ++ /* ++ * If routes are older than startup_time then ++ * we know we read them in from the kernel. ++ * As such we can safely remove them. ++ */ ++ if (zrouter.startup_time < re->uptime) ++ continue; ++ + /* + * So we are starting up and have received + * routes from the kernel that we have installed +@@ -3183,7 +3192,7 @@ void rib_sweep_table(struct route_table *table) + } + + /* Sweep all RIB tables. */ +-void rib_sweep_route(void) ++int rib_sweep_route(struct thread *t) + { + struct vrf *vrf; + struct zebra_vrf *zvrf; +@@ -3197,6 +3206,8 @@ void rib_sweep_route(void) + } + + zebra_router_sweep_route(); ++ ++ return 0; + } + + /* Remove specific by protocol routes from 'table'. */ +diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h +index b316b91d0..b2e92bad0 100644 +--- a/zebra/zebra_router.h ++++ b/zebra/zebra_router.h +@@ -110,8 +110,15 @@ struct zebra_router { + * The EVPN instance, if any + */ + struct zebra_vrf *evpn_vrf; ++ ++ /* ++ * Time for when we sweep the rib from old routes ++ */ ++ time_t startup_time; + }; + ++#define GRACEFUL_RESTART_TIME 60 ++ + extern struct zebra_router zrouter; + + extern void zebra_router_init(void); diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index edeb30ce1e71..da0ab7ba47c5 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -4,3 +4,4 @@ 0005-Support-VRF.patch 0006-changes-for-making-snmp-socket-non-blocking.patch 0007-prevent-dead-fd-poll-data-port-fix-from-frr.patch +0008-zebra-kernel-level-graceful-restart.patch \ No newline at end of file