2015-05-22 11:39:56 +02:00
|
|
|
/*
|
|
|
|
* VRF functions.
|
|
|
|
* Copyright (C) 2014 6WIND S.A.
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published
|
|
|
|
* by the Free Software Foundation; either version 2, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GNU Zebra; see the file COPYING. If not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
2015-05-22 11:39:58 +02:00
|
|
|
#include "if.h"
|
2015-05-22 11:39:56 +02:00
|
|
|
#include "vrf.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "memory.h"
|
|
|
|
|
|
|
|
/* Holding VRF hooks */
|
|
|
|
struct vrf_master
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
int (*vrf_new_hook) (vrf_id_t, const char *, void **);
|
|
|
|
int (*vrf_delete_hook) (vrf_id_t, const char *, void **);
|
|
|
|
int (*vrf_enable_hook) (vrf_id_t, const char *, void **);
|
|
|
|
int (*vrf_disable_hook) (vrf_id_t, const char *, void **);
|
2015-05-22 11:39:56 +02:00
|
|
|
} vrf_master = {0,};
|
|
|
|
|
|
|
|
/* VRF table */
|
|
|
|
struct route_table *vrf_table = NULL;
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* VRF is part of a list too to store it before its actually active */
|
|
|
|
struct list *vrf_list;
|
|
|
|
|
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);
|
|
|
|
static void vrf_disable (struct vrf *vrf);
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* VRF list existance check by name. */
|
|
|
|
struct vrf *
|
|
|
|
vrf_list_lookup_by_name (const char *name)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp))
|
|
|
|
{
|
|
|
|
if (strcmp(name, vrfp->name) == 0)
|
|
|
|
return vrfp;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct vrf *
|
|
|
|
vrf_list_lookup_by_name_len (const char *name, size_t namelen)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
|
|
|
if (namelen > INTERFACE_NAMSIZ)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp))
|
|
|
|
{
|
|
|
|
if (!memcmp(name, vrfp->name, namelen) && (vrfp->name[namelen] == '\0'))
|
|
|
|
return vrfp;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create new interface structure. */
|
|
|
|
struct vrf *
|
|
|
|
vrf_create (const char *name, size_t namelen)
|
|
|
|
{
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
|
|
|
vrfp = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
|
|
|
|
|
|
|
assert (name);
|
|
|
|
assert (namelen <= VRF_NAMSIZ); /* Need space for '\0' at end. */
|
|
|
|
strncpy (vrfp->name, name, namelen);
|
|
|
|
vrfp->name[namelen] = '\0';
|
|
|
|
if (vrf_list_lookup_by_name (vrfp->name) == NULL)
|
|
|
|
listnode_add_sort (vrf_list, vrfp);
|
|
|
|
else
|
|
|
|
zlog_err("vrf_create(%s): corruption detected -- vrf with this "
|
|
|
|
"name exists already with vrf-id %u!", vrfp->name, vrfp->vrf_id);
|
|
|
|
|
|
|
|
UNSET_FLAG(vrfp->status, ZEBRA_VRF_ACTIVE);
|
|
|
|
|
|
|
|
/* Pending: - Make sure this 0 vrf-id isnt taken as default vrf
|
|
|
|
- See if calling the the new_hook here is ok, may need to make the attached callback re-entrant.
|
|
|
|
if (vrf_master.vrf_new_hook)
|
|
|
|
(*vrf_master.vrf_new_hook) (0, name, &vrfp->info);
|
|
|
|
*/
|
|
|
|
return vrfp;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct vrf *
|
|
|
|
vrf_get_by_name_len (const char *name, size_t namelen)
|
|
|
|
{
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
|
|
|
return ((vrfp = vrf_list_lookup_by_name_len (name, namelen)) != NULL) ? vrfp :
|
|
|
|
vrf_create (name, namelen);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct vrf *
|
|
|
|
vrf_get_by_name (const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrfp;
|
|
|
|
|
|
|
|
return ((vrfp = vrf_list_lookup_by_name (name)) != NULL) ? vrfp :
|
|
|
|
vrf_create (name, strlen(name));
|
|
|
|
}
|
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
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Build the table key */
|
|
|
|
static void
|
|
|
|
vrf_build_key (vrf_id_t vrf_id, struct prefix *p)
|
|
|
|
{
|
|
|
|
p->family = AF_INET;
|
|
|
|
p->prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
p->u.prefix4.s_addr = vrf_id;
|
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* Get a VRF. If not found, create one.
|
|
|
|
* Arg: name
|
|
|
|
* Description: Please note that this routine can be called with just the name
|
|
|
|
and 0 vrf-id */
|
|
|
|
struct vrf *
|
|
|
|
vrf_get (vrf_id_t vrf_id, const char *name)
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
struct route_node *rn;
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *vrf = NULL;
|
2015-05-22 11:39:56 +02:00
|
|
|
|
|
|
|
vrf_build_key (vrf_id, &p);
|
|
|
|
rn = route_node_get (vrf_table, &p);
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
vrf = (struct vrf *)rn->info;
|
|
|
|
route_unlock_node (rn); /* get */
|
2016-02-01 18:09:51 +01:00
|
|
|
|
|
|
|
if (name)
|
|
|
|
{
|
|
|
|
strncpy (vrf->name, name, strlen(name));
|
|
|
|
vrf->name[strlen(name)] = '\0';
|
|
|
|
if (vrf_list_lookup_by_name (vrf->name) == NULL)
|
|
|
|
listnode_add_sort (vrf_list, vrf);
|
|
|
|
}
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
2016-02-01 18:09:51 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (name)
|
|
|
|
vrf = vrf_get_by_name(name);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
if (!vrf)
|
|
|
|
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
vrf->vrf_id = vrf_id;
|
|
|
|
rn->info = vrf;
|
|
|
|
vrf->node = rn;
|
2015-05-22 11:39:59 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* Initialize interfaces. */
|
|
|
|
if_init (vrf_id, &vrf->iflist);
|
|
|
|
}
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
if (name)
|
|
|
|
zlog_info ("VRF %s with id %u is created.", name, vrf_id);
|
|
|
|
else
|
|
|
|
zlog_info ("VRF %u is created.", vrf_id);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
if (vrf_master.vrf_new_hook && name) {
|
|
|
|
(*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
|
|
|
|
|
|
|
|
if (vrf->info)
|
|
|
|
zlog_info ("zvrf is created.");
|
|
|
|
}
|
2015-05-22 11:39:56 +02:00
|
|
|
return vrf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete a VRF. This is called in vrf_terminate(). */
|
2016-02-01 18:09:51 +01:00
|
|
|
void
|
2015-05-22 11:39:56 +02:00
|
|
|
vrf_delete (struct vrf *vrf)
|
|
|
|
{
|
|
|
|
zlog_info ("VRF %u is to be deleted.", 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
|
|
|
if (vrf_is_enabled (vrf))
|
|
|
|
vrf_disable (vrf);
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
if (vrf_master.vrf_delete_hook)
|
2016-02-01 18:09:51 +01:00
|
|
|
(*vrf_master.vrf_delete_hook) (vrf->vrf_id, vrf->name, &vrf->info);
|
|
|
|
|
|
|
|
if (CHECK_FLAG (vrf->status, ZEBRA_VRF_ACTIVE))
|
|
|
|
if_terminate (vrf->vrf_id, &vrf->iflist);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
if (vrf->node)
|
|
|
|
{
|
|
|
|
vrf->node->info = NULL;
|
|
|
|
route_unlock_node(vrf->node);
|
|
|
|
}
|
2015-05-22 11:39:59 +02:00
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
listnode_delete (vrf_list, vrf);
|
2015-05-22 11:39:56 +02:00
|
|
|
|
|
|
|
XFREE (MTYPE_VRF, vrf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look up a VRF by identifier. */
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *
|
2015-05-22 11:39:56 +02:00
|
|
|
vrf_lookup (vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
struct route_node *rn;
|
|
|
|
struct vrf *vrf = NULL;
|
|
|
|
|
|
|
|
vrf_build_key (vrf_id, &p);
|
|
|
|
rn = route_node_lookup (vrf_table, &p);
|
|
|
|
if (rn)
|
|
|
|
{
|
|
|
|
vrf = (struct vrf *)rn->info;
|
|
|
|
route_unlock_node (rn); /* lookup */
|
|
|
|
}
|
|
|
|
return 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
|
|
|
/*
|
|
|
|
* Check whether the VRF is enabled - that is, whether the VRF
|
|
|
|
* is ready to allocate resources. Currently there's only one
|
|
|
|
* type of resource: socket.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
vrf_is_enabled (struct vrf *vrf)
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
return vrf && CHECK_FLAG (vrf->status, ZEBRA_VRF_ACTIVE);
|
|
|
|
|
|
|
|
/*Pending: figure out the real use of this routine.. it used to be..
|
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 vrf && vrf->vrf_id == VRF_DEFAULT;
|
2016-02-01 18:09:51 +01: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.
|
|
|
|
*/
|
2016-02-01 18:09:51 +01:00
|
|
|
int
|
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
|
|
|
vrf_enable (struct vrf *vrf)
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
//Pending: see if VRF lib had a reason to leave it for default only
|
|
|
|
// /* Till now, only the default VRF can be enabled. */
|
|
|
|
// if (vrf->vrf_id == VRF_DEFAULT)
|
|
|
|
// {
|
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
|
|
|
zlog_info ("VRF %u is enabled.", vrf->vrf_id);
|
|
|
|
|
|
|
|
if (vrf_master.vrf_enable_hook)
|
2016-02-01 18:09:51 +01:00
|
|
|
(*vrf_master.vrf_enable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
|
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 1;
|
2016-02-01 18:09:51 +01: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
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
// return 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
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vrf_disable (struct vrf *vrf)
|
|
|
|
{
|
|
|
|
if (vrf_is_enabled (vrf))
|
|
|
|
{
|
|
|
|
zlog_info ("VRF %u is to be disabled.", vrf->vrf_id);
|
|
|
|
|
|
|
|
/* Till now, nothing to be done for the default VRF. */
|
2016-02-01 18:09:51 +01:00
|
|
|
//Pending: see why this statement.
|
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_master.vrf_disable_hook)
|
2016-02-01 18:09:51 +01:00
|
|
|
(*vrf_master.vrf_disable_hook) (vrf->vrf_id, vrf->name, &vrf->info);
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Add a VRF hook. Please add hooks before calling vrf_init(). */
|
|
|
|
void
|
2016-02-01 18:09:51 +01:00
|
|
|
vrf_add_hook (int type, int (*func)(vrf_id_t, const char *, void **))
|
2015-05-22 11:39:56 +02:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case VRF_NEW_HOOK:
|
|
|
|
vrf_master.vrf_new_hook = func;
|
|
|
|
break;
|
|
|
|
case VRF_DELETE_HOOK:
|
|
|
|
vrf_master.vrf_delete_hook = func;
|
|
|
|
break;
|
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
|
|
|
case VRF_ENABLE_HOOK:
|
|
|
|
vrf_master.vrf_enable_hook = func;
|
|
|
|
break;
|
|
|
|
case VRF_DISABLE_HOOK:
|
|
|
|
vrf_master.vrf_disable_hook = func;
|
|
|
|
break;
|
2015-05-22 11:39:56 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the iterator of the first VRF. */
|
|
|
|
vrf_iter_t
|
|
|
|
vrf_first (void)
|
|
|
|
{
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
for (rn = route_top (vrf_table); rn; rn = route_next (rn))
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
route_unlock_node (rn); /* top/next */
|
|
|
|
return (vrf_iter_t)rn;
|
|
|
|
}
|
|
|
|
return VRF_ITER_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the next VRF iterator to the given iterator. */
|
|
|
|
vrf_iter_t
|
|
|
|
vrf_next (vrf_iter_t iter)
|
|
|
|
{
|
|
|
|
struct route_node *rn = NULL;
|
|
|
|
|
|
|
|
/* Lock it first because route_next() will unlock it. */
|
|
|
|
if (iter != VRF_ITER_INVALID)
|
|
|
|
rn = route_next (route_lock_node ((struct route_node *)iter));
|
|
|
|
|
|
|
|
for (; rn; rn = route_next (rn))
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
route_unlock_node (rn); /* next */
|
|
|
|
return (vrf_iter_t)rn;
|
|
|
|
}
|
|
|
|
return VRF_ITER_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the VRF iterator of the given VRF ID. If it does not exist,
|
|
|
|
* the iterator of the next existing VRF is returned. */
|
|
|
|
vrf_iter_t
|
|
|
|
vrf_iterator (vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct prefix p;
|
|
|
|
struct route_node *rn;
|
|
|
|
|
|
|
|
vrf_build_key (vrf_id, &p);
|
|
|
|
rn = route_node_get (vrf_table, &p);
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
/* OK, the VRF exists. */
|
|
|
|
route_unlock_node (rn); /* get */
|
|
|
|
return (vrf_iter_t)rn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the next VRF. */
|
|
|
|
for (rn = route_next (rn); rn; rn = route_next (rn))
|
|
|
|
if (rn->info)
|
|
|
|
{
|
|
|
|
route_unlock_node (rn); /* next */
|
|
|
|
return (vrf_iter_t)rn;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VRF_ITER_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Obtain the VRF ID from the given VRF iterator. */
|
|
|
|
vrf_id_t
|
|
|
|
vrf_iter2id (vrf_iter_t iter)
|
|
|
|
{
|
|
|
|
struct route_node *rn = (struct route_node *) iter;
|
|
|
|
return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT;
|
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *
|
|
|
|
vrf_iter2vrf (vrf_iter_t iter)
|
|
|
|
{
|
|
|
|
struct route_node *rn = (struct route_node *) iter;
|
|
|
|
return (rn && rn->info) ? (struct vrf *)rn->info : NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Obtain the data pointer from the given VRF iterator. */
|
|
|
|
void *
|
|
|
|
vrf_iter2info (vrf_iter_t iter)
|
|
|
|
{
|
|
|
|
struct route_node *rn = (struct route_node *) iter;
|
|
|
|
return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:59 +02:00
|
|
|
/* Obtain the interface list from the given VRF iterator. */
|
|
|
|
struct list *
|
|
|
|
vrf_iter2iflist (vrf_iter_t iter)
|
|
|
|
{
|
|
|
|
struct route_node *rn = (struct route_node *) iter;
|
|
|
|
return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL;
|
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
/* Look up a VRF by name. */
|
|
|
|
struct vrf *
|
|
|
|
vrf_lookup_by_name (const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrf = NULL;
|
|
|
|
vrf_iter_t iter;
|
|
|
|
|
|
|
|
for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
|
|
|
|
{
|
|
|
|
vrf = vrf_iter2vrf (iter);
|
|
|
|
if (vrf && !strcmp(vrf->name, name))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vrf;
|
|
|
|
}
|
|
|
|
|
|
|
|
vrf_id_t
|
|
|
|
vrf_name_to_id (const char *name)
|
|
|
|
{
|
|
|
|
struct vrf *vrf;
|
|
|
|
vrf_id_t vrf_id = VRF_DEFAULT; //Pending: need a way to return invalid id/ routine not used.
|
|
|
|
|
|
|
|
vrf = vrf_lookup_by_name (name);
|
|
|
|
if (vrf)
|
|
|
|
vrf_id = vrf->vrf_id;
|
|
|
|
|
|
|
|
return vrf_id;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Get the data pointer of the specified VRF. If not found, create one. */
|
|
|
|
void *
|
|
|
|
vrf_info_get (vrf_id_t vrf_id)
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf *vrf = vrf_get (vrf_id, NULL);
|
2015-05-22 11:39:56 +02:00
|
|
|
return vrf->info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look up the data pointer of the specified VRF. */
|
|
|
|
void *
|
|
|
|
vrf_info_lookup (vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf *vrf = vrf_lookup (vrf_id);
|
|
|
|
return vrf ? vrf->info : NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:59 +02:00
|
|
|
/* Look up the interface list in a VRF. */
|
|
|
|
struct list *
|
|
|
|
vrf_iflist (vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf * vrf = vrf_lookup (vrf_id);
|
|
|
|
return vrf ? vrf->iflist : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the interface list of the specified VRF. Create one if not find. */
|
|
|
|
struct list *
|
|
|
|
vrf_iflist_get (vrf_id_t vrf_id)
|
|
|
|
{
|
2016-02-01 18:09:51 +01:00
|
|
|
struct vrf * vrf = vrf_get (vrf_id, NULL);
|
2015-05-22 11:39:59 +02:00
|
|
|
return vrf->iflist;
|
|
|
|
}
|
|
|
|
|
*: add VRF ID in the API message header
The API messages are used by zebra to exchange the interfaces, addresses,
routes and router-id information with its clients. To distinguish which
VRF the information belongs to, a new field "VRF ID" is added in the
message header. And hence the message version is increased to 3.
* The new field "VRF ID" in the message header:
Length (2 bytes)
Marker (1 byte)
Version (1 byte)
VRF ID (2 bytes, newly added)
Command (2 bytes)
- Client side:
- zclient_create_header() adds the VRF ID in the message header.
- zclient_read() extracts and validates the VRF ID from the header,
and passes the VRF ID to the callback functions registered to
the API messages.
- All relative functions are appended with a new parameter "vrf_id",
including all the callback functions.
- "vrf_id" is also added to "struct zapi_ipv4" and "struct zapi_ipv6".
Clients need to correctly set the VRF ID when using the API
functions zapi_ipv4_route() and zapi_ipv6_route().
- Till now all messages sent from a client have the default VRF ID
"0" in the header.
- The HELLO message is special, which is used as the heart-beat of
a client, and has no relation with VRF. The VRF ID in the HELLO
message header will always be 0 and ignored by zebra.
- Zebra side:
- zserv_create_header() adds the VRF ID in the message header.
- zebra_client_read() extracts and validates the VRF ID from the
header, and passes the VRF ID to the functions which process
the received messages.
- All relative functions are appended with a new parameter "vrf_id".
* Suppress the messages in a VRF which a client does not care:
Some clients may not care about the information in the VRF X, and
zebra should not send the messages in the VRF X to those clients.
Extra flags are used to indicate which VRF is registered by a client,
and a new message ZEBRA_VRF_UNREGISTER is introduced to let a client
can unregister a VRF when it does not need any information in that
VRF.
A client sends any message other than ZEBRA_VRF_UNREGISTER in a VRF
will automatically register to that VRF.
- lib/vrf:
A new utility "VRF bit-map" is provided to manage the flags for
VRFs, one bit per VRF ID.
- Use vrf_bitmap_init()/vrf_bitmap_free() to initialize/free a
bit-map;
- Use vrf_bitmap_set()/vrf_bitmap_unset() to set/unset a flag
in the given bit-map, corresponding to the given VRF ID;
- Use vrf_bitmap_check() to test whether the flag, in the given
bit-map and for the given VRF ID, is set.
- Client side:
- In "struct zclient", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
default_information
These flags are extended for each VRF, and controlled by the
clients themselves (or with the help of zclient_redistribute()
and zclient_redistribute_default()).
- Zebra side:
- In "struct zserv", the following flags are changed from
"u_char" to "vrf_bitmap_t":
redist[ZEBRA_ROUTE_MAX]
redist_default
ifinfo
ridinfo
These flags are extended for each VRF, as the VRF registration
flags. They are maintained on receiving a ZEBRA_XXX_ADD or
ZEBRA_XXX_DELETE message.
When sending an interface/address/route/router-id message in
a VRF to a client, if the corresponding VRF registration flag
is not set, this message will not be dropped by zebra.
- A new function zread_vrf_unregister() is introduced to process
the new command ZEBRA_VRF_UNREGISTER. All the VRF registration
flags are cleared for the requested VRF.
Those clients, who support only the default VRF, will never receive
a message in a non-default VRF, thanks to the filter in zebra.
* New callback for the event of successful connection to zebra:
- zclient_start() is splitted, keeping only the code of connecting
to zebra.
- Now zclient_init()=>zclient_connect()=>zclient_start() operations
are purely dealing with the connection to zbera.
- Once zebra is successfully connected, at the end of zclient_start(),
a new callback is used to inform the client about connection.
- Till now, in the callback of connect-to-zebra event, all clients
send messages to zebra to request the router-id/interface/routes
information in the default VRF.
Of corse in future the client can do anything it wants in this
callback. For example, it may send requests for both default VRF
and some non-default VRFs.
Signed-off-by: Feng Lu <lu.feng@6wind.com>
Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
Conflicts:
lib/zclient.h
lib/zebra.h
zebra/zserv.c
zebra/zserv.h
Conflicts:
bgpd/bgp_nexthop.c
bgpd/bgp_nht.c
bgpd/bgp_zebra.c
isisd/isis_zebra.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
nhrpd/nhrp_interface.c
nhrpd/nhrp_route.c
nhrpd/nhrpd.h
ospf6d/ospf6_zebra.c
ospf6d/ospf6_zebra.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
ripd/rip_zebra.c
ripngd/ripng_zebra.c
zebra/redistribute.c
zebra/rt_netlink.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zserv.c
zebra/zserv.h
2014-10-16 03:52:36 +02:00
|
|
|
/*
|
|
|
|
* VRF bit-map
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VRF_BITMAP_NUM_OF_GROUPS 8
|
|
|
|
#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP \
|
|
|
|
(UINT16_MAX / VRF_BITMAP_NUM_OF_GROUPS)
|
|
|
|
#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \
|
|
|
|
(VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */
|
|
|
|
|
|
|
|
#define VRF_BITMAP_GROUP(_id) \
|
|
|
|
((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
|
|
|
|
#define VRF_BITMAP_BIT_OFFSET(_id) \
|
|
|
|
((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP)
|
|
|
|
|
|
|
|
#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) \
|
|
|
|
((_bit_offset) / CHAR_BIT)
|
|
|
|
#define VRF_BITMAP_FLAG(_bit_offset) \
|
|
|
|
(((u_char)1) << ((_bit_offset) % CHAR_BIT))
|
|
|
|
|
|
|
|
struct vrf_bitmap
|
|
|
|
{
|
|
|
|
u_char *groups[VRF_BITMAP_NUM_OF_GROUPS];
|
|
|
|
};
|
|
|
|
|
|
|
|
vrf_bitmap_t
|
|
|
|
vrf_bitmap_init (void)
|
|
|
|
{
|
|
|
|
return (vrf_bitmap_t) XCALLOC (MTYPE_VRF_BITMAP, sizeof (struct vrf_bitmap));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vrf_bitmap_free (vrf_bitmap_t bmap)
|
|
|
|
{
|
|
|
|
struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (bmap == VRF_BITMAP_NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++)
|
|
|
|
if (bm->groups[i])
|
|
|
|
XFREE (MTYPE_VRF_BITMAP, bm->groups[i]);
|
|
|
|
|
|
|
|
XFREE (MTYPE_VRF_BITMAP, bm);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
|
|
|
|
u_char group = VRF_BITMAP_GROUP (vrf_id);
|
|
|
|
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
|
|
|
|
|
|
|
|
if (bmap == VRF_BITMAP_NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (bm->groups[group] == NULL)
|
|
|
|
bm->groups[group] = XCALLOC (MTYPE_VRF_BITMAP,
|
|
|
|
VRF_BITMAP_NUM_OF_BYTES_IN_GROUP);
|
|
|
|
|
|
|
|
SET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
|
|
|
|
VRF_BITMAP_FLAG (offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
|
|
|
|
u_char group = VRF_BITMAP_GROUP (vrf_id);
|
|
|
|
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
|
|
|
|
|
|
|
|
if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
|
|
|
|
VRF_BITMAP_FLAG (offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
struct vrf_bitmap *bm = (struct vrf_bitmap *) bmap;
|
|
|
|
u_char group = VRF_BITMAP_GROUP (vrf_id);
|
|
|
|
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
|
|
|
|
|
|
|
|
if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
|
|
|
|
VRF_BITMAP_FLAG (offset)) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
//Pending: See if combining the common parts with if_cmp_func() make sense.
|
|
|
|
/* Compare interface names, returning an integer greater than, equal to, or
|
|
|
|
* less than 0, (following the strcmp convention), according to the
|
|
|
|
* relationship between vrfp1 and vrfp2. Interface names consist of an
|
|
|
|
* alphabetic prefix and a numeric suffix. The primary sort key is
|
|
|
|
* lexicographic by name, and then numeric by number. No number sorts
|
|
|
|
* before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
|
|
|
|
* devpty0, de0 < del0
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2)
|
|
|
|
{
|
|
|
|
unsigned int l1, l2;
|
|
|
|
long int x1, x2;
|
|
|
|
char *p1, *p2;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
p1 = vrfp1->name;
|
|
|
|
p2 = vrfp2->name;
|
|
|
|
|
|
|
|
while (*p1 && *p2) {
|
|
|
|
/* look up to any number */
|
|
|
|
l1 = strcspn(p1, "0123456789");
|
|
|
|
l2 = strcspn(p2, "0123456789");
|
|
|
|
|
|
|
|
/* name lengths are different -> compare names */
|
|
|
|
if (l1 != l2)
|
|
|
|
return (strcmp(p1, p2));
|
|
|
|
|
|
|
|
/* Note that this relies on all numbers being less than all letters, so
|
|
|
|
* that de0 < del0.
|
|
|
|
*/
|
|
|
|
res = strncmp(p1, p2, l1);
|
|
|
|
|
|
|
|
/* names are different -> compare them */
|
|
|
|
if (res)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
/* with identical name part, go to numeric part */
|
|
|
|
p1 += l1;
|
|
|
|
p2 += l1;
|
|
|
|
|
|
|
|
if (!*p1)
|
|
|
|
return -1;
|
|
|
|
if (!*p2)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
x1 = strtol(p1, &p1, 10);
|
|
|
|
x2 = strtol(p2, &p2, 10);
|
|
|
|
|
|
|
|
/* let's compare numbers now */
|
|
|
|
if (x1 < x2)
|
|
|
|
return -1;
|
|
|
|
if (x1 > x2)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* numbers were equal, lets do it again..
|
|
|
|
(it happens with name like "eth123.456:789") */
|
|
|
|
}
|
|
|
|
if (*p1)
|
|
|
|
return 1;
|
|
|
|
if (*p2)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Initialize VRF module. */
|
|
|
|
void
|
|
|
|
vrf_init (void)
|
|
|
|
{
|
|
|
|
struct vrf *default_vrf;
|
|
|
|
|
2016-02-01 18:09:51 +01:00
|
|
|
vrf_list = list_new ();
|
|
|
|
vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func;
|
|
|
|
|
2015-05-22 11:39:56 +02:00
|
|
|
/* Allocate VRF table. */
|
|
|
|
vrf_table = route_table_init ();
|
|
|
|
|
|
|
|
/* The default VRF always exists. */
|
2016-02-01 18:09:51 +01:00
|
|
|
default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
|
2015-05-22 11:39:56 +02:00
|
|
|
if (!default_vrf)
|
|
|
|
{
|
|
|
|
zlog_err ("vrf_init: failed to create the default VRF!");
|
|
|
|
exit (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
|
|
|
/* Enable the default VRF. */
|
|
|
|
if (!vrf_enable (default_vrf))
|
|
|
|
{
|
|
|
|
zlog_err ("vrf_init: failed to enable the default VRF!");
|
|
|
|
exit (1);
|
|
|
|
}
|
2015-05-22 11:39:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Terminate VRF module. */
|
|
|
|
void
|
|
|
|
vrf_terminate (void)
|
|
|
|
{
|
|
|
|
struct route_node *rn;
|
|
|
|
struct vrf *vrf;
|
|
|
|
|
|
|
|
for (rn = route_top (vrf_table); rn; rn = route_next (rn))
|
|
|
|
if ((vrf = rn->info) != NULL)
|
|
|
|
vrf_delete (vrf);
|
|
|
|
|
|
|
|
route_table_finish (vrf_table);
|
|
|
|
vrf_table = NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/* Create a socket for the VRF. */
|
|
|
|
int
|
|
|
|
vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
ret = socket (domain, type, protocol);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|