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