mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 07:24:39 +08:00
mlxsw: spectrum: qdiscs: Support PRIO qdisc offload
Add support for offloading PRIO qdisc as root qdisc. The support is for up to 8 bands. Routed packets priority is determined by the DSCP field with the default translations. Bridged packets priority is determined by the PCP field, if exist, otherwise it is set to 0. Since both options have only priorities 0-7, higher priorities mapping are being ignored. Signed-off-by: Nogah Frankel <nogahf@mellanox.com> Reviewed-by: Yuval Mintz <yuvalm@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7fdb61b44c
commit
46a3615be4
@ -1830,6 +1830,8 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
|||||||
return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
|
return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
|
||||||
case TC_SETUP_QDISC_RED:
|
case TC_SETUP_QDISC_RED:
|
||||||
return mlxsw_sp_setup_tc_red(mlxsw_sp_port, type_data);
|
return mlxsw_sp_setup_tc_red(mlxsw_sp_port, type_data);
|
||||||
|
case TC_SETUP_QDISC_PRIO:
|
||||||
|
return mlxsw_sp_setup_tc_prio(mlxsw_sp_port, type_data);
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -565,6 +565,8 @@ int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port);
|
|||||||
void mlxsw_sp_tc_qdisc_fini(struct mlxsw_sp_port *mlxsw_sp_port);
|
void mlxsw_sp_tc_qdisc_fini(struct mlxsw_sp_port *mlxsw_sp_port);
|
||||||
int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
|
int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
struct tc_red_qopt_offload *p);
|
struct tc_red_qopt_offload *p);
|
||||||
|
int mlxsw_sp_setup_tc_prio(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct tc_prio_qopt_offload *p);
|
||||||
|
|
||||||
/* spectrum_fid.c */
|
/* spectrum_fid.c */
|
||||||
int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
|
int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
|
||||||
|
@ -41,9 +41,12 @@
|
|||||||
#include "spectrum.h"
|
#include "spectrum.h"
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
|
|
||||||
|
#define MLXSW_SP_PRIO_BAND_TO_TCLASS(band) (IEEE_8021QAZ_MAX_TCS - band - 1)
|
||||||
|
|
||||||
enum mlxsw_sp_qdisc_type {
|
enum mlxsw_sp_qdisc_type {
|
||||||
MLXSW_SP_QDISC_NO_QDISC,
|
MLXSW_SP_QDISC_NO_QDISC,
|
||||||
MLXSW_SP_QDISC_RED,
|
MLXSW_SP_QDISC_RED,
|
||||||
|
MLXSW_SP_QDISC_PRIO,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlxsw_sp_qdisc_ops {
|
struct mlxsw_sp_qdisc_ops {
|
||||||
@ -403,6 +406,85 @@ int mlxsw_sp_setup_tc_red(struct mlxsw_sp_port *mlxsw_sp_port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_qdisc_prio_destroy(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
|
||||||
|
mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i,
|
||||||
|
MLXSW_SP_PORT_DEFAULT_TCLASS);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_qdisc_prio_check_params(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc,
|
||||||
|
void *params)
|
||||||
|
{
|
||||||
|
struct tc_prio_qopt_offload_params *p = params;
|
||||||
|
|
||||||
|
if (p->bands > IEEE_8021QAZ_MAX_TCS)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mlxsw_sp_qdisc_prio_replace(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc,
|
||||||
|
void *params)
|
||||||
|
{
|
||||||
|
struct tc_prio_qopt_offload_params *p = params;
|
||||||
|
int tclass, i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||||
|
tclass = MLXSW_SP_PRIO_BAND_TO_TCLASS(p->priomap[i]);
|
||||||
|
err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, tclass);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mlxsw_sp_qdisc_ops mlxsw_sp_qdisc_ops_prio = {
|
||||||
|
.type = MLXSW_SP_QDISC_PRIO,
|
||||||
|
.check_params = mlxsw_sp_qdisc_prio_check_params,
|
||||||
|
.replace = mlxsw_sp_qdisc_prio_replace,
|
||||||
|
.destroy = mlxsw_sp_qdisc_prio_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
int mlxsw_sp_setup_tc_prio(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct tc_prio_qopt_offload *p)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp_qdisc *mlxsw_sp_qdisc;
|
||||||
|
|
||||||
|
if (p->parent != TC_H_ROOT)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
mlxsw_sp_qdisc = mlxsw_sp_port->root_qdisc;
|
||||||
|
if (p->command == TC_PRIO_REPLACE)
|
||||||
|
return mlxsw_sp_qdisc_replace(mlxsw_sp_port, p->handle,
|
||||||
|
mlxsw_sp_qdisc,
|
||||||
|
&mlxsw_sp_qdisc_ops_prio,
|
||||||
|
&p->replace_params);
|
||||||
|
|
||||||
|
if (!mlxsw_sp_qdisc_compare(mlxsw_sp_qdisc, p->handle,
|
||||||
|
MLXSW_SP_QDISC_PRIO))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
switch (p->command) {
|
||||||
|
case TC_PRIO_DESTROY:
|
||||||
|
return mlxsw_sp_qdisc_destroy(mlxsw_sp_port, mlxsw_sp_qdisc);
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port)
|
int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port)
|
||||||
{
|
{
|
||||||
mlxsw_sp_port->root_qdisc = kzalloc(sizeof(*mlxsw_sp_port->root_qdisc),
|
mlxsw_sp_port->root_qdisc = kzalloc(sizeof(*mlxsw_sp_port->root_qdisc),
|
||||||
|
Loading…
Reference in New Issue
Block a user