mlxsw: spectrum_fid: Allow FID lookup by its index
authorIdo Schimmel <idosch@mellanox.com>
Wed, 21 Nov 2018 08:02:45 +0000 (08:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 22 Nov 2018 01:10:31 +0000 (17:10 -0800)
When processing a notification about a new FDB entry learned from a
VxLAN tunnel, the driver is provided with the FID index among other
parameters.

The driver potentially needs to update the bridge and VxLAN drivers
about the new entry using a pointer to the VxLAN device and the
corresponding VNI.

These two parameters are stored in the FID, so add a new function that
allows looking up a FID based on its index.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c

index b8f00863a0c6290c583a2cb19567f650585f29f8..879ac65886af8006539a31f3345100ff73af6b40 100644 (file)
@@ -721,6 +721,8 @@ int mlxsw_sp_setup_tc_prio(struct mlxsw_sp_port *mlxsw_sp_port,
                           struct tc_prio_qopt_offload *p);
 
 /* spectrum_fid.c */
+struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
+                                                 u16 fid_index);
 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex);
 struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
                                                __be32 vni);
index ad2bc8e3b2edb529c7a0331d28232882a8926b2d..71b2d20afcc258548385cc3a1d9fb6f474c6a704 100644 (file)
@@ -15,6 +15,7 @@
 struct mlxsw_sp_fid_family;
 
 struct mlxsw_sp_fid_core {
+       struct rhashtable fid_ht;
        struct rhashtable vni_ht;
        struct mlxsw_sp_fid_family *fid_family_arr[MLXSW_SP_FID_TYPE_MAX];
        unsigned int *port_fid_mappings;
@@ -26,6 +27,7 @@ struct mlxsw_sp_fid {
        unsigned int ref_count;
        u16 fid_index;
        struct mlxsw_sp_fid_family *fid_family;
+       struct rhash_head ht_node;
 
        struct rhash_head vni_ht_node;
        __be32 vni;
@@ -45,6 +47,12 @@ struct mlxsw_sp_fid_8021d {
        int br_ifindex;
 };
 
+static const struct rhashtable_params mlxsw_sp_fid_ht_params = {
+       .key_len = sizeof_field(struct mlxsw_sp_fid, fid_index),
+       .key_offset = offsetof(struct mlxsw_sp_fid, fid_index),
+       .head_offset = offsetof(struct mlxsw_sp_fid, ht_node),
+};
+
 static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
        .key_len = sizeof_field(struct mlxsw_sp_fid, vni),
        .key_offset = offsetof(struct mlxsw_sp_fid, vni),
@@ -114,6 +122,19 @@ static const int *mlxsw_sp_packet_type_sfgc_types[] = {
        [MLXSW_SP_FLOOD_TYPE_MC]        = mlxsw_sp_sfgc_mc_packet_types,
 };
 
+struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
+                                                 u16 fid_index)
+{
+       struct mlxsw_sp_fid *fid;
+
+       fid = rhashtable_lookup_fast(&mlxsw_sp->fid_core->fid_ht, &fid_index,
+                                    mlxsw_sp_fid_ht_params);
+       if (fid)
+               fid->ref_count++;
+
+       return fid;
+}
+
 int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
 {
        if (!fid->vni_valid)
@@ -956,10 +977,17 @@ static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_configure;
 
+       err = rhashtable_insert_fast(&mlxsw_sp->fid_core->fid_ht, &fid->ht_node,
+                                    mlxsw_sp_fid_ht_params);
+       if (err)
+               goto err_rhashtable_insert;
+
        list_add(&fid->list, &fid_family->fids_list);
        fid->ref_count++;
        return fid;
 
+err_rhashtable_insert:
+       fid->fid_family->ops->deconfigure(fid);
 err_configure:
        __clear_bit(fid_index - fid_family->start_index,
                    fid_family->fids_bitmap);
@@ -971,6 +999,7 @@ err_index_alloc:
 void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
 {
        struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
+       struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
 
        if (--fid->ref_count == 1 && fid->rif) {
                /* Destroy the associated RIF and let it drop the last
@@ -979,6 +1008,8 @@ void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid)
                return mlxsw_sp_rif_destroy(fid->rif);
        } else if (fid->ref_count == 0) {
                list_del(&fid->list);
+               rhashtable_remove_fast(&mlxsw_sp->fid_core->fid_ht,
+                                      &fid->ht_node, mlxsw_sp_fid_ht_params);
                fid->fid_family->ops->deconfigure(fid);
                __clear_bit(fid->fid_index - fid_family->start_index,
                            fid_family->fids_bitmap);
@@ -1138,9 +1169,13 @@ int mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp)
                return -ENOMEM;
        mlxsw_sp->fid_core = fid_core;
 
+       err = rhashtable_init(&fid_core->fid_ht, &mlxsw_sp_fid_ht_params);
+       if (err)
+               goto err_rhashtable_fid_init;
+
        err = rhashtable_init(&fid_core->vni_ht, &mlxsw_sp_fid_vni_ht_params);
        if (err)
-               goto err_rhashtable_init;
+               goto err_rhashtable_vni_init;
 
        fid_core->port_fid_mappings = kcalloc(max_ports, sizeof(unsigned int),
                                              GFP_KERNEL);
@@ -1169,7 +1204,9 @@ err_fid_ops_register:
        kfree(fid_core->port_fid_mappings);
 err_alloc_port_fid_mappings:
        rhashtable_destroy(&fid_core->vni_ht);
-err_rhashtable_init:
+err_rhashtable_vni_init:
+       rhashtable_destroy(&fid_core->fid_ht);
+err_rhashtable_fid_init:
        kfree(fid_core);
        return err;
 }
@@ -1184,5 +1221,6 @@ void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp)
                                               fid_core->fid_family_arr[i]);
        kfree(fid_core->port_fid_mappings);
        rhashtable_destroy(&fid_core->vni_ht);
+       rhashtable_destroy(&fid_core->fid_ht);
        kfree(fid_core);
 }