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 ocelot_flower_parse_action(struct ocelot *ocelot, int port, 232 bool ingress, struct flow_cls_offload *f, 233 struct ocelot_vcap_filter *filter) 234 { 235 const struct flow_action *action = &f->rule->action; 236 struct netlink_ext_ack *extack = f->common.extack; 237 bool allow_missing_goto_target = false; 238 const struct flow_action_entry *a; 239 enum ocelot_tag_tpid_sel tpid; 240 int i, chain, egress_port; 241 u32 pol_ix, pol_max; 242 u64 rate; 243 int err; 244 245 if (!flow_action_basic_hw_stats_check(&f->rule->action, 246 f->common.extack)) 247 return -EOPNOTSUPP; 248 249 chain = f->common.chain_index; 250 filter->block_id = ocelot_chain_to_block(chain, ingress); 251 if (filter->block_id < 0) { 252 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain"); 253 return -EOPNOTSUPP; 254 } 255 if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2) 256 filter->lookup = ocelot_chain_to_lookup(chain); 257 if (filter->block_id == VCAP_IS2) 258 filter->pag = ocelot_chain_to_pag(chain); 259 260 filter->goto_target = -1; 261 filter->type = OCELOT_VCAP_FILTER_DUMMY; 262 263 flow_action_for_each(i, a, action) { 264 switch (a->id) { 265 case FLOW_ACTION_DROP: 266 if (filter->block_id != VCAP_IS2) { 267 NL_SET_ERR_MSG_MOD(extack, 268 "Drop action can only be offloaded to VCAP IS2"); 269 return -EOPNOTSUPP; 270 } 271 if (filter->goto_target != -1) { 272 NL_SET_ERR_MSG_MOD(extack, 273 "Last action must be GOTO"); 274 return -EOPNOTSUPP; 275 } 276 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; 277 filter->action.port_mask = 0; 278 filter->action.police_ena = true; 279 filter->action.pol_ix = OCELOT_POLICER_DISCARD; 280 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 281 break; 282 case FLOW_ACTION_TRAP: 283 if (filter->block_id != VCAP_IS2) { 284 NL_SET_ERR_MSG_MOD(extack, 285 "Trap action can only be offloaded to VCAP IS2"); 286 return -EOPNOTSUPP; 287 } 288 if (filter->goto_target != -1) { 289 NL_SET_ERR_MSG_MOD(extack, 290 "Last action must be GOTO"); 291 return -EOPNOTSUPP; 292 } 293 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY; 294 filter->action.port_mask = 0; 295 filter->action.cpu_copy_ena = true; 296 filter->action.cpu_qu_num = 0; 297 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 298 list_add_tail(&filter->trap_list, &ocelot->traps); 299 break; 300 case FLOW_ACTION_POLICE: 301 if (filter->block_id == PSFP_BLOCK_ID) { 302 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; 303 break; 304 } 305 if (filter->block_id != VCAP_IS2 || 306 filter->lookup != 0) { 307 NL_SET_ERR_MSG_MOD(extack, 308 "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP"); 309 return -EOPNOTSUPP; 310 } 311 if (filter->goto_target != -1) { 312 NL_SET_ERR_MSG_MOD(extack, 313 "Last action must be GOTO"); 314 return -EOPNOTSUPP; 315 } 316 317 err = ocelot_policer_validate(action, a, extack); 318 if (err) 319 return err; 320 321 filter->action.police_ena = true; 322 323 pol_ix = a->hw_index + ocelot->vcap_pol.base; 324 pol_max = ocelot->vcap_pol.max; 325 326 if (ocelot->vcap_pol.max2 && pol_ix > pol_max) { 327 pol_ix += ocelot->vcap_pol.base2 - pol_max - 1; 328 pol_max = ocelot->vcap_pol.max2; 329 } 330 331 if (pol_ix >= pol_max) 332 return -EINVAL; 333 334 filter->action.pol_ix = pol_ix; 335 336 rate = a->police.rate_bytes_ps; 337 filter->action.pol.rate = div_u64(rate, 1000) * 8; 338 filter->action.pol.burst = a->police.burst; 339 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 340 break; 341 case FLOW_ACTION_REDIRECT: 342 if (filter->block_id != VCAP_IS2) { 343 NL_SET_ERR_MSG_MOD(extack, 344 "Redirect action can only be offloaded to VCAP IS2"); 345 return -EOPNOTSUPP; 346 } 347 if (filter->goto_target != -1) { 348 NL_SET_ERR_MSG_MOD(extack, 349 "Last action must be GOTO"); 350 return -EOPNOTSUPP; 351 } 352 egress_port = ocelot->ops->netdev_to_port(a->dev); 353 if (egress_port < 0) { 354 NL_SET_ERR_MSG_MOD(extack, 355 "Destination not an ocelot port"); 356 return -EOPNOTSUPP; 357 } 358 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT; 359 filter->action.port_mask = BIT(egress_port); 360 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 361 break; 362 case FLOW_ACTION_MIRRED: 363 if (filter->block_id != VCAP_IS2) { 364 NL_SET_ERR_MSG_MOD(extack, 365 "Mirror action can only be offloaded to VCAP IS2"); 366 return -EOPNOTSUPP; 367 } 368 if (filter->goto_target != -1) { 369 NL_SET_ERR_MSG_MOD(extack, 370 "Last action must be GOTO"); 371 return -EOPNOTSUPP; 372 } 373 egress_port = ocelot->ops->netdev_to_port(a->dev); 374 if (egress_port < 0) { 375 NL_SET_ERR_MSG_MOD(extack, 376 "Destination not an ocelot port"); 377 return -EOPNOTSUPP; 378 } 379 filter->egress_port.value = egress_port; 380 filter->action.mirror_ena = true; 381 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 382 break; 383 case FLOW_ACTION_VLAN_POP: 384 if (filter->block_id != VCAP_IS1) { 385 NL_SET_ERR_MSG_MOD(extack, 386 "VLAN pop action can only be offloaded to VCAP IS1"); 387 return -EOPNOTSUPP; 388 } 389 if (filter->goto_target != -1) { 390 NL_SET_ERR_MSG_MOD(extack, 391 "Last action must be GOTO"); 392 return -EOPNOTSUPP; 393 } 394 filter->action.vlan_pop_cnt_ena = true; 395 filter->action.vlan_pop_cnt++; 396 if (filter->action.vlan_pop_cnt > 2) { 397 NL_SET_ERR_MSG_MOD(extack, 398 "Cannot pop more than 2 VLAN headers"); 399 return -EOPNOTSUPP; 400 } 401 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 402 break; 403 case FLOW_ACTION_VLAN_MANGLE: 404 if (filter->block_id == VCAP_IS1) { 405 err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port, 406 filter, a, 407 extack); 408 } else if (filter->block_id == VCAP_ES0) { 409 err = ocelot_flower_parse_egress_vlan_modify(filter, a, 410 extack); 411 } else { 412 NL_SET_ERR_MSG_MOD(extack, 413 "VLAN modify action can only be offloaded to VCAP IS1 or ES0"); 414 err = -EOPNOTSUPP; 415 } 416 if (err) 417 return err; 418 break; 419 case FLOW_ACTION_PRIORITY: 420 if (filter->block_id != VCAP_IS1) { 421 NL_SET_ERR_MSG_MOD(extack, 422 "Priority action can only be offloaded to VCAP IS1"); 423 return -EOPNOTSUPP; 424 } 425 if (filter->goto_target != -1) { 426 NL_SET_ERR_MSG_MOD(extack, 427 "Last action must be GOTO"); 428 return -EOPNOTSUPP; 429 } 430 filter->action.qos_ena = true; 431 filter->action.qos_val = a->priority; 432 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 433 break; 434 case FLOW_ACTION_GOTO: 435 filter->goto_target = a->chain_index; 436 437 if (filter->block_id == VCAP_IS1 && filter->lookup == 2) { 438 int pag = ocelot_chain_to_pag(filter->goto_target); 439 440 filter->action.pag_override_mask = 0xff; 441 filter->action.pag_val = pag; 442 filter->type = OCELOT_VCAP_FILTER_PAG; 443 } 444 break; 445 case FLOW_ACTION_VLAN_PUSH: 446 if (filter->block_id != VCAP_ES0) { 447 NL_SET_ERR_MSG_MOD(extack, 448 "VLAN push action can only be offloaded to VCAP ES0"); 449 return -EOPNOTSUPP; 450 } 451 switch (ntohs(a->vlan.proto)) { 452 case ETH_P_8021Q: 453 tpid = OCELOT_TAG_TPID_SEL_8021Q; 454 break; 455 case ETH_P_8021AD: 456 tpid = OCELOT_TAG_TPID_SEL_8021AD; 457 break; 458 default: 459 NL_SET_ERR_MSG_MOD(extack, 460 "Cannot push custom TPID"); 461 return -EOPNOTSUPP; 462 } 463 filter->action.tag_a_tpid_sel = tpid; 464 filter->action.push_outer_tag = OCELOT_ES0_TAG; 465 filter->action.tag_a_vid_sel = OCELOT_ES0_VID; 466 filter->action.vid_a_val = a->vlan.vid; 467 filter->action.pcp_a_val = a->vlan.prio; 468 filter->type = OCELOT_VCAP_FILTER_OFFLOAD; 469 break; 470 case FLOW_ACTION_GATE: 471 if (filter->block_id != PSFP_BLOCK_ID) { 472 NL_SET_ERR_MSG_MOD(extack, 473 "Gate action can only be offloaded to PSFP chain"); 474 return -EOPNOTSUPP; 475 } 476 filter->type = OCELOT_PSFP_FILTER_OFFLOAD; 477 break; 478 default: 479 NL_SET_ERR_MSG_MOD(extack, "Cannot offload action"); 480 return -EOPNOTSUPP; 481 } 482 } 483 484 if (filter->goto_target == -1) { 485 if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) || 486 chain == 0 || filter->block_id == PSFP_BLOCK_ID) { 487 allow_missing_goto_target = true; 488 } else { 489 NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action"); 490 return -EOPNOTSUPP; 491 } 492 } 493 494 if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) && 495 !allow_missing_goto_target) { 496 NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target"); 497 return -EOPNOTSUPP; 498 } 499 500 return 0; 501 } 502 503 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port, 504 struct flow_cls_offload *f, 505 struct ocelot_vcap_filter *filter) 506 { 507 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 508 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; 509 int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length; 510 struct netlink_ext_ack *extack = f->common.extack; 511 struct net_device *dev, *indev; 512 struct flow_match_meta match; 513 int ingress_port; 514 515 flow_rule_match_meta(rule, &match); 516 517 if (!match.mask->ingress_ifindex) 518 return 0; 519 520 if (match.mask->ingress_ifindex != 0xFFFFFFFF) { 521 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); 522 return -EOPNOTSUPP; 523 } 524 525 dev = ocelot->ops->port_to_netdev(ocelot, port); 526 if (!dev) 527 return -EINVAL; 528 529 indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex); 530 if (!indev) { 531 NL_SET_ERR_MSG_MOD(extack, 532 "Can't find the ingress port to match on"); 533 return -ENOENT; 534 } 535 536 ingress_port = ocelot->ops->netdev_to_port(indev); 537 if (ingress_port < 0) { 538 NL_SET_ERR_MSG_MOD(extack, 539 "Can only offload an ocelot ingress port"); 540 return -EOPNOTSUPP; 541 } 542 if (ingress_port == port) { 543 NL_SET_ERR_MSG_MOD(extack, 544 "Ingress port is equal to the egress port"); 545 return -EINVAL; 546 } 547 548 filter->ingress_port.value = ingress_port; 549 filter->ingress_port.mask = GENMASK(key_length - 1, 0); 550 551 return 0; 552 } 553 554 static int 555 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, 556 struct flow_cls_offload *f, 557 struct ocelot_vcap_filter *filter) 558 { 559 struct flow_rule *rule = flow_cls_offload_flow_rule(f); 560 struct flow_dissector *dissector = rule->match.dissector; 561 struct netlink_ext_ack *extack = f->common.extack; 562 u16 proto = ntohs(f->common.protocol); 563 bool match_protocol = true; 564 int ret; 565 566 if (dissector->used_keys & 567 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | 568 BIT(FLOW_DISSECTOR_KEY_BASIC) | 569 BIT(FLOW_DISSECTOR_KEY_META) | 570 BIT(FLOW_DISSECTOR_KEY_PORTS) | 571 BIT(FLOW_DISSECTOR_KEY_VLAN) | 572 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 573 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 574 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) { 575 return -EOPNOTSUPP; 576 } 577 578 /* For VCAP ES0 (egress rewriter) we can match on the ingress port */ 579 if (!ingress) { 580 ret = ocelot_flower_parse_indev(ocelot, port, f, filter); 581 if (ret) 582 return ret; 583 } 584 585 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 586 struct flow_match_control match; 587 588 flow_rule_match_control(rule, &match); 589 } 590 591 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 592 struct flow_match_eth_addrs match; 593 594 if (filter->block_id == VCAP_ES0) { 595 NL_SET_ERR_MSG_MOD(extack, 596 "VCAP ES0 cannot match on MAC address"); 597 return -EOPNOTSUPP; 598 } 599 600 /* The hw support mac matches only for MAC_ETYPE key, 601 * therefore if other matches(port, tcp flags, etc) are added 602 * then just bail out 603 */ 604 if ((dissector->used_keys & 605 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 606 BIT(FLOW_DISSECTOR_KEY_BASIC) | 607 BIT(FLOW_DISSECTOR_KEY_CONTROL))) != 608 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 609 BIT(FLOW_DISSECTOR_KEY_BASIC) | 610 BIT(FLOW_DISSECTOR_KEY_CONTROL))) 611 return -EOPNOTSUPP; 612 613 flow_rule_match_eth_addrs(rule, &match); 614 615 if (filter->block_id == VCAP_IS1 && 616 !is_zero_ether_addr(match.mask->dst)) { 617 NL_SET_ERR_MSG_MOD(extack, 618 "Key type S1_NORMAL cannot match on destination MAC"); 619 return -EOPNOTSUPP; 620 } 621 622 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 623 ether_addr_copy(filter->key.etype.dmac.value, 624 match.key->dst); 625 ether_addr_copy(filter->key.etype.smac.value, 626 match.key->src); 627 ether_addr_copy(filter->key.etype.dmac.mask, 628 match.mask->dst); 629 ether_addr_copy(filter->key.etype.smac.mask, 630 match.mask->src); 631 goto finished_key_parsing; 632 } 633 634 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 635 struct flow_match_basic match; 636 637 flow_rule_match_basic(rule, &match); 638 if (ntohs(match.key->n_proto) == ETH_P_IP) { 639 if (filter->block_id == VCAP_ES0) { 640 NL_SET_ERR_MSG_MOD(extack, 641 "VCAP ES0 cannot match on IP protocol"); 642 return -EOPNOTSUPP; 643 } 644 645 filter->key_type = OCELOT_VCAP_KEY_IPV4; 646 filter->key.ipv4.proto.value[0] = 647 match.key->ip_proto; 648 filter->key.ipv4.proto.mask[0] = 649 match.mask->ip_proto; 650 match_protocol = false; 651 } 652 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 653 if (filter->block_id == VCAP_ES0) { 654 NL_SET_ERR_MSG_MOD(extack, 655 "VCAP ES0 cannot match on IP protocol"); 656 return -EOPNOTSUPP; 657 } 658 659 filter->key_type = OCELOT_VCAP_KEY_IPV6; 660 filter->key.ipv6.proto.value[0] = 661 match.key->ip_proto; 662 filter->key.ipv6.proto.mask[0] = 663 match.mask->ip_proto; 664 match_protocol = false; 665 } 666 } 667 668 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 669 proto == ETH_P_IP) { 670 struct flow_match_ipv4_addrs match; 671 u8 *tmp; 672 673 if (filter->block_id == VCAP_ES0) { 674 NL_SET_ERR_MSG_MOD(extack, 675 "VCAP ES0 cannot match on IP address"); 676 return -EOPNOTSUPP; 677 } 678 679 flow_rule_match_ipv4_addrs(rule, &match); 680 681 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) { 682 NL_SET_ERR_MSG_MOD(extack, 683 "Key type S1_NORMAL cannot match on destination IP"); 684 return -EOPNOTSUPP; 685 } 686 687 tmp = &filter->key.ipv4.sip.value.addr[0]; 688 memcpy(tmp, &match.key->src, 4); 689 690 tmp = &filter->key.ipv4.sip.mask.addr[0]; 691 memcpy(tmp, &match.mask->src, 4); 692 693 tmp = &filter->key.ipv4.dip.value.addr[0]; 694 memcpy(tmp, &match.key->dst, 4); 695 696 tmp = &filter->key.ipv4.dip.mask.addr[0]; 697 memcpy(tmp, &match.mask->dst, 4); 698 match_protocol = false; 699 } 700 701 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 702 proto == ETH_P_IPV6) { 703 return -EOPNOTSUPP; 704 } 705 706 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 707 struct flow_match_ports match; 708 709 if (filter->block_id == VCAP_ES0) { 710 NL_SET_ERR_MSG_MOD(extack, 711 "VCAP ES0 cannot match on L4 ports"); 712 return -EOPNOTSUPP; 713 } 714 715 flow_rule_match_ports(rule, &match); 716 filter->key.ipv4.sport.value = ntohs(match.key->src); 717 filter->key.ipv4.sport.mask = ntohs(match.mask->src); 718 filter->key.ipv4.dport.value = ntohs(match.key->dst); 719 filter->key.ipv4.dport.mask = ntohs(match.mask->dst); 720 match_protocol = false; 721 } 722 723 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 724 struct flow_match_vlan match; 725 726 flow_rule_match_vlan(rule, &match); 727 filter->key_type = OCELOT_VCAP_KEY_ANY; 728 filter->vlan.vid.value = match.key->vlan_id; 729 filter->vlan.vid.mask = match.mask->vlan_id; 730 filter->vlan.pcp.value[0] = match.key->vlan_priority; 731 filter->vlan.pcp.mask[0] = match.mask->vlan_priority; 732 match_protocol = false; 733 } 734 735 finished_key_parsing: 736 if (match_protocol && proto != ETH_P_ALL) { 737 if (filter->block_id == VCAP_ES0) { 738 NL_SET_ERR_MSG_MOD(extack, 739 "VCAP ES0 cannot match on L2 proto"); 740 return -EOPNOTSUPP; 741 } 742 743 /* TODO: support SNAP, LLC etc */ 744 if (proto < ETH_P_802_3_MIN) 745 return -EOPNOTSUPP; 746 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 747 *(__be16 *)filter->key.etype.etype.value = htons(proto); 748 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff); 749 } 750 /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */ 751 752 return 0; 753 } 754 755 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, 756 struct flow_cls_offload *f, 757 struct ocelot_vcap_filter *filter) 758 { 759 int ret; 760 761 filter->prio = f->common.prio; 762 filter->id.cookie = f->cookie; 763 filter->id.tc_offload = true; 764 765 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter); 766 if (ret) 767 return ret; 768 769 /* PSFP filter need to parse key by stream identification function. */ 770 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) 771 return 0; 772 773 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter); 774 } 775 776 static struct ocelot_vcap_filter 777 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress, 778 struct flow_cls_offload *f) 779 { 780 struct ocelot_vcap_filter *filter; 781 782 filter = kzalloc(sizeof(*filter), GFP_KERNEL); 783 if (!filter) 784 return NULL; 785 786 if (ingress) { 787 filter->ingress_port_mask = BIT(port); 788 } else { 789 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; 790 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length; 791 792 filter->egress_port.value = port; 793 filter->egress_port.mask = GENMASK(key_length - 1, 0); 794 } 795 796 return filter; 797 } 798 799 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot, 800 struct ocelot_vcap_filter *filter) 801 { 802 list_add(&filter->list, &ocelot->dummy_rules); 803 804 return 0; 805 } 806 807 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot, 808 struct ocelot_vcap_filter *filter) 809 { 810 list_del(&filter->list); 811 kfree(filter); 812 813 return 0; 814 } 815 816 /* If we have an egress VLAN modification rule, we need to actually write the 817 * delta between the input VLAN (from the key) and the output VLAN (from the 818 * action), but the action was parsed first. So we need to patch the delta into 819 * the action here. 820 */ 821 static int 822 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter, 823 struct netlink_ext_ack *extack) 824 { 825 if (filter->block_id != VCAP_ES0 || 826 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID) 827 return 0; 828 829 if (filter->vlan.vid.mask != VLAN_VID_MASK) { 830 NL_SET_ERR_MSG_MOD(extack, 831 "VCAP ES0 VLAN rewriting needs a full VLAN in the key"); 832 return -EOPNOTSUPP; 833 } 834 835 filter->action.vid_a_val -= filter->vlan.vid.value; 836 filter->action.vid_a_val &= VLAN_VID_MASK; 837 838 return 0; 839 } 840 841 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, 842 struct flow_cls_offload *f, bool ingress) 843 { 844 struct netlink_ext_ack *extack = f->common.extack; 845 struct ocelot_vcap_filter *filter; 846 int chain = f->common.chain_index; 847 int block_id, ret; 848 849 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) { 850 NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain"); 851 return -EOPNOTSUPP; 852 } 853 854 block_id = ocelot_chain_to_block(chain, ingress); 855 if (block_id < 0) { 856 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain"); 857 return -EOPNOTSUPP; 858 } 859 860 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id], 861 f->cookie, true); 862 if (filter) { 863 /* Filter already exists on other ports */ 864 if (!ingress) { 865 NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters"); 866 return -EOPNOTSUPP; 867 } 868 869 filter->ingress_port_mask |= BIT(port); 870 871 return ocelot_vcap_filter_replace(ocelot, filter); 872 } 873 874 /* Filter didn't exist, create it now */ 875 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f); 876 if (!filter) 877 return -ENOMEM; 878 879 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter); 880 if (ret) { 881 if (!list_empty(&filter->trap_list)) 882 list_del(&filter->trap_list); 883 kfree(filter); 884 return ret; 885 } 886 887 ret = ocelot_flower_patch_es0_vlan_modify(filter, extack); 888 if (ret) { 889 kfree(filter); 890 return ret; 891 } 892 893 /* The non-optional GOTOs for the TCAM skeleton don't need 894 * to be actually offloaded. 895 */ 896 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 897 return ocelot_vcap_dummy_filter_add(ocelot, filter); 898 899 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) { 900 kfree(filter); 901 if (ocelot->ops->psfp_filter_add) 902 return ocelot->ops->psfp_filter_add(ocelot, port, f); 903 904 NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW"); 905 return -EOPNOTSUPP; 906 } 907 908 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack); 909 } 910 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); 911 912 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, 913 struct flow_cls_offload *f, bool ingress) 914 { 915 struct ocelot_vcap_filter *filter; 916 struct ocelot_vcap_block *block; 917 int block_id; 918 919 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 920 if (block_id < 0) 921 return 0; 922 923 if (block_id == PSFP_BLOCK_ID) { 924 if (ocelot->ops->psfp_filter_del) 925 return ocelot->ops->psfp_filter_del(ocelot, f); 926 927 return -EOPNOTSUPP; 928 } 929 930 block = &ocelot->block[block_id]; 931 932 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 933 if (!filter) 934 return 0; 935 936 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 937 return ocelot_vcap_dummy_filter_del(ocelot, filter); 938 939 if (ingress) { 940 filter->ingress_port_mask &= ~BIT(port); 941 if (filter->ingress_port_mask) 942 return ocelot_vcap_filter_replace(ocelot, filter); 943 } 944 945 return ocelot_vcap_filter_del(ocelot, filter); 946 } 947 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); 948 949 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, 950 struct flow_cls_offload *f, bool ingress) 951 { 952 struct ocelot_vcap_filter *filter; 953 struct ocelot_vcap_block *block; 954 struct flow_stats stats = {0}; 955 int block_id, ret; 956 957 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 958 if (block_id < 0) 959 return 0; 960 961 if (block_id == PSFP_BLOCK_ID) { 962 if (ocelot->ops->psfp_stats_get) { 963 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats); 964 if (ret) 965 return ret; 966 967 goto stats_update; 968 } 969 970 return -EOPNOTSUPP; 971 } 972 973 block = &ocelot->block[block_id]; 974 975 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 976 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY) 977 return 0; 978 979 ret = ocelot_vcap_filter_stats_update(ocelot, filter); 980 if (ret) 981 return ret; 982 983 stats.pkts = filter->stats.pkts; 984 985 stats_update: 986 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0, 987 FLOW_ACTION_HW_STATS_IMMEDIATE); 988 return 0; 989 } 990 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); 991