Skip to content

Commit

Permalink
mlxsw: spectrum_switchdev: Optimize SFN records processing
Browse files Browse the repository at this point in the history
Currently, only one SFN query is done from repetitive work at a time,
processing 64 entries. Another work iteration is scheduled in 100ms,
that means that the max rate of learned FDB entries is limited to 6400/s.
That is slow. Fix this by doing 2 optimizations:
1) Run 10 SFN queries at a time.
2) In case the SFN is not drained, schedule work with 0 delay to allow
   to continue processing rest of the records.

On a testing setup with 500K entries the time to process decreased
from 870secs to 10secs.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Tested-by: Alex Kushnarov <alexanderk@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Feb 27, 2020
1 parent c535f92 commit 648e53c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 13 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlxsw/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ static inline void mlxsw_reg_sfn_pack(char *payload)
{
MLXSW_REG_ZERO(sfn, payload);
mlxsw_reg_sfn_swid_set(payload, 0);
mlxsw_reg_sfn_end_set(payload, 1);
mlxsw_reg_sfn_end_set(payload, 0);
mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT);
}

Expand Down
35 changes: 23 additions & 12 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2674,19 +2674,24 @@ static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,
}
}

static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp)
static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp,
bool no_delay)
{
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
unsigned int interval = no_delay ? 0 : bridge->fdb_notify.interval;

mlxsw_core_schedule_dw(&bridge->fdb_notify.dw,
msecs_to_jiffies(bridge->fdb_notify.interval));
msecs_to_jiffies(interval));
}

#define MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION 10

static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
{
struct mlxsw_sp_bridge *bridge;
struct mlxsw_sp *mlxsw_sp;
char *sfn_pl;
int queries;
u8 num_rec;
int i;
int err;
Expand All @@ -2699,20 +2704,26 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
mlxsw_sp = bridge->mlxsw_sp;

rtnl_lock();
mlxsw_reg_sfn_pack(sfn_pl);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
if (err) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
goto out;
queries = MLXSW_SP_FDB_SFN_QUERIES_PER_SESSION;
while (queries > 0) {
mlxsw_reg_sfn_pack(sfn_pl);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl);
if (err) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n");
goto out;
}
num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
for (i = 0; i < num_rec; i++)
mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);
if (num_rec != MLXSW_REG_SFN_REC_MAX_COUNT)
goto out;
queries--;
}
num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl);
for (i = 0; i < num_rec; i++)
mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i);

out:
rtnl_unlock();
kfree(sfn_pl);
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, !queries);
}

struct mlxsw_sp_switchdev_event_work {
Expand Down Expand Up @@ -3458,7 +3469,7 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)

INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp, false);
return 0;

err_register_switchdev_blocking_notifier:
Expand Down

0 comments on commit 648e53c

Please sign in to comment.