1// SPDX-License-Identifier: GPL-2.0+
2
3#include "lan966x_main.h"
4
5static int lan966x_tc_matchall_add(struct lan966x_port *port,
6				   struct tc_cls_matchall_offload *f,
7				   bool ingress)
8{
9	struct flow_action_entry *act;
10
11	if (!flow_offload_has_one_action(&f->rule->action)) {
12		NL_SET_ERR_MSG_MOD(f->common.extack,
13				   "Only once action per filter is supported");
14		return -EOPNOTSUPP;
15	}
16
17	act = &f->rule->action.entries[0];
18	switch (act->id) {
19	case FLOW_ACTION_POLICE:
20		return lan966x_police_port_add(port, &f->rule->action, act,
21					       f->cookie, ingress,
22					       f->common.extack);
23	case FLOW_ACTION_MIRRED:
24		return lan966x_mirror_port_add(port, act, f->cookie,
25					       ingress, f->common.extack);
26	case FLOW_ACTION_GOTO:
27		return lan966x_goto_port_add(port, f->common.chain_index,
28					     act->chain_index, f->cookie,
29					     f->common.extack);
30	default:
31		NL_SET_ERR_MSG_MOD(f->common.extack,
32				   "Unsupported action");
33		return -EOPNOTSUPP;
34	}
35
36	return 0;
37}
38
39static int lan966x_tc_matchall_del(struct lan966x_port *port,
40				   struct tc_cls_matchall_offload *f,
41				   bool ingress)
42{
43	if (f->cookie == port->tc.police_id) {
44		return lan966x_police_port_del(port, f->cookie,
45					       f->common.extack);
46	} else if (f->cookie == port->tc.ingress_mirror_id ||
47		   f->cookie == port->tc.egress_mirror_id) {
48		return lan966x_mirror_port_del(port, ingress,
49					       f->common.extack);
50	} else {
51		return lan966x_goto_port_del(port, f->cookie, f->common.extack);
52	}
53
54	return 0;
55}
56
57static int lan966x_tc_matchall_stats(struct lan966x_port *port,
58				     struct tc_cls_matchall_offload *f,
59				     bool ingress)
60{
61	if (f->cookie == port->tc.police_id) {
62		lan966x_police_port_stats(port, &f->stats);
63	} else if (f->cookie == port->tc.ingress_mirror_id ||
64		   f->cookie == port->tc.egress_mirror_id) {
65		lan966x_mirror_port_stats(port, &f->stats, ingress);
66	} else {
67		NL_SET_ERR_MSG_MOD(f->common.extack,
68				   "Unsupported action");
69		return -EOPNOTSUPP;
70	}
71
72	return 0;
73}
74
75int lan966x_tc_matchall(struct lan966x_port *port,
76			struct tc_cls_matchall_offload *f,
77			bool ingress)
78{
79	switch (f->command) {
80	case TC_CLSMATCHALL_REPLACE:
81		return lan966x_tc_matchall_add(port, f, ingress);
82	case TC_CLSMATCHALL_DESTROY:
83		return lan966x_tc_matchall_del(port, f, ingress);
84	case TC_CLSMATCHALL_STATS:
85		return lan966x_tc_matchall_stats(port, f, ingress);
86	default:
87		return -EOPNOTSUPP;
88	}
89
90	return 0;
91}
92