1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Microchip VCAP API 3 * 4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries. 5 */ 6 7 #include <net/tc_act/tc_gate.h> 8 #include <net/tcp.h> 9 10 #include "sparx5_tc.h" 11 #include "vcap_api.h" 12 #include "vcap_api_client.h" 13 #include "vcap_tc.h" 14 #include "sparx5_main.h" 15 #include "sparx5_vcap_impl.h" 16 17 #define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */ 18 19 /* Collect keysets and type ids for multiple rules per size */ 20 struct sparx5_wildcard_rule { 21 bool selected; 22 u8 value; 23 u8 mask; 24 enum vcap_keyfield_set keyset; 25 }; 26 27 struct sparx5_multiple_rules { 28 struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE]; 29 }; 30 31 struct sparx5_tc_flower_template { 32 struct list_head list; /* for insertion in the list of templates */ 33 int cid; /* chain id */ 34 enum vcap_keyfield_set orig; /* keyset used before the template */ 35 enum vcap_keyfield_set keyset; /* new keyset used by template */ 36 u16 l3_proto; /* protocol specified in the template */ 37 }; 38 39 static int 40 sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st) 41 { 42 int err = 0; 43 44 switch (st->tpid) { 45 case ETH_P_8021Q: 46 err = vcap_rule_add_key_u32(st->vrule, 47 VCAP_KF_8021Q_TPID, 48 SPX5_TPID_SEL_8100, ~0); 49 break; 50 case ETH_P_8021AD: 51 err = vcap_rule_add_key_u32(st->vrule, 52 VCAP_KF_8021Q_TPID, 53 SPX5_TPID_SEL_88A8, ~0); 54 break; 55 default: 56 NL_SET_ERR_MSG_MOD(st->fco->common.extack, 57 "Invalid vlan proto"); 58 err = -EINVAL; 59 break; 60 } 61 return err; 62 } 63 64 static int 65 sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st) 66 { 67 struct flow_match_basic mt; 68 int err = 0; 69 70 flow_rule_match_basic(st->frule, &mt); 71 72 if (mt.mask->n_proto) { 73 st->l3_proto = be16_to_cpu(mt.key->n_proto); 74 if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) { 75 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE, 76 st->l3_proto, ~0); 77 if (err) 78 goto out; 79 } else if (st->l3_proto == ETH_P_IP) { 80 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS, 81 VCAP_BIT_1); 82 if (err) 83 goto out; 84 } else if (st->l3_proto == ETH_P_IPV6) { 85 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS, 86 VCAP_BIT_0); 87 if (err) 88 goto out; 89 if (st->admin->vtype == VCAP_TYPE_IS0) { 90 err = vcap_rule_add_key_bit(st->vrule, 91 VCAP_KF_IP_SNAP_IS, 92 VCAP_BIT_1); 93 if (err) 94 goto out; 95 } 96 } 97 } 98 99 if (mt.mask->ip_proto) { 100 st->l4_proto = mt.key->ip_proto; 101 if (st->l4_proto == IPPROTO_TCP) { 102 err = vcap_rule_add_key_bit(st->vrule, 103 VCAP_KF_TCP_IS, 104 VCAP_BIT_1); 105 if (err) 106 goto out; 107 } else if (st->l4_proto == IPPROTO_UDP) { 108 err = vcap_rule_add_key_bit(st->vrule, 109 VCAP_KF_TCP_IS, 110 VCAP_BIT_0); 111 if (err) 112 goto out; 113 if (st->admin->vtype == VCAP_TYPE_IS0) { 114 err = vcap_rule_add_key_bit(st->vrule, 115 VCAP_KF_TCP_UDP_IS, 116 VCAP_BIT_1); 117 if (err) 118 goto out; 119 } 120 } else { 121 err = vcap_rule_add_key_u32(st->vrule, 122 VCAP_KF_L3_IP_PROTO, 123 st->l4_proto, ~0); 124 if (err) 125 goto out; 126 } 127 } 128 129 st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC); 130 131 return err; 132 133 out: 134 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error"); 135 return err; 136 } 137 138 static int 139 sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st) 140 { 141 struct flow_match_control mt; 142 u32 value, mask; 143 int err = 0; 144 145 flow_rule_match_control(st->frule, &mt); 146 147 if (mt.mask->flags) { 148 if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) { 149 if (mt.key->flags & FLOW_DIS_FIRST_FRAG) { 150 value = 1; /* initial fragment */ 151 mask = 0x3; 152 } else { 153 if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { 154 value = 3; /* follow up fragment */ 155 mask = 0x3; 156 } else { 157 value = 0; /* no fragment */ 158 mask = 0x3; 159 } 160 } 161 } else { 162 if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { 163 value = 3; /* follow up fragment */ 164 mask = 0x3; 165 } else { 166 value = 0; /* no fragment */ 167 mask = 0x3; 168 } 169 } 170 171 err = vcap_rule_add_key_u32(st->vrule, 172 VCAP_KF_L3_FRAGMENT_TYPE, 173 value, mask); 174 if (err) 175 goto out; 176 } 177 178 st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL); 179 180 return err; 181 182 out: 183 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error"); 184 return err; 185 } 186 187 static int 188 sparx5_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st) 189 { 190 if (st->admin->vtype != VCAP_TYPE_IS0) { 191 NL_SET_ERR_MSG_MOD(st->fco->common.extack, 192 "cvlan not supported in this VCAP"); 193 return -EINVAL; 194 } 195 196 return vcap_tc_flower_handler_cvlan_usage(st); 197 } 198 199 static int 200 sparx5_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st) 201 { 202 enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS; 203 enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS; 204 int err; 205 206 if (st->admin->vtype == VCAP_TYPE_IS0) { 207 vid_key = VCAP_KF_8021Q_VID0; 208 pcp_key = VCAP_KF_8021Q_PCP0; 209 } 210 211 err = vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key); 212 if (err) 213 return err; 214 215 if (st->admin->vtype == VCAP_TYPE_ES0 && st->tpid) 216 err = sparx5_tc_flower_es0_tpid(st); 217 218 return err; 219 } 220 221 static int (*sparx5_tc_flower_usage_handlers[])(struct vcap_tc_flower_parse_usage *st) = { 222 [FLOW_DISSECTOR_KEY_ETH_ADDRS] = vcap_tc_flower_handler_ethaddr_usage, 223 [FLOW_DISSECTOR_KEY_IPV4_ADDRS] = vcap_tc_flower_handler_ipv4_usage, 224 [FLOW_DISSECTOR_KEY_IPV6_ADDRS] = vcap_tc_flower_handler_ipv6_usage, 225 [FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage, 226 [FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage, 227 [FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage, 228 [FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage, 229 [FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage, 230 [FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage, 231 [FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage, 232 [FLOW_DISSECTOR_KEY_IP] = vcap_tc_flower_handler_ip_usage, 233 }; 234 235 static int sparx5_tc_use_dissectors(struct vcap_tc_flower_parse_usage *st, 236 struct vcap_admin *admin, 237 struct vcap_rule *vrule) 238 { 239 int idx, err = 0; 240 241 for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) { 242 if (!flow_rule_match_key(st->frule, idx)) 243 continue; 244 if (!sparx5_tc_flower_usage_handlers[idx]) 245 continue; 246 err = sparx5_tc_flower_usage_handlers[idx](st); 247 if (err) 248 return err; 249 } 250 251 if (st->frule->match.dissector->used_keys ^ st->used_keys) { 252 NL_SET_ERR_MSG_MOD(st->fco->common.extack, 253 "Unsupported match item"); 254 return -ENOENT; 255 } 256 257 return err; 258 } 259 260 static int sparx5_tc_flower_action_check(struct vcap_control *vctrl, 261 struct net_device *ndev, 262 struct flow_cls_offload *fco, 263 bool ingress) 264 { 265 struct flow_rule *rule = flow_cls_offload_flow_rule(fco); 266 struct flow_action_entry *actent, *last_actent = NULL; 267 struct flow_action *act = &rule->action; 268 u64 action_mask = 0; 269 int idx; 270 271 if (!flow_action_has_entries(act)) { 272 NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions"); 273 return -EINVAL; 274 } 275 276 if (!flow_action_basic_hw_stats_check(act, fco->common.extack)) 277 return -EOPNOTSUPP; 278 279 flow_action_for_each(idx, actent, act) { 280 if (action_mask & BIT(actent->id)) { 281 NL_SET_ERR_MSG_MOD(fco->common.extack, 282 "More actions of the same type"); 283 return -EINVAL; 284 } 285 action_mask |= BIT(actent->id); 286 last_actent = actent; /* Save last action for later check */ 287 } 288 289 /* Check if last action is a goto 290 * The last chain/lookup does not need to have a goto action 291 */ 292 if (last_actent->id == FLOW_ACTION_GOTO) { 293 /* Check if the destination chain is in one of the VCAPs */ 294 if (!vcap_is_next_lookup(vctrl, fco->common.chain_index, 295 last_actent->chain_index)) { 296 NL_SET_ERR_MSG_MOD(fco->common.extack, 297 "Invalid goto chain"); 298 return -EINVAL; 299 } 300 } else if (!vcap_is_last_chain(vctrl, fco->common.chain_index, 301 ingress)) { 302 NL_SET_ERR_MSG_MOD(fco->common.extack, 303 "Last action must be 'goto'"); 304 return -EINVAL; 305 } 306 307 /* Catch unsupported combinations of actions */ 308 if (action_mask & BIT(FLOW_ACTION_TRAP) && 309 action_mask & BIT(FLOW_ACTION_ACCEPT)) { 310 NL_SET_ERR_MSG_MOD(fco->common.extack, 311 "Cannot combine pass and trap action"); 312 return -EOPNOTSUPP; 313 } 314 315 if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) && 316 action_mask & BIT(FLOW_ACTION_VLAN_POP)) { 317 NL_SET_ERR_MSG_MOD(fco->common.extack, 318 "Cannot combine vlan push and pop action"); 319 return -EOPNOTSUPP; 320 } 321 322 if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) && 323 action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) { 324 NL_SET_ERR_MSG_MOD(fco->common.extack, 325 "Cannot combine vlan push and modify action"); 326 return -EOPNOTSUPP; 327 } 328 329 if (action_mask & BIT(FLOW_ACTION_VLAN_POP) && 330 action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) { 331 NL_SET_ERR_MSG_MOD(fco->common.extack, 332 "Cannot combine vlan pop and modify action"); 333 return -EOPNOTSUPP; 334 } 335 336 return 0; 337 } 338 339 /* Add a rule counter action */ 340 static int sparx5_tc_add_rule_counter(struct vcap_admin *admin, 341 struct vcap_rule *vrule) 342 { 343 int err; 344 345 switch (admin->vtype) { 346 case VCAP_TYPE_IS0: 347 break; 348 case VCAP_TYPE_ES0: 349 err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX, 350 vrule->id); 351 if (err) 352 return err; 353 vcap_rule_set_counter_id(vrule, vrule->id); 354 break; 355 case VCAP_TYPE_IS2: 356 case VCAP_TYPE_ES2: 357 err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID, 358 vrule->id); 359 if (err) 360 return err; 361 vcap_rule_set_counter_id(vrule, vrule->id); 362 break; 363 default: 364 pr_err("%s:%d: vcap type: %d not supported\n", 365 __func__, __LINE__, admin->vtype); 366 break; 367 } 368 return 0; 369 } 370 371 /* Collect all port keysets and apply the first of them, possibly wildcarded */ 372 static int sparx5_tc_select_protocol_keyset(struct net_device *ndev, 373 struct vcap_rule *vrule, 374 struct vcap_admin *admin, 375 u16 l3_proto, 376 struct sparx5_multiple_rules *multi) 377 { 378 struct sparx5_port *port = netdev_priv(ndev); 379 struct vcap_keyset_list portkeysetlist = {}; 380 enum vcap_keyfield_set portkeysets[10] = {}; 381 struct vcap_keyset_list matches = {}; 382 enum vcap_keyfield_set keysets[10]; 383 int idx, jdx, err = 0, count = 0; 384 struct sparx5_wildcard_rule *mru; 385 const struct vcap_set *kinfo; 386 struct vcap_control *vctrl; 387 388 vctrl = port->sparx5->vcap_ctrl; 389 390 /* Find the keysets that the rule can use */ 391 matches.keysets = keysets; 392 matches.max = ARRAY_SIZE(keysets); 393 if (!vcap_rule_find_keysets(vrule, &matches)) 394 return -EINVAL; 395 396 /* Find the keysets that the port configuration supports */ 397 portkeysetlist.max = ARRAY_SIZE(portkeysets); 398 portkeysetlist.keysets = portkeysets; 399 err = sparx5_vcap_get_port_keyset(ndev, 400 admin, vrule->vcap_chain_id, 401 l3_proto, 402 &portkeysetlist); 403 if (err) 404 return err; 405 406 /* Find the intersection of the two sets of keyset */ 407 for (idx = 0; idx < portkeysetlist.cnt; ++idx) { 408 kinfo = vcap_keyfieldset(vctrl, admin->vtype, 409 portkeysetlist.keysets[idx]); 410 if (!kinfo) 411 continue; 412 413 /* Find a port keyset that matches the required keys 414 * If there are multiple keysets then compose a type id mask 415 */ 416 for (jdx = 0; jdx < matches.cnt; ++jdx) { 417 if (portkeysetlist.keysets[idx] != matches.keysets[jdx]) 418 continue; 419 420 mru = &multi->rule[kinfo->sw_per_item]; 421 if (!mru->selected) { 422 mru->selected = true; 423 mru->keyset = portkeysetlist.keysets[idx]; 424 mru->value = kinfo->type_id; 425 } 426 mru->value &= kinfo->type_id; 427 mru->mask |= kinfo->type_id; 428 ++count; 429 } 430 } 431 if (count == 0) 432 return -EPROTO; 433 434 if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt) 435 return -ENOENT; 436 437 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 438 mru = &multi->rule[idx]; 439 if (!mru->selected) 440 continue; 441 442 /* Align the mask to the combined value */ 443 mru->mask ^= mru->value; 444 } 445 446 /* Set the chosen keyset on the rule and set a wildcarded type if there 447 * are more than one keyset 448 */ 449 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 450 mru = &multi->rule[idx]; 451 if (!mru->selected) 452 continue; 453 454 vcap_set_rule_set_keyset(vrule, mru->keyset); 455 if (count > 1) 456 /* Some keysets do not have a type field */ 457 vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, 458 mru->value, 459 ~mru->mask); 460 mru->selected = false; /* mark as done */ 461 break; /* Stop here and add more rules later */ 462 } 463 return err; 464 } 465 466 static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl, 467 struct flow_cls_offload *fco, 468 struct vcap_rule *erule, 469 struct vcap_admin *admin, 470 struct sparx5_wildcard_rule *rule) 471 { 472 enum vcap_key_field keylist[] = { 473 VCAP_KF_IF_IGR_PORT_MASK, 474 VCAP_KF_IF_IGR_PORT_MASK_SEL, 475 VCAP_KF_IF_IGR_PORT_MASK_RNG, 476 VCAP_KF_LOOKUP_FIRST_IS, 477 VCAP_KF_TYPE, 478 }; 479 struct vcap_rule *vrule; 480 int err; 481 482 /* Add an extra rule with a special user and the new keyset */ 483 erule->user = VCAP_USER_TC_EXTRA; 484 vrule = vcap_copy_rule(erule); 485 if (IS_ERR(vrule)) 486 return PTR_ERR(vrule); 487 488 /* Link the new rule to the existing rule with the cookie */ 489 vrule->cookie = erule->cookie; 490 vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true); 491 err = vcap_set_rule_set_keyset(vrule, rule->keyset); 492 if (err) { 493 pr_err("%s:%d: could not set keyset %s in rule: %u\n", 494 __func__, __LINE__, 495 vcap_keyset_name(vctrl, rule->keyset), 496 vrule->id); 497 goto out; 498 } 499 500 /* Some keysets do not have a type field, so ignore return value */ 501 vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask); 502 503 err = vcap_set_rule_set_actionset(vrule, erule->actionset); 504 if (err) 505 goto out; 506 507 err = sparx5_tc_add_rule_counter(admin, vrule); 508 if (err) 509 goto out; 510 511 err = vcap_val_rule(vrule, ETH_P_ALL); 512 if (err) { 513 pr_err("%s:%d: could not validate rule: %u\n", 514 __func__, __LINE__, vrule->id); 515 vcap_set_tc_exterr(fco, vrule); 516 goto out; 517 } 518 err = vcap_add_rule(vrule); 519 if (err) { 520 pr_err("%s:%d: could not add rule: %u\n", 521 __func__, __LINE__, vrule->id); 522 goto out; 523 } 524 out: 525 vcap_free_rule(vrule); 526 return err; 527 } 528 529 static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl, 530 struct flow_cls_offload *fco, 531 struct vcap_rule *erule, 532 struct vcap_admin *admin, 533 struct sparx5_multiple_rules *multi) 534 { 535 int idx, err = 0; 536 537 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 538 if (!multi->rule[idx].selected) 539 continue; 540 541 err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin, 542 &multi->rule[idx]); 543 if (err) 544 break; 545 } 546 return err; 547 } 548 549 /* Add the actionset that is the default for the VCAP type */ 550 static int sparx5_tc_set_actionset(struct vcap_admin *admin, 551 struct vcap_rule *vrule) 552 { 553 enum vcap_actionfield_set aset; 554 int err = 0; 555 556 switch (admin->vtype) { 557 case VCAP_TYPE_IS0: 558 aset = VCAP_AFS_CLASSIFICATION; 559 break; 560 case VCAP_TYPE_IS2: 561 aset = VCAP_AFS_BASE_TYPE; 562 break; 563 case VCAP_TYPE_ES0: 564 aset = VCAP_AFS_ES0; 565 break; 566 case VCAP_TYPE_ES2: 567 aset = VCAP_AFS_BASE_TYPE; 568 break; 569 default: 570 pr_err("%s:%d: %s\n", __func__, __LINE__, "Invalid VCAP type"); 571 return -EINVAL; 572 } 573 /* Do not overwrite any current actionset */ 574 if (vrule->actionset == VCAP_AFS_NO_VALUE) 575 err = vcap_set_rule_set_actionset(vrule, aset); 576 return err; 577 } 578 579 /* Add the VCAP key to match on for a rule target value */ 580 static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin, 581 struct vcap_rule *vrule, 582 int target_cid) 583 { 584 int link_val = target_cid % VCAP_CID_LOOKUP_SIZE; 585 int err; 586 587 if (!link_val) 588 return 0; 589 590 switch (admin->vtype) { 591 case VCAP_TYPE_IS0: 592 /* Add NXT_IDX key for chaining rules between IS0 instances */ 593 err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL, 594 1, /* enable */ 595 ~0); 596 if (err) 597 return err; 598 return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX, 599 link_val, /* target */ 600 ~0); 601 case VCAP_TYPE_IS2: 602 /* Add PAG key for chaining rules from IS0 */ 603 return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG, 604 link_val, /* target */ 605 ~0); 606 case VCAP_TYPE_ES0: 607 case VCAP_TYPE_ES2: 608 /* Add ISDX key for chaining rules from IS0 */ 609 return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS, link_val, 610 ~0); 611 default: 612 break; 613 } 614 return 0; 615 } 616 617 /* Add the VCAP action that adds a target value to a rule */ 618 static int sparx5_tc_add_rule_link(struct vcap_control *vctrl, 619 struct vcap_admin *admin, 620 struct vcap_rule *vrule, 621 int from_cid, int to_cid) 622 { 623 struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid); 624 int diff, err = 0; 625 626 if (!to_admin) { 627 pr_err("%s:%d: unsupported chain direction: %d\n", 628 __func__, __LINE__, to_cid); 629 return -EINVAL; 630 } 631 632 diff = vcap_chain_offset(vctrl, from_cid, to_cid); 633 if (!diff) 634 return 0; 635 636 if (admin->vtype == VCAP_TYPE_IS0 && 637 to_admin->vtype == VCAP_TYPE_IS0) { 638 /* Between IS0 instances the G_IDX value is used */ 639 err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff); 640 if (err) 641 goto out; 642 err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL, 643 1); /* Replace */ 644 if (err) 645 goto out; 646 } else if (admin->vtype == VCAP_TYPE_IS0 && 647 to_admin->vtype == VCAP_TYPE_IS2) { 648 /* Between IS0 and IS2 the PAG value is used */ 649 err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff); 650 if (err) 651 goto out; 652 err = vcap_rule_add_action_u32(vrule, 653 VCAP_AF_PAG_OVERRIDE_MASK, 654 0xff); 655 if (err) 656 goto out; 657 } else if (admin->vtype == VCAP_TYPE_IS0 && 658 (to_admin->vtype == VCAP_TYPE_ES0 || 659 to_admin->vtype == VCAP_TYPE_ES2)) { 660 /* Between IS0 and ES0/ES2 the ISDX value is used */ 661 err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL, 662 diff); 663 if (err) 664 goto out; 665 err = vcap_rule_add_action_bit(vrule, 666 VCAP_AF_ISDX_ADD_REPLACE_SEL, 667 VCAP_BIT_1); 668 if (err) 669 goto out; 670 } else { 671 pr_err("%s:%d: unsupported chain destination: %d\n", 672 __func__, __LINE__, to_cid); 673 err = -EOPNOTSUPP; 674 } 675 out: 676 return err; 677 } 678 679 static int sparx5_tc_flower_parse_act_gate(struct sparx5_psfp_sg *sg, 680 struct flow_action_entry *act, 681 struct netlink_ext_ack *extack) 682 { 683 int i; 684 685 if (act->gate.prio < -1 || act->gate.prio > SPX5_PSFP_SG_MAX_IPV) { 686 NL_SET_ERR_MSG_MOD(extack, "Invalid gate priority"); 687 return -EINVAL; 688 } 689 690 if (act->gate.cycletime < SPX5_PSFP_SG_MIN_CYCLE_TIME_NS || 691 act->gate.cycletime > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) { 692 NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletime"); 693 return -EINVAL; 694 } 695 696 if (act->gate.cycletimeext > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) { 697 NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletimeext"); 698 return -EINVAL; 699 } 700 701 if (act->gate.num_entries >= SPX5_PSFP_GCE_CNT) { 702 NL_SET_ERR_MSG_MOD(extack, "Invalid number of gate entries"); 703 return -EINVAL; 704 } 705 706 sg->gate_state = true; 707 sg->ipv = act->gate.prio; 708 sg->num_entries = act->gate.num_entries; 709 sg->cycletime = act->gate.cycletime; 710 sg->cycletimeext = act->gate.cycletimeext; 711 712 for (i = 0; i < sg->num_entries; i++) { 713 sg->gce[i].gate_state = !!act->gate.entries[i].gate_state; 714 sg->gce[i].interval = act->gate.entries[i].interval; 715 sg->gce[i].ipv = act->gate.entries[i].ipv; 716 sg->gce[i].maxoctets = act->gate.entries[i].maxoctets; 717 } 718 719 return 0; 720 } 721 722 static int sparx5_tc_flower_parse_act_police(struct sparx5_policer *pol, 723 struct flow_action_entry *act, 724 struct netlink_ext_ack *extack) 725 { 726 pol->type = SPX5_POL_SERVICE; 727 pol->rate = div_u64(act->police.rate_bytes_ps, 1000) * 8; 728 pol->burst = act->police.burst; 729 pol->idx = act->hw_index; 730 731 /* rate is now in kbit */ 732 if (pol->rate > DIV_ROUND_UP(SPX5_SDLB_GROUP_RATE_MAX, 1000)) { 733 NL_SET_ERR_MSG_MOD(extack, "Maximum rate exceeded"); 734 return -EINVAL; 735 } 736 737 if (act->police.exceed.act_id != FLOW_ACTION_DROP) { 738 NL_SET_ERR_MSG_MOD(extack, "Offload not supported when exceed action is not drop"); 739 return -EOPNOTSUPP; 740 } 741 742 if (act->police.notexceed.act_id != FLOW_ACTION_PIPE && 743 act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { 744 NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform action is not pipe or ok"); 745 return -EOPNOTSUPP; 746 } 747 748 return 0; 749 } 750 751 static int sparx5_tc_flower_psfp_setup(struct sparx5 *sparx5, 752 struct vcap_rule *vrule, int sg_idx, 753 int pol_idx, struct sparx5_psfp_sg *sg, 754 struct sparx5_psfp_fm *fm, 755 struct sparx5_psfp_sf *sf) 756 { 757 u32 psfp_sfid = 0, psfp_fmid = 0, psfp_sgid = 0; 758 int ret; 759 760 /* Must always have a stream gate - max sdu (filter option) is evaluated 761 * after frames have passed the gate, so in case of only a policer, we 762 * allocate a stream gate that is always open. 763 */ 764 if (sg_idx < 0) { 765 sg_idx = sparx5_pool_idx_to_id(SPX5_PSFP_SG_OPEN); 766 sg->ipv = 0; /* Disabled */ 767 sg->cycletime = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT; 768 sg->num_entries = 1; 769 sg->gate_state = 1; /* Open */ 770 sg->gate_enabled = 1; 771 sg->gce[0].gate_state = 1; 772 sg->gce[0].interval = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT; 773 sg->gce[0].ipv = 0; 774 sg->gce[0].maxoctets = 0; /* Disabled */ 775 } 776 777 ret = sparx5_psfp_sg_add(sparx5, sg_idx, sg, &psfp_sgid); 778 if (ret < 0) 779 return ret; 780 781 if (pol_idx >= 0) { 782 /* Add new flow-meter */ 783 ret = sparx5_psfp_fm_add(sparx5, pol_idx, fm, &psfp_fmid); 784 if (ret < 0) 785 return ret; 786 } 787 788 /* Map stream filter to stream gate */ 789 sf->sgid = psfp_sgid; 790 791 /* Add new stream-filter and map it to a steam gate */ 792 ret = sparx5_psfp_sf_add(sparx5, sf, &psfp_sfid); 793 if (ret < 0) 794 return ret; 795 796 /* Streams are classified by ISDX - map ISDX 1:1 to sfid for now. */ 797 sparx5_isdx_conf_set(sparx5, psfp_sfid, psfp_sfid, psfp_fmid); 798 799 ret = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_ADD_REPLACE_SEL, 800 VCAP_BIT_1); 801 if (ret) 802 return ret; 803 804 ret = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL, psfp_sfid); 805 if (ret) 806 return ret; 807 808 return 0; 809 } 810 811 /* Handle the action trap for a VCAP rule */ 812 static int sparx5_tc_action_trap(struct vcap_admin *admin, 813 struct vcap_rule *vrule, 814 struct flow_cls_offload *fco) 815 { 816 int err = 0; 817 818 switch (admin->vtype) { 819 case VCAP_TYPE_IS2: 820 err = vcap_rule_add_action_bit(vrule, 821 VCAP_AF_CPU_COPY_ENA, 822 VCAP_BIT_1); 823 if (err) 824 break; 825 err = vcap_rule_add_action_u32(vrule, 826 VCAP_AF_CPU_QUEUE_NUM, 0); 827 if (err) 828 break; 829 err = vcap_rule_add_action_u32(vrule, 830 VCAP_AF_MASK_MODE, 831 SPX5_PMM_REPLACE_ALL); 832 break; 833 case VCAP_TYPE_ES0: 834 err = vcap_rule_add_action_u32(vrule, 835 VCAP_AF_FWD_SEL, 836 SPX5_FWSEL_REDIRECT_TO_LOOPBACK); 837 break; 838 case VCAP_TYPE_ES2: 839 err = vcap_rule_add_action_bit(vrule, 840 VCAP_AF_CPU_COPY_ENA, 841 VCAP_BIT_1); 842 if (err) 843 break; 844 err = vcap_rule_add_action_u32(vrule, 845 VCAP_AF_CPU_QUEUE_NUM, 0); 846 break; 847 default: 848 NL_SET_ERR_MSG_MOD(fco->common.extack, 849 "Trap action not supported in this VCAP"); 850 err = -EOPNOTSUPP; 851 break; 852 } 853 return err; 854 } 855 856 static int sparx5_tc_action_vlan_pop(struct vcap_admin *admin, 857 struct vcap_rule *vrule, 858 struct flow_cls_offload *fco, 859 u16 tpid) 860 { 861 int err = 0; 862 863 switch (admin->vtype) { 864 case VCAP_TYPE_ES0: 865 break; 866 default: 867 NL_SET_ERR_MSG_MOD(fco->common.extack, 868 "VLAN pop action not supported in this VCAP"); 869 return -EOPNOTSUPP; 870 } 871 872 switch (tpid) { 873 case ETH_P_8021Q: 874 case ETH_P_8021AD: 875 err = vcap_rule_add_action_u32(vrule, 876 VCAP_AF_PUSH_OUTER_TAG, 877 SPX5_OTAG_UNTAG); 878 break; 879 default: 880 NL_SET_ERR_MSG_MOD(fco->common.extack, 881 "Invalid vlan proto"); 882 err = -EINVAL; 883 } 884 return err; 885 } 886 887 static int sparx5_tc_action_vlan_modify(struct vcap_admin *admin, 888 struct vcap_rule *vrule, 889 struct flow_cls_offload *fco, 890 struct flow_action_entry *act, 891 u16 tpid) 892 { 893 int err = 0; 894 895 switch (admin->vtype) { 896 case VCAP_TYPE_ES0: 897 err = vcap_rule_add_action_u32(vrule, 898 VCAP_AF_PUSH_OUTER_TAG, 899 SPX5_OTAG_TAG_A); 900 if (err) 901 return err; 902 break; 903 default: 904 NL_SET_ERR_MSG_MOD(fco->common.extack, 905 "VLAN modify action not supported in this VCAP"); 906 return -EOPNOTSUPP; 907 } 908 909 switch (tpid) { 910 case ETH_P_8021Q: 911 err = vcap_rule_add_action_u32(vrule, 912 VCAP_AF_TAG_A_TPID_SEL, 913 SPX5_TPID_A_8100); 914 break; 915 case ETH_P_8021AD: 916 err = vcap_rule_add_action_u32(vrule, 917 VCAP_AF_TAG_A_TPID_SEL, 918 SPX5_TPID_A_88A8); 919 break; 920 default: 921 NL_SET_ERR_MSG_MOD(fco->common.extack, 922 "Invalid vlan proto"); 923 err = -EINVAL; 924 } 925 if (err) 926 return err; 927 928 err = vcap_rule_add_action_u32(vrule, 929 VCAP_AF_TAG_A_VID_SEL, 930 SPX5_VID_A_VAL); 931 if (err) 932 return err; 933 934 err = vcap_rule_add_action_u32(vrule, 935 VCAP_AF_VID_A_VAL, 936 act->vlan.vid); 937 if (err) 938 return err; 939 940 err = vcap_rule_add_action_u32(vrule, 941 VCAP_AF_TAG_A_PCP_SEL, 942 SPX5_PCP_A_VAL); 943 if (err) 944 return err; 945 946 err = vcap_rule_add_action_u32(vrule, 947 VCAP_AF_PCP_A_VAL, 948 act->vlan.prio); 949 if (err) 950 return err; 951 952 return vcap_rule_add_action_u32(vrule, 953 VCAP_AF_TAG_A_DEI_SEL, 954 SPX5_DEI_A_CLASSIFIED); 955 } 956 957 static int sparx5_tc_action_vlan_push(struct vcap_admin *admin, 958 struct vcap_rule *vrule, 959 struct flow_cls_offload *fco, 960 struct flow_action_entry *act, 961 u16 tpid) 962 { 963 u16 act_tpid = be16_to_cpu(act->vlan.proto); 964 int err = 0; 965 966 switch (admin->vtype) { 967 case VCAP_TYPE_ES0: 968 break; 969 default: 970 NL_SET_ERR_MSG_MOD(fco->common.extack, 971 "VLAN push action not supported in this VCAP"); 972 return -EOPNOTSUPP; 973 } 974 975 if (tpid == ETH_P_8021AD) { 976 NL_SET_ERR_MSG_MOD(fco->common.extack, 977 "Cannot push on double tagged frames"); 978 return -EOPNOTSUPP; 979 } 980 981 err = sparx5_tc_action_vlan_modify(admin, vrule, fco, act, act_tpid); 982 if (err) 983 return err; 984 985 switch (act_tpid) { 986 case ETH_P_8021Q: 987 break; 988 case ETH_P_8021AD: 989 /* Push classified tag as inner tag */ 990 err = vcap_rule_add_action_u32(vrule, 991 VCAP_AF_PUSH_INNER_TAG, 992 SPX5_ITAG_PUSH_B_TAG); 993 if (err) 994 break; 995 err = vcap_rule_add_action_u32(vrule, 996 VCAP_AF_TAG_B_TPID_SEL, 997 SPX5_TPID_B_CLASSIFIED); 998 break; 999 default: 1000 NL_SET_ERR_MSG_MOD(fco->common.extack, 1001 "Invalid vlan proto"); 1002 err = -EINVAL; 1003 } 1004 return err; 1005 } 1006 1007 static void sparx5_tc_flower_set_port_mask(struct vcap_u72_action *ports, 1008 struct net_device *ndev) 1009 { 1010 struct sparx5_port *port = netdev_priv(ndev); 1011 int byidx = port->portno / BITS_PER_BYTE; 1012 int biidx = port->portno % BITS_PER_BYTE; 1013 1014 ports->value[byidx] |= BIT(biidx); 1015 } 1016 1017 static int sparx5_tc_action_mirred(struct vcap_admin *admin, 1018 struct vcap_rule *vrule, 1019 struct flow_cls_offload *fco, 1020 struct flow_action_entry *act) 1021 { 1022 struct vcap_u72_action ports = {0}; 1023 int err; 1024 1025 if (admin->vtype != VCAP_TYPE_IS0 && admin->vtype != VCAP_TYPE_IS2) { 1026 NL_SET_ERR_MSG_MOD(fco->common.extack, 1027 "Mirror action not supported in this VCAP"); 1028 return -EOPNOTSUPP; 1029 } 1030 1031 err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE, 1032 SPX5_PMM_OR_DSTMASK); 1033 if (err) 1034 return err; 1035 1036 sparx5_tc_flower_set_port_mask(&ports, act->dev); 1037 1038 return vcap_rule_add_action_u72(vrule, VCAP_AF_PORT_MASK, &ports); 1039 } 1040 1041 static int sparx5_tc_action_redirect(struct vcap_admin *admin, 1042 struct vcap_rule *vrule, 1043 struct flow_cls_offload *fco, 1044 struct flow_action_entry *act) 1045 { 1046 struct vcap_u72_action ports = {0}; 1047 int err; 1048 1049 if (admin->vtype != VCAP_TYPE_IS0 && admin->vtype != VCAP_TYPE_IS2) { 1050 NL_SET_ERR_MSG_MOD(fco->common.extack, 1051 "Redirect action not supported in this VCAP"); 1052 return -EOPNOTSUPP; 1053 } 1054 1055 err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE, 1056 SPX5_PMM_REPLACE_ALL); 1057 if (err) 1058 return err; 1059 1060 sparx5_tc_flower_set_port_mask(&ports, act->dev); 1061 1062 return vcap_rule_add_action_u72(vrule, VCAP_AF_PORT_MASK, &ports); 1063 } 1064 1065 /* Remove rule keys that may prevent templates from matching a keyset */ 1066 static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin, 1067 struct vcap_rule *vrule, 1068 u16 l3_proto) 1069 { 1070 switch (admin->vtype) { 1071 case VCAP_TYPE_IS0: 1072 vcap_rule_rem_key(vrule, VCAP_KF_ETYPE); 1073 switch (l3_proto) { 1074 case ETH_P_IP: 1075 break; 1076 case ETH_P_IPV6: 1077 vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS); 1078 break; 1079 default: 1080 break; 1081 } 1082 break; 1083 case VCAP_TYPE_ES2: 1084 switch (l3_proto) { 1085 case ETH_P_IP: 1086 if (vrule->keyset == VCAP_KFS_IP4_OTHER) 1087 vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS); 1088 break; 1089 case ETH_P_IPV6: 1090 if (vrule->keyset == VCAP_KFS_IP6_STD) 1091 vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS); 1092 vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS); 1093 break; 1094 default: 1095 break; 1096 } 1097 break; 1098 case VCAP_TYPE_IS2: 1099 switch (l3_proto) { 1100 case ETH_P_IP: 1101 case ETH_P_IPV6: 1102 vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS); 1103 break; 1104 default: 1105 break; 1106 } 1107 break; 1108 default: 1109 break; 1110 } 1111 } 1112 1113 static bool sparx5_tc_flower_use_template(struct net_device *ndev, 1114 struct flow_cls_offload *fco, 1115 struct vcap_admin *admin, 1116 struct vcap_rule *vrule) 1117 { 1118 struct sparx5_port *port = netdev_priv(ndev); 1119 struct sparx5_tc_flower_template *ftp; 1120 1121 list_for_each_entry(ftp, &port->tc_templates, list) { 1122 if (ftp->cid != fco->common.chain_index) 1123 continue; 1124 1125 vcap_set_rule_set_keyset(vrule, ftp->keyset); 1126 sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto); 1127 return true; 1128 } 1129 return false; 1130 } 1131 1132 static int sparx5_tc_flower_replace(struct net_device *ndev, 1133 struct flow_cls_offload *fco, 1134 struct vcap_admin *admin, 1135 bool ingress) 1136 { 1137 struct sparx5_psfp_sf sf = { .max_sdu = SPX5_PSFP_SF_MAX_SDU }; 1138 struct netlink_ext_ack *extack = fco->common.extack; 1139 int err, idx, tc_sg_idx = -1, tc_pol_idx = -1; 1140 struct vcap_tc_flower_parse_usage state = { 1141 .fco = fco, 1142 .l3_proto = ETH_P_ALL, 1143 .admin = admin, 1144 }; 1145 struct sparx5_port *port = netdev_priv(ndev); 1146 struct sparx5_multiple_rules multi = {}; 1147 struct sparx5 *sparx5 = port->sparx5; 1148 struct sparx5_psfp_sg sg = { 0 }; 1149 struct sparx5_psfp_fm fm = { 0 }; 1150 struct flow_action_entry *act; 1151 struct vcap_control *vctrl; 1152 struct flow_rule *frule; 1153 struct vcap_rule *vrule; 1154 1155 vctrl = port->sparx5->vcap_ctrl; 1156 1157 err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress); 1158 if (err) 1159 return err; 1160 1161 vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC, 1162 fco->common.prio, 0); 1163 if (IS_ERR(vrule)) 1164 return PTR_ERR(vrule); 1165 1166 vrule->cookie = fco->cookie; 1167 1168 state.vrule = vrule; 1169 state.frule = flow_cls_offload_flow_rule(fco); 1170 err = sparx5_tc_use_dissectors(&state, admin, vrule); 1171 if (err) 1172 goto out; 1173 1174 err = sparx5_tc_add_rule_counter(admin, vrule); 1175 if (err) 1176 goto out; 1177 1178 err = sparx5_tc_add_rule_link_target(admin, vrule, 1179 fco->common.chain_index); 1180 if (err) 1181 goto out; 1182 1183 frule = flow_cls_offload_flow_rule(fco); 1184 flow_action_for_each(idx, act, &frule->action) { 1185 switch (act->id) { 1186 case FLOW_ACTION_GATE: { 1187 err = sparx5_tc_flower_parse_act_gate(&sg, act, extack); 1188 if (err < 0) 1189 goto out; 1190 1191 tc_sg_idx = act->hw_index; 1192 1193 break; 1194 } 1195 case FLOW_ACTION_POLICE: { 1196 err = sparx5_tc_flower_parse_act_police(&fm.pol, act, 1197 extack); 1198 if (err < 0) 1199 goto out; 1200 1201 tc_pol_idx = fm.pol.idx; 1202 sf.max_sdu = act->police.mtu; 1203 1204 break; 1205 } 1206 case FLOW_ACTION_TRAP: 1207 err = sparx5_tc_action_trap(admin, vrule, fco); 1208 if (err) 1209 goto out; 1210 break; 1211 case FLOW_ACTION_MIRRED: 1212 err = sparx5_tc_action_mirred(admin, vrule, fco, act); 1213 if (err) 1214 goto out; 1215 break; 1216 case FLOW_ACTION_REDIRECT: 1217 err = sparx5_tc_action_redirect(admin, vrule, fco, act); 1218 if (err) 1219 goto out; 1220 break; 1221 case FLOW_ACTION_ACCEPT: 1222 err = sparx5_tc_set_actionset(admin, vrule); 1223 if (err) 1224 goto out; 1225 break; 1226 case FLOW_ACTION_GOTO: 1227 err = sparx5_tc_set_actionset(admin, vrule); 1228 if (err) 1229 goto out; 1230 sparx5_tc_add_rule_link(vctrl, admin, vrule, 1231 fco->common.chain_index, 1232 act->chain_index); 1233 break; 1234 case FLOW_ACTION_VLAN_POP: 1235 err = sparx5_tc_action_vlan_pop(admin, vrule, fco, 1236 state.tpid); 1237 if (err) 1238 goto out; 1239 break; 1240 case FLOW_ACTION_VLAN_PUSH: 1241 err = sparx5_tc_action_vlan_push(admin, vrule, fco, 1242 act, state.tpid); 1243 if (err) 1244 goto out; 1245 break; 1246 case FLOW_ACTION_VLAN_MANGLE: 1247 err = sparx5_tc_action_vlan_modify(admin, vrule, fco, 1248 act, state.tpid); 1249 if (err) 1250 goto out; 1251 break; 1252 default: 1253 NL_SET_ERR_MSG_MOD(fco->common.extack, 1254 "Unsupported TC action"); 1255 err = -EOPNOTSUPP; 1256 goto out; 1257 } 1258 } 1259 1260 /* Setup PSFP */ 1261 if (tc_sg_idx >= 0 || tc_pol_idx >= 0) { 1262 err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx, 1263 tc_pol_idx, &sg, &fm, &sf); 1264 if (err) 1265 goto out; 1266 } 1267 1268 if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) { 1269 err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin, 1270 state.l3_proto, &multi); 1271 if (err) { 1272 NL_SET_ERR_MSG_MOD(fco->common.extack, 1273 "No matching port keyset for filter protocol and keys"); 1274 goto out; 1275 } 1276 } 1277 1278 /* provide the l3 protocol to guide the keyset selection */ 1279 err = vcap_val_rule(vrule, state.l3_proto); 1280 if (err) { 1281 vcap_set_tc_exterr(fco, vrule); 1282 goto out; 1283 } 1284 err = vcap_add_rule(vrule); 1285 if (err) 1286 NL_SET_ERR_MSG_MOD(fco->common.extack, 1287 "Could not add the filter"); 1288 1289 if (state.l3_proto == ETH_P_ALL) 1290 err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin, 1291 &multi); 1292 1293 out: 1294 vcap_free_rule(vrule); 1295 return err; 1296 } 1297 1298 static void sparx5_tc_free_psfp_resources(struct sparx5 *sparx5, 1299 struct vcap_rule *vrule) 1300 { 1301 struct vcap_client_actionfield *afield; 1302 u32 isdx, sfid, sgid, fmid; 1303 1304 /* Check if VCAP_AF_ISDX_VAL action is set for this rule - and if 1305 * it is used for stream and/or flow-meter classification. 1306 */ 1307 afield = vcap_find_actionfield(vrule, VCAP_AF_ISDX_VAL); 1308 if (!afield) 1309 return; 1310 1311 isdx = afield->data.u32.value; 1312 sfid = sparx5_psfp_isdx_get_sf(sparx5, isdx); 1313 1314 if (!sfid) 1315 return; 1316 1317 fmid = sparx5_psfp_isdx_get_fm(sparx5, isdx); 1318 sgid = sparx5_psfp_sf_get_sg(sparx5, sfid); 1319 1320 if (fmid && sparx5_psfp_fm_del(sparx5, fmid) < 0) 1321 pr_err("%s:%d Could not delete invalid fmid: %d", __func__, 1322 __LINE__, fmid); 1323 1324 if (sgid && sparx5_psfp_sg_del(sparx5, sgid) < 0) 1325 pr_err("%s:%d Could not delete invalid sgid: %d", __func__, 1326 __LINE__, sgid); 1327 1328 if (sparx5_psfp_sf_del(sparx5, sfid) < 0) 1329 pr_err("%s:%d Could not delete invalid sfid: %d", __func__, 1330 __LINE__, sfid); 1331 1332 sparx5_isdx_conf_set(sparx5, isdx, 0, 0); 1333 } 1334 1335 static int sparx5_tc_free_rule_resources(struct net_device *ndev, 1336 struct vcap_control *vctrl, 1337 int rule_id) 1338 { 1339 struct sparx5_port *port = netdev_priv(ndev); 1340 struct sparx5 *sparx5 = port->sparx5; 1341 struct vcap_rule *vrule; 1342 int ret = 0; 1343 1344 vrule = vcap_get_rule(vctrl, rule_id); 1345 if (IS_ERR(vrule)) 1346 return -EINVAL; 1347 1348 sparx5_tc_free_psfp_resources(sparx5, vrule); 1349 1350 vcap_free_rule(vrule); 1351 return ret; 1352 } 1353 1354 static int sparx5_tc_flower_destroy(struct net_device *ndev, 1355 struct flow_cls_offload *fco, 1356 struct vcap_admin *admin) 1357 { 1358 struct sparx5_port *port = netdev_priv(ndev); 1359 int err = -ENOENT, count = 0, rule_id; 1360 struct vcap_control *vctrl; 1361 1362 vctrl = port->sparx5->vcap_ctrl; 1363 while (true) { 1364 rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie); 1365 if (rule_id <= 0) 1366 break; 1367 if (count == 0) { 1368 /* Resources are attached to the first rule of 1369 * a set of rules. Only works if the rules are 1370 * in the correct order. 1371 */ 1372 err = sparx5_tc_free_rule_resources(ndev, vctrl, 1373 rule_id); 1374 if (err) 1375 pr_err("%s:%d: could not free resources %d\n", 1376 __func__, __LINE__, rule_id); 1377 } 1378 err = vcap_del_rule(vctrl, ndev, rule_id); 1379 if (err) { 1380 pr_err("%s:%d: could not delete rule %d\n", 1381 __func__, __LINE__, rule_id); 1382 break; 1383 } 1384 } 1385 return err; 1386 } 1387 1388 static int sparx5_tc_flower_stats(struct net_device *ndev, 1389 struct flow_cls_offload *fco, 1390 struct vcap_admin *admin) 1391 { 1392 struct sparx5_port *port = netdev_priv(ndev); 1393 struct vcap_counter ctr = {}; 1394 struct vcap_control *vctrl; 1395 ulong lastused = 0; 1396 int err; 1397 1398 vctrl = port->sparx5->vcap_ctrl; 1399 err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie); 1400 if (err) 1401 return err; 1402 flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused, 1403 FLOW_ACTION_HW_STATS_IMMEDIATE); 1404 return err; 1405 } 1406 1407 static int sparx5_tc_flower_template_create(struct net_device *ndev, 1408 struct flow_cls_offload *fco, 1409 struct vcap_admin *admin) 1410 { 1411 struct sparx5_port *port = netdev_priv(ndev); 1412 struct vcap_tc_flower_parse_usage state = { 1413 .fco = fco, 1414 .l3_proto = ETH_P_ALL, 1415 .admin = admin, 1416 }; 1417 struct sparx5_tc_flower_template *ftp; 1418 struct vcap_keyset_list kslist = {}; 1419 enum vcap_keyfield_set keysets[10]; 1420 struct vcap_control *vctrl; 1421 struct vcap_rule *vrule; 1422 int count, err; 1423 1424 if (admin->vtype == VCAP_TYPE_ES0) { 1425 pr_err("%s:%d: %s\n", __func__, __LINE__, 1426 "VCAP does not support templates"); 1427 return -EINVAL; 1428 } 1429 1430 count = vcap_admin_rule_count(admin, fco->common.chain_index); 1431 if (count > 0) { 1432 pr_err("%s:%d: %s\n", __func__, __LINE__, 1433 "Filters are already present"); 1434 return -EBUSY; 1435 } 1436 1437 ftp = kzalloc(sizeof(*ftp), GFP_KERNEL); 1438 if (!ftp) 1439 return -ENOMEM; 1440 1441 ftp->cid = fco->common.chain_index; 1442 ftp->orig = VCAP_KFS_NO_VALUE; 1443 ftp->keyset = VCAP_KFS_NO_VALUE; 1444 1445 vctrl = port->sparx5->vcap_ctrl; 1446 vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, 1447 VCAP_USER_TC, fco->common.prio, 0); 1448 if (IS_ERR(vrule)) { 1449 err = PTR_ERR(vrule); 1450 goto err_rule; 1451 } 1452 1453 state.vrule = vrule; 1454 state.frule = flow_cls_offload_flow_rule(fco); 1455 err = sparx5_tc_use_dissectors(&state, admin, vrule); 1456 if (err) { 1457 pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err); 1458 goto out; 1459 } 1460 1461 ftp->l3_proto = state.l3_proto; 1462 1463 sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto); 1464 1465 /* Find the keysets that the rule can use */ 1466 kslist.keysets = keysets; 1467 kslist.max = ARRAY_SIZE(keysets); 1468 if (!vcap_rule_find_keysets(vrule, &kslist)) { 1469 pr_err("%s:%d: %s\n", __func__, __LINE__, 1470 "Could not find a suitable keyset"); 1471 err = -ENOENT; 1472 goto out; 1473 } 1474 1475 ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist); 1476 kslist.cnt = 0; 1477 sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index, 1478 state.l3_proto, 1479 ftp->keyset, 1480 &kslist); 1481 1482 if (kslist.cnt > 0) 1483 ftp->orig = kslist.keysets[0]; 1484 1485 /* Store new template */ 1486 list_add_tail(&ftp->list, &port->tc_templates); 1487 vcap_free_rule(vrule); 1488 return 0; 1489 1490 out: 1491 vcap_free_rule(vrule); 1492 err_rule: 1493 kfree(ftp); 1494 return err; 1495 } 1496 1497 static int sparx5_tc_flower_template_destroy(struct net_device *ndev, 1498 struct flow_cls_offload *fco, 1499 struct vcap_admin *admin) 1500 { 1501 struct sparx5_port *port = netdev_priv(ndev); 1502 struct sparx5_tc_flower_template *ftp, *tmp; 1503 int err = -ENOENT; 1504 1505 /* Rules using the template are removed by the tc framework */ 1506 list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) { 1507 if (ftp->cid != fco->common.chain_index) 1508 continue; 1509 1510 sparx5_vcap_set_port_keyset(ndev, admin, 1511 fco->common.chain_index, 1512 ftp->l3_proto, ftp->orig, 1513 NULL); 1514 list_del(&ftp->list); 1515 kfree(ftp); 1516 break; 1517 } 1518 return err; 1519 } 1520 1521 int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco, 1522 bool ingress) 1523 { 1524 struct sparx5_port *port = netdev_priv(ndev); 1525 struct vcap_control *vctrl; 1526 struct vcap_admin *admin; 1527 int err = -EINVAL; 1528 1529 /* Get vcap instance from the chain id */ 1530 vctrl = port->sparx5->vcap_ctrl; 1531 admin = vcap_find_admin(vctrl, fco->common.chain_index); 1532 if (!admin) { 1533 NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain"); 1534 return err; 1535 } 1536 1537 switch (fco->command) { 1538 case FLOW_CLS_REPLACE: 1539 return sparx5_tc_flower_replace(ndev, fco, admin, ingress); 1540 case FLOW_CLS_DESTROY: 1541 return sparx5_tc_flower_destroy(ndev, fco, admin); 1542 case FLOW_CLS_STATS: 1543 return sparx5_tc_flower_stats(ndev, fco, admin); 1544 case FLOW_CLS_TMPLT_CREATE: 1545 return sparx5_tc_flower_template_create(ndev, fco, admin); 1546 case FLOW_CLS_TMPLT_DESTROY: 1547 return sparx5_tc_flower_template_destroy(ndev, fco, admin); 1548 default: 1549 return -EOPNOTSUPP; 1550 } 1551 } 1552