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_ULL(FLOW_DISSECTOR_KEY_CONTROL) | 585 BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 586 BIT_ULL(FLOW_DISSECTOR_KEY_META) | 587 BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | 588 BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | 589 BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 590 BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 591 BIT_ULL(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_has_control_flags(rule, extack)) 613 return -EOPNOTSUPP; 614 615 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { 616 struct flow_match_vlan match; 617 618 flow_rule_match_vlan(rule, &match); 619 filter->key_type = OCELOT_VCAP_KEY_ANY; 620 filter->vlan.vid.value = match.key->vlan_id; 621 filter->vlan.vid.mask = match.mask->vlan_id; 622 filter->vlan.pcp.value[0] = match.key->vlan_priority; 623 filter->vlan.pcp.mask[0] = match.mask->vlan_priority; 624 match_protocol = false; 625 } 626 627 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 628 struct flow_match_eth_addrs match; 629 630 if (filter->block_id == VCAP_ES0) { 631 NL_SET_ERR_MSG_MOD(extack, 632 "VCAP ES0 cannot match on MAC address"); 633 return -EOPNOTSUPP; 634 } 635 636 /* The hw support mac matches only for MAC_ETYPE key, 637 * therefore if other matches(port, tcp flags, etc) are added 638 * then just bail out 639 */ 640 if ((dissector->used_keys & 641 (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 642 BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 643 BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) != 644 (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 645 BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 646 BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) 647 return -EOPNOTSUPP; 648 649 flow_rule_match_eth_addrs(rule, &match); 650 651 if (filter->block_id == VCAP_IS1 && 652 !is_zero_ether_addr(match.mask->dst)) { 653 NL_SET_ERR_MSG_MOD(extack, 654 "Key type S1_NORMAL cannot match on destination MAC"); 655 return -EOPNOTSUPP; 656 } 657 658 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 659 ether_addr_copy(filter->key.etype.dmac.value, 660 match.key->dst); 661 ether_addr_copy(filter->key.etype.smac.value, 662 match.key->src); 663 ether_addr_copy(filter->key.etype.dmac.mask, 664 match.mask->dst); 665 ether_addr_copy(filter->key.etype.smac.mask, 666 match.mask->src); 667 goto finished_key_parsing; 668 } 669 670 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 671 struct flow_match_basic match; 672 673 flow_rule_match_basic(rule, &match); 674 if (ntohs(match.key->n_proto) == ETH_P_IP) { 675 if (filter->block_id == VCAP_ES0) { 676 NL_SET_ERR_MSG_MOD(extack, 677 "VCAP ES0 cannot match on IP protocol"); 678 return -EOPNOTSUPP; 679 } 680 681 filter->key_type = OCELOT_VCAP_KEY_IPV4; 682 filter->key.ipv4.proto.value[0] = 683 match.key->ip_proto; 684 filter->key.ipv4.proto.mask[0] = 685 match.mask->ip_proto; 686 match_protocol = false; 687 } 688 if (ntohs(match.key->n_proto) == ETH_P_IPV6) { 689 if (filter->block_id == VCAP_ES0) { 690 NL_SET_ERR_MSG_MOD(extack, 691 "VCAP ES0 cannot match on IP protocol"); 692 return -EOPNOTSUPP; 693 } 694 695 filter->key_type = OCELOT_VCAP_KEY_IPV6; 696 filter->key.ipv6.proto.value[0] = 697 match.key->ip_proto; 698 filter->key.ipv6.proto.mask[0] = 699 match.mask->ip_proto; 700 match_protocol = false; 701 } 702 } 703 704 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) && 705 proto == ETH_P_IP) { 706 struct flow_match_ipv4_addrs match; 707 u8 *tmp; 708 709 if (filter->block_id == VCAP_ES0) { 710 NL_SET_ERR_MSG_MOD(extack, 711 "VCAP ES0 cannot match on IP address"); 712 return -EOPNOTSUPP; 713 } 714 715 flow_rule_match_ipv4_addrs(rule, &match); 716 717 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) { 718 NL_SET_ERR_MSG_MOD(extack, 719 "Key type S1_NORMAL cannot match on destination IP"); 720 return -EOPNOTSUPP; 721 } 722 723 tmp = &filter->key.ipv4.sip.value.addr[0]; 724 memcpy(tmp, &match.key->src, 4); 725 726 tmp = &filter->key.ipv4.sip.mask.addr[0]; 727 memcpy(tmp, &match.mask->src, 4); 728 729 tmp = &filter->key.ipv4.dip.value.addr[0]; 730 memcpy(tmp, &match.key->dst, 4); 731 732 tmp = &filter->key.ipv4.dip.mask.addr[0]; 733 memcpy(tmp, &match.mask->dst, 4); 734 match_protocol = false; 735 } 736 737 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) && 738 proto == ETH_P_IPV6) { 739 return -EOPNOTSUPP; 740 } 741 742 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 743 struct flow_match_ports match; 744 745 if (filter->block_id == VCAP_ES0) { 746 NL_SET_ERR_MSG_MOD(extack, 747 "VCAP ES0 cannot match on L4 ports"); 748 return -EOPNOTSUPP; 749 } 750 751 flow_rule_match_ports(rule, &match); 752 filter->key.ipv4.sport.value = ntohs(match.key->src); 753 filter->key.ipv4.sport.mask = ntohs(match.mask->src); 754 filter->key.ipv4.dport.value = ntohs(match.key->dst); 755 filter->key.ipv4.dport.mask = ntohs(match.mask->dst); 756 match_protocol = false; 757 } 758 759 finished_key_parsing: 760 if (match_protocol && proto != ETH_P_ALL) { 761 if (filter->block_id == VCAP_ES0) { 762 NL_SET_ERR_MSG_MOD(extack, 763 "VCAP ES0 cannot match on L2 proto"); 764 return -EOPNOTSUPP; 765 } 766 767 /* TODO: support SNAP, LLC etc */ 768 if (proto < ETH_P_802_3_MIN) 769 return -EOPNOTSUPP; 770 filter->key_type = OCELOT_VCAP_KEY_ETYPE; 771 *(__be16 *)filter->key.etype.etype.value = htons(proto); 772 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff); 773 } 774 /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */ 775 776 return 0; 777 } 778 779 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, 780 struct flow_cls_offload *f, 781 struct ocelot_vcap_filter *filter) 782 { 783 int ret; 784 785 filter->prio = f->common.prio; 786 filter->id.cookie = f->cookie; 787 filter->id.tc_offload = true; 788 789 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter); 790 if (ret) 791 return ret; 792 793 /* PSFP filter need to parse key by stream identification function. */ 794 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) 795 return 0; 796 797 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter); 798 } 799 800 static struct ocelot_vcap_filter 801 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress, 802 struct flow_cls_offload *f) 803 { 804 struct ocelot_vcap_filter *filter; 805 806 filter = kzalloc(sizeof(*filter), GFP_KERNEL); 807 if (!filter) 808 return NULL; 809 810 if (ingress) { 811 filter->ingress_port_mask = BIT(port); 812 } else { 813 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0]; 814 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length; 815 816 filter->egress_port.value = port; 817 filter->egress_port.mask = GENMASK(key_length - 1, 0); 818 } 819 820 return filter; 821 } 822 823 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot, 824 struct ocelot_vcap_filter *filter) 825 { 826 list_add(&filter->list, &ocelot->dummy_rules); 827 828 return 0; 829 } 830 831 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot, 832 struct ocelot_vcap_filter *filter) 833 { 834 list_del(&filter->list); 835 kfree(filter); 836 837 return 0; 838 } 839 840 /* If we have an egress VLAN modification rule, we need to actually write the 841 * delta between the input VLAN (from the key) and the output VLAN (from the 842 * action), but the action was parsed first. So we need to patch the delta into 843 * the action here. 844 */ 845 static int 846 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter, 847 struct netlink_ext_ack *extack) 848 { 849 if (filter->block_id != VCAP_ES0 || 850 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID) 851 return 0; 852 853 if (filter->vlan.vid.mask != VLAN_VID_MASK) { 854 NL_SET_ERR_MSG_MOD(extack, 855 "VCAP ES0 VLAN rewriting needs a full VLAN in the key"); 856 return -EOPNOTSUPP; 857 } 858 859 filter->action.vid_a_val -= filter->vlan.vid.value; 860 filter->action.vid_a_val &= VLAN_VID_MASK; 861 862 return 0; 863 } 864 865 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, 866 struct flow_cls_offload *f, bool ingress) 867 { 868 struct netlink_ext_ack *extack = f->common.extack; 869 struct ocelot_vcap_filter *filter; 870 int chain = f->common.chain_index; 871 int block_id, ret; 872 873 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) { 874 NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain"); 875 return -EOPNOTSUPP; 876 } 877 878 block_id = ocelot_chain_to_block(chain, ingress); 879 if (block_id < 0) { 880 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain"); 881 return -EOPNOTSUPP; 882 } 883 884 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id], 885 f->cookie, true); 886 if (filter) { 887 /* Filter already exists on other ports */ 888 if (!ingress) { 889 NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters"); 890 return -EOPNOTSUPP; 891 } 892 893 filter->ingress_port_mask |= BIT(port); 894 895 return ocelot_vcap_filter_replace(ocelot, filter); 896 } 897 898 /* Filter didn't exist, create it now */ 899 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f); 900 if (!filter) 901 return -ENOMEM; 902 903 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter); 904 if (ret) { 905 kfree(filter); 906 return ret; 907 } 908 909 ret = ocelot_flower_patch_es0_vlan_modify(filter, extack); 910 if (ret) { 911 kfree(filter); 912 return ret; 913 } 914 915 /* The non-optional GOTOs for the TCAM skeleton don't need 916 * to be actually offloaded. 917 */ 918 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 919 return ocelot_vcap_dummy_filter_add(ocelot, filter); 920 921 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) { 922 kfree(filter); 923 if (ocelot->ops->psfp_filter_add) 924 return ocelot->ops->psfp_filter_add(ocelot, port, f); 925 926 NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW"); 927 return -EOPNOTSUPP; 928 } 929 930 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack); 931 } 932 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace); 933 934 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, 935 struct flow_cls_offload *f, bool ingress) 936 { 937 struct ocelot_vcap_filter *filter; 938 struct ocelot_vcap_block *block; 939 int block_id; 940 941 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 942 if (block_id < 0) 943 return 0; 944 945 if (block_id == PSFP_BLOCK_ID) { 946 if (ocelot->ops->psfp_filter_del) 947 return ocelot->ops->psfp_filter_del(ocelot, f); 948 949 return -EOPNOTSUPP; 950 } 951 952 block = &ocelot->block[block_id]; 953 954 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 955 if (!filter) 956 return 0; 957 958 if (filter->type == OCELOT_VCAP_FILTER_DUMMY) 959 return ocelot_vcap_dummy_filter_del(ocelot, filter); 960 961 if (ingress) { 962 filter->ingress_port_mask &= ~BIT(port); 963 if (filter->ingress_port_mask) 964 return ocelot_vcap_filter_replace(ocelot, filter); 965 } 966 967 return ocelot_vcap_filter_del(ocelot, filter); 968 } 969 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy); 970 971 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, 972 struct flow_cls_offload *f, bool ingress) 973 { 974 struct ocelot_vcap_filter *filter; 975 struct ocelot_vcap_block *block; 976 struct flow_stats stats = {0}; 977 int block_id, ret; 978 979 block_id = ocelot_chain_to_block(f->common.chain_index, ingress); 980 if (block_id < 0) 981 return 0; 982 983 if (block_id == PSFP_BLOCK_ID) { 984 if (ocelot->ops->psfp_stats_get) { 985 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats); 986 if (ret) 987 return ret; 988 989 goto stats_update; 990 } 991 992 return -EOPNOTSUPP; 993 } 994 995 block = &ocelot->block[block_id]; 996 997 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true); 998 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY) 999 return 0; 1000 1001 ret = ocelot_vcap_filter_stats_update(ocelot, filter); 1002 if (ret) 1003 return ret; 1004 1005 stats.pkts = filter->stats.pkts; 1006 1007 stats_update: 1008 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0, 1009 FLOW_ACTION_HW_STATS_IMMEDIATE); 1010 return 0; 1011 } 1012 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats); 1013