Skip to content

Commit dc45545

Browse files
committed
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 <[email protected]> Signed-off-by: Donald Sharp <[email protected]>
1 parent 900193b commit dc45545

File tree

4 files changed

+51
-18
lines changed

4 files changed

+51
-18
lines changed

zebra/main.c

+35-16
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ int allow_delete = 0;
7777
/* Don't delete kernel route. */
7878
int keep_kernel_mode = 0;
7979

80+
int graceful_restart;
81+
8082
bool v6_rr_semantics = false;
8183

8284
#ifdef HAVE_NETLINK
@@ -95,6 +97,7 @@ struct option longopts[] = {
9597
{"label_socket", no_argument, NULL, 'l'},
9698
{"retain", no_argument, NULL, 'r'},
9799
{"vrfdefaultname", required_argument, NULL, 'o'},
100+
{"graceful_restart", required_argument, NULL, 'K'},
98101
#ifdef HAVE_NETLINK
99102
{"vrfwnetns", no_argument, NULL, 'n'},
100103
{"nl-bufsize", required_argument, NULL, 's'},
@@ -264,13 +267,14 @@ int main(int argc, char **argv)
264267
char *netlink_fuzzing = NULL;
265268
#endif /* HANDLE_NETLINK_FUZZING */
266269

270+
graceful_restart = 0;
267271
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
268272
logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
269273

270274
frr_preinit(&zebra_di, argc, argv);
271275

272276
frr_opt_add(
273-
"bakz:e:l:o:r"
277+
"bakz:e:l:o:rK:"
274278
#ifdef HAVE_NETLINK
275279
"s:n"
276280
#endif
@@ -282,24 +286,25 @@ int main(int argc, char **argv)
282286
#endif /* HANDLE_NETLINK_FUZZING */
283287
,
284288
longopts,
285-
" -b, --batch Runs in batch mode\n"
286-
" -a, --allow_delete Allow other processes to delete zebra routes\n"
287-
" -z, --socket Set path of zebra socket\n"
288-
" -e, --ecmp Specify ECMP to use.\n"
289-
" -l, --label_socket Socket to external label manager\n"
290-
" -k, --keep_kernel Don't delete old routes which were installed by zebra.\n"
291-
" -r, --retain When program terminates, retain added route by zebra.\n"
292-
" -o, --vrfdefaultname Set default VRF name.\n"
289+
" -b, --batch Runs in batch mode\n"
290+
" -a, --allow_delete Allow other processes to delete zebra routes\n"
291+
" -z, --socket Set path of zebra socket\n"
292+
" -e, --ecmp Specify ECMP to use.\n"
293+
" -l, --label_socket Socket to external label manager\n"
294+
" -k, --keep_kernel Don't delete old routes which were installed by zebra.\n"
295+
" -r, --retain When program terminates, retain added route by zebra.\n"
296+
" -o, --vrfdefaultname Set default VRF name.\n"
297+
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
293298
#ifdef HAVE_NETLINK
294-
" -n, --vrfwnetns Use NetNS as VRF backend\n"
295-
" -s, --nl-bufsize Set netlink receive buffer size\n"
296-
" --v6-rr-semantics Use v6 RR semantics\n"
299+
" -n, --vrfwnetns Use NetNS as VRF backend\n"
300+
" -s, --nl-bufsize Set netlink receive buffer size\n"
301+
" --v6-rr-semantics Use v6 RR semantics\n"
297302
#endif /* HAVE_NETLINK */
298303
#if defined(HANDLE_ZAPI_FUZZING)
299-
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
304+
" -c <file> Bypass normal startup and use this file for testing of zapi\n"
300305
#endif /* HANDLE_ZAPI_FUZZING */
301306
#if defined(HANDLE_NETLINK_FUZZING)
302-
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
307+
" -w <file> Bypass normal startup and use this file for testing of netlink input\n"
303308
#endif /* HANDLE_NETLINK_FUZZING */
304309
);
305310

@@ -319,6 +324,10 @@ int main(int argc, char **argv)
319324
allow_delete = 1;
320325
break;
321326
case 'k':
327+
if (graceful_restart) {
328+
zlog_err("Graceful Restart initiated, we cannot keep the existing kernel routes");
329+
return 1;
330+
}
322331
keep_kernel_mode = 1;
323332
break;
324333
case 'e':
@@ -350,6 +359,15 @@ int main(int argc, char **argv)
350359
case 'r':
351360
retain_mode = 1;
352361
break;
362+
case 'K':
363+
if (keep_kernel_mode) {
364+
zlog_err("Keep Kernel mode specified, graceful restart incompatible");
365+
return 1;
366+
}
367+
graceful_restart = atoi(optarg);
368+
if (graceful_restart > 5 * GRACEFUL_RESTART_TIME)
369+
graceful_restart = 5 * GRACEFUL_RESTART_TIME;
370+
break;
353371
#ifdef HAVE_NETLINK
354372
case 's':
355373
nl_rcvbufsize = atoi(optarg);
@@ -437,8 +455,9 @@ int main(int argc, char **argv)
437455
* will be equal to the current getpid(). To know about such routes,
438456
* we have to have route_read() called before.
439457
*/
440-
if (!keep_kernel_mode)
441-
rib_sweep_route();
458+
zrouter.startup = time(NULL);
459+
thread_add_timer(zrouter.master, rib_sweep_route,
460+
NULL, graceful_restart, NULL);
442461

443462
/* Needed for BSD routing socket. */
444463
pid = getpid();

zebra/rib.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
351351
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
352352
extern void rib_update_table(struct route_table *table,
353353
rib_update_event_t event);
354-
extern void rib_sweep_route(void);
354+
extern int rib_sweep_route(struct thread *t);
355355
extern void rib_sweep_table(struct route_table *table);
356356
extern void rib_close_table(struct route_table *table);
357357
extern void rib_init(void);

zebra/zebra_rib.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -3139,12 +3139,15 @@ void rib_sweep_table(struct route_table *table)
31393139
struct route_entry *re;
31403140
struct route_entry *next;
31413141
struct nexthop *nexthop;
3142+
int64_t now = zrouter.startup;
31423143

31433144
if (!table)
31443145
return;
31453146

31463147
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
31473148
RNODE_FOREACH_RE_SAFE (rn, re, next) {
3149+
int64_t re_time = re->uptime;
3150+
31483151
if (IS_ZEBRA_DEBUG_RIB)
31493152
route_entry_dump(&rn->p, NULL, re);
31503153

@@ -3154,6 +3157,8 @@ void rib_sweep_table(struct route_table *table)
31543157
if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
31553158
continue;
31563159

3160+
if (now - re_time < 0)
3161+
continue;
31573162
/*
31583163
* So we are starting up and have received
31593164
* routes from the kernel that we have installed
@@ -3183,7 +3188,7 @@ void rib_sweep_table(struct route_table *table)
31833188
}
31843189

31853190
/* Sweep all RIB tables. */
3186-
void rib_sweep_route(void)
3191+
int rib_sweep_route(struct thread *t)
31873192
{
31883193
struct vrf *vrf;
31893194
struct zebra_vrf *zvrf;
@@ -3197,6 +3202,8 @@ void rib_sweep_route(void)
31973202
}
31983203

31993204
zebra_router_sweep_route();
3205+
3206+
return 0;
32003207
}
32013208

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

zebra/zebra_router.h

+7
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,15 @@ struct zebra_router {
110110
* The EVPN instance, if any
111111
*/
112112
struct zebra_vrf *evpn_vrf;
113+
114+
/*
115+
* Time for when we sweep the rib from old routes
116+
*/
117+
time_t startup;
113118
};
114119

120+
#define GRACEFUL_RESTART_TIME 60
121+
115122
extern struct zebra_router zrouter;
116123

117124
extern void zebra_router_init(void);

0 commit comments

Comments
 (0)