Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hashmap for vrf lookup by table #10821

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions lib/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include <zebra.h>
#include "zebra/zebra_vrf.h"
nathan-duddles marked this conversation as resolved.
Show resolved Hide resolved

#include "if.h"
#include "vrf.h"
Expand All @@ -35,6 +36,7 @@
#include "lib_errors.h"
#include "northbound.h"
#include "northbound_cli.h"
#include "jhash.h"

/* default VRF name value used when VRF backend is not NETNS */
#define VRF_DEFAULT_NAME_INTERNAL "default"
Expand Down Expand Up @@ -75,11 +77,89 @@ static struct vrf_master {

static int vrf_is_enabled(struct vrf *vrf);

/*Hash Table for table_id based lookup of vrf_id*/
DEFINE_MTYPE_STATIC(LIB, HASH_ENTRY, "VRF IDs by Table Hash Entry");

PREDECL_HASH(vrf_ids_by_table);

struct vrf_ids_by_table_entry {
struct vrf_ids_by_table_item hash_item;
uint32_t table_id;
vrf_id_t vrf_id;
};

static int vrf_ids_by_table_cmp(const struct vrf_ids_by_table_entry *a,
const struct vrf_ids_by_table_entry *b)
{
return numcmp(a->table_id, b->table_id);
}

static uint32_t vrf_ids_by_table_hash(const struct vrf_ids_by_table_entry *item)
{
return jhash_1word(item->table_id, 0xa010bf92);
}

DECLARE_HASH(vrf_ids_by_table, struct vrf_ids_by_table_entry, hash_item,
vrf_ids_by_table_cmp, vrf_ids_by_table_hash);

static struct vrf_ids_by_table_head vrf_ids_by_table_head;

static int vrf_ids_by_table_is_initialized;

/* Helper functions for vrf_ids_by_table hashmap */
static struct vrf_ids_by_table_entry *vrf_ids_by_table_entry_new(void)
{
struct vrf_ids_by_table_entry *new_entry;
new_entry = XCALLOC(MTYPE_HASH_ENTRY,
sizeof(struct vrf_ids_by_table_entry));

return new_entry;
}

static void vrf_ids_by_table_delete(uint32_t table_id)
{
if (!vrf_ids_by_table_is_initialized)
return;

struct vrf_ids_by_table_entry lookup = {.table_id = table_id};
struct vrf_ids_by_table_entry *entry =
vrf_ids_by_table_find(&vrf_ids_by_table_head, &lookup);

if (entry) {
vrf_ids_by_table_del(&vrf_ids_by_table_head, entry);
XFREE(MTYPE_HASH_ENTRY, entry);
}
}

static void vrf_ids_by_table_update(uint32_t table_id, vrf_id_t new_vrf_id)
{
if (new_vrf_id == VRF_UNKNOWN)
return;

if (!vrf_ids_by_table_is_initialized) {
vrf_ids_by_table_init(&vrf_ids_by_table_head);
vrf_ids_by_table_is_initialized = 1;
}

struct vrf_ids_by_table_entry lookup = {.table_id = table_id};
struct vrf_ids_by_table_entry *entry =
vrf_ids_by_table_find(&vrf_ids_by_table_head, &lookup);

if (!entry) {
entry = vrf_ids_by_table_entry_new();
entry->table_id = table_id;
vrf_ids_by_table_add(&vrf_ids_by_table_head, entry);
}

entry->vrf_id = new_vrf_id;
}

/* VRF list existance check by name. */
struct vrf *vrf_lookup_by_name(const char *name)
{
struct vrf vrf;
strlcpy(vrf.name, name, sizeof(vrf.name));

return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
}

Expand Down Expand Up @@ -150,6 +230,7 @@ struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
if (!vrf && vrf_id != VRF_UNKNOWN)
vrf = vrf_lookup_by_id(vrf_id);

/* Unable to find VRF by either ID or name, so create */
if (vrf == NULL) {
vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
vrf->vrf_id = VRF_UNKNOWN;
Expand Down Expand Up @@ -200,6 +281,7 @@ struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)

/*Treat VRF add for existing vrf as update
* Update VRF ID and also update in VRF ID table
* and also update in vrf_ids_by_table hashmap
*/
if (name)
vrf = vrf_lookup_by_name(name);
Expand All @@ -222,6 +304,9 @@ struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
vrf->vrf_id = new_vrf_id;
RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);

/* Update hash map */
vrf_ids_by_table_update(vrf->data.l.table_id, new_vrf_id);

} else {

/*
Expand All @@ -232,6 +317,40 @@ struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
return vrf;
}

/* Update table_id in existing VRF.
* Arg:
* vrf - pointer to vrf struct.
* new_table_id - The table_id to be saved to vrf struct.
* Description: This function first checks if vrf struct has matching table_id
* matching new_table_id arg. If so, it ensures entry is created in
* vrf_ids_by_table hashmap and returns. If not matching, then it removes
* previous entry and adds new entry with new_table_id.
* Finally, it updates the table_id in the vrf struct.
*/
void vrf_update_table_id(struct vrf *vrf, uint32_t new_table_id)
{
if (!vrf)
return;

/* If new and old table ids are same */
if (new_table_id == vrf->data.l.table_id) {

/* Ensure that entry is added to hash map */
vrf_ids_by_table_update(new_table_id, vrf->vrf_id);

return;
}

/* New and old table ids are different
* so remove any entry with old table_id and vrf_id, and add new entry
*/
vrf_ids_by_table_delete(vrf->data.l.table_id);
vrf_ids_by_table_update(new_table_id, vrf->vrf_id);

/*Update table_id in vrf struct */
vrf->data.l.table_id = new_table_id;
}

/* Delete a VRF. This is called when the underlying VRF goes away, a
* pre-configured VRF is deleted or when shutting down (vrf_terminate()).
*/
Expand Down Expand Up @@ -263,6 +382,9 @@ void vrf_delete(struct vrf *vrf)
if (vrf_master.vrf_delete_hook)
(*vrf_master.vrf_delete_hook)(vrf);

/* remove from vrf_ids_by_table hash map*/
vrf_ids_by_table_delete(vrf->data.l.table_id);

QOBJ_UNREG(vrf);

if (vrf->name[0] != '\0')
Expand All @@ -279,6 +401,50 @@ struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
}

/* Finds vrf_id of vrf with table_id or ns_id.
*
* table_id
* The table_id associated with vrf of interest
*
* ns_id
* The ns_id associated with vrf of interest
*
* Description:
* This function checks if vrf is backened by netns
* or vrf lite, and looks them up appropriately.
* Hashmap look up implemented for vrf lite, but not netns.
*
* Returns:
* vrf_id if found table by table_id, or VRF_DEFAULT if not found
*/
vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;

/* case vrf with netns : match the netnsid */
if (vrf_is_backend_netns()) {
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
zvrf = vrf->info;
nathan-duddles marked this conversation as resolved.
Show resolved Hide resolved
if (zvrf == NULL)
continue;
if (ns_id == zvrf_id(zvrf))
return zvrf_id(zvrf);
}
/* case vrf with VRF_BACKEND_VRF_LITE : match the table_id */
} else if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {

struct vrf_ids_by_table_entry lookup = {.table_id = table_id};

struct vrf_ids_by_table_entry *entry =
vrf_ids_by_table_find(&vrf_ids_by_table_head, &lookup);
if (entry != NULL)
return entry->vrf_id;
}

return VRF_DEFAULT;
}

/*
* Enable a VRF - that is, let the VRF be ready to use.
* The VRF_ENABLE_HOOK callback will be called to inform
Expand Down Expand Up @@ -498,6 +664,10 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
vrf_master.vrf_disable_hook = disable;
vrf_master.vrf_delete_hook = destroy;

/* Initialize vrf_ids_by_table */
vrf_ids_by_table_init(&vrf_ids_by_table_head);
vrf_ids_by_table_is_initialized = 1;

/* The default VRF always exists. */
default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
if (!default_vrf) {
Expand Down Expand Up @@ -559,6 +729,10 @@ void vrf_terminate(void)
vrf = vrf_lookup_by_id(VRF_DEFAULT);
if (vrf)
vrf_terminate_single(vrf);

/* Clean up vrf_ids_by_table hashmap */
vrf_ids_by_table_fini(&vrf_ids_by_table_head);
vrf_ids_by_table_is_initialized = 0;
}

int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
Expand Down
2 changes: 2 additions & 0 deletions lib/vrf.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ extern struct vrf_name_head vrfs_by_name;

extern struct vrf *vrf_lookup_by_id(vrf_id_t);
extern struct vrf *vrf_lookup_by_name(const char *);
extern vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id);
extern struct vrf *vrf_get(vrf_id_t, const char *);
extern struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name);
extern void vrf_update_table_id(struct vrf *vrf, uint32_t new_table_id);
extern const char *vrf_id_to_name(vrf_id_t vrf_id);

#define VRF_LOGNAME(V) V ? V->name : "Unknown"
Expand Down
4 changes: 3 additions & 1 deletion lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -2150,7 +2150,9 @@ static int zclient_vrf_add(ZAPI_CALLBACK_ARGS)
if (!vrf)
return 0;

vrf->data.l.table_id = data.l.table_id;
/* set the vrf table_id if created*/
vrf_update_table_id(vrf, data.l.table_id);

memcpy(vrf->data.l.netns_name, data.l.netns_name, NS_NAMSIZ);
vrf_enable(vrf);

Expand Down
27 changes: 0 additions & 27 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,33 +361,6 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
return proto;
}

/*
Pending: create an efficient table_id (in a tree/hash) based lookup)
*/
vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;

RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
zvrf = vrf->info;
if (zvrf == NULL)
continue;
/* case vrf with netns : match the netnsid */
if (vrf_is_backend_netns()) {
if (ns_id == zvrf_id(zvrf))
return zvrf_id(zvrf);
} else {
/* VRF is VRF_BACKEND_VRF_LITE */
if (zvrf->table_id != table_id)
continue;
return zvrf_id(zvrf);
}
}

return VRF_DEFAULT;
}

/**
* @parse_encap_mpls() - Parses encapsulated mpls attributes
* @tb: Pointer to rtattr to look for nested items in.
Expand Down
1 change: 0 additions & 1 deletion zebra/rt_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
uint16_t vid);
extern int netlink_neigh_read_specific_ip(const struct ipaddr *ip,
struct interface *vlan_if);
extern vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id);

struct nl_batch;
extern enum netlink_msg_status
Expand Down