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 struct ocelot_port_block { 12 struct ocelot_acl_block *block; 13 struct ocelot_port *port; 14 }; 15 16 static u16 get_prio(u32 prio) 17 { 18 /* prio starts from 0x1000 while the ids starts from 0 */ 19 return prio >> 16; 20 } 21 22 static int ocelot_flower_parse_action(struct flow_cls_offload *f, 23 struct ocelot_ace_rule *rule) 24 { 25 const struct flow_action_entry *a; 26 int i; 27 28 if (f->rule->action.num_entries != 1) 29 return -EOPNOTSUPP; 30 31 flow_action_for_each(i, a, &f->rule->action) { 32 switch (a->id) { 33 case FLOW_ACTION_DROP: 34 rule->action = OCELOT_ACL_ACTION_DROP; 35 break; 36 case FLOW_ACTION_TRAP: 37 rule->action = OCELOT_ACL_ACTION_TRAP; 38 break; 39 default: 40 return -EOPNOTSUPP; 41 } 42 } 43 44 return 0; 45 } 46 47 static int ocelot_flower_parse(struct flow_cls_offload *f, 48 struct ocelot_ace_rule *ocelot_rule) 49 { 50 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 51 struct flow_dissector *dissector = rule->match.dissector; 52 53 if (dissector->used_keys & 54 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 55 BIT(FLOW_DISSECTOR_KEY_BASIC) | 56 BIT(FLOW_DISSECTOR_KEY_PORTS) | 57 BIT(FLOW_DISSECTOR_KEY_VLAN) | 58 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 59 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 60 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { 61 return -EOPNOTSUPP; 62 } 63 64 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 65 struct flow_match_control match; 66 67 flow_rule_match_control(rule, &match); 68 } 69 70 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 71 struct flow_match_eth_addrs match; 72 u16 proto = ntohs(f->common.protocol); 73 74 /* The hw support mac matches only for MAC_ETYPE key, 75 * therefore if other matches(port, tcp flags, etc) are added 76 * then just bail out 77 */ 78 if ((dissector->used_keys & 79 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 80 BIT(FLOW_DISSECTOR_KEY_BASIC) | 81 BIT(FLOW_DISSECTOR_KEY_CONTROL))) != 82 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 83 BIT(FLOW_DISSECTOR_KEY_BASIC) | 84 BIT(FLOW_DISSECTOR_KEY_CONTROL))) 85 return -EOPNOTSUPP; 86 87 if (proto == ETH_P_IP || 88 proto == ETH_P_IPV6 || 89 proto == ETH_P_ARP) 90 return -EOPNOTSUPP; 91 92 flow_rule_match_eth_addrs(rule, &match); 93 ocelot_rule->type = OCELOT_ACE_TYPE_ETYPE; 94 ether_addr_copy(ocelot_rule->frame.etype.dmac.value, 95 match.key->dst); 96 ether_addr_copy(ocelot_rule->frame.etype.smac.value, 97 match.key->src); 98 ether_addr_copy(ocelot_rule->frame.etype.dmac.mask, 99 match.mask->dst); 100 ether_addr_copy(ocelot_rule->frame.etype.smac.mask, 101 match.mask->src); 102 goto finished_key_parsing; 103 } 104 105 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 106 struct flow_match_basic match; 107 108 flow_rule_match_basic(rule, &match); 109 if (ntohs(match.key->n_proto) == ETH_P_IP) { 110 ocelot_rule->type = OCELOT_ACE_TYPE_IPV4; 111 ocelot_rule->frame.ipv4.proto.value[0] = 112 match.key->ip_proto; 113 ocelot_rule->frame.ipv4.proto.mask[0] = 114 match.mask->ip_proto; 115 } 116 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 117 ocelot_rule->type = OCELOT_ACE_TYPE_IPV6; 118 ocelot_rule->frame.ipv6.proto.value[0] = 119 match.key->ip_proto; 120 ocelot_rule->frame.ipv6.proto.mask[0] = 121 match.mask->ip_proto; 122 } 123 } 124 125 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 126 ntohs(f->common.protocol) == ETH_P_IP) { 127 struct flow_match_ipv4_addrs match; 128 u8 *tmp; 129 130 flow_rule_match_ipv4_addrs(rule, &match); 131 tmp = &ocelot_rule->frame.ipv4.sip.value.addr[0]; 132 memcpy(tmp, &match.key->src, 4); 133 134 tmp = &ocelot_rule->frame.ipv4.sip.mask.addr[0]; 135 memcpy(tmp, &match.mask->src, 4); 136 137 tmp = &ocelot_rule->frame.ipv4.dip.value.addr[0]; 138 memcpy(tmp, &match.key->dst, 4); 139 140 tmp = &ocelot_rule->frame.ipv4.dip.mask.addr[0]; 141 memcpy(tmp, &match.mask->dst, 4); 142 } 143 144 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 145 ntohs(f->common.protocol) == ETH_P_IPV6) { 146 return -EOPNOTSUPP; 147 } 148 149 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 150 struct flow_match_ports match; 151 152 flow_rule_match_ports(rule, &match); 153 ocelot_rule->frame.ipv4.sport.value = ntohs(match.key->src); 154 ocelot_rule->frame.ipv4.sport.mask = ntohs(match.mask->src); 155 ocelot_rule->frame.ipv4.dport.value = ntohs(match.key->dst); 156 ocelot_rule->frame.ipv4.dport.mask = ntohs(match.mask->dst); 157 } 158 159 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 160 struct flow_match_vlan match; 161 162 flow_rule_match_vlan(rule, &match); 163 ocelot_rule->type = OCELOT_ACE_TYPE_ANY; 164 ocelot_rule->vlan.vid.value = match.key->vlan_id; 165 ocelot_rule->vlan.vid.mask = match.mask->vlan_id; 166 ocelot_rule->vlan.pcp.value[0] = match.key->vlan_priority; 167 ocelot_rule->vlan.pcp.mask[0] = match.mask->vlan_priority; 168 } 169 170 finished_key_parsing: 171 ocelot_rule->prio = get_prio(f->common.prio); 172 ocelot_rule->id = f->cookie; 173 return ocelot_flower_parse_action(f, ocelot_rule); 174 } 175 176 static 177 struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f, 178 struct ocelot_port_block *block) 179 { 180 struct ocelot_ace_rule *rule; 181 182 rule = kzalloc(sizeof(*rule), GFP_KERNEL); 183 if (!rule) 184 return NULL; 185 186 rule->port = block->port; 187 rule->chip_port = block->port->chip_port; 188 return rule; 189 } 190 191 static int ocelot_flower_replace(struct flow_cls_offload *f, 192 struct ocelot_port_block *port_block) 193 { 194 struct ocelot_ace_rule *rule; 195 int ret; 196 197 rule = ocelot_ace_rule_create(f, port_block); 198 if (!rule) 199 return -ENOMEM; 200 201 ret = ocelot_flower_parse(f, rule); 202 if (ret) { 203 kfree(rule); 204 return ret; 205 } 206 207 ret = ocelot_ace_rule_offload_add(rule); 208 if (ret) 209 return ret; 210 211 port_block->port->tc.offload_cnt++; 212 return 0; 213 } 214 215 static int ocelot_flower_destroy(struct flow_cls_offload *f, 216 struct ocelot_port_block *port_block) 217 { 218 struct ocelot_ace_rule rule; 219 int ret; 220 221 rule.prio = get_prio(f->common.prio); 222 rule.port = port_block->port; 223 rule.id = f->cookie; 224 225 ret = ocelot_ace_rule_offload_del(&rule); 226 if (ret) 227 return ret; 228 229 port_block->port->tc.offload_cnt--; 230 return 0; 231 } 232 233 static int ocelot_flower_stats_update(struct flow_cls_offload *f, 234 struct ocelot_port_block *port_block) 235 { 236 struct ocelot_ace_rule rule; 237 int ret; 238 239 rule.prio = get_prio(f->common.prio); 240 rule.port = port_block->port; 241 rule.id = f->cookie; 242 ret = ocelot_ace_rule_stats_update(&rule); 243 if (ret) 244 return ret; 245 246 flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0); 247 return 0; 248 } 249 250 static int ocelot_setup_tc_cls_flower(struct flow_cls_offload *f, 251 struct ocelot_port_block *port_block) 252 { 253 switch (f->command) { 254 case FLOW_CLS_REPLACE: 255 return ocelot_flower_replace(f, port_block); 256 case FLOW_CLS_DESTROY: 257 return ocelot_flower_destroy(f, port_block); 258 case FLOW_CLS_STATS: 259 return ocelot_flower_stats_update(f, port_block); 260 default: 261 return -EOPNOTSUPP; 262 } 263 } 264 265 static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type, 266 void *type_data, void *cb_priv) 267 { 268 struct ocelot_port_block *port_block = cb_priv; 269 270 if (!tc_cls_can_offload_and_chain0(port_block->port->dev, type_data)) 271 return -EOPNOTSUPP; 272 273 switch (type) { 274 case TC_SETUP_CLSFLOWER: 275 return ocelot_setup_tc_cls_flower(type_data, cb_priv); 276 case TC_SETUP_CLSMATCHALL: 277 return 0; 278 default: 279 return -EOPNOTSUPP; 280 } 281 } 282 283 static struct ocelot_port_block* 284 ocelot_port_block_create(struct ocelot_port *port) 285 { 286 struct ocelot_port_block *port_block; 287 288 port_block = kzalloc(sizeof(*port_block), GFP_KERNEL); 289 if (!port_block) 290 return NULL; 291 292 port_block->port = port; 293 294 return port_block; 295 } 296 297 static void ocelot_port_block_destroy(struct ocelot_port_block *block) 298 { 299 kfree(block); 300 } 301 302 static void ocelot_tc_block_unbind(void *cb_priv) 303 { 304 struct ocelot_port_block *port_block = cb_priv; 305 306 ocelot_port_block_destroy(port_block); 307 } 308 309 int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port, 310 struct flow_block_offload *f) 311 { 312 struct ocelot_port_block *port_block; 313 struct flow_block_cb *block_cb; 314 int ret; 315 316 if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) 317 return -EOPNOTSUPP; 318 319 block_cb = flow_block_cb_lookup(f->block, 320 ocelot_setup_tc_block_cb_flower, port); 321 if (!block_cb) { 322 port_block = ocelot_port_block_create(port); 323 if (!port_block) 324 return -ENOMEM; 325 326 block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower, 327 port, port_block, 328 ocelot_tc_block_unbind); 329 if (IS_ERR(block_cb)) { 330 ret = PTR_ERR(block_cb); 331 goto err_cb_register; 332 } 333 flow_block_cb_add(block_cb, f); 334 list_add_tail(&block_cb->driver_list, f->driver_block_list); 335 } else { 336 port_block = flow_block_cb_priv(block_cb); 337 } 338 339 flow_block_cb_incref(block_cb); 340 return 0; 341 342 err_cb_register: 343 ocelot_port_block_destroy(port_block); 344 345 return ret; 346 } 347 348 void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port, 349 struct flow_block_offload *f) 350 { 351 struct flow_block_cb *block_cb; 352 353 block_cb = flow_block_cb_lookup(f->block, 354 ocelot_setup_tc_block_cb_flower, port); 355 if (!block_cb) 356 return; 357 358 if (!flow_block_cb_decref(block_cb)) { 359 flow_block_cb_remove(block_cb, f); 360 list_del(&block_cb->driver_list); 361 } 362 } 363