mlxsw: spectrum: Make the add_matchall_tc_entry symmetric
Currently, the mlxsw spectrum driver only supports offloading the matchall classifier together with the mirred action. To allow more matchall tc offloads, make the code symmetric so that it can be easily extended later on for other actions. Signed-off-by: Yotam Gigi <yotamg@mellanox.com> Reviewed-by: Ido Schimmel <idosch@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
169852718f
commit
65acb5d082
|
@ -1161,7 +1161,7 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mlxsw_sp_port_mall_tc_entry *
|
static struct mlxsw_sp_port_mall_tc_entry *
|
||||||
mlxsw_sp_port_mirror_entry_find(struct mlxsw_sp_port *port,
|
mlxsw_sp_port_mall_tc_entry_find(struct mlxsw_sp_port *port,
|
||||||
unsigned long cookie) {
|
unsigned long cookie) {
|
||||||
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
||||||
|
|
||||||
|
@ -1174,17 +1174,15 @@ mlxsw_sp_port_mirror_entry_find(struct mlxsw_sp_port *port,
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
struct tc_cls_matchall_offload *cls,
|
struct mlxsw_sp_port_mall_mirror_tc_entry *mirror,
|
||||||
const struct tc_action *a,
|
const struct tc_action *a,
|
||||||
bool ingress)
|
bool ingress)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
|
||||||
struct net *net = dev_net(mlxsw_sp_port->dev);
|
struct net *net = dev_net(mlxsw_sp_port->dev);
|
||||||
enum mlxsw_sp_span_type span_type;
|
enum mlxsw_sp_span_type span_type;
|
||||||
struct mlxsw_sp_port *to_port;
|
struct mlxsw_sp_port *to_port;
|
||||||
struct net_device *to_dev;
|
struct net_device *to_dev;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int err;
|
|
||||||
|
|
||||||
ifindex = tcf_mirred_ifindex(a);
|
ifindex = tcf_mirred_ifindex(a);
|
||||||
to_dev = __dev_get_by_index(net, ifindex);
|
to_dev = __dev_get_by_index(net, ifindex);
|
||||||
|
@ -1199,26 +1197,24 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
}
|
}
|
||||||
to_port = netdev_priv(to_dev);
|
to_port = netdev_priv(to_dev);
|
||||||
|
|
||||||
mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
|
mirror->to_local_port = to_port->local_port;
|
||||||
if (!mall_tc_entry)
|
mirror->ingress = ingress;
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
mall_tc_entry->cookie = cls->cookie;
|
|
||||||
mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR;
|
|
||||||
mall_tc_entry->mirror.to_local_port = to_port->local_port;
|
|
||||||
mall_tc_entry->mirror.ingress = ingress;
|
|
||||||
list_add_tail(&mall_tc_entry->list, &mlxsw_sp_port->mall_tc_list);
|
|
||||||
|
|
||||||
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
err = mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type);
|
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type);
|
||||||
if (err)
|
}
|
||||||
goto err_mirror_add;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_mirror_add:
|
static void
|
||||||
list_del(&mall_tc_entry->list);
|
mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
kfree(mall_tc_entry);
|
struct mlxsw_sp_port_mall_mirror_tc_entry *mirror)
|
||||||
return err;
|
{
|
||||||
|
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||||
|
enum mlxsw_sp_span_type span_type;
|
||||||
|
struct mlxsw_sp_port *to_port;
|
||||||
|
|
||||||
|
to_port = mlxsw_sp->ports[mirror->to_local_port];
|
||||||
|
span_type = mirror->ingress ?
|
||||||
|
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
||||||
|
mlxsw_sp_span_mirror_remove(mlxsw_sp_port, to_port, span_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
@ -1226,6 +1222,7 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
struct tc_cls_matchall_offload *cls,
|
struct tc_cls_matchall_offload *cls,
|
||||||
bool ingress)
|
bool ingress)
|
||||||
{
|
{
|
||||||
|
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
||||||
const struct tc_action *a;
|
const struct tc_action *a;
|
||||||
LIST_HEAD(actions);
|
LIST_HEAD(actions);
|
||||||
int err;
|
int err;
|
||||||
|
@ -1235,50 +1232,58 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mall_tc_entry = kzalloc(sizeof(*mall_tc_entry), GFP_KERNEL);
|
||||||
|
if (!mall_tc_entry)
|
||||||
|
return -ENOMEM;
|
||||||
|
mall_tc_entry->cookie = cls->cookie;
|
||||||
|
|
||||||
tcf_exts_to_list(cls->exts, &actions);
|
tcf_exts_to_list(cls->exts, &actions);
|
||||||
list_for_each_entry(a, &actions, list) {
|
a = list_first_entry(&actions, struct tc_action, list);
|
||||||
if (!is_tcf_mirred_egress_mirror(a) ||
|
|
||||||
protocol != htons(ETH_P_ALL)) {
|
if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) {
|
||||||
return -ENOTSUPP;
|
struct mlxsw_sp_port_mall_mirror_tc_entry *mirror;
|
||||||
|
|
||||||
|
mall_tc_entry->type = MLXSW_SP_PORT_MALL_MIRROR;
|
||||||
|
mirror = &mall_tc_entry->mirror;
|
||||||
|
err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port,
|
||||||
|
mirror, a, ingress);
|
||||||
|
} else {
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, cls,
|
|
||||||
a, ingress);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto err_add_action;
|
||||||
}
|
|
||||||
|
|
||||||
|
list_add_tail(&mall_tc_entry->list, &mlxsw_sp_port->mall_tc_list);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_add_action:
|
||||||
|
kfree(mall_tc_entry);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
struct tc_cls_matchall_offload *cls)
|
struct tc_cls_matchall_offload *cls)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
|
||||||
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
struct mlxsw_sp_port_mall_tc_entry *mall_tc_entry;
|
||||||
enum mlxsw_sp_span_type span_type;
|
|
||||||
struct mlxsw_sp_port *to_port;
|
|
||||||
|
|
||||||
mall_tc_entry = mlxsw_sp_port_mirror_entry_find(mlxsw_sp_port,
|
mall_tc_entry = mlxsw_sp_port_mall_tc_entry_find(mlxsw_sp_port,
|
||||||
cls->cookie);
|
cls->cookie);
|
||||||
if (!mall_tc_entry) {
|
if (!mall_tc_entry) {
|
||||||
netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n");
|
netdev_dbg(mlxsw_sp_port->dev, "tc entry not found on port\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
list_del(&mall_tc_entry->list);
|
||||||
|
|
||||||
switch (mall_tc_entry->type) {
|
switch (mall_tc_entry->type) {
|
||||||
case MLXSW_SP_PORT_MALL_MIRROR:
|
case MLXSW_SP_PORT_MALL_MIRROR:
|
||||||
to_port = mlxsw_sp->ports[mall_tc_entry->mirror.to_local_port];
|
mlxsw_sp_port_del_cls_matchall_mirror(mlxsw_sp_port,
|
||||||
span_type = mall_tc_entry->mirror.ingress ?
|
&mall_tc_entry->mirror);
|
||||||
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
|
|
||||||
|
|
||||||
mlxsw_sp_span_mirror_remove(mlxsw_sp_port, to_port, span_type);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&mall_tc_entry->list);
|
|
||||||
kfree(mall_tc_entry);
|
kfree(mall_tc_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue