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 1 commit
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
Prev Previous commit
Next Next commit
lib: Add vrf_lookup_by_table with hashmap to vrf.c[h]
Lookup uses hashmap with table_id key and vrf_id values.
Only for vrf backended by vrf lite. Could do similar
implementation with ns_id in future.

Hashmap local to vrf.c but must be updated when
vrf is added or modified. For updates to vrf_id,
call to helper function vrf_ids_by_table_update()
is added in the publicly used vrf_update() function.

Previously, the table_id was set by directly modifying
vrf->data.l.table_id in zclient.c. However, as no functions
in vrf.c are notified when change occurs, a helper function,
vrf_update_table_id(), is added. This both updates
vrf_data.l.table_id, and updates the local hashmap.

vrf_delete() function used for removing vrfs. Add call to
here to vrf_ids_by_table_delete() helper function
to remove entries from hashmap.

Signed-off-by: Nathan Duddles <duddles.nathan@gmail.com>
  • Loading branch information
nathan-duddles committed Mar 17, 2022
commit 399a33c6bc9a654ab4b68f40cd314a2831d64e10
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