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