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