blob: 89653a8bb61544e6dff210bfb069e545bb80631f [file] [log] [blame]
Feng Lu41f44a22015-05-22 11:39:56 +02001/*
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
Feng Lu55cfa2f2014-07-03 18:24:34 +080025#ifdef HAVE_NETNS
26#undef _GNU_SOURCE
27#define _GNU_SOURCE
28
29#include <sched.h>
30#endif
31
Feng Lu126215c2015-05-22 11:39:58 +020032#include "if.h"
Feng Lu41f44a22015-05-22 11:39:56 +020033#include "vrf.h"
34#include "prefix.h"
35#include "table.h"
36#include "log.h"
37#include "memory.h"
Feng Lu55cfa2f2014-07-03 18:24:34 +080038#include "command.h"
39#include "vty.h"
40
41#ifdef HAVE_NETNS
42
43#ifndef CLONE_NEWNET
44#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */
45#endif
46
47#ifndef HAVE_SETNS
48static inline int setns(int fd, int nstype)
49{
50#ifdef __NR_setns
51 return syscall(__NR_setns, fd, nstype);
52#else
53 errno = ENOSYS;
54 return -1;
55#endif
56}
57#endif /* HAVE_SETNS */
58
59#define VRF_RUN_DIR "/var/run/netns"
60#define VRF_DEFAULT_NAME "/proc/self/ns/net"
61
62#else /* !HAVE_NETNS */
Feng Lu41f44a22015-05-22 11:39:56 +020063
Feng Lufb2bfc12015-05-22 11:40:08 +020064#define VRF_DEFAULT_NAME "Default-IP-Routing-Table"
65
Feng Lu55cfa2f2014-07-03 18:24:34 +080066#endif /* HAVE_NETNS */
67
Feng Lu41f44a22015-05-22 11:39:56 +020068struct vrf
69{
70 /* Identifier, same as the vector index */
71 vrf_id_t vrf_id;
72 /* Name */
73 char *name;
Feng Lu55cfa2f2014-07-03 18:24:34 +080074 /* File descriptor */
75 int fd;
Feng Lu41f44a22015-05-22 11:39:56 +020076
Feng Lu5a5702f2015-05-22 11:39:59 +020077 /* Master list of interfaces belonging to this VRF */
78 struct list *iflist;
79
Feng Lu41f44a22015-05-22 11:39:56 +020080 /* User data */
81 void *info;
82};
83
84/* Holding VRF hooks */
85struct vrf_master
86{
87 int (*vrf_new_hook) (vrf_id_t, void **);
88 int (*vrf_delete_hook) (vrf_id_t, void **);
Feng Lufb2bfc12015-05-22 11:40:08 +020089 int (*vrf_enable_hook) (vrf_id_t, void **);
90 int (*vrf_disable_hook) (vrf_id_t, void **);
Feng Lu41f44a22015-05-22 11:39:56 +020091} vrf_master = {0,};
92
93/* VRF table */
94struct route_table *vrf_table = NULL;
95
Feng Lufb2bfc12015-05-22 11:40:08 +020096static int vrf_is_enabled (struct vrf *vrf);
97static int vrf_enable (struct vrf *vrf);
98static void vrf_disable (struct vrf *vrf);
99
100
Feng Lu41f44a22015-05-22 11:39:56 +0200101/* Build the table key */
102static void
103vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
104{
105 p->family = AF_INET;
106 p->prefixlen = IPV4_MAX_BITLEN;
107 p->u.prefix4.s_addr = vrf_id;
108}
109
110/* Get a VRF. If not found, create one. */
111static struct vrf *
112vrf_get (vrf_id_t vrf_id)
113{
114 struct prefix p;
115 struct route_node *rn;
116 struct vrf *vrf;
117
118 vrf_build_key (vrf_id, &p);
119 rn = route_node_get (vrf_table, &p);
120 if (rn->info)
121 {
122 vrf = (struct vrf *)rn->info;
123 route_unlock_node (rn); /* get */
124 return vrf;
125 }
126
127 vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
128 vrf->vrf_id = vrf_id;
Feng Lu55cfa2f2014-07-03 18:24:34 +0800129 vrf->fd = -1;
Feng Lu41f44a22015-05-22 11:39:56 +0200130 rn->info = vrf;
131
Feng Lu5a5702f2015-05-22 11:39:59 +0200132 /* Initialize interfaces. */
133 if_init (vrf_id, &vrf->iflist);
134
Feng Lu41f44a22015-05-22 11:39:56 +0200135 zlog_info ("VRF %u is created.", vrf_id);
136
137 if (vrf_master.vrf_new_hook)
138 (*vrf_master.vrf_new_hook) (vrf_id, &vrf->info);
139
140 return vrf;
141}
142
143/* Delete a VRF. This is called in vrf_terminate(). */
144static void
145vrf_delete (struct vrf *vrf)
146{
147 zlog_info ("VRF %u is to be deleted.", vrf->vrf_id);
148
Feng Lu55cfa2f2014-07-03 18:24:34 +0800149 vrf_disable (vrf);
Feng Lufb2bfc12015-05-22 11:40:08 +0200150
Feng Lu41f44a22015-05-22 11:39:56 +0200151 if (vrf_master.vrf_delete_hook)
152 (*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info);
153
Feng Lu5a5702f2015-05-22 11:39:59 +0200154 if_terminate (vrf->vrf_id, &vrf->iflist);
155
Feng Lu41f44a22015-05-22 11:39:56 +0200156 if (vrf->name)
157 XFREE (MTYPE_VRF_NAME, vrf->name);
158
159 XFREE (MTYPE_VRF, vrf);
160}
161
162/* Look up a VRF by identifier. */
163static struct vrf *
164vrf_lookup (vrf_id_t vrf_id)
165{
166 struct prefix p;
167 struct route_node *rn;
168 struct vrf *vrf = NULL;
169
170 vrf_build_key (vrf_id, &p);
171 rn = route_node_lookup (vrf_table, &p);
172 if (rn)
173 {
174 vrf = (struct vrf *)rn->info;
175 route_unlock_node (rn); /* lookup */
176 }
177 return vrf;
178}
179
Feng Lufb2bfc12015-05-22 11:40:08 +0200180/*
181 * Check whether the VRF is enabled - that is, whether the VRF
182 * is ready to allocate resources. Currently there's only one
183 * type of resource: socket.
184 */
185static int
186vrf_is_enabled (struct vrf *vrf)
187{
Feng Lu55cfa2f2014-07-03 18:24:34 +0800188#ifdef HAVE_NETNS
189 return vrf && vrf->fd >= 0;
190#else
191 return vrf && vrf->fd == -2 && vrf->vrf_id == VRF_DEFAULT;
192#endif
Feng Lufb2bfc12015-05-22 11:40:08 +0200193}
194
195/*
196 * Enable a VRF - that is, let the VRF be ready to use.
197 * The VRF_ENABLE_HOOK callback will be called to inform
198 * that they can allocate resources in this VRF.
199 *
200 * RETURN: 1 - enabled successfully; otherwise, 0.
201 */
202static int
203vrf_enable (struct vrf *vrf)
204{
Feng Lufb2bfc12015-05-22 11:40:08 +0200205
Feng Lu55cfa2f2014-07-03 18:24:34 +0800206 if (!vrf_is_enabled (vrf))
207 {
208#ifdef HAVE_NETNS
209 vrf->fd = open (vrf->name, O_RDONLY);
210#else
211 vrf->fd = -2; /* Remember that vrf_enable_hook has been called */
212 errno = -ENOTSUP;
213#endif
214
215 if (!vrf_is_enabled (vrf))
216 {
217 zlog_err ("Can not enable VRF %u: %s!",
218 vrf->vrf_id, safe_strerror (errno));
219 return 0;
220 }
221
222#ifdef HAVE_NETNS
223 zlog_info ("VRF %u is associated with NETNS %s.",
224 vrf->vrf_id, vrf->name);
225#endif
226
227 zlog_info ("VRF %u is enabled.", vrf->vrf_id);
Feng Lufb2bfc12015-05-22 11:40:08 +0200228 if (vrf_master.vrf_enable_hook)
229 (*vrf_master.vrf_enable_hook) (vrf->vrf_id, &vrf->info);
Feng Lufb2bfc12015-05-22 11:40:08 +0200230 }
231
Feng Lu55cfa2f2014-07-03 18:24:34 +0800232 return 1;
Feng Lufb2bfc12015-05-22 11:40:08 +0200233}
234
235/*
236 * Disable a VRF - that is, let the VRF be unusable.
237 * The VRF_DELETE_HOOK callback will be called to inform
238 * that they must release the resources in the VRF.
239 */
240static void
241vrf_disable (struct vrf *vrf)
242{
243 if (vrf_is_enabled (vrf))
244 {
245 zlog_info ("VRF %u is to be disabled.", vrf->vrf_id);
246
Feng Lufb2bfc12015-05-22 11:40:08 +0200247 if (vrf_master.vrf_disable_hook)
248 (*vrf_master.vrf_disable_hook) (vrf->vrf_id, &vrf->info);
Feng Lu55cfa2f2014-07-03 18:24:34 +0800249
250#ifdef HAVE_NETNS
251 close (vrf->fd);
252#endif
253 vrf->fd = -1;
Feng Lufb2bfc12015-05-22 11:40:08 +0200254 }
255}
256
257
Feng Lu41f44a22015-05-22 11:39:56 +0200258/* Add a VRF hook. Please add hooks before calling vrf_init(). */
259void
260vrf_add_hook (int type, int (*func)(vrf_id_t, void **))
261{
262 switch (type) {
263 case VRF_NEW_HOOK:
264 vrf_master.vrf_new_hook = func;
265 break;
266 case VRF_DELETE_HOOK:
267 vrf_master.vrf_delete_hook = func;
268 break;
Feng Lufb2bfc12015-05-22 11:40:08 +0200269 case VRF_ENABLE_HOOK:
270 vrf_master.vrf_enable_hook = func;
271 break;
272 case VRF_DISABLE_HOOK:
273 vrf_master.vrf_disable_hook = func;
274 break;
Feng Lu41f44a22015-05-22 11:39:56 +0200275 default:
276 break;
277 }
278}
279
280/* Return the iterator of the first VRF. */
281vrf_iter_t
282vrf_first (void)
283{
284 struct route_node *rn;
285
286 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
287 if (rn->info)
288 {
289 route_unlock_node (rn); /* top/next */
290 return (vrf_iter_t)rn;
291 }
292 return VRF_ITER_INVALID;
293}
294
295/* Return the next VRF iterator to the given iterator. */
296vrf_iter_t
297vrf_next (vrf_iter_t iter)
298{
299 struct route_node *rn = NULL;
300
301 /* Lock it first because route_next() will unlock it. */
302 if (iter != VRF_ITER_INVALID)
303 rn = route_next (route_lock_node ((struct route_node *)iter));
304
305 for (; rn; rn = route_next (rn))
306 if (rn->info)
307 {
308 route_unlock_node (rn); /* next */
309 return (vrf_iter_t)rn;
310 }
311 return VRF_ITER_INVALID;
312}
313
314/* Return the VRF iterator of the given VRF ID. If it does not exist,
315 * the iterator of the next existing VRF is returned. */
316vrf_iter_t
317vrf_iterator (vrf_id_t vrf_id)
318{
319 struct prefix p;
320 struct route_node *rn;
321
322 vrf_build_key (vrf_id, &p);
323 rn = route_node_get (vrf_table, &p);
324 if (rn->info)
325 {
326 /* OK, the VRF exists. */
327 route_unlock_node (rn); /* get */
328 return (vrf_iter_t)rn;
329 }
330
331 /* Find the next VRF. */
332 for (rn = route_next (rn); rn; rn = route_next (rn))
333 if (rn->info)
334 {
335 route_unlock_node (rn); /* next */
336 return (vrf_iter_t)rn;
337 }
338
339 return VRF_ITER_INVALID;
340}
341
342/* Obtain the VRF ID from the given VRF iterator. */
343vrf_id_t
344vrf_iter2id (vrf_iter_t iter)
345{
346 struct route_node *rn = (struct route_node *) iter;
347 return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
348}
349
350/* Obtain the data pointer from the given VRF iterator. */
351void *
352vrf_iter2info (vrf_iter_t iter)
353{
354 struct route_node *rn = (struct route_node *) iter;
355 return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
356}
357
Feng Lu5a5702f2015-05-22 11:39:59 +0200358/* Obtain the interface list from the given VRF iterator. */
359struct list *
360vrf_iter2iflist (vrf_iter_t iter)
361{
362 struct route_node *rn = (struct route_node *) iter;
363 return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
364}
365
Feng Lu41f44a22015-05-22 11:39:56 +0200366/* Get the data pointer of the specified VRF. If not found, create one. */
367void *
368vrf_info_get (vrf_id_t vrf_id)
369{
370 struct vrf *vrf = vrf_get (vrf_id);
371 return vrf->info;
372}
373
374/* Look up the data pointer of the specified VRF. */
375void *
376vrf_info_lookup (vrf_id_t vrf_id)
377{
378 struct vrf *vrf = vrf_lookup (vrf_id);
379 return vrf ? vrf->info : NULL;
380}
381
Feng Lu5a5702f2015-05-22 11:39:59 +0200382/* Look up the interface list in a VRF. */
383struct list *
384vrf_iflist (vrf_id_t vrf_id)
385{
386 struct vrf * vrf = vrf_lookup (vrf_id);
387 return vrf ? vrf->iflist : NULL;
388}
389
390/* Get the interface list of the specified VRF. Create one if not find. */
391struct list *
392vrf_iflist_get (vrf_id_t vrf_id)
393{
394 struct vrf * vrf = vrf_get (vrf_id);
395 return vrf->iflist;
396}
397
Feng Luc99f3482014-10-16 09:52:36 +0800398/*
399 * VRF bit-map
400 */
401
402#define VRF_BITMAP_NUM_OF_GROUPS 8
403#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \
404 (UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
405#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
406 (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
407
408#define VRF_BITMAP_GROUP(_id) \
409 ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
410#define VRF_BITMAP_BIT_OFFSET(_id) \
411 ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
412
413#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \
414 ((_bit_offset) / CHAR_BIT)
415#define VRF_BITMAP_FLAG(_bit_offset) \
416 (((u_char)1) << ((_bit_offset) % CHAR_BIT))
417
418struct vrf_bitmap
419{
420 u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
421};
422
423vrf_bitmap_t
424vrf_bitmap_init (void)
425{
426 return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap));
427}
428
429void
430vrf_bitmap_free (vrf_bitmap_t bmap)
431{
432 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
433 int i;
434
435 if (bmap == VRF_BITMAP_NULL)
436 return;
437
438 for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
439 if (bm->groups[i])
440 XFREE (MTYPE_VRF_BITMAP, bm->groups[i]);
441
442 XFREE (MTYPE_VRF_BITMAP, bm);
443}
444
445void
446vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
447{
448 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
449 u_char group = VRF_BITMAP_GROUP (vrf_id);
450 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
451
452 if (bmap == VRF_BITMAP_NULL)
453 return;
454
455 if (bm->groups[group] == NULL)
456 bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP,
457 VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
458
459 SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
460 VRF_BITMAP_FLAG (offset));
461}
462
463void
464vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
465{
466 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
467 u_char group = VRF_BITMAP_GROUP (vrf_id);
468 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
469
470 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
471 return;
472
473 UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
474 VRF_BITMAP_FLAG (offset));
475}
476
477int
478vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
479{
480 struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
481 u_char group = VRF_BITMAP_GROUP (vrf_id);
482 u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
483
484 if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
485 return 0;
486
487 return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
488 VRF_BITMAP_FLAG (offset)) ? 1 : 0;
489}
490
Feng Lu55cfa2f2014-07-03 18:24:34 +0800491#ifdef HAVE_NETNS
492/*
493 * VRF realization with NETNS
494 */
495
496static char *
497vrf_netns_pathname (struct vty *vty, const char *name)
498{
499 static char pathname[PATH_MAX];
500 char *result;
501
502 if (name[0] == '/') /* absolute pathname */
503 result = realpath (name, pathname);
504 else /* relevant pathname */
505 {
506 char tmp_name[PATH_MAX];
507 snprintf (tmp_name, PATH_MAX, "%s/%s", VRF_RUN_DIR, name);
508 result = realpath (tmp_name, pathname);
509 }
510
511 if (! result)
512 {
513 vty_out (vty, "Invalid pathname: %s%s", safe_strerror (errno),
514 VTY_NEWLINE);
515 return NULL;
516 }
517 return pathname;
518}
519
520DEFUN (vrf_netns,
521 vrf_netns_cmd,
522 "vrf <1-65535> netns NAME",
523 "Enable a VRF\n"
524 "Specify the VRF identifier\n"
525 "Associate with a NETNS\n"
526 "The file name in " VRF_RUN_DIR ", or a full pathname\n")
527{
528 vrf_id_t vrf_id = VRF_DEFAULT;
529 struct vrf *vrf = NULL;
530 char *pathname = vrf_netns_pathname (vty, argv[1]);
531
532 if (!pathname)
533 return CMD_WARNING;
534
535 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
536 vrf = vrf_get (vrf_id);
537
538 if (vrf->name && strcmp (vrf->name, pathname) != 0)
539 {
540 vty_out (vty, "VRF %u is already configured with NETNS %s%s",
541 vrf->vrf_id, vrf->name, VTY_NEWLINE);
542 return CMD_WARNING;
543 }
544
545 if (!vrf->name)
546 vrf->name = XSTRDUP (MTYPE_VRF_NAME, pathname);
547
548 if (!vrf_enable (vrf))
549 {
550 vty_out (vty, "Can not associate VRF %u with NETNS %s%s",
551 vrf->vrf_id, vrf->name, VTY_NEWLINE);
552 return CMD_WARNING;
553 }
554
555 return CMD_SUCCESS;
556}
557
558DEFUN (no_vrf_netns,
559 no_vrf_netns_cmd,
560 "no vrf <1-65535> netns NAME",
561 NO_STR
562 "Enable a VRF\n"
563 "Specify the VRF identifier\n"
564 "Associate with a NETNS\n"
565 "The file name in " VRF_RUN_DIR ", or a full pathname\n")
566{
567 vrf_id_t vrf_id = VRF_DEFAULT;
568 struct vrf *vrf = NULL;
569 char *pathname = vrf_netns_pathname (vty, argv[1]);
570
571 if (!pathname)
572 return CMD_WARNING;
573
574 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
575 vrf = vrf_lookup (vrf_id);
576
577 if (!vrf)
578 {
579 vty_out (vty, "VRF %u is not found%s", vrf_id, VTY_NEWLINE);
580 return CMD_SUCCESS;
581 }
582
583 if (vrf->name && strcmp (vrf->name, pathname) != 0)
584 {
585 vty_out (vty, "Incorrect NETNS file name%s", VTY_NEWLINE);
586 return CMD_WARNING;
587 }
588
589 vrf_disable (vrf);
590
591 if (vrf->name)
592 {
593 XFREE (MTYPE_VRF_NAME, vrf->name);
594 vrf->name = NULL;
595 }
596
597 return CMD_SUCCESS;
598}
599
600/* VRF node. */
601static struct cmd_node vrf_node =
602{
603 VRF_NODE,
604 "", /* VRF node has no interface. */
605 1
606};
607
608/* VRF configuration write function. */
609static int
610vrf_config_write (struct vty *vty)
611{
612 struct route_node *rn;
613 struct vrf *vrf;
614 int write = 0;
615
616 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
617 if ((vrf = rn->info) != NULL &&
618 vrf->vrf_id != VRF_DEFAULT && vrf->name)
619 {
620 vty_out (vty, "vrf %u netns %s%s", vrf->vrf_id, vrf->name, VTY_NEWLINE);
621 write++;
622 }
623
624 return write;
625}
626
627#endif /* HAVE_NETNS */
628
Feng Lu41f44a22015-05-22 11:39:56 +0200629/* Initialize VRF module. */
630void
631vrf_init (void)
632{
633 struct vrf *default_vrf;
634
635 /* Allocate VRF table. */
636 vrf_table = route_table_init ();
637
638 /* The default VRF always exists. */
639 default_vrf = vrf_get (VRF_DEFAULT);
640 if (!default_vrf)
641 {
642 zlog_err ("vrf_init: failed to create the default VRF!");
643 exit (1);
644 }
645
646 /* Set the default VRF name. */
Feng Lufb2bfc12015-05-22 11:40:08 +0200647 default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, VRF_DEFAULT_NAME);
648
649 /* Enable the default VRF. */
650 if (!vrf_enable (default_vrf))
651 {
652 zlog_err ("vrf_init: failed to enable the default VRF!");
653 exit (1);
654 }
Feng Lu55cfa2f2014-07-03 18:24:34 +0800655
656#ifdef HAVE_NETNS
657 /* Install VRF commands. */
658 install_node (&vrf_node, vrf_config_write);
659 install_element (CONFIG_NODE, &vrf_netns_cmd);
660 install_element (CONFIG_NODE, &no_vrf_netns_cmd);
661#endif
Feng Lu41f44a22015-05-22 11:39:56 +0200662}
663
664/* Terminate VRF module. */
665void
666vrf_terminate (void)
667{
668 struct route_node *rn;
669 struct vrf *vrf;
670
671 for (rn = route_top (vrf_table); rn; rn = route_next (rn))
672 if ((vrf = rn->info) != NULL)
673 vrf_delete (vrf);
674
675 route_table_finish (vrf_table);
676 vrf_table = NULL;
Feng Lu41f44a22015-05-22 11:39:56 +0200677}
678
Feng Lufb2bfc12015-05-22 11:40:08 +0200679/* Create a socket for the VRF. */
680int
681vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
682{
Feng Lu55cfa2f2014-07-03 18:24:34 +0800683 struct vrf *vrf = vrf_lookup (vrf_id);
Feng Lufb2bfc12015-05-22 11:40:08 +0200684 int ret = -1;
685
Feng Lu55cfa2f2014-07-03 18:24:34 +0800686 if (!vrf_is_enabled (vrf))
Feng Lufb2bfc12015-05-22 11:40:08 +0200687 {
688 errno = ENOSYS;
689 return -1;
690 }
691
Feng Lu55cfa2f2014-07-03 18:24:34 +0800692#ifdef HAVE_NETNS
693 ret = (vrf_id != VRF_DEFAULT) ? setns (vrf->fd, CLONE_NEWNET) : 0;
694 if (ret >= 0)
695 {
696 ret = socket (domain, type, protocol);
697 if (vrf_id != VRF_DEFAULT)
698 setns (vrf_lookup (VRF_DEFAULT)->fd, CLONE_NEWNET);
699 }
700#else
701 ret = socket (domain, type, protocol);
702#endif
Feng Lufb2bfc12015-05-22 11:40:08 +0200703
704 return ret;
705}