1 // SPDX-License-Identifier: (GPL-2.0 OR MIT) 2 /* Microsemi Ocelot Switch driver 3 * Copyright (c) 2019 Microsemi Corporation 4 */ 5 6 #include <net/pkt_cls.h> 7 #include <net/tc_act/tc_gact.h> 8 9 #include "ocelot_ace.h" 10 11 static int ocelot_flower_parse_action(struct flow_cls_offload *f, 12 struct ocelot_ace_rule *ace) 13 { 14 const struct flow_action_entry *a; 15 int i; 16 17 if (!flow_offload_has_one_action(&f->rule->action)) 18 return -EOPNOTSUPP; 19 20 if (!flow_action_basic_hw_stats_types_check(&f->rule->action, 21 f->common.extack)) 22 return -EOPNOTSUPP; 23 24 flow_action_for_each(i, a, &f->rule->action) { 25 switch (a->id) { 26 case FLOW_ACTION_DROP: 27 ace->action = OCELOT_ACL_ACTION_DROP; 28 break; 29 case FLOW_ACTION_TRAP: 30 ace->action = OCELOT_ACL_ACTION_TRAP; 31 break; 32 default: 33 return -EOPNOTSUPP; 34 } 35 } 36 37 return 0; 38 } 39 40 static int ocelot_flower_parse(struct flow_cls_offload *f, 41 struct ocelot_ace_rule *ace) 42 { 43 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 44 struct flow_dissector *dissector = rule->match.dissector; 45 46 if (dissector->used_keys & 47 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 48 BIT(FLOW_DISSECTOR_KEY_BASIC) | 49 BIT(FLOW_DISSECTOR_KEY_PORTS) | 50 BIT(FLOW_DISSECTOR_KEY_VLAN) | 51 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 52 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 53 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { 54 return -EOPNOTSUPP; 55 } 56 57 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 58 struct flow_match_control match; 59 60 flow_rule_match_control(rule, &match); 61 } 62 63 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 64 struct flow_match_eth_addrs match; 65 u16 proto = ntohs(f->common.protocol); 66 67 /* The hw support mac matches only for MAC_ETYPE key, 68 * therefore if other matches(port, tcp flags, etc) are added 69 * then just bail out 70 */ 71 if ((dissector->used_keys & 72 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 73 BIT(FLOW_DISSECTOR_KEY_BASIC) | 74 BIT(FLOW_DISSECTOR_KEY_CONTROL))) != 75 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 76 BIT(FLOW_DISSECTOR_KEY_BASIC) | 77 BIT(FLOW_DISSECTOR_KEY_CONTROL))) 78 return -EOPNOTSUPP; 79 80 if (proto == ETH_P_IP || 81 proto == ETH_P_IPV6 || 82 proto == ETH_P_ARP) 83 return -EOPNOTSUPP; 84 85 flow_rule_match_eth_addrs(rule, &match); 86 ace->type = OCELOT_ACE_TYPE_ETYPE; 87 ether_addr_copy(ace->frame.etype.dmac.value, 88 match.key->dst); 89 ether_addr_copy(ace->frame.etype.smac.value, 90 match.key->src); 91 ether_addr_copy(ace->frame.etype.dmac.mask, 92 match.mask->dst); 93 ether_addr_copy(ace->frame.etype.smac.mask, 94 match.mask->src); 95 goto finished_key_parsing; 96 } 97 98 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 99 struct flow_match_basic match; 100 101 flow_rule_match_basic(rule, &match); 102 if (ntohs(match.key->n_proto) == ETH_P_IP) { 103 ace->type = OCELOT_ACE_TYPE_IPV4; 104 ace->frame.ipv4.proto.value[0] = 105 match.key->ip_proto; 106 ace->frame.ipv4.proto.mask[0] = 107 match.mask->ip_proto; 108 } 109 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 110 ace->type = OCELOT_ACE_TYPE_IPV6; 111 ace->frame.ipv6.proto.value[0] = 112 match.key->ip_proto; 113 ace->frame.ipv6.proto.mask[0] = 114 match.mask->ip_proto; 115 } 116 } 117 118 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 119 ntohs(f->common.protocol) == ETH_P_IP) { 120 struct flow_match_ipv4_addrs match; 121 u8 *tmp; 122 123 flow_rule_match_ipv4_addrs(rule, &match); 124 tmp = &ace->frame.ipv4.sip.value.addr[0]; 125 memcpy(tmp, &match.key->src, 4); 126 127 tmp = &ace->frame.ipv4.sip.mask.addr[0]; 128 memcpy(tmp, &match.mask->src, 4); 129 130 tmp = &ace->frame.ipv4.dip.value.addr[0]; 131 memcpy(tmp, &match.key->dst, 4); 132 133 tmp = &ace->frame.ipv4.dip.mask.addr[0]; 134 memcpy(tmp, &match.mask->dst, 4); 135 } 136 137 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 138 ntohs(f->common.protocol) == ETH_P_IPV6) { 139 return -EOPNOTSUPP; 140 } 141 142 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 143 struct flow_match_ports match; 144 145 flow_rule_match_ports(rule, &match); 146 ace->frame.ipv4.sport.value = ntohs(match.key->src); 147 ace->frame.ipv4.sport.mask = ntohs(match.mask->src); 148 ace->frame.ipv4.dport.value = ntohs(match.key->dst); 149 ace->frame.ipv4.dport.mask = ntohs(match.mask->dst); 150 } 151 152 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 153 struct flow_match_vlan match; 154 155 flow_rule_match_vlan(rule, &match); 156 ace->type = OCELOT_ACE_TYPE_ANY; 157 ace->vlan.vid.value = match.key->vlan_id; 158 ace->vlan.vid.mask = match.mask->vlan_id; 159 ace->vlan.pcp.value[0] = match.key->vlan_priority; 160 ace->vlan.pcp.mask[0] = match.mask->vlan_priority; 161 } 162 163 finished_key_parsing: 164 ace->prio = f->common.prio; 165 ace->id = f->cookie; 166 return ocelot_flower_parse_action(f, ace); 167 } 168 169 static 170 struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port, 171 struct flow_cls_offload *f) 172 { 173 struct ocelot_ace_rule *ace; 174 175 ace = kzalloc(sizeof(*ace), GFP_KERNEL); 176 if (!ace) 177 return NULL; 178 179 ace->ingress_port_mask = BIT(port); 180 return ace; 181 } 182 183 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, 184 struct flow_cls_offload *f, bool ingress) 185 { 186 struct ocelot_ace_rule *ace; 187 int ret; 188 189 ace = ocelot_ace_rule_create(ocelot, port, f); 190 if (!ace) 191 return -ENOMEM; 192 193 ret = ocelot_flower_parse(f, ace); 194 if (ret) { 195 kfree(ace); 196 return ret; 197 } 198 199 return ocelot_ace_rule_offload_add(ocelot, ace); 200 } 201 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); 202 203 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, 204 struct flow_cls_offload *f, bool ingress) 205 { 206 struct ocelot_ace_rule ace; 207 208 ace.prio = f->common.prio; 209 ace.id = f->cookie; 210 211 return ocelot_ace_rule_offload_del(ocelot, &ace); 212 } 213 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); 214 215 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, 216 struct flow_cls_offload *f, bool ingress) 217 { 218 struct ocelot_ace_rule ace; 219 int ret; 220 221 ace.prio = f->common.prio; 222 ace.id = f->cookie; 223 ret = ocelot_ace_rule_stats_update(ocelot, &ace); 224 if (ret) 225 return ret; 226 227 flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0); 228 return 0; 229 } 230 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); 231 232 int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv, 233 struct flow_cls_offload *f, 234 bool ingress) 235 { 236 struct ocelot *ocelot = priv->port.ocelot; 237 int port = priv->chip_port; 238 239 if (!ingress) 240 return -EOPNOTSUPP; 241 242 switch (f->command) { 243 case FLOW_CLS_REPLACE: 244 return ocelot_cls_flower_replace(ocelot, port, f, ingress); 245 case FLOW_CLS_DESTROY: 246 return ocelot_cls_flower_destroy(ocelot, port, f, ingress); 247 case FLOW_CLS_STATS: 248 return ocelot_cls_flower_stats(ocelot, port, f, ingress); 249 default: 250 return -EOPNOTSUPP; 251 } 252 } 253