Skip to content

Commit d78978e

Browse files
authored
zebra: Add kernel level graceful restart (#4301)
zebra: Add kernel level graceful restart
2 parents fa468cd + 33656d2 commit d78978e

File tree

5 files changed

+48
-25
lines changed

5 files changed

+48
-25
lines changed

doc/user/zebra.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
2323
Runs in batch mode. *zebra* parses configuration file and terminates
2424
immediately.
2525

26-
.. option:: -k, --keep_kernel
26+
.. option:: -K TIME, --graceful_restart TIME
2727

28-
When zebra starts up, don't delete old self inserted routes.
28+
If this option is specified, the graceful restart time is TIME seconds.
29+
Zebra, when started, will read in routes. Those routes that Zebra
30+
identifies that it was the originator of will be swept in TIME seconds.
31+
If no time is specified then we will sweep those routes immediately.
2932

3033
.. option:: -r, --retain
3134

zebra/main.c

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ int retain_mode = 0;
7474
/* Allow non-quagga entities to delete quagga routes */
7575
int allow_delete = 0;
7676

77-
/* Don't delete kernel route. */
78-
int keep_kernel_mode = 0;
77+
int graceful_restart;
7978

8079
bool v6_rr_semantics = false;
8180

@@ -95,6 +94,7 @@ struct option longopts[] = {
9594
{"label_socket", no_argument, NULL, 'l'},
9695
{"retain", no_argument, NULL, 'r'},
9796
{"vrfdefaultname", required_argument, NULL, 'o'},
97+
{"graceful_restart", required_argument, NULL, 'K'},
9898
#ifdef HAVE_NETLINK
9999
{"vrfwnetns", no_argument, NULL, 'n'},
100100
{"nl-bufsize", required_argument, NULL, 's'},
@@ -262,13 +262,14 @@ int main(int argc, char **argv)
262262
char *netlink_fuzzing = NULL;
263263
#endif /* HANDLE_NETLINK_FUZZING */
264264

265+
graceful_restart = 0;
265266
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
266267
logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
267268

268269
frr_preinit(&zebra_di, argc, argv);
269270

270271
frr_opt_add(
271-
"bakz:e:l:o:r"
272+
"baz:e:l:o:rK:"
272273
#ifdef HAVE_NETLINK
273274
"s:n"
274275
#endif
@@ -280,24 +281,24 @@ int main(int argc, char **argv)
280281
#endif /* HANDLE_NETLINK_FUZZING */
281282
,
282283
longopts,
283-
" -b, --batch Runs in batch mode\n"
284-
" -a, --allow_delete Allow other processes to delete zebra routes\n"
285-
" -z, --socket Set path of zebra socket\n"
286-
" -e, --ecmp Specify ECMP to use.\n"
287-
" -l, --label_socket Socket to external label manager\n"
288-
" -k, --keep_kernel Don't delete old routes which were installed by zebra.\n"
289-
" -r, --retain When program terminates, retain added route by zebra.\n"
290-
" -o, --vrfdefaultname Set default VRF name.\n"
284+
" -b, --batch Runs in batch mode\n"
285+
" -a, --allow_delete Allow other processes to delete zebra routes\n"
286+
" -z, --socket Set path of zebra socket\n"
287+
" -e, --ecmp Specify ECMP to use.\n"
288+
" -l, --label_socket Socket to external label manager\n"
289+
" -r, --retain When program terminates, retain added route by zebra.\n"
290+
" -o, --vrfdefaultname Set default VRF name.\n"
291+
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
291292
#ifdef HAVE_NETLINK
292-
" -n, --vrfwnetns Use NetNS as VRF backend\n"
293-
" -s, --nl-bufsize Set netlink receive buffer size\n"
294-
" --v6-rr-semantics Use v6 RR semantics\n"
293+
" -n, --vrfwnetns Use NetNS as VRF backend\n"
294+
" -s, --nl-bufsize Set netlink receive buffer size\n"
295+
" --v6-rr-semantics Use v6 RR semantics\n"
295296
#endif /* HAVE_NETLINK */
296297
#if defined(HANDLE_ZAPI_FUZZING)
297-
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
298+
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
298299
#endif /* HANDLE_ZAPI_FUZZING */
299300
#if defined(HANDLE_NETLINK_FUZZING)
300-
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
301+
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
301302
#endif /* HANDLE_NETLINK_FUZZING */
302303
);
303304

@@ -316,9 +317,6 @@ int main(int argc, char **argv)
316317
case 'a':
317318
allow_delete = 1;
318319
break;
319-
case 'k':
320-
keep_kernel_mode = 1;
321-
break;
322320
case 'e':
323321
zrouter.multipath_num = atoi(optarg);
324322
if (zrouter.multipath_num > MULTIPATH_NUM
@@ -348,6 +346,9 @@ int main(int argc, char **argv)
348346
case 'r':
349347
retain_mode = 1;
350348
break;
349+
case 'K':
350+
graceful_restart = atoi(optarg);
351+
break;
351352
#ifdef HAVE_NETLINK
352353
case 's':
353354
nl_rcvbufsize = atoi(optarg);
@@ -435,8 +436,9 @@ int main(int argc, char **argv)
435436
* will be equal to the current getpid(). To know about such routes,
436437
* we have to have route_read() called before.
437438
*/
438-
if (!keep_kernel_mode)
439-
rib_sweep_route();
439+
zrouter.startup_time = monotime(NULL);
440+
thread_add_timer(zrouter.master, rib_sweep_route,
441+
NULL, graceful_restart, NULL);
440442

441443
/* Needed for BSD routing socket. */
442444
pid = getpid();

zebra/rib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
400400
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
401401
extern void rib_update_table(struct route_table *table,
402402
rib_update_event_t event);
403-
extern void rib_sweep_route(void);
403+
extern int rib_sweep_route(struct thread *t);
404404
extern void rib_sweep_table(struct route_table *table);
405405
extern void rib_close_table(struct route_table *table);
406406
extern void rib_init(void);

zebra/zebra_rib.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3127,6 +3127,7 @@ void rib_sweep_table(struct route_table *table)
31273127

31283128
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
31293129
RNODE_FOREACH_RE_SAFE (rn, re, next) {
3130+
31303131
if (IS_ZEBRA_DEBUG_RIB)
31313132
route_entry_dump(&rn->p, NULL, re);
31323133

@@ -3136,6 +3137,14 @@ void rib_sweep_table(struct route_table *table)
31363137
if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
31373138
continue;
31383139

3140+
/*
3141+
* If routes are older than startup_time then
3142+
* we know we read them in from the kernel.
3143+
* As such we can safely remove them.
3144+
*/
3145+
if (zrouter.startup_time < re->uptime)
3146+
continue;
3147+
31393148
/*
31403149
* So we are starting up and have received
31413150
* routes from the kernel that we have installed
@@ -3165,7 +3174,7 @@ void rib_sweep_table(struct route_table *table)
31653174
}
31663175

31673176
/* Sweep all RIB tables. */
3168-
void rib_sweep_route(void)
3177+
int rib_sweep_route(struct thread *t)
31693178
{
31703179
struct vrf *vrf;
31713180
struct zebra_vrf *zvrf;
@@ -3179,6 +3188,8 @@ void rib_sweep_route(void)
31793188
}
31803189

31813190
zebra_router_sweep_route();
3191+
3192+
return 0;
31823193
}
31833194

31843195
/* Remove specific by protocol routes from 'table'. */

zebra/zebra_router.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,15 @@ struct zebra_router {
112112
struct zebra_vrf *evpn_vrf;
113113

114114
uint32_t multipath_num;
115+
116+
/*
117+
* Time for when we sweep the rib from old routes
118+
*/
119+
time_t startup_time;
115120
};
116121

122+
#define GRACEFUL_RESTART_TIME 60
123+
117124
extern struct zebra_router zrouter;
118125

119126
extern void zebra_router_init(void);

0 commit comments

Comments
 (0)