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