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