]>
Commit | Line | Data |
---|---|---|
7c551956 DS |
1 | /* |
2 | * Copyright (C) 2016 CumulusNetworks | |
3 | * Donald Sharp | |
4 | * | |
5 | * This file is part of Quagga | |
6 | * | |
7 | * Quagga is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * Quagga is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
896014f4 DL |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; see the file COPYING; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
7c551956 DS |
20 | */ |
21 | #include <zebra.h> | |
22 | ||
23 | #include "log.h" | |
24 | #include "linklist.h" | |
f30c50b9 | 25 | #include "command.h" |
4a1ab8e4 | 26 | #include "memory.h" |
05737783 | 27 | #include "srcdest_table.h" |
7c551956 | 28 | |
82f97584 | 29 | #include "vty.h" |
7c551956 DS |
30 | #include "zebra/debug.h" |
31 | #include "zebra/zserv.h" | |
32 | #include "zebra/rib.h" | |
33 | #include "zebra/zebra_vrf.h" | |
5a8dfcd8 | 34 | #include "zebra/zebra_rnh.h" |
7c551956 | 35 | #include "zebra/router-id.h" |
4a1ab8e4 | 36 | #include "zebra/zebra_memory.h" |
28f6dde8 | 37 | #include "zebra/zebra_static.h" |
5a8dfcd8 | 38 | #include "zebra/interface.h" |
7758e3f3 | 39 | #include "zebra/zebra_mpls.h" |
13d60d35 | 40 | #include "zebra/zebra_vxlan.h" |
7c551956 DS |
41 | |
42 | extern struct zebra_t zebrad; | |
43 | ||
9d97533e | 44 | static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, |
45 | safi_t safi); | |
46 | static void zebra_rnhtable_node_cleanup(struct route_table *table, | |
47 | struct route_node *node); | |
48 | ||
7c551956 | 49 | /* VRF information update. */ |
d62a17ae | 50 | static void zebra_vrf_add_update(struct zebra_vrf *zvrf) |
7c551956 | 51 | { |
d62a17ae | 52 | struct listnode *node, *nnode; |
53 | struct zserv *client; | |
7c551956 | 54 | |
d62a17ae | 55 | if (IS_ZEBRA_DEBUG_EVENT) |
56 | zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf)); | |
7c551956 | 57 | |
d62a17ae | 58 | for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) |
59 | zsend_vrf_add(client, zvrf); | |
7c551956 DS |
60 | } |
61 | ||
d62a17ae | 62 | static void zebra_vrf_delete_update(struct zebra_vrf *zvrf) |
7c551956 | 63 | { |
d62a17ae | 64 | struct listnode *node, *nnode; |
65 | struct zserv *client; | |
7c551956 | 66 | |
d62a17ae | 67 | if (IS_ZEBRA_DEBUG_EVENT) |
68 | zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf)); | |
7c551956 | 69 | |
d62a17ae | 70 | for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) |
71 | zsend_vrf_delete(client, zvrf); | |
7c551956 DS |
72 | } |
73 | ||
d62a17ae | 74 | void zebra_vrf_update_all(struct zserv *client) |
7c551956 | 75 | { |
d62a17ae | 76 | struct vrf *vrf; |
7c551956 | 77 | |
a2addae8 | 78 | RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { |
d62a17ae | 79 | if (vrf->vrf_id) |
80 | zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id)); | |
81 | } | |
7c551956 DS |
82 | } |
83 | ||
84 | /* Callback upon creating a new VRF. */ | |
d62a17ae | 85 | static int zebra_vrf_new(struct vrf *vrf) |
7c551956 | 86 | { |
d62a17ae | 87 | struct zebra_vrf *zvrf; |
7c551956 | 88 | |
d62a17ae | 89 | if (IS_ZEBRA_DEBUG_EVENT) |
84915b0a | 90 | zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id); |
7c551956 | 91 | |
d62a17ae | 92 | zvrf = zebra_vrf_alloc(); |
93 | zvrf->zns = zebra_ns_lookup( | |
94 | NS_DEFAULT); /* Point to the global (single) NS */ | |
95 | router_id_init(zvrf); | |
96 | vrf->info = zvrf; | |
97 | zvrf->vrf = vrf; | |
34f8e6af | 98 | |
d62a17ae | 99 | return 0; |
7c551956 DS |
100 | } |
101 | ||
102 | /* Callback upon enabling a VRF. */ | |
d62a17ae | 103 | static int zebra_vrf_enable(struct vrf *vrf) |
7c551956 | 104 | { |
d62a17ae | 105 | struct zebra_vrf *zvrf = vrf->info; |
106 | struct route_table *stable; | |
107 | struct route_node *rn; | |
108 | struct static_route *si; | |
9d97533e | 109 | struct route_table *table; |
d62a17ae | 110 | struct interface *ifp; |
111 | afi_t afi; | |
112 | safi_t safi; | |
113 | ||
114 | assert(zvrf); | |
84915b0a | 115 | if (IS_ZEBRA_DEBUG_EVENT) |
116 | zlog_debug("VRF %s id %u is now active", | |
117 | zvrf_name(zvrf), zvrf_id(zvrf)); | |
d62a17ae | 118 | |
84915b0a | 119 | /* Inform clients that the VRF is now active. This is an |
120 | * add for the clients. | |
121 | */ | |
d62a17ae | 122 | zebra_vrf_add_update(zvrf); |
123 | ||
9d97533e | 124 | /* Allocate tables */ |
125 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { | |
126 | for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) | |
127 | zebra_vrf_table_create(zvrf, afi, safi); | |
128 | ||
129 | table = route_table_init(); | |
130 | table->cleanup = zebra_rnhtable_node_cleanup; | |
131 | zvrf->rnh_table[afi] = table; | |
132 | ||
133 | table = route_table_init(); | |
134 | table->cleanup = zebra_rnhtable_node_cleanup; | |
135 | zvrf->import_check_table[afi] = table; | |
136 | } | |
137 | ||
84915b0a | 138 | /* Install any static routes configured for this VRF. */ |
d62a17ae | 139 | for (afi = AFI_IP; afi < AFI_MAX; afi++) |
140 | for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { | |
141 | stable = zvrf->stable[afi][safi]; | |
142 | if (!stable) | |
143 | continue; | |
144 | ||
145 | for (rn = route_top(stable); rn; rn = route_next(rn)) | |
146 | for (si = rn->info; si; si = si->next) { | |
147 | si->vrf_id = vrf->vrf_id; | |
148 | if (si->ifindex) { | |
149 | ifp = if_lookup_by_name( | |
150 | si->ifname, si->vrf_id); | |
151 | if (ifp) | |
152 | si->ifindex = | |
153 | ifp->ifindex; | |
154 | else | |
155 | continue; | |
156 | } | |
157 | static_install_route(afi, safi, &rn->p, | |
158 | NULL, si); | |
159 | } | |
fb148af4 | 160 | } |
2414ffe5 | 161 | |
84915b0a | 162 | /* Kick off any VxLAN-EVPN processing. */ |
163 | zebra_vxlan_vrf_enable(zvrf); | |
164 | ||
d62a17ae | 165 | return 0; |
7c551956 DS |
166 | } |
167 | ||
168 | /* Callback upon disabling a VRF. */ | |
d62a17ae | 169 | static int zebra_vrf_disable(struct vrf *vrf) |
7c551956 | 170 | { |
d62a17ae | 171 | struct zebra_vrf *zvrf = vrf->info; |
172 | struct route_table *stable; | |
173 | struct route_node *rn; | |
174 | struct static_route *si; | |
9d97533e | 175 | struct route_table *table; |
176 | struct interface *ifp; | |
d62a17ae | 177 | afi_t afi; |
178 | safi_t safi; | |
9d97533e | 179 | unsigned i; |
d62a17ae | 180 | |
84915b0a | 181 | assert(zvrf); |
182 | if (IS_ZEBRA_DEBUG_EVENT) | |
183 | zlog_debug("VRF %s id %u is now inactive", | |
184 | zvrf_name(zvrf), zvrf_id(zvrf)); | |
d62a17ae | 185 | |
84915b0a | 186 | /* Uninstall any static routes configured for this VRF. */ |
d62a17ae | 187 | for (afi = AFI_IP; afi < AFI_MAX; afi++) |
188 | for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { | |
189 | stable = zvrf->stable[afi][safi]; | |
190 | if (!stable) | |
191 | continue; | |
192 | ||
193 | for (rn = route_top(stable); rn; rn = route_next(rn)) | |
194 | for (si = rn->info; si; si = si->next) | |
195 | static_uninstall_route( | |
196 | afi, safi, &rn->p, NULL, si); | |
197 | } | |
198 | ||
84915b0a | 199 | /* Stop any VxLAN-EVPN processing. */ |
200 | zebra_vxlan_vrf_disable(zvrf); | |
d62a17ae | 201 | |
84915b0a | 202 | /* Inform clients that the VRF is now inactive. This is a |
203 | * delete for the clients. | |
204 | */ | |
d62a17ae | 205 | zebra_vrf_delete_update(zvrf); |
206 | ||
9d97533e | 207 | /* If asked to retain routes, there's nothing more to do. */ |
208 | if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) | |
209 | return 0; | |
210 | ||
211 | /* Remove all routes. */ | |
212 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { | |
213 | for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) | |
214 | rib_close_table(zvrf->table[afi][safi]); | |
9d97533e | 215 | } |
216 | ||
217 | /* Cleanup Vxlan, MPLS and PW tables. */ | |
218 | zebra_vxlan_cleanup_tables(zvrf); | |
219 | zebra_mpls_cleanup_tables(zvrf); | |
220 | zebra_pw_exit(zvrf); | |
221 | ||
222 | /* Remove link-local IPv4 addresses created for BGP unnumbered peering. */ | |
223 | FOR_ALL_INTERFACES (vrf, ifp) | |
224 | if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp); | |
225 | ||
226 | /* clean-up work queues */ | |
227 | for (i = 0; i < MQ_SIZE; i++) { | |
228 | struct listnode *lnode, *nnode; | |
229 | struct route_node *rnode; | |
230 | rib_dest_t *dest; | |
231 | ||
27b136bd DS |
232 | for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], |
233 | lnode, nnode, rnode)) { | |
9d97533e | 234 | dest = rib_dest_from_rnode(rnode); |
235 | if (dest && rib_dest_vrf(dest) == zvrf) { | |
236 | route_unlock_node(rnode); | |
237 | list_delete_node(zebrad.mq->subq[i], lnode); | |
238 | zebrad.mq->size--; | |
239 | } | |
d62a17ae | 240 | } |
9d97533e | 241 | } |
7c551956 | 242 | |
9d97533e | 243 | /* Cleanup (free) routing tables and NHT tables. */ |
244 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { | |
245 | void *table_info; | |
5a8dfcd8 | 246 | |
9d97533e | 247 | for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { |
248 | table = zvrf->table[afi][safi]; | |
249 | table_info = table->info; | |
250 | route_table_finish(table); | |
251 | XFREE(MTYPE_RIB_TABLE_INFO, table_info); | |
252 | zvrf->table[afi][safi] = NULL; | |
253 | } | |
254 | ||
9d97533e | 255 | route_table_finish(zvrf->rnh_table[afi]); |
256 | zvrf->rnh_table[afi] = NULL; | |
257 | route_table_finish(zvrf->import_check_table[afi]); | |
258 | zvrf->import_check_table[afi] = NULL; | |
5a8dfcd8 RW |
259 | } |
260 | ||
d62a17ae | 261 | return 0; |
7c551956 DS |
262 | } |
263 | ||
d62a17ae | 264 | static int zebra_vrf_delete(struct vrf *vrf) |
7c551956 | 265 | { |
d62a17ae | 266 | struct zebra_vrf *zvrf = vrf->info; |
267 | struct route_table *table; | |
d62a17ae | 268 | afi_t afi; |
269 | safi_t safi; | |
270 | unsigned i; | |
271 | ||
272 | assert(zvrf); | |
84915b0a | 273 | if (IS_ZEBRA_DEBUG_EVENT) |
274 | zlog_debug("VRF %s id %u deleted", | |
275 | zvrf_name(zvrf), zvrf_id(zvrf)); | |
5a8dfcd8 | 276 | |
d62a17ae | 277 | /* clean-up work queues */ |
278 | for (i = 0; i < MQ_SIZE; i++) { | |
279 | struct listnode *lnode, *nnode; | |
280 | struct route_node *rnode; | |
281 | rib_dest_t *dest; | |
282 | ||
9d97533e | 283 | for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) { |
d62a17ae | 284 | dest = rib_dest_from_rnode(rnode); |
285 | if (dest && rib_dest_vrf(dest) == zvrf) { | |
286 | route_unlock_node(rnode); | |
287 | list_delete_node(zebrad.mq->subq[i], lnode); | |
288 | zebrad.mq->size--; | |
289 | } | |
290 | } | |
5a8dfcd8 | 291 | } |
5a8dfcd8 | 292 | |
84915b0a | 293 | /* Free Vxlan and MPLS. */ |
294 | zebra_vxlan_close_tables(zvrf); | |
295 | zebra_mpls_close_tables(zvrf); | |
296 | ||
d62a17ae | 297 | /* release allocated memory */ |
298 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { | |
299 | void *table_info; | |
0f124559 | 300 | |
d62a17ae | 301 | for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { |
302 | table = zvrf->table[afi][safi]; | |
9d97533e | 303 | if (table) { |
304 | table_info = table->info; | |
305 | route_table_finish(table); | |
306 | XFREE(MTYPE_RIB_TABLE_INFO, table_info); | |
307 | } | |
d62a17ae | 308 | |
309 | table = zvrf->stable[afi][safi]; | |
310 | route_table_finish(table); | |
311 | } | |
5a8dfcd8 | 312 | |
d62a17ae | 313 | route_table_finish(zvrf->rnh_table[afi]); |
314 | route_table_finish(zvrf->import_check_table[afi]); | |
5a8dfcd8 | 315 | } |
b7cfce93 | 316 | |
84915b0a | 317 | /* Cleanup EVPN states for vrf */ |
b7cfce93 MK |
318 | zebra_vxlan_vrf_delete(zvrf); |
319 | ||
d62a17ae | 320 | list_delete_all_node(zvrf->rid_all_sorted_list); |
321 | list_delete_all_node(zvrf->rid_lo_sorted_list); | |
322 | XFREE(MTYPE_ZEBRA_VRF, zvrf); | |
323 | vrf->info = NULL; | |
5a8dfcd8 | 324 | |
d62a17ae | 325 | return 0; |
7c551956 DS |
326 | } |
327 | ||
22bd3e94 | 328 | /* Return if this VRF has any FRR configuration or not. |
329 | * IMPORTANT: This function needs to be updated when additional configuration | |
330 | * is added for a VRF. | |
331 | */ | |
332 | int zebra_vrf_has_config(struct zebra_vrf *zvrf) | |
333 | { | |
334 | afi_t afi; | |
335 | safi_t safi; | |
336 | struct route_table *stable; | |
337 | ||
338 | /* NOTE: This is a don't care for the default VRF, but we go through | |
339 | * the motions to keep things consistent. | |
340 | */ | |
341 | /* Any static routes? */ | |
342 | for (afi = AFI_IP; afi < AFI_MAX; afi++) { | |
343 | for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { | |
344 | stable = zvrf->stable[afi][safi]; | |
345 | if (!stable) | |
346 | continue; | |
347 | if (route_table_count(stable)) | |
348 | return 1; | |
349 | } | |
350 | } | |
351 | ||
352 | /* EVPN L3-VNI? */ | |
353 | if (zvrf->l3vni) | |
354 | return 1; | |
355 | ||
356 | return 0; | |
357 | } | |
358 | ||
7c551956 DS |
359 | /* Lookup the routing table in a VRF based on both VRF-Id and table-id. |
360 | * NOTE: Table-id is relevant only in the Default VRF. | |
361 | */ | |
d62a17ae | 362 | struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, |
363 | vrf_id_t vrf_id, | |
364 | u_int32_t table_id) | |
7c551956 | 365 | { |
d62a17ae | 366 | struct route_table *table = NULL; |
367 | ||
368 | if (afi >= AFI_MAX || safi >= SAFI_MAX) | |
369 | return NULL; | |
370 | ||
371 | if (vrf_id == VRF_DEFAULT) { | |
372 | if (table_id == RT_TABLE_MAIN | |
373 | || table_id == zebrad.rtm_table_default) | |
374 | table = zebra_vrf_table(afi, safi, vrf_id); | |
375 | else | |
376 | table = zebra_vrf_other_route_table(afi, table_id, | |
377 | vrf_id); | |
378 | } else | |
379 | table = zebra_vrf_table(afi, safi, vrf_id); | |
380 | ||
381 | return table; | |
7c551956 DS |
382 | } |
383 | ||
5335613b DS |
384 | void zebra_rtable_node_cleanup(struct route_table *table, |
385 | struct route_node *node) | |
5a8dfcd8 | 386 | { |
d62a17ae | 387 | struct route_entry *re, *next; |
5a8dfcd8 | 388 | |
a2addae8 | 389 | RNODE_FOREACH_RE_SAFE (node, re, next) { |
407c87a6 DS |
390 | rib_unlink(node, re); |
391 | } | |
5a8dfcd8 | 392 | |
d62a17ae | 393 | if (node->info) |
394 | XFREE(MTYPE_RIB_DEST, node->info); | |
5a8dfcd8 RW |
395 | } |
396 | ||
d62a17ae | 397 | static void zebra_stable_node_cleanup(struct route_table *table, |
398 | struct route_node *node) | |
5a8dfcd8 | 399 | { |
d62a17ae | 400 | struct static_route *si, *next; |
401 | ||
402 | if (node->info) | |
403 | for (si = node->info; si; si = next) { | |
404 | next = si->next; | |
405 | XFREE(MTYPE_STATIC_ROUTE, si); | |
406 | } | |
5a8dfcd8 RW |
407 | } |
408 | ||
d62a17ae | 409 | static void zebra_rnhtable_node_cleanup(struct route_table *table, |
410 | struct route_node *node) | |
5a8dfcd8 | 411 | { |
d62a17ae | 412 | if (node->info) |
413 | zebra_free_rnh(node->info); | |
5a8dfcd8 RW |
414 | } |
415 | ||
7c551956 DS |
416 | /* |
417 | * Create a routing table for the specific AFI/SAFI in the given VRF. | |
418 | */ | |
d62a17ae | 419 | static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, |
420 | safi_t safi) | |
7c551956 | 421 | { |
d62a17ae | 422 | rib_table_info_t *info; |
423 | struct route_table *table; | |
424 | ||
425 | assert(!zvrf->table[afi][safi]); | |
426 | ||
427 | if (afi == AFI_IP6) | |
428 | table = srcdest_table_init(); | |
429 | else | |
430 | table = route_table_init(); | |
431 | table->cleanup = zebra_rtable_node_cleanup; | |
432 | zvrf->table[afi][safi] = table; | |
433 | ||
434 | info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); | |
435 | info->zvrf = zvrf; | |
436 | info->afi = afi; | |
437 | info->safi = safi; | |
438 | table->info = info; | |
7c551956 DS |
439 | } |
440 | ||
441 | /* Allocate new zebra VRF. */ | |
d62a17ae | 442 | struct zebra_vrf *zebra_vrf_alloc(void) |
7c551956 | 443 | { |
d62a17ae | 444 | struct zebra_vrf *zvrf; |
445 | afi_t afi; | |
446 | safi_t safi; | |
447 | struct route_table *table; | |
448 | ||
449 | zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf)); | |
450 | ||
9d97533e | 451 | /* Allocate table for static route configuration. */ |
d62a17ae | 452 | for (afi = AFI_IP; afi <= AFI_IP6; afi++) { |
453 | for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { | |
d62a17ae | 454 | if (afi == AFI_IP6) |
455 | table = srcdest_table_init(); | |
456 | else | |
457 | table = route_table_init(); | |
458 | table->cleanup = zebra_stable_node_cleanup; | |
459 | zvrf->stable[afi][safi] = table; | |
460 | } | |
d62a17ae | 461 | } |
462 | ||
463 | zebra_vxlan_init_tables(zvrf); | |
464 | zebra_mpls_init_tables(zvrf); | |
6833ae01 | 465 | zebra_pw_init(zvrf); |
d62a17ae | 466 | |
467 | return zvrf; | |
7c551956 DS |
468 | } |
469 | ||
470 | /* Lookup VRF by identifier. */ | |
d62a17ae | 471 | struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id) |
7c551956 | 472 | { |
d62a17ae | 473 | return vrf_info_lookup(vrf_id); |
7c551956 DS |
474 | } |
475 | ||
51bdc5f8 | 476 | /* Lookup VRF by name. */ |
d62a17ae | 477 | struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name) |
871d39b3 | 478 | { |
d62a17ae | 479 | struct vrf *vrf; |
871d39b3 | 480 | |
d62a17ae | 481 | if (!name) |
482 | name = VRF_DEFAULT_NAME; | |
a3d21ef3 | 483 | |
d62a17ae | 484 | vrf = vrf_lookup_by_name(name); |
485 | if (vrf) | |
486 | return ((struct zebra_vrf *)vrf->info); | |
51bdc5f8 | 487 | |
d62a17ae | 488 | return NULL; |
871d39b3 DS |
489 | } |
490 | ||
7c551956 | 491 | /* Lookup the routing table in an enabled VRF. */ |
d62a17ae | 492 | struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id) |
7c551956 | 493 | { |
d62a17ae | 494 | struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); |
7c551956 | 495 | |
d62a17ae | 496 | if (!zvrf) |
497 | return NULL; | |
7c551956 | 498 | |
d62a17ae | 499 | if (afi >= AFI_MAX || safi >= SAFI_MAX) |
500 | return NULL; | |
7c551956 | 501 | |
d62a17ae | 502 | return zvrf->table[afi][safi]; |
7c551956 DS |
503 | } |
504 | ||
505 | /* Lookup the static routing table in a VRF. */ | |
d62a17ae | 506 | struct route_table *zebra_vrf_static_table(afi_t afi, safi_t safi, |
507 | struct zebra_vrf *zvrf) | |
7c551956 | 508 | { |
d62a17ae | 509 | if (!zvrf) |
510 | return NULL; | |
7c551956 | 511 | |
d62a17ae | 512 | if (afi >= AFI_MAX || safi >= SAFI_MAX) |
513 | return NULL; | |
7c551956 | 514 | |
d62a17ae | 515 | return zvrf->stable[afi][safi]; |
7c551956 DS |
516 | } |
517 | ||
d62a17ae | 518 | struct route_table *zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, |
519 | vrf_id_t vrf_id) | |
7c551956 | 520 | { |
d62a17ae | 521 | struct zebra_vrf *zvrf; |
5335613b | 522 | struct zebra_ns *zns; |
d62a17ae | 523 | |
524 | zvrf = vrf_info_lookup(vrf_id); | |
525 | if (!zvrf) | |
526 | return NULL; | |
527 | ||
5335613b DS |
528 | zns = zvrf->zns; |
529 | ||
d62a17ae | 530 | if (afi >= AFI_MAX) |
531 | return NULL; | |
532 | ||
d62a17ae | 533 | if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) |
534 | && (table_id != zebrad.rtm_table_default)) { | |
5335613b | 535 | return zebra_ns_get_table(zns, zvrf, table_id, afi); |
d62a17ae | 536 | } |
537 | ||
538 | return zvrf->table[afi][SAFI_UNICAST]; | |
7c551956 DS |
539 | } |
540 | ||
d62a17ae | 541 | static int vrf_config_write(struct vty *vty) |
f30c50b9 | 542 | { |
d62a17ae | 543 | struct vrf *vrf; |
544 | struct zebra_vrf *zvrf; | |
545 | ||
a2addae8 | 546 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { |
d62a17ae | 547 | zvrf = vrf->info; |
1e9f448f DS |
548 | |
549 | if (!zvrf) | |
550 | continue; | |
551 | ||
a5654735 MK |
552 | if (zvrf_id(zvrf) == VRF_DEFAULT) { |
553 | if (zvrf->l3vni) | |
554 | vty_out(vty, "vni %u\n", zvrf->l3vni); | |
555 | vty_out(vty, "!\n"); | |
556 | } | |
557 | ||
84915b0a | 558 | if (vrf_is_user_cfged(vrf)) { |
37728041 | 559 | vty_out(vty, "vrf %s\n", zvrf_name(zvrf)); |
22bd3e94 | 560 | if (zvrf->l3vni) |
c48d9f5f MK |
561 | vty_out(vty, " vni %u%s\n", |
562 | zvrf->l3vni, | |
563 | is_l3vni_for_prefix_routes_only(zvrf->l3vni) ? | |
564 | " prefix-routes-only" :""); | |
22bd3e94 | 565 | vty_out(vty, "!\n"); |
566 | } | |
37728041 DS |
567 | |
568 | static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route"); | |
569 | static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute"); | |
570 | static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route"); | |
ab32921c | 571 | |
37728041 DS |
572 | if (vrf->vrf_id != VRF_DEFAULT) |
573 | vty_out(vty, "!\n"); | |
d62a17ae | 574 | } |
575 | return 0; | |
f30c50b9 RW |
576 | } |
577 | ||
7c551956 | 578 | /* Zebra VRF initialization. */ |
d62a17ae | 579 | void zebra_vrf_init(void) |
7c551956 | 580 | { |
d62a17ae | 581 | vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable, |
582 | zebra_vrf_delete); | |
7c551956 | 583 | |
d62a17ae | 584 | vrf_cmd_init(vrf_config_write); |
7c551956 | 585 | } |