2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2015-05-22 11:39:56 +02:00
|
|
|
/*
|
|
|
|
* VRF functions.
|
|
|
|
* Copyright (C) 2014 6WIND S.A.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
2024-01-04 20:42:17 +01:00
|
|
|
#include <sys/ioctl.h>
|
2015-05-22 11:39:56 +02:00
|
|
|
|
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
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
/* Set by the owner (zebra). */
|
|
|
|
bool vrf_notify_oper_changes;
|
|
|
|
|
2020-08-24 18:01:15 +02:00
|
|
|
/* default VRF name value used when VRF backend is not NETNS */
|
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
|
|
|
|
2024-12-26 22:08:21 +01:00
|
|
|
static int vrf_backend = VRF_BACKEND_VRF_LITE;
|
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 *);
|
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
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
static void vrf_update_state(struct vrf *vrf)
|
|
|
|
{
|
|
|
|
if (!vrf->state || !vrf_notify_oper_changes)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove top level container update when we have patch support, for now
|
|
|
|
* this keeps us from generating 2 separate REPLACE messages though.
|
|
|
|
*/
|
|
|
|
nb_op_updatef(vrf->state, "id", "%u", vrf->vrf_id);
|
|
|
|
nb_op_update(vrf->state, "active", CHECK_FLAG(vrf->status, VRF_ACTIVE) ? "true" : "false");
|
|
|
|
}
|
|
|
|
|
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)) {
|
2025-01-08 15:57:10 +01:00
|
|
|
/* vrf name has changed */
|
|
|
|
if (vrf_notify_oper_changes) {
|
|
|
|
nb_op_update_delete_pathf(NULL, "/frr-vrf:lib/vrf[name=\"%s\"]", vrf->name);
|
|
|
|
lyd_free_all(vrf->state);
|
|
|
|
}
|
2016-10-30 02:44:06 +02:00
|
|
|
RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
|
2025-01-08 15:57:10 +01: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);
|
2025-01-08 15:57:10 +01:00
|
|
|
/* New state with new name */
|
|
|
|
if (vrf_notify_oper_changes)
|
|
|
|
vrf->state = nb_op_update_pathf(NULL, "/frr-vrf:lib/vrf[name=\"%s\"]/state",
|
|
|
|
NULL, vrf->name);
|
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);
|
2025-01-08 15:57:10 +01:00
|
|
|
|
|
|
|
/* We have a name now so we can have state */
|
|
|
|
if (vrf_notify_oper_changes)
|
|
|
|
vrf->state = nb_op_update_pathf(NULL, "/frr-vrf:lib/vrf[name=\"%s\"]/state",
|
|
|
|
NULL, vrf->name);
|
2016-04-21 18:15:07 +02:00
|
|
|
}
|
2025-01-08 15:57:10 +01:00
|
|
|
/* Update state before hook call */
|
|
|
|
if (vrf->state)
|
|
|
|
vrf_update_state(vrf);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-11-12 13:37:30 +01:00
|
|
|
/* Update a VRF. If not found, create one.
|
|
|
|
* Arg:
|
|
|
|
* name - The name of the vrf.
|
|
|
|
* vrf_id - The vrf_id of the vrf.
|
|
|
|
* Description: This function first finds the vrf using its name. If the vrf is
|
|
|
|
* found and the vrf-id of the existing vrf does not match the new vrf id, it
|
|
|
|
* will disable the existing vrf and update it with new vrf-id. If the vrf is
|
|
|
|
* not found, it will create the vrf with given name and the new vrf id.
|
|
|
|
*/
|
|
|
|
struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrf = NULL;
|
|
|
|
|
|
|
|
/*Treat VRF add for existing vrf as update
|
|
|
|
* Update VRF ID and also update in VRF ID table
|
|
|
|
*/
|
|
|
|
if (name)
|
|
|
|
vrf = vrf_lookup_by_name(name);
|
|
|
|
if (vrf && new_vrf_id != VRF_UNKNOWN && vrf->vrf_id != VRF_UNKNOWN
|
|
|
|
&& vrf->vrf_id != new_vrf_id) {
|
|
|
|
if (debug_vrf) {
|
|
|
|
zlog_debug(
|
|
|
|
"Vrf Update event: %s old id: %u, new id: %u",
|
|
|
|
name, vrf->vrf_id, new_vrf_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Disable the vrf to simulate implicit delete
|
|
|
|
* so that all stale routes are deleted
|
|
|
|
* This vrf will be enabled down the line
|
|
|
|
*/
|
|
|
|
vrf_disable(vrf);
|
|
|
|
|
|
|
|
|
|
|
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
vrf->vrf_id = new_vrf_id;
|
|
|
|
RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
vrf_update_state(vrf);
|
2020-11-12 13:37:30 +01:00
|
|
|
} else {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vrf_get is implied creation if it does not exist
|
|
|
|
*/
|
|
|
|
vrf = vrf_get(new_vrf_id, name);
|
|
|
|
}
|
|
|
|
return 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
|
|
|
/* 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);
|
|
|
|
|
2021-10-13 14:06:38 +02:00
|
|
|
if (vrf->vrf_id != VRF_UNKNOWN) {
|
|
|
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
|
|
|
vrf->vrf_id = VRF_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
*: 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.
|
|
|
|
*/
|
2021-11-02 21:54:43 +01:00
|
|
|
if (vrf_is_user_cfged(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
|
|
|
return;
|
|
|
|
|
2021-10-13 14:06:38 +02:00
|
|
|
/* Do not delete the VRF if it has interfaces configured in it. */
|
|
|
|
if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
|
|
|
|
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);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
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
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
if (vrf_notify_oper_changes) {
|
|
|
|
nb_op_update_delete_pathf(NULL, "/frr-vrf:lib/vrf[name=\"%s\"]", vrf->name);
|
|
|
|
lyd_free_all(vrf->state);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
vrf_update_state(vrf);
|
|
|
|
|
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
|
|
|
|
2025-01-08 15:57:10 +01:00
|
|
|
vrf_update_state(vrf);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-02-28 20:34:06 +01:00
|
|
|
void vrf_iterate(vrf_iter_func fnc)
|
|
|
|
{
|
|
|
|
struct vrf *vrf, *tmp;
|
|
|
|
|
|
|
|
if (debug_vrf)
|
|
|
|
zlog_debug("%s: vrf subsystem iteration", __func__);
|
|
|
|
|
|
|
|
RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) {
|
|
|
|
if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
fnc(vrf);
|
|
|
|
}
|
|
|
|
|
|
|
|
RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) {
|
|
|
|
if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
fnc(vrf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally process default VRF */
|
|
|
|
vrf = vrf_lookup_by_id(VRF_DEFAULT);
|
|
|
|
if (vrf)
|
|
|
|
fnc(vrf);
|
|
|
|
}
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
const char *vrf_id_to_name(vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
2020-08-26 16:26:49 +02:00
|
|
|
if (vrf_id == VRF_DEFAULT)
|
|
|
|
return VRF_DEFAULT_NAME;
|
|
|
|
|
2017-10-08 03:49:27 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* 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
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
void vrf_bitmap_init(vrf_bitmap_t *pbmap)
|
*: 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
|
|
|
{
|
2023-04-19 14:13:18 +02:00
|
|
|
*pbmap = 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
|
|
|
}
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
void vrf_bitmap_free(vrf_bitmap_t *pbmap)
|
*: 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
|
|
|
{
|
2023-04-19 14:13:18 +02:00
|
|
|
struct hash *vrf_hash;
|
|
|
|
|
|
|
|
if (!*pbmap)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vrf_hash = *pbmap;
|
*: 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
|
|
|
|
2023-03-21 13:54:21 +01:00
|
|
|
hash_clean_and_free(&vrf_hash, vrf_hash_bitmap_free);
|
*: 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
|
|
|
}
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
void vrf_bitmap_set(vrf_bitmap_t *pbmap, vrf_id_t vrf_id)
|
*: 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 lookup = { .vrf_id = vrf_id };
|
2023-04-19 14:13:18 +02:00
|
|
|
struct hash *vrf_hash;
|
2018-08-24 01:58:36 +02:00
|
|
|
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
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
if (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;
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
if (!*pbmap)
|
|
|
|
*pbmap = vrf_hash =
|
|
|
|
hash_create_size(2, vrf_hash_bitmap_key,
|
|
|
|
vrf_hash_bitmap_cmp, "VRF BIT HASH");
|
|
|
|
else
|
|
|
|
vrf_hash = *pbmap;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
void vrf_bitmap_unset(vrf_bitmap_t *pbmap, vrf_id_t vrf_id)
|
*: 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 lookup = { .vrf_id = vrf_id };
|
2023-04-19 14:13:18 +02:00
|
|
|
struct hash *vrf_hash;
|
2018-08-24 01:58:36 +02:00
|
|
|
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
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
if (vrf_id == VRF_UNKNOWN)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the hash is not created then unsetting is unnecessary
|
|
|
|
*/
|
|
|
|
if (!*pbmap)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vrf_hash = *pbmap;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we can't look it up, no need to unset it!
|
|
|
|
*/
|
|
|
|
bit = hash_lookup(vrf_hash, &lookup);
|
|
|
|
if (!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
|
|
|
return;
|
|
|
|
|
2018-08-24 01:58:36 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
int vrf_bitmap_check(vrf_bitmap_t *pbmap, vrf_id_t vrf_id)
|
*: 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 lookup = { .vrf_id = vrf_id };
|
2023-04-19 14:13:18 +02:00
|
|
|
struct hash *vrf_hash;
|
2018-08-24 01:58:36 +02:00
|
|
|
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
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
if (!*pbmap || 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;
|
|
|
|
|
2023-04-19 14:13:18 +02:00
|
|
|
vrf_hash = *pbmap;
|
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 *),
|
*: rework renaming the default VRF
Currently, it is possible to rename the default VRF either by passing
`-o` option to zebra or by creating a file in `/var/run/netns` and
binding it to `/proc/self/ns/net`.
In both cases, only zebra knows about the rename and other daemons learn
about it only after they connect to zebra. This is a problem, because
daemons may read their config before they connect to zebra. To handle
this rename after the config is read, we have some special code in every
single daemon, which is not very bad but not desirable in my opinion.
But things are getting worse when we need to handle this in northbound
layer as we have to manually rewrite the config nodes. This approach is
already hacky, but still works as every daemon handles its own NB
structures. But it is completely incompatible with the central
management daemon architecture we are aiming for, as mgmtd doesn't even
have a connection with zebra to learn from it. And it shouldn't have it,
because operational state changes should never affect configuration.
To solve the problem and simplify the code, I propose to expand the `-o`
option to all daemons. By using the startup option, we let daemons know
about the rename before they read their configs so we don't need any
special code to deal with it. There's an easy way to pass the option to
all daemons by using `frr_global_options` variable.
Unfortunately, the second way of renaming by creating a file in
`/var/run/netns` is incompatible with the new mgmtd architecture.
Theoretically, we could force daemons to read their configs only after
they connect to zebra, but it means adding even more code to handle a
very specific use-case. And anyway this won't work for mgmtd as it
doesn't have a connection with zebra. So I had to remove this option.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-12-03 23:22:55 +01:00
|
|
|
int (*disable)(struct vrf *), int (*destroy)(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;
|
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);
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2021-06-10 22:52:35 +02:00
|
|
|
static void vrf_terminate_single(struct vrf *vrf)
|
|
|
|
{
|
|
|
|
/* Clear configured flag and invoke delete. */
|
2022-11-22 23:18:02 +01:00
|
|
|
vrf_disable(vrf);
|
2021-06-10 22:52:35 +02:00
|
|
|
UNSET_FLAG(vrf->status, VRF_CONFIGURED);
|
2021-10-13 14:06:38 +02:00
|
|
|
if_terminate(vrf);
|
2021-11-05 23:22:07 +01:00
|
|
|
vrf_delete(vrf);
|
2021-06-10 22:52:35 +02:00
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
void vrf_terminate(void)
|
|
|
|
{
|
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
|
|
|
|
2024-02-28 20:34:06 +01:00
|
|
|
vrf_iterate(vrf_terminate_single);
|
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)
|
|
|
|
{
|
|
|
|
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_NETNS:
|
|
|
|
case VRF_BACKEND_VRF_LITE:
|
|
|
|
break;
|
2023-01-30 16:06:29 +01:00
|
|
|
case VRF_BACKEND_MAX:
|
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;
|
|
|
|
|
|
|
|
return 0;
|
2018-01-22 09:42:53 +01:00
|
|
|
}
|
|
|
|
|
2017-12-13 11:04:31 +01:00
|
|
|
/* vrf CLI commands */
|
2024-04-16 21:10:45 +02:00
|
|
|
DEFUN_YANG_NOSH (vrf_exit,
|
2018-03-30 04:13:57 +02:00
|
|
|
vrf_exit_cmd,
|
|
|
|
"exit-vrf",
|
|
|
|
"Exit current mode and down to previous mode\n")
|
|
|
|
{
|
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;
|
2021-10-18 22:34:02 +02:00
|
|
|
char xpath_list[XPATH_MAXLEN];
|
|
|
|
struct vrf *vrf;
|
|
|
|
int ret;
|
2017-12-13 11:04:31 +01:00
|
|
|
|
2021-10-18 22:34:02 +02:00
|
|
|
if (strlen(vrfname) > VRF_NAMSIZ) {
|
|
|
|
vty_out(vty,
|
|
|
|
"%% VRF name %s invalid: length exceeds %d bytes\n",
|
|
|
|
vrfname, VRF_NAMSIZ);
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
|
|
|
|
|
|
|
|
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
|
2023-01-26 14:56:04 +01:00
|
|
|
ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
|
2021-10-18 22:34:02 +02:00
|
|
|
if (ret == CMD_SUCCESS) {
|
|
|
|
VTY_PUSH_XPATH(VRF_NODE, xpath_list);
|
|
|
|
vrf = vrf_lookup_by_name(vrfname);
|
|
|
|
if (vrf)
|
|
|
|
VTY_PUSH_CONTEXT(VRF_NODE, vrf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2017-12-13 11:04:31 +01:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2021-06-21 17:04:46 +02:00
|
|
|
if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
|
|
|
|
/*
|
2021-11-08 11:33:03 +01:00
|
|
|
* Remove the VRF interface config when removing the VRF.
|
2021-06-21 17:04:46 +02:00
|
|
|
*/
|
|
|
|
snprintf(xpath_list, sizeof(xpath_list),
|
2021-11-08 11:33:03 +01:00
|
|
|
"/frr-interface:lib/interface[name='%s']", vrfname);
|
2021-06-21 17:04:46 +02:00
|
|
|
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
|
|
|
|
}
|
|
|
|
|
2021-02-16 10:57:30 +01:00
|
|
|
snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, 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);
|
2021-06-21 17:04:46 +02:00
|
|
|
return nb_cli_apply_changes(vty, NULL);
|
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
|
|
|
|
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
|
|
|
|
2021-08-25 18:29:42 +02:00
|
|
|
void vrf_cmd_init(int (*writefunc)(struct vty *vty))
|
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);
|
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
|
|
|
|
*: rework renaming the default VRF
Currently, it is possible to rename the default VRF either by passing
`-o` option to zebra or by creating a file in `/var/run/netns` and
binding it to `/proc/self/ns/net`.
In both cases, only zebra knows about the rename and other daemons learn
about it only after they connect to zebra. This is a problem, because
daemons may read their config before they connect to zebra. To handle
this rename after the config is read, we have some special code in every
single daemon, which is not very bad but not desirable in my opinion.
But things are getting worse when we need to handle this in northbound
layer as we have to manually rewrite the config nodes. This approach is
already hacky, but still works as every daemon handles its own NB
structures. But it is completely incompatible with the central
management daemon architecture we are aiming for, as mgmtd doesn't even
have a connection with zebra to learn from it. And it shouldn't have it,
because operational state changes should never affect configuration.
To solve the problem and simplify the code, I propose to expand the `-o`
option to all daemons. By using the startup option, we let daemons know
about the rename before they read their configs so we don't need any
special code to deal with it. There's an easy way to pass the option to
all daemons by using `frr_global_options` variable.
Unfortunately, the second way of renaming by creating a file in
`/var/run/netns` is incompatible with the new mgmtd architecture.
Theoretically, we could force daemons to read their configs only after
they connect to zebra, but it means adding even more code to handle a
very specific use-case. And anyway this won't work for mgmtd as it
doesn't have a connection with zebra. So I had to remove this option.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-12-03 23:22:55 +01:00
|
|
|
void vrf_set_default_name(const char *default_name)
|
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
|
|
|
snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *vrf_get_default_name(void)
|
|
|
|
{
|
|
|
|
return vrf_default_name;
|
|
|
|
}
|
|
|
|
|
lib: fix binding to a vrf
There are two possible use-cases for the `vrf_bind` function:
- bind socket to an interface in a vrf
- bind socket to a vrf device
For the former case, there's one problem - success is returned when the
interface is not found. In that case, the socket is left unbound without
throwing an error.
For the latter case, there are multiple possible problems:
- If the name is not set, then the socket is left unbound (zebra, vrrp).
- If the name is "default" and there's an interface with that name in the
default VRF, then the socket is bound to that interface.
- In most daemons, if the router is configured before the VRF is actually
created, we're trying to open and bind the socket right after the
daemon receives a VRF registration from zebra. We may not receive the
VRF-interface registration from zebra yet at that point. Therefore,
`if_lookup_by_name` fails, and the socket is left unbound.
This commit fixes all the issues and updates the function description.
Suggested-by: Pat Ruddy <pat@voltanet.io>
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-05-07 01:49:40 +02:00
|
|
|
int vrf_bind(vrf_id_t vrf_id, int fd, const char *ifname)
|
2018-02-05 17:28:51 +01:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2019-04-23 17:31:42 +02:00
|
|
|
struct interface *ifp;
|
lib: fix binding to a vrf
There are two possible use-cases for the `vrf_bind` function:
- bind socket to an interface in a vrf
- bind socket to a vrf device
For the former case, there's one problem - success is returned when the
interface is not found. In that case, the socket is left unbound without
throwing an error.
For the latter case, there are multiple possible problems:
- If the name is not set, then the socket is left unbound (zebra, vrrp).
- If the name is "default" and there's an interface with that name in the
default VRF, then the socket is bound to that interface.
- In most daemons, if the router is configured before the VRF is actually
created, we're trying to open and bind the socket right after the
daemon receives a VRF registration from zebra. We may not receive the
VRF-interface registration from zebra yet at that point. Therefore,
`if_lookup_by_name` fails, and the socket is left unbound.
This commit fixes all the issues and updates the function description.
Suggested-by: Pat Ruddy <pat@voltanet.io>
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-05-07 01:49:40 +02:00
|
|
|
struct vrf *vrf;
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (vrf_id == VRF_UNKNOWN)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* can't bind to a VRF that doesn't exist */
|
|
|
|
vrf = vrf_lookup_by_id(vrf_id);
|
|
|
|
if (!vrf_is_enabled(vrf))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (ifname && strcmp(ifname, vrf->name)) {
|
|
|
|
/* binding to a regular interface */
|
|
|
|
|
|
|
|
/* can't bind to an interface that doesn't exist */
|
|
|
|
ifp = if_lookup_by_name(ifname, vrf_id);
|
|
|
|
if (!ifp)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
/* binding to a VRF device */
|
|
|
|
|
|
|
|
/* nothing to do for netns */
|
|
|
|
if (vrf_is_backend_netns())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* nothing to do for default vrf */
|
|
|
|
if (vrf_id == VRF_DEFAULT)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ifname = vrf->name;
|
|
|
|
}
|
2018-02-05 17:28:51 +01:00
|
|
|
|
|
|
|
#ifdef SO_BINDTODEVICE
|
lib: fix binding to a vrf
There are two possible use-cases for the `vrf_bind` function:
- bind socket to an interface in a vrf
- bind socket to a vrf device
For the former case, there's one problem - success is returned when the
interface is not found. In that case, the socket is left unbound without
throwing an error.
For the latter case, there are multiple possible problems:
- If the name is not set, then the socket is left unbound (zebra, vrrp).
- If the name is "default" and there's an interface with that name in the
default VRF, then the socket is bound to that interface.
- In most daemons, if the router is configured before the VRF is actually
created, we're trying to open and bind the socket right after the
daemon receives a VRF registration from zebra. We may not receive the
VRF-interface registration from zebra yet at that point. Therefore,
`if_lookup_by_name` fails, and the socket is left unbound.
This commit fixes all the issues and updates the function description.
Suggested-by: Pat Ruddy <pat@voltanet.io>
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-05-07 01:49:40 +02:00
|
|
|
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
|
|
|
|
strlen(ifname) + 1);
|
2018-02-05 17:28:51 +01:00
|
|
|
if (ret < 0)
|
lib: fix binding to a vrf
There are two possible use-cases for the `vrf_bind` function:
- bind socket to an interface in a vrf
- bind socket to a vrf device
For the former case, there's one problem - success is returned when the
interface is not found. In that case, the socket is left unbound without
throwing an error.
For the latter case, there are multiple possible problems:
- If the name is not set, then the socket is left unbound (zebra, vrrp).
- If the name is "default" and there's an interface with that name in the
default VRF, then the socket is bound to that interface.
- In most daemons, if the router is configured before the VRF is actually
created, we're trying to open and bind the socket right after the
daemon receives a VRF registration from zebra. We may not receive the
VRF-interface registration from zebra yet at that point. Therefore,
`if_lookup_by_name` fails, and the socket is left unbound.
This commit fixes all the issues and updates the function description.
Suggested-by: Pat Ruddy <pat@voltanet.io>
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
2021-05-07 01:49:40 +02:00
|
|
|
zlog_err("bind to interface %s failed, errno=%d", ifname,
|
|
|
|
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,
|
|
|
|
const struct addrinfo *hints, struct addrinfo **res,
|
|
|
|
vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
|
2023-11-29 20:37:23 +01: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);
|
|
|
|
|
2021-03-28 23:49:13 +02:00
|
|
|
SET_FLAG(vrfp->status, VRF_CONFIGURED);
|
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. */
|
2021-03-28 23:49:13 +02:00
|
|
|
UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
|
2020-03-11 02:20:49 +01:00
|
|
|
vrf_delete(vrfp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
|
2024-01-27 18:38:06 +01:00
|
|
|
static void lib_vrf_cli_write(struct vty *vty, const struct lyd_node *dnode,
|
|
|
|
bool show_defaults)
|
|
|
|
{
|
|
|
|
const char *name = yang_dnode_get_string(dnode, "name");
|
|
|
|
|
|
|
|
if (strcmp(name, VRF_DEFAULT_NAME)) {
|
|
|
|
vty_out(vty, "!\n");
|
|
|
|
vty_out(vty, "vrf %s\n", name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lib_vrf_cli_write_end(struct vty *vty, const struct lyd_node *dnode)
|
|
|
|
{
|
|
|
|
const char *name = yang_dnode_get_string(dnode, "name");
|
|
|
|
|
|
|
|
if (strcmp(name, VRF_DEFAULT_NAME))
|
|
|
|
vty_out(vty, "exit-vrf\n");
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-10-20 10:53:05 +02:00
|
|
|
static const void *lib_vrf_lookup_next(struct nb_cb_lookup_entry_args *args)
|
|
|
|
{
|
|
|
|
const char *vrfname = args->keys->key[0];
|
|
|
|
struct vrf vrfkey, *vrf;
|
|
|
|
|
|
|
|
strlcpy(vrfkey.name, vrfname, sizeof(vrfkey.name));
|
|
|
|
vrf = RB_FIND(vrf_name_head, &vrfs_by_name, &vrfkey);
|
|
|
|
if (!strcmp(vrf->name, vrfname))
|
|
|
|
vrf = RB_NEXT(vrf_name_head, vrf);
|
|
|
|
|
|
|
|
return vrf;
|
|
|
|
}
|
|
|
|
|
2020-03-11 02:20:49 +01:00
|
|
|
/*
|
2025-02-26 21:43:22 +01:00
|
|
|
* XPath: /frr-vrf:lib/vrf/state/id
|
2020-03-11 02:20:49 +01:00
|
|
|
*/
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2025-02-26 21:43:22 +01:00
|
|
|
* XPath: /frr-vrf:lib/vrf/state/active
|
2020-03-11 02:20:49 +01:00
|
|
|
*/
|
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
|
|
|
|
2025-02-26 21:43:22 +01:00
|
|
|
return yang_data_new_bool(args->xpath, vrfp->status == VRF_ACTIVE ? true : false);
|
2020-03-11 02:20:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* clang-format off */
|
2024-02-04 20:52:47 +01:00
|
|
|
|
|
|
|
/* cli_show callbacks are kept here for daemons not yet converted to mgmtd */
|
2020-03-11 02:20:49 +01:00
|
|
|
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,
|
2024-01-27 18:38:06 +01:00
|
|
|
.cli_show = lib_vrf_cli_write,
|
|
|
|
.cli_show_end = lib_vrf_cli_write_end,
|
2020-03-11 02:20:49 +01:00
|
|
|
.get_next = lib_vrf_get_next,
|
|
|
|
.get_keys = lib_vrf_get_keys,
|
|
|
|
.lookup_entry = lib_vrf_lookup_entry,
|
2023-10-20 10:53:05 +02:00
|
|
|
.lookup_next = lib_vrf_lookup_next,
|
2021-05-04 16:41:58 +02:00
|
|
|
},
|
|
|
|
.priority = NB_DFLT_PRIORITY - 2,
|
2020-03-11 02:20:49 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-02-04 20:52:47 +01:00
|
|
|
const struct frr_yang_module_info frr_vrf_cli_info = {
|
|
|
|
.name = "frr-vrf",
|
|
|
|
.ignore_cfg_cbs = true,
|
|
|
|
.nodes = {
|
|
|
|
{
|
|
|
|
.xpath = "/frr-vrf:lib/vrf",
|
|
|
|
.cbs = {
|
|
|
|
.cli_show = lib_vrf_cli_write,
|
|
|
|
.cli_show_end = lib_vrf_cli_write_end,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.xpath = NULL,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|