]> git.proxmox.com Git - mirror_frr.git/blame - lib/vrf.c
quagga-reload broken when comparing Quagga.conf in 2.5 format vs 3.0
[mirror_frr.git] / lib / vrf.c
CommitLineData
b72ede27
FL
1/*
2 * VRF functions.
3 * Copyright (C) 2014 6WIND S.A.
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra 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 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
6a69b354 25#include "if.h"
b72ede27
FL
26#include "vrf.h"
27#include "prefix.h"
28#include "table.h"
29#include "log.h"
30#include "memory.h"
19dc275e
DS
31#include "command.h"
32
33/*
34 * Turn on/off debug code
35 * for vrf.
36 */
37int debug_vrf = 0;
b72ede27 38
b72ede27
FL
39/* Holding VRF hooks */
40struct vrf_master
41{
216b18ef
DS
42 int (*vrf_new_hook) (vrf_id_t, const char *, void **);
43 int (*vrf_delete_hook) (vrf_id_t, const char *, void **);
44 int (*vrf_enable_hook) (vrf_id_t, const char *, void **);
45 int (*vrf_disable_hook) (vrf_id_t, const char *, void **);
b72ede27
FL
46} vrf_master = {0,};
47
48/* VRF table */
49struct route_table *vrf_table = NULL;
50
216b18ef
DS
51/* VRF is part of a list too to store it before its actually active */
52struct list *vrf_list;
53
e5bf3e1e 54static int vrf_is_enabled (struct vrf *vrf);
e5bf3e1e
FL
55static void vrf_disable (struct vrf *vrf);
56
216b18ef
DS
57/* VRF list existance check by name. */
58struct vrf *
59vrf_list_lookup_by_name (const char *name)
60{
61 struct listnode *node;
62 struct vrf *vrfp;
63
64 if (name)
65 for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp))
66 {
67 if (strcmp(name, vrfp->name) == 0)
68 return vrfp;
69 }
70 return NULL;
71}
72
b72ede27
FL
73/* Build the table key */
74static void
75vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
76{
77 p->family = AF_INET;
78 p->prefixlen = IPV4_MAX_BITLEN;
79 p->u.prefix4.s_addr = vrf_id;
80}
81
216b18ef
DS
82/* Get a VRF. If not found, create one.
83 * Arg: name
84 * Description: Please note that this routine can be called with just the name
85 and 0 vrf-id */
86struct vrf *
87vrf_get (vrf_id_t vrf_id, const char *name)
b72ede27
FL
88{
89 struct prefix p;
c88a8b75 90 struct route_node *rn = NULL;
216b18ef 91 struct vrf *vrf = NULL;
0f48374b 92 size_t namelen = 0;
b72ede27 93
c88a8b75
DS
94 /* Only create a route node if the vrf was learned from the kernel */
95 if (vrf_id != VRF_UNKNOWN)
b72ede27 96 {
c88a8b75
DS
97 vrf_build_key (vrf_id, &p);
98 rn = route_node_get (vrf_table, &p);
216b18ef 99
c88a8b75 100 if (rn->info)
216b18ef 101 {
c88a8b75
DS
102 vrf = (struct vrf *)rn->info;
103 route_unlock_node (rn); /* get */
104
105 if (name)
106 {
107 strncpy (vrf->name, name, strlen(name));
108 vrf->name[strlen(name)] = '\0';
109 if (vrf_list_lookup_by_name (vrf->name) == NULL)
110 listnode_add_sort (vrf_list, vrf);
111 }
112 if (debug_vrf)
113 zlog_debug ("VRF(%u) %s Found %p", vrf_id, (name) ? name : "(NULL)",
114 vrf);
216b18ef 115 }
c88a8b75
DS
116 }
117
118 if (name && !vrf)
119 vrf = vrf_list_lookup_by_name(name);
120
121 if (vrf)
122 {
19dc275e 123 if (debug_vrf)
c88a8b75
DS
124 zlog_debug ("VRF(%u) %s lookup by name is successful",
125 vrf_id, (name) ? name : "(NULL)");
b72ede27 126 }
216b18ef
DS
127 else
128 {
129 if (name)
c88a8b75
DS
130 {
131 namelen = strlen (name);
132 if (namelen > VRF_NAMSIZ)
8087b296 133 {
c88a8b75
DS
134 zlog_err("Attempt to get/create VRF %u name %s - name too long",
135 vrf_id, name);
136 return NULL;
8087b296 137 }
c88a8b75 138 }
8087b296 139
c88a8b75
DS
140 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
141 if (debug_vrf)
142 zlog_debug ("VRF(%u) %s is created.",
143 vrf_id, (name) ? name : "(NULL)");
144 if (name)
145 {
146 strncpy (vrf->name, name, namelen);
147 vrf->name[namelen] = '\0';
148 listnode_add_sort (vrf_list, vrf);
149 }
150
151 if ((vrf_id != VRF_UNKNOWN) && (rn != NULL))
152 {
153 rn->info = vrf;
154 vrf->node = rn;
155 }
216b18ef 156 vrf->vrf_id = vrf_id;
8736158a 157
216b18ef 158 /* Initialize interfaces. */
b2d7c082 159 if_init (&vrf->iflist);
216b18ef 160 }
b72ede27 161
c88a8b75
DS
162 if (vrf_master.vrf_new_hook && name)
163 {
164 (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
165
166 if (vrf->info)
167 zlog_info ("zvrf is created.");
168 }
216b18ef 169
b72ede27
FL
170 return vrf;
171}
172
173/* Delete a VRF. This is called in vrf_terminate(). */
216b18ef 174void
b72ede27
FL
175vrf_delete (struct vrf *vrf)
176{
19dc275e
DS
177 if (debug_vrf)
178 zlog_debug ("VRF %u is to be deleted.", vrf->vrf_id);
b72ede27 179
e5bf3e1e
FL
180 if (vrf_is_enabled (vrf))
181 vrf_disable (vrf);
182
b72ede27 183 if (vrf_master.vrf_delete_hook)
216b18ef
DS
184 (*vrf_master.vrf_delete_hook) (vrf->vrf_id, vrf->name, &vrf->info);
185
79694123 186 if (CHECK_FLAG (vrf->status, VRF_ACTIVE))
b2d7c082 187 if_terminate (&vrf->iflist);
b72ede27 188
216b18ef
DS
189 if (vrf->node)
190 {
191 vrf->node->info = NULL;
192 route_unlock_node(vrf->node);
193 }
8736158a 194
216b18ef 195 listnode_delete (vrf_list, vrf);
b72ede27
FL
196
197 XFREE (MTYPE_VRF, vrf);
198}
199
200/* Look up a VRF by identifier. */
216b18ef 201struct vrf *
b72ede27
FL
202vrf_lookup (vrf_id_t vrf_id)
203{
204 struct prefix p;
205 struct route_node *rn;
206 struct vrf *vrf = NULL;
207
208 vrf_build_key (vrf_id, &p);
209 rn = route_node_lookup (vrf_table, &p);
210 if (rn)
211 {
212 vrf = (struct vrf *)rn->info;
213 route_unlock_node (rn); /* lookup */
214 }
215 return vrf;
216}
217
e5bf3e1e
FL
218/*
219 * Check whether the VRF is enabled - that is, whether the VRF
220 * is ready to allocate resources. Currently there's only one
221 * type of resource: socket.
222 */
223static int
224vrf_is_enabled (struct vrf *vrf)
225{
79694123 226 return vrf && CHECK_FLAG (vrf->status, VRF_ACTIVE);
216b18ef
DS
227
228 /*Pending: figure out the real use of this routine.. it used to be..
e5bf3e1e 229 return vrf && vrf->vrf_id == VRF_DEFAULT;
216b18ef 230 */
e5bf3e1e
FL
231}
232
233/*
234 * Enable a VRF - that is, let the VRF be ready to use.
235 * The VRF_ENABLE_HOOK callback will be called to inform
236 * that they can allocate resources in this VRF.
237 *
238 * RETURN: 1 - enabled successfully; otherwise, 0.
239 */
216b18ef 240int
e5bf3e1e
FL
241vrf_enable (struct vrf *vrf)
242{
19dc275e
DS
243 if (debug_vrf)
244 zlog_debug ("VRF %u is enabled.", vrf->vrf_id);
e5bf3e1e 245
e2b1be64
DS
246 if (!CHECK_FLAG (vrf->status, VRF_ACTIVE))
247 SET_FLAG (vrf->status, VRF_ACTIVE);
e5bf3e1e 248
e2b1be64
DS
249 if (vrf_master.vrf_enable_hook)
250 (*vrf_master.vrf_enable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
e5bf3e1e 251
e2b1be64 252 return 1;
e5bf3e1e
FL
253}
254
255/*
256 * Disable a VRF - that is, let the VRF be unusable.
257 * The VRF_DELETE_HOOK callback will be called to inform
258 * that they must release the resources in the VRF.
259 */
260static void
261vrf_disable (struct vrf *vrf)
262{
e74f14fc 263 UNSET_FLAG (vrf->status, VRF_ACTIVE);
e5bf3e1e
FL
264 if (vrf_is_enabled (vrf))
265 {
19dc275e
DS
266 if (debug_vrf)
267 zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id);
e5bf3e1e
FL
268
269 /* Till now, nothing to be done for the default VRF. */
216b18ef 270 //Pending: see why this statement.
e5bf3e1e
FL
271
272 if (vrf_master.vrf_disable_hook)
216b18ef 273 (*vrf_master.vrf_disable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
e5bf3e1e 274 }
e74f14fc 275
e5bf3e1e
FL
276}
277
278
b72ede27
FL
279/* Add a VRF hook. Please add hooks before calling vrf_init(). */
280void
216b18ef 281vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **))
b72ede27 282{
19dc275e
DS
283 if (debug_vrf)
284 zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__,
285 type, func);
286
b72ede27
FL
287 switch (type) {
288 case VRF_NEW_HOOK:
289 vrf_master.vrf_new_hook = func;
290 break;
291 case VRF_DELETE_HOOK:
292 vrf_master.vrf_delete_hook = func;
293 break;
e5bf3e1e
FL
294 case VRF_ENABLE_HOOK:
295 vrf_master.vrf_enable_hook = func;
296 break;
297 case VRF_DISABLE_HOOK:
298 vrf_master.vrf_disable_hook = func;
299 break;
b72ede27
FL
300 default:
301 break;
302 }
303}
304
305/* Return the iterator of the first VRF. */
306vrf_iter_t
307vrf_first (void)
308{
309 struct route_node *rn;
310
311 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
312 if (rn->info)
313 {
314 route_unlock_node (rn); /* top/next */
315 return (vrf_iter_t)rn;
316 }
317 return VRF_ITER_INVALID;
318}
319
320/* Return the next VRF iterator to the given iterator. */
321vrf_iter_t
322vrf_next (vrf_iter_t iter)
323{
324 struct route_node *rn = NULL;
325
326 /* Lock it first because route_next() will unlock it. */
327 if (iter != VRF_ITER_INVALID)
328 rn = route_next (route_lock_node ((struct route_node *)iter));
329
330 for (; rn; rn = route_next (rn))
331 if (rn->info)
332 {
333 route_unlock_node (rn); /* next */
334 return (vrf_iter_t)rn;
335 }
336 return VRF_ITER_INVALID;
337}
338
339/* Return the VRF iterator of the given VRF ID. If it does not exist,
340 * the iterator of the next existing VRF is returned. */
341vrf_iter_t
342vrf_iterator (vrf_id_t vrf_id)
343{
344 struct prefix p;
345 struct route_node *rn;
346
347 vrf_build_key (vrf_id, &p);
348 rn = route_node_get (vrf_table, &p);
349 if (rn->info)
350 {
351 /* OK, the VRF exists. */
352 route_unlock_node (rn); /* get */
353 return (vrf_iter_t)rn;
354 }
355
356 /* Find the next VRF. */
357 for (rn = route_next (rn); rn; rn = route_next (rn))
358 if (rn->info)
359 {
360 route_unlock_node (rn); /* next */
361 return (vrf_iter_t)rn;
362 }
363
364 return VRF_ITER_INVALID;
365}
366
367/* Obtain the VRF ID from the given VRF iterator. */
368vrf_id_t
369vrf_iter2id (vrf_iter_t iter)
370{
371 struct route_node *rn = (struct route_node *) iter;
372 return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
373}
374
216b18ef
DS
375struct vrf *
376vrf_iter2vrf (vrf_iter_t iter)
377{
378 struct route_node *rn = (struct route_node *) iter;
379 return (rn && rn->info) ? (struct vrf *)rn->info : NULL;
380}
381
b72ede27
FL
382/* Obtain the data pointer from the given VRF iterator. */
383void *
384vrf_iter2info (vrf_iter_t iter)
385{
386 struct route_node *rn = (struct route_node *) iter;
387 return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
388}
389
8736158a
FL
390/* Obtain the interface list from the given VRF iterator. */
391struct list *
392vrf_iter2iflist (vrf_iter_t iter)
393{
394 struct route_node *rn = (struct route_node *) iter;
395 return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
396}
397
216b18ef
DS
398/* Look up a VRF by name. */
399struct vrf *
400vrf_lookup_by_name (const char *name)
401{
402 struct vrf *vrf = NULL;
403 vrf_iter_t iter;
404
405 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
406 {
407 vrf = vrf_iter2vrf (iter);
408 if (vrf && !strcmp(vrf->name, name))
2e447c86 409 return vrf;
216b18ef
DS
410 }
411
2e447c86 412 return NULL;
216b18ef
DS
413}
414
415vrf_id_t
416vrf_name_to_id (const char *name)
417{
418 struct vrf *vrf;
419 vrf_id_t vrf_id = VRF_DEFAULT; //Pending: need a way to return invalid id/ routine not used.
420
421 vrf = vrf_lookup_by_name (name);
422 if (vrf)
423 vrf_id = vrf->vrf_id;
424
425 return vrf_id;
426}
427
b72ede27
FL
428/* Get the data pointer of the specified VRF. If not found, create one. */
429void *
430vrf_info_get (vrf_id_t vrf_id)
431{
216b18ef 432 struct vrf *vrf = vrf_get (vrf_id, NULL);
b72ede27
FL
433 return vrf->info;
434}
435
436/* Look up the data pointer of the specified VRF. */
437void *
438vrf_info_lookup (vrf_id_t vrf_id)
439{
440 struct vrf *vrf = vrf_lookup (vrf_id);
441 return vrf ? vrf->info : NULL;
442}
443
8736158a
FL
444/* Look up the interface list in a VRF. */
445struct list *
446vrf_iflist (vrf_id_t vrf_id)
447{
448 struct vrf * vrf = vrf_lookup (vrf_id);
449 return vrf ? vrf->iflist : NULL;
450}
451
452/* Get the interface list of the specified VRF. Create one if not find. */
453struct list *
454vrf_iflist_get (vrf_id_t vrf_id)
455{
216b18ef 456 struct vrf * vrf = vrf_get (vrf_id, NULL);
8736158a
FL
457 return vrf->iflist;
458}
459
b33adb7c 460/* Create the interface list for the specified VRF, if needed. */
461void
462vrf_iflist_create (vrf_id_t vrf_id)
463{
464 struct vrf * vrf = vrf_lookup (vrf_id);
465 if (vrf && !vrf->iflist)
b2d7c082 466 if_init (&vrf->iflist);
b33adb7c 467}
468
009b18fc 469/* Free the interface list of the specified VRF. */
470void
471vrf_iflist_terminate (vrf_id_t vrf_id)
472{
473 struct vrf * vrf = vrf_lookup (vrf_id);
474 if (vrf && vrf->iflist)
b2d7c082 475 if_terminate (&vrf->iflist);
009b18fc 476}
477
7076bb2f
FL
478/*
479 * VRF bit-map
480 */
481
482#define VRF_BITMAP_NUM_OF_GROUPS 8
483#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \
484 (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
485#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
486 (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
487
488#define VRF_BITMAP_GROUP(_id) \
489 ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
490#define VRF_BITMAP_BIT_OFFSET(_id) \
491 ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
492
493#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \
494 ((_bit_offset) / CHAR_BIT)
495#define VRF_BITMAP_FLAG(_bit_offset) \
496 (((u_char)1) << ((_bit_offset) % CHAR_BIT))
497
498struct vrf_bitmap
499{
500 u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
501};
502
503vrf_bitmap_t
504vrf_bitmap_init (void)
505{
506 return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap));
507}
508
509void
510vrf_bitmap_free (vrf_bitmap_t bmap)
511{
512 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
513 int i;
514
515 if (bmap == VRF_BITMAP_NULL)
516 return;
517
518 for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
519 if (bm->groups[i])
520 XFREE (MTYPE_VRF_BITMAP, bm->groups[i]);
521
522 XFREE (MTYPE_VRF_BITMAP, bm);
523}
524
525void
526vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
527{
528 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
529 u_char group = VRF_BITMAP_GROUP (vrf_id);
530 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
531
532 if (bmap == VRF_BITMAP_NULL)
533 return;
534
535 if (bm->groups[group] == NULL)
536 bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP,
537 VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
538
539 SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
540 VRF_BITMAP_FLAG (offset));
541}
542
543void
544vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
545{
546 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
547 u_char group = VRF_BITMAP_GROUP (vrf_id);
548 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
549
550 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
551 return;
552
553 UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
554 VRF_BITMAP_FLAG (offset));
555}
556
557int
558vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
559{
560 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
561 u_char group = VRF_BITMAP_GROUP (vrf_id);
562 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
563
564 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
565 return 0;
566
567 return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
568 VRF_BITMAP_FLAG (offset)) ? 1 : 0;
569}
570
216b18ef
DS
571/* Compare interface names, returning an integer greater than, equal to, or
572 * less than 0, (following the strcmp convention), according to the
573 * relationship between vrfp1 and vrfp2. Interface names consist of an
574 * alphabetic prefix and a numeric suffix. The primary sort key is
575 * lexicographic by name, and then numeric by number. No number sorts
576 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
577 * devpty0, de0 < del0
578 */
974fc9d2 579static int
216b18ef
DS
580vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2)
581{
974fc9d2 582 return if_cmp_name_func (vrfp1->name, vrfp2->name);
216b18ef
DS
583}
584
b72ede27
FL
585/* Initialize VRF module. */
586void
587vrf_init (void)
588{
589 struct vrf *default_vrf;
590
19dc275e
DS
591 if (debug_vrf)
592 zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__);
593
216b18ef
DS
594 vrf_list = list_new ();
595 vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func;
596
b72ede27
FL
597 /* Allocate VRF table. */
598 vrf_table = route_table_init ();
599
600 /* The default VRF always exists. */
216b18ef 601 default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
b72ede27
FL
602 if (!default_vrf)
603 {
604 zlog_err ("vrf_init: failed to create the default VRF!");
605 exit (1);
606 }
607
e5bf3e1e
FL
608 /* Enable the default VRF. */
609 if (!vrf_enable (default_vrf))
610 {
611 zlog_err ("vrf_init: failed to enable the default VRF!");
612 exit (1);
613 }
b72ede27
FL
614}
615
616/* Terminate VRF module. */
617void
618vrf_terminate (void)
619{
620 struct route_node *rn;
621 struct vrf *vrf;
622
19dc275e
DS
623 if (debug_vrf)
624 zlog_debug ("%s: Shutting down vrf subsystem", __PRETTY_FUNCTION__);
625
b72ede27
FL
626 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
627 if ((vrf = rn->info) != NULL)
628 vrf_delete (vrf);
629
630 route_table_finish (vrf_table);
631 vrf_table = NULL;
632}
633
e5bf3e1e
FL
634/* Create a socket for the VRF. */
635int
636vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
637{
638 int ret = -1;
639
19dc275e 640 ret = socket (domain, type, protocol);
e5bf3e1e
FL
641
642 return ret;
643}
644
19dc275e
DS
645/*
646 * Debug CLI for vrf's
647 */
648DEFUN (vrf_debug,
649 vrf_debug_cmd,
650 "debug vrf",
651 DEBUG_STR
652 "VRF Debugging\n")
653{
654 debug_vrf = 1;
655
656 return CMD_SUCCESS;
657}
658
659DEFUN (no_vrf_debug,
660 no_vrf_debug_cmd,
661 "no debug vrf",
662 NO_STR
663 DEBUG_STR
664 "VRF Debugging\n")
665{
666 debug_vrf = 0;
667
668 return CMD_SUCCESS;
669}
670
671static int
672vrf_write_host (struct vty *vty)
673{
674 if (debug_vrf)
675 vty_out (vty, "debug vrf%s", VTY_NEWLINE);
676
677 return 1;
678}
679
680static struct cmd_node vrf_debug_node =
681{
682 VRF_DEBUG_NODE,
683 "",
684 1
685};
686
687void
688vrf_install_commands (void)
689{
690 install_node (&vrf_debug_node, vrf_write_host);
691
692 install_element (CONFIG_NODE, &vrf_debug_cmd);
693 install_element (ENABLE_NODE, &vrf_debug_cmd);
694 install_element (CONFIG_NODE, &no_vrf_debug_cmd);
695 install_element (ENABLE_NODE, &no_vrf_debug_cmd);
696}