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