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 #include <soc/mscc/ocelot_vcap.h> 9 #include "ocelot_police.h" 10 #include "ocelot_vcap.h" 11 12 /* Arbitrarily chosen constants for encoding the VCAP block and lookup number 13 * into the chain number. This is UAPI. 14 */ 15 #define VCAP_BLOCK 10000 16 #define VCAP_LOOKUP 1000 17 #define VCAP_IS1_NUM_LOOKUPS 3 18 #define VCAP_IS2_NUM_LOOKUPS 2 19 #define VCAP_IS2_NUM_PAG 256 20 #define VCAP_IS1_CHAIN(lookup) \ 21 (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP) 22 #define VCAP_IS2_CHAIN(lookup, pag) \ 23 (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag)) 24 /* PSFP chain and block ID */ 25 #define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS 26 #define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK) 27 28 static int ocelot_chain_to_block(int chain, bool ingress) 29 { 30 int lookup, pag; 31 32 if (!ingress) { 33 if (chain == 0) 34 return VCAP_ES0; 35 return -EOPNOTSUPP; 36 } 37 38 /* Backwards compatibility with older, single-chain tc-flower 39 * offload support in Ocelot 40 */ 41 if (chain == 0) 42 return VCAP_IS2; 43 44 for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++) 45 if (chain == VCAP_IS1_CHAIN(lookup)) 46 return VCAP_IS1; 47 48 for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++) 49 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++) 50 if (chain == VCAP_IS2_CHAIN(lookup, pag)) 51 return VCAP_IS2; 52 53 if (chain == OCELOT_PSFP_CHAIN) 54 return PSFP_BLOCK_ID; 55 56 return -EOPNOTSUPP; 57 } 58 59 /* Caller must ensure this is a valid IS1 or IS2 chain first, 60 * by calling ocelot_chain_to_block. 61 */ 62 static int ocelot_chain_to_lookup(int chain) 63 { 64 return (chain / VCAP_LOOKUP) % 10; 65 } 66 67 /* Caller must ensure this is a valid IS2 chain first, 68 * by calling ocelot_chain_to_block. 69 */ 70 static int ocelot_chain_to_pag(int chain) 71 { 72 int lookup = ocelot_chain_to_lookup(chain); 73 74 /* calculate PAG value as chain index relative to the first PAG */ 75 return chain - VCAP_IS2_CHAIN(lookup, 0); 76 } 77 78 static bool ocelot_is_goto_target_valid(int goto_target, int chain, 79 bool ingress) 80 { 81 int pag; 82 83 /* Can't offload GOTO in VCAP ES0 */ 84 if (!ingress) 85 return (goto_target < 0); 86 87 /* Non-optional GOTOs */ 88 if (chain == 0) 89 /* VCAP IS1 can be skipped, either partially or completely */ 90 return (goto_target == VCAP_IS1_CHAIN(0) || 91 goto_target == VCAP_IS1_CHAIN(1) || 92 goto_target == VCAP_IS1_CHAIN(2) || 93 goto_target == VCAP_IS2_CHAIN(0, 0) || 94 goto_target == VCAP_IS2_CHAIN(1, 0) || 95 goto_target == OCELOT_PSFP_CHAIN); 96 97 if (chain == VCAP_IS1_CHAIN(0)) 98 return (goto_target == VCAP_IS1_CHAIN(1)); 99 100 if (chain == VCAP_IS1_CHAIN(1)) 101 return (goto_target == VCAP_IS1_CHAIN(2)); 102 103 /* Lookup 2 of VCAP IS1 can really support non-optional GOTOs, 104 * using a Policy Association Group (PAG) value, which is an 8-bit 105 * value encoding a VCAP IS2 target chain. 106 */ 107 if (chain == VCAP_IS1_CHAIN(2)) { 108 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++) 109 if (goto_target == VCAP_IS2_CHAIN(0, pag)) 110 return true; 111 112 return false; 113 } 114 115 /* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1. 116 * We cannot change the PAG at this point. 117 */ 118 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++) 119 if (chain == VCAP_IS2_CHAIN(0, pag)) 120 return (goto_target == VCAP_IS2_CHAIN(1, pag)); 121 122 /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */ 123 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++) 124 if (chain == VCAP_IS2_CHAIN(1, pag)) 125 return (goto_target == OCELOT_PSFP_CHAIN); 126 127 return false; 128 } 129 130 static struct ocelot_vcap_filter * 131 ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain) 132 { 133 struct ocelot_vcap_filter *filter; 134 struct ocelot_vcap_block *block; 135 int block_id; 136 137 block_id = ocelot_chain_to_block(chain, true); 138 if (block_id < 0) 139 return NULL; 140 141 if (block_id == VCAP_IS2) { 142 block = &ocelot->block[VCAP_IS1]; 143 144 list_for_each_entry(filter, &block->rules, list) 145 if (filter->type == OCELOT_VCAP_FILTER_PAG && 146 filter->goto_target == chain) 147 return filter; 148 } 149 150 list_for_each_entry(filter, &ocelot->dummy_rules, list) 151 if (filter->goto_target == chain) 152 return filter; 153 154 return NULL; 155 } 156 157 static int 158 ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port, 159 struct ocelot_vcap_filter *filter, 160 const struct flow_action_entry *a, 161 struct netlink_ext_ack *extack) 162 { 163 struct ocelot_port *ocelot_port = ocelot->ports[port]; 164 165 if (filter->goto_target != -1) { 166 NL_SET_ERR_MSG_MOD(extack, 167 "Last action must be GOTO"); 168 return -EOPNOTSUPP; 169 } 170 171 if (!ocelot_port->vlan_aware) { 172 NL_SET_ERR_MSG_MOD(extack, 173 "Can only modify VLAN under VLAN aware bridge"); 174 return -EOPNOTSUPP; 175 } 176 177 filter->action.vid_replace_ena = true; 178 filter->action.pcp_dei_ena = true; 179 filter->action.vid = a->vlan.vid; 180 filter->action.pcp = a->vlan.prio; 181 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 182 183 return 0; 184 } 185 186 static int 187 ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter, 188 const struct flow_action_entry *a, 189 struct netlink_ext_ack *extack) 190 { 191 enum ocelot_tag_tpid_sel tpid; 192 193 switch (ntohs(a->vlan.proto)) { 194 case ETH_P_8021Q: 195 tpid = OCELOT_TAG_TPID_SEL_8021Q; 196 break; 197 case ETH_P_8021AD: 198 tpid = OCELOT_TAG_TPID_SEL_8021AD; 199 break; 200 default: 201 NL_SET_ERR_MSG_MOD(extack, 202 "Cannot modify custom TPID"); 203 return -EOPNOTSUPP; 204 } 205 206 filter->action.tag_a_tpid_sel = tpid; 207 filter->action.push_outer_tag = OCELOT_ES0_TAG; 208 filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID; 209 filter->action.vid_a_val = a->vlan.vid; 210 filter->action.pcp_a_val = a->vlan.prio; 211 filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP; 212 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 213 214 return 0; 215 } 216 217 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port, 218 bool ingress, struct flow_cls_offload *f, 219 struct ocelot_vcap_filter *filter) 220 { 221 const struct flow_action *action = &f->rule->action; 222 struct netlink_ext_ack *extack = f->common.extack; 223 bool allow_missing_goto_target = false; 224 const struct flow_action_entry *a; 225 enum ocelot_tag_tpid_sel tpid; 226 int i, chain, egress_port; 227 u32 pol_ix, pol_max; 228 u64 rate; 229 int err; 230 231 if (!flow_action_basic_hw_stats_check(&f->rule->action, 232 f->common.extack)) 233 return -EOPNOTSUPP; 234 235 chain = f->common.chain_index; 236 filter->block_id = ocelot_chain_to_block(chain, ingress); 237 if (filter->block_id < 0) { 238 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain"); 239 return -EOPNOTSUPP; 240 } 241 if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2) 242 filter->lookup = ocelot_chain_to_lookup(chain); 243 if (filter->block_id == VCAP_IS2) 244 filter->pag = ocelot_chain_to_pag(chain); 245 246 filter->goto_target = -1; 247 filter->type = OCELOT_VCAP_FILTER_DUMMY; 248 249 flow_action_for_each(i, a, action) { 250 switch (a->id) { 251 case FLOW_ACTION_DROP: 252 if (filter->block_id != VCAP_IS2) { 253 NL_SET_ERR_MSG_MOD(extack, 254 "Drop action can only be offloaded to VCAP IS2"); 255 return -EOPNOTSUPP; 256 } 257 if (filter->goto_target != -1) { 258 NL_SET_ERR_MSG_MOD(extack, 259 "Last action must be GOTO"); 260 return -EOPNOTSUPP; 261 } 262 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; 263 filter->action.port_mask = 0; 264 filter->action.police_ena = true; 265 filter->action.pol_ix = OCELOT_POLICER_DISCARD; 266 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 267 break; 268 case FLOW_ACTION_TRAP: 269 if (filter->block_id != VCAP_IS2) { 270 NL_SET_ERR_MSG_MOD(extack, 271 "Trap action can only be offloaded to VCAP IS2"); 272 return -EOPNOTSUPP; 273 } 274 if (filter->goto_target != -1) { 275 NL_SET_ERR_MSG_MOD(extack, 276 "Last action must be GOTO"); 277 return -EOPNOTSUPP; 278 } 279 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; 280 filter->action.port_mask = 0; 281 filter->action.cpu_copy_ena = true; 282 filter->action.cpu_qu_num = 0; 283 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 284 list_add_tail(&filter->trap_list, &ocelot->traps); 285 break; 286 case FLOW_ACTION_POLICE: 287 if (filter->block_id == PSFP_BLOCK_ID) { 288 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; 289 break; 290 } 291 if (filter->block_id != VCAP_IS2 || 292 filter->lookup != 0) { 293 NL_SET_ERR_MSG_MOD(extack, 294 "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP"); 295 return -EOPNOTSUPP; 296 } 297 if (filter->goto_target != -1) { 298 NL_SET_ERR_MSG_MOD(extack, 299 "Last action must be GOTO"); 300 return -EOPNOTSUPP; 301 } 302 303 err = ocelot_policer_validate(action, a, extack); 304 if (err) 305 return err; 306 307 filter->action.police_ena = true; 308 309 pol_ix = a->hw_index + ocelot->vcap_pol.base; 310 pol_max = ocelot->vcap_pol.max; 311 312 if (ocelot->vcap_pol.max2 && pol_ix > pol_max) { 313 pol_ix += ocelot->vcap_pol.base2 - pol_max - 1; 314 pol_max = ocelot->vcap_pol.max2; 315 } 316 317 if (pol_ix >= pol_max) 318 return -EINVAL; 319 320 filter->action.pol_ix = pol_ix; 321 322 rate = a->police.rate_bytes_ps; 323 filter->action.pol.rate = div_u64(rate, 1000) * 8; 324 filter->action.pol.burst = a->police.burst; 325 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 326 break; 327 case FLOW_ACTION_REDIRECT: 328 if (filter->block_id != VCAP_IS2) { 329 NL_SET_ERR_MSG_MOD(extack, 330 "Redirect action can only be offloaded to VCAP IS2"); 331 return -EOPNOTSUPP; 332 } 333 if (filter->goto_target != -1) { 334 NL_SET_ERR_MSG_MOD(extack, 335 "Last action must be GOTO"); 336 return -EOPNOTSUPP; 337 } 338 egress_port = ocelot->ops->netdev_to_port(a->dev); 339 if (egress_port < 0) { 340 NL_SET_ERR_MSG_MOD(extack, 341 "Destination not an ocelot port"); 342 return -EOPNOTSUPP; 343 } 344 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; 345 filter->action.port_mask = BIT(egress_port); 346 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 347 break; 348 case FLOW_ACTION_VLAN_POP: 349 if (filter->block_id != VCAP_IS1) { 350 NL_SET_ERR_MSG_MOD(extack, 351 "VLAN pop action can only be offloaded to VCAP IS1"); 352 return -EOPNOTSUPP; 353 } 354 if (filter->goto_target != -1) { 355 NL_SET_ERR_MSG_MOD(extack, 356 "Last action must be GOTO"); 357 return -EOPNOTSUPP; 358 } 359 filter->action.vlan_pop_cnt_ena = true; 360 filter->action.vlan_pop_cnt++; 361 if (filter->action.vlan_pop_cnt > 2) { 362 NL_SET_ERR_MSG_MOD(extack, 363 "Cannot pop more than 2 VLAN headers"); 364 return -EOPNOTSUPP; 365 } 366 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 367 break; 368 case FLOW_ACTION_VLAN_MANGLE: 369 if (filter->block_id == VCAP_IS1) { 370 err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port, 371 filter, a, 372 extack); 373 } else if (filter->block_id == VCAP_ES0) { 374 err = ocelot_flower_parse_egress_vlan_modify(filter, a, 375 extack); 376 } else { 377 NL_SET_ERR_MSG_MOD(extack, 378 "VLAN modify action can only be offloaded to VCAP IS1 or ES0"); 379 err = -EOPNOTSUPP; 380 } 381 if (err) 382 return err; 383 break; 384 case FLOW_ACTION_PRIORITY: 385 if (filter->block_id != VCAP_IS1) { 386 NL_SET_ERR_MSG_MOD(extack, 387 "Priority action can only be offloaded to VCAP IS1"); 388 return -EOPNOTSUPP; 389 } 390 if (filter->goto_target != -1) { 391 NL_SET_ERR_MSG_MOD(extack, 392 "Last action must be GOTO"); 393 return -EOPNOTSUPP; 394 } 395 filter->action.qos_ena = true; 396 filter->action.qos_val = a->priority; 397 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 398 break; 399 case FLOW_ACTION_GOTO: 400 filter->goto_target = a->chain_index; 401 402 if (filter->block_id == VCAP_IS1 && filter->lookup == 2) { 403 int pag = ocelot_chain_to_pag(filter->goto_target); 404 405 filter->action.pag_override_mask = 0xff; 406 filter->action.pag_val = pag; 407 filter->type = OCELOT_VCAP_FILTER_PAG; 408 } 409 break; 410 case FLOW_ACTION_VLAN_PUSH: 411 if (filter->block_id != VCAP_ES0) { 412 NL_SET_ERR_MSG_MOD(extack, 413 "VLAN push action can only be offloaded to VCAP ES0"); 414 return -EOPNOTSUPP; 415 } 416 switch (ntohs(a->vlan.proto)) { 417 case ETH_P_8021Q: 418 tpid = OCELOT_TAG_TPID_SEL_8021Q; 419 break; 420 case ETH_P_8021AD: 421 tpid = OCELOT_TAG_TPID_SEL_8021AD; 422 break; 423 default: 424 NL_SET_ERR_MSG_MOD(extack, 425 "Cannot push custom TPID"); 426 return -EOPNOTSUPP; 427 } 428 filter->action.tag_a_tpid_sel = tpid; 429 filter->action.push_outer_tag = OCELOT_ES0_TAG; 430 filter->action.tag_a_vid_sel = OCELOT_ES0_VID; 431 filter->action.vid_a_val = a->vlan.vid; 432 filter->action.pcp_a_val = a->vlan.prio; 433 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 434 break; 435 case FLOW_ACTION_GATE: 436 if (filter->block_id != PSFP_BLOCK_ID) { 437 NL_SET_ERR_MSG_MOD(extack, 438 "Gate action can only be offloaded to PSFP chain"); 439 return -EOPNOTSUPP; 440 } 441 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; 442 break; 443 default: 444 NL_SET_ERR_MSG_MOD(extack, "Cannot offload action"); 445 return -EOPNOTSUPP; 446 } 447 } 448 449 if (filter->goto_target == -1) { 450 if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) || 451 chain == 0 || filter->block_id == PSFP_BLOCK_ID) { 452 allow_missing_goto_target = true; 453 } else { 454 NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action"); 455 return -EOPNOTSUPP; 456 } 457 } 458 459 if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) && 460 !allow_missing_goto_target) { 461 NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target"); 462 return -EOPNOTSUPP; 463 } 464 465 return 0; 466 } 467 468 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port, 469 struct flow_cls_offload *f, 470 struct ocelot_vcap_filter *filter) 471 { 472 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 473 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; 474 int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length; 475 struct netlink_ext_ack *extack = f->common.extack; 476 struct net_device *dev, *indev; 477 struct flow_match_meta match; 478 int ingress_port; 479 480 flow_rule_match_meta(rule, &match); 481 482 if (!match.mask->ingress_ifindex) 483 return 0; 484 485 if (match.mask->ingress_ifindex != 0xFFFFFFFF) { 486 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); 487 return -EOPNOTSUPP; 488 } 489 490 dev = ocelot->ops->port_to_netdev(ocelot, port); 491 if (!dev) 492 return -EINVAL; 493 494 indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex); 495 if (!indev) { 496 NL_SET_ERR_MSG_MOD(extack, 497 "Can't find the ingress port to match on"); 498 return -ENOENT; 499 } 500 501 ingress_port = ocelot->ops->netdev_to_port(indev); 502 if (ingress_port < 0) { 503 NL_SET_ERR_MSG_MOD(extack, 504 "Can only offload an ocelot ingress port"); 505 return -EOPNOTSUPP; 506 } 507 if (ingress_port == port) { 508 NL_SET_ERR_MSG_MOD(extack, 509 "Ingress port is equal to the egress port"); 510 return -EINVAL; 511 } 512 513 filter->ingress_port.value = ingress_port; 514 filter->ingress_port.mask = GENMASK(key_length - 1, 0); 515 516 return 0; 517 } 518 519 static int 520 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, 521 struct flow_cls_offload *f, 522 struct ocelot_vcap_filter *filter) 523 { 524 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 525 struct flow_dissector *dissector = rule->match.dissector; 526 struct netlink_ext_ack *extack = f->common.extack; 527 u16 proto = ntohs(f->common.protocol); 528 bool match_protocol = true; 529 int ret; 530 531 if (dissector->used_keys & 532 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 533 BIT(FLOW_DISSECTOR_KEY_BASIC) | 534 BIT(FLOW_DISSECTOR_KEY_META) | 535 BIT(FLOW_DISSECTOR_KEY_PORTS) | 536 BIT(FLOW_DISSECTOR_KEY_VLAN) | 537 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 538 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 539 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { 540 return -EOPNOTSUPP; 541 } 542 543 /* For VCAP ES0 (egress rewriter) we can match on the ingress port */ 544 if (!ingress) { 545 ret = ocelot_flower_parse_indev(ocelot, port, f, filter); 546 if (ret) 547 return ret; 548 } 549 550 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 551 struct flow_match_control match; 552 553 flow_rule_match_control(rule, &match); 554 } 555 556 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 557 struct flow_match_eth_addrs match; 558 559 if (filter->block_id == VCAP_ES0) { 560 NL_SET_ERR_MSG_MOD(extack, 561 "VCAP ES0 cannot match on MAC address"); 562 return -EOPNOTSUPP; 563 } 564 565 /* The hw support mac matches only for MAC_ETYPE key, 566 * therefore if other matches(port, tcp flags, etc) are added 567 * then just bail out 568 */ 569 if ((dissector->used_keys & 570 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 571 BIT(FLOW_DISSECTOR_KEY_BASIC) | 572 BIT(FLOW_DISSECTOR_KEY_CONTROL))) != 573 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 574 BIT(FLOW_DISSECTOR_KEY_BASIC) | 575 BIT(FLOW_DISSECTOR_KEY_CONTROL))) 576 return -EOPNOTSUPP; 577 578 flow_rule_match_eth_addrs(rule, &match); 579 580 if (filter->block_id == VCAP_IS1 && 581 !is_zero_ether_addr(match.mask->dst)) { 582 NL_SET_ERR_MSG_MOD(extack, 583 "Key type S1_NORMAL cannot match on destination MAC"); 584 return -EOPNOTSUPP; 585 } 586 587 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 588 ether_addr_copy(filter->key.etype.dmac.value, 589 match.key->dst); 590 ether_addr_copy(filter->key.etype.smac.value, 591 match.key->src); 592 ether_addr_copy(filter->key.etype.dmac.mask, 593 match.mask->dst); 594 ether_addr_copy(filter->key.etype.smac.mask, 595 match.mask->src); 596 goto finished_key_parsing; 597 } 598 599 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 600 struct flow_match_basic match; 601 602 flow_rule_match_basic(rule, &match); 603 if (ntohs(match.key->n_proto) == ETH_P_IP) { 604 if (filter->block_id == VCAP_ES0) { 605 NL_SET_ERR_MSG_MOD(extack, 606 "VCAP ES0 cannot match on IP protocol"); 607 return -EOPNOTSUPP; 608 } 609 610 filter->key_type = OCELOT_VCAP_KEY_IPV4; 611 filter->key.ipv4.proto.value[0] = 612 match.key->ip_proto; 613 filter->key.ipv4.proto.mask[0] = 614 match.mask->ip_proto; 615 match_protocol = false; 616 } 617 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 618 if (filter->block_id == VCAP_ES0) { 619 NL_SET_ERR_MSG_MOD(extack, 620 "VCAP ES0 cannot match on IP protocol"); 621 return -EOPNOTSUPP; 622 } 623 624 filter->key_type = OCELOT_VCAP_KEY_IPV6; 625 filter->key.ipv6.proto.value[0] = 626 match.key->ip_proto; 627 filter->key.ipv6.proto.mask[0] = 628 match.mask->ip_proto; 629 match_protocol = false; 630 } 631 } 632 633 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 634 proto == ETH_P_IP) { 635 struct flow_match_ipv4_addrs match; 636 u8 *tmp; 637 638 if (filter->block_id == VCAP_ES0) { 639 NL_SET_ERR_MSG_MOD(extack, 640 "VCAP ES0 cannot match on IP address"); 641 return -EOPNOTSUPP; 642 } 643 644 flow_rule_match_ipv4_addrs(rule, &match); 645 646 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) { 647 NL_SET_ERR_MSG_MOD(extack, 648 "Key type S1_NORMAL cannot match on destination IP"); 649 return -EOPNOTSUPP; 650 } 651 652 tmp = &filter->key.ipv4.sip.value.addr[0]; 653 memcpy(tmp, &match.key->src, 4); 654 655 tmp = &filter->key.ipv4.sip.mask.addr[0]; 656 memcpy(tmp, &match.mask->src, 4); 657 658 tmp = &filter->key.ipv4.dip.value.addr[0]; 659 memcpy(tmp, &match.key->dst, 4); 660 661 tmp = &filter->key.ipv4.dip.mask.addr[0]; 662 memcpy(tmp, &match.mask->dst, 4); 663 match_protocol = false; 664 } 665 666 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 667 proto == ETH_P_IPV6) { 668 return -EOPNOTSUPP; 669 } 670 671 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 672 struct flow_match_ports match; 673 674 if (filter->block_id == VCAP_ES0) { 675 NL_SET_ERR_MSG_MOD(extack, 676 "VCAP ES0 cannot match on L4 ports"); 677 return -EOPNOTSUPP; 678 } 679 680 flow_rule_match_ports(rule, &match); 681 filter->key.ipv4.sport.value = ntohs(match.key->src); 682 filter->key.ipv4.sport.mask = ntohs(match.mask->src); 683 filter->key.ipv4.dport.value = ntohs(match.key->dst); 684 filter->key.ipv4.dport.mask = ntohs(match.mask->dst); 685 match_protocol = false; 686 } 687 688 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 689 struct flow_match_vlan match; 690 691 flow_rule_match_vlan(rule, &match); 692 filter->key_type = OCELOT_VCAP_KEY_ANY; 693 filter->vlan.vid.value = match.key->vlan_id; 694 filter->vlan.vid.mask = match.mask->vlan_id; 695 filter->vlan.pcp.value[0] = match.key->vlan_priority; 696 filter->vlan.pcp.mask[0] = match.mask->vlan_priority; 697 match_protocol = false; 698 } 699 700 finished_key_parsing: 701 if (match_protocol && proto != ETH_P_ALL) { 702 if (filter->block_id == VCAP_ES0) { 703 NL_SET_ERR_MSG_MOD(extack, 704 "VCAP ES0 cannot match on L2 proto"); 705 return -EOPNOTSUPP; 706 } 707 708 /* TODO: support SNAP, LLC etc */ 709 if (proto < ETH_P_802_3_MIN) 710 return -EOPNOTSUPP; 711 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 712 *(__be16 *)filter->key.etype.etype.value = htons(proto); 713 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff); 714 } 715 /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */ 716 717 return 0; 718 } 719 720 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, 721 struct flow_cls_offload *f, 722 struct ocelot_vcap_filter *filter) 723 { 724 int ret; 725 726 filter->prio = f->common.prio; 727 filter->id.cookie = f->cookie; 728 filter->id.tc_offload = true; 729 730 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter); 731 if (ret) 732 return ret; 733 734 /* PSFP filter need to parse key by stream identification function. */ 735 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) 736 return 0; 737 738 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter); 739 } 740 741 static struct ocelot_vcap_filter 742 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress, 743 struct flow_cls_offload *f) 744 { 745 struct ocelot_vcap_filter *filter; 746 747 filter = kzalloc(sizeof(*filter), GFP_KERNEL); 748 if (!filter) 749 return NULL; 750 751 if (ingress) { 752 filter->ingress_port_mask = BIT(port); 753 } else { 754 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; 755 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length; 756 757 filter->egress_port.value = port; 758 filter->egress_port.mask = GENMASK(key_length - 1, 0); 759 } 760 761 return filter; 762 } 763 764 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot, 765 struct ocelot_vcap_filter *filter) 766 { 767 list_add(&filter->list, &ocelot->dummy_rules); 768 769 return 0; 770 } 771 772 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot, 773 struct ocelot_vcap_filter *filter) 774 { 775 list_del(&filter->list); 776 kfree(filter); 777 778 return 0; 779 } 780 781 /* If we have an egress VLAN modification rule, we need to actually write the 782 * delta between the input VLAN (from the key) and the output VLAN (from the 783 * action), but the action was parsed first. So we need to patch the delta into 784 * the action here. 785 */ 786 static int 787 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter, 788 struct netlink_ext_ack *extack) 789 { 790 if (filter->block_id != VCAP_ES0 || 791 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID) 792 return 0; 793 794 if (filter->vlan.vid.mask != VLAN_VID_MASK) { 795 NL_SET_ERR_MSG_MOD(extack, 796 "VCAP ES0 VLAN rewriting needs a full VLAN in the key"); 797 return -EOPNOTSUPP; 798 } 799 800 filter->action.vid_a_val -= filter->vlan.vid.value; 801 filter->action.vid_a_val &= VLAN_VID_MASK; 802 803 return 0; 804 } 805 806 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, 807 struct flow_cls_offload *f, bool ingress) 808 { 809 struct netlink_ext_ack *extack = f->common.extack; 810 struct ocelot_vcap_filter *filter; 811 int chain = f->common.chain_index; 812 int block_id, ret; 813 814 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) { 815 NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain"); 816 return -EOPNOTSUPP; 817 } 818 819 block_id = ocelot_chain_to_block(chain, ingress); 820 if (block_id < 0) { 821 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain"); 822 return -EOPNOTSUPP; 823 } 824 825 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id], 826 f->cookie, true); 827 if (filter) { 828 /* Filter already exists on other ports */ 829 if (!ingress) { 830 NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters"); 831 return -EOPNOTSUPP; 832 } 833 834 filter->ingress_port_mask |= BIT(port); 835 836 return ocelot_vcap_filter_replace(ocelot, filter); 837 } 838 839 /* Filter didn't exist, create it now */ 840 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f); 841 if (!filter) 842 return -ENOMEM; 843 844 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter); 845 if (ret) { 846 if (!list_empty(&filter->trap_list)) 847 list_del(&filter->trap_list); 848 kfree(filter); 849 return ret; 850 } 851 852 ret = ocelot_flower_patch_es0_vlan_modify(filter, extack); 853 if (ret) { 854 kfree(filter); 855 return ret; 856 } 857 858 /* The non-optional GOTOs for the TCAM skeleton don't need 859 * to be actually offloaded. 860 */ 861 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 862 return ocelot_vcap_dummy_filter_add(ocelot, filter); 863 864 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) { 865 kfree(filter); 866 if (ocelot->ops->psfp_filter_add) 867 return ocelot->ops->psfp_filter_add(ocelot, port, f); 868 869 NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW"); 870 return -EOPNOTSUPP; 871 } 872 873 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack); 874 } 875 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); 876 877 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, 878 struct flow_cls_offload *f, bool ingress) 879 { 880 struct ocelot_vcap_filter *filter; 881 struct ocelot_vcap_block *block; 882 int block_id; 883 884 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 885 if (block_id < 0) 886 return 0; 887 888 if (block_id == PSFP_BLOCK_ID) { 889 if (ocelot->ops->psfp_filter_del) 890 return ocelot->ops->psfp_filter_del(ocelot, f); 891 892 return -EOPNOTSUPP; 893 } 894 895 block = &ocelot->block[block_id]; 896 897 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 898 if (!filter) 899 return 0; 900 901 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 902 return ocelot_vcap_dummy_filter_del(ocelot, filter); 903 904 if (ingress) { 905 filter->ingress_port_mask &= ~BIT(port); 906 if (filter->ingress_port_mask) 907 return ocelot_vcap_filter_replace(ocelot, filter); 908 } 909 910 return ocelot_vcap_filter_del(ocelot, filter); 911 } 912 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); 913 914 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, 915 struct flow_cls_offload *f, bool ingress) 916 { 917 struct ocelot_vcap_filter *filter; 918 struct ocelot_vcap_block *block; 919 struct flow_stats stats = {0}; 920 int block_id, ret; 921 922 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 923 if (block_id < 0) 924 return 0; 925 926 if (block_id == PSFP_BLOCK_ID) { 927 if (ocelot->ops->psfp_stats_get) { 928 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats); 929 if (ret) 930 return ret; 931 932 goto stats_update; 933 } 934 935 return -EOPNOTSUPP; 936 } 937 938 block = &ocelot->block[block_id]; 939 940 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 941 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY) 942 return 0; 943 944 ret = ocelot_vcap_filter_stats_update(ocelot, filter); 945 if (ret) 946 return ret; 947 948 stats.pkts = filter->stats.pkts; 949 950 stats_update: 951 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0, 952 FLOW_ACTION_HW_STATS_IMMEDIATE); 953 return 0; 954 } 955 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); 956