1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include "lan966x_main.h"
4 
5 static 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 
39 static 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 
57 static 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 
75 int 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