]> git.proxmox.com Git - mirror_frr.git/blame - lib/vrf.c
zebra: collect and get netnamespaces information
[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 *
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
b72ede27
FL
20 */
21
22#include <zebra.h>
23
4691b65a
PG
24/* for basename */
25#include <libgen.h>
26
6a69b354 27#include "if.h"
b72ede27 28#include "vrf.h"
7922fc65 29#include "vrf_int.h"
b72ede27
FL
30#include "prefix.h"
31#include "table.h"
32#include "log.h"
33#include "memory.h"
19dc275e 34#include "command.h"
b95c1883 35#include "ns.h"
19dc275e 36
d62a17ae 37DEFINE_MTYPE_STATIC(LIB, VRF, "VRF")
4a1ab8e4
DL
38DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map")
39
e80e7cce
DL
40DEFINE_QOBJ_TYPE(vrf)
41
d62a17ae 42static __inline int vrf_id_compare(const struct vrf *, const struct vrf *);
43static __inline int vrf_name_compare(const struct vrf *, const struct vrf *);
1a1a7065 44
d62a17ae 45RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
46RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
1a1a7065 47
d62a17ae 48struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
49struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
1a1a7065 50
78dd30b2
PG
51static int vrf_backend;
52
19dc275e
DS
53/*
54 * Turn on/off debug code
55 * for vrf.
56 */
57int debug_vrf = 0;
b72ede27 58
b72ede27 59/* Holding VRF hooks */
d62a17ae 60struct vrf_master {
61 int (*vrf_new_hook)(struct vrf *);
62 int (*vrf_delete_hook)(struct vrf *);
63 int (*vrf_enable_hook)(struct vrf *);
64 int (*vrf_disable_hook)(struct vrf *);
65} vrf_master = {
66 0,
67};
b72ede27 68
d62a17ae 69static int vrf_is_enabled(struct vrf *vrf);
e5bf3e1e 70
216b18ef 71/* VRF list existance check by name. */
d62a17ae 72struct vrf *vrf_lookup_by_name(const char *name)
216b18ef 73{
d62a17ae 74 struct vrf vrf;
75 strlcpy(vrf.name, name, sizeof(vrf.name));
76 return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
216b18ef 77}
216b18ef 78
d62a17ae 79static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
b72ede27 80{
d62a17ae 81 return (a->vrf_id - b->vrf_id);
216b18ef
DS
82}
83
d62a17ae 84static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
b72ede27 85{
d62a17ae 86 return strcmp(a->name, b->name);
b72ede27
FL
87}
88
ce1be369
PG
89int vrf_switch_to_netns(vrf_id_t vrf_id)
90{
91 char *name;
92 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
93
94 /* VRF has no NETNS backend. silently ignore */
95 if (!vrf || vrf->data.l.netns_name[0] == '\0')
96 return 0;
97 /* VRF is default VRF. silently ignore */
98 if (vrf->vrf_id == VRF_DEFAULT)
99 return 0;
100 name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
101 if (debug_vrf)
102 zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
103 return ns_switch_to_netns(name);
104}
105
106int vrf_switchback_to_initial(void)
107{
108 int ret = ns_switchback_to_initial();
109
110 if (ret == 0 && debug_vrf)
111 zlog_debug("VRF_SWITCHBACK");
112 return ret;
113}
114
697d3ec7
PG
115/* return 1 if vrf can be enabled */
116int vrf_update_vrf_id(vrf_id_t vrf_id, struct vrf *vrf)
117{
118 vrf_id_t old_vrf_id;
119
120 if (!vrf)
121 return 0;
122 old_vrf_id = vrf->vrf_id;
123 if (vrf_id == vrf->vrf_id)
124 return 0;
125 if (vrf->vrf_id != VRF_UNKNOWN)
126 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
127 vrf->vrf_id = vrf_id;
128 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
129 if (old_vrf_id == VRF_UNKNOWN)
130 return 1;
131 return 0;
132}
133
216b18ef 134/* Get a VRF. If not found, create one.
34f8e6af
DS
135 * Arg:
136 * name - The name of the vrf. May be NULL if unknown.
137 * vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
216b18ef 138 * Description: Please note that this routine can be called with just the name
34f8e6af
DS
139 * and 0 vrf-id
140 */
d62a17ae 141struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
142{
143 struct vrf *vrf = NULL;
144 int new = 0;
145
146 if (debug_vrf)
fe533c56
PG
147 zlog_debug("VRF_GET: %s(%u)",
148 name == NULL ? "(NULL)" : name, vrf_id);
d62a17ae 149
150 /* Nothing to see, move along here */
151 if (!name && vrf_id == VRF_UNKNOWN)
152 return NULL;
153
154 /* Try to find VRF both by ID and name */
155 if (vrf_id != VRF_UNKNOWN)
156 vrf = vrf_lookup_by_id(vrf_id);
157 if (!vrf && name)
158 vrf = vrf_lookup_by_name(name);
159
160 if (vrf == NULL) {
161 vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
162 vrf->vrf_id = VRF_UNKNOWN;
d62a17ae 163 QOBJ_REG(vrf, vrf);
164 new = 1;
165
166 if (debug_vrf)
167 zlog_debug("VRF(%u) %s is created.", vrf_id,
168 (name) ? name : "(NULL)");
169 }
170
171 /* Set identifier */
172 if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
173 vrf->vrf_id = vrf_id;
174 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
175 }
176
177 /* Set name */
178 if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
179 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
180 strlcpy(vrf->name, name, sizeof(vrf->name));
181 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
182 } else if (name && vrf->name[0] == '\0') {
183 strlcpy(vrf->name, name, sizeof(vrf->name));
184 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
185 }
d62a17ae 186 if (new &&vrf_master.vrf_new_hook)
187 (*vrf_master.vrf_new_hook)(vrf);
188
189 return vrf;
b72ede27
FL
190}
191
84915b0a 192/* Delete a VRF. This is called when the underlying VRF goes away, a
193 * pre-configured VRF is deleted or when shutting down (vrf_terminate()).
194 */
d62a17ae 195void vrf_delete(struct vrf *vrf)
b72ede27 196{
d62a17ae 197 if (debug_vrf)
198 zlog_debug("VRF %u is to be deleted.", vrf->vrf_id);
b72ede27 199
d62a17ae 200 if (vrf_is_enabled(vrf))
201 vrf_disable(vrf);
e5bf3e1e 202
84915b0a 203 /* If the VRF is user configured, it'll stick around, just remove
204 * the ID mapping. Interfaces assigned to this VRF should've been
205 * removed already as part of the VRF going down.
206 */
207 if (vrf_is_user_cfged(vrf)) {
208 if (vrf->vrf_id != VRF_UNKNOWN) {
209 /* Delete any VRF interfaces - should be only
210 * the VRF itself, other interfaces should've
211 * been moved out of the VRF.
212 */
213 if_terminate(vrf);
214 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
215 vrf->vrf_id = VRF_UNKNOWN;
216 }
217 return;
218 }
219
d62a17ae 220 if (vrf_master.vrf_delete_hook)
221 (*vrf_master.vrf_delete_hook)(vrf);
216b18ef 222
d62a17ae 223 QOBJ_UNREG(vrf);
f4e14fdb 224 if_terminate(vrf);
b72ede27 225
d62a17ae 226 if (vrf->vrf_id != VRF_UNKNOWN)
227 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
228 if (vrf->name[0] != '\0')
229 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
b72ede27 230
d62a17ae 231 XFREE(MTYPE_VRF, vrf);
b72ede27
FL
232}
233
234/* Look up a VRF by identifier. */
d62a17ae 235struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
b72ede27 236{
d62a17ae 237 struct vrf vrf;
238 vrf.vrf_id = vrf_id;
239 return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
b72ede27
FL
240}
241
e5bf3e1e
FL
242/*
243 * Enable a VRF - that is, let the VRF be ready to use.
244 * The VRF_ENABLE_HOOK callback will be called to inform
245 * that they can allocate resources in this VRF.
246 *
247 * RETURN: 1 - enabled successfully; otherwise, 0.
248 */
d62a17ae 249int vrf_enable(struct vrf *vrf)
e5bf3e1e 250{
d62a17ae 251 if (vrf_is_enabled(vrf))
252 return 1;
05e8e11e 253
d62a17ae 254 if (debug_vrf)
255 zlog_debug("VRF %u is enabled.", vrf->vrf_id);
e5bf3e1e 256
d62a17ae 257 SET_FLAG(vrf->status, VRF_ACTIVE);
e5bf3e1e 258
d62a17ae 259 if (vrf_master.vrf_enable_hook)
260 (*vrf_master.vrf_enable_hook)(vrf);
e5bf3e1e 261
d62a17ae 262 return 1;
e5bf3e1e
FL
263}
264
265/*
266 * Disable a VRF - that is, let the VRF be unusable.
267 * The VRF_DELETE_HOOK callback will be called to inform
268 * that they must release the resources in the VRF.
269 */
697d3ec7 270void vrf_disable(struct vrf *vrf)
e5bf3e1e 271{
d62a17ae 272 if (!vrf_is_enabled(vrf))
273 return;
a647bfa8 274
d62a17ae 275 UNSET_FLAG(vrf->status, VRF_ACTIVE);
e5bf3e1e 276
d62a17ae 277 if (debug_vrf)
278 zlog_debug("VRF %u is to be disabled.", vrf->vrf_id);
e5bf3e1e 279
d62a17ae 280 /* Till now, nothing to be done for the default VRF. */
281 // Pending: see why this statement.
e74f14fc 282
d62a17ae 283 if (vrf_master.vrf_disable_hook)
284 (*vrf_master.vrf_disable_hook)(vrf);
e5bf3e1e
FL
285}
286
b7cfce93
MK
287const char *vrf_id_to_name(vrf_id_t vrf_id)
288{
289 struct vrf *vrf;
290
291 vrf = vrf_lookup_by_id(vrf_id);
292 if (vrf)
293 return vrf->name;
294
181c08c6 295 return "n/a";
b7cfce93
MK
296}
297
d62a17ae 298vrf_id_t vrf_name_to_id(const char *name)
216b18ef 299{
d62a17ae 300 struct vrf *vrf;
301 vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
302 // id/ routine not used.
216b18ef 303
d62a17ae 304 vrf = vrf_lookup_by_name(name);
305 if (vrf)
306 vrf_id = vrf->vrf_id;
216b18ef 307
d62a17ae 308 return vrf_id;
216b18ef
DS
309}
310
b72ede27 311/* Get the data pointer of the specified VRF. If not found, create one. */
d62a17ae 312void *vrf_info_get(vrf_id_t vrf_id)
b72ede27 313{
d62a17ae 314 struct vrf *vrf = vrf_get(vrf_id, NULL);
315 return vrf->info;
b72ede27
FL
316}
317
318/* Look up the data pointer of the specified VRF. */
d62a17ae 319void *vrf_info_lookup(vrf_id_t vrf_id)
b72ede27 320{
d62a17ae 321 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
322 return vrf ? vrf->info : NULL;
b72ede27
FL
323}
324
7076bb2f
FL
325/*
326 * VRF bit-map
327 */
328
3bd74754 329#define VRF_BITMAP_NUM_OF_GROUPS 1024
a9ff90c4 330#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS)
d62a17ae 331#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
332 (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
333
334#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
335#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
336
337#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT)
338#define VRF_BITMAP_FLAG(_bit_offset) (((u_char)1) << ((_bit_offset) % CHAR_BIT))
339
340struct vrf_bitmap {
341 u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
7076bb2f
FL
342};
343
d62a17ae 344vrf_bitmap_t vrf_bitmap_init(void)
7076bb2f 345{
d62a17ae 346 return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP,
347 sizeof(struct vrf_bitmap));
7076bb2f
FL
348}
349
d62a17ae 350void vrf_bitmap_free(vrf_bitmap_t bmap)
7076bb2f 351{
d62a17ae 352 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
353 int i;
7076bb2f 354
d62a17ae 355 if (bmap == VRF_BITMAP_NULL)
356 return;
7076bb2f 357
d62a17ae 358 for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
359 if (bm->groups[i])
360 XFREE(MTYPE_VRF_BITMAP, bm->groups[i]);
7076bb2f 361
d62a17ae 362 XFREE(MTYPE_VRF_BITMAP, bm);
7076bb2f
FL
363}
364
d62a17ae 365void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 366{
d62a17ae 367 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
368 u_char group = VRF_BITMAP_GROUP(vrf_id);
369 u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 370
d62a17ae 371 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
372 return;
7076bb2f 373
d62a17ae 374 if (bm->groups[group] == NULL)
375 bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP,
376 VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
7076bb2f 377
d62a17ae 378 SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
379 VRF_BITMAP_FLAG(offset));
7076bb2f
FL
380}
381
d62a17ae 382void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 383{
d62a17ae 384 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
385 u_char group = VRF_BITMAP_GROUP(vrf_id);
386 u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 387
d62a17ae 388 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
389 || bm->groups[group] == NULL)
390 return;
7076bb2f 391
d62a17ae 392 UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
393 VRF_BITMAP_FLAG(offset));
7076bb2f
FL
394}
395
d62a17ae 396int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
7076bb2f 397{
d62a17ae 398 struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap;
399 u_char group = VRF_BITMAP_GROUP(vrf_id);
400 u_char offset = VRF_BITMAP_BIT_OFFSET(vrf_id);
7076bb2f 401
d62a17ae 402 if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN
403 || bm->groups[group] == NULL)
404 return 0;
7076bb2f 405
d62a17ae 406 return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)],
407 VRF_BITMAP_FLAG(offset))
408 ? 1
409 : 0;
7076bb2f
FL
410}
411
d62a17ae 412static void vrf_autocomplete(vector comps, struct cmd_token *token)
d617d5fe 413{
d62a17ae 414 struct vrf *vrf = NULL;
d617d5fe 415
a2addae8 416 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
a9ff90c4 417 if (vrf->vrf_id != VRF_DEFAULT)
d62a17ae 418 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
419 }
d617d5fe
DS
420}
421
422static const struct cmd_variable_handler vrf_var_handlers[] = {
d62a17ae 423 {
424 .varname = "vrf",
425 .completions = vrf_autocomplete,
426 },
427 {.completions = NULL},
d617d5fe
DS
428};
429
b72ede27 430/* Initialize VRF module. */
d62a17ae 431void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
432 int (*disable)(struct vrf *), int (*delete)(struct vrf *))
433{
434 struct vrf *default_vrf;
435
436 if (debug_vrf)
437 zlog_debug("%s: Initializing VRF subsystem",
438 __PRETTY_FUNCTION__);
439
440 vrf_master.vrf_new_hook = create;
441 vrf_master.vrf_enable_hook = enable;
442 vrf_master.vrf_disable_hook = disable;
443 vrf_master.vrf_delete_hook = delete;
444
445 /* The default VRF always exists. */
446 default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
447 if (!default_vrf) {
448 zlog_err("vrf_init: failed to create the default VRF!");
449 exit(1);
450 }
451
452 /* Enable the default VRF. */
453 if (!vrf_enable(default_vrf)) {
454 zlog_err("vrf_init: failed to enable the default VRF!");
455 exit(1);
456 }
457
458 cmd_variable_handler_register(vrf_var_handlers);
b72ede27
FL
459}
460
461/* Terminate VRF module. */
d62a17ae 462void vrf_terminate(void)
b72ede27 463{
d62a17ae 464 struct vrf *vrf;
b72ede27 465
d62a17ae 466 if (debug_vrf)
467 zlog_debug("%s: Shutting down vrf subsystem",
468 __PRETTY_FUNCTION__);
19dc275e 469
55cd0f61
DS
470 while (!RB_EMPTY(vrf_id_head, &vrfs_by_id)) {
471 vrf = RB_ROOT(vrf_id_head, &vrfs_by_id);
472
65c3a7c4 473 /* Clear configured flag and invoke delete. */
474 UNSET_FLAG(vrf->status, VRF_CONFIGURED);
d62a17ae 475 vrf_delete(vrf);
65c3a7c4 476 }
55cd0f61
DS
477
478 while (!RB_EMPTY(vrf_name_head, &vrfs_by_name)) {
479 vrf = RB_ROOT(vrf_name_head, &vrfs_by_name);
480
65c3a7c4 481 /* Clear configured flag and invoke delete. */
482 UNSET_FLAG(vrf->status, VRF_CONFIGURED);
d62a17ae 483 vrf_delete(vrf);
65c3a7c4 484 }
b72ede27
FL
485}
486
e5bf3e1e 487/* Create a socket for the VRF. */
d62a17ae 488int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id)
e5bf3e1e 489{
d62a17ae 490 int ret = -1;
e5bf3e1e 491
d62a17ae 492 ret = socket(domain, type, protocol);
e5bf3e1e 493
d62a17ae 494 return ret;
e5bf3e1e
FL
495}
496
78dd30b2
PG
497int vrf_is_backend_netns(void)
498{
499 return (vrf_backend == VRF_BACKEND_NETNS);
500}
501
502int vrf_get_backend(void)
503{
504 return vrf_backend;
505}
506
507void vrf_configure_backend(int vrf_backend_netns)
508{
509 vrf_backend = vrf_backend_netns;
510}
511
697d3ec7 512int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf)
f30c50b9 513{
d62a17ae 514 struct vrf *vrfp;
f30c50b9 515
d62a17ae 516 if (strlen(vrfname) > VRF_NAMSIZ) {
697d3ec7
PG
517 if (vty)
518 vty_out(vty,
519 "%% VRF name %s invalid: length exceeds %d bytes\n",
520 vrfname, VRF_NAMSIZ);
521 else
522 zlog_warn(
523 "%% VRF name %s invalid: length exceeds %d bytes\n",
524 vrfname, VRF_NAMSIZ);
d62a17ae 525 return CMD_WARNING_CONFIG_FAILED;
526 }
f30c50b9 527
d62a17ae 528 vrfp = vrf_get(VRF_UNKNOWN, vrfname);
f30c50b9 529
697d3ec7
PG
530 if (vty)
531 VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
f30c50b9 532
697d3ec7
PG
533 if (vrf)
534 *vrf = vrfp;
d62a17ae 535 return CMD_SUCCESS;
f30c50b9
RW
536}
537
ce1be369
PG
538int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
539{
540 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
541
542 if (!vrf || vrf->data.l.netns_name[0] == '\0')
543 return 0;
544 if (vrf->vrf_id == VRF_DEFAULT)
545 return 0;
546 return 1;
547}
548
697d3ec7
PG
549/* vrf CLI commands */
550DEFUN_NOSH (vrf,
551 vrf_cmd,
552 "vrf NAME",
553 "Select a VRF to configure\n"
554 "VRF's name\n")
555{
556 int idx_name = 1;
557 const char *vrfname = argv[idx_name]->arg;
558
559 return vrf_handler_create(vty, vrfname, NULL);
560}
561
f30c50b9
RW
562DEFUN_NOSH (no_vrf,
563 no_vrf_cmd,
d7a75a6c 564 "no vrf NAME",
f30c50b9
RW
565 NO_STR
566 "Delete a pseudo VRF's configuration\n"
567 "VRF's name\n")
568{
d62a17ae 569 const char *vrfname = argv[2]->arg;
53dc2b05 570
d62a17ae 571 struct vrf *vrfp;
f30c50b9 572
d62a17ae 573 vrfp = vrf_lookup_by_name(vrfname);
f30c50b9 574
d62a17ae 575 if (vrfp == NULL) {
576 vty_out(vty, "%% VRF %s does not exist\n", vrfname);
577 return CMD_WARNING_CONFIG_FAILED;
578 }
f30c50b9 579
d62a17ae 580 if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
581 vty_out(vty, "%% Only inactive VRFs can be deleted\n");
582 return CMD_WARNING_CONFIG_FAILED;
583 }
f30c50b9 584
84915b0a 585 /* Clear configured flag and invoke delete. */
586 UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
d62a17ae 587 vrf_delete(vrfp);
f30c50b9 588
d62a17ae 589 return CMD_SUCCESS;
f30c50b9
RW
590}
591
53dc2b05 592
d62a17ae 593struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1};
7ddcfca4 594
19dc275e
DS
595/*
596 * Debug CLI for vrf's
597 */
598DEFUN (vrf_debug,
599 vrf_debug_cmd,
600 "debug vrf",
601 DEBUG_STR
602 "VRF Debugging\n")
603{
d62a17ae 604 debug_vrf = 1;
19dc275e 605
d62a17ae 606 return CMD_SUCCESS;
19dc275e
DS
607}
608
609DEFUN (no_vrf_debug,
610 no_vrf_debug_cmd,
611 "no debug vrf",
612 NO_STR
613 DEBUG_STR
614 "VRF Debugging\n")
615{
d62a17ae 616 debug_vrf = 0;
19dc275e 617
d62a17ae 618 return CMD_SUCCESS;
19dc275e
DS
619}
620
d62a17ae 621static int vrf_write_host(struct vty *vty)
19dc275e 622{
d62a17ae 623 if (debug_vrf)
624 vty_out(vty, "debug vrf\n");
19dc275e 625
d62a17ae 626 return 1;
19dc275e
DS
627}
628
d62a17ae 629static struct cmd_node vrf_debug_node = {VRF_DEBUG_NODE, "", 1};
19dc275e 630
d62a17ae 631void vrf_install_commands(void)
19dc275e 632{
d62a17ae 633 install_node(&vrf_debug_node, vrf_write_host);
19dc275e 634
d62a17ae 635 install_element(CONFIG_NODE, &vrf_debug_cmd);
636 install_element(ENABLE_NODE, &vrf_debug_cmd);
637 install_element(CONFIG_NODE, &no_vrf_debug_cmd);
638 install_element(ENABLE_NODE, &no_vrf_debug_cmd);
19dc275e 639}
53dc2b05 640
d62a17ae 641void vrf_cmd_init(int (*writefunc)(struct vty *vty))
7ddcfca4 642{
d62a17ae 643 install_element(CONFIG_NODE, &vrf_cmd);
644 install_element(CONFIG_NODE, &no_vrf_cmd);
645 install_node(&vrf_node, writefunc);
646 install_default(VRF_NODE);
b95c1883 647 ns_cmd_init();
19dc275e 648}