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