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