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