2015-05-22 11:39:56 +02:00
|
|
|
/*
|
|
|
|
* VRF functions.
|
|
|
|
* Copyright (C) 2014 6WIND S.A.
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published
|
|
|
|
* by the Free Software Foundation; either version 2, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
2017-05-13 10:25:29 +02:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2015-05-22 11:39:56 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
2017-12-22 16:02:51 +01:00
|
|
|
/* for basename */
|
|
|
|
#include <libgen.h>
|
|
|
|
|
2015-05-22 11:39:58 +02:00
|
|
|
#include "if.h"
|
2015-05-22 11:39:56 +02:00
|
|
|
#include "vrf.h"
|
2017-05-16 01:02:34 +02:00
|
|
|
#include "vrf_int.h"
|
2015-05-22 11:39:56 +02:00
|
|
|
#include "prefix.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "memory.h"
|
2016-02-03 15:00:25 +01:00
|
|
|
#include "command.h"
|
2017-12-06 12:03:59 +01:00
|
|
|
#include "ns.h"
|
2018-03-13 15:26:03 +01:00
|
|
|
#include "privs.h"
|
2018-04-10 21:57:09 +02:00
|
|
|
#include "nexthop_group.h"
|
2018-06-14 14:23:49 +02:00
|
|
|
#include "lib_errors.h"
|
2020-03-11 02:20:49 +01:00
|
|
|
#include "northbound.h"
|
2020-03-21 22:35:14 +01:00
|
|
|
#include "northbound_cli.h"
|
2016-02-03 15:00:25 +01:00
|
|
|
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
/* default VRF ID value used when VRF backend is not NETNS */
|
|
|
|
#define VRF_DEFAULT_INTERNAL 0
|
2018-06-22 16:03:11 +02:00
|
|
|
#define VRF_DEFAULT_NAME_INTERNAL "default"
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
|
2015-05-29 05:48:31 +02:00
|
|
|
DEFINE_MTYPE_STATIC(LIB, VRF, "VRF")
|
|
|
|
DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map")
|
|
|
|
|
2016-09-27 14:51:08 +02:00
|
|
|
DEFINE_QOBJ_TYPE(vrf)
|
|
|
|
|
2017-06-16 15:44:31 +02:00
|
|
|
static __inline int vrf_id_compare(const struct vrf *, const struct vrf *);
|
|
|
|
static __inline int vrf_name_compare(const struct vrf *, const struct vrf *);
|
2016-10-29 18:37:11 +02:00
|
|
|
|
2017-06-16 15:44:31 +02:00
|
|
|
RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
|
|
|
|
RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
|
2016-10-29 18:37:11 +02:00
|
|
|
|
|
|
|
struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
|
2016-10-30 00:30:57 +02:00
|
|
|
struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
|
2016-10-29 18:37:11 +02:00
|
|
|
|
2018-01-22 09:42:53 +01:00
|
|
|
static int vrf_backend;
|
2019-02-07 14:55:06 +01:00
|
|
|
static int vrf_backend_configured;
|
2018-03-13 15:26:03 +01:00
|
|
|
static struct zebra_privs_t *vrf_daemon_privs;
|
2018-06-22 13:54:47 +02:00
|
|
|
static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
|
2018-01-22 09:42:53 +01:00
|
|
|
|
2016-02-03 15:00:25 +01:00
|
|
|
/*
|
|
|
|
* Turn on/off debug code
|
|
|
|
* for vrf.
|
|
|
|
*/
|
2019-04-03 22:34:18 +02:00
|
|
|
static int debug_vrf = 0;
|
2015-05-22 11:39:56 +02:00
|
|
|
|
|
|
|
/* Holding VRF hooks */
|
2019-11-27 21:17:57 +01:00
|
|
|
static struct vrf_master {
|
2016-10-30 22:50:26 +01:00
|
|
|
int (*vrf_new_hook)(struct vrf *);
|
|
|
|
int (*vrf_delete_hook)(struct vrf *);
|
|
|
|
int (*vrf_enable_hook)(struct vrf *);
|
|
|
|
int (*vrf_disable_hook)(struct vrf *);
|
2018-05-29 11:17:10 +02:00
|
|
|
int (*vrf_update_name_hook)(struct vrf *vrf);
|
2015-05-22 11:39:56 +02:00
|
|
|
} vrf_master = {
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
static int vrf_is_enabled(struct vrf *vrf);
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* VRF list existance check by name. */
|
2016-10-30 02:44:06 +02:00
|
|
|
struct vrf *vrf_lookup_by_name(const char *name)
|
2016-02-01 18:09:51 +01:00
|
|
|
{
|
2016-10-30 00:30:57 +02:00
|
|
|
struct vrf vrf;
|
|
|
|
strlcpy(vrf.name, name, sizeof(vrf.name));
|
|
|
|
return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
|
2016-02-01 18:09:51 +01:00
|
|
|
}
|
|
|
|
|
2017-06-16 15:44:31 +02:00
|
|
|
static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
2016-10-29 18:37:11 +02:00
|
|
|
return (a->vrf_id - b->vrf_id);
|
2016-02-01 18:09:51 +01:00
|
|
|
}
|
|
|
|
|
2017-06-16 15:44:31 +02:00
|
|
|
static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
2016-10-30 00:30:57 +02:00
|
|
|
return strcmp(a->name, b->name);
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
2018-02-05 16:23:42 +01:00
|
|
|
/* if ns_id is different and not VRF_UNKNOWN,
|
|
|
|
* then update vrf identifier, and enable VRF
|
|
|
|
*/
|
|
|
|
static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
|
|
|
|
{
|
|
|
|
ns_id_t vrf_id = (vrf_id_t)ns_id;
|
|
|
|
vrf_id_t old_vrf_id;
|
|
|
|
struct vrf *vrf = (struct vrf *)opaqueptr;
|
|
|
|
|
|
|
|
if (!vrf)
|
|
|
|
return;
|
|
|
|
old_vrf_id = vrf->vrf_id;
|
|
|
|
if (vrf_id == vrf->vrf_id)
|
|
|
|
return;
|
|
|
|
if (vrf->vrf_id != VRF_UNKNOWN)
|
|
|
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
vrf->vrf_id = vrf_id;
|
|
|
|
RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
if (old_vrf_id == VRF_UNKNOWN)
|
2020-04-08 07:57:15 +02:00
|
|
|
vrf_enable(vrf);
|
2018-02-05 16:23:42 +01:00
|
|
|
}
|
|
|
|
|
2017-12-20 12:29:21 +01:00
|
|
|
int vrf_switch_to_netns(vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
|
|
|
|
|
|
|
|
/* VRF is default VRF. silently ignore */
|
2018-02-05 16:23:42 +01:00
|
|
|
if (!vrf || vrf->vrf_id == VRF_DEFAULT)
|
2018-06-17 20:55:01 +02:00
|
|
|
return 1; /* 1 = default */
|
2018-02-05 16:23:42 +01:00
|
|
|
/* VRF has no NETNS backend. silently ignore */
|
|
|
|
if (vrf->data.l.netns_name[0] == '\0')
|
2018-06-17 20:55:01 +02:00
|
|
|
return 2; /* 2 = no netns */
|
2017-12-20 12:29:21 +01:00
|
|
|
name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
|
|
|
|
if (debug_vrf)
|
|
|
|
zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
|
|
|
|
return ns_switch_to_netns(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
int vrf_switchback_to_initial(void)
|
|
|
|
{
|
|
|
|
int ret = ns_switchback_to_initial();
|
|
|
|
|
|
|
|
if (ret == 0 && debug_vrf)
|
|
|
|
zlog_debug("VRF_SWITCHBACK");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* Get a VRF. If not found, create one.
|
2016-05-02 21:30:55 +02:00
|
|
|
* Arg:
|
|
|
|
* name - The name of the vrf. May be NULL if unknown.
|
|
|
|
* vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
|
2016-02-01 18:09:51 +01:00
|
|
|
* Description: Please note that this routine can be called with just the name
|
2016-05-02 21:30:55 +02:00
|
|
|
* and 0 vrf-id
|
|
|
|
*/
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *vrf = NULL;
|
2016-10-30 02:44:06 +02:00
|
|
|
int new = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
/* Nothing to see, move along here */
|
2016-05-02 21:30:55 +02:00
|
|
|
if (!name && vrf_id == VRF_UNKNOWN)
|
|
|
|
return NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-03-20 10:59:48 +01:00
|
|
|
/* attempt to find already available VRF
|
|
|
|
*/
|
|
|
|
if (name)
|
|
|
|
vrf = vrf_lookup_by_name(name);
|
2018-06-22 16:03:11 +02:00
|
|
|
if (vrf && vrf_id != VRF_UNKNOWN
|
|
|
|
&& vrf->vrf_id != VRF_UNKNOWN
|
|
|
|
&& vrf->vrf_id != vrf_id) {
|
|
|
|
zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
|
|
|
|
name, vrf_id, vrf->vrf_id);
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-10-30 02:44:06 +02:00
|
|
|
/* Try to find VRF both by ID and name */
|
2018-03-20 10:59:48 +01:00
|
|
|
if (!vrf && vrf_id != VRF_UNKNOWN)
|
2016-10-30 02:44:06 +02:00
|
|
|
vrf = vrf_lookup_by_id(vrf_id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
if (vrf == NULL) {
|
2016-04-21 18:15:07 +02:00
|
|
|
vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
|
2016-10-28 20:53:38 +02:00
|
|
|
vrf->vrf_id = VRF_UNKNOWN;
|
2016-09-27 14:51:08 +02:00
|
|
|
QOBJ_REG(vrf, vrf);
|
2016-10-30 02:44:06 +02:00
|
|
|
new = 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-05-02 21:30:55 +02:00
|
|
|
if (debug_vrf)
|
2016-10-30 02:44:06 +02:00
|
|
|
zlog_debug("VRF(%u) %s is created.", vrf_id,
|
|
|
|
(name) ? name : "(NULL)");
|
2016-02-01 18:09:51 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
/* Set identifier */
|
|
|
|
if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
|
|
|
|
vrf->vrf_id = vrf_id;
|
|
|
|
RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
|
2016-05-02 21:30:55 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
/* Set name */
|
|
|
|
if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
|
2019-06-14 13:52:00 +02:00
|
|
|
/* update the vrf name */
|
2016-10-30 02:44:06 +02:00
|
|
|
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
|
2019-06-14 13:52:00 +02:00
|
|
|
strlcpy(vrf->data.l.netns_name,
|
|
|
|
name, NS_NAMSIZ);
|
2016-10-30 02:44:06 +02:00
|
|
|
strlcpy(vrf->name, name, sizeof(vrf->name));
|
|
|
|
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
|
2019-06-14 13:52:00 +02:00
|
|
|
if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
vrf_set_default_name(vrf->name, false);
|
2016-10-30 02:44:06 +02:00
|
|
|
} else if (name && vrf->name[0] == '\0') {
|
|
|
|
strlcpy(vrf->name, name, sizeof(vrf->name));
|
|
|
|
RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
|
2016-04-21 18:15:07 +02:00
|
|
|
}
|
2016-10-30 02:44:06 +02:00
|
|
|
if (new &&vrf_master.vrf_new_hook)
|
2016-10-30 22:50:26 +01:00
|
|
|
(*vrf_master.vrf_new_hook)(vrf);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
return vrf;
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
*: Handle VRF configuration when VRF gets inactivated and activated
A VRF is active only when the corresponding VRF device is present in the
kernel. However, when the kernel VRF device is removed, the VRF container in
FRR should go away only if there is no user configuration for it. Otherwise,
when the VRF device is created again so that the VRF becomes active, FRR
cannot take the correct actions. Example configuration for the VRF includes
static routes and EVPN L3 VNI.
Note that a VRF is currently considered to be "configured" as soon as the
operator has issued the "vrf <name>" command in FRR. Such a configured VRF
is not deleted upon VRF device removal, it is only made inactive. A VRF that
is "configured" can be deleted only upon operator action and only if the VRF
has been deactivated i.e., the VRF device removed from the kernel. This is
an existing restriction.
To implement this change, the VRF disable and delete actions have been modified.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Mitesh Kanjariya <mkanjariya@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-18553, CM-18918, CM-10139
Reviewed By: CCR-7022
Testing Done:
1. vrf and pim-vrf automation tests
2. Multiple VRF delete and readd (ifdown, ifup-with-depends)
3. FRR stop, start, restart
4. Networking restart
5. Configuration delete and readd
Some of the above tests run in different sequences (manually).
2017-12-02 02:36:37 +01:00
|
|
|
/* Delete a VRF. This is called when the underlying VRF goes away, a
|
|
|
|
* pre-configured VRF is deleted or when shutting down (vrf_terminate()).
|
|
|
|
*/
|
2015-05-22 11:39:56 +02:00
|
|
|
void vrf_delete(struct vrf *vrf)
|
|
|
|
{
|
2016-02-03 15:00:25 +01:00
|
|
|
if (debug_vrf)
|
2020-09-18 02:17:14 +02:00
|
|
|
zlog_debug("VRF %s(%u) is to be deleted.", vrf->name,
|
|
|
|
vrf->vrf_id);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
if (vrf_is_enabled(vrf))
|
|
|
|
vrf_disable(vrf);
|
|
|
|
|
*: Handle VRF configuration when VRF gets inactivated and activated
A VRF is active only when the corresponding VRF device is present in the
kernel. However, when the kernel VRF device is removed, the VRF container in
FRR should go away only if there is no user configuration for it. Otherwise,
when the VRF device is created again so that the VRF becomes active, FRR
cannot take the correct actions. Example configuration for the VRF includes
static routes and EVPN L3 VNI.
Note that a VRF is currently considered to be "configured" as soon as the
operator has issued the "vrf <name>" command in FRR. Such a configured VRF
is not deleted upon VRF device removal, it is only made inactive. A VRF that
is "configured" can be deleted only upon operator action and only if the VRF
has been deactivated i.e., the VRF device removed from the kernel. This is
an existing restriction.
To implement this change, the VRF disable and delete actions have been modified.
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Mitesh Kanjariya <mkanjariya@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-18553, CM-18918, CM-10139
Reviewed By: CCR-7022
Testing Done:
1. vrf and pim-vrf automation tests
2. Multiple VRF delete and readd (ifdown, ifup-with-depends)
3. FRR stop, start, restart
4. Networking restart
5. Configuration delete and readd
Some of the above tests run in different sequences (manually).
2017-12-02 02:36:37 +01:00
|
|
|
/* If the VRF is user configured, it'll stick around, just remove
|
|
|
|
* the ID mapping. Interfaces assigned to this VRF should've been
|
|
|
|
* removed already as part of the VRF going down.
|
|
|
|
*/
|
|
|
|
if (vrf_is_user_cfged(vrf)) {
|
|
|
|
if (vrf->vrf_id != VRF_UNKNOWN) {
|
|
|
|
/* Delete any VRF interfaces - should be only
|
|
|
|
* the VRF itself, other interfaces should've
|
|
|
|
* been moved out of the VRF.
|
|
|
|
*/
|
|
|
|
if_terminate(vrf);
|
|
|
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
vrf->vrf_id = VRF_UNKNOWN;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
if (vrf_master.vrf_delete_hook)
|
2016-10-30 22:50:26 +01:00
|
|
|
(*vrf_master.vrf_delete_hook)(vrf);
|
2016-02-01 18:09:51 +01:00
|
|
|
|
2016-09-27 14:51:08 +02:00
|
|
|
QOBJ_UNREG(vrf);
|
2017-10-03 03:06:01 +02:00
|
|
|
if_terminate(vrf);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-10-29 18:37:11 +02:00
|
|
|
if (vrf->vrf_id != VRF_UNKNOWN)
|
|
|
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
2016-10-30 02:44:06 +02:00
|
|
|
if (vrf->name[0] != '\0')
|
|
|
|
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
|
|
|
XFREE(MTYPE_VRF, vrf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look up a VRF by identifier. */
|
2016-11-02 15:16:58 +01:00
|
|
|
struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
2016-10-29 18:37:11 +02:00
|
|
|
struct vrf vrf;
|
|
|
|
vrf.vrf_id = vrf_id;
|
|
|
|
return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
/*
|
|
|
|
* Enable a VRF - that is, let the VRF be ready to use.
|
|
|
|
* The VRF_ENABLE_HOOK callback will be called to inform
|
|
|
|
* that they can allocate resources in this VRF.
|
|
|
|
*
|
|
|
|
* RETURN: 1 - enabled successfully; otherwise, 0.
|
|
|
|
*/
|
|
|
|
int vrf_enable(struct vrf *vrf)
|
|
|
|
{
|
2016-10-30 02:44:06 +02:00
|
|
|
if (vrf_is_enabled(vrf))
|
|
|
|
return 1;
|
|
|
|
|
2016-02-03 15:00:25 +01:00
|
|
|
if (debug_vrf)
|
2020-09-18 02:17:14 +02:00
|
|
|
zlog_debug("VRF %s(%u) is enabled.", vrf->name, vrf->vrf_id);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
SET_FLAG(vrf->status, VRF_ACTIVE);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2016-04-13 16:06:36 +02:00
|
|
|
if (vrf_master.vrf_enable_hook)
|
2016-10-30 22:50:26 +01:00
|
|
|
(*vrf_master.vrf_enable_hook)(vrf);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2018-04-10 21:57:09 +02:00
|
|
|
/*
|
|
|
|
* If we have any nexthop group entries that
|
|
|
|
* are awaiting vrf initialization then
|
|
|
|
* let's let people know about it
|
|
|
|
*/
|
|
|
|
nexthop_group_enable_vrf(vrf);
|
|
|
|
|
2016-04-13 16:06:36 +02:00
|
|
|
return 1;
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable a VRF - that is, let the VRF be unusable.
|
|
|
|
* The VRF_DELETE_HOOK callback will be called to inform
|
|
|
|
* that they must release the resources in the VRF.
|
|
|
|
*/
|
2017-12-13 11:04:31 +01:00
|
|
|
void vrf_disable(struct vrf *vrf)
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
{
|
2016-10-30 02:44:06 +02:00
|
|
|
if (!vrf_is_enabled(vrf))
|
|
|
|
return;
|
2016-05-05 14:20:32 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
UNSET_FLAG(vrf->status, VRF_ACTIVE);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
if (debug_vrf)
|
2020-09-18 02:17:14 +02:00
|
|
|
zlog_debug("VRF %s(%u) is to be disabled.", vrf->name,
|
|
|
|
vrf->vrf_id);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
/* Till now, nothing to be done for the default VRF. */
|
|
|
|
// Pending: see why this statement.
|
2016-04-13 14:20:33 +02:00
|
|
|
|
2020-09-18 02:13:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When the vrf is disabled let's
|
|
|
|
* handle all nexthop-groups associated
|
|
|
|
* with this vrf
|
|
|
|
*/
|
|
|
|
nexthop_group_disable_vrf(vrf);
|
|
|
|
|
2016-10-30 02:44:06 +02:00
|
|
|
if (vrf_master.vrf_disable_hook)
|
2016-10-30 22:50:26 +01:00
|
|
|
(*vrf_master.vrf_disable_hook)(vrf);
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
}
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
const char *vrf_id_to_name(vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
|
|
|
vrf = vrf_lookup_by_id(vrf_id);
|
2020-03-15 19:42:30 +01:00
|
|
|
return VRF_LOGNAME(vrf);
|
2017-10-08 03:49:27 +02:00
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
vrf_id_t vrf_name_to_id(const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
|
|
|
|
// id/ routine not used.
|
|
|
|
|
2018-11-20 10:30:47 +01:00
|
|
|
if (!name)
|
|
|
|
return vrf_id;
|
2016-02-01 18:09:51 +01:00
|
|
|
vrf = vrf_lookup_by_name(name);
|
|
|
|
if (vrf)
|
|
|
|
vrf_id = vrf->vrf_id;
|
|
|
|
|
|
|
|
return vrf_id;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Get the data pointer of the specified VRF. If not found, create one. */
|
|
|
|
void *vrf_info_get(vrf_id_t vrf_id)
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *vrf = vrf_get(vrf_id, NULL);
|
2015-05-22 11:39:56 +02:00
|
|
|
return vrf->info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look up the data pointer of the specified VRF. */
|
|
|
|
void *vrf_info_lookup(vrf_id_t vrf_id)
|
|
|
|
{
|
2016-11-02 15:16:58 +01:00
|
|
|
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
|
2015-05-22 11:39:56 +02:00
|
|
|
return vrf ? vrf->info : NULL;
|
|
|
|
}
|
|
|
|
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
/*
|
2018-08-24 01:58:36 +02:00
|
|
|
* VRF hash for storing set or not.
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
*/
|
2018-08-24 01:58:36 +02:00
|
|
|
struct vrf_bit_set {
|
|
|
|
vrf_id_t vrf_id;
|
|
|
|
bool set;
|
|
|
|
};
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
2019-05-14 22:19:07 +02:00
|
|
|
static unsigned int vrf_hash_bitmap_key(const void *data)
|
2018-08-24 01:58:36 +02:00
|
|
|
{
|
2019-05-14 22:19:07 +02:00
|
|
|
const struct vrf_bit_set *bit = data;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
return bit->vrf_id;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-17 21:27:12 +02:00
|
|
|
static bool vrf_hash_bitmap_cmp(const void *a, const void *b)
|
2018-08-24 01:58:36 +02:00
|
|
|
{
|
|
|
|
const struct vrf_bit_set *bit1 = a;
|
|
|
|
const struct vrf_bit_set *bit2 = b;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
return bit1->vrf_id == bit2->vrf_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *vrf_hash_bitmap_alloc(void *data)
|
|
|
|
{
|
|
|
|
struct vrf_bit_set *copy = data;
|
|
|
|
struct vrf_bit_set *bit;
|
|
|
|
|
|
|
|
bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
|
|
|
|
bit->vrf_id = copy->vrf_id;
|
|
|
|
|
|
|
|
return bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vrf_hash_bitmap_free(void *data)
|
|
|
|
{
|
|
|
|
struct vrf_bit_set *bit = data;
|
|
|
|
|
|
|
|
XFREE(MTYPE_VRF_BITMAP, bit);
|
|
|
|
}
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
|
|
|
vrf_bitmap_t vrf_bitmap_init(void)
|
|
|
|
{
|
2018-08-24 01:58:36 +02:00
|
|
|
return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
|
|
|
|
"VRF BIT HASH");
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void vrf_bitmap_free(vrf_bitmap_t bmap)
|
|
|
|
{
|
2018-08-24 01:58:36 +02:00
|
|
|
struct hash *vrf_hash = bmap;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
if (vrf_hash == NULL)
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
return;
|
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
hash_clean(vrf_hash, vrf_hash_bitmap_free);
|
|
|
|
hash_free(vrf_hash);
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
2018-08-24 01:58:36 +02:00
|
|
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
|
|
|
struct hash *vrf_hash = bmap;
|
|
|
|
struct vrf_bit_set *bit;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
return;
|
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
|
|
|
bit->set = true;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
2018-08-24 01:58:36 +02:00
|
|
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
|
|
|
struct hash *vrf_hash = bmap;
|
|
|
|
struct vrf_bit_set *bit;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
return;
|
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
|
|
|
|
bit->set = false;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
2018-08-24 01:58:36 +02:00
|
|
|
struct vrf_bit_set lookup = { .vrf_id = vrf_id };
|
|
|
|
struct hash *vrf_hash = bmap;
|
|
|
|
struct vrf_bit_set *bit;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
return 0;
|
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
bit = hash_lookup(vrf_hash, &lookup);
|
|
|
|
if (bit)
|
|
|
|
return bit->set;
|
|
|
|
|
|
|
|
return 0;
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
}
|
|
|
|
|
2017-06-15 19:43:26 +02:00
|
|
|
static void vrf_autocomplete(vector comps, struct cmd_token *token)
|
|
|
|
{
|
|
|
|
struct vrf *vrf = NULL;
|
|
|
|
|
2018-06-22 14:32:01 +02:00
|
|
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
|
|
|
vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
|
2017-06-15 19:43:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct cmd_variable_handler vrf_var_handlers[] = {
|
|
|
|
{
|
2017-06-16 19:09:37 +02:00
|
|
|
.varname = "vrf",
|
2017-06-15 19:43:26 +02:00
|
|
|
.completions = vrf_autocomplete,
|
|
|
|
},
|
2019-09-24 18:51:46 +02:00
|
|
|
{
|
|
|
|
.varname = "vrf_name",
|
|
|
|
.completions = vrf_autocomplete,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.varname = "nexthop_vrf",
|
|
|
|
.completions = vrf_autocomplete,
|
|
|
|
},
|
2017-06-15 19:43:26 +02:00
|
|
|
{.completions = NULL},
|
|
|
|
};
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Initialize VRF module. */
|
2017-05-16 01:31:27 +02:00
|
|
|
void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
|
2019-01-15 19:34:23 +01:00
|
|
|
int (*disable)(struct vrf *), int (*destroy)(struct vrf *),
|
2018-05-29 11:17:10 +02:00
|
|
|
int ((*update)(struct vrf *)))
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
|
|
|
struct vrf *default_vrf;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-02-05 16:23:42 +01:00
|
|
|
/* initialise NS, in case VRF backend if NETNS */
|
|
|
|
ns_init();
|
2016-02-03 15:00:25 +01:00
|
|
|
if (debug_vrf)
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_debug("%s: Initializing VRF subsystem", __func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-05-16 01:31:27 +02:00
|
|
|
vrf_master.vrf_new_hook = create;
|
|
|
|
vrf_master.vrf_enable_hook = enable;
|
|
|
|
vrf_master.vrf_disable_hook = disable;
|
2019-01-15 19:34:23 +01:00
|
|
|
vrf_master.vrf_delete_hook = destroy;
|
2018-05-29 11:17:10 +02:00
|
|
|
vrf_master.vrf_update_name_hook = update;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* The default VRF always exists. */
|
2018-07-04 17:30:14 +02:00
|
|
|
default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
|
2015-05-22 11:39:56 +02:00
|
|
|
if (!default_vrf) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err(EC_LIB_VRF_START,
|
2018-09-13 21:38:57 +02:00
|
|
|
"vrf_init: failed to create the default VRF!");
|
2015-05-22 11:39:56 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2018-08-30 11:42:55 +02:00
|
|
|
if (vrf_is_backend_netns()) {
|
|
|
|
struct ns *ns;
|
|
|
|
|
2018-06-27 18:23:09 +02:00
|
|
|
strlcpy(default_vrf->data.l.netns_name,
|
2018-07-04 17:30:14 +02:00
|
|
|
VRF_DEFAULT_NAME, NS_NAMSIZ);
|
2018-08-30 11:42:55 +02:00
|
|
|
ns = ns_lookup(ns_get_default_id());
|
2018-09-06 07:48:12 +02:00
|
|
|
ns->vrf_ctxt = default_vrf;
|
|
|
|
default_vrf->ns_ctxt = ns;
|
2018-08-30 11:42:55 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
/* Enable the default VRF. */
|
|
|
|
if (!vrf_enable(default_vrf)) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err(EC_LIB_VRF_START,
|
2018-09-13 21:38:57 +02:00
|
|
|
"vrf_init: failed to enable the default VRF!");
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-15 19:43:26 +02:00
|
|
|
cmd_variable_handler_register(vrf_var_handlers);
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Terminate VRF module. */
|
|
|
|
void vrf_terminate(void)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
2016-02-03 15:00:25 +01:00
|
|
|
if (debug_vrf)
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_debug("%s: Shutting down vrf subsystem", __func__);
|
2016-02-03 15:00:25 +01:00
|
|
|
|
2018-02-18 01:02:55 +01:00
|
|
|
while (!RB_EMPTY(vrf_id_head, &vrfs_by_id)) {
|
|
|
|
vrf = RB_ROOT(vrf_id_head, &vrfs_by_id);
|
|
|
|
|
2017-12-04 22:10:09 +01:00
|
|
|
/* Clear configured flag and invoke delete. */
|
|
|
|
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
2016-10-29 18:37:11 +02:00
|
|
|
vrf_delete(vrf);
|
2017-12-04 22:10:09 +01:00
|
|
|
}
|
2018-02-18 01:02:55 +01:00
|
|
|
|
|
|
|
while (!RB_EMPTY(vrf_name_head, &vrfs_by_name)) {
|
|
|
|
vrf = RB_ROOT(vrf_name_head, &vrfs_by_name);
|
|
|
|
|
2017-12-04 22:10:09 +01:00
|
|
|
/* Clear configured flag and invoke delete. */
|
|
|
|
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
2016-10-30 02:44:06 +02:00
|
|
|
vrf_delete(vrf);
|
2017-12-04 22:10:09 +01:00
|
|
|
}
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
2018-02-05 17:28:51 +01:00
|
|
|
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
|
2019-01-04 22:08:10 +01:00
|
|
|
const char *interfacename)
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
{
|
2018-01-26 12:28:27 +01:00
|
|
|
int ret, save_errno, ret2;
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
|
2018-01-26 12:28:27 +01:00
|
|
|
ret = vrf_switch_to_netns(vrf_id);
|
|
|
|
if (ret < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
|
2018-08-06 18:36:50 +02:00
|
|
|
__func__, vrf_id, safe_strerror(errno));
|
2018-06-14 14:23:49 +02:00
|
|
|
|
2016-02-03 15:00:25 +01:00
|
|
|
ret = socket(domain, type, protocol);
|
2018-01-26 12:28:27 +01:00
|
|
|
save_errno = errno;
|
|
|
|
ret2 = vrf_switchback_to_initial();
|
|
|
|
if (ret2 < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: Can't switchback from VRF %u (%s)", __func__,
|
|
|
|
vrf_id, safe_strerror(errno));
|
2018-01-26 12:28:27 +01:00
|
|
|
errno = save_errno;
|
2018-02-05 17:28:51 +01:00
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
ret2 = vrf_bind(vrf_id, ret, interfacename);
|
|
|
|
if (ret2 < 0) {
|
|
|
|
close(ret);
|
|
|
|
ret = ret2;
|
|
|
|
}
|
lib/vrf: enable / disable a VRF
A new API vrf_is_enabled() is defined to check whether a VRF is ready
to use, that is, to allocate resources in that VRF. Currently there's
only one type of resource: socket.
Two new hooks VRF_ENABLE_HOOK/VRF_DISABLE_HOOK are introduced to tell
the user when a VRF gets ready or to be unavailable.
The VRF_ENABLE_HOOK callback is called in the new function vrf_enable(),
which is used to let the VRF be ready to use. Till now, only the default
VRF can be enabled, and we need do nothing to enable the default, except
calling the hook.
The VRF_DISABLE_HOOK callback is called in the new function
vrf_disable(), which is used to let the VRF be unusable. Till now,
it is called only when the VRF is to be deleted.
A new utility vrf_socket() is defined to provide a socket in a given
VRF to the user.
Till now before introducing a way of VRF realization, only the default
VRF is enabled since its birth, and vrf_socket() creates socket for
only the default VRF.
This patch defines the framework of the VRF APIs. The way they serve
the users is:
- vrf_is_enabled() is used to tell the user whether a VRF is usable;
- users are informed by the VRF_ENABLE_HOOK that a VRF gets usable;
they can allocate resources after that;
- users are informed by the VRF_DISABLE_HOOK that a VRF is to be
unavailable, and they must release the resources instantly;
- vrf_socket() is used to provide a socket in a given VRF.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Vincent JARDIN <vincent.jardin@6wind.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
2015-05-22 11:40:08 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-01-22 09:42:53 +01:00
|
|
|
int vrf_is_backend_netns(void)
|
|
|
|
{
|
|
|
|
return (vrf_backend == VRF_BACKEND_NETNS);
|
|
|
|
}
|
|
|
|
|
|
|
|
int vrf_get_backend(void)
|
|
|
|
{
|
2019-02-07 14:55:06 +01:00
|
|
|
if (!vrf_backend_configured)
|
|
|
|
return VRF_BACKEND_UNKNOWN;
|
2018-01-22 09:42:53 +01:00
|
|
|
return vrf_backend;
|
|
|
|
}
|
|
|
|
|
2020-03-03 00:42:56 +01:00
|
|
|
int vrf_configure_backend(enum vrf_backend_type backend)
|
2018-01-22 09:42:53 +01:00
|
|
|
{
|
2020-03-24 18:16:06 +01:00
|
|
|
/* Work around issue in old gcc */
|
|
|
|
switch (backend) {
|
|
|
|
case VRF_BACKEND_UNKNOWN:
|
|
|
|
case VRF_BACKEND_NETNS:
|
|
|
|
case VRF_BACKEND_VRF_LITE:
|
|
|
|
break;
|
|
|
|
default:
|
2020-03-03 00:42:56 +01:00
|
|
|
return -1;
|
2020-03-24 18:16:06 +01:00
|
|
|
}
|
2020-03-03 00:42:56 +01:00
|
|
|
|
|
|
|
vrf_backend = backend;
|
2019-02-07 14:55:06 +01:00
|
|
|
vrf_backend_configured = 1;
|
2020-03-03 00:42:56 +01:00
|
|
|
|
|
|
|
return 0;
|
2018-01-22 09:42:53 +01:00
|
|
|
}
|
|
|
|
|
2018-03-26 12:22:18 +02:00
|
|
|
int vrf_handler_create(struct vty *vty, const char *vrfname,
|
|
|
|
struct vrf **vrf)
|
2016-10-29 02:32:07 +02:00
|
|
|
{
|
|
|
|
struct vrf *vrfp;
|
2020-03-21 22:35:14 +01:00
|
|
|
char xpath_list[XPATH_MAXLEN];
|
|
|
|
int ret;
|
2016-10-29 02:32:07 +02:00
|
|
|
|
2017-01-27 21:16:31 +01:00
|
|
|
if (strlen(vrfname) > VRF_NAMSIZ) {
|
2017-12-13 11:04:31 +01:00
|
|
|
if (vty)
|
|
|
|
vty_out(vty,
|
2018-03-06 20:02:52 +01:00
|
|
|
"%% VRF name %s invalid: length exceeds %d bytes\n",
|
|
|
|
vrfname, VRF_NAMSIZ);
|
2017-12-13 11:04:31 +01:00
|
|
|
else
|
2018-08-20 16:39:44 +02:00
|
|
|
flog_warn(
|
2018-09-13 21:34:28 +02:00
|
|
|
EC_LIB_VRF_LENGTH,
|
2018-03-06 20:02:52 +01:00
|
|
|
"%% VRF name %s invalid: length exceeds %d bytes\n",
|
|
|
|
vrfname, VRF_NAMSIZ);
|
2017-07-13 21:56:08 +02:00
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
2016-10-29 02:32:07 +02:00
|
|
|
}
|
|
|
|
|
2020-03-21 22:35:14 +01:00
|
|
|
if (vty) {
|
|
|
|
snprintf(xpath_list, sizeof(xpath_list),
|
|
|
|
"/frr-vrf:lib/vrf[name='%s']", vrfname);
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
|
|
|
|
ret = nb_cli_apply_changes(vty, xpath_list);
|
|
|
|
if (ret == CMD_SUCCESS) {
|
|
|
|
VTY_PUSH_XPATH(VRF_NODE, xpath_list);
|
lib: introduce configuration back-off timer for YANG-modeled commands
When using the default CLI mode, the northbound layer needs to create
a separate transaction to process each YANG-modeled command since
they are supposed to be applied immediately (there's no candidate
configuration nor the "commit" command like in the transactional
CLI). The problem is that configuration transactions have an overhead
associated to them, in big part because of the use of some heavy
libyang functions like `lyd_validate()` and `lyd_diff()`. As of
now this overhead is substantial and doesn't scale well when large
numbers of transactions need to be performed in sequence.
As an example, loading 50k prefix-lists using a single transaction
takes about 2 seconds on a modern CPU. Loading the same 50k
prefix-lists using 50k transactions can take more than an hour
to complete (which is unacceptable by any standard). To fix this
problem, some heavy optimization work needs to be done on libyang and
on the FRR northbound itself too (e.g. perform partial configuration
diffs whenever possible). This, however, should be a long term
effort since these optimizations shouldn't be trivial to implement
and we're far from having the performance numbers we need.
In the meanwhile, this commit introduces a simple but efficient
workaround to alleviate the issue. In short, a new back-off timer
was introduced in the CLI to monitor and detect when too many
YANG-modeled commands are being received at the same time. When
a certain threshold is reached (100 YANG-modeled commands within
one second), the northbound starts to group all subsequent commands
into a single large transaction, which allows them to be processed
much faster (e.g. seconds and not hours). It's essentially a
protection mechanism that creates dynamically-sized transactions
when necessary to prevent performance issues from happening. This
mechanism is enabled both when parsing configuration files and when
reading commands from a terminal.
The downside of this optimization is that, if several YANG-modeled
commands are grouped into the same transaction and at least one of
them fails, the whole transaction is rejected. This is undesirable
since users don't expect transactional behavior when that's not
enabled explicitly. To minimize this issue, the CLI will log all
commands that were rejected whenever that happens, to make the
user aware of what happened and have enough information to fix
the problem. Commands that fail due to parsing errors or CLI-level
validations in general are rejected separately.
Again, this proposed workaround is intended to be temporary. The
goal is to provided a quick fix to issues like #6658 while we work
on better long-term solutions.
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
2020-07-02 19:43:36 +02:00
|
|
|
nb_cli_pending_commit_check(vty);
|
2020-03-21 22:35:14 +01:00
|
|
|
vrfp = vrf_lookup_by_name(vrfname);
|
|
|
|
if (vrfp)
|
|
|
|
VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
|
2016-10-29 02:32:07 +02:00
|
|
|
|
2020-03-21 22:35:14 +01:00
|
|
|
if (vrf)
|
|
|
|
*vrf = vrfp;
|
|
|
|
}
|
2016-10-29 02:32:07 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-03-06 20:02:52 +01:00
|
|
|
int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
|
2019-10-02 13:34:40 +02:00
|
|
|
ns_id_t ns_id, ns_id_t internal_ns_id,
|
|
|
|
ns_id_t rel_def_ns_id)
|
2018-02-05 16:23:42 +01:00
|
|
|
{
|
|
|
|
struct ns *ns = NULL;
|
|
|
|
|
|
|
|
if (!vrf)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
|
|
|
|
if (vty)
|
|
|
|
vty_out(vty,
|
|
|
|
"VRF %u is already configured with VRF %s\n",
|
|
|
|
vrf->vrf_id, vrf->name);
|
|
|
|
else
|
2019-03-14 19:41:15 +01:00
|
|
|
zlog_info("VRF %u is already configured with VRF %s",
|
2018-02-05 16:23:42 +01:00
|
|
|
vrf->vrf_id, vrf->name);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
if (vrf->ns_ctxt != NULL) {
|
2018-03-06 20:02:52 +01:00
|
|
|
ns = (struct ns *)vrf->ns_ctxt;
|
2018-07-02 18:50:20 +02:00
|
|
|
if (!strcmp(ns->name, pathname)) {
|
2018-02-05 16:23:42 +01:00
|
|
|
if (vty)
|
|
|
|
vty_out(vty,
|
2018-03-06 20:02:52 +01:00
|
|
|
"VRF %u already configured with NETNS %s\n",
|
|
|
|
vrf->vrf_id, ns->name);
|
2018-02-05 16:23:42 +01:00
|
|
|
else
|
2018-08-20 16:39:44 +02:00
|
|
|
zlog_info(
|
2018-08-24 18:26:43 +02:00
|
|
|
"VRF %u already configured with NETNS %s",
|
|
|
|
vrf->vrf_id, ns->name);
|
2018-02-05 16:23:42 +01:00
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ns = ns_lookup_name(pathname);
|
|
|
|
if (ns && ns->vrf_ctxt) {
|
|
|
|
struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
|
|
|
|
|
|
|
|
if (vrf2 == vrf)
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
if (vty)
|
2018-03-06 20:02:52 +01:00
|
|
|
vty_out(vty,
|
2020-03-27 12:35:23 +01:00
|
|
|
"NS %s is already configured with VRF %u(%s)\n",
|
2018-03-06 20:02:52 +01:00
|
|
|
ns->name, vrf2->vrf_id, vrf2->name);
|
2018-02-05 16:23:42 +01:00
|
|
|
else
|
2018-08-20 16:39:44 +02:00
|
|
|
zlog_info("NS %s is already configured with VRF %u(%s)",
|
2018-02-05 16:23:42 +01:00
|
|
|
ns->name, vrf2->vrf_id, vrf2->name);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
ns = ns_get_created(ns, pathname, ns_id);
|
2018-03-26 12:22:18 +02:00
|
|
|
ns->internal_ns_id = internal_ns_id;
|
2019-10-02 13:34:40 +02:00
|
|
|
ns->relative_default_ns = rel_def_ns_id;
|
2018-02-05 16:23:42 +01:00
|
|
|
ns->vrf_ctxt = (void *)vrf;
|
|
|
|
vrf->ns_ctxt = (void *)ns;
|
|
|
|
/* update VRF netns NAME */
|
2018-07-02 18:50:20 +02:00
|
|
|
strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
|
2018-02-05 16:23:42 +01:00
|
|
|
|
|
|
|
if (!ns_enable(ns, vrf_update_vrf_id)) {
|
|
|
|
if (vty)
|
|
|
|
vty_out(vty, "Can not associate NS %u with NETNS %s\n",
|
2018-03-06 20:02:52 +01:00
|
|
|
ns->ns_id, ns->name);
|
2018-02-05 16:23:42 +01:00
|
|
|
else
|
2018-08-20 16:39:44 +02:00
|
|
|
zlog_info("Can not associate NS %u with NETNS %s",
|
2018-02-05 16:23:42 +01:00
|
|
|
ns->ns_id, ns->name);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-12-13 11:04:31 +01:00
|
|
|
/* vrf CLI commands */
|
2018-03-30 04:13:57 +02:00
|
|
|
DEFUN_NOSH(vrf_exit,
|
|
|
|
vrf_exit_cmd,
|
|
|
|
"exit-vrf",
|
|
|
|
"Exit current mode and down to previous mode\n")
|
|
|
|
{
|
|
|
|
/* We have to set vrf context to default vrf */
|
|
|
|
VTY_PUSH_CONTEXT(VRF_NODE, vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME));
|
2020-04-29 23:49:29 +02:00
|
|
|
cmd_exit(vty);
|
2018-03-30 04:13:57 +02:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-07-06 17:47:44 +02:00
|
|
|
DEFUN_YANG_NOSH (vrf,
|
2017-12-13 11:04:31 +01:00
|
|
|
vrf_cmd,
|
|
|
|
"vrf NAME",
|
|
|
|
"Select a VRF to configure\n"
|
|
|
|
"VRF's name\n")
|
|
|
|
{
|
|
|
|
int idx_name = 1;
|
|
|
|
const char *vrfname = argv[idx_name]->arg;
|
|
|
|
|
|
|
|
return vrf_handler_create(vty, vrfname, NULL);
|
|
|
|
}
|
|
|
|
|
2020-07-06 17:47:44 +02:00
|
|
|
DEFUN_YANG (no_vrf,
|
2018-07-09 02:16:47 +02:00
|
|
|
no_vrf_cmd,
|
|
|
|
"no vrf NAME",
|
|
|
|
NO_STR
|
|
|
|
"Delete a pseudo VRF's configuration\n"
|
|
|
|
"VRF's name\n")
|
2016-10-29 02:32:07 +02:00
|
|
|
{
|
2016-12-05 19:43:38 +01:00
|
|
|
const char *vrfname = argv[2]->arg;
|
2020-03-21 22:35:14 +01:00
|
|
|
char xpath_list[XPATH_MAXLEN];
|
2016-12-05 19:43:38 +01:00
|
|
|
|
2016-10-29 02:32:07 +02:00
|
|
|
struct vrf *vrfp;
|
|
|
|
|
2016-12-05 19:43:38 +01:00
|
|
|
vrfp = vrf_lookup_by_name(vrfname);
|
2016-10-29 02:32:07 +02:00
|
|
|
|
2020-07-09 18:20:32 +02:00
|
|
|
if (vrfp == NULL)
|
|
|
|
return CMD_SUCCESS;
|
2016-10-29 02:32:07 +02:00
|
|
|
|
|
|
|
if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
|
2017-07-13 19:12:39 +02:00
|
|
|
vty_out(vty, "%% Only inactive VRFs can be deleted\n");
|
2017-07-13 21:56:08 +02:00
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
2016-10-29 02:32:07 +02:00
|
|
|
}
|
|
|
|
|
2020-03-21 22:35:14 +01:00
|
|
|
snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']",
|
|
|
|
vrfname);
|
2016-10-29 02:32:07 +02:00
|
|
|
|
2020-03-21 22:35:14 +01:00
|
|
|
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
|
|
|
|
return nb_cli_apply_changes(vty, xpath_list);
|
2016-10-29 02:32:07 +02:00
|
|
|
}
|
|
|
|
|
2016-12-05 19:43:38 +01:00
|
|
|
|
2018-09-08 21:46:23 +02:00
|
|
|
static struct cmd_node vrf_node = {
|
2018-09-09 00:15:50 +02:00
|
|
|
.name = "vrf",
|
2018-09-08 21:46:23 +02:00
|
|
|
.node = VRF_NODE,
|
2018-09-08 23:15:09 +02:00
|
|
|
.parent_node = CONFIG_NODE,
|
2018-09-08 21:46:23 +02:00
|
|
|
.prompt = "%s(config-vrf)# ",
|
|
|
|
};
|
2016-12-05 20:04:08 +01:00
|
|
|
|
2018-07-09 02:16:47 +02:00
|
|
|
DEFUN_NOSH (vrf_netns,
|
2018-06-01 16:35:52 +02:00
|
|
|
vrf_netns_cmd,
|
|
|
|
"netns NAME",
|
|
|
|
"Attach VRF to a Namespace\n"
|
|
|
|
"The file name in " NS_RUN_DIR ", or a full pathname\n")
|
2018-02-05 16:23:42 +01:00
|
|
|
{
|
2018-03-13 15:26:03 +01:00
|
|
|
int idx_name = 1, ret;
|
2018-02-05 16:23:42 +01:00
|
|
|
char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
|
|
|
|
|
|
|
|
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
|
|
|
|
|
|
|
if (!pathname)
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
2018-03-13 15:26:03 +01:00
|
|
|
|
2019-08-13 15:47:23 +02:00
|
|
|
frr_with_privs(vrf_daemon_privs) {
|
2018-08-10 18:46:07 +02:00
|
|
|
ret = vrf_netns_handler_create(vty, vrf, pathname,
|
2019-10-02 13:34:40 +02:00
|
|
|
NS_UNKNOWN,
|
|
|
|
NS_UNKNOWN,
|
|
|
|
NS_UNKNOWN);
|
2018-08-10 18:46:07 +02:00
|
|
|
}
|
2018-03-13 15:26:03 +01:00
|
|
|
return ret;
|
2018-02-05 16:23:42 +01:00
|
|
|
}
|
|
|
|
|
2018-07-09 02:16:47 +02:00
|
|
|
DEFUN_NOSH (no_vrf_netns,
|
2018-02-05 16:23:42 +01:00
|
|
|
no_vrf_netns_cmd,
|
|
|
|
"no netns [NAME]",
|
|
|
|
NO_STR
|
|
|
|
"Detach VRF from a Namespace\n"
|
|
|
|
"The file name in " NS_RUN_DIR ", or a full pathname\n")
|
|
|
|
{
|
|
|
|
struct ns *ns = NULL;
|
|
|
|
|
|
|
|
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
|
|
|
|
|
|
|
if (!vrf_is_backend_netns()) {
|
|
|
|
vty_out(vty, "VRF backend is not Netns. Aborting\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
if (!vrf->ns_ctxt) {
|
|
|
|
vty_out(vty, "VRF %s(%u) is not configured with NetNS\n",
|
|
|
|
vrf->name, vrf->vrf_id);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
ns = (struct ns *)vrf->ns_ctxt;
|
|
|
|
|
|
|
|
ns->vrf_ctxt = NULL;
|
|
|
|
vrf_disable(vrf);
|
|
|
|
/* vrf ID from VRF is necessary for Zebra
|
|
|
|
* so that propagate to other clients is done
|
|
|
|
*/
|
|
|
|
ns_delete(ns);
|
|
|
|
vrf->ns_ctxt = NULL;
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2016-02-03 15:00:25 +01:00
|
|
|
/*
|
|
|
|
* Debug CLI for vrf's
|
|
|
|
*/
|
|
|
|
DEFUN (vrf_debug,
|
|
|
|
vrf_debug_cmd,
|
|
|
|
"debug vrf",
|
|
|
|
DEBUG_STR
|
|
|
|
"VRF Debugging\n")
|
|
|
|
{
|
|
|
|
debug_vrf = 1;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_vrf_debug,
|
|
|
|
no_vrf_debug_cmd,
|
|
|
|
"no debug vrf",
|
|
|
|
NO_STR
|
|
|
|
DEBUG_STR
|
|
|
|
"VRF Debugging\n")
|
|
|
|
{
|
|
|
|
debug_vrf = 0;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int vrf_write_host(struct vty *vty)
|
|
|
|
{
|
|
|
|
if (debug_vrf)
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, "debug vrf\n");
|
2016-02-03 15:00:25 +01:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-08 22:31:43 +02:00
|
|
|
static int vrf_write_host(struct vty *vty);
|
2018-09-08 21:46:23 +02:00
|
|
|
static struct cmd_node vrf_debug_node = {
|
2018-09-09 00:15:50 +02:00
|
|
|
.name = "vrf debug",
|
2018-09-08 21:46:23 +02:00
|
|
|
.node = VRF_DEBUG_NODE,
|
|
|
|
.prompt = "",
|
2018-09-08 22:31:43 +02:00
|
|
|
.config_write = vrf_write_host,
|
2018-09-08 21:46:23 +02:00
|
|
|
};
|
2016-02-03 15:00:25 +01:00
|
|
|
|
|
|
|
void vrf_install_commands(void)
|
|
|
|
{
|
2018-09-08 22:31:43 +02:00
|
|
|
install_node(&vrf_debug_node);
|
2016-02-03 15:00:25 +01:00
|
|
|
|
|
|
|
install_element(CONFIG_NODE, &vrf_debug_cmd);
|
|
|
|
install_element(ENABLE_NODE, &vrf_debug_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_vrf_debug_cmd);
|
|
|
|
install_element(ENABLE_NODE, &no_vrf_debug_cmd);
|
|
|
|
}
|
2016-12-05 19:43:38 +01:00
|
|
|
|
2018-03-13 15:26:03 +01:00
|
|
|
void vrf_cmd_init(int (*writefunc)(struct vty *vty),
|
|
|
|
struct zebra_privs_t *daemon_privs)
|
2016-12-05 20:04:08 +01:00
|
|
|
{
|
2016-12-05 19:43:38 +01:00
|
|
|
install_element(CONFIG_NODE, &vrf_cmd);
|
|
|
|
install_element(CONFIG_NODE, &no_vrf_cmd);
|
2018-09-08 22:31:43 +02:00
|
|
|
vrf_node.config_write = writefunc;
|
|
|
|
install_node(&vrf_node);
|
2016-12-05 20:04:08 +01:00
|
|
|
install_default(VRF_NODE);
|
2018-03-30 04:13:57 +02:00
|
|
|
install_element(VRF_NODE, &vrf_exit_cmd);
|
2018-02-05 16:23:42 +01:00
|
|
|
if (vrf_is_backend_netns() && ns_have_netns()) {
|
|
|
|
/* Install NS commands. */
|
2018-03-13 15:26:03 +01:00
|
|
|
vrf_daemon_privs = daemon_privs;
|
2018-02-05 16:23:42 +01:00
|
|
|
install_element(VRF_NODE, &vrf_netns_cmd);
|
|
|
|
install_element(VRF_NODE, &no_vrf_netns_cmd);
|
|
|
|
}
|
2016-02-03 15:00:25 +01:00
|
|
|
}
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
|
2018-11-21 14:46:08 +01:00
|
|
|
void vrf_set_default_name(const char *default_name, bool force)
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
{
|
2018-06-22 13:54:47 +02:00
|
|
|
struct vrf *def_vrf;
|
2018-11-21 14:46:08 +01:00
|
|
|
static bool def_vrf_forced;
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
|
2018-06-22 13:54:47 +02:00
|
|
|
def_vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
|
|
|
assert(default_name);
|
2018-11-21 14:46:08 +01:00
|
|
|
if (def_vrf && !force && def_vrf_forced) {
|
|
|
|
zlog_debug("VRF: %s, avoid changing name to %s, previously forced (%u)",
|
|
|
|
def_vrf->name, default_name,
|
|
|
|
def_vrf->vrf_id);
|
|
|
|
return;
|
|
|
|
}
|
2019-06-14 13:52:00 +02:00
|
|
|
if (strmatch(vrf_default_name, default_name))
|
|
|
|
return;
|
2018-06-22 13:54:47 +02:00
|
|
|
snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
|
|
|
|
if (def_vrf) {
|
2018-11-21 14:46:08 +01:00
|
|
|
if (force)
|
|
|
|
def_vrf_forced = true;
|
2018-06-22 13:54:47 +02:00
|
|
|
RB_REMOVE(vrf_name_head, &vrfs_by_name, def_vrf);
|
|
|
|
strlcpy(def_vrf->data.l.netns_name,
|
|
|
|
vrf_default_name, NS_NAMSIZ);
|
|
|
|
strlcpy(def_vrf->name, vrf_default_name, sizeof(def_vrf->name));
|
|
|
|
RB_INSERT(vrf_name_head, &vrfs_by_name, def_vrf);
|
2018-05-29 11:17:10 +02:00
|
|
|
if (vrf_master.vrf_update_name_hook)
|
|
|
|
(*vrf_master.vrf_update_name_hook)(def_vrf);
|
2018-06-22 13:54:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *vrf_get_default_name(void)
|
|
|
|
{
|
|
|
|
return vrf_default_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
vrf_id_t vrf_get_default_id(void)
|
|
|
|
{
|
2018-03-26 12:22:18 +02:00
|
|
|
/* backend netns is only known by zebra
|
|
|
|
* for other daemons, we return VRF_DEFAULT_INTERNAL
|
|
|
|
*/
|
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being
assigned a NSID. This avoids the need to handle the case where if the
incoming NSID was 0 for a non default VRF, then a specific handling had
to be done to keep 0 value for default VRF.
In most cases, as the first NETNS to get a NSID will be the default VRF,
most probably the default VRF will be assigned to 0, while the other
ones will have their value incremented. On some cases, where the NSID is
already assigned for NETNS, including default VRF, then the default VRF
value will be the one derived from the NSID of default VRF, thus keeping
consistency between VRF IDs and NETNS IDs.
Default NS is attempted to be created. Actually, some VMs may have the
netns feature, but the NS initialisation fails because that folder is
not present.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2018-01-16 13:59:58 +01:00
|
|
|
if (vrf_is_backend_netns())
|
|
|
|
return ns_get_default_id();
|
|
|
|
else
|
|
|
|
return VRF_DEFAULT_INTERNAL;
|
|
|
|
}
|
2018-01-26 12:28:27 +01:00
|
|
|
|
2019-01-04 22:08:10 +01:00
|
|
|
int vrf_bind(vrf_id_t vrf_id, int fd, const char *name)
|
2018-02-05 17:28:51 +01:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2019-04-23 17:31:42 +02:00
|
|
|
struct interface *ifp;
|
2018-02-05 17:28:51 +01:00
|
|
|
|
2019-06-24 01:46:39 +02:00
|
|
|
if (fd < 0 || name == NULL)
|
2018-02-05 17:28:51 +01:00
|
|
|
return fd;
|
2019-04-23 17:31:42 +02:00
|
|
|
/* the device should exist
|
|
|
|
* otherwise we should return
|
|
|
|
* case ifname = vrf in netns mode => return
|
|
|
|
*/
|
2019-06-24 01:46:39 +02:00
|
|
|
ifp = if_lookup_by_name(name, vrf_id);
|
2019-04-23 17:31:42 +02:00
|
|
|
if (!ifp)
|
2018-02-05 17:28:51 +01:00
|
|
|
return fd;
|
|
|
|
#ifdef SO_BINDTODEVICE
|
2018-05-06 17:25:58 +02:00
|
|
|
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
|
2018-02-05 17:28:51 +01:00
|
|
|
if (ret < 0)
|
2018-03-06 20:02:52 +01:00
|
|
|
zlog_debug("bind to interface %s failed, errno=%d", name,
|
|
|
|
errno);
|
2018-02-05 17:28:51 +01:00
|
|
|
#endif /* SO_BINDTODEVICE */
|
|
|
|
return ret;
|
|
|
|
}
|
2018-01-26 12:28:27 +01:00
|
|
|
int vrf_getaddrinfo(const char *node, const char *service,
|
2018-03-06 20:02:52 +01:00
|
|
|
const struct addrinfo *hints, struct addrinfo **res,
|
|
|
|
vrf_id_t vrf_id)
|
2018-01-26 12:28:27 +01:00
|
|
|
{
|
|
|
|
int ret, ret2, save_errno;
|
|
|
|
|
|
|
|
ret = vrf_switch_to_netns(vrf_id);
|
|
|
|
if (ret < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
|
2018-08-06 18:36:50 +02:00
|
|
|
__func__, vrf_id, safe_strerror(errno));
|
2018-01-26 12:28:27 +01:00
|
|
|
ret = getaddrinfo(node, service, hints, res);
|
|
|
|
save_errno = errno;
|
|
|
|
ret2 = vrf_switchback_to_initial();
|
|
|
|
if (ret2 < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: Can't switchback from VRF %u (%s)", __func__,
|
|
|
|
vrf_id, safe_strerror(errno));
|
2018-01-26 12:28:27 +01:00
|
|
|
errno = save_errno;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-02-05 17:00:45 +01:00
|
|
|
int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
|
|
|
|
{
|
|
|
|
int ret, saved_errno, rc;
|
|
|
|
|
|
|
|
ret = vrf_switch_to_netns(vrf_id);
|
|
|
|
if (ret < 0) {
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
|
2018-08-06 18:36:50 +02:00
|
|
|
__func__, vrf_id, safe_strerror(errno));
|
2018-02-05 17:00:45 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
rc = ioctl(d, request, params);
|
|
|
|
saved_errno = errno;
|
|
|
|
ret = vrf_switchback_to_initial();
|
|
|
|
if (ret < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: Can't switchback from VRF %u (%s)", __func__,
|
|
|
|
vrf_id, safe_strerror(errno));
|
2018-02-05 17:00:45 +01:00
|
|
|
errno = saved_errno;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2018-02-05 17:28:51 +01:00
|
|
|
int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
|
2019-01-04 22:08:10 +01:00
|
|
|
const char *interfacename)
|
2018-01-26 12:28:27 +01:00
|
|
|
{
|
|
|
|
int ret, save_errno, ret2;
|
|
|
|
|
|
|
|
ret = vrf_switch_to_netns(vrf_id);
|
|
|
|
if (ret < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
|
2018-08-06 18:36:50 +02:00
|
|
|
__func__, vrf_id, safe_strerror(errno));
|
2018-01-26 12:28:27 +01:00
|
|
|
ret = sockunion_socket(su);
|
|
|
|
save_errno = errno;
|
|
|
|
ret2 = vrf_switchback_to_initial();
|
|
|
|
if (ret2 < 0)
|
2018-09-13 21:34:28 +02:00
|
|
|
flog_err_sys(EC_LIB_SOCKET,
|
2018-08-06 18:36:50 +02:00
|
|
|
"%s: Can't switchback from VRF %u (%s)", __func__,
|
|
|
|
vrf_id, safe_strerror(errno));
|
2018-01-26 12:28:27 +01:00
|
|
|
errno = save_errno;
|
2018-02-05 17:28:51 +01:00
|
|
|
|
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
ret2 = vrf_bind(vrf_id, ret, interfacename);
|
|
|
|
if (ret2 < 0) {
|
|
|
|
close(ret);
|
|
|
|
ret = ret2;
|
|
|
|
}
|
2018-01-26 12:28:27 +01:00
|
|
|
return ret;
|
|
|
|
}
|
2018-10-11 18:37:01 +02:00
|
|
|
|
|
|
|
vrf_id_t vrf_generate_id(void)
|
|
|
|
{
|
|
|
|
static int vrf_id_local;
|
|
|
|
|
|
|
|
return ++vrf_id_local;
|
|
|
|
}
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
/* ------- Northbound callbacks ------- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XPath: /frr-vrf:lib/vrf
|
|
|
|
*/
|
2020-04-04 18:38:51 +02:00
|
|
|
static int lib_vrf_create(struct nb_cb_create_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
|
|
|
const char *vrfname;
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
vrfname = yang_dnode_get_string(args->dnode, "./name");
|
2020-03-11 02:20:49 +01:00
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
if (args->event != NB_EV_APPLY)
|
2020-03-11 02:20:49 +01:00
|
|
|
return NB_OK;
|
|
|
|
|
|
|
|
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
nb_running_set_entry(args->dnode, vrfp);
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
static int lib_vrf_destroy(struct nb_cb_destroy_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
switch (args->event) {
|
2020-03-11 02:20:49 +01:00
|
|
|
case NB_EV_VALIDATE:
|
2020-04-04 18:38:51 +02:00
|
|
|
vrfp = nb_running_get_entry(args->dnode, NULL, true);
|
2020-03-11 02:20:49 +01:00
|
|
|
if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
|
2020-05-15 02:34:12 +02:00
|
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
|
|
"Only inactive VRFs can be deleted");
|
2020-03-11 02:20:49 +01:00
|
|
|
return NB_ERR_VALIDATION;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NB_EV_PREPARE:
|
|
|
|
case NB_EV_ABORT:
|
|
|
|
break;
|
|
|
|
case NB_EV_APPLY:
|
2020-04-04 18:38:51 +02:00
|
|
|
vrfp = nb_running_unset_entry(args->dnode);
|
2020-03-21 22:35:14 +01:00
|
|
|
|
2020-03-11 02:20:49 +01:00
|
|
|
/* Clear configured flag and invoke delete. */
|
|
|
|
UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
|
|
|
|
vrf_delete(vrfp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
static const void *lib_vrf_get_next(struct nb_cb_get_next_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
2020-04-04 18:38:51 +02:00
|
|
|
struct vrf *vrfp = (struct vrf *)args->list_entry;
|
2020-03-11 02:20:49 +01:00
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
if (args->list_entry == NULL) {
|
2020-03-11 02:20:49 +01:00
|
|
|
vrfp = RB_MIN(vrf_name_head, &vrfs_by_name);
|
|
|
|
} else {
|
|
|
|
vrfp = RB_NEXT(vrf_name_head, vrfp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return vrfp;
|
|
|
|
}
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
static int lib_vrf_get_keys(struct nb_cb_get_keys_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
2020-04-04 18:38:51 +02:00
|
|
|
struct vrf *vrfp = (struct vrf *)args->list_entry;
|
2020-03-11 02:20:49 +01:00
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
args->keys->num = 1;
|
|
|
|
strlcpy(args->keys->key[0], vrfp->name, sizeof(args->keys->key[0]));
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
2020-04-04 18:38:51 +02:00
|
|
|
const char *vrfname = args->keys->key[0];
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
struct vrf *vrf = vrf_lookup_by_name(vrfname);
|
|
|
|
|
|
|
|
return vrf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XPath: /frr-vrf:lib/vrf/id
|
|
|
|
*/
|
2020-04-04 18:38:51 +02:00
|
|
|
static struct yang_data *
|
|
|
|
lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
2020-04-04 18:38:51 +02:00
|
|
|
struct vrf *vrfp = (struct vrf *)args->list_entry;
|
2020-03-11 02:20:49 +01:00
|
|
|
|
2020-04-04 18:38:51 +02:00
|
|
|
return yang_data_new_uint32(args->xpath, vrfp->vrf_id);
|
2020-03-11 02:20:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XPath: /frr-vrf:lib/vrf/active
|
|
|
|
*/
|
2020-04-04 18:38:51 +02:00
|
|
|
static struct yang_data *
|
|
|
|
lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
|
2020-03-11 02:20:49 +01:00
|
|
|
{
|
2020-04-04 18:38:51 +02:00
|
|
|
struct vrf *vrfp = (struct vrf *)args->list_entry;
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
if (vrfp->status == VRF_ACTIVE)
|
|
|
|
return yang_data_new_bool(
|
2020-04-04 18:38:51 +02:00
|
|
|
args->xpath, vrfp->status == VRF_ACTIVE ? true : false);
|
2020-03-11 02:20:49 +01:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clang-format off */
|
|
|
|
const struct frr_yang_module_info frr_vrf_info = {
|
|
|
|
.name = "frr-vrf",
|
|
|
|
.nodes = {
|
|
|
|
{
|
|
|
|
.xpath = "/frr-vrf:lib/vrf",
|
|
|
|
.cbs = {
|
|
|
|
.create = lib_vrf_create,
|
|
|
|
.destroy = lib_vrf_destroy,
|
|
|
|
.get_next = lib_vrf_get_next,
|
|
|
|
.get_keys = lib_vrf_get_keys,
|
|
|
|
.lookup_entry = lib_vrf_lookup_entry,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.xpath = "/frr-vrf:lib/vrf/state/id",
|
|
|
|
.cbs = {
|
|
|
|
.get_elem = lib_vrf_state_id_get_elem,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.xpath = "/frr-vrf:lib/vrf/state/active",
|
|
|
|
.cbs = {
|
|
|
|
.get_elem = lib_vrf_state_active_get_elem,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.xpath = NULL,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|