mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 16:42:32 +00:00
zebra: Add kernel level graceful restart
<Initial Code from Praveen Chaudhary> 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 <pchaudhary@linkedin.com> Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
528628cb2e
commit
d4644d4196
@ -27,6 +27,13 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
|
|||||||
|
|
||||||
When zebra starts up, don't delete old self inserted routes.
|
When zebra starts up, don't delete old self inserted routes.
|
||||||
|
|
||||||
|
.. option:: -K TIME, --graceful_restart TIME
|
||||||
|
|
||||||
|
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
|
.. option:: -r, --retain
|
||||||
|
|
||||||
When program terminates, do not flush routes installed by *zebra* from the
|
When program terminates, do not flush routes installed by *zebra* from the
|
||||||
|
48
zebra/main.c
48
zebra/main.c
@ -77,6 +77,8 @@ int allow_delete = 0;
|
|||||||
/* Don't delete kernel route. */
|
/* Don't delete kernel route. */
|
||||||
int keep_kernel_mode = 0;
|
int keep_kernel_mode = 0;
|
||||||
|
|
||||||
|
int graceful_restart;
|
||||||
|
|
||||||
bool v6_rr_semantics = false;
|
bool v6_rr_semantics = false;
|
||||||
|
|
||||||
#ifdef HAVE_NETLINK
|
#ifdef HAVE_NETLINK
|
||||||
@ -95,6 +97,7 @@ struct option longopts[] = {
|
|||||||
{"label_socket", no_argument, NULL, 'l'},
|
{"label_socket", no_argument, NULL, 'l'},
|
||||||
{"retain", no_argument, NULL, 'r'},
|
{"retain", no_argument, NULL, 'r'},
|
||||||
{"vrfdefaultname", required_argument, NULL, 'o'},
|
{"vrfdefaultname", required_argument, NULL, 'o'},
|
||||||
|
{"graceful_restart", required_argument, NULL, 'K'},
|
||||||
#ifdef HAVE_NETLINK
|
#ifdef HAVE_NETLINK
|
||||||
{"vrfwnetns", no_argument, NULL, 'n'},
|
{"vrfwnetns", no_argument, NULL, 'n'},
|
||||||
{"nl-bufsize", required_argument, NULL, 's'},
|
{"nl-bufsize", required_argument, NULL, 's'},
|
||||||
@ -262,13 +265,14 @@ int main(int argc, char **argv)
|
|||||||
char *netlink_fuzzing = NULL;
|
char *netlink_fuzzing = NULL;
|
||||||
#endif /* HANDLE_NETLINK_FUZZING */
|
#endif /* HANDLE_NETLINK_FUZZING */
|
||||||
|
|
||||||
|
graceful_restart = 0;
|
||||||
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
|
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
|
||||||
logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
|
logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
|
||||||
|
|
||||||
frr_preinit(&zebra_di, argc, argv);
|
frr_preinit(&zebra_di, argc, argv);
|
||||||
|
|
||||||
frr_opt_add(
|
frr_opt_add(
|
||||||
"bakz:e:l:o:r"
|
"bakz:e:l:o:rK:"
|
||||||
#ifdef HAVE_NETLINK
|
#ifdef HAVE_NETLINK
|
||||||
"s:n"
|
"s:n"
|
||||||
#endif
|
#endif
|
||||||
@ -280,24 +284,25 @@ int main(int argc, char **argv)
|
|||||||
#endif /* HANDLE_NETLINK_FUZZING */
|
#endif /* HANDLE_NETLINK_FUZZING */
|
||||||
,
|
,
|
||||||
longopts,
|
longopts,
|
||||||
" -b, --batch Runs in batch mode\n"
|
" -b, --batch Runs in batch mode\n"
|
||||||
" -a, --allow_delete Allow other processes to delete zebra routes\n"
|
" -a, --allow_delete Allow other processes to delete zebra routes\n"
|
||||||
" -z, --socket Set path of zebra socket\n"
|
" -z, --socket Set path of zebra socket\n"
|
||||||
" -e, --ecmp Specify ECMP to use.\n"
|
" -e, --ecmp Specify ECMP to use.\n"
|
||||||
" -l, --label_socket Socket to external label manager\n"
|
" -l, --label_socket Socket to external label manager\n"
|
||||||
" -k, --keep_kernel Don't delete old routes which were installed by zebra.\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"
|
" -r, --retain When program terminates, retain added route by zebra.\n"
|
||||||
" -o, --vrfdefaultname Set default VRF name.\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
|
#ifdef HAVE_NETLINK
|
||||||
" -n, --vrfwnetns Use NetNS as VRF backend\n"
|
" -n, --vrfwnetns Use NetNS as VRF backend\n"
|
||||||
" -s, --nl-bufsize Set netlink receive buffer size\n"
|
" -s, --nl-bufsize Set netlink receive buffer size\n"
|
||||||
" --v6-rr-semantics Use v6 RR semantics\n"
|
" --v6-rr-semantics Use v6 RR semantics\n"
|
||||||
#endif /* HAVE_NETLINK */
|
#endif /* HAVE_NETLINK */
|
||||||
#if defined(HANDLE_ZAPI_FUZZING)
|
#if defined(HANDLE_ZAPI_FUZZING)
|
||||||
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
|
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
|
||||||
#endif /* HANDLE_ZAPI_FUZZING */
|
#endif /* HANDLE_ZAPI_FUZZING */
|
||||||
#if defined(HANDLE_NETLINK_FUZZING)
|
#if defined(HANDLE_NETLINK_FUZZING)
|
||||||
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
|
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
|
||||||
#endif /* HANDLE_NETLINK_FUZZING */
|
#endif /* HANDLE_NETLINK_FUZZING */
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -317,6 +322,10 @@ int main(int argc, char **argv)
|
|||||||
allow_delete = 1;
|
allow_delete = 1;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
|
if (graceful_restart) {
|
||||||
|
zlog_err("Graceful Restart initiated, we cannot keep the existing kernel routes");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
keep_kernel_mode = 1;
|
keep_kernel_mode = 1;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
@ -348,6 +357,13 @@ int main(int argc, char **argv)
|
|||||||
case 'r':
|
case 'r':
|
||||||
retain_mode = 1;
|
retain_mode = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'K':
|
||||||
|
if (keep_kernel_mode) {
|
||||||
|
zlog_err("Keep Kernel mode specified, graceful restart incompatible");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
graceful_restart = atoi(optarg);
|
||||||
|
break;
|
||||||
#ifdef HAVE_NETLINK
|
#ifdef HAVE_NETLINK
|
||||||
case 's':
|
case 's':
|
||||||
nl_rcvbufsize = atoi(optarg);
|
nl_rcvbufsize = atoi(optarg);
|
||||||
@ -435,8 +451,10 @@ int main(int argc, char **argv)
|
|||||||
* will be equal to the current getpid(). To know about such routes,
|
* will be equal to the current getpid(). To know about such routes,
|
||||||
* we have to have route_read() called before.
|
* we have to have route_read() called before.
|
||||||
*/
|
*/
|
||||||
|
zrouter.startup_time = monotime(NULL);
|
||||||
if (!keep_kernel_mode)
|
if (!keep_kernel_mode)
|
||||||
rib_sweep_route();
|
thread_add_timer(zrouter.master, rib_sweep_route,
|
||||||
|
NULL, graceful_restart, NULL);
|
||||||
|
|
||||||
/* Needed for BSD routing socket. */
|
/* Needed for BSD routing socket. */
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
@ -400,7 +400,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(vrf_id_t vrf_id, rib_update_event_t event);
|
||||||
extern void rib_update_table(struct route_table *table,
|
extern void rib_update_table(struct route_table *table,
|
||||||
rib_update_event_t event);
|
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_sweep_table(struct route_table *table);
|
||||||
extern void rib_close_table(struct route_table *table);
|
extern void rib_close_table(struct route_table *table);
|
||||||
extern void rib_init(void);
|
extern void rib_init(void);
|
||||||
|
@ -3127,6 +3127,7 @@ void rib_sweep_table(struct route_table *table)
|
|||||||
|
|
||||||
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
|
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
|
||||||
RNODE_FOREACH_RE_SAFE (rn, re, next) {
|
RNODE_FOREACH_RE_SAFE (rn, re, next) {
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_RIB)
|
if (IS_ZEBRA_DEBUG_RIB)
|
||||||
route_entry_dump(&rn->p, NULL, re);
|
route_entry_dump(&rn->p, NULL, re);
|
||||||
|
|
||||||
@ -3136,6 +3137,14 @@ void rib_sweep_table(struct route_table *table)
|
|||||||
if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
|
if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
|
||||||
continue;
|
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
|
* So we are starting up and have received
|
||||||
* routes from the kernel that we have installed
|
* routes from the kernel that we have installed
|
||||||
@ -3165,7 +3174,7 @@ void rib_sweep_table(struct route_table *table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sweep all RIB tables. */
|
/* Sweep all RIB tables. */
|
||||||
void rib_sweep_route(void)
|
int rib_sweep_route(struct thread *t)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
@ -3179,6 +3188,8 @@ void rib_sweep_route(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
zebra_router_sweep_route();
|
zebra_router_sweep_route();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove specific by protocol routes from 'table'. */
|
/* Remove specific by protocol routes from 'table'. */
|
||||||
|
@ -112,8 +112,15 @@ struct zebra_router {
|
|||||||
struct zebra_vrf *evpn_vrf;
|
struct zebra_vrf *evpn_vrf;
|
||||||
|
|
||||||
uint32_t multipath_num;
|
uint32_t multipath_num;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 struct zebra_router zrouter;
|
||||||
|
|
||||||
extern void zebra_router_init(void);
|
extern void zebra_router_init(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user