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