Skip to content

Commit

Permalink
Merge branch 'mlxsw-refactor-parser'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
mlxsw: Refactor parsing configuration

The Spectrum ASIC has a configurable limit on how deep into the packet
it parses. By default, the limit is 96 bytes.

There are several cases where this parsing depth is not enough and there
is a need to increase it: Decapsulation of VxLAN packets and
timestamping of PTP packets.

Currently, parsing depth API is maintained as part of VxLAN module,
because the MPRS register which configures parsing depth also configures
UDP destination port number used for VxLAN encapsulation and
decapsulation.

However, in addition to two above mentioned users of this API, the
multipath hash code also needs to invoke it in order to correctly hash
based on inner fields of IPv6-in-IPv6 packets.

Upcoming support for IPv6-in-IPv6 tunneling will add another user, as
without increasing the parsing depth such packets cannot be properly
decapsulated.

Therefore, this patchset refactors the parsing configuration API and
moves it out of the VxLAN module to the main driver code.

Tested using existing selftests.

Patch set overview:

Patch #1 adds the new parsing configuration infrastructure.
Patch #2 converts existing users to the new infrastructure.
Patch #3 deletes the old infrastructure.
Patch #4 calls the new infrastructure from the multipath hash code.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Aug 22, 2021
2 parents 809159e + 43c1b83 commit dddb6c2
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 78 deletions.
82 changes: 82 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -2717,6 +2717,22 @@ mlxsw_sp_sample_trigger_params_unset(struct mlxsw_sp *mlxsw_sp,
static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr);

#define MLXSW_SP_DEFAULT_PARSING_DEPTH 96
#define MLXSW_SP_INCREASED_PARSING_DEPTH 128
#define MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT 4789

static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp)
{
mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH;
mlxsw_sp->parsing.vxlan_udp_dport = MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT;
mutex_init(&mlxsw_sp->parsing.lock);
}

static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
{
mutex_destroy(&mlxsw_sp->parsing.lock);
}

static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info,
struct netlink_ext_ack *extack)
Expand All @@ -2727,6 +2743,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->core = mlxsw_core;
mlxsw_sp->bus_info = mlxsw_bus_info;

mlxsw_sp_parsing_init(mlxsw_sp);
mlxsw_core_emad_string_tlv_enable(mlxsw_core);

err = mlxsw_sp_base_mac_get(mlxsw_sp);
Expand Down Expand Up @@ -2926,6 +2943,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp_fids_fini(mlxsw_sp);
err_fids_init:
mlxsw_sp_kvdl_fini(mlxsw_sp);
mlxsw_sp_parsing_fini(mlxsw_sp);
return err;
}

Expand Down Expand Up @@ -3046,6 +3064,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_policers_fini(mlxsw_sp);
mlxsw_sp_fids_fini(mlxsw_sp);
mlxsw_sp_kvdl_fini(mlxsw_sp);
mlxsw_sp_parsing_fini(mlxsw_sp);
}

/* Per-FID flood tables are used for both "true" 802.1D FIDs and emulated
Expand Down Expand Up @@ -3611,6 +3630,69 @@ void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port)
dev_put(mlxsw_sp_port->dev);
}

int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp)
{
char mprs_pl[MLXSW_REG_MPRS_LEN];
int err = 0;

mutex_lock(&mlxsw_sp->parsing.lock);

if (refcount_inc_not_zero(&mlxsw_sp->parsing.parsing_depth_ref))
goto out_unlock;

mlxsw_reg_mprs_pack(mprs_pl, MLXSW_SP_INCREASED_PARSING_DEPTH,
mlxsw_sp->parsing.vxlan_udp_dport);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
if (err)
goto out_unlock;

mlxsw_sp->parsing.parsing_depth = MLXSW_SP_INCREASED_PARSING_DEPTH;
refcount_set(&mlxsw_sp->parsing.parsing_depth_ref, 1);

out_unlock:
mutex_unlock(&mlxsw_sp->parsing.lock);
return err;
}

void mlxsw_sp_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp)
{
char mprs_pl[MLXSW_REG_MPRS_LEN];

mutex_lock(&mlxsw_sp->parsing.lock);

if (!refcount_dec_and_test(&mlxsw_sp->parsing.parsing_depth_ref))
goto out_unlock;

mlxsw_reg_mprs_pack(mprs_pl, MLXSW_SP_DEFAULT_PARSING_DEPTH,
mlxsw_sp->parsing.vxlan_udp_dport);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH;

out_unlock:
mutex_unlock(&mlxsw_sp->parsing.lock);
}

int mlxsw_sp_parsing_vxlan_udp_dport_set(struct mlxsw_sp *mlxsw_sp,
__be16 udp_dport)
{
char mprs_pl[MLXSW_REG_MPRS_LEN];
int err;

mutex_lock(&mlxsw_sp->parsing.lock);

mlxsw_reg_mprs_pack(mprs_pl, mlxsw_sp->parsing.parsing_depth,
be16_to_cpu(udp_dport));
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
if (err)
goto out_unlock;

mlxsw_sp->parsing.vxlan_udp_dport = be16_to_cpu(udp_dport);

out_unlock:
mutex_unlock(&mlxsw_sp->parsing.lock);
return err;
}

static void
mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *lag_dev)
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ struct mlxsw_sp_port_mapping {
u8 lane;
};

struct mlxsw_sp_parsing {
refcount_t parsing_depth_ref;
u16 parsing_depth;
u16 vxlan_udp_dport;
struct mutex lock; /* Protects parsing configuration */
};

struct mlxsw_sp {
struct mlxsw_sp_port **ports;
struct mlxsw_core *core;
Expand All @@ -173,6 +180,7 @@ struct mlxsw_sp {
struct mlxsw_sp_counter_pool *counter_pool;
struct mlxsw_sp_span *span;
struct mlxsw_sp_trap *trap;
struct mlxsw_sp_parsing parsing;
const struct mlxsw_sp_switchdev_ops *switchdev_ops;
const struct mlxsw_sp_kvdl_ops *kvdl_ops;
const struct mlxsw_afa_ops *afa_ops;
Expand Down Expand Up @@ -652,6 +660,10 @@ struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_parsing_vxlan_udp_dport_set(struct mlxsw_sp *mlxsw_sp,
__be16 udp_dport);

/* spectrum_dcb.c */
#ifdef CONFIG_MLXSW_SPECTRUM_DCB
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ struct mlxsw_sp_nve {
unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
u32 tunnel_index;
u16 ul_rif_index; /* Reserved for Spectrum */
unsigned int inc_parsing_depth_refs;
};

struct mlxsw_sp_nve_ops {
Expand Down
94 changes: 20 additions & 74 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@
#include "spectrum.h"
#include "spectrum_nve.h"

/* Eth (18B) | IPv6 (40B) | UDP (8B) | VxLAN (8B) | Eth (14B) | IPv6 (40B)
*
* In the worst case - where we have a VLAN tag on the outer Ethernet
* header and IPv6 in overlay and underlay - we need to parse 128 bytes
*/
#define MLXSW_SP_NVE_VXLAN_PARSING_DEPTH 128
#define MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH 96

#define MLXSW_SP_NVE_VXLAN_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \
VXLAN_F_LEARN)

Expand Down Expand Up @@ -115,66 +107,6 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
config->udp_dport = cfg->dst_port;
}

static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
unsigned int parsing_depth,
__be16 udp_dport)
{
char mprs_pl[MLXSW_REG_MPRS_LEN];

mlxsw_reg_mprs_pack(mprs_pl, parsing_depth, be16_to_cpu(udp_dport));
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
}

static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
__be16 udp_dport)
{
int parsing_depth = mlxsw_sp->nve->inc_parsing_depth_refs ?
MLXSW_SP_NVE_VXLAN_PARSING_DEPTH :
MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH;

return __mlxsw_sp_nve_parsing_set(mlxsw_sp, parsing_depth, udp_dport);
}

static int
__mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp,
__be16 udp_dport)
{
int err;

mlxsw_sp->nve->inc_parsing_depth_refs++;

err = mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
if (err)
goto err_nve_parsing_set;
return 0;

err_nve_parsing_set:
mlxsw_sp->nve->inc_parsing_depth_refs--;
return err;
}

static void
__mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp,
__be16 udp_dport)
{
mlxsw_sp->nve->inc_parsing_depth_refs--;
mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
}

int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp)
{
__be16 udp_dport = mlxsw_sp->nve->config.udp_dport;

return __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, udp_dport);
}

void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp)
{
__be16 udp_dport = mlxsw_sp->nve->config.udp_dport;

__mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, udp_dport);
}

static void
mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
const struct mlxsw_sp_nve_config *config)
Expand Down Expand Up @@ -238,10 +170,14 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
int err;

err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
err = mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, config->udp_dport);
if (err)
return err;

err = mlxsw_sp_parsing_depth_inc(mlxsw_sp);
if (err)
goto err_parsing_depth_inc;

err = mlxsw_sp1_nve_vxlan_config_set(mlxsw_sp, config);
if (err)
goto err_config_set;
Expand All @@ -263,7 +199,9 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
err_rtdp_set:
mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
err_config_set:
__mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
mlxsw_sp_parsing_depth_dec(mlxsw_sp);
err_parsing_depth_inc:
mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0);
return err;
}

Expand All @@ -275,7 +213,8 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
config->ul_proto, &config->ul_sip);
mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
__mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
mlxsw_sp_parsing_depth_dec(mlxsw_sp);
mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0);
}

static int
Expand Down Expand Up @@ -412,10 +351,14 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
int err;

err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
err = mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, config->udp_dport);
if (err)
return err;

err = mlxsw_sp_parsing_depth_inc(mlxsw_sp);
if (err)
goto err_parsing_depth_inc;

err = mlxsw_sp2_nve_vxlan_config_set(mlxsw_sp, config);
if (err)
goto err_config_set;
Expand All @@ -438,7 +381,9 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
err_rtdp_set:
mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
err_config_set:
__mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
mlxsw_sp_parsing_depth_dec(mlxsw_sp);
err_parsing_depth_inc:
mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0);
return err;
}

Expand All @@ -450,7 +395,8 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
config->ul_proto, &config->ul_sip);
mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
__mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
mlxsw_sp_parsing_depth_dec(mlxsw_sp);
mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0);
}

const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,14 +975,14 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
}

if ((ing_types || egr_types) && !(orig_ing_types || orig_egr_types)) {
err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
err = mlxsw_sp_parsing_depth_inc(mlxsw_sp);
if (err) {
netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
return err;
}
}
if (!(ing_types || egr_types) && (orig_ing_types || orig_egr_types))
mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp);
mlxsw_sp_parsing_depth_dec(mlxsw_sp);

return mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp_port->mlxsw_sp,
ing_types, egr_types);
Expand Down
Loading

0 comments on commit dddb6c2

Please sign in to comment.