linux-stable/drivers/net/ethernet/microchip/lan966x/lan966x_tc_matchall.c
Steen Hegelund cfd9e7b74a net: microchip: vcap api: Use src and dst chain id to chain VCAP lookups
This adds both the source and destination chain id to the information kept
for enabled port lookups.
This allows enabling and disabling a chain of lookups by walking the chain
information for a port.

This changes the way that VCAP lookups are enabled from userspace: instead
of one matchall rule that enables all the 4 Sparx5 IS2 lookups, you need a
matchall rule per lookup.

In practice that is done by adding one matchall rule in chain 0 to goto IS2
Lookup 0, and then for each lookup you add a rule per lookup (low priority)
that does a goto to the next lookup chain.

Examples:

If you want IS2 Lookup 0 to be enabled you add the same matchall filter as
before:

tc filter add dev eth12 ingress chain 0 prio 1000 handle 1000 matchall \
       skip_sw action goto chain 8000000

If you also want to enable lookup 1 to 3 in IS2 and chain them you need
to add the following matchall filters:

tc filter add dev eth12 ingress chain 8000000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8100000

tc filter add dev eth12 ingress chain 8100000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8200000

tc filter add dev eth12 ingress chain 8200000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8300000

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-01-16 13:45:17 +00:00

91 lines
2.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+
#include "lan966x_main.h"
static int lan966x_tc_matchall_add(struct lan966x_port *port,
struct tc_cls_matchall_offload *f,
bool ingress)
{
struct flow_action_entry *act;
if (!flow_offload_has_one_action(&f->rule->action)) {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Only once action per filter is supported");
return -EOPNOTSUPP;
}
act = &f->rule->action.entries[0];
switch (act->id) {
case FLOW_ACTION_POLICE:
return lan966x_police_port_add(port, &f->rule->action, act,
f->cookie, ingress,
f->common.extack);
case FLOW_ACTION_MIRRED:
return lan966x_mirror_port_add(port, act, f->cookie,
ingress, f->common.extack);
case FLOW_ACTION_GOTO:
return lan966x_goto_port_add(port, f->common.chain_index,
act->chain_index, f->cookie,
f->common.extack);
default:
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported action");
return -EOPNOTSUPP;
}
return 0;
}
static int lan966x_tc_matchall_del(struct lan966x_port *port,
struct tc_cls_matchall_offload *f,
bool ingress)
{
if (f->cookie == port->tc.police_id) {
return lan966x_police_port_del(port, f->cookie,
f->common.extack);
} else if (f->cookie == port->tc.ingress_mirror_id ||
f->cookie == port->tc.egress_mirror_id) {
return lan966x_mirror_port_del(port, ingress,
f->common.extack);
} else {
return lan966x_goto_port_del(port, f->cookie, f->common.extack);
}
return 0;
}
static int lan966x_tc_matchall_stats(struct lan966x_port *port,
struct tc_cls_matchall_offload *f,
bool ingress)
{
if (f->cookie == port->tc.police_id) {
lan966x_police_port_stats(port, &f->stats);
} else if (f->cookie == port->tc.ingress_mirror_id ||
f->cookie == port->tc.egress_mirror_id) {
lan966x_mirror_port_stats(port, &f->stats, ingress);
} else {
NL_SET_ERR_MSG_MOD(f->common.extack,
"Unsupported action");
return -EOPNOTSUPP;
}
return 0;
}
int lan966x_tc_matchall(struct lan966x_port *port,
struct tc_cls_matchall_offload *f,
bool ingress)
{
switch (f->command) {
case TC_CLSMATCHALL_REPLACE:
return lan966x_tc_matchall_add(port, f, ingress);
case TC_CLSMATCHALL_DESTROY:
return lan966x_tc_matchall_del(port, f, ingress);
case TC_CLSMATCHALL_STATS:
return lan966x_tc_matchall_stats(port, f, ingress);
default:
return -EOPNOTSUPP;
}
return 0;
}