mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-17 00:20:07 +00:00
lib/zebra: convert vrf_list to a red-black tree
Since we're already using a red-black tree to store VRFs sorted by their vrf_id's, create a new tree to store VRFs sorted by their names. The biggest advantage of doing this is that we reduce the time complexity of vrf_list_lookup_by_name() from O(n) to O(log n). Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
5f3d1bdf3c
commit
806f87607e
50
lib/vrf.c
50
lib/vrf.c
@ -36,10 +36,13 @@ DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map")
|
|||||||
DEFINE_QOBJ_TYPE(vrf)
|
DEFINE_QOBJ_TYPE(vrf)
|
||||||
|
|
||||||
static __inline int vrf_id_compare (struct vrf *, struct vrf *);
|
static __inline int vrf_id_compare (struct vrf *, struct vrf *);
|
||||||
|
static __inline int vrf_name_compare (struct vrf *, struct vrf *);
|
||||||
|
|
||||||
RB_GENERATE (vrf_id_head, vrf, id_entry, vrf_id_compare)
|
RB_GENERATE (vrf_id_head, vrf, id_entry, vrf_id_compare)
|
||||||
|
RB_GENERATE (vrf_name_head, vrf, name_entry, vrf_name_compare)
|
||||||
|
|
||||||
struct vrf_id_head vrfs_by_id = RB_INITIALIZER (&vrfs_by_id);
|
struct vrf_id_head vrfs_by_id = RB_INITIALIZER (&vrfs_by_id);
|
||||||
|
struct vrf_name_head vrfs_by_name = RB_INITIALIZER (&vrfs_by_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn on/off debug code
|
* Turn on/off debug code
|
||||||
@ -56,9 +59,6 @@ struct vrf_master
|
|||||||
int (*vrf_disable_hook) (vrf_id_t, const char *, void **);
|
int (*vrf_disable_hook) (vrf_id_t, const char *, void **);
|
||||||
} vrf_master = {0,};
|
} vrf_master = {0,};
|
||||||
|
|
||||||
/* VRF is part of a list too to store it before its actually active */
|
|
||||||
struct list *vrf_list;
|
|
||||||
|
|
||||||
static int vrf_is_enabled (struct vrf *vrf);
|
static int vrf_is_enabled (struct vrf *vrf);
|
||||||
static void vrf_disable (struct vrf *vrf);
|
static void vrf_disable (struct vrf *vrf);
|
||||||
|
|
||||||
@ -66,16 +66,9 @@ static void vrf_disable (struct vrf *vrf);
|
|||||||
struct vrf *
|
struct vrf *
|
||||||
vrf_list_lookup_by_name (const char *name)
|
vrf_list_lookup_by_name (const char *name)
|
||||||
{
|
{
|
||||||
struct listnode *node;
|
struct vrf vrf;
|
||||||
struct vrf *vrfp;
|
strlcpy (vrf.name, name, sizeof (vrf.name));
|
||||||
|
return (RB_FIND (vrf_name_head, &vrfs_by_name, &vrf));
|
||||||
if (name)
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrfp))
|
|
||||||
{
|
|
||||||
if (strcmp(name, vrfp->name) == 0)
|
|
||||||
return vrfp;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline int
|
static __inline int
|
||||||
@ -84,6 +77,12 @@ vrf_id_compare (struct vrf *a, struct vrf *b)
|
|||||||
return (a->vrf_id - b->vrf_id);
|
return (a->vrf_id - b->vrf_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vrf_name_compare (struct vrf *a, struct vrf *b)
|
||||||
|
{
|
||||||
|
return strcmp (a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a VRF. If not found, create one.
|
/* Get a VRF. If not found, create one.
|
||||||
* Arg:
|
* Arg:
|
||||||
* name - The name of the vrf. May be NULL if unknown.
|
* name - The name of the vrf. May be NULL if unknown.
|
||||||
@ -123,7 +122,7 @@ vrf_get (vrf_id_t vrf_id, const char *name)
|
|||||||
vrf_id, (name) ? name : "(NULL)");
|
vrf_id, (name) ? name : "(NULL)");
|
||||||
strcpy (vrf->name, name);
|
strcpy (vrf->name, name);
|
||||||
vrf->vrf_id = VRF_UNKNOWN;
|
vrf->vrf_id = VRF_UNKNOWN;
|
||||||
listnode_add_sort (vrf_list, vrf);
|
RB_INSERT (vrf_name_head, &vrfs_by_name, vrf);
|
||||||
if_init (&vrf->iflist);
|
if_init (&vrf->iflist);
|
||||||
QOBJ_REG (vrf, vrf);
|
QOBJ_REG (vrf, vrf);
|
||||||
if (vrf_master.vrf_new_hook)
|
if (vrf_master.vrf_new_hook)
|
||||||
@ -180,7 +179,7 @@ vrf_get (vrf_id_t vrf_id, const char *name)
|
|||||||
* so let's set it.
|
* so let's set it.
|
||||||
*/
|
*/
|
||||||
strcpy (vrf->name, name);
|
strcpy (vrf->name, name);
|
||||||
listnode_add_sort (vrf_list, vrf);
|
RB_INSERT (vrf_name_head, &vrfs_by_name, vrf);
|
||||||
if (vrf_master.vrf_new_hook)
|
if (vrf_master.vrf_new_hook)
|
||||||
{
|
{
|
||||||
(*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
|
(*vrf_master.vrf_new_hook) (vrf_id, name, &vrf->info);
|
||||||
@ -197,7 +196,7 @@ vrf_get (vrf_id_t vrf_id, const char *name)
|
|||||||
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf));
|
||||||
vrf->vrf_id = vrf_id;
|
vrf->vrf_id = vrf_id;
|
||||||
strcpy (vrf->name, name);
|
strcpy (vrf->name, name);
|
||||||
listnode_add_sort (vrf_list, vrf);
|
RB_INSERT (vrf_name_head, &vrfs_by_name, vrf);
|
||||||
RB_INSERT (vrf_id_head, &vrfs_by_id, vrf);
|
RB_INSERT (vrf_id_head, &vrfs_by_id, vrf);
|
||||||
if_init (&vrf->iflist);
|
if_init (&vrf->iflist);
|
||||||
QOBJ_REG (vrf, vrf);
|
QOBJ_REG (vrf, vrf);
|
||||||
@ -265,7 +264,7 @@ vrf_delete (struct vrf *vrf)
|
|||||||
|
|
||||||
if (vrf->vrf_id != VRF_UNKNOWN)
|
if (vrf->vrf_id != VRF_UNKNOWN)
|
||||||
RB_REMOVE (vrf_id_head, &vrfs_by_id, vrf);
|
RB_REMOVE (vrf_id_head, &vrfs_by_id, vrf);
|
||||||
listnode_delete (vrf_list, vrf);
|
RB_REMOVE (vrf_name_head, &vrfs_by_name, vrf);
|
||||||
|
|
||||||
XFREE (MTYPE_VRF, vrf);
|
XFREE (MTYPE_VRF, vrf);
|
||||||
}
|
}
|
||||||
@ -536,20 +535,6 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
|
|||||||
VRF_BITMAP_FLAG (offset)) ? 1 : 0;
|
VRF_BITMAP_FLAG (offset)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
vrf_cmp_func (struct vrf *vrfp1, struct vrf *vrfp2)
|
|
||||||
{
|
|
||||||
return if_cmp_name_func (vrfp1->name, vrfp2->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize VRF module. */
|
/* Initialize VRF module. */
|
||||||
void
|
void
|
||||||
vrf_init (void)
|
vrf_init (void)
|
||||||
@ -559,9 +544,6 @@ vrf_init (void)
|
|||||||
if (debug_vrf)
|
if (debug_vrf)
|
||||||
zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__);
|
zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
vrf_list = list_new ();
|
|
||||||
vrf_list->cmp = (int (*)(void *, void *))vrf_cmp_func;
|
|
||||||
|
|
||||||
/* The default VRF always exists. */
|
/* The default VRF always exists. */
|
||||||
default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
|
default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
|
||||||
if (!default_vrf)
|
if (!default_vrf)
|
||||||
|
@ -70,7 +70,7 @@ enum {
|
|||||||
|
|
||||||
struct vrf
|
struct vrf
|
||||||
{
|
{
|
||||||
RB_ENTRY(vrf) id_entry;
|
RB_ENTRY(vrf) id_entry, name_entry;
|
||||||
|
|
||||||
/* Identifier, same as the vector index */
|
/* Identifier, same as the vector index */
|
||||||
vrf_id_t vrf_id;
|
vrf_id_t vrf_id;
|
||||||
@ -92,11 +92,13 @@ struct vrf
|
|||||||
};
|
};
|
||||||
RB_HEAD (vrf_id_head, vrf);
|
RB_HEAD (vrf_id_head, vrf);
|
||||||
RB_PROTOTYPE (vrf_id_head, vrf, id_entry, vrf_id_compare)
|
RB_PROTOTYPE (vrf_id_head, vrf, id_entry, vrf_id_compare)
|
||||||
|
RB_HEAD (vrf_name_head, vrf);
|
||||||
|
RB_PROTOTYPE (vrf_name_head, vrf, name_entry, vrf_name_compare)
|
||||||
DECLARE_QOBJ_TYPE(vrf)
|
DECLARE_QOBJ_TYPE(vrf)
|
||||||
|
|
||||||
|
|
||||||
extern struct vrf_id_head vrfs_by_id;
|
extern struct vrf_id_head vrfs_by_id;
|
||||||
extern struct list *vrf_list;
|
extern struct vrf_name_head vrfs_by_name;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a specific hook to VRF module.
|
* Add a specific hook to VRF module.
|
||||||
|
@ -446,11 +446,10 @@ DEFUN_NOSH (zebra_vrf,
|
|||||||
static int
|
static int
|
||||||
vrf_config_write (struct vty *vty)
|
vrf_config_write (struct vty *vty)
|
||||||
{
|
{
|
||||||
struct listnode *node;
|
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf))
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
{
|
{
|
||||||
zvrf = vrf->info;
|
zvrf = vrf->info;
|
||||||
if (! zvrf || strcmp (zvrf->name, VRF_DEFAULT_NAME))
|
if (! zvrf || strcmp (zvrf->name, VRF_DEFAULT_NAME))
|
||||||
|
@ -3677,9 +3677,8 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd)
|
|||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int write =0;
|
int write =0;
|
||||||
struct listnode *node;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf))
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
{
|
{
|
||||||
zvrf = vrf->info;
|
zvrf = vrf->info;
|
||||||
if (! zvrf)
|
if (! zvrf)
|
||||||
@ -5789,9 +5788,8 @@ static_config_ipv6 (struct vty *vty)
|
|||||||
struct route_table *stable;
|
struct route_table *stable;
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
struct listnode *node;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf))
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
{
|
{
|
||||||
zvrf = vrf->info;
|
zvrf = vrf->info;
|
||||||
if (! zvrf)
|
if (! zvrf)
|
||||||
@ -5886,9 +5884,8 @@ DEFUN (show_vrf,
|
|||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
struct listnode *node;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO (vrf_list, node, vrf))
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
{
|
{
|
||||||
zvrf = vrf->info;
|
zvrf = vrf->info;
|
||||||
if (! zvrf || ! zvrf->vrf_id)
|
if (! zvrf || ! zvrf->vrf_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user