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