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