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