/src/frr/zebra/redistribute.c
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* Redistribution Handler |
3 | | * Copyright (C) 1998 Kunihiro Ishiguro |
4 | | */ |
5 | | |
6 | | #include <zebra.h> |
7 | | |
8 | | #include "vector.h" |
9 | | #include "vty.h" |
10 | | #include "command.h" |
11 | | #include "prefix.h" |
12 | | #include "table.h" |
13 | | #include "stream.h" |
14 | | #include "zclient.h" |
15 | | #include "linklist.h" |
16 | | #include "log.h" |
17 | | #include "vrf.h" |
18 | | #include "srcdest_table.h" |
19 | | |
20 | | #include "zebra/rib.h" |
21 | | #include "zebra/zebra_router.h" |
22 | | #include "zebra/zebra_ns.h" |
23 | | #include "zebra/zebra_vrf.h" |
24 | | #include "zebra/zebra_routemap.h" |
25 | | #include "zebra/redistribute.h" |
26 | | #include "zebra/debug.h" |
27 | | #include "zebra/router-id.h" |
28 | | #include "zebra/zapi_msg.h" |
29 | | #include "zebra/zebra_vxlan.h" |
30 | | #include "zebra/zebra_errors.h" |
31 | | |
32 | | #define ZEBRA_PTM_SUPPORT |
33 | | |
34 | | /* array holding redistribute info about table redistribution */ |
35 | | /* bit AFI is set if that AFI is redistributing routes from this table */ |
36 | | static int zebra_import_table_used[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; |
37 | | static uint32_t zebra_import_table_distance[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; |
38 | | |
39 | | int is_zebra_import_table_enabled(afi_t afi, vrf_id_t vrf_id, uint32_t table_id) |
40 | 0 | { |
41 | | /* |
42 | | * Make sure that what we are called with actualy makes sense |
43 | | */ |
44 | 0 | if (afi == AFI_MAX) |
45 | 0 | return 0; |
46 | | |
47 | 0 | if (is_zebra_valid_kernel_table(table_id) && |
48 | 0 | table_id < ZEBRA_KERNEL_TABLE_MAX) |
49 | 0 | return zebra_import_table_used[afi][table_id]; |
50 | 0 | return 0; |
51 | 0 | } |
52 | | |
53 | | static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id) |
54 | 0 | { |
55 | 0 | int afi; |
56 | 0 | struct prefix p; |
57 | 0 | struct route_table *table; |
58 | 0 | struct route_node *rn; |
59 | 0 | struct route_entry *newre; |
60 | |
|
61 | 0 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { |
62 | |
|
63 | 0 | if (!vrf_bitmap_check(client->redist_default[afi], vrf_id)) |
64 | 0 | continue; |
65 | | |
66 | | /* Lookup table. */ |
67 | 0 | table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); |
68 | 0 | if (!table) |
69 | 0 | continue; |
70 | | |
71 | | /* Lookup default route. */ |
72 | 0 | memset(&p, 0, sizeof(p)); |
73 | 0 | p.family = afi2family(afi); |
74 | 0 | rn = route_node_lookup(table, &p); |
75 | 0 | if (!rn) |
76 | 0 | continue; |
77 | | |
78 | 0 | RNODE_FOREACH_RE (rn, newre) { |
79 | 0 | if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) |
80 | 0 | zsend_redistribute_route( |
81 | 0 | ZEBRA_REDISTRIBUTE_ROUTE_ADD, client, |
82 | 0 | rn, newre); |
83 | 0 | } |
84 | |
|
85 | 0 | route_unlock_node(rn); |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | | /* Redistribute routes. */ |
90 | | static void zebra_redistribute(struct zserv *client, int type, |
91 | | unsigned short instance, vrf_id_t vrf_id, |
92 | | int afi) |
93 | 0 | { |
94 | 0 | struct route_entry *newre; |
95 | 0 | struct route_table *table; |
96 | 0 | struct route_node *rn; |
97 | |
|
98 | 0 | table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); |
99 | 0 | if (!table) |
100 | 0 | return; |
101 | | |
102 | 0 | for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) |
103 | 0 | RNODE_FOREACH_RE (rn, newre) { |
104 | 0 | if (IS_ZEBRA_DEBUG_RIB) |
105 | 0 | zlog_debug( |
106 | 0 | "%s: client %s %pRN(%u:%u) checking: selected=%d, type=%s, instance=%u, distance=%d, metric=%d zebra_check_addr=%d", |
107 | 0 | __func__, |
108 | 0 | zebra_route_string(client->proto), rn, |
109 | 0 | vrf_id, newre->instance, |
110 | 0 | !!CHECK_FLAG(newre->flags, |
111 | 0 | ZEBRA_FLAG_SELECTED), |
112 | 0 | zebra_route_string(newre->type), |
113 | 0 | newre->instance, |
114 | 0 | newre->distance, |
115 | 0 | newre->metric, |
116 | 0 | zebra_check_addr(&rn->p)); |
117 | |
|
118 | 0 | if (!CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)) |
119 | 0 | continue; |
120 | 0 | if ((type != ZEBRA_ROUTE_ALL |
121 | 0 | && (newre->type != type |
122 | 0 | || newre->instance != instance))) |
123 | 0 | continue; |
124 | 0 | if (!zebra_check_addr(&rn->p)) |
125 | 0 | continue; |
126 | | |
127 | 0 | zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, |
128 | 0 | client, rn, newre); |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | | /* |
133 | | * Function to check if prefix is candidate for |
134 | | * redistribute. |
135 | | */ |
136 | | static bool zebra_redistribute_check(const struct route_node *rn, |
137 | | const struct route_entry *re, |
138 | | struct zserv *client) |
139 | 0 | { |
140 | 0 | struct zebra_vrf *zvrf; |
141 | 0 | afi_t afi; |
142 | | |
143 | | /* Process only if there is valid re */ |
144 | 0 | if (!re) |
145 | 0 | return false; |
146 | | |
147 | 0 | afi = family2afi(rn->p.family); |
148 | 0 | zvrf = zebra_vrf_lookup_by_id(re->vrf_id); |
149 | 0 | if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) |
150 | 0 | return false; |
151 | | |
152 | | /* If default route and redistributed */ |
153 | 0 | if (is_default_prefix(&rn->p) && |
154 | 0 | vrf_bitmap_check(client->redist_default[afi], re->vrf_id)) |
155 | 0 | return true; |
156 | | |
157 | | /* If redistribute in enabled for zebra route all */ |
158 | 0 | if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id)) |
159 | 0 | return true; |
160 | | |
161 | | /* |
162 | | * If multi-instance then check for route |
163 | | * redistribution for given instance. |
164 | | */ |
165 | 0 | if (re->instance) { |
166 | 0 | if (redist_check_instance(&client->mi_redist[afi][re->type], |
167 | 0 | re->instance)) |
168 | 0 | return true; |
169 | 0 | else |
170 | 0 | return false; |
171 | 0 | } |
172 | | |
173 | | /* If redistribution is enabled for give route type. */ |
174 | 0 | if (vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id)) |
175 | 0 | return true; |
176 | | |
177 | 0 | return false; |
178 | 0 | } |
179 | | |
180 | | /* Either advertise a route for redistribution to registered clients or */ |
181 | | /* withdraw redistribution if add cannot be done for client */ |
182 | | void redistribute_update(const struct route_node *rn, |
183 | | const struct route_entry *re, |
184 | | const struct route_entry *prev_re) |
185 | 0 | { |
186 | 0 | struct listnode *node, *nnode; |
187 | 0 | struct zserv *client; |
188 | |
|
189 | 0 | if (IS_ZEBRA_DEBUG_RIB) |
190 | 0 | zlog_debug( |
191 | 0 | "(%u:%u):%pRN(%u): Redist update re %p (%s), old %p (%s)", |
192 | 0 | re->vrf_id, re->table, rn, re->instance, re, |
193 | 0 | zebra_route_string(re->type), prev_re, |
194 | 0 | prev_re ? zebra_route_string(prev_re->type) : "None"); |
195 | |
|
196 | 0 | if (!zebra_check_addr(&rn->p)) { |
197 | 0 | if (IS_ZEBRA_DEBUG_RIB) |
198 | 0 | zlog_debug("Redist update filter prefix %pRN", rn); |
199 | 0 | return; |
200 | 0 | } |
201 | | |
202 | | |
203 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
204 | 0 | if (zebra_redistribute_check(rn, re, client)) { |
205 | 0 | if (IS_ZEBRA_DEBUG_RIB) { |
206 | 0 | zlog_debug( |
207 | 0 | "%s: client %s %pRN(%u:%u), type=%d, distance=%d, metric=%d", |
208 | 0 | __func__, |
209 | 0 | zebra_route_string(client->proto), rn, |
210 | 0 | re->vrf_id, re->table, re->type, |
211 | 0 | re->distance, re->metric); |
212 | 0 | } |
213 | 0 | zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD, |
214 | 0 | client, rn, re); |
215 | 0 | } else if (zebra_redistribute_check(rn, prev_re, client)) |
216 | 0 | zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, |
217 | 0 | client, rn, prev_re); |
218 | 0 | } |
219 | 0 | } |
220 | | |
221 | | /* |
222 | | * During a route delete, where 'new_re' is NULL, redist a delete to all |
223 | | * clients registered for the type of 'old_re'. |
224 | | * During a route update, redist a delete to any clients who will not see |
225 | | * an update when the new route is installed. There are cases when a client |
226 | | * may have seen a redist for 'old_re', but will not see |
227 | | * the redist for 'new_re'. |
228 | | */ |
229 | | void redistribute_delete(const struct route_node *rn, |
230 | | const struct route_entry *old_re, |
231 | | const struct route_entry *new_re) |
232 | 0 | { |
233 | 0 | struct listnode *node, *nnode; |
234 | 0 | struct zserv *client; |
235 | 0 | vrf_id_t vrfid; |
236 | |
|
237 | 0 | if (old_re) |
238 | 0 | vrfid = old_re->vrf_id; |
239 | 0 | else if (new_re) |
240 | 0 | vrfid = new_re->vrf_id; |
241 | 0 | else |
242 | 0 | return; |
243 | | |
244 | 0 | if (IS_ZEBRA_DEBUG_RIB) { |
245 | 0 | uint8_t old_inst, new_inst; |
246 | 0 | uint32_t table = 0; |
247 | |
|
248 | 0 | old_inst = new_inst = 0; |
249 | |
|
250 | 0 | if (old_re) { |
251 | 0 | old_inst = old_re->instance; |
252 | 0 | table = old_re->table; |
253 | 0 | } |
254 | 0 | if (new_re) { |
255 | 0 | new_inst = new_re->instance; |
256 | 0 | table = new_re->table; |
257 | 0 | } |
258 | |
|
259 | 0 | zlog_debug( |
260 | 0 | "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)", |
261 | 0 | vrfid, table, rn, old_re, old_inst, |
262 | 0 | old_re ? zebra_route_string(old_re->type) : "None", |
263 | 0 | new_re, new_inst, |
264 | 0 | new_re ? zebra_route_string(new_re->type) : "None"); |
265 | 0 | } |
266 | | |
267 | | /* Skip invalid (e.g. linklocal) prefix */ |
268 | 0 | if (!zebra_check_addr(&rn->p)) { |
269 | 0 | if (IS_ZEBRA_DEBUG_RIB) { |
270 | 0 | zlog_debug( |
271 | 0 | "%u:%pRN: Redist del old: skipping invalid prefix", |
272 | 0 | vrfid, rn); |
273 | 0 | } |
274 | 0 | return; |
275 | 0 | } |
276 | | |
277 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
278 | | /* Do not send unsolicited messages to synchronous clients. */ |
279 | 0 | if (client->synchronous) |
280 | 0 | continue; |
281 | | /* |
282 | | * Skip this client if it will receive an update for the |
283 | | * 'new' re |
284 | | */ |
285 | 0 | if (zebra_redistribute_check(rn, new_re, client)) |
286 | 0 | continue; |
287 | | |
288 | | /* Send a delete for the 'old' re to any subscribed client. */ |
289 | 0 | if (zebra_redistribute_check(rn, old_re, client)) |
290 | 0 | zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL, |
291 | 0 | client, rn, old_re); |
292 | 0 | } |
293 | 0 | } |
294 | | |
295 | | |
296 | | void zebra_redistribute_add(ZAPI_HANDLER_ARGS) |
297 | 0 | { |
298 | 0 | afi_t afi = 0; |
299 | 0 | int type = 0; |
300 | 0 | unsigned short instance; |
301 | |
|
302 | 0 | STREAM_GETC(msg, afi); |
303 | 0 | STREAM_GETC(msg, type); |
304 | 0 | STREAM_GETW(msg, instance); |
305 | | |
306 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
307 | 0 | zlog_debug( |
308 | 0 | "%s: client proto %s afi=%d, wants %s, vrf %s(%u), instance=%d", |
309 | 0 | __func__, zebra_route_string(client->proto), afi, |
310 | 0 | zebra_route_string(type), VRF_LOGNAME(zvrf->vrf), |
311 | 0 | zvrf_id(zvrf), instance); |
312 | |
|
313 | 0 | if (afi == 0 || afi >= AFI_MAX) { |
314 | 0 | flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, |
315 | 0 | "%s: Specified afi %d does not exist", __func__, afi); |
316 | 0 | return; |
317 | 0 | } |
318 | | |
319 | 0 | if (type == 0 || type >= ZEBRA_ROUTE_MAX) { |
320 | 0 | zlog_debug("%s: Specified Route Type %d does not exist", |
321 | 0 | __func__, type); |
322 | 0 | return; |
323 | 0 | } |
324 | | |
325 | 0 | if (instance) { |
326 | 0 | if (!redist_check_instance(&client->mi_redist[afi][type], |
327 | 0 | instance)) { |
328 | 0 | redist_add_instance(&client->mi_redist[afi][type], |
329 | 0 | instance); |
330 | 0 | zebra_redistribute(client, type, instance, |
331 | 0 | zvrf_id(zvrf), afi); |
332 | 0 | } |
333 | 0 | } else { |
334 | 0 | if (!vrf_bitmap_check(client->redist[afi][type], |
335 | 0 | zvrf_id(zvrf))) { |
336 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
337 | 0 | zlog_debug( |
338 | 0 | "%s: setting vrf %s(%u) redist bitmap", |
339 | 0 | __func__, VRF_LOGNAME(zvrf->vrf), |
340 | 0 | zvrf_id(zvrf)); |
341 | 0 | vrf_bitmap_set(client->redist[afi][type], |
342 | 0 | zvrf_id(zvrf)); |
343 | 0 | zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi); |
344 | 0 | } |
345 | 0 | } |
346 | |
|
347 | 0 | stream_failure: |
348 | 0 | return; |
349 | 0 | } |
350 | | |
351 | | void zebra_redistribute_delete(ZAPI_HANDLER_ARGS) |
352 | 0 | { |
353 | 0 | afi_t afi = 0; |
354 | 0 | int type = 0; |
355 | 0 | unsigned short instance; |
356 | |
|
357 | 0 | STREAM_GETC(msg, afi); |
358 | 0 | STREAM_GETC(msg, type); |
359 | 0 | STREAM_GETW(msg, instance); |
360 | | |
361 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
362 | 0 | zlog_debug( |
363 | 0 | "%s: client proto %s afi=%d, no longer wants %s, vrf %s(%u), instance=%d", |
364 | 0 | __func__, zebra_route_string(client->proto), afi, |
365 | 0 | zebra_route_string(type), VRF_LOGNAME(zvrf->vrf), |
366 | 0 | zvrf_id(zvrf), instance); |
367 | | |
368 | |
|
369 | 0 | if (afi == 0 || afi >= AFI_MAX) { |
370 | 0 | flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, |
371 | 0 | "%s: Specified afi %d does not exist", __func__, afi); |
372 | 0 | return; |
373 | 0 | } |
374 | | |
375 | 0 | if (type == 0 || type >= ZEBRA_ROUTE_MAX) { |
376 | 0 | zlog_debug("%s: Specified Route Type %d does not exist", |
377 | 0 | __func__, type); |
378 | 0 | return; |
379 | 0 | } |
380 | | |
381 | | /* |
382 | | * NOTE: no need to withdraw the previously advertised routes. The |
383 | | * clients |
384 | | * themselves should keep track of the received routes from zebra and |
385 | | * withdraw them when necessary. |
386 | | */ |
387 | 0 | if (instance) |
388 | 0 | redist_del_instance(&client->mi_redist[afi][type], instance); |
389 | 0 | else |
390 | 0 | vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf)); |
391 | |
|
392 | 0 | stream_failure: |
393 | 0 | return; |
394 | 0 | } |
395 | | |
396 | | void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS) |
397 | 0 | { |
398 | 0 | afi_t afi = 0; |
399 | |
|
400 | 0 | STREAM_GETC(msg, afi); |
401 | | |
402 | 0 | if (afi == 0 || afi >= AFI_MAX) { |
403 | 0 | flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, |
404 | 0 | "%s: Specified afi %u does not exist", __func__, afi); |
405 | 0 | return; |
406 | 0 | } |
407 | | |
408 | 0 | vrf_bitmap_set(client->redist_default[afi], zvrf_id(zvrf)); |
409 | 0 | zebra_redistribute_default(client, zvrf_id(zvrf)); |
410 | |
|
411 | 0 | stream_failure: |
412 | 0 | return; |
413 | 0 | } |
414 | | |
415 | | void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS) |
416 | 0 | { |
417 | 0 | afi_t afi = 0; |
418 | |
|
419 | 0 | STREAM_GETC(msg, afi); |
420 | | |
421 | 0 | if (afi == 0 || afi >= AFI_MAX) { |
422 | 0 | flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, |
423 | 0 | "%s: Specified afi %u does not exist", __func__, afi); |
424 | 0 | return; |
425 | 0 | } |
426 | | |
427 | 0 | vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); |
428 | |
|
429 | 0 | stream_failure: |
430 | 0 | return; |
431 | 0 | } |
432 | | |
433 | | /* Interface up information. */ |
434 | | void zebra_interface_up_update(struct interface *ifp) |
435 | 0 | { |
436 | 0 | struct listnode *node, *nnode; |
437 | 0 | struct zserv *client; |
438 | |
|
439 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
440 | 0 | zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s vrf %s(%u)", |
441 | 0 | ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); |
442 | |
|
443 | 0 | if (ifp->ptm_status || !ifp->ptm_enable) { |
444 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, |
445 | 0 | client)) { |
446 | | /* Do not send unsolicited messages to synchronous |
447 | | * clients. |
448 | | */ |
449 | 0 | if (client->synchronous) |
450 | 0 | continue; |
451 | | |
452 | 0 | zsend_interface_update(ZEBRA_INTERFACE_UP, |
453 | 0 | client, ifp); |
454 | 0 | zsend_interface_link_params(client, ifp); |
455 | 0 | } |
456 | 0 | } |
457 | 0 | } |
458 | | |
459 | | /* Interface down information. */ |
460 | | void zebra_interface_down_update(struct interface *ifp) |
461 | 0 | { |
462 | 0 | struct listnode *node, *nnode; |
463 | 0 | struct zserv *client; |
464 | |
|
465 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
466 | 0 | zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s vrf %s(%u)", |
467 | 0 | ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); |
468 | |
|
469 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
470 | | /* Do not send unsolicited messages to synchronous clients. */ |
471 | 0 | if (client->synchronous) |
472 | 0 | continue; |
473 | | |
474 | 0 | zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | | /* Interface information update. */ |
479 | | void zebra_interface_add_update(struct interface *ifp) |
480 | 0 | { |
481 | 0 | struct listnode *node, *nnode; |
482 | 0 | struct zserv *client; |
483 | |
|
484 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
485 | 0 | zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s vrf %s(%u)", |
486 | 0 | ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); |
487 | |
|
488 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
489 | | /* Do not send unsolicited messages to synchronous clients. */ |
490 | 0 | if (client->synchronous) |
491 | 0 | continue; |
492 | | |
493 | 0 | client->ifadd_cnt++; |
494 | 0 | zsend_interface_add(client, ifp); |
495 | 0 | zsend_interface_link_params(client, ifp); |
496 | 0 | } |
497 | 0 | } |
498 | | |
499 | | void zebra_interface_delete_update(struct interface *ifp) |
500 | 0 | { |
501 | 0 | struct listnode *node, *nnode; |
502 | 0 | struct zserv *client; |
503 | |
|
504 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
505 | 0 | zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s vrf %s(%u)", |
506 | 0 | ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); |
507 | |
|
508 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
509 | | /* Do not send unsolicited messages to synchronous clients. */ |
510 | 0 | if (client->synchronous) |
511 | 0 | continue; |
512 | | |
513 | 0 | client->ifdel_cnt++; |
514 | 0 | zsend_interface_delete(client, ifp); |
515 | 0 | } |
516 | 0 | } |
517 | | |
518 | | /* Interface address addition. */ |
519 | | void zebra_interface_address_add_update(struct interface *ifp, |
520 | | struct connected *ifc) |
521 | 0 | { |
522 | 0 | struct listnode *node, *nnode; |
523 | 0 | struct zserv *client; |
524 | |
|
525 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
526 | 0 | zlog_debug( |
527 | 0 | "MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %pFX on %s vrf %s(%u)", |
528 | 0 | ifc->address, ifp->name, ifp->vrf->name, |
529 | 0 | ifp->vrf->vrf_id); |
530 | |
|
531 | 0 | if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) |
532 | 0 | flog_warn( |
533 | 0 | EC_ZEBRA_ADVERTISING_UNUSABLE_ADDR, |
534 | 0 | "advertising address to clients that is not yet usable."); |
535 | |
|
536 | 0 | zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 1); |
537 | |
|
538 | 0 | router_id_add_address(ifc); |
539 | |
|
540 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
541 | | /* Do not send unsolicited messages to synchronous clients. */ |
542 | 0 | if (client->synchronous) |
543 | 0 | continue; |
544 | | |
545 | 0 | if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { |
546 | 0 | client->connected_rt_add_cnt++; |
547 | 0 | zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_ADD, |
548 | 0 | client, ifp, ifc); |
549 | 0 | } |
550 | 0 | } |
551 | | /* interface associated NHGs may have been deleted, |
552 | | * re-sync zebra -> dplane NHGs |
553 | | */ |
554 | 0 | zebra_interface_nhg_reinstall(ifp); |
555 | 0 | } |
556 | | |
557 | | /* Interface address deletion. */ |
558 | | void zebra_interface_address_delete_update(struct interface *ifp, |
559 | | struct connected *ifc) |
560 | 0 | { |
561 | 0 | struct listnode *node, *nnode; |
562 | 0 | struct zserv *client; |
563 | |
|
564 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
565 | 0 | zlog_debug( |
566 | 0 | "MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %pFX on %s vrf %s(%u)", |
567 | 0 | ifc->address, ifp->name, ifp->vrf->name, |
568 | 0 | ifp->vrf->vrf_id); |
569 | |
|
570 | 0 | zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0); |
571 | |
|
572 | 0 | router_id_del_address(ifc); |
573 | |
|
574 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
575 | | /* Do not send unsolicited messages to synchronous clients. */ |
576 | 0 | if (client->synchronous) |
577 | 0 | continue; |
578 | | |
579 | 0 | if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) { |
580 | 0 | client->connected_rt_del_cnt++; |
581 | 0 | zsend_interface_address(ZEBRA_INTERFACE_ADDRESS_DELETE, |
582 | 0 | client, ifp, ifc); |
583 | 0 | } |
584 | 0 | } |
585 | 0 | } |
586 | | |
587 | | /* Interface VRF change. May need to delete from clients not interested in |
588 | | * the new VRF. Note that this function is invoked *prior* to the VRF change. |
589 | | */ |
590 | | void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id) |
591 | 0 | { |
592 | 0 | struct listnode *node, *nnode; |
593 | 0 | struct zserv *client; |
594 | |
|
595 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
596 | 0 | zlog_debug( |
597 | 0 | "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u", |
598 | 0 | ifp->name, ifp->vrf->vrf_id, new_vrf_id); |
599 | |
|
600 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
601 | | /* Do not send unsolicited messages to synchronous clients. */ |
602 | 0 | if (client->synchronous) |
603 | 0 | continue; |
604 | | |
605 | | /* Need to delete if the client is not interested in the new |
606 | | * VRF. */ |
607 | 0 | zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); |
608 | 0 | client->ifdel_cnt++; |
609 | 0 | zsend_interface_delete(client, ifp); |
610 | 0 | zsend_interface_vrf_update(client, ifp, new_vrf_id); |
611 | 0 | } |
612 | 0 | } |
613 | | |
614 | | /* Interface VRF change. This function is invoked *post* VRF change and sends an |
615 | | * add to clients who are interested in the new VRF but not in the old VRF. |
616 | | */ |
617 | | void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id) |
618 | 0 | { |
619 | 0 | struct listnode *node, *nnode; |
620 | 0 | struct zserv *client; |
621 | |
|
622 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
623 | 0 | zlog_debug( |
624 | 0 | "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u", |
625 | 0 | ifp->name, old_vrf_id, ifp->vrf->vrf_id); |
626 | |
|
627 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
628 | | /* Do not send unsolicited messages to synchronous clients. */ |
629 | 0 | if (client->synchronous) |
630 | 0 | continue; |
631 | | |
632 | | /* Need to add if the client is interested in the new VRF. */ |
633 | 0 | client->ifadd_cnt++; |
634 | 0 | zsend_interface_add(client, ifp); |
635 | 0 | zsend_interface_addresses(client, ifp); |
636 | 0 | } |
637 | 0 | } |
638 | | |
639 | | int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, |
640 | | struct route_entry *re, const char *rmap_name) |
641 | 0 | { |
642 | 0 | struct route_entry *newre; |
643 | 0 | struct route_entry *same; |
644 | 0 | struct prefix p; |
645 | 0 | struct nexthop_group *ng; |
646 | 0 | route_map_result_t ret = RMAP_PERMITMATCH; |
647 | 0 | afi_t afi; |
648 | |
|
649 | 0 | afi = family2afi(rn->p.family); |
650 | 0 | if (rmap_name) |
651 | 0 | ret = zebra_import_table_route_map_check( |
652 | 0 | afi, re->type, re->instance, &rn->p, |
653 | 0 | re->nhe->nhg.nexthop, |
654 | 0 | zvrf->vrf->vrf_id, re->tag, rmap_name); |
655 | |
|
656 | 0 | if (ret != RMAP_PERMITMATCH) { |
657 | 0 | UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED); |
658 | 0 | zebra_del_import_table_entry(zvrf, rn, re); |
659 | 0 | return 0; |
660 | 0 | } |
661 | | |
662 | 0 | prefix_copy(&p, &rn->p); |
663 | |
|
664 | 0 | RNODE_FOREACH_RE (rn, same) { |
665 | 0 | if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) |
666 | 0 | continue; |
667 | | |
668 | 0 | if (same->type == re->type && same->instance == re->instance |
669 | 0 | && same->table == re->table |
670 | 0 | && same->type != ZEBRA_ROUTE_CONNECT) |
671 | 0 | break; |
672 | 0 | } |
673 | |
|
674 | 0 | if (same) { |
675 | 0 | UNSET_FLAG(same->flags, ZEBRA_FLAG_SELECTED); |
676 | 0 | zebra_del_import_table_entry(zvrf, rn, same); |
677 | 0 | } |
678 | |
|
679 | 0 | newre = zebra_rib_route_entry_new( |
680 | 0 | 0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id, |
681 | 0 | zvrf->table_id, re->metric, re->mtu, |
682 | 0 | zebra_import_table_distance[afi][re->table], re->tag); |
683 | |
|
684 | 0 | ng = nexthop_group_new(); |
685 | 0 | copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL); |
686 | |
|
687 | 0 | rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng, false); |
688 | |
|
689 | 0 | return 0; |
690 | 0 | } |
691 | | |
692 | | int zebra_del_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, |
693 | | struct route_entry *re) |
694 | 0 | { |
695 | 0 | struct prefix p; |
696 | 0 | afi_t afi; |
697 | |
|
698 | 0 | afi = family2afi(rn->p.family); |
699 | 0 | prefix_copy(&p, &rn->p); |
700 | |
|
701 | 0 | rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE, |
702 | 0 | re->table, re->flags, &p, NULL, re->nhe->nhg.nexthop, |
703 | 0 | re->nhe_id, zvrf->table_id, re->metric, re->distance, |
704 | 0 | false); |
705 | |
|
706 | 0 | return 0; |
707 | 0 | } |
708 | | |
709 | | /* Assuming no one calls this with the main routing table */ |
710 | | int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id, |
711 | | uint32_t distance, const char *rmap_name, int add) |
712 | 0 | { |
713 | 0 | struct route_table *table; |
714 | 0 | struct route_entry *re; |
715 | 0 | struct route_node *rn; |
716 | 0 | struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf_id); |
717 | |
|
718 | 0 | if (!is_zebra_valid_kernel_table(table_id) |
719 | 0 | || (table_id == RT_TABLE_MAIN)) |
720 | 0 | return -1; |
721 | | |
722 | 0 | if (afi >= AFI_MAX) |
723 | 0 | return -1; |
724 | | |
725 | 0 | table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, vrf_id, |
726 | 0 | table_id); |
727 | 0 | if (table == NULL) { |
728 | 0 | return 0; |
729 | 0 | } else if (IS_ZEBRA_DEBUG_RIB) { |
730 | 0 | zlog_debug("%s routes from table %d", |
731 | 0 | add ? "Importing" : "Unimporting", table_id); |
732 | 0 | } |
733 | | |
734 | 0 | if (add) { |
735 | 0 | if (rmap_name) |
736 | 0 | zebra_add_import_table_route_map(afi, rmap_name, |
737 | 0 | table_id); |
738 | 0 | else { |
739 | 0 | rmap_name = |
740 | 0 | zebra_get_import_table_route_map(afi, table_id); |
741 | 0 | if (rmap_name) { |
742 | 0 | zebra_del_import_table_route_map(afi, table_id); |
743 | 0 | rmap_name = NULL; |
744 | 0 | } |
745 | 0 | } |
746 | |
|
747 | 0 | zebra_import_table_used[afi][table_id] = 1; |
748 | 0 | zebra_import_table_distance[afi][table_id] = distance; |
749 | 0 | } else { |
750 | 0 | zebra_import_table_used[afi][table_id] = 0; |
751 | 0 | zebra_import_table_distance[afi][table_id] = |
752 | 0 | ZEBRA_TABLE_DISTANCE_DEFAULT; |
753 | |
|
754 | 0 | rmap_name = zebra_get_import_table_route_map(afi, table_id); |
755 | 0 | if (rmap_name) { |
756 | 0 | zebra_del_import_table_route_map(afi, table_id); |
757 | 0 | rmap_name = NULL; |
758 | 0 | } |
759 | 0 | } |
760 | |
|
761 | 0 | for (rn = route_top(table); rn; rn = route_next(rn)) { |
762 | | /* For each entry in the non-default routing table, |
763 | | * add the entry in the main table |
764 | | */ |
765 | 0 | if (!rn->info) |
766 | 0 | continue; |
767 | | |
768 | 0 | RNODE_FOREACH_RE (rn, re) { |
769 | 0 | if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) |
770 | 0 | continue; |
771 | 0 | break; |
772 | 0 | } |
773 | |
|
774 | 0 | if (!re) |
775 | 0 | continue; |
776 | | |
777 | 0 | if (((afi == AFI_IP) && (rn->p.family == AF_INET)) |
778 | 0 | || ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) { |
779 | 0 | if (add) |
780 | 0 | zebra_add_import_table_entry(zvrf, rn, re, |
781 | 0 | rmap_name); |
782 | 0 | else |
783 | 0 | zebra_del_import_table_entry(zvrf, rn, re); |
784 | 0 | } |
785 | 0 | } |
786 | 0 | return 0; |
787 | 0 | } |
788 | | |
789 | | int zebra_import_table_config(struct vty *vty, vrf_id_t vrf_id) |
790 | 0 | { |
791 | 0 | int i; |
792 | 0 | afi_t afi; |
793 | 0 | int write = 0; |
794 | 0 | char afi_str[AFI_MAX][10] = {"", "ip", "ipv6", "ethernet"}; |
795 | 0 | const char *rmap_name; |
796 | |
|
797 | 0 | for (afi = AFI_IP; afi < AFI_MAX; afi++) { |
798 | 0 | for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { |
799 | 0 | if (!is_zebra_import_table_enabled(afi, vrf_id, i)) |
800 | 0 | continue; |
801 | | |
802 | 0 | if (zebra_import_table_distance[afi][i] |
803 | 0 | != ZEBRA_TABLE_DISTANCE_DEFAULT) { |
804 | 0 | vty_out(vty, "%s import-table %d distance %d", |
805 | 0 | afi_str[afi], i, |
806 | 0 | zebra_import_table_distance[afi][i]); |
807 | 0 | } else { |
808 | 0 | vty_out(vty, "%s import-table %d", afi_str[afi], |
809 | 0 | i); |
810 | 0 | } |
811 | |
|
812 | 0 | rmap_name = zebra_get_import_table_route_map(afi, i); |
813 | 0 | if (rmap_name) |
814 | 0 | vty_out(vty, " route-map %s", rmap_name); |
815 | |
|
816 | 0 | vty_out(vty, "\n"); |
817 | 0 | write = 1; |
818 | 0 | } |
819 | 0 | } |
820 | |
|
821 | 0 | return write; |
822 | 0 | } |
823 | | |
824 | | static void zebra_import_table_rm_update_vrf_afi(struct zebra_vrf *zvrf, |
825 | | afi_t afi, int table_id, |
826 | | const char *rmap) |
827 | 0 | { |
828 | 0 | struct route_table *table; |
829 | 0 | struct route_entry *re; |
830 | 0 | struct route_node *rn; |
831 | 0 | const char *rmap_name; |
832 | |
|
833 | 0 | rmap_name = zebra_get_import_table_route_map(afi, table_id); |
834 | 0 | if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) |
835 | 0 | return; |
836 | | |
837 | 0 | table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, |
838 | 0 | zvrf->vrf->vrf_id, table_id); |
839 | 0 | if (!table) { |
840 | 0 | if (IS_ZEBRA_DEBUG_RIB_DETAILED) |
841 | 0 | zlog_debug("%s: Table id=%d not found", __func__, |
842 | 0 | table_id); |
843 | 0 | return; |
844 | 0 | } |
845 | | |
846 | 0 | for (rn = route_top(table); rn; rn = route_next(rn)) { |
847 | | /* |
848 | | * For each entry in the non-default routing table, |
849 | | * add the entry in the main table |
850 | | */ |
851 | 0 | if (!rn->info) |
852 | 0 | continue; |
853 | | |
854 | 0 | RNODE_FOREACH_RE (rn, re) { |
855 | 0 | if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) |
856 | 0 | continue; |
857 | 0 | break; |
858 | 0 | } |
859 | |
|
860 | 0 | if (!re) |
861 | 0 | continue; |
862 | | |
863 | 0 | if (((afi == AFI_IP) && (rn->p.family == AF_INET)) |
864 | 0 | || ((afi == AFI_IP6) && (rn->p.family == AF_INET6))) |
865 | 0 | zebra_add_import_table_entry(zvrf, rn, re, rmap_name); |
866 | 0 | } |
867 | |
|
868 | 0 | return; |
869 | 0 | } |
870 | | |
871 | | static void zebra_import_table_rm_update_vrf(struct zebra_vrf *zvrf, |
872 | | const char *rmap) |
873 | 0 | { |
874 | 0 | afi_t afi; |
875 | 0 | int i; |
876 | |
|
877 | 0 | for (afi = AFI_IP; afi < AFI_MAX; afi++) { |
878 | 0 | for (i = 1; i < ZEBRA_KERNEL_TABLE_MAX; i++) { |
879 | 0 | if (!is_zebra_import_table_enabled( |
880 | 0 | afi, zvrf->vrf->vrf_id, i)) |
881 | 0 | continue; |
882 | | |
883 | 0 | zebra_import_table_rm_update_vrf_afi(zvrf, afi, i, |
884 | 0 | rmap); |
885 | 0 | } |
886 | 0 | } |
887 | 0 | } |
888 | | |
889 | | void zebra_import_table_rm_update(const char *rmap) |
890 | 0 | { |
891 | 0 | struct vrf *vrf; |
892 | 0 | struct zebra_vrf *zvrf; |
893 | |
|
894 | 0 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { |
895 | 0 | zvrf = vrf->info; |
896 | |
|
897 | 0 | if (!zvrf) |
898 | 0 | continue; |
899 | | |
900 | 0 | zebra_import_table_rm_update_vrf(zvrf, rmap); |
901 | 0 | } |
902 | 0 | } |
903 | | |
904 | | /* Interface parameters update */ |
905 | | void zebra_interface_parameters_update(struct interface *ifp) |
906 | 0 | { |
907 | 0 | struct listnode *node, *nnode; |
908 | 0 | struct zserv *client; |
909 | |
|
910 | 0 | if (IS_ZEBRA_DEBUG_EVENT) |
911 | 0 | zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s vrf %s(%u)", |
912 | 0 | ifp->name, ifp->vrf->name, ifp->vrf->vrf_id); |
913 | |
|
914 | 0 | for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) { |
915 | | /* Do not send unsolicited messages to synchronous clients. */ |
916 | 0 | if (client->synchronous) |
917 | 0 | continue; |
918 | | |
919 | 0 | zsend_interface_link_params(client, ifp); |
920 | 0 | } |
921 | 0 | } |