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(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, action: &f->rule->action, act, |
21 | police_id: f->cookie, ingress, |
22 | extack: f->common.extack); |
23 | case FLOW_ACTION_MIRRED: |
24 | return lan966x_mirror_port_add(port, action: act, mirror_id: f->cookie, |
25 | ingress, extack: f->common.extack); |
26 | case FLOW_ACTION_GOTO: |
27 | return lan966x_goto_port_add(port, from_cid: f->common.chain_index, |
28 | to_cid: act->chain_index, goto_id: f->cookie, |
29 | extack: 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, police_id: f->cookie, |
45 | extack: 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 | extack: f->common.extack); |
50 | } else { |
51 | return lan966x_goto_port_del(port, goto_id: f->cookie, extack: 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, stats: &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, stats: &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 | |