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 2 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
142 changes: 142 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 Down Expand Up @@ -57,6 +58,62 @@ static int vrf_backend;
static int vrf_backend_configured;
static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;

/*Hash Table for table_id based lookup of vrf_id*/
PREDECL_HASH(vrf_ids_by_table);

struct vrf_ids_by_table_proxy {
struct vrf_ids_by_table_item vrf_ids_by_table_hash_item;
uint32_t table_id;
vrf_id_t vrf_id;
};

static struct vrf_ids_by_table_head vrf_ids_by_table_head;

static int vrf_ids_by_table_cmp(const struct vrf_ids_by_table_proxy *item_a,
const struct vrf_ids_by_table_proxy *item_b)
{
return (item_a->table_id == item_b->table_id);
nathan-duddles marked this conversation as resolved.
Show resolved Hide resolved
}

static uint32_t vrf_ids_by_table_hash(const struct vrf_ids_by_table_proxy *item)
{
return item->table_id;
nathan-duddles marked this conversation as resolved.
Show resolved Hide resolved
}

DECLARE_HASH(vrf_ids_by_table, struct vrf_ids_by_table_proxy,
vrf_ids_by_table_hash_item, vrf_ids_by_table_cmp,
vrf_ids_by_table_hash);

/* Helper functions for vrf_ids_by_table hashmap */
static void vrf_ids_by_table_delete(uint32_t table_id, vrf_id_t vrf_id)
{
struct vrf_ids_by_table_proxy ref = {.table_id = table_id};
struct vrf_ids_by_table_proxy *item =
vrf_ids_by_table_find(&vrf_ids_by_table_head, &ref);

/* If entry contains both table_id and vrf_id, remove from hashmap */
if (item != NULL && item->vrf_id == vrf_id) {
vrf_ids_by_table_del(&vrf_ids_by_table_head, &ref);
}
}

static void vrf_ids_by_table_update(uint32_t table_id, vrf_id_t new_vrf_id)
{
struct vrf_ids_by_table_proxy ref = {.table_id = table_id,
.vrf_id = new_vrf_id};

/* If not already in hashmap, adds and returns null;
* otherwise returns current entry
*/
struct vrf_ids_by_table_proxy *item =
vrf_ids_by_table_add(&vrf_ids_by_table_head, &ref);

/* If current entry with table_id, then update */
if (item != NULL) {
item->vrf_id = new_vrf_id;
}
}

/*
* Turn on/off debug code
* for vrf.
Expand Down Expand Up @@ -150,6 +207,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 +258,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 +281,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 +294,38 @@ 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 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->vrf_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 +357,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, vrf->vrf_id);

QOBJ_UNREG(vrf);

if (vrf->name[0] != '\0')
Expand All @@ -279,6 +376,51 @@ 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_proxy ref = {.table_id = table_id};

struct vrf_ids_by_table_proxy *found_entry =
vrf_ids_by_table_find(&vrf_ids_by_table_head, &ref);
if (found_entry != NULL) {
return found_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
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