]> git.proxmox.com Git - mirror_frr.git/blob - lib/vrf.c
Merge remote-tracking branch 'origin/cmaster' into cmaster-next
[mirror_frr.git] / lib / vrf.c
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
25 #include "if.h"
26 #include "vrf.h"
27 #include "prefix.h"
28 #include "table.h"
29 #include "log.h"
30 #include "memory.h"
31 #include "command.h"
32
33 /*
34 * Turn on/off debug code
35 * for vrf.
36 */
37 int debug_vrf = 0;
38
39 /* Holding VRF hooks */
40 struct vrf_master
41 {
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 **);
46 } vrf_master = {0,};
47
48 /* VRF table */
49 struct route_table *vrf_table = NULL;
50
51 /* VRF is part of a list too to store it before its actually active */
52 struct list *vrf_list;
53
54 static int vrf_is_enabled (struct vrf *vrf);
55 static void vrf_disable (struct vrf *vrf);
56
57 /* VRF list existance check by name. */
58 struct vrf *
59 vrf_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
73 /* Build the table key */
74 static void
75 vrf_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
82 /* Get a VRF. If not found, create one.
83 * Arg:
84 * name - The name of the vrf. May be NULL if unknown.
85 * vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
86 * Description: Please note that this routine can be called with just the name
87 * and 0 vrf-id
88 */
89 struct vrf *
90 vrf_get (vrf_id_t vrf_id, const char *name)
91 {
92 struct prefix p;
93 struct route_node *rn = NULL;
94 struct vrf *vrf = NULL;
95
96 if (debug_vrf)
97 zlog_debug ("VRF_GET: %s(%d)", name, vrf_id);
98
99 /*
100 * Nothing to see, move along here
101 */
102 if (!name && vrf_id == VRF_UNKNOWN)
103 return NULL;
104
105 /*
106 * Valid vrf name and unknown vrf_id case
107 *
108 * This is called when we are configured from
109 * the cli but we have no kernel information yet.
110 */
111 if (name && vrf_id == VRF_UNKNOWN)
112 {
113 vrf = vrf_list_lookup_by_name (name);
114 if (vrf)
115 return vrf;
116
117 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
118 if (debug_vrf)
119 zlog_debug ("VRF(%u) %s is created.",
120 vrf_id, (name) ? name : "(NULL)");
121 strcpy (vrf->name, name);
122 listnode_add_sort (vrf_list, vrf);
123 if_init (&vrf->iflist);
124 if (vrf_master.vrf_new_hook)
125 {
126 (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
127
128 if (debug_vrf && vrf->info)
129 zlog_info ("zvrf is created.");
130 }
131 if (debug_vrf)
132 zlog_debug("Vrf Created: %p", vrf);
133 return vrf;
134 }
135 /*
136 * Valid vrf name and valid vrf_id case
137 *
138 * This can be passed from the kernel
139 */
140 else if (name && vrf_id != VRF_UNKNOWN)
141 {
142 vrf = vrf_list_lookup_by_name (name);
143 if (vrf)
144 {
145 /*
146 * If the passed in vrf_id and name match
147 * return, nothing to do here.
148 */
149 if (vrf->vrf_id == vrf_id)
150 return vrf;
151
152 /*
153 * Now we have a situation where we've had a
154 * vrf created, but not yet created the vrf_id route
155 * node, let's do so and match the code up.
156 */
157 vrf_build_key (vrf_id, &p);
158 rn = route_node_get (vrf_table, &p);
159
160 rn->info = vrf;
161 vrf->node = rn;
162 vrf->vrf_id = vrf_id;
163 if (vrf_master.vrf_new_hook)
164 (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
165
166 if (debug_vrf)
167 zlog_debug("Vrf found matched stuff up: %p", vrf);
168
169 return vrf;
170 }
171 else
172 {
173 /*
174 * We can have 1 of two situations here
175 * We've already been told about the vrf_id
176 * or we haven't.
177 */
178 vrf_build_key (vrf_id, &p);
179 rn = route_node_get (vrf_table, &p);
180 if (rn->info)
181 {
182 vrf = rn->info;
183 route_unlock_node (rn);
184 /*
185 * We know at this point that the vrf->name is not
186 * right because we would have caught it above.
187 * so let's set it.
188 */
189 strcpy (vrf->name, name);
190 listnode_add_sort (vrf_list, vrf);
191 if (vrf_master.vrf_new_hook)
192 {
193 (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
194
195 if (debug_vrf && vrf->info)
196 zlog_info ("zvrf is created.");
197 }
198 if (debug_vrf)
199 zlog_debug("Vrf Created: %p", vrf);
200 return vrf;
201 }
202 else
203 {
204 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
205
206 rn->info = vrf;
207 vrf->node = rn;
208 vrf->vrf_id = vrf_id;
209 strcpy (vrf->name, name);
210 listnode_add_sort (vrf_list, vrf);
211 if_init (&vrf->iflist);
212 if (vrf_master.vrf_new_hook)
213 {
214 (*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
215
216 if (debug_vrf && vrf->info)
217 zlog_info ("zvrf is created.");
218 }
219 if (debug_vrf)
220 zlog_debug("Vrf Created: %p", vrf);
221 return vrf;
222 }
223 }
224 }
225 /*
226 * The final case, we've been passed a valid vrf_id
227 * but no name. So we create the route node
228 * if it hasn't already been created.
229 */
230 else if (!name)
231 {
232 vrf_build_key (vrf_id, &p);
233 rn = route_node_get (vrf_table, &p);
234 if (debug_vrf)
235 zlog_debug("Vrf found: %p", rn->info);
236
237 if (rn->info)
238 {
239 route_unlock_node (rn);
240 return (rn->info);
241 }
242 else
243 {
244 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
245 rn->info = vrf;
246 vrf->node = rn;
247 vrf->vrf_id = vrf_id;
248 if_init (&vrf->iflist);
249 if (debug_vrf)
250 zlog_debug("Vrf Created: %p", vrf);
251 return vrf;
252 }
253 }
254
255 /*
256 * We shouldn't get here and if we do
257 * something has gone wrong.
258 */
259 return NULL;
260 }
261
262 /* Delete a VRF. This is called in vrf_terminate(). */
263 void
264 vrf_delete (struct vrf *vrf)
265 {
266 if (debug_vrf)
267 zlog_debug ("VRF %u is to be deleted.", vrf->vrf_id);
268
269 if (vrf_is_enabled (vrf))
270 vrf_disable (vrf);
271
272 if (vrf_master.vrf_delete_hook)
273 (*vrf_master.vrf_delete_hook) (vrf->vrf_id, vrf->name, &vrf->info);
274
275 if_terminate (&vrf->iflist);
276
277 if (vrf->node)
278 {
279 vrf->node->info = NULL;
280 route_unlock_node(vrf->node);
281 }
282
283 listnode_delete (vrf_list, vrf);
284
285 XFREE (MTYPE_VRF, vrf);
286 }
287
288 /* Look up a VRF by identifier. */
289 struct vrf *
290 vrf_lookup (vrf_id_t vrf_id)
291 {
292 struct prefix p;
293 struct route_node *rn;
294 struct vrf *vrf = NULL;
295
296 vrf_build_key (vrf_id, &p);
297 rn = route_node_lookup (vrf_table, &p);
298 if (rn)
299 {
300 vrf = (struct vrf *)rn->info;
301 route_unlock_node (rn); /* lookup */
302 }
303 return vrf;
304 }
305
306 /*
307 * Check whether the VRF is enabled - that is, whether the VRF
308 * is ready to allocate resources. Currently there's only one
309 * type of resource: socket.
310 */
311 static int
312 vrf_is_enabled (struct vrf *vrf)
313 {
314 return vrf && CHECK_FLAG (vrf->status, VRF_ACTIVE);
315
316 /*Pending: figure out the real use of this routine.. it used to be..
317 return vrf && vrf->vrf_id == VRF_DEFAULT;
318 */
319 }
320
321 /*
322 * Enable a VRF - that is, let the VRF be ready to use.
323 * The VRF_ENABLE_HOOK callback will be called to inform
324 * that they can allocate resources in this VRF.
325 *
326 * RETURN: 1 - enabled successfully; otherwise, 0.
327 */
328 int
329 vrf_enable (struct vrf *vrf)
330 {
331 if (debug_vrf)
332 zlog_debug ("VRF %u is enabled.", vrf->vrf_id);
333
334 if (!CHECK_FLAG (vrf->status, VRF_ACTIVE))
335 SET_FLAG (vrf->status, VRF_ACTIVE);
336
337 if (vrf_master.vrf_enable_hook)
338 (*vrf_master.vrf_enable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
339
340 return 1;
341 }
342
343 /*
344 * Disable a VRF - that is, let the VRF be unusable.
345 * The VRF_DELETE_HOOK callback will be called to inform
346 * that they must release the resources in the VRF.
347 */
348 static void
349 vrf_disable (struct vrf *vrf)
350 {
351 if (vrf_is_enabled (vrf))
352 {
353 UNSET_FLAG (vrf->status, VRF_ACTIVE);
354
355 if (debug_vrf)
356 zlog_debug ("VRF %u is to be disabled.", vrf->vrf_id);
357
358 /* Till now, nothing to be done for the default VRF. */
359 //Pending: see why this statement.
360
361 if (vrf_master.vrf_disable_hook)
362 (*vrf_master.vrf_disable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
363 }
364
365 }
366
367
368 /* Add a VRF hook. Please add hooks before calling vrf_init(). */
369 void
370 vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **))
371 {
372 if (debug_vrf)
373 zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__,
374 type, func);
375
376 switch (type) {
377 case VRF_NEW_HOOK:
378 vrf_master.vrf_new_hook = func;
379 break;
380 case VRF_DELETE_HOOK:
381 vrf_master.vrf_delete_hook = func;
382 break;
383 case VRF_ENABLE_HOOK:
384 vrf_master.vrf_enable_hook = func;
385 break;
386 case VRF_DISABLE_HOOK:
387 vrf_master.vrf_disable_hook = func;
388 break;
389 default:
390 break;
391 }
392 }
393
394 /* Return the iterator of the first VRF. */
395 vrf_iter_t
396 vrf_first (void)
397 {
398 struct route_node *rn;
399
400 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
401 if (rn->info)
402 {
403 route_unlock_node (rn); /* top/next */
404 return (vrf_iter_t)rn;
405 }
406 return VRF_ITER_INVALID;
407 }
408
409 /* Return the next VRF iterator to the given iterator. */
410 vrf_iter_t
411 vrf_next (vrf_iter_t iter)
412 {
413 struct route_node *rn = NULL;
414
415 /* Lock it first because route_next() will unlock it. */
416 if (iter != VRF_ITER_INVALID)
417 rn = route_next (route_lock_node ((struct route_node *)iter));
418
419 for (; rn; rn = route_next (rn))
420 if (rn->info)
421 {
422 route_unlock_node (rn); /* next */
423 return (vrf_iter_t)rn;
424 }
425 return VRF_ITER_INVALID;
426 }
427
428 /* Return the VRF iterator of the given VRF ID. If it does not exist,
429 * the iterator of the next existing VRF is returned. */
430 vrf_iter_t
431 vrf_iterator (vrf_id_t vrf_id)
432 {
433 struct prefix p;
434 struct route_node *rn;
435
436 vrf_build_key (vrf_id, &p);
437 rn = route_node_get (vrf_table, &p);
438 if (rn->info)
439 {
440 /* OK, the VRF exists. */
441 route_unlock_node (rn); /* get */
442 return (vrf_iter_t)rn;
443 }
444
445 /* Find the next VRF. */
446 for (rn = route_next (rn); rn; rn = route_next (rn))
447 if (rn->info)
448 {
449 route_unlock_node (rn); /* next */
450 return (vrf_iter_t)rn;
451 }
452
453 return VRF_ITER_INVALID;
454 }
455
456 /* Obtain the VRF ID from the given VRF iterator. */
457 vrf_id_t
458 vrf_iter2id (vrf_iter_t iter)
459 {
460 struct route_node *rn = (struct route_node *) iter;
461 return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
462 }
463
464 struct vrf *
465 vrf_iter2vrf (vrf_iter_t iter)
466 {
467 struct route_node *rn = (struct route_node *) iter;
468 return (rn && rn->info) ? (struct vrf *)rn->info : NULL;
469 }
470
471 /* Obtain the data pointer from the given VRF iterator. */
472 void *
473 vrf_iter2info (vrf_iter_t iter)
474 {
475 struct route_node *rn = (struct route_node *) iter;
476 return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
477 }
478
479 /* Obtain the interface list from the given VRF iterator. */
480 struct list *
481 vrf_iter2iflist (vrf_iter_t iter)
482 {
483 struct route_node *rn = (struct route_node *) iter;
484 return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
485 }
486
487 /* Look up a VRF by name. */
488 struct vrf *
489 vrf_lookup_by_name (const char *name)
490 {
491 struct vrf *vrf = NULL;
492 vrf_iter_t iter;
493
494 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
495 {
496 vrf = vrf_iter2vrf (iter);
497 if (vrf && !strcmp(vrf->name, name))
498 return vrf;
499 }
500
501 return NULL;
502 }
503
504 vrf_id_t
505 vrf_name_to_id (const char *name)
506 {
507 struct vrf *vrf;
508 vrf_id_t vrf_id = VRF_DEFAULT; //Pending: need a way to return invalid id/ routine not used.
509
510 vrf = vrf_lookup_by_name (name);
511 if (vrf)
512 vrf_id = vrf->vrf_id;
513
514 return vrf_id;
515 }
516
517 /* Get the data pointer of the specified VRF. If not found, create one. */
518 void *
519 vrf_info_get (vrf_id_t vrf_id)
520 {
521 struct vrf *vrf = vrf_get (vrf_id, NULL);
522 return vrf->info;
523 }
524
525 /* Look up the data pointer of the specified VRF. */
526 void *
527 vrf_info_lookup (vrf_id_t vrf_id)
528 {
529 struct vrf *vrf = vrf_lookup (vrf_id);
530 return vrf ? vrf->info : NULL;
531 }
532
533 /* Look up the interface list in a VRF. */
534 struct list *
535 vrf_iflist (vrf_id_t vrf_id)
536 {
537 struct vrf * vrf = vrf_lookup (vrf_id);
538 return vrf ? vrf->iflist : NULL;
539 }
540
541 /* Get the interface list of the specified VRF. Create one if not find. */
542 struct list *
543 vrf_iflist_get (vrf_id_t vrf_id)
544 {
545 struct vrf * vrf = vrf_get (vrf_id, NULL);
546 return vrf->iflist;
547 }
548
549 /* Create the interface list for the specified VRF, if needed. */
550 void
551 vrf_iflist_create (vrf_id_t vrf_id)
552 {
553 struct vrf * vrf = vrf_lookup (vrf_id);
554 if (vrf && !vrf->iflist)
555 if_init (&vrf->iflist);
556 }
557
558 /* Free the interface list of the specified VRF. */
559 void
560 vrf_iflist_terminate (vrf_id_t vrf_id)
561 {
562 struct vrf * vrf = vrf_lookup (vrf_id);
563 if (vrf && vrf->iflist)
564 if_terminate (&vrf->iflist);
565 }
566
567 /*
568 * VRF bit-map
569 */
570
571 #define VRF_BITMAP_NUM_OF_GROUPS 8
572 #define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \
573 (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
574 #define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
575 (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
576
577 #define VRF_BITMAP_GROUP(_id) \
578 ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
579 #define VRF_BITMAP_BIT_OFFSET(_id) \
580 ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
581
582 #define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \
583 ((_bit_offset) / CHAR_BIT)
584 #define VRF_BITMAP_FLAG(_bit_offset) \
585 (((u_char)1) << ((_bit_offset) % CHAR_BIT))
586
587 struct vrf_bitmap
588 {
589 u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
590 };
591
592 vrf_bitmap_t
593 vrf_bitmap_init (void)
594 {
595 return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap));
596 }
597
598 void
599 vrf_bitmap_free (vrf_bitmap_t bmap)
600 {
601 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
602 int i;
603
604 if (bmap == VRF_BITMAP_NULL)
605 return;
606
607 for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
608 if (bm->groups[i])
609 XFREE (MTYPE_VRF_BITMAP, bm->groups[i]);
610
611 XFREE (MTYPE_VRF_BITMAP, bm);
612 }
613
614 void
615 vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
616 {
617 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
618 u_char group = VRF_BITMAP_GROUP (vrf_id);
619 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
620
621 if (bmap == VRF_BITMAP_NULL)
622 return;
623
624 if (bm->groups[group] == NULL)
625 bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP,
626 VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
627
628 SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
629 VRF_BITMAP_FLAG (offset));
630 }
631
632 void
633 vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
634 {
635 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
636 u_char group = VRF_BITMAP_GROUP (vrf_id);
637 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
638
639 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
640 return;
641
642 UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
643 VRF_BITMAP_FLAG (offset));
644 }
645
646 int
647 vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
648 {
649 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
650 u_char group = VRF_BITMAP_GROUP (vrf_id);
651 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
652
653 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
654 return 0;
655
656 return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
657 VRF_BITMAP_FLAG (offset)) ? 1 : 0;
658 }
659
660 /* Compare interface names, returning an integer greater than, equal to, or
661 * less than 0, (following the strcmp convention), according to the
662 * relationship between vrfp1 and vrfp2. Interface names consist of an
663 * alphabetic prefix and a numeric suffix. The primary sort key is
664 * lexicographic by name, and then numeric by number. No number sorts
665 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
666 * devpty0, de0 < del0
667 */
668 static int
669 vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2)
670 {
671 return if_cmp_name_func (vrfp1->name, vrfp2->name);
672 }
673
674 /* Initialize VRF module. */
675 void
676 vrf_init (void)
677 {
678 struct vrf *default_vrf;
679
680 if (debug_vrf)
681 zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__);
682
683 vrf_list = list_new ();
684 vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func;
685
686 /* Allocate VRF table. */
687 vrf_table = route_table_init ();
688
689 /* The default VRF always exists. */
690 default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
691 if (!default_vrf)
692 {
693 zlog_err ("vrf_init: failed to create the default VRF!");
694 exit (1);
695 }
696
697 /* Enable the default VRF. */
698 if (!vrf_enable (default_vrf))
699 {
700 zlog_err ("vrf_init: failed to enable the default VRF!");
701 exit (1);
702 }
703 }
704
705 /* Terminate VRF module. */
706 void
707 vrf_terminate (void)
708 {
709 struct route_node *rn;
710 struct vrf *vrf;
711
712 if (debug_vrf)
713 zlog_debug ("%s: Shutting down vrf subsystem", __PRETTY_FUNCTION__);
714
715 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
716 if ((vrf = rn->info) != NULL)
717 vrf_delete (vrf);
718
719 route_table_finish (vrf_table);
720 vrf_table = NULL;
721 }
722
723 /* Create a socket for the VRF. */
724 int
725 vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
726 {
727 int ret = -1;
728
729 ret = socket (domain, type, protocol);
730
731 return ret;
732 }
733
734 /*
735 * Debug CLI for vrf's
736 */
737 DEFUN (vrf_debug,
738 vrf_debug_cmd,
739 "debug vrf",
740 DEBUG_STR
741 "VRF Debugging\n")
742 {
743 debug_vrf = 1;
744
745 return CMD_SUCCESS;
746 }
747
748 DEFUN (no_vrf_debug,
749 no_vrf_debug_cmd,
750 "no debug vrf",
751 NO_STR
752 DEBUG_STR
753 "VRF Debugging\n")
754 {
755 debug_vrf = 0;
756
757 return CMD_SUCCESS;
758 }
759
760 static int
761 vrf_write_host (struct vty *vty)
762 {
763 if (debug_vrf)
764 vty_out (vty, "debug vrf%s", VTY_NEWLINE);
765
766 return 1;
767 }
768
769 static struct cmd_node vrf_debug_node =
770 {
771 VRF_DEBUG_NODE,
772 "",
773 1
774 };
775
776 void
777 vrf_install_commands (void)
778 {
779 install_node (&vrf_debug_node, vrf_write_host);
780
781 install_element (CONFIG_NODE, &vrf_debug_cmd);
782 install_element (ENABLE_NODE, &vrf_debug_cmd);
783 install_element (CONFIG_NODE, &no_vrf_debug_cmd);
784 install_element (ENABLE_NODE, &no_vrf_debug_cmd);
785 }