Commit 5e9c16cc authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

mlxsw: spectrum_router: Implement private fib

Shadow FIB is needed in order to hold additional information for FIB
entries and keep track of used prefixes. That is needed for the LPM tree
construction to be introduced later on in this set.
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f48cc6b2
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/dcbnl.h> #include <linux/dcbnl.h>
#include <linux/in6.h>
#include <net/switchdev.h> #include <net/switchdev.h>
#include "port.h" #include "port.h"
...@@ -160,6 +161,12 @@ struct mlxsw_sp_sb { ...@@ -160,6 +161,12 @@ struct mlxsw_sp_sb {
} ports[MLXSW_PORT_MAX_PORTS]; } ports[MLXSW_PORT_MAX_PORTS];
}; };
#define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE)
struct mlxsw_sp_prefix_usage {
DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT);
};
struct mlxsw_sp { struct mlxsw_sp {
struct { struct {
struct list_head list; struct list_head list;
......
...@@ -35,11 +35,131 @@ ...@@ -35,11 +35,131 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/rhashtable.h>
#include <linux/bitops.h>
#include <linux/in6.h>
#include "spectrum.h" #include "spectrum.h"
#include "core.h" #include "core.h"
#include "reg.h" #include "reg.h"
static void
mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
unsigned char prefix_len)
{
set_bit(prefix_len, prefix_usage->b);
}
static void
mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
unsigned char prefix_len)
{
clear_bit(prefix_len, prefix_usage->b);
}
struct mlxsw_sp_fib_key {
unsigned char addr[sizeof(struct in6_addr)];
unsigned char prefix_len;
};
struct mlxsw_sp_fib_entry {
struct rhash_head ht_node;
struct mlxsw_sp_fib_key key;
};
struct mlxsw_sp_fib {
struct rhashtable ht;
unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
struct mlxsw_sp_prefix_usage prefix_usage;
};
static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
.key_offset = offsetof(struct mlxsw_sp_fib_entry, key),
.head_offset = offsetof(struct mlxsw_sp_fib_entry, ht_node),
.key_len = sizeof(struct mlxsw_sp_fib_key),
.automatic_shrinking = true,
};
static int mlxsw_sp_fib_entry_insert(struct mlxsw_sp_fib *fib,
struct mlxsw_sp_fib_entry *fib_entry)
{
unsigned char prefix_len = fib_entry->key.prefix_len;
int err;
err = rhashtable_insert_fast(&fib->ht, &fib_entry->ht_node,
mlxsw_sp_fib_ht_params);
if (err)
return err;
if (fib->prefix_ref_count[prefix_len]++ == 0)
mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len);
return 0;
}
static void mlxsw_sp_fib_entry_remove(struct mlxsw_sp_fib *fib,
struct mlxsw_sp_fib_entry *fib_entry)
{
unsigned char prefix_len = fib_entry->key.prefix_len;
if (--fib->prefix_ref_count[prefix_len] == 0)
mlxsw_sp_prefix_usage_clear(&fib->prefix_usage, prefix_len);
rhashtable_remove_fast(&fib->ht, &fib_entry->ht_node,
mlxsw_sp_fib_ht_params);
}
static struct mlxsw_sp_fib_entry *
mlxsw_sp_fib_entry_create(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len)
{
struct mlxsw_sp_fib_entry *fib_entry;
fib_entry = kzalloc(sizeof(*fib_entry), GFP_KERNEL);
if (!fib_entry)
return NULL;
memcpy(fib_entry->key.addr, addr, addr_len);
fib_entry->key.prefix_len = prefix_len;
return fib_entry;
}
static void mlxsw_sp_fib_entry_destroy(struct mlxsw_sp_fib_entry *fib_entry)
{
kfree(fib_entry);
}
static struct mlxsw_sp_fib_entry *
mlxsw_sp_fib_entry_lookup(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len)
{
struct mlxsw_sp_fib_key key = {{ 0 } };
memcpy(key.addr, addr, addr_len);
key.prefix_len = prefix_len;
return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
}
static struct mlxsw_sp_fib *mlxsw_sp_fib_create(void)
{
struct mlxsw_sp_fib *fib;
int err;
fib = kzalloc(sizeof(*fib), GFP_KERNEL);
if (!fib)
return ERR_PTR(-ENOMEM);
err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
if (err)
goto err_rhashtable_init;
return fib;
err_rhashtable_init:
kfree(fib);
return ERR_PTR(err);
}
static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib *fib)
{
rhashtable_destroy(&fib->ht);
kfree(fib);
}
static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
{ {
char rgcr_pl[MLXSW_REG_RGCR_LEN]; char rgcr_pl[MLXSW_REG_RGCR_LEN];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment