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