Skip to content

Commit e846efe

Browse files
Amit Cohendavem330
authored andcommitted
mlxsw: spectrum: Add hash table for IPv6 address mapping
The device supports forwarding entries such as routes and FDBs that perform tunnel (e.g., VXLAN, IP-in-IP) encapsulation or decapsulation. When the underlay is IPv6, these entries do not encode the 128 bit IPv6 address used for encapsulation / decapsulation. Instead, these entries encode a 24 bit pointer to an array called KVDL where the IPv6 address is stored. Currently, only IP-in-IP with IPv6 underlay is supported, but subsequent patches will add support for VxLAN with IPv6 underlay. To avoid duplicating the logic required to store and retrieve these IPv6 addresses, introduce a hash table that will store the mapping between IPv6 addresses and their KVDL index. Signed-off-by: Amit Cohen <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f71f1bc commit e846efe

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,140 @@ static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
27552755
mutex_destroy(&mlxsw_sp->parsing.lock);
27562756
}
27572757

2758+
struct mlxsw_sp_ipv6_addr_node {
2759+
struct in6_addr key;
2760+
struct rhash_head ht_node;
2761+
u32 kvdl_index;
2762+
refcount_t refcount;
2763+
};
2764+
2765+
static const struct rhashtable_params mlxsw_sp_ipv6_addr_ht_params = {
2766+
.key_offset = offsetof(struct mlxsw_sp_ipv6_addr_node, key),
2767+
.head_offset = offsetof(struct mlxsw_sp_ipv6_addr_node, ht_node),
2768+
.key_len = sizeof(struct in6_addr),
2769+
.automatic_shrinking = true,
2770+
};
2771+
2772+
static int
2773+
mlxsw_sp_ipv6_addr_init(struct mlxsw_sp *mlxsw_sp, const struct in6_addr *addr6,
2774+
u32 *p_kvdl_index)
2775+
{
2776+
struct mlxsw_sp_ipv6_addr_node *node;
2777+
char rips_pl[MLXSW_REG_RIPS_LEN];
2778+
int err;
2779+
2780+
err = mlxsw_sp_kvdl_alloc(mlxsw_sp,
2781+
MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS, 1,
2782+
p_kvdl_index);
2783+
if (err)
2784+
return err;
2785+
2786+
mlxsw_reg_rips_pack(rips_pl, *p_kvdl_index, addr6);
2787+
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rips), rips_pl);
2788+
if (err)
2789+
goto err_rips_write;
2790+
2791+
node = kzalloc(sizeof(*node), GFP_KERNEL);
2792+
if (!node) {
2793+
err = -ENOMEM;
2794+
goto err_node_alloc;
2795+
}
2796+
2797+
node->key = *addr6;
2798+
node->kvdl_index = *p_kvdl_index;
2799+
refcount_set(&node->refcount, 1);
2800+
2801+
err = rhashtable_insert_fast(&mlxsw_sp->ipv6_addr_ht,
2802+
&node->ht_node,
2803+
mlxsw_sp_ipv6_addr_ht_params);
2804+
if (err)
2805+
goto err_rhashtable_insert;
2806+
2807+
return 0;
2808+
2809+
err_rhashtable_insert:
2810+
kfree(node);
2811+
err_node_alloc:
2812+
err_rips_write:
2813+
mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS, 1,
2814+
*p_kvdl_index);
2815+
return err;
2816+
}
2817+
2818+
static void mlxsw_sp_ipv6_addr_fini(struct mlxsw_sp *mlxsw_sp,
2819+
struct mlxsw_sp_ipv6_addr_node *node)
2820+
{
2821+
u32 kvdl_index = node->kvdl_index;
2822+
2823+
rhashtable_remove_fast(&mlxsw_sp->ipv6_addr_ht, &node->ht_node,
2824+
mlxsw_sp_ipv6_addr_ht_params);
2825+
kfree(node);
2826+
mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS, 1,
2827+
kvdl_index);
2828+
}
2829+
2830+
int mlxsw_sp_ipv6_addr_kvdl_index_get(struct mlxsw_sp *mlxsw_sp,
2831+
const struct in6_addr *addr6,
2832+
u32 *p_kvdl_index)
2833+
{
2834+
struct mlxsw_sp_ipv6_addr_node *node;
2835+
int err = 0;
2836+
2837+
mutex_lock(&mlxsw_sp->ipv6_addr_ht_lock);
2838+
node = rhashtable_lookup_fast(&mlxsw_sp->ipv6_addr_ht, addr6,
2839+
mlxsw_sp_ipv6_addr_ht_params);
2840+
if (node) {
2841+
refcount_inc(&node->refcount);
2842+
*p_kvdl_index = node->kvdl_index;
2843+
goto out_unlock;
2844+
}
2845+
2846+
err = mlxsw_sp_ipv6_addr_init(mlxsw_sp, addr6, p_kvdl_index);
2847+
2848+
out_unlock:
2849+
mutex_unlock(&mlxsw_sp->ipv6_addr_ht_lock);
2850+
return err;
2851+
}
2852+
2853+
void
2854+
mlxsw_sp_ipv6_addr_put(struct mlxsw_sp *mlxsw_sp, const struct in6_addr *addr6)
2855+
{
2856+
struct mlxsw_sp_ipv6_addr_node *node;
2857+
2858+
mutex_lock(&mlxsw_sp->ipv6_addr_ht_lock);
2859+
node = rhashtable_lookup_fast(&mlxsw_sp->ipv6_addr_ht, addr6,
2860+
mlxsw_sp_ipv6_addr_ht_params);
2861+
if (WARN_ON(!node))
2862+
goto out_unlock;
2863+
2864+
if (!refcount_dec_and_test(&node->refcount))
2865+
goto out_unlock;
2866+
2867+
mlxsw_sp_ipv6_addr_fini(mlxsw_sp, node);
2868+
2869+
out_unlock:
2870+
mutex_unlock(&mlxsw_sp->ipv6_addr_ht_lock);
2871+
}
2872+
2873+
static int mlxsw_sp_ipv6_addr_ht_init(struct mlxsw_sp *mlxsw_sp)
2874+
{
2875+
int err;
2876+
2877+
err = rhashtable_init(&mlxsw_sp->ipv6_addr_ht,
2878+
&mlxsw_sp_ipv6_addr_ht_params);
2879+
if (err)
2880+
return err;
2881+
2882+
mutex_init(&mlxsw_sp->ipv6_addr_ht_lock);
2883+
return 0;
2884+
}
2885+
2886+
static void mlxsw_sp_ipv6_addr_ht_fini(struct mlxsw_sp *mlxsw_sp)
2887+
{
2888+
mutex_destroy(&mlxsw_sp->ipv6_addr_ht_lock);
2889+
rhashtable_destroy(&mlxsw_sp->ipv6_addr_ht);
2890+
}
2891+
27582892
static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
27592893
const struct mlxsw_bus_info *mlxsw_bus_info,
27602894
struct netlink_ext_ack *extack)
@@ -2843,6 +2977,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
28432977
goto err_afa_init;
28442978
}
28452979

2980+
err = mlxsw_sp_ipv6_addr_ht_init(mlxsw_sp);
2981+
if (err) {
2982+
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize hash table for IPv6 addresses\n");
2983+
goto err_ipv6_addr_ht_init;
2984+
}
2985+
28462986
err = mlxsw_sp_nve_init(mlxsw_sp);
28472987
if (err) {
28482988
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize NVE\n");
@@ -2944,6 +3084,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
29443084
err_acl_init:
29453085
mlxsw_sp_nve_fini(mlxsw_sp);
29463086
err_nve_init:
3087+
mlxsw_sp_ipv6_addr_ht_fini(mlxsw_sp);
3088+
err_ipv6_addr_ht_init:
29473089
mlxsw_sp_afa_fini(mlxsw_sp);
29483090
err_afa_init:
29493091
mlxsw_sp_counter_pool_fini(mlxsw_sp);
@@ -3075,6 +3217,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
30753217
mlxsw_sp_router_fini(mlxsw_sp);
30763218
mlxsw_sp_acl_fini(mlxsw_sp);
30773219
mlxsw_sp_nve_fini(mlxsw_sp);
3220+
mlxsw_sp_ipv6_addr_ht_fini(mlxsw_sp);
30783221
mlxsw_sp_afa_fini(mlxsw_sp);
30793222
mlxsw_sp_counter_pool_fini(mlxsw_sp);
30803223
mlxsw_sp_switchdev_fini(mlxsw_sp);

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ struct mlxsw_sp {
203203
const struct mlxsw_listener *listeners;
204204
size_t listeners_count;
205205
u32 lowest_shaper_bs;
206+
struct rhashtable ipv6_addr_ht;
207+
struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
206208
};
207209

208210
struct mlxsw_sp_ptp_ops {
@@ -587,6 +589,11 @@ mlxsw_sp_sample_trigger_params_set(struct mlxsw_sp *mlxsw_sp,
587589
void
588590
mlxsw_sp_sample_trigger_params_unset(struct mlxsw_sp *mlxsw_sp,
589591
const struct mlxsw_sp_sample_trigger *trigger);
592+
int mlxsw_sp_ipv6_addr_kvdl_index_get(struct mlxsw_sp *mlxsw_sp,
593+
const struct in6_addr *addr6,
594+
u32 *p_kvdl_index);
595+
void
596+
mlxsw_sp_ipv6_addr_put(struct mlxsw_sp *mlxsw_sp, const struct in6_addr *addr6);
590597

591598
extern const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals;
592599
extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals;

0 commit comments

Comments
 (0)