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/tcp.h> 8 9 #include "sparx5_tc.h" 10 #include "vcap_api.h" 11 #include "vcap_api_client.h" 12 #include "sparx5_main.h" 13 #include "sparx5_vcap_impl.h" 14 15 #define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */ 16 17 /* Collect keysets and type ids for multiple rules per size */ 18 struct sparx5_wildcard_rule { 19 bool selected; 20 u8 value; 21 u8 mask; 22 enum vcap_keyfield_set keyset; 23 }; 24 25 struct sparx5_multiple_rules { 26 struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE]; 27 }; 28 29 struct sparx5_tc_flower_parse_usage { 30 struct flow_cls_offload *fco; 31 struct flow_rule *frule; 32 struct vcap_rule *vrule; 33 struct vcap_admin *admin; 34 u16 l3_proto; 35 u8 l4_proto; 36 unsigned int used_keys; 37 }; 38 39 enum sparx5_is2_arp_opcode { 40 SPX5_IS2_ARP_REQUEST, 41 SPX5_IS2_ARP_REPLY, 42 SPX5_IS2_RARP_REQUEST, 43 SPX5_IS2_RARP_REPLY, 44 }; 45 46 enum tc_arp_opcode { 47 TC_ARP_OP_RESERVED, 48 TC_ARP_OP_REQUEST, 49 TC_ARP_OP_REPLY, 50 }; 51 52 static int sparx5_tc_flower_handler_ethaddr_usage(struct sparx5_tc_flower_parse_usage *st) 53 { 54 enum vcap_key_field smac_key = VCAP_KF_L2_SMAC; 55 enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC; 56 struct flow_match_eth_addrs match; 57 struct vcap_u48_key smac, dmac; 58 int err = 0; 59 60 flow_rule_match_eth_addrs(st->frule, &match); 61 62 if (!is_zero_ether_addr(match.mask->src)) { 63 vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN); 64 vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN); 65 err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac); 66 if (err) 67 goto out; 68 } 69 70 if (!is_zero_ether_addr(match.mask->dst)) { 71 vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN); 72 vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN); 73 err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac); 74 if (err) 75 goto out; 76 } 77 78 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS); 79 80 return err; 81 82 out: 83 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error"); 84 return err; 85 } 86 87 static int 88 sparx5_tc_flower_handler_ipv4_usage(struct sparx5_tc_flower_parse_usage *st) 89 { 90 int err = 0; 91 92 if (st->l3_proto == ETH_P_IP) { 93 struct flow_match_ipv4_addrs mt; 94 95 flow_rule_match_ipv4_addrs(st->frule, &mt); 96 if (mt.mask->src) { 97 err = vcap_rule_add_key_u32(st->vrule, 98 VCAP_KF_L3_IP4_SIP, 99 be32_to_cpu(mt.key->src), 100 be32_to_cpu(mt.mask->src)); 101 if (err) 102 goto out; 103 } 104 if (mt.mask->dst) { 105 err = vcap_rule_add_key_u32(st->vrule, 106 VCAP_KF_L3_IP4_DIP, 107 be32_to_cpu(mt.key->dst), 108 be32_to_cpu(mt.mask->dst)); 109 if (err) 110 goto out; 111 } 112 } 113 114 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS); 115 116 return err; 117 118 out: 119 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error"); 120 return err; 121 } 122 123 static int 124 sparx5_tc_flower_handler_ipv6_usage(struct sparx5_tc_flower_parse_usage *st) 125 { 126 int err = 0; 127 128 if (st->l3_proto == ETH_P_IPV6) { 129 struct flow_match_ipv6_addrs mt; 130 struct vcap_u128_key sip; 131 struct vcap_u128_key dip; 132 133 flow_rule_match_ipv6_addrs(st->frule, &mt); 134 /* Check if address masks are non-zero */ 135 if (!ipv6_addr_any(&mt.mask->src)) { 136 vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16); 137 vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16); 138 err = vcap_rule_add_key_u128(st->vrule, 139 VCAP_KF_L3_IP6_SIP, &sip); 140 if (err) 141 goto out; 142 } 143 if (!ipv6_addr_any(&mt.mask->dst)) { 144 vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16); 145 vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16); 146 err = vcap_rule_add_key_u128(st->vrule, 147 VCAP_KF_L3_IP6_DIP, &dip); 148 if (err) 149 goto out; 150 } 151 } 152 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS); 153 return err; 154 out: 155 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error"); 156 return err; 157 } 158 159 static int 160 sparx5_tc_flower_handler_control_usage(struct sparx5_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 if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) { 170 if (mt.key->flags & FLOW_DIS_FIRST_FRAG) { 171 value = 1; /* initial fragment */ 172 mask = 0x3; 173 } else { 174 if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { 175 value = 3; /* follow up fragment */ 176 mask = 0x3; 177 } else { 178 value = 0; /* no fragment */ 179 mask = 0x3; 180 } 181 } 182 } else { 183 if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { 184 value = 3; /* follow up fragment */ 185 mask = 0x3; 186 } else { 187 value = 0; /* no fragment */ 188 mask = 0x3; 189 } 190 } 191 192 err = vcap_rule_add_key_u32(st->vrule, 193 VCAP_KF_L3_FRAGMENT_TYPE, 194 value, mask); 195 if (err) 196 goto out; 197 } 198 199 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL); 200 201 return err; 202 203 out: 204 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error"); 205 return err; 206 } 207 208 static int 209 sparx5_tc_flower_handler_portnum_usage(struct sparx5_tc_flower_parse_usage *st) 210 { 211 struct flow_match_ports mt; 212 u16 value, mask; 213 int err = 0; 214 215 flow_rule_match_ports(st->frule, &mt); 216 217 if (mt.mask->src) { 218 value = be16_to_cpu(mt.key->src); 219 mask = be16_to_cpu(mt.mask->src); 220 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value, 221 mask); 222 if (err) 223 goto out; 224 } 225 226 if (mt.mask->dst) { 227 value = be16_to_cpu(mt.key->dst); 228 mask = be16_to_cpu(mt.mask->dst); 229 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value, 230 mask); 231 if (err) 232 goto out; 233 } 234 235 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_PORTS); 236 237 return err; 238 239 out: 240 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error"); 241 return err; 242 } 243 244 static int 245 sparx5_tc_flower_handler_basic_usage(struct sparx5_tc_flower_parse_usage *st) 246 { 247 struct flow_match_basic mt; 248 int err = 0; 249 250 flow_rule_match_basic(st->frule, &mt); 251 252 if (mt.mask->n_proto) { 253 st->l3_proto = be16_to_cpu(mt.key->n_proto); 254 if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) { 255 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE, 256 st->l3_proto, ~0); 257 if (err) 258 goto out; 259 } else if (st->l3_proto == ETH_P_IP) { 260 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS, 261 VCAP_BIT_1); 262 if (err) 263 goto out; 264 } else if (st->l3_proto == ETH_P_IPV6) { 265 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS, 266 VCAP_BIT_0); 267 if (err) 268 goto out; 269 if (st->admin->vtype == VCAP_TYPE_IS0) { 270 err = vcap_rule_add_key_bit(st->vrule, 271 VCAP_KF_IP_SNAP_IS, 272 VCAP_BIT_1); 273 if (err) 274 goto out; 275 } 276 277 } 278 } 279 280 if (mt.mask->ip_proto) { 281 st->l4_proto = mt.key->ip_proto; 282 if (st->l4_proto == IPPROTO_TCP) { 283 err = vcap_rule_add_key_bit(st->vrule, 284 VCAP_KF_TCP_IS, 285 VCAP_BIT_1); 286 if (err) 287 goto out; 288 } else if (st->l4_proto == IPPROTO_UDP) { 289 err = vcap_rule_add_key_bit(st->vrule, 290 VCAP_KF_TCP_IS, 291 VCAP_BIT_0); 292 if (err) 293 goto out; 294 if (st->admin->vtype == VCAP_TYPE_IS0) { 295 err = vcap_rule_add_key_bit(st->vrule, 296 VCAP_KF_TCP_UDP_IS, 297 VCAP_BIT_1); 298 if (err) 299 goto out; 300 } 301 } else { 302 err = vcap_rule_add_key_u32(st->vrule, 303 VCAP_KF_L3_IP_PROTO, 304 st->l4_proto, ~0); 305 if (err) 306 goto out; 307 } 308 } 309 310 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_BASIC); 311 312 return err; 313 314 out: 315 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error"); 316 return err; 317 } 318 319 static int 320 sparx5_tc_flower_handler_cvlan_usage(struct sparx5_tc_flower_parse_usage *st) 321 { 322 enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0; 323 enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0; 324 struct flow_match_vlan mt; 325 u16 tpid; 326 int err; 327 328 if (st->admin->vtype != VCAP_TYPE_IS0) 329 return -EINVAL; 330 331 flow_rule_match_cvlan(st->frule, &mt); 332 333 tpid = be16_to_cpu(mt.key->vlan_tpid); 334 335 if (tpid == ETH_P_8021Q) { 336 vid_key = VCAP_KF_8021Q_VID1; 337 pcp_key = VCAP_KF_8021Q_PCP1; 338 } 339 340 if (mt.mask->vlan_id) { 341 err = vcap_rule_add_key_u32(st->vrule, vid_key, 342 mt.key->vlan_id, 343 mt.mask->vlan_id); 344 if (err) 345 goto out; 346 } 347 348 if (mt.mask->vlan_priority) { 349 err = vcap_rule_add_key_u32(st->vrule, pcp_key, 350 mt.key->vlan_priority, 351 mt.mask->vlan_priority); 352 if (err) 353 goto out; 354 } 355 356 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN); 357 358 return 0; 359 out: 360 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error"); 361 return err; 362 } 363 364 static int 365 sparx5_tc_flower_handler_vlan_usage(struct sparx5_tc_flower_parse_usage *st) 366 { 367 enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS; 368 enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS; 369 struct flow_match_vlan mt; 370 int err; 371 372 flow_rule_match_vlan(st->frule, &mt); 373 374 if (st->admin->vtype == VCAP_TYPE_IS0) { 375 vid_key = VCAP_KF_8021Q_VID0; 376 pcp_key = VCAP_KF_8021Q_PCP0; 377 } 378 379 if (mt.mask->vlan_id) { 380 err = vcap_rule_add_key_u32(st->vrule, vid_key, 381 mt.key->vlan_id, 382 mt.mask->vlan_id); 383 if (err) 384 goto out; 385 } 386 387 if (mt.mask->vlan_priority) { 388 err = vcap_rule_add_key_u32(st->vrule, pcp_key, 389 mt.key->vlan_priority, 390 mt.mask->vlan_priority); 391 if (err) 392 goto out; 393 } 394 395 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_VLAN); 396 397 return 0; 398 out: 399 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error"); 400 return err; 401 } 402 403 static int 404 sparx5_tc_flower_handler_tcp_usage(struct sparx5_tc_flower_parse_usage *st) 405 { 406 struct flow_match_tcp mt; 407 u16 tcp_flags_mask; 408 u16 tcp_flags_key; 409 enum vcap_bit val; 410 int err = 0; 411 412 flow_rule_match_tcp(st->frule, &mt); 413 tcp_flags_key = be16_to_cpu(mt.key->flags); 414 tcp_flags_mask = be16_to_cpu(mt.mask->flags); 415 416 if (tcp_flags_mask & TCPHDR_FIN) { 417 val = VCAP_BIT_0; 418 if (tcp_flags_key & TCPHDR_FIN) 419 val = VCAP_BIT_1; 420 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val); 421 if (err) 422 goto out; 423 } 424 425 if (tcp_flags_mask & TCPHDR_SYN) { 426 val = VCAP_BIT_0; 427 if (tcp_flags_key & TCPHDR_SYN) 428 val = VCAP_BIT_1; 429 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val); 430 if (err) 431 goto out; 432 } 433 434 if (tcp_flags_mask & TCPHDR_RST) { 435 val = VCAP_BIT_0; 436 if (tcp_flags_key & TCPHDR_RST) 437 val = VCAP_BIT_1; 438 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val); 439 if (err) 440 goto out; 441 } 442 443 if (tcp_flags_mask & TCPHDR_PSH) { 444 val = VCAP_BIT_0; 445 if (tcp_flags_key & TCPHDR_PSH) 446 val = VCAP_BIT_1; 447 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val); 448 if (err) 449 goto out; 450 } 451 452 if (tcp_flags_mask & TCPHDR_ACK) { 453 val = VCAP_BIT_0; 454 if (tcp_flags_key & TCPHDR_ACK) 455 val = VCAP_BIT_1; 456 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val); 457 if (err) 458 goto out; 459 } 460 461 if (tcp_flags_mask & TCPHDR_URG) { 462 val = VCAP_BIT_0; 463 if (tcp_flags_key & TCPHDR_URG) 464 val = VCAP_BIT_1; 465 err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val); 466 if (err) 467 goto out; 468 } 469 470 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP); 471 472 return err; 473 474 out: 475 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error"); 476 return err; 477 } 478 479 static int 480 sparx5_tc_flower_handler_arp_usage(struct sparx5_tc_flower_parse_usage *st) 481 { 482 struct flow_match_arp mt; 483 u16 value, mask; 484 u32 ipval, ipmsk; 485 int err; 486 487 flow_rule_match_arp(st->frule, &mt); 488 489 if (mt.mask->op) { 490 mask = 0x3; 491 if (st->l3_proto == ETH_P_ARP) { 492 value = mt.key->op == TC_ARP_OP_REQUEST ? 493 SPX5_IS2_ARP_REQUEST : 494 SPX5_IS2_ARP_REPLY; 495 } else { /* RARP */ 496 value = mt.key->op == TC_ARP_OP_REQUEST ? 497 SPX5_IS2_RARP_REQUEST : 498 SPX5_IS2_RARP_REPLY; 499 } 500 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE, 501 value, mask); 502 if (err) 503 goto out; 504 } 505 506 /* The IS2 ARP keyset does not support ARP hardware addresses */ 507 if (!is_zero_ether_addr(mt.mask->sha) || 508 !is_zero_ether_addr(mt.mask->tha)) { 509 err = -EINVAL; 510 goto out; 511 } 512 513 if (mt.mask->sip) { 514 ipval = be32_to_cpu((__force __be32)mt.key->sip); 515 ipmsk = be32_to_cpu((__force __be32)mt.mask->sip); 516 517 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP, 518 ipval, ipmsk); 519 if (err) 520 goto out; 521 } 522 523 if (mt.mask->tip) { 524 ipval = be32_to_cpu((__force __be32)mt.key->tip); 525 ipmsk = be32_to_cpu((__force __be32)mt.mask->tip); 526 527 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP, 528 ipval, ipmsk); 529 if (err) 530 goto out; 531 } 532 533 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_ARP); 534 535 return 0; 536 537 out: 538 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error"); 539 return err; 540 } 541 542 static int 543 sparx5_tc_flower_handler_ip_usage(struct sparx5_tc_flower_parse_usage *st) 544 { 545 struct flow_match_ip mt; 546 int err = 0; 547 548 flow_rule_match_ip(st->frule, &mt); 549 550 if (mt.mask->tos) { 551 err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS, 552 mt.key->tos, 553 mt.mask->tos); 554 if (err) 555 goto out; 556 } 557 558 st->used_keys |= BIT(FLOW_DISSECTOR_KEY_IP); 559 560 return err; 561 562 out: 563 NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error"); 564 return err; 565 } 566 567 static int (*sparx5_tc_flower_usage_handlers[])(struct sparx5_tc_flower_parse_usage *st) = { 568 [FLOW_DISSECTOR_KEY_ETH_ADDRS] = sparx5_tc_flower_handler_ethaddr_usage, 569 [FLOW_DISSECTOR_KEY_IPV4_ADDRS] = sparx5_tc_flower_handler_ipv4_usage, 570 [FLOW_DISSECTOR_KEY_IPV6_ADDRS] = sparx5_tc_flower_handler_ipv6_usage, 571 [FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage, 572 [FLOW_DISSECTOR_KEY_PORTS] = sparx5_tc_flower_handler_portnum_usage, 573 [FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage, 574 [FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage, 575 [FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage, 576 [FLOW_DISSECTOR_KEY_TCP] = sparx5_tc_flower_handler_tcp_usage, 577 [FLOW_DISSECTOR_KEY_ARP] = sparx5_tc_flower_handler_arp_usage, 578 [FLOW_DISSECTOR_KEY_IP] = sparx5_tc_flower_handler_ip_usage, 579 }; 580 581 static int sparx5_tc_use_dissectors(struct flow_cls_offload *fco, 582 struct vcap_admin *admin, 583 struct vcap_rule *vrule, 584 u16 *l3_proto) 585 { 586 struct sparx5_tc_flower_parse_usage state = { 587 .fco = fco, 588 .vrule = vrule, 589 .l3_proto = ETH_P_ALL, 590 .admin = admin, 591 }; 592 int idx, err = 0; 593 594 state.frule = flow_cls_offload_flow_rule(fco); 595 for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) { 596 if (!flow_rule_match_key(state.frule, idx)) 597 continue; 598 if (!sparx5_tc_flower_usage_handlers[idx]) 599 continue; 600 err = sparx5_tc_flower_usage_handlers[idx](&state); 601 if (err) 602 return err; 603 } 604 605 if (state.frule->match.dissector->used_keys ^ state.used_keys) { 606 NL_SET_ERR_MSG_MOD(fco->common.extack, 607 "Unsupported match item"); 608 return -ENOENT; 609 } 610 611 if (l3_proto) 612 *l3_proto = state.l3_proto; 613 return err; 614 } 615 616 static int sparx5_tc_flower_action_check(struct vcap_control *vctrl, 617 struct net_device *ndev, 618 struct flow_cls_offload *fco) 619 { 620 struct flow_rule *rule = flow_cls_offload_flow_rule(fco); 621 struct flow_action_entry *actent, *last_actent = NULL; 622 struct flow_action *act = &rule->action; 623 u64 action_mask = 0; 624 int idx; 625 626 if (!flow_action_has_entries(act)) { 627 NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions"); 628 return -EINVAL; 629 } 630 631 if (!flow_action_basic_hw_stats_check(act, fco->common.extack)) 632 return -EOPNOTSUPP; 633 634 flow_action_for_each(idx, actent, act) { 635 if (action_mask & BIT(actent->id)) { 636 NL_SET_ERR_MSG_MOD(fco->common.extack, 637 "More actions of the same type"); 638 return -EINVAL; 639 } 640 action_mask |= BIT(actent->id); 641 last_actent = actent; /* Save last action for later check */ 642 } 643 644 /* Check if last action is a goto 645 * The last chain/lookup does not need to have a goto action 646 */ 647 if (last_actent->id == FLOW_ACTION_GOTO) { 648 /* Check if the destination chain is in one of the VCAPs */ 649 if (!vcap_is_next_lookup(vctrl, fco->common.chain_index, 650 last_actent->chain_index)) { 651 NL_SET_ERR_MSG_MOD(fco->common.extack, 652 "Invalid goto chain"); 653 return -EINVAL; 654 } 655 } else if (!vcap_is_last_chain(vctrl, fco->common.chain_index)) { 656 NL_SET_ERR_MSG_MOD(fco->common.extack, 657 "Last action must be 'goto'"); 658 return -EINVAL; 659 } 660 661 /* Catch unsupported combinations of actions */ 662 if (action_mask & BIT(FLOW_ACTION_TRAP) && 663 action_mask & BIT(FLOW_ACTION_ACCEPT)) { 664 NL_SET_ERR_MSG_MOD(fco->common.extack, 665 "Cannot combine pass and trap action"); 666 return -EOPNOTSUPP; 667 } 668 669 return 0; 670 } 671 672 /* Add a rule counter action */ 673 static int sparx5_tc_add_rule_counter(struct vcap_admin *admin, 674 struct vcap_rule *vrule) 675 { 676 int err; 677 678 if (admin->vtype == VCAP_TYPE_IS2) { 679 err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID, 680 vrule->id); 681 if (err) 682 return err; 683 vcap_rule_set_counter_id(vrule, vrule->id); 684 } 685 686 return 0; 687 } 688 689 /* Collect all port keysets and apply the first of them, possibly wildcarded */ 690 static int sparx5_tc_select_protocol_keyset(struct net_device *ndev, 691 struct vcap_rule *vrule, 692 struct vcap_admin *admin, 693 u16 l3_proto, 694 struct sparx5_multiple_rules *multi) 695 { 696 struct sparx5_port *port = netdev_priv(ndev); 697 struct vcap_keyset_list portkeysetlist = {}; 698 enum vcap_keyfield_set portkeysets[10] = {}; 699 struct vcap_keyset_list matches = {}; 700 enum vcap_keyfield_set keysets[10]; 701 int idx, jdx, err = 0, count = 0; 702 struct sparx5_wildcard_rule *mru; 703 const struct vcap_set *kinfo; 704 struct vcap_control *vctrl; 705 706 vctrl = port->sparx5->vcap_ctrl; 707 708 /* Find the keysets that the rule can use */ 709 matches.keysets = keysets; 710 matches.max = ARRAY_SIZE(keysets); 711 if (vcap_rule_find_keysets(vrule, &matches) == 0) 712 return -EINVAL; 713 714 /* Find the keysets that the port configuration supports */ 715 portkeysetlist.max = ARRAY_SIZE(portkeysets); 716 portkeysetlist.keysets = portkeysets; 717 err = sparx5_vcap_get_port_keyset(ndev, 718 admin, vrule->vcap_chain_id, 719 l3_proto, 720 &portkeysetlist); 721 if (err) 722 return err; 723 724 /* Find the intersection of the two sets of keyset */ 725 for (idx = 0; idx < portkeysetlist.cnt; ++idx) { 726 kinfo = vcap_keyfieldset(vctrl, admin->vtype, 727 portkeysetlist.keysets[idx]); 728 if (!kinfo) 729 continue; 730 731 /* Find a port keyset that matches the required keys 732 * If there are multiple keysets then compose a type id mask 733 */ 734 for (jdx = 0; jdx < matches.cnt; ++jdx) { 735 if (portkeysetlist.keysets[idx] != matches.keysets[jdx]) 736 continue; 737 738 mru = &multi->rule[kinfo->sw_per_item]; 739 if (!mru->selected) { 740 mru->selected = true; 741 mru->keyset = portkeysetlist.keysets[idx]; 742 mru->value = kinfo->type_id; 743 } 744 mru->value &= kinfo->type_id; 745 mru->mask |= kinfo->type_id; 746 ++count; 747 } 748 } 749 if (count == 0) 750 return -EPROTO; 751 752 if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt) 753 return -ENOENT; 754 755 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 756 mru = &multi->rule[idx]; 757 if (!mru->selected) 758 continue; 759 760 /* Align the mask to the combined value */ 761 mru->mask ^= mru->value; 762 } 763 764 /* Set the chosen keyset on the rule and set a wildcarded type if there 765 * are more than one keyset 766 */ 767 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 768 mru = &multi->rule[idx]; 769 if (!mru->selected) 770 continue; 771 772 vcap_set_rule_set_keyset(vrule, mru->keyset); 773 if (count > 1) 774 /* Some keysets do not have a type field */ 775 vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, 776 mru->value, 777 ~mru->mask); 778 mru->selected = false; /* mark as done */ 779 break; /* Stop here and add more rules later */ 780 } 781 return err; 782 } 783 784 static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl, 785 struct flow_cls_offload *fco, 786 struct vcap_rule *erule, 787 struct vcap_admin *admin, 788 struct sparx5_wildcard_rule *rule) 789 { 790 enum vcap_key_field keylist[] = { 791 VCAP_KF_IF_IGR_PORT_MASK, 792 VCAP_KF_IF_IGR_PORT_MASK_SEL, 793 VCAP_KF_IF_IGR_PORT_MASK_RNG, 794 VCAP_KF_LOOKUP_FIRST_IS, 795 VCAP_KF_TYPE, 796 }; 797 struct vcap_rule *vrule; 798 int err; 799 800 /* Add an extra rule with a special user and the new keyset */ 801 erule->user = VCAP_USER_TC_EXTRA; 802 vrule = vcap_copy_rule(erule); 803 if (IS_ERR(vrule)) 804 return PTR_ERR(vrule); 805 806 /* Link the new rule to the existing rule with the cookie */ 807 vrule->cookie = erule->cookie; 808 vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true); 809 err = vcap_set_rule_set_keyset(vrule, rule->keyset); 810 if (err) { 811 pr_err("%s:%d: could not set keyset %s in rule: %u\n", 812 __func__, __LINE__, 813 vcap_keyset_name(vctrl, rule->keyset), 814 vrule->id); 815 goto out; 816 } 817 818 /* Some keysets do not have a type field, so ignore return value */ 819 vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask); 820 821 err = vcap_set_rule_set_actionset(vrule, erule->actionset); 822 if (err) 823 goto out; 824 825 err = sparx5_tc_add_rule_counter(admin, vrule); 826 if (err) 827 goto out; 828 829 err = vcap_val_rule(vrule, ETH_P_ALL); 830 if (err) { 831 pr_err("%s:%d: could not validate rule: %u\n", 832 __func__, __LINE__, vrule->id); 833 vcap_set_tc_exterr(fco, vrule); 834 goto out; 835 } 836 err = vcap_add_rule(vrule); 837 if (err) { 838 pr_err("%s:%d: could not add rule: %u\n", 839 __func__, __LINE__, vrule->id); 840 goto out; 841 } 842 out: 843 vcap_free_rule(vrule); 844 return err; 845 } 846 847 static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl, 848 struct flow_cls_offload *fco, 849 struct vcap_rule *erule, 850 struct vcap_admin *admin, 851 struct sparx5_multiple_rules *multi) 852 { 853 int idx, err = 0; 854 855 for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) { 856 if (!multi->rule[idx].selected) 857 continue; 858 859 err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin, 860 &multi->rule[idx]); 861 if (err) 862 break; 863 } 864 return err; 865 } 866 867 /* Add the actionset that is the default for the VCAP type */ 868 static int sparx5_tc_set_actionset(struct vcap_admin *admin, 869 struct vcap_rule *vrule) 870 { 871 enum vcap_actionfield_set aset; 872 int err = 0; 873 874 switch (admin->vtype) { 875 case VCAP_TYPE_IS0: 876 aset = VCAP_AFS_CLASSIFICATION; 877 break; 878 case VCAP_TYPE_IS2: 879 aset = VCAP_AFS_BASE_TYPE; 880 break; 881 default: 882 return -EINVAL; 883 } 884 /* Do not overwrite any current actionset */ 885 if (vrule->actionset == VCAP_AFS_NO_VALUE) 886 err = vcap_set_rule_set_actionset(vrule, aset); 887 return err; 888 } 889 890 /* Add the VCAP key to match on for a rule target value */ 891 static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin, 892 struct vcap_rule *vrule, 893 int target_cid) 894 { 895 int link_val = target_cid % VCAP_CID_LOOKUP_SIZE; 896 int err; 897 898 if (!link_val) 899 return 0; 900 901 switch (admin->vtype) { 902 case VCAP_TYPE_IS0: 903 /* Add NXT_IDX key for chaining rules between IS0 instances */ 904 err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL, 905 1, /* enable */ 906 ~0); 907 if (err) 908 return err; 909 return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX, 910 link_val, /* target */ 911 ~0); 912 case VCAP_TYPE_IS2: 913 /* Add PAG key for chaining rules from IS0 */ 914 return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG, 915 link_val, /* target */ 916 ~0); 917 default: 918 break; 919 } 920 return 0; 921 } 922 923 /* Add the VCAP action that adds a target value to a rule */ 924 static int sparx5_tc_add_rule_link(struct vcap_control *vctrl, 925 struct vcap_admin *admin, 926 struct vcap_rule *vrule, 927 int from_cid, int to_cid) 928 { 929 struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid); 930 int diff, err = 0; 931 932 diff = vcap_chain_offset(vctrl, from_cid, to_cid); 933 if (!(to_admin && diff > 0)) { 934 pr_err("%s:%d: unsupported chain direction: %d\n", 935 __func__, __LINE__, to_cid); 936 return -EINVAL; 937 } 938 if (admin->vtype == VCAP_TYPE_IS0 && 939 to_admin->vtype == VCAP_TYPE_IS0) { 940 /* Between IS0 instances the G_IDX value is used */ 941 err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff); 942 if (err) 943 goto out; 944 err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL, 945 1); /* Replace */ 946 if (err) 947 goto out; 948 } else if (admin->vtype == VCAP_TYPE_IS0 && 949 to_admin->vtype == VCAP_TYPE_IS2) { 950 /* Between IS0 and IS2 the PAG value is used */ 951 err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff); 952 if (err) 953 goto out; 954 err = vcap_rule_add_action_u32(vrule, 955 VCAP_AF_PAG_OVERRIDE_MASK, 956 0xff); 957 if (err) 958 goto out; 959 } else { 960 pr_err("%s:%d: unsupported chain destination: %d\n", 961 __func__, __LINE__, to_cid); 962 err = -EOPNOTSUPP; 963 } 964 out: 965 return err; 966 } 967 968 static int sparx5_tc_flower_replace(struct net_device *ndev, 969 struct flow_cls_offload *fco, 970 struct vcap_admin *admin) 971 { 972 struct sparx5_port *port = netdev_priv(ndev); 973 struct sparx5_multiple_rules multi = {}; 974 struct flow_action_entry *act; 975 struct vcap_control *vctrl; 976 struct flow_rule *frule; 977 struct vcap_rule *vrule; 978 u16 l3_proto; 979 int err, idx; 980 981 vctrl = port->sparx5->vcap_ctrl; 982 983 err = sparx5_tc_flower_action_check(vctrl, ndev, fco); 984 if (err) 985 return err; 986 987 vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC, 988 fco->common.prio, 0); 989 if (IS_ERR(vrule)) 990 return PTR_ERR(vrule); 991 992 vrule->cookie = fco->cookie; 993 994 l3_proto = ETH_P_ALL; 995 err = sparx5_tc_use_dissectors(fco, admin, vrule, &l3_proto); 996 if (err) 997 goto out; 998 999 err = sparx5_tc_add_rule_counter(admin, vrule); 1000 if (err) 1001 goto out; 1002 1003 err = sparx5_tc_add_rule_link_target(admin, vrule, 1004 fco->common.chain_index); 1005 if (err) 1006 goto out; 1007 1008 frule = flow_cls_offload_flow_rule(fco); 1009 flow_action_for_each(idx, act, &frule->action) { 1010 switch (act->id) { 1011 case FLOW_ACTION_TRAP: 1012 if (admin->vtype != VCAP_TYPE_IS2) { 1013 NL_SET_ERR_MSG_MOD(fco->common.extack, 1014 "Trap action not supported in this VCAP"); 1015 err = -EOPNOTSUPP; 1016 goto out; 1017 } 1018 err = vcap_rule_add_action_bit(vrule, 1019 VCAP_AF_CPU_COPY_ENA, 1020 VCAP_BIT_1); 1021 if (err) 1022 goto out; 1023 err = vcap_rule_add_action_u32(vrule, 1024 VCAP_AF_CPU_QUEUE_NUM, 0); 1025 if (err) 1026 goto out; 1027 err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE, 1028 SPX5_PMM_REPLACE_ALL); 1029 if (err) 1030 goto out; 1031 break; 1032 case FLOW_ACTION_ACCEPT: 1033 err = sparx5_tc_set_actionset(admin, vrule); 1034 if (err) 1035 goto out; 1036 break; 1037 case FLOW_ACTION_GOTO: 1038 err = sparx5_tc_set_actionset(admin, vrule); 1039 if (err) 1040 goto out; 1041 sparx5_tc_add_rule_link(vctrl, admin, vrule, 1042 fco->common.chain_index, 1043 act->chain_index); 1044 break; 1045 default: 1046 NL_SET_ERR_MSG_MOD(fco->common.extack, 1047 "Unsupported TC action"); 1048 err = -EOPNOTSUPP; 1049 goto out; 1050 } 1051 } 1052 1053 err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin, l3_proto, 1054 &multi); 1055 if (err) { 1056 NL_SET_ERR_MSG_MOD(fco->common.extack, 1057 "No matching port keyset for filter protocol and keys"); 1058 goto out; 1059 } 1060 1061 /* provide the l3 protocol to guide the keyset selection */ 1062 err = vcap_val_rule(vrule, l3_proto); 1063 if (err) { 1064 vcap_set_tc_exterr(fco, vrule); 1065 goto out; 1066 } 1067 err = vcap_add_rule(vrule); 1068 if (err) 1069 NL_SET_ERR_MSG_MOD(fco->common.extack, 1070 "Could not add the filter"); 1071 1072 if (l3_proto == ETH_P_ALL) 1073 err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin, 1074 &multi); 1075 1076 out: 1077 vcap_free_rule(vrule); 1078 return err; 1079 } 1080 1081 static int sparx5_tc_flower_destroy(struct net_device *ndev, 1082 struct flow_cls_offload *fco, 1083 struct vcap_admin *admin) 1084 { 1085 struct sparx5_port *port = netdev_priv(ndev); 1086 struct vcap_control *vctrl; 1087 int err = -ENOENT, rule_id; 1088 1089 vctrl = port->sparx5->vcap_ctrl; 1090 while (true) { 1091 rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie); 1092 if (rule_id <= 0) 1093 break; 1094 err = vcap_del_rule(vctrl, ndev, rule_id); 1095 if (err) { 1096 pr_err("%s:%d: could not delete rule %d\n", 1097 __func__, __LINE__, rule_id); 1098 break; 1099 } 1100 } 1101 return err; 1102 } 1103 1104 static int sparx5_tc_flower_stats(struct net_device *ndev, 1105 struct flow_cls_offload *fco, 1106 struct vcap_admin *admin) 1107 { 1108 struct sparx5_port *port = netdev_priv(ndev); 1109 struct vcap_counter ctr = {}; 1110 struct vcap_control *vctrl; 1111 ulong lastused = 0; 1112 int err; 1113 1114 vctrl = port->sparx5->vcap_ctrl; 1115 err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie); 1116 if (err) 1117 return err; 1118 flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused, 1119 FLOW_ACTION_HW_STATS_IMMEDIATE); 1120 return err; 1121 } 1122 1123 int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco, 1124 bool ingress) 1125 { 1126 struct sparx5_port *port = netdev_priv(ndev); 1127 struct vcap_control *vctrl; 1128 struct vcap_admin *admin; 1129 int err = -EINVAL; 1130 1131 /* Get vcap instance from the chain id */ 1132 vctrl = port->sparx5->vcap_ctrl; 1133 admin = vcap_find_admin(vctrl, fco->common.chain_index); 1134 if (!admin) { 1135 NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain"); 1136 return err; 1137 } 1138 1139 switch (fco->command) { 1140 case FLOW_CLS_REPLACE: 1141 return sparx5_tc_flower_replace(ndev, fco, admin); 1142 case FLOW_CLS_DESTROY: 1143 return sparx5_tc_flower_destroy(ndev, fco, admin); 1144 case FLOW_CLS_STATS: 1145 return sparx5_tc_flower_stats(ndev, fco, admin); 1146 default: 1147 return -EOPNOTSUPP; 1148 } 1149 } 1150