/src/frr/zebra/zebra_gr.c
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * Zebra GR related helper functions. |
4 | | * |
5 | | * Portions: |
6 | | * Copyright (C) 2019 VMware, Inc. |
7 | | * et al. |
8 | | */ |
9 | | |
10 | | #include <zebra.h> |
11 | | #include <libgen.h> |
12 | | |
13 | | #include "lib/prefix.h" |
14 | | #include "lib/command.h" |
15 | | #include "lib/if.h" |
16 | | #include "frrevent.h" |
17 | | #include "lib/stream.h" |
18 | | #include "lib/memory.h" |
19 | | #include "lib/table.h" |
20 | | #include "lib/network.h" |
21 | | #include "lib/sockunion.h" |
22 | | #include "lib/log.h" |
23 | | #include "lib/zclient.h" |
24 | | #include "lib/privs.h" |
25 | | #include "lib/network.h" |
26 | | #include "lib/buffer.h" |
27 | | #include "lib/nexthop.h" |
28 | | #include "lib/vrf.h" |
29 | | #include "lib/libfrr.h" |
30 | | #include "lib/sockopt.h" |
31 | | |
32 | | #include "zebra/zebra_router.h" |
33 | | #include "zebra/debug.h" |
34 | | #include "zebra/zapi_msg.h" |
35 | | |
36 | | DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_GR, "GR"); |
37 | | |
38 | | /* |
39 | | * Forward declaration. |
40 | | */ |
41 | | static struct zserv *zebra_gr_find_stale_client(struct zserv *client); |
42 | | static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread); |
43 | | static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info); |
44 | | static void zebra_gr_process_client_stale_routes(struct zserv *client, |
45 | | struct client_gr_info *info); |
46 | | static void zebra_gr_delete_stale_route_table_afi(struct event *event); |
47 | | /* |
48 | | * Debug macros. |
49 | | */ |
50 | | #define LOG_GR(msg, ...) \ |
51 | 0 | do { \ |
52 | 0 | if (IS_ZEBRA_DEBUG_EVENT) \ |
53 | 0 | zlog_debug(msg, ##__VA_ARGS__); \ |
54 | 0 | } while (0) |
55 | | |
56 | | /* |
57 | | * Client connection functions |
58 | | */ |
59 | | |
60 | | /* |
61 | | * Function to clean all the stale clients, |
62 | | * function will also clean up all per instance |
63 | | * capabilities that are exchanged. |
64 | | */ |
65 | | void zebra_gr_stale_client_cleanup(struct list *client_list) |
66 | 0 | { |
67 | 0 | struct listnode *node, *nnode; |
68 | 0 | struct zserv *s_client = NULL; |
69 | 0 | struct client_gr_info *info, *ninfo; |
70 | | |
71 | | /* Find the stale client */ |
72 | 0 | for (ALL_LIST_ELEMENTS(client_list, node, nnode, s_client)) { |
73 | |
|
74 | 0 | LOG_GR("%s: Stale client %s is being deleted", __func__, |
75 | 0 | zebra_route_string(s_client->proto)); |
76 | |
|
77 | 0 | TAILQ_FOREACH_SAFE (info, &s_client->gr_info_queue, gr_info, |
78 | 0 | ninfo) { |
79 | | |
80 | | /* Cancel the stale timer */ |
81 | 0 | if (info->t_stale_removal != NULL) { |
82 | 0 | EVENT_OFF(info->t_stale_removal); |
83 | 0 | info->t_stale_removal = NULL; |
84 | 0 | info->do_delete = true; |
85 | | /* Process the stale routes */ |
86 | 0 | event_execute( |
87 | 0 | zrouter.master, |
88 | 0 | zebra_gr_route_stale_delete_timer_expiry, |
89 | 0 | info, 0); |
90 | 0 | } |
91 | 0 | } |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | /* |
96 | | * A helper function to create client info. |
97 | | */ |
98 | | static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client) |
99 | 0 | { |
100 | 0 | struct client_gr_info *info; |
101 | |
|
102 | 0 | info = XCALLOC(MTYPE_ZEBRA_GR, sizeof(struct client_gr_info)); |
103 | |
|
104 | 0 | info->stale_client_ptr = client; |
105 | |
|
106 | 0 | TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info); |
107 | 0 | return info; |
108 | 0 | } |
109 | | |
110 | | /* |
111 | | * A helper function to delete and destroy client info. |
112 | | */ |
113 | | static void zebra_gr_client_info_delete(struct zserv *client, |
114 | | struct client_gr_info *info) |
115 | 0 | { |
116 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
117 | |
|
118 | 0 | TAILQ_REMOVE(&(client->gr_info_queue), info, gr_info); |
119 | |
|
120 | 0 | EVENT_OFF(info->t_stale_removal); |
121 | |
|
122 | 0 | LOG_GR("%s: Instance info is being deleted for client %s vrf %s(%u)", |
123 | 0 | __func__, zebra_route_string(client->proto), VRF_LOGNAME(vrf), |
124 | 0 | info->vrf_id); |
125 | | |
126 | | /* Delete all the stale routes. */ |
127 | 0 | info->do_delete = true; |
128 | 0 | zebra_gr_delete_stale_routes(info); |
129 | |
|
130 | 0 | XFREE(MTYPE_ZEBRA_GR, info); |
131 | 0 | } |
132 | | |
133 | | /* |
134 | | * Function to handle client when it disconnect. |
135 | | */ |
136 | | int32_t zebra_gr_client_disconnect(struct zserv *client) |
137 | 0 | { |
138 | 0 | struct zserv *stale_client; |
139 | 0 | struct timeval tv; |
140 | 0 | struct client_gr_info *info = NULL; |
141 | | |
142 | | /* Find the stale client */ |
143 | 0 | stale_client = zebra_gr_find_stale_client(client); |
144 | | |
145 | | /* |
146 | | * We should never be here. |
147 | | */ |
148 | 0 | if (stale_client) { |
149 | 0 | LOG_GR("%s: Stale client %s exist, we should not be here!", |
150 | 0 | __func__, zebra_route_string(client->proto)); |
151 | | #ifndef FUZZING |
152 | | assert(0); |
153 | | #endif |
154 | 0 | } |
155 | |
|
156 | 0 | client->restart_time = monotime(&tv); |
157 | | |
158 | | /* For all the GR instance start the stale removal timer. */ |
159 | 0 | #ifdef FUZZING |
160 | 0 | struct client_gr_info dupinfo = {}; |
161 | 0 | #endif |
162 | 0 | TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { |
163 | 0 | if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities) |
164 | 0 | && (info->t_stale_removal == NULL)) { |
165 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
166 | |
|
167 | 0 | event_add_timer( |
168 | 0 | zrouter.master, |
169 | 0 | zebra_gr_route_stale_delete_timer_expiry, info, |
170 | 0 | info->stale_removal_time, |
171 | 0 | &info->t_stale_removal); |
172 | 0 | info->stale_client_ptr = client; |
173 | 0 | info->stale_client = true; |
174 | 0 | LOG_GR("%s: Client %s vrf %s(%u) Stale timer update to %d", |
175 | 0 | __func__, zebra_route_string(client->proto), |
176 | 0 | VRF_LOGNAME(vrf), info->vrf_id, |
177 | 0 | info->stale_removal_time); |
178 | |
|
179 | 0 | dupinfo = *info; |
180 | 0 | #ifdef FUZZING |
181 | | // yeah, that thread will never execute...clean it up now |
182 | | //struct thread t = {}; |
183 | 0 | struct event t = {}; |
184 | 0 | t.arg = info; |
185 | 0 | info->t_stale_removal = &t; |
186 | 0 | zebra_gr_route_stale_delete_timer_expiry(&t); |
187 | 0 | info = &dupinfo; |
188 | 0 | #endif |
189 | 0 | } |
190 | 0 | } |
191 | | #ifndef FUZZING |
192 | | listnode_add(zrouter.stale_client_list, client); |
193 | | #endif |
194 | 0 | return 0; |
195 | 0 | } |
196 | | |
197 | | /* |
198 | | * Function to delete stale client |
199 | | */ |
200 | | static void zebra_gr_delete_stale_client(struct client_gr_info *info) |
201 | 0 | { |
202 | 0 | struct client_gr_info *bgp_info; |
203 | 0 | struct zserv *s_client = NULL; |
204 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
205 | |
|
206 | 0 | s_client = info->stale_client_ptr; |
207 | |
|
208 | 0 | if (!s_client || !info->stale_client) |
209 | 0 | return; |
210 | | |
211 | | /* |
212 | | * If there are bgp instances with the stale delete timer pending |
213 | | * then stale client is not deleted |
214 | | */ |
215 | 0 | if ((s_client->gr_instance_count > 0) && info->gr_enable) |
216 | 0 | s_client->gr_instance_count--; |
217 | |
|
218 | 0 | TAILQ_REMOVE(&(s_client->gr_info_queue), info, gr_info); |
219 | |
|
220 | 0 | LOG_GR("%s: Client %s gr count %d", __func__, |
221 | 0 | zebra_route_string(s_client->proto), |
222 | 0 | s_client->gr_instance_count); |
223 | |
|
224 | 0 | TAILQ_FOREACH (bgp_info, &s_client->gr_info_queue, gr_info) { |
225 | 0 | if (bgp_info->t_stale_removal != NULL) |
226 | 0 | return; |
227 | 0 | } |
228 | | |
229 | 0 | LOG_GR("%s: Client %s vrf %s(%u) is being deleted", __func__, |
230 | 0 | zebra_route_string(s_client->proto), VRF_LOGNAME(vrf), |
231 | 0 | info->vrf_id); |
232 | |
|
233 | 0 | TAILQ_INIT(&(s_client->gr_info_queue)); |
234 | 0 | listnode_delete(zrouter.stale_client_list, s_client); |
235 | 0 | if (info->stale_client) |
236 | 0 | zserv_client_delete(s_client); |
237 | 0 | XFREE(MTYPE_ZEBRA_GR, info); |
238 | 0 | } |
239 | | |
240 | | /* |
241 | | * Function to find stale client. |
242 | | */ |
243 | | static struct zserv *zebra_gr_find_stale_client(struct zserv *client) |
244 | 0 | { |
245 | 0 | struct listnode *node, *nnode; |
246 | 0 | struct zserv *stale_client; |
247 | | |
248 | | /* Find the stale client */ |
249 | 0 | for (ALL_LIST_ELEMENTS(zrouter.stale_client_list, node, nnode, |
250 | 0 | stale_client)) { |
251 | 0 | if (client->proto == stale_client->proto |
252 | 0 | && client->instance == stale_client->instance) { |
253 | 0 | return stale_client; |
254 | 0 | } |
255 | 0 | } |
256 | | |
257 | 0 | return NULL; |
258 | 0 | } |
259 | | |
260 | | /* |
261 | | * Function to handle reconnect of client post restart. |
262 | | */ |
263 | | void zebra_gr_client_reconnect(struct zserv *client) |
264 | 0 | { |
265 | 0 | struct listnode *node, *nnode; |
266 | 0 | struct zserv *old_client = NULL; |
267 | 0 | struct client_gr_info *info = NULL; |
268 | | |
269 | | /* Find the stale client */ |
270 | 0 | for (ALL_LIST_ELEMENTS(zrouter.stale_client_list, node, nnode, |
271 | 0 | old_client)) { |
272 | 0 | if (client->proto == old_client->proto |
273 | 0 | && client->instance == old_client->instance) |
274 | 0 | break; |
275 | 0 | } |
276 | | |
277 | | /* Copy the timers */ |
278 | 0 | if (!old_client) |
279 | 0 | return; |
280 | | |
281 | 0 | client->gr_instance_count = old_client->gr_instance_count; |
282 | 0 | client->restart_time = old_client->restart_time; |
283 | |
|
284 | 0 | LOG_GR("%s : old client %s, gr_instance_count %d", __func__, |
285 | 0 | zebra_route_string(old_client->proto), |
286 | 0 | old_client->gr_instance_count); |
287 | |
|
288 | 0 | if (TAILQ_FIRST(&old_client->gr_info_queue)) { |
289 | 0 | TAILQ_CONCAT(&client->gr_info_queue, &old_client->gr_info_queue, |
290 | 0 | gr_info); |
291 | 0 | TAILQ_INIT(&old_client->gr_info_queue); |
292 | 0 | } |
293 | |
|
294 | 0 | TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { |
295 | 0 | info->stale_client_ptr = client; |
296 | 0 | info->stale_client = false; |
297 | 0 | } |
298 | | |
299 | | /* Delete the stale client */ |
300 | 0 | listnode_delete(zrouter.stale_client_list, old_client); |
301 | | /* Delete old client */ |
302 | 0 | zserv_client_delete(old_client); |
303 | 0 | } |
304 | | |
305 | | struct zebra_gr_afi_clean { |
306 | | struct client_gr_info *info; |
307 | | afi_t afi; |
308 | | uint8_t proto; |
309 | | uint8_t instance; |
310 | | |
311 | | struct event *t_gac; |
312 | | }; |
313 | | |
314 | | /* |
315 | | * Functions to deal with capabilities |
316 | | */ |
317 | | |
318 | | /* |
319 | | * Function to decode and call appropriate functions |
320 | | * to handle client capabilities. |
321 | | */ |
322 | | void zread_client_capabilities(ZAPI_HANDLER_ARGS) |
323 | 0 | { |
324 | 0 | struct zapi_cap api; |
325 | 0 | struct client_gr_info *info = NULL; |
326 | 0 | struct stream *s; |
327 | 0 | struct vrf *vrf; |
328 | |
|
329 | 0 | s = msg; |
330 | |
|
331 | 0 | if (zapi_capabilities_decode(s, &api)) { |
332 | 0 | LOG_GR("%s: Error in reading capabilities for client %s", |
333 | 0 | __func__, zebra_route_string(client->proto)); |
334 | 0 | return; |
335 | 0 | } |
336 | | |
337 | 0 | vrf = vrf_lookup_by_id(api.vrf_id); |
338 | | |
339 | | /* |
340 | | * If this ever matters uncomment and add safi to the |
341 | | * arrays as needed to track |
342 | | */ |
343 | 0 | if (api.safi != SAFI_UNICAST) |
344 | 0 | return; |
345 | | |
346 | | /* GR only for dynamic clients */ |
347 | 0 | if (client->proto <= ZEBRA_ROUTE_CONNECT) { |
348 | 0 | LOG_GR("%s: GR capabilities for client %s not supported", |
349 | 0 | __func__, zebra_route_string(client->proto)); |
350 | 0 | return; |
351 | 0 | } |
352 | | |
353 | | /* Find the bgp information for the specified vrf id */ |
354 | 0 | TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { |
355 | 0 | if (info->vrf_id == api.vrf_id) |
356 | 0 | break; |
357 | 0 | } |
358 | | |
359 | | /* |
360 | | * If the command is delete, then cancel the stale timer and |
361 | | * delete the bgp info |
362 | | */ |
363 | 0 | switch (api.cap) { |
364 | 0 | case ZEBRA_CLIENT_GR_DISABLE: |
365 | 0 | if (!info) |
366 | 0 | return; |
367 | | |
368 | 0 | LOG_GR("%s: Client %s instance GR disabled count %d", __func__, |
369 | 0 | zebra_route_string(client->proto), |
370 | 0 | client->gr_instance_count); |
371 | |
|
372 | 0 | if ((info->gr_enable) && (client->gr_instance_count > 0)) |
373 | 0 | client->gr_instance_count--; |
374 | |
|
375 | 0 | zebra_gr_client_info_delete(client, info); |
376 | 0 | break; |
377 | 0 | case ZEBRA_CLIENT_GR_CAPABILITIES: |
378 | | /* Allocate bgp info */ |
379 | 0 | if (!info) |
380 | 0 | info = zebra_gr_client_info_create(client); |
381 | | |
382 | | /* Update other parameters */ |
383 | 0 | if (!info->gr_enable) { |
384 | 0 | client->gr_instance_count++; |
385 | |
|
386 | 0 | LOG_GR("%s: Cient %s vrf %s(%u) GR enabled count %d", |
387 | 0 | __func__, zebra_route_string(client->proto), |
388 | 0 | VRF_LOGNAME(vrf), api.vrf_id, |
389 | 0 | client->gr_instance_count); |
390 | |
|
391 | 0 | info->capabilities = api.cap; |
392 | 0 | info->stale_removal_time = api.stale_removal_time; |
393 | 0 | info->vrf_id = api.vrf_id; |
394 | 0 | info->gr_enable = true; |
395 | 0 | } |
396 | 0 | break; |
397 | 0 | case ZEBRA_CLIENT_RIB_STALE_TIME: |
398 | 0 | LOG_GR("%s: Client %s stale time update event", __func__, |
399 | 0 | zebra_route_string(client->proto)); |
400 | | |
401 | | /* Update the stale removal timer */ |
402 | 0 | if (info && info->t_stale_removal == NULL) { |
403 | |
|
404 | 0 | LOG_GR("%s: vrf %s(%u) Stale time: %d is now update to: %d", |
405 | 0 | __func__, VRF_LOGNAME(vrf), info->vrf_id, |
406 | 0 | info->stale_removal_time, |
407 | 0 | api.stale_removal_time); |
408 | |
|
409 | 0 | info->stale_removal_time = api.stale_removal_time; |
410 | 0 | } |
411 | |
|
412 | 0 | break; |
413 | 0 | case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE: |
414 | 0 | if (!info) { |
415 | 0 | LOG_GR("%s: Client %s route update complete for AFI %d, SAFI %d, no Graceful Restart communication, returning", |
416 | 0 | __func__, zebra_route_string(client->proto), |
417 | 0 | api.afi, api.safi); |
418 | 0 | return; |
419 | 0 | } |
420 | | |
421 | 0 | LOG_GR("%s: Client %s vrf %s(%u) route update complete for AFI %d, SAFI %d", |
422 | 0 | __func__, zebra_route_string(client->proto), |
423 | 0 | VRF_LOGNAME(vrf), info->vrf_id, api.afi, api.safi); |
424 | 0 | info->route_sync[api.afi] = true; |
425 | | |
426 | | /* |
427 | | * Schedule for after anything already in the meta Q |
428 | | */ |
429 | 0 | rib_add_gr_run(api.afi, api.vrf_id, client->proto, |
430 | 0 | client->instance); |
431 | 0 | zebra_gr_process_client_stale_routes(client, info); |
432 | 0 | break; |
433 | 0 | case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING: |
434 | 0 | if (!info) { |
435 | 0 | LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d", |
436 | 0 | __func__, zebra_route_string(client->proto), |
437 | 0 | api.afi, api.safi); |
438 | 0 | } else { |
439 | 0 | LOG_GR("%s: Client %s vrf %s(%u) route update pending for AFI %d, SAFI %d", |
440 | 0 | __func__, zebra_route_string(client->proto), |
441 | 0 | VRF_LOGNAME(vrf), info->vrf_id, api.afi, |
442 | 0 | api.safi); |
443 | |
|
444 | 0 | info->af_enabled[api.afi] = true; |
445 | 0 | } |
446 | 0 | break; |
447 | 0 | } |
448 | 0 | } |
449 | | |
450 | | /* |
451 | | * Stale route handling |
452 | | */ |
453 | | |
454 | | /* |
455 | | * Delete all the stale routes that have not been refreshed |
456 | | * post restart. |
457 | | */ |
458 | | static void zebra_gr_route_stale_delete_timer_expiry(struct event *thread) |
459 | 0 | { |
460 | 0 | struct client_gr_info *info = EVENT_ARG(thread); |
461 | 0 | int32_t cnt = 0; |
462 | 0 | struct zserv *client; |
463 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
464 | |
|
465 | 0 | client = (struct zserv *)info->stale_client_ptr; |
466 | |
|
467 | 0 | cnt = zebra_gr_delete_stale_routes(info); |
468 | | |
469 | | /* Restart the timer */ |
470 | 0 | if (cnt > 0) { |
471 | 0 | LOG_GR("%s: Client %s vrf %s(%u) processed %d routes. Start timer again", |
472 | 0 | __func__, zebra_route_string(client->proto), |
473 | 0 | VRF_LOGNAME(vrf), info->vrf_id, cnt); |
474 | |
|
475 | 0 | event_add_timer(zrouter.master, |
476 | 0 | zebra_gr_route_stale_delete_timer_expiry, info, |
477 | 0 | ZEBRA_DEFAULT_STALE_UPDATE_DELAY, |
478 | 0 | &info->t_stale_removal); |
479 | 0 | } else { |
480 | | /* No routes to delete for the VRF */ |
481 | 0 | LOG_GR("%s: Client %s vrf %s(%u) all stale routes processed", |
482 | 0 | __func__, zebra_route_string(client->proto), |
483 | 0 | VRF_LOGNAME(vrf), info->vrf_id); |
484 | |
|
485 | 0 | zebra_gr_delete_stale_client(info); |
486 | 0 | } |
487 | 0 | } |
488 | | |
489 | | |
490 | | /* |
491 | | * Function to process to check if route entry is stale |
492 | | * or has been updated. |
493 | | * |
494 | | * Returns true when a node is deleted else false |
495 | | */ |
496 | | static bool zebra_gr_process_route_entry(struct zserv *client, |
497 | | struct route_node *rn, |
498 | | struct route_entry *re) |
499 | 0 | { |
500 | 0 | /* If the route is not refreshed after restart, delete the entry */ |
501 | 0 | if (re->uptime < client->restart_time) { |
502 | 0 | if (IS_ZEBRA_DEBUG_RIB) |
503 | 0 | zlog_debug("%s: Client %s stale route %pFX is deleted", |
504 | 0 | __func__, zebra_route_string(client->proto), |
505 | 0 | &rn->p); |
506 | 0 | rib_delnode(rn, re); |
507 | 0 |
|
508 | 0 | return true; |
509 | 0 | } |
510 | 0 |
|
511 | 0 | return false; |
512 | 0 | } |
513 | | |
514 | | static void zebra_gr_delete_stale_route_table_afi(struct event *event) |
515 | 0 | { |
516 | 0 | struct zebra_gr_afi_clean *gac = EVENT_ARG(event); |
517 | 0 | struct route_table *table; |
518 | 0 | struct route_node *rn; |
519 | 0 | struct route_entry *re, *next; |
520 | 0 | struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(gac->info->vrf_id); |
521 | 0 | int32_t n = 0; |
522 | 0 |
|
523 | 0 | if (!zvrf) |
524 | 0 | goto done; |
525 | 0 |
|
526 | 0 | table = zvrf->table[gac->afi][SAFI_UNICAST]; |
527 | 0 | if (!table) |
528 | 0 | goto done; |
529 | 0 |
|
530 | 0 | for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { |
531 | 0 | RNODE_FOREACH_RE_SAFE (rn, re, next) { |
532 | 0 | if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) |
533 | 0 | continue; |
534 | 0 |
|
535 | 0 | /* If the route refresh is received |
536 | 0 | * after restart then do not delete |
537 | 0 | * the route |
538 | 0 | */ |
539 | 0 |
|
540 | 0 | if (re->type == gac->proto && |
541 | 0 | re->instance == gac->instance && |
542 | 0 | zebra_gr_process_route_entry( |
543 | 0 | gac->info->stale_client_ptr, rn, re)) |
544 | 0 | n++; |
545 | 0 |
|
546 | 0 | /* If the max route count is reached |
547 | 0 | * then timer thread will be restarted |
548 | 0 | * Store the current prefix and afi |
549 | 0 | */ |
550 | 0 | if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT) && |
551 | 0 | (gac->info->do_delete == false)) { |
552 | 0 | event_add_timer( |
553 | 0 | zrouter.master, |
554 | 0 | zebra_gr_delete_stale_route_table_afi, |
555 | 0 | gac, ZEBRA_DEFAULT_STALE_UPDATE_DELAY, |
556 | 0 | &gac->t_gac); |
557 | 0 | } |
558 | 0 | } |
559 | 0 | } |
560 | 0 |
|
561 | 0 | done: |
562 | 0 | XFREE(MTYPE_ZEBRA_GR, gac); |
563 | 0 | } |
564 | | |
565 | | /* |
566 | | * This function walks through the route table for all vrf and deletes |
567 | | * the stale routes for the restarted client specified by the protocol |
568 | | * type |
569 | | */ |
570 | | static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info, |
571 | | struct zebra_vrf *zvrf) |
572 | 0 | { |
573 | 0 | afi_t afi; |
574 | 0 | uint8_t proto; |
575 | 0 | uint16_t instance; |
576 | 0 | struct zserv *s_client; |
577 | |
|
578 | 0 | s_client = info->stale_client_ptr; |
579 | 0 | if (s_client == NULL) { |
580 | 0 | LOG_GR("%s: Stale client %s(%u) not present", __func__, |
581 | 0 | zvrf->vrf->name, zvrf->vrf->vrf_id); |
582 | 0 | return -1; |
583 | 0 | } |
584 | | |
585 | 0 | proto = s_client->proto; |
586 | 0 | instance = s_client->instance; |
587 | |
|
588 | 0 | LOG_GR("%s: Client %s %s(%u) stale routes are being deleted", __func__, |
589 | 0 | zebra_route_string(proto), zvrf->vrf->name, zvrf->vrf->vrf_id); |
590 | | |
591 | | /* Process routes for all AFI */ |
592 | 0 | for (afi = AFI_IP; afi < AFI_MAX; afi++) { |
593 | | |
594 | | /* |
595 | | * Schedule for immediately after anything in the |
596 | | * meta-Q |
597 | | */ |
598 | 0 | rib_add_gr_run(afi, info->vrf_id, proto, instance); |
599 | 0 | } |
600 | 0 | return 0; |
601 | 0 | } |
602 | | |
603 | | /* |
604 | | * Delete the stale routes when client is restarted and routes are not |
605 | | * refreshed within the stale timeout |
606 | | */ |
607 | | static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info) |
608 | 0 | { |
609 | 0 | struct zebra_vrf *zvrf; |
610 | 0 | uint64_t cnt = 0; |
611 | |
|
612 | 0 | if (info == NULL) |
613 | 0 | return -1; |
614 | | |
615 | 0 | zvrf = zebra_vrf_lookup_by_id(info->vrf_id); |
616 | 0 | if (zvrf == NULL) { |
617 | 0 | LOG_GR("%s: Invalid VRF entry %u", __func__, info->vrf_id); |
618 | 0 | return -1; |
619 | 0 | } |
620 | | |
621 | 0 | cnt = zebra_gr_delete_stale_route(info, zvrf); |
622 | 0 | return cnt; |
623 | 0 | } |
624 | | |
625 | | /* |
626 | | * This function checks if route update for all AFI, SAFI is completed |
627 | | * and cancels the stale timer |
628 | | */ |
629 | | static void zebra_gr_process_client_stale_routes(struct zserv *client, |
630 | | struct client_gr_info *info) |
631 | 0 | { |
632 | 0 | afi_t afi; |
633 | |
|
634 | 0 | if (info == NULL) |
635 | 0 | return; |
636 | | |
637 | | /* Check if route update completed for all AFI, SAFI */ |
638 | 0 | for (afi = AFI_IP; afi < AFI_MAX; afi++) { |
639 | 0 | if (info->af_enabled[afi] && !info->route_sync[afi]) { |
640 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
641 | |
|
642 | 0 | LOG_GR("%s: Client %s vrf: %s(%u) route update not completed for AFI %d", |
643 | 0 | __func__, zebra_route_string(client->proto), |
644 | 0 | VRF_LOGNAME(vrf), info->vrf_id, afi); |
645 | 0 | return; |
646 | 0 | } |
647 | 0 | } |
648 | | |
649 | | /* |
650 | | * Route update completed for all AFI, SAFI |
651 | | * Cancel the stale timer, routes are already being processed |
652 | | */ |
653 | 0 | if (info->t_stale_removal) { |
654 | 0 | struct vrf *vrf = vrf_lookup_by_id(info->vrf_id); |
655 | |
|
656 | 0 | LOG_GR("%s: Client %s canceled stale delete timer vrf %s(%d)", |
657 | 0 | __func__, zebra_route_string(client->proto), |
658 | 0 | VRF_LOGNAME(vrf), info->vrf_id); |
659 | 0 | EVENT_OFF(info->t_stale_removal); |
660 | 0 | } |
661 | 0 | } |
662 | | |
663 | | void zebra_gr_process_client(afi_t afi, vrf_id_t vrf_id, uint8_t proto, |
664 | | uint8_t instance) |
665 | 0 | { |
666 | 0 | struct zserv *client = zserv_find_client(proto, instance); |
667 | 0 | struct client_gr_info *info = NULL; |
668 | 0 | struct zebra_gr_afi_clean *gac; |
669 | |
|
670 | 0 | if (client == NULL) |
671 | 0 | return; |
672 | | |
673 | 0 | TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) { |
674 | 0 | if (info->vrf_id == vrf_id) |
675 | 0 | break; |
676 | 0 | } |
677 | |
|
678 | 0 | if (info == NULL) |
679 | 0 | return; |
680 | | |
681 | 0 | gac = XCALLOC(MTYPE_ZEBRA_GR, sizeof(*gac)); |
682 | 0 | gac->info = info; |
683 | 0 | gac->afi = afi; |
684 | 0 | gac->proto = proto; |
685 | 0 | gac->instance = instance; |
686 | |
|
687 | 0 | event_add_event(zrouter.master, zebra_gr_delete_stale_route_table_afi, |
688 | 0 | gac, 0, &gac->t_gac); |
689 | 0 | } |