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