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 	default:
27 		NL_SET_ERR_MSG_MOD(f->common.extack,
28 				   "Unsupported action");
29 		return -EOPNOTSUPP;
30 	}
31 
32 	return 0;
33 }
34 
35 static int lan966x_tc_matchall_del(struct lan966x_port *port,
36 				   struct tc_cls_matchall_offload *f,
37 				   bool ingress)
38 {
39 	if (f->cookie == port->tc.police_id) {
40 		return lan966x_police_port_del(port, f->cookie,
41 					       f->common.extack);
42 	} else if (f->cookie == port->tc.ingress_mirror_id ||
43 		   f->cookie == port->tc.egress_mirror_id) {
44 		return lan966x_mirror_port_del(port, ingress,
45 					       f->common.extack);
46 	} else {
47 		NL_SET_ERR_MSG_MOD(f->common.extack,
48 				   "Unsupported action");
49 		return -EOPNOTSUPP;
50 	}
51 
52 	return 0;
53 }
54 
55 static int lan966x_tc_matchall_stats(struct lan966x_port *port,
56 				     struct tc_cls_matchall_offload *f,
57 				     bool ingress)
58 {
59 	if (f->cookie == port->tc.police_id) {
60 		lan966x_police_port_stats(port, &f->stats);
61 	} else if (f->cookie == port->tc.ingress_mirror_id ||
62 		   f->cookie == port->tc.egress_mirror_id) {
63 		lan966x_mirror_port_stats(port, &f->stats, ingress);
64 	} else {
65 		NL_SET_ERR_MSG_MOD(f->common.extack,
66 				   "Unsupported action");
67 		return -EOPNOTSUPP;
68 	}
69 
70 	return 0;
71 }
72 
73 int lan966x_tc_matchall(struct lan966x_port *port,
74 			struct tc_cls_matchall_offload *f,
75 			bool ingress)
76 {
77 	if (!tc_cls_can_offload_and_chain0(port->dev, &f->common)) {
78 		NL_SET_ERR_MSG_MOD(f->common.extack,
79 				   "Only chain zero is supported");
80 		return -EOPNOTSUPP;
81 	}
82 
83 	switch (f->command) {
84 	case TC_CLSMATCHALL_REPLACE:
85 		return lan966x_tc_matchall_add(port, f, ingress);
86 	case TC_CLSMATCHALL_DESTROY:
87 		return lan966x_tc_matchall_del(port, f, ingress);
88 	case TC_CLSMATCHALL_STATS:
89 		return lan966x_tc_matchall_stats(port, f, ingress);
90 	default:
91 		return -EOPNOTSUPP;
92 	}
93 
94 	return 0;
95 }
96