Skip to content

Commit

Permalink
Merge branch 'mlxsw-Un-offload-FDB-on-NVE-detach-attach'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
mlxsw: Un/offload FDB on NVE detach/attach

Petr says:

When a VXLAN device is attached to a bridge of a driver capable of
offloading such, or upped, the FDB entries already present at the device
need to be offloaded. Similarly when an offloaded VXLAN device ceases
being interesting (it is downed, or detached, or a front-panel port
netdevice is detached from the bridge that the VXLAN device is attached
to), any offloaded FDB entries need to be unoffloaded and unmarked. This
attach / detach processing is implemented in this patchset.

In patch Freescale#1, a code pattern is extracted into a named function for
easier reuse.

In patch Freescale#2, vxlan_fdb_replay() is added to send
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE for each FDB entry with a given VNI.
The intention is that the offloading driver will interpret these events
like any other and thus offload the FDB entries that existed prior to
VXLAN attach.

In patches Freescale#3 and Freescale#4, the functions vxlan_fdb_clear_offload() resp.
br_fdb_clear_offload() are added. These clear the offloaded flag at
matching FDB entries.

In patches Freescale#5-Freescale#9, we introduce FID-type-specific and NVE-type-specific
ops necessary to properly abstract invocations of the replay/clear
functions.

Finally patch Freescale#10 implements the FDB management.

In patch Freescale#11, the mlxsw-specific test case is extended to check that the
management of offload marks under the newly-supported situations is
correct. Patch Freescale#12, from Ido, exercises the new code paths in actual
functional test.

v2:
- Patch Freescale#1:
    - Modify vxlan_fdb_switchdev_notifier_info() to initialize the
      structure through a passed-in pointer argument, instead of returning
      it as a value.
- Patch Freescale#2:
    - Adapt to API change in vxlan_fdb_switchdev_notifier_info()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed Dec 7, 2018
2 parents 6b241e4 + 55939b2 commit 9f4c2cf
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 31 deletions.
16 changes: 11 additions & 5 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ enum mlxsw_sp_fid_type {
MLXSW_SP_FID_TYPE_MAX,
};

enum mlxsw_sp_nve_type {
MLXSW_SP_NVE_TYPE_VXLAN,
};

struct mlxsw_sp_mid {
struct list_head list;
unsigned char addr[ETH_ALEN];
Expand Down Expand Up @@ -383,6 +387,7 @@ int mlxsw_sp_bridge_vxlan_join(struct mlxsw_sp *mlxsw_sp,
struct netlink_ext_ack *extack);
void mlxsw_sp_bridge_vxlan_leave(struct mlxsw_sp *mlxsw_sp,
const struct net_device *vxlan_dev);
extern struct notifier_block mlxsw_sp_switchdev_notifier;

/* spectrum.c */
int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
Expand Down Expand Up @@ -745,16 +750,21 @@ bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid);
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);
int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
enum mlxsw_sp_nve_type *p_type);
struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
__be32 vni);
int mlxsw_sp_fid_vni(const struct mlxsw_sp_fid *fid, __be32 *vni);
int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
u32 nve_flood_index);
void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid);
bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid);
int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, __be32 vni, int nve_ifindex);
int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
__be32 vni, int nve_ifindex);
void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid);
bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid);
void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev);
int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
enum mlxsw_sp_flood_type packet_type, u8 local_port,
bool member);
Expand Down Expand Up @@ -823,10 +833,6 @@ extern const struct mlxsw_sp_mr_tcam_ops mlxsw_sp1_mr_tcam_ops;
extern const struct mlxsw_sp_mr_tcam_ops mlxsw_sp2_mr_tcam_ops;

/* spectrum_nve.c */
enum mlxsw_sp_nve_type {
MLXSW_SP_NVE_TYPE_VXLAN,
};

struct mlxsw_sp_nve_params {
enum mlxsw_sp_nve_type type;
__be32 vni;
Expand Down
44 changes: 43 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct mlxsw_sp_fid {
struct rhash_head ht_node;

struct rhash_head vni_ht_node;
enum mlxsw_sp_nve_type nve_type;
__be32 vni;
u32 nve_flood_index;
int nve_ifindex;
Expand Down Expand Up @@ -84,6 +85,8 @@ struct mlxsw_sp_fid_ops {
int (*nve_flood_index_set)(struct mlxsw_sp_fid *fid,
u32 nve_flood_index);
void (*nve_flood_index_clear)(struct mlxsw_sp_fid *fid);
void (*fdb_clear_offload)(const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev);
};

struct mlxsw_sp_fid_family {
Expand Down Expand Up @@ -151,6 +154,17 @@ int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex)
return 0;
}

int mlxsw_sp_fid_nve_type(const struct mlxsw_sp_fid *fid,
enum mlxsw_sp_nve_type *p_type)
{
if (!fid->vni_valid)
return -EINVAL;

*p_type = fid->nve_type;

return 0;
}

struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_vni(struct mlxsw_sp *mlxsw_sp,
__be32 vni)
{
Expand Down Expand Up @@ -211,7 +225,8 @@ bool mlxsw_sp_fid_nve_flood_index_is_set(const struct mlxsw_sp_fid *fid)
return fid->nve_flood_index_valid;
}

int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, __be32 vni, int nve_ifindex)
int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
__be32 vni, int nve_ifindex)
{
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
Expand All @@ -221,6 +236,7 @@ int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, __be32 vni, int nve_ifindex)
if (WARN_ON(!ops->vni_set || fid->vni_valid))
return -EINVAL;

fid->nve_type = type;
fid->nve_ifindex = nve_ifindex;
fid->vni = vni;
err = rhashtable_lookup_insert_fast(&mlxsw_sp->fid_core->vni_ht,
Expand Down Expand Up @@ -263,6 +279,16 @@ bool mlxsw_sp_fid_vni_is_set(const struct mlxsw_sp_fid *fid)
return fid->vni_valid;
}

void mlxsw_sp_fid_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev)
{
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
const struct mlxsw_sp_fid_ops *ops = fid_family->ops;

if (ops->fdb_clear_offload)
ops->fdb_clear_offload(fid, nve_dev);
}

static const struct mlxsw_sp_flood_table *
mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
enum mlxsw_sp_flood_type packet_type)
Expand Down Expand Up @@ -752,6 +778,13 @@ static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
fid->vni_valid, 0, false);
}

static void
mlxsw_sp_fid_8021d_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev)
{
br_fdb_clear_offload(nve_dev, 0);
}

static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
.setup = mlxsw_sp_fid_8021d_setup,
.configure = mlxsw_sp_fid_8021d_configure,
Expand All @@ -765,6 +798,7 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
.vni_clear = mlxsw_sp_fid_8021d_vni_clear,
.nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
.nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
.fdb_clear_offload = mlxsw_sp_fid_8021d_fdb_clear_offload,
};

static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
Expand Down Expand Up @@ -801,6 +835,13 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
.lag_vid_valid = 1,
};

static void
mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev)
{
br_fdb_clear_offload(nve_dev, mlxsw_sp_fid_8021q_vid(fid));
}

static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
.setup = mlxsw_sp_fid_8021q_setup,
.configure = mlxsw_sp_fid_8021d_configure,
Expand All @@ -814,6 +855,7 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
.vni_clear = mlxsw_sp_fid_8021d_vni_clear,
.nve_flood_index_set = mlxsw_sp_fid_8021d_nve_flood_index_set,
.nve_flood_index_clear = mlxsw_sp_fid_8021d_nve_flood_index_clear,
.fdb_clear_offload = mlxsw_sp_fid_8021q_fdb_clear_offload,
};

/* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
Expand Down
44 changes: 43 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,21 @@ static void mlxsw_sp_nve_fdb_flush_by_fid(struct mlxsw_sp *mlxsw_sp,
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdf), sfdf_pl);
}

static void mlxsw_sp_nve_fdb_clear_offload(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_fid *fid,
const struct net_device *nve_dev,
__be32 vni)
{
const struct mlxsw_sp_nve_ops *ops;
enum mlxsw_sp_nve_type type;

if (WARN_ON(mlxsw_sp_fid_nve_type(fid, &type)))
return;

ops = mlxsw_sp->nve->nve_ops_arr[type];
ops->fdb_clear_offload(nve_dev, vni);
}

int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
struct mlxsw_sp_nve_params *params,
struct netlink_ext_ack *extack)
Expand Down Expand Up @@ -817,16 +832,25 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
return err;
}

err = mlxsw_sp_fid_vni_set(fid, params->vni, params->dev->ifindex);
err = mlxsw_sp_fid_vni_set(fid, params->type, params->vni,
params->dev->ifindex);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed to set VNI on FID");
goto err_fid_vni_set;
}

nve->config = config;

err = ops->fdb_replay(params->dev, params->vni);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Failed to offload the FDB");
goto err_fdb_replay;
}

return 0;

err_fdb_replay:
mlxsw_sp_fid_vni_clear(fid);
err_fid_vni_set:
mlxsw_sp_nve_tunnel_fini(mlxsw_sp);
return err;
Expand All @@ -836,9 +860,27 @@ void mlxsw_sp_nve_fid_disable(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fid *fid)
{
u16 fid_index = mlxsw_sp_fid_index(fid);
struct net_device *nve_dev;
int nve_ifindex;
__be32 vni;

mlxsw_sp_nve_flood_ip_flush(mlxsw_sp, fid);
mlxsw_sp_nve_fdb_flush_by_fid(mlxsw_sp, fid_index);

if (WARN_ON(mlxsw_sp_fid_nve_ifindex(fid, &nve_ifindex) ||
mlxsw_sp_fid_vni(fid, &vni)))
goto out;

nve_dev = dev_get_by_index(&init_net, nve_ifindex);
if (!nve_dev)
goto out;

mlxsw_sp_nve_fdb_clear_offload(mlxsw_sp, fid, nve_dev, vni);
mlxsw_sp_fid_fdb_clear_offload(fid, nve_dev);

dev_put(nve_dev);

out:
mlxsw_sp_fid_vni_clear(fid);
mlxsw_sp_nve_tunnel_fini(mlxsw_sp);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct mlxsw_sp_nve_ops {
int (*init)(struct mlxsw_sp_nve *nve,
const struct mlxsw_sp_nve_config *config);
void (*fini)(struct mlxsw_sp_nve *nve);
int (*fdb_replay)(const struct net_device *nve_dev, __be32 vni);
void (*fdb_clear_offload)(const struct net_device *nve_dev, __be32 vni);
};

extern const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops;
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,30 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
config->udp_dport);
}

static int
mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni)
{
if (WARN_ON(!netif_is_vxlan(nve_dev)))
return -EINVAL;
return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier);
}

static void
mlxsw_sp_nve_vxlan_clear_offload(const struct net_device *nve_dev, __be32 vni)
{
if (WARN_ON(!netif_is_vxlan(nve_dev)))
return;
vxlan_fdb_clear_offload(nve_dev, vni);
}

const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = {
.type = MLXSW_SP_NVE_TYPE_VXLAN,
.can_offload = mlxsw_sp1_nve_vxlan_can_offload,
.nve_config = mlxsw_sp_nve_vxlan_config,
.init = mlxsw_sp1_nve_vxlan_init,
.fini = mlxsw_sp1_nve_vxlan_fini,
.fdb_replay = mlxsw_sp_nve_vxlan_fdb_replay,
.fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload,
};

static bool mlxsw_sp2_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve,
Expand All @@ -242,4 +260,6 @@ const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
.nve_config = mlxsw_sp_nve_vxlan_config,
.init = mlxsw_sp2_nve_vxlan_init,
.fini = mlxsw_sp2_nve_vxlan_fini,
.fdb_replay = mlxsw_sp_nve_vxlan_fdb_replay,
.fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload,
};
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3186,7 +3186,7 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
return NOTIFY_BAD;
}

static struct notifier_block mlxsw_sp_switchdev_notifier = {
struct notifier_block mlxsw_sp_switchdev_notifier = {
.notifier_call = mlxsw_sp_switchdev_event,
};

Expand Down
Loading

0 comments on commit 9f4c2cf

Please sign in to comment.