mae.c (cecdd52a3dd312564f81a39df08378b7b39a2654) | mae.c (b9d5c9b7d8a47ca4af5e32f576265c388a467af5) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/**************************************************************************** 3 * Driver for Solarflare network controllers and boards 4 * Copyright 2019 Solarflare Communications Inc. 5 * Copyright 2020-2022 Xilinx Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published --- 240 unchanged lines hidden (view full) --- 249 u8 *field_support) 250{ 251 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(MAE_NUM_FIELDS)); 252 MCDI_DECLARE_STRUCT_PTR(caps); 253 unsigned int count; 254 size_t outlen; 255 int rc, i; 256 | 1// SPDX-License-Identifier: GPL-2.0-only 2/**************************************************************************** 3 * Driver for Solarflare network controllers and boards 4 * Copyright 2019 Solarflare Communications Inc. 5 * Copyright 2020-2022 Xilinx Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published --- 240 unchanged lines hidden (view full) --- 249 u8 *field_support) 250{ 251 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(MAE_NUM_FIELDS)); 252 MCDI_DECLARE_STRUCT_PTR(caps); 253 unsigned int count; 254 size_t outlen; 255 int rc, i; 256 |
257 /* AR and OR caps MCDIs have identical layout, so we are using the 258 * same code for both. 259 */ 260 BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(MAE_NUM_FIELDS) < 261 MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(MAE_NUM_FIELDS)); |
|
257 BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_IN_LEN); | 262 BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_IN_LEN); |
263 BUILD_BUG_ON(MC_CMD_MAE_GET_OR_CAPS_IN_LEN); |
|
258 259 rc = efx_mcdi_rpc(efx, cmd, NULL, 0, outbuf, sizeof(outbuf), &outlen); 260 if (rc) 261 return rc; | 264 265 rc = efx_mcdi_rpc(efx, cmd, NULL, 0, outbuf, sizeof(outbuf), &outlen); 266 if (rc) 267 return rc; |
268 BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_OUT_COUNT_OFST != 269 MC_CMD_MAE_GET_OR_CAPS_OUT_COUNT_OFST); |
|
262 count = MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_COUNT); 263 memset(field_support, MAE_FIELD_UNSUPPORTED, MAE_NUM_FIELDS); | 270 count = MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_COUNT); 271 memset(field_support, MAE_FIELD_UNSUPPORTED, MAE_NUM_FIELDS); |
272 BUILD_BUG_ON(MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST != 273 MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_OFST); |
|
264 caps = _MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_FIELD_FLAGS); 265 /* We're only interested in the support status enum, not any other 266 * flags, so just extract that from each entry. 267 */ 268 for (i = 0; i < count; i++) 269 if (i * sizeof(*outbuf) + MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST < outlen) 270 field_support[i] = EFX_DWORD_FIELD(caps[i], MAE_FIELD_FLAGS_SUPPORT_STATUS); 271 return 0; 272} 273 274int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps) 275{ 276 int rc; 277 278 rc = efx_mae_get_basic_caps(efx, caps); 279 if (rc) 280 return rc; | 274 caps = _MCDI_DWORD(outbuf, MAE_GET_AR_CAPS_OUT_FIELD_FLAGS); 275 /* We're only interested in the support status enum, not any other 276 * flags, so just extract that from each entry. 277 */ 278 for (i = 0; i < count; i++) 279 if (i * sizeof(*outbuf) + MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST < outlen) 280 field_support[i] = EFX_DWORD_FIELD(caps[i], MAE_FIELD_FLAGS_SUPPORT_STATUS); 281 return 0; 282} 283 284int efx_mae_get_caps(struct efx_nic *efx, struct mae_caps *caps) 285{ 286 int rc; 287 288 rc = efx_mae_get_basic_caps(efx, caps); 289 if (rc) 290 return rc; |
281 return efx_mae_get_rule_fields(efx, MC_CMD_MAE_GET_AR_CAPS, 282 caps->action_rule_fields); | 291 rc = efx_mae_get_rule_fields(efx, MC_CMD_MAE_GET_AR_CAPS, 292 caps->action_rule_fields); 293 if (rc) 294 return rc; 295 return efx_mae_get_rule_fields(efx, MC_CMD_MAE_GET_OR_CAPS, 296 caps->outer_rule_fields); |
283} 284 285/* Bit twiddling: 286 * Prefix: 1...110...0 287 * ~: 0...001...1 288 * + 1: 0...010...0 is power of two 289 * so (~x) & ((~x) + 1) == 0. Converse holds also. 290 */ --- 136 unchanged lines hidden (view full) --- 427#endif 428 CHECK(L4_SPORT, l4_sport) || 429 CHECK(L4_DPORT, l4_dport) || 430 CHECK(TCP_FLAGS, tcp_flags) || 431 CHECK_BIT(IS_IP_FRAG, ip_frag) || 432 CHECK_BIT(IP_FIRST_FRAG, ip_firstfrag) || 433 CHECK(RECIRC_ID, recirc_id)) 434 return rc; | 297} 298 299/* Bit twiddling: 300 * Prefix: 1...110...0 301 * ~: 0...001...1 302 * + 1: 0...010...0 is power of two 303 * so (~x) & ((~x) + 1) == 0. Converse holds also. 304 */ --- 136 unchanged lines hidden (view full) --- 441#endif 442 CHECK(L4_SPORT, l4_sport) || 443 CHECK(L4_DPORT, l4_dport) || 444 CHECK(TCP_FLAGS, tcp_flags) || 445 CHECK_BIT(IS_IP_FRAG, ip_frag) || 446 CHECK_BIT(IP_FIRST_FRAG, ip_firstfrag) || 447 CHECK(RECIRC_ID, recirc_id)) 448 return rc; |
449 /* Matches on outer fields are done in a separate hardware table, 450 * the Outer Rule table. Thus the Action Rule merely does an 451 * exact match on Outer Rule ID if any outer field matches are 452 * present. The exception is the VNI/VSID (enc_keyid), which is 453 * available to the Action Rule match iff the Outer Rule matched 454 * (and thus identified the encap protocol to use to extract it). 455 */ 456 if (efx_tc_match_is_encap(mask)) { 457 rc = efx_mae_match_check_cap_typ( 458 supported_fields[MAE_FIELD_OUTER_RULE_ID], 459 MASK_ONES); 460 if (rc) { 461 NL_SET_ERR_MSG_MOD(extack, "No support for encap rule ID matches"); 462 return rc; 463 } 464 if (CHECK(ENC_VNET_ID, enc_keyid)) 465 return rc; 466 } else if (mask->enc_keyid) { 467 NL_SET_ERR_MSG_MOD(extack, "Match on enc_keyid requires other encap fields"); 468 return -EINVAL; 469 } |
|
435 return 0; 436} 437#undef CHECK_BIT 438#undef CHECK 439 | 470 return 0; 471} 472#undef CHECK_BIT 473#undef CHECK 474 |
475#define CHECK(_mcdi) ({ \ 476 rc = efx_mae_match_check_cap_typ(supported_fields[MAE_FIELD_ ## _mcdi],\ 477 MASK_ONES); \ 478 if (rc) \ 479 NL_SET_ERR_MSG_FMT_MOD(extack, \ 480 "No support for field %s", #_mcdi); \ 481 rc; \ 482}) 483/* Checks that the fields needed for encap-rule matches are supported by the 484 * MAE. All the fields are exact-match. 485 */ 486int efx_mae_check_encap_match_caps(struct efx_nic *efx, bool ipv6, 487 struct netlink_ext_ack *extack) 488{ 489 u8 *supported_fields = efx->tc->caps->outer_rule_fields; 490 int rc; 491 492 if (CHECK(ENC_ETHER_TYPE)) 493 return rc; 494 if (ipv6) { 495 if (CHECK(ENC_SRC_IP6) || 496 CHECK(ENC_DST_IP6)) 497 return rc; 498 } else { 499 if (CHECK(ENC_SRC_IP4) || 500 CHECK(ENC_DST_IP4)) 501 return rc; 502 } 503 if (CHECK(ENC_L4_DPORT) || 504 CHECK(ENC_IP_PROTO)) 505 return rc; 506 return 0; 507} 508#undef CHECK 509 |
|
440int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt) 441{ 442 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(1)); 443 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN); 444 size_t outlen; 445 int rc; 446 447 if (!cnt) --- 229 unchanged lines hidden (view full) --- 677 678int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) 679{ 680 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); 681 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN); 682 size_t outlen; 683 int rc; 684 | 510int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt) 511{ 512 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(1)); 513 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN); 514 size_t outlen; 515 int rc; 516 517 if (!cnt) --- 229 unchanged lines hidden (view full) --- 747 748int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) 749{ 750 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); 751 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN); 752 size_t outlen; 753 int rc; 754 |
755 MCDI_POPULATE_DWORD_2(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, 756 MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push, 757 MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop); 758 |
|
685 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, 686 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 687 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, 688 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 689 if (act->count && !WARN_ON(!act->count->cnt)) 690 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 691 act->count->cnt->fw_id); 692 else 693 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 694 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL); 695 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, 696 MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL); | 759 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, 760 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 761 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, 762 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); 763 if (act->count && !WARN_ON(!act->count->cnt)) 764 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 765 act->count->cnt->fw_id); 766 else 767 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, 768 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL); 769 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, 770 MC_CMD_MAE_COUNTER_LIST_ALLOC_OUT_COUNTER_LIST_ID_NULL); |
771 if (act->vlan_push) { 772 MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE, 773 act->vlan_tci[0]); 774 MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE, 775 act->vlan_proto[0]); 776 } 777 if (act->vlan_push >= 2) { 778 MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE, 779 act->vlan_tci[1]); 780 MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, 781 act->vlan_proto[1]); 782 } |
|
697 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, 698 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); 699 if (act->deliver) 700 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER, 701 act->dest_mport); 702 BUILD_BUG_ON(MAE_MPORT_SELECTOR_NULL); 703 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_ALLOC, inbuf, sizeof(inbuf), 704 outbuf, sizeof(outbuf), &outlen); --- 215 unchanged lines hidden (view full) --- 920 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE, 921 match->value.l4_dport); 922 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK, 923 match->mask.l4_dport); 924 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE, 925 match->value.tcp_flags); 926 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK, 927 match->mask.tcp_flags); | 783 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, 784 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); 785 if (act->deliver) 786 MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER, 787 act->dest_mport); 788 BUILD_BUG_ON(MAE_MPORT_SELECTOR_NULL); 789 rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_SET_ALLOC, inbuf, sizeof(inbuf), 790 outbuf, sizeof(outbuf), &outlen); --- 215 unchanged lines hidden (view full) --- 1006 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE, 1007 match->value.l4_dport); 1008 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK, 1009 match->mask.l4_dport); 1010 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE, 1011 match->value.tcp_flags); 1012 MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK, 1013 match->mask.tcp_flags); |
1014 /* enc-keys are handled indirectly, through encap_match ID */ 1015 if (match->encap) { 1016 MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID, 1017 match->encap->fw_id); 1018 MCDI_STRUCT_SET_DWORD(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK, 1019 U32_MAX); 1020 /* enc_keyid (VNI/VSID) is not part of the encap_match */ 1021 MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE, 1022 match->value.enc_keyid); 1023 MCDI_STRUCT_SET_DWORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK, 1024 match->mask.enc_keyid); 1025 } else if (WARN_ON_ONCE(match->mask.enc_src_ip) || 1026 WARN_ON_ONCE(match->mask.enc_dst_ip) || 1027 WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_src_ip6)) || 1028 WARN_ON_ONCE(!ipv6_addr_any(&match->mask.enc_dst_ip6)) || 1029 WARN_ON_ONCE(match->mask.enc_ip_tos) || 1030 WARN_ON_ONCE(match->mask.enc_ip_ttl) || 1031 WARN_ON_ONCE(match->mask.enc_sport) || 1032 WARN_ON_ONCE(match->mask.enc_dport) || 1033 WARN_ON_ONCE(match->mask.enc_keyid)) { 1034 /* No enc-keys should appear in a rule without an encap_match */ 1035 return -EOPNOTSUPP; 1036 } |
|
928 return 0; 929} 930 931int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, 932 u32 prio, u32 acts_id, u32 *id) 933{ 934 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_INSERT_IN_LEN(MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN)); 935 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN); --- 88 unchanged lines hidden --- | 1037 return 0; 1038} 1039 1040int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, 1041 u32 prio, u32 acts_id, u32 *id) 1042{ 1043 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_INSERT_IN_LEN(MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN)); 1044 MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN); --- 88 unchanged lines hidden --- |