DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 00/34] net/sfc: support HW conntrack assistance
@ 2023-06-01 19:55 Ivan Malov
  2023-06-01 19:55 ` [PATCH 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
                   ` (36 more replies)
  0 siblings, 37 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

Denis Pryazhennikov (11):
  common/sfc_efx/base: update MCDI headers
  common/sfc_efx/base: detect MCDI Table Access API support
  common/sfc_efx/base: add API to list HW tables
  common/sfc_efx/base: add macro to get indexed QWORD field
  common/sfc_efx/base: add API to get HW table desc
  common/sfc_efx/base: add API to insert data to HW table
  common/sfc_efx/base: add API to delete entry from HW table
  net/sfc: add MCDI wrappers for BCAM tables
  net/sfc: add functions to manipulate MCDI table fields
  net/sfc: attach to HW table API
  net/sfc: add API to manage HW Conntrack table

Ivan Malov (23):
  net/sfc: make entry pointer optional in MAE resource helpers
  net/sfc: turn flow create/destroy methods into lock wrappers
  net/sfc: let driver-internal flows use VF representor action
  net/sfc: extend generic flow API to allow for internal flows
  net/sfc: switch driver-internal flows to use generic methods
  net/sfc: move MAE flow parsing method to MAE-specific source
  net/sfc: move MAE counter stream start to action set handler
  net/sfc: prepare MAE outer rules for action rule indirection
  net/sfc: turn MAE flow action rules into shareable resources
  common/sfc_efx/base: provide an API to clone MAE match specs
  common/sfc_efx/base: add API to read back MAE match criteria
  common/sfc_efx/base: match on conntrack mark in action rules
  common/sfc_efx/base: add API to request MAE conntrack lookup
  net/sfc: make use of conntrack assistance for transfer flows
  common/sfc_efx/base: support NAT edits in MAE
  net/sfc: add support for IPv4 NAT offload to MAE backend
  net/sfc: rename SW structures used by transfer flow counters
  net/sfc: rework MAE action rule counter representation in SW
  net/sfc: support indirect count action in transfer flows
  common/sfc_efx/base: rework MAE counter provisioning helpers
  net/sfc: indicate MAE counter type in use for transfer flows
  common/sfc_efx/base: support conntrack assistance counters
  net/sfc: use conntrack assistance counters in transfer flows

 doc/guides/nics/features/sfc.ini            |    5 +
 doc/guides/nics/sfc_efx.rst                 |   10 +
 drivers/common/sfc_efx/base/efx.h           |  198 +-
 drivers/common/sfc_efx/base/efx_impl.h      |    5 +-
 drivers/common/sfc_efx/base/efx_mae.c       |  383 ++-
 drivers/common/sfc_efx/base/efx_mcdi.h      |    4 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 drivers/common/sfc_efx/base/efx_table.c     |  506 ++++
 drivers/common/sfc_efx/base/hunt_nic.c      |    2 +
 drivers/common/sfc_efx/base/medford2_nic.c  |    2 +
 drivers/common/sfc_efx/base/medford_nic.c   |    2 +
 drivers/common/sfc_efx/base/meson.build     |    1 +
 drivers/common/sfc_efx/base/rhead_nic.c     |    9 +
 drivers/common/sfc_efx/base/siena_nic.c     |    2 +
 drivers/common/sfc_efx/version.map          |   14 +
 drivers/net/sfc/meson.build                 |    6 +-
 drivers/net/sfc/sfc.c                       |   27 +-
 drivers/net/sfc/sfc.h                       |    3 +
 drivers/net/sfc/sfc_flow.c                  |  233 +-
 drivers/net/sfc/sfc_flow.h                  |   45 +-
 drivers/net/sfc/sfc_mae.c                   | 1897 ++++++++++----
 drivers/net/sfc/sfc_mae.h                   |  131 +-
 drivers/net/sfc/sfc_mae_counter.c           |  146 +-
 drivers/net/sfc/sfc_mae_counter.h           |   16 +-
 drivers/net/sfc/sfc_mae_ct.c                |  201 ++
 drivers/net/sfc/sfc_mae_ct.h                |   68 +
 drivers/net/sfc/sfc_repr.c                  |   20 +-
 drivers/net/sfc/sfc_repr_proxy.c            |   53 +-
 drivers/net/sfc/sfc_repr_proxy.h            |    2 +-
 drivers/net/sfc/sfc_repr_proxy_api.h        |    3 +
 drivers/net/sfc/sfc_switch.c                |    7 +-
 drivers/net/sfc/sfc_switch.h                |   10 +
 drivers/net/sfc/sfc_tbl_meta.c              |   71 +
 drivers/net/sfc/sfc_tbl_meta.h              |   37 +
 drivers/net/sfc/sfc_tbl_meta_cache.c        |  253 ++
 drivers/net/sfc/sfc_tbl_meta_cache.h        |   25 +
 drivers/net/sfc/sfc_tbls.c                  |  200 ++
 drivers/net/sfc/sfc_tbls.h                  |  285 +++
 38 files changed, 6574 insertions(+), 865 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h
 create mode 100644 drivers/net/sfc/sfc_tbls.c
 create mode 100644 drivers/net/sfc/sfc_tbls.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 01/34] common/sfc_efx/base: update MCDI headers
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
                   ` (35 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Pickup new FW interface definitions.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 1 file changed, 2467 insertions(+), 90 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index d1d8093601..76bd1bf4d9 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -5,7 +5,10 @@
  */
 
 /*
- * This file is automatically generated. DO NOT EDIT IT.
+ * This file is automatically generated, but contains manual changes.
+ * - replaced the autogenerated license header with BSD-3-Clause;
+ * - used tabs for the indentation of MC_CMD_ERR_*.
+ *
  * To make changes, edit the .yml files in smartnic_registry under doc/mcdi/ and
  * rebuild this file with "make mcdi_headers_v5".
  */
@@ -81,19 +84,19 @@
  *               |                      \------- Error
  *               \------------------------------ Resync (always set)
  *
- * The client writes it's request into MC shared memory, and rings the
- * doorbell. Each request is completed by either by the MC writting
- * back into shared memory, or by writting out an event.
+ * The client writes its request into MC shared memory, and rings the
+ * doorbell. Each request is completed either by the MC writing
+ * back into shared memory, or by writing out an event.
  *
  * All MCDI commands support completion by shared memory response. Each
  * request may also contain additional data (accounted for by HEADER.LEN),
- * and some response's may also contain additional data (again, accounted
+ * and some responses may also contain additional data (again, accounted
  * for by HEADER.LEN).
  *
  * Some MCDI commands support completion by event, in which any associated
  * response data is included in the event.
  *
- * The protocol requires one response to be delivered for every request, a
+ * The protocol requires one response to be delivered for every request; a
  * request should not be sent unless the response for the previous request
  * has been received (either by polling shared memory, or by receiving
  * an event).
@@ -339,7 +342,7 @@
 /* enum: The requesting client is not a function */
 #define	MC_CMD_ERR_CLIENT_NOT_FN 0x100c
 /* enum: The requested operation might require the command to be passed between
- * MCs, and thetransport doesn't support that. Should only ever been seen over
+ * MCs, and the transport doesn't support that. Should only ever been seen over
  * the UART.
  */
 #define	MC_CMD_ERR_TRANSPORT_NOPROXY 0x100d
@@ -376,7 +379,7 @@
  * sub-variant switching.
  */
 #define	MC_CMD_ERR_FILTERS_PRESENT 0x1014
-/* enum: The clock whose frequency you've attempted to set set doesn't exist on
+/* enum: The clock whose frequency you've attempted to set doesn't exist on
  * this NIC
  */
 #define	MC_CMD_ERR_NO_CLOCK 0x1015
@@ -658,12 +661,624 @@
  * be allocated by different counter blocks, so e.g. AR counter 42 is different
  * from CT counter 42. Generation counts are also type-specific. This value is
  * also present in the header of streaming counter packets, in the IDENTIFIER
- * field (see packetiser packet format definitions).
+ * field (see packetiser packet format definitions). Also note that LACP
+ * counter IDs are not allocated individually, instead the counter IDs are
+ * directly tied to the LACP balance table indices. These in turn are allocated
+ * in large contiguous blocks as a LAG config. Calling MAE_COUNTER_ALLOC/FREE
+ * with an LACP counter type will return EPERM.
  */
 /* enum: Action Rule counters - can be referenced in AR response. */
 #define	MAE_COUNTER_TYPE_AR 0x0
 /* enum: Conntrack counters - can be referenced in CT response. */
 #define	MAE_COUNTER_TYPE_CT 0x1
+/* enum: Outer Rule counters - can be referenced in OR response. */
+#define	MAE_COUNTER_TYPE_OR 0x2
+/* enum: LACP counters - linked to LACP balance table entries. */
+#define	MAE_COUNTER_TYPE_LACP 0x3
+
+/* MAE_COUNTER_ID enum: ID of allocated counter or counter list. */
+/* enum: A counter ID that is guaranteed never to represent a real counter or
+ * counter list.
+ */
+#define	MAE_COUNTER_ID_NULL 0xffffffff
+
+/* TABLE_ID enum: Unique IDs for tables. The 32-bit ID values have been
+ * structured with bits [31:24] reserved (0), [23:16] indicating which major
+ * block the tables belongs to (0=VNIC TX, none currently; 1=MAE; 2=VNIC RX),
+ * [15:8] a unique ID within the block, and [7:0] reserved for future
+ * variations of the same table. (All of the tables currently defined within
+ * the streaming engines are listed here, but this does not imply that they are
+ * all supported - MC_CMD_TABLE_LIST returns the list of actually supported
+ * tables.) The DPU offload engines' enumerators follow a deliberate pattern:
+ * 0x01010000 + is_dpu_net * 0x10000 + is_wr_or_tx * 0x8000 + is_lite_pipe *
+ * 0x1000 + oe_engine_type * 0x100 + oe_instance_within_pipe * 0x10
+ */
+/* enum: Outer_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_TABLE 0x10000
+/* enum: Outer_Rule_No_CT_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_NO_CT_TABLE 0x10100
+/* enum: Mgmt_Filter_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGMT_FILTER_TABLE 0x10200
+/* enum: Conntrack_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_CONNTRACK_TABLE 0x10300
+/* enum: Action_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ACTION_RULE_TABLE 0x10400
+/* enum: Mgroup_Default_Action_Set_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGROUP_DEFAULT_ACTION_SET_TABLE 0x10500
+/* enum: Encap_Hdr_Part1_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART1_TABLE 0x10600
+/* enum: Encap_Hdr_Part2_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART2_TABLE 0x10700
+/* enum: Replace_Src_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_SRC_MAC_TABLE 0x10800
+/* enum: Replace_Dst_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_DST_MAC_TABLE 0x10900
+/* enum: Dst_Mport_VC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_VC_TABLE 0x10a00
+/* enum: LACP_LAG_Config_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_LAG_CONFIG_TABLE 0x10b00
+/* enum: LACP_Balance_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_BALANCE_TABLE 0x10c00
+/* enum: Dst_Mport_Host_Chan_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_HOST_CHAN_TABLE 0x10d00
+/* enum: VNIC_Rx_Encap_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_VNIC_RX_ENCAP_TABLE 0x20000
+/* enum: Steering_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_STEERING_TABLE 0x20100
+/* enum: RSS_Context_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_RSS_CONTEXT_TABLE 0x20200
+/* enum: Indirection_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_INDIRECTION_TABLE 0x20300
+/* enum: DPU.host read pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC0_OE_PROFILE 0x1010000
+/* enum: DPU.host read pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC1_OE_PROFILE 0x1010010
+/* enum: DPU.host write pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC0_OE_PROFILE 0x1018000
+/* enum: DPU.host write pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC1_OE_PROFILE 0x1018010
+/* enum: DPU.net 'full' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CRC0_OE_PROFILE 0x1020000
+/* enum: DPU.net 'full' receive pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM0_OE_PROFILE 0x1020100
+/* enum: DPU.net 'full' receive pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM1_OE_PROFILE 0x1020110
+/* enum: DPU.net 'full' receive pipe AES-GCM offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_AES_GCM0_OE_PROFILE 0x1020200
+/* enum: DPU.net 'lite' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CRC0_OE_PROFILE 0x1021000
+/* enum: DPU.net 'lite' receive pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CSUM0_OE_PROFILE 0x1021100
+/* enum: DPU.net 'full' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CRC0_OE_PROFILE 0x1028000
+/* enum: DPU.net 'full' transmit pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM0_OE_PROFILE 0x1028100
+/* enum: DPU.net 'full' transmit pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM1_OE_PROFILE 0x1028110
+/* enum: DPU.net 'full' transmit pipe AES-GCM offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_AES_GCM0_OE_PROFILE 0x1028200
+/* enum: DPU.net 'lite' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CRC0_OE_PROFILE 0x1029000
+/* enum: DPU.net 'lite' transmit pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CSUM0_OE_PROFILE 0x1029100
+
+/* TABLE_COMPRESSED_VLAN enum: Compressed VLAN TPID as used by some field
+ * types; can be calculated by (((ether_type_msb >> 2) & 0x4) ^ 0x4) |
+ * (ether_type_msb & 0x3);
+ */
+#define	TABLE_COMPRESSED_VLAN_TPID_8100 0x5 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_88A8 0x4 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9100 0x1 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9200 0x2 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9300 0x3 /* enum */
+
+/* TABLE_NAT_DIR enum: NAT direction. */
+#define	TABLE_NAT_DIR_SOURCE 0x0 /* enum */
+#define	TABLE_NAT_DIR_DEST 0x1 /* enum */
+
+/* TABLE_RSS_KEY_MODE enum: Defines how the value for Toeplitz hashing for RSS
+ * is constructed as a concatenation (indicated here by "++") of packet header
+ * fields.
+ */
+/* enum: IP src addr ++ IP dst addr */
+#define	TABLE_RSS_KEY_MODE_SA_DA 0x0
+/* enum: IP src addr ++ IP dst addr ++ TCP/UDP src port ++ TCP/UDP dst port */
+#define	TABLE_RSS_KEY_MODE_SA_DA_SP_DP 0x1
+/* enum: IP src addr */
+#define	TABLE_RSS_KEY_MODE_SA 0x2
+/* enum: IP dst addr */
+#define	TABLE_RSS_KEY_MODE_DA 0x3
+/* enum: IP src addr ++ TCP/UDP src port */
+#define	TABLE_RSS_KEY_MODE_SA_SP 0x4
+/* enum: IP dest addr ++ TCP dest port */
+#define	TABLE_RSS_KEY_MODE_DA_DP 0x5
+/* enum: Nothing (produces input of 0, resulting in output hash of 0) */
+#define	TABLE_RSS_KEY_MODE_NONE 0x7
+
+/* TABLE_RSS_SPREAD_MODE enum: RSS spreading mode. */
+/* enum: RSS uses Indirection_Table lookup. */
+#define	TABLE_RSS_SPREAD_MODE_INDIRECTION 0x0
+/* enum: RSS uses even spreading calculation. */
+#define	TABLE_RSS_SPREAD_MODE_EVEN 0x1
+
+/* CRC_VARIANT enum: Operation for the DPU CRC engine to perform. */
+/* enum: Calculate a 32-bit CRC. */
+#define	CRC_VARIANT_CRC32 0x1
+/* enum: Calculate a 64-bit CRC. */
+#define	CRC_VARIANT_CRC64 0x2
+
+/* DPU_CSUM_OP enum: Operation for the DPU checksum engine to perform. */
+/* enum: Calculate the checksum for a TCP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_TCP 0x0
+/* enum: Calculate the checksum for a UDP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_UDP 0x1
+/* enum: Calculate the checksum for a TCP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_TCP 0x2
+/* enum: Calculate the checksum for a UDP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_UDP 0x3
+
+/* GCM_OP_CODE enum: Operation for the DPU AES-GCM engine to perform. */
+/* enum: Encrypt/decrypt a stream of data. */
+#define	GCM_OP_CODE_BULK_CRYPT 0x0
+/* enum: Calculate the authentication tag for a stream of data. */
+#define	GCM_OP_CODE_BULK_AUTH 0x1
+/* enum: Encrypt/decrypt an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_CRYPT 0x2
+/* enum: Calculate the authentication tag of an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_AUTH 0x3
+
+/* AES_KEY_LEN enum: Key size for AES crypto operations */
+/* enum: 128 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_128 0x0
+/* enum: 256 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_256 0x1
+
+/* TABLE_FIELD_ID enum: Unique IDs for fields. Related concepts have been
+ * loosely grouped together into blocks with gaps for expansion, but the values
+ * are arbitrary. Field IDs are not specific to particular tables, and in some
+ * cases this sharing means that they are not used with the exact names of the
+ * corresponding table definitions in SF-123102-TC; however, the mapping should
+ * still be clear. The intent is that a list of fields, with their associated
+ * bit widths and semantics version code, unambiguously defines the semantics
+ * of the fields in a key or response. (Again, this list includes all of the
+ * fields currently defined within the streaming engines, but only a subset may
+ * actually be used by the supported list of tables.)
+ */
+/* enum: May appear multiple times within a key or response, and indicates that
+ * the field is unused and should be set to 0 (or masked out if permitted by
+ * the MASK_VALUE for this field).
+ */
+#define	TABLE_FIELD_ID_UNUSED 0x0
+/* enum: Source m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_SRC_MPORT 0x1
+/* enum: Destination m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_DST_MPORT 0x2
+/* enum: Source m-group ID. */
+#define	TABLE_FIELD_ID_SRC_MGROUP_ID 0x3
+/* enum: Physical network port ID (or m-port ID; same thing, for physical
+ * network ports).
+ */
+#define	TABLE_FIELD_ID_NETWORK_PORT_ID 0x4
+/* enum: True if packet arrived via network port, false if it arrived via host.
+ */
+#define	TABLE_FIELD_ID_IS_FROM_NETWORK 0x5
+/* enum: Full virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC 0x6
+/* enum: Low bits of virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC_LOW 0x7
+/* enum: User mark value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_MARK 0x8
+/* enum: User flag value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_FLAG 0x9
+/* enum: Counter ID associated with a response. All-bits-1 is a null value to
+ * suppress counting.
+ */
+#define	TABLE_FIELD_ID_COUNTER_ID 0xa
+/* enum: Discriminator which may be set by plugins in some lookup keys; this
+ * allows plugins to make a reinterpretation of packet fields in these keys
+ * without clashing with the normal interpretation.
+ */
+#define	TABLE_FIELD_ID_DISCRIM 0xb
+/* enum: Destination MAC address. The mapping from bytes in a frame to the
+ * 48-bit value for this field is in network order, i.e. a MAC address of
+ * AA:BB:CC:DD:EE:FF becomes a 48-bit value of 0xAABBCCDDEEFF.
+ */
+#define	TABLE_FIELD_ID_DST_MAC 0x14
+/* enum: Source MAC address (see notes for DST_MAC). */
+#define	TABLE_FIELD_ID_SRC_MAC 0x15
+/* enum: Outer VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_OVLAN_TPID_COMPRESSED 0x16
+/* enum: Full outer VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_OVLAN 0x17
+/* enum: Outer VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_OVLAN_VID 0x18
+/* enum: Inner VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_IVLAN_TPID_COMPRESSED 0x19
+/* enum: Full inner VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_IVLAN 0x1a
+/* enum: Inner VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_IVLAN_VID 0x1b
+/* enum: Ethertype. */
+#define	TABLE_FIELD_ID_ETHER_TYPE 0x1c
+/* enum: Source IP address, either IPv4 or IPv6. The mapping from bytes in a
+ * frame to the 128-bit value for this field is in network order, with IPv4
+ * addresses assumed to have 12 bytes of trailing zeroes. i.e. the IPv6 address
+ * [2345::6789:ABCD] is 0x2345000000000000000000006789ABCD; the IPv4 address
+ * 192.168.1.2 is 0xC0A80102000000000000000000000000.
+ */
+#define	TABLE_FIELD_ID_SRC_IP 0x1d
+/* enum: Destination IP address (see notes for SRC_IP). */
+#define	TABLE_FIELD_ID_DST_IP 0x1e
+/* enum: IPv4 Type-of-Service or IPv6 Traffic Class field. */
+#define	TABLE_FIELD_ID_IP_TOS 0x1f
+/* enum: IP Protocol. */
+#define	TABLE_FIELD_ID_IP_PROTO 0x20
+/* enum: Layer 4 source port. */
+#define	TABLE_FIELD_ID_SRC_PORT 0x21
+/* enum: Layer 4 destination port. */
+#define	TABLE_FIELD_ID_DST_PORT 0x22
+/* enum: TCP flags. */
+#define	TABLE_FIELD_ID_TCP_FLAGS 0x23
+/* enum: Virtual Network Identifier (VXLAN) or Virtual Session ID (NVGRE). */
+#define	TABLE_FIELD_ID_VNI 0x24
+/* enum: True if packet has any tunnel encapsulation header. */
+#define	TABLE_FIELD_ID_HAS_ENCAP 0x32
+/* enum: True if encap header has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_OVLAN 0x33
+/* enum: True if encap header has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_IVLAN 0x34
+/* enum: True if encap header is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP 0x35
+/* enum: True if encap header is specifically IPv4. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP4 0x36
+/* enum: True if encap header is UDP. */
+#define	TABLE_FIELD_ID_HAS_ENC_UDP 0x37
+/* enum: True if only/inner frame has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_OVLAN 0x38
+/* enum: True if only/inner frame has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_IVLAN 0x39
+/* enum: True if only/inner frame is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_IP 0x3a
+/* enum: True if only/inner frame has a recognised L4 IP protocol (TCP or UDP).
+ */
+#define	TABLE_FIELD_ID_HAS_L4 0x3b
+/* enum: True if only/inner frame is an IP fragment. */
+#define	TABLE_FIELD_ID_IP_FRAG 0x3c
+/* enum: True if only/inner frame is the first IP fragment (fragment offset 0).
+ */
+#define	TABLE_FIELD_ID_IP_FIRST_FRAG 0x3d
+/* enum: True if only/inner frame has an IP Time-To-Live of <= 1. (Note: the
+ * implementation calls this "ip_ttl_is_one" but does in fact match packets
+ * with TTL=0 - which we shouldn't be seeing! - as well.)
+ */
+#define	TABLE_FIELD_ID_IP_TTL_LE_ONE 0x3e
+/* enum: True if only/inner frame has any of TCP SYN, FIN or RST flags set. */
+#define	TABLE_FIELD_ID_TCP_INTERESTING_FLAGS 0x3f
+/* enum: Plugin channel selection. */
+#define	TABLE_FIELD_ID_RDP_PL_CHAN 0x50
+/* enum: Enable update of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL_EN 0x51
+/* enum: New value of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL 0x52
+/* enum: Enable update of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL_EN 0x53
+/* enum: New value of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL 0x54
+/* enum: Enable update of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN_EN 0x55
+/* enum: New value of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN 0x56
+/* enum: Recirculation ID for lookup sequences with two action rule lookups. */
+#define	TABLE_FIELD_ID_RECIRC_ID 0x64
+/* enum: Domain ID passed to conntrack and action rule lookups. */
+#define	TABLE_FIELD_ID_DOMAIN 0x65
+/* enum: Construction mode for encap_tunnel_id - see MAE_CT_VNI_MODE enum. */
+#define	TABLE_FIELD_ID_CT_VNI_MODE 0x66
+/* enum: True to inhibit conntrack lookup if TCP SYN, FIN or RST flag is set.
+ */
+#define	TABLE_FIELD_ID_CT_TCP_FLAGS_INHIBIT 0x67
+/* enum: True to do conntrack lookups for IPv4 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_TCP 0x68
+/* enum: True to do conntrack lookups for IPv4 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_UDP 0x69
+/* enum: True to do conntrack lookups for IPv6 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_TCP 0x6a
+/* enum: True to do conntrack lookups for IPv6 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_UDP 0x6b
+/* enum: Outer rule identifier. */
+#define	TABLE_FIELD_ID_OUTER_RULE_ID 0x6c
+/* enum: Encapsulation type - see MAE_MCDI_ENCAP_TYPE enum. */
+#define	TABLE_FIELD_ID_ENCAP_TYPE 0x6d
+/* enum: Encap tunnel ID for conntrack lookups from VNI, VLAN tag(s), or 0,
+ * depending on CT_VNI_MODE.
+ */
+#define	TABLE_FIELD_ID_ENCAP_TUNNEL_ID 0x78
+/* enum: A conntrack entry identifier, passed to plugins. */
+#define	TABLE_FIELD_ID_CT_ENTRY_ID 0x79
+/* enum: Either source or destination NAT replacement port. */
+#define	TABLE_FIELD_ID_NAT_PORT 0x7a
+/* enum: Either source or destination NAT replacement IPv4 address. Note that
+ * this is specifically an IPv4 address (IPv6 is not supported for NAT), with
+ * byte mapped to a 32-bit value in network order, i.e. the IPv4 address
+ * 192.168.1.2 is the value 0xC0A80102.
+ */
+#define	TABLE_FIELD_ID_NAT_IP 0x7b
+/* enum: NAT direction: 0=>source, 1=>destination. */
+#define	TABLE_FIELD_ID_NAT_DIR 0x7c
+/* enum: Conntrack mark value, passed to action rule lookup. Note that this is
+ * not related to the "user mark" in the metadata / packet prefix.
+ */
+#define	TABLE_FIELD_ID_CT_MARK 0x7d
+/* enum: Private flags for conntrack, passed to action rule lookup. */
+#define	TABLE_FIELD_ID_CT_PRIV_FLAGS 0x7e
+/* enum: True if the conntrack lookup resulted in a hit. */
+#define	TABLE_FIELD_ID_CT_HIT 0x7f
+/* enum: True to suppress delivery when source and destination m-ports match.
+ */
+#define	TABLE_FIELD_ID_SUPPRESS_SELF_DELIVERY 0x8c
+/* enum: True to perform tunnel decapsulation. */
+#define	TABLE_FIELD_ID_DO_DECAP 0x8d
+/* enum: True to copy outer frame DSCP to inner on decap. */
+#define	TABLE_FIELD_ID_DECAP_DSCP_COPY 0x8e
+/* enum: True to map outer frame ECN to inner on decap, by RFC 6040 rules. */
+#define	TABLE_FIELD_ID_DECAP_ECN_RFC6040 0x8f
+/* enum: True to replace DSCP field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_DSCP 0x90
+/* enum: True to replace ECN field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_ECN 0x91
+/* enum: True to decrement IP Time-To-Live. */
+#define	TABLE_FIELD_ID_DO_DECR_IP_TTL 0x92
+/* enum: True to replace source MAC address. */
+#define	TABLE_FIELD_ID_DO_SRC_MAC 0x93
+/* enum: True to replace destination MAC address. */
+#define	TABLE_FIELD_ID_DO_DST_MAC 0x94
+/* enum: Number of VLAN tags to pop. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_POP 0x95
+/* enum: Number of VLANs tags to push. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_PUSH 0x96
+/* enum: True to count this packet. */
+#define	TABLE_FIELD_ID_DO_COUNT 0x97
+/* enum: True to perform tunnel encapsulation. */
+#define	TABLE_FIELD_ID_DO_ENCAP 0x98
+/* enum: True to copy inner frame DSCP to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_DSCP_COPY 0x99
+/* enum: True to copy inner frame ECN to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_ECN_COPY 0x9a
+/* enum: True to deliver the packet (otherwise it is dropped). */
+#define	TABLE_FIELD_ID_DO_DELIVER 0x9b
+/* enum: True to set the user flag in the metadata. */
+#define	TABLE_FIELD_ID_DO_FLAG 0x9c
+/* enum: True to update the user mark in the metadata. */
+#define	TABLE_FIELD_ID_DO_MARK 0x9d
+/* enum: True to override the capsule virtual channel for network deliveries.
+ */
+#define	TABLE_FIELD_ID_DO_SET_NET_CHAN 0x9e
+/* enum: True to override the reported source m-port for host deliveries. */
+#define	TABLE_FIELD_ID_DO_SET_SRC_MPORT 0x9f
+/* enum: Encap header ID for DO_ENCAP, indexing Encap_Hdr_Part1/2_Table. */
+#define	TABLE_FIELD_ID_ENCAP_HDR_ID 0xaa
+/* enum: New DSCP value for DO_REPLACE_DSCP. */
+#define	TABLE_FIELD_ID_DSCP_VALUE 0xab
+/* enum: If DO_REPLACE_ECN is set, the new value for the ECN field. If
+ * DO_REPLACE_ECN is not set, ECN_CONTROL[0] and ECN_CONTROL[1] are set to
+ * request remapping of ECT0 and ECT1 ECN codepoints respectively to CE.
+ */
+#define	TABLE_FIELD_ID_ECN_CONTROL 0xac
+/* enum: Source MAC ID for DO_SRC_MAC, indexing Replace_Src_MAC_Table. */
+#define	TABLE_FIELD_ID_SRC_MAC_ID 0xad
+/* enum: Destination MAC ID for DO_DST_MAC, indexing Replace_Dst_MAC_Table. */
+#define	TABLE_FIELD_ID_DST_MAC_ID 0xae
+/* enum: Parameter for either DO_SET_NET_CHAN (only bottom 6 bits used in this
+ * case) or DO_SET_SRC_MPORT.
+ */
+#define	TABLE_FIELD_ID_REPORTED_SRC_MPORT_OR_NET_CHAN 0xaf
+/* enum: 64-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK64 0xb4
+/* enum: 32-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK32 0xb5
+/* enum: 16-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK16 0xb6
+/* enum: 8-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK8 0xb7
+/* enum: 4-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK4 0xb8
+/* enum: 2-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK2 0xb9
+/* enum: Added encapsulation header length in words. */
+#define	TABLE_FIELD_ID_HDR_LEN_W 0xba
+/* enum: Static value for layer 2/3 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L23 0xbb
+/* enum: Static value for layer 4 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L4 0xbc
+/* enum: True to use the static ENC_LACP_HASH values for the encap header
+ * instead of the calculated values for the inner frame when delivering a newly
+ * encapsulated packet to a LAG m-port.
+ */
+#define	TABLE_FIELD_ID_USE_ENC_LACP_HASHES 0xbd
+/* enum: True to trigger conntrack from first action rule lookup (AR=>CT=>AR
+ * sequence).
+ */
+#define	TABLE_FIELD_ID_DO_CT 0xc8
+/* enum: True to perform NAT using parameters from conntrack lookup response.
+ */
+#define	TABLE_FIELD_ID_DO_NAT 0xc9
+/* enum: True to trigger recirculated action rule lookup (AR=>AR sequence). */
+#define	TABLE_FIELD_ID_DO_RECIRC 0xca
+/* enum: Next action set payload ID for replay. The null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_PAYLOAD 0xcb
+/* enum: Next action set row ID for replay. The null value is all-1-bits. */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_ROW 0xcc
+/* enum: Action set payload ID for additional delivery to management CPU. The
+ * null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_PAYLOAD 0xcd
+/* enum: Action set row ID for additional delivery to management CPU. The null
+ * value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_ROW 0xce
+/* enum: True to include layer 4 in LACP hash on delivery to a LAG m-port. */
+#define	TABLE_FIELD_ID_LACP_INC_L4 0xdc
+/* enum: True to request that LACP is performed by a plugin. */
+#define	TABLE_FIELD_ID_LACP_PLUGIN 0xdd
+/* enum: LACP_Balance_Table base address divided by 64. */
+#define	TABLE_FIELD_ID_BAL_TBL_BASE_DIV64 0xde
+/* enum: Length of balance table region: 0=>64, 1=>128, 2=>256. */
+#define	TABLE_FIELD_ID_BAL_TBL_LEN_ID 0xdf
+/* enum: LACP LAG ID (i.e. the low 3 bits of LACP LAG mport ID), indexing
+ * LACP_LAG_Config_Table. Refer to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_LACP_LAG_ID 0xe0
+/* enum: Address in LACP_Balance_Table. The balance table is partitioned
+ * between LAGs according to the settings in LACP_LAG_Config_Table and then
+ * indexed by the LACP hash, providing the mapping to destination mports. Refer
+ * to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_BAL_TBL_ADDR 0xe1
+/* enum: UDP port to match for UDP-based encapsulations; required to be 0 for
+ * other encapsulation types.
+ */
+#define	TABLE_FIELD_ID_UDP_PORT 0xe6
+/* enum: True to perform RSS based on outer fields rather than inner fields. */
+#define	TABLE_FIELD_ID_RSS_ON_OUTER 0xe7
+/* enum: True to perform steering table lookup on outer fields rather than
+ * inner fields.
+ */
+#define	TABLE_FIELD_ID_STEER_ON_OUTER 0xe8
+/* enum: Destination queue ID for host delivery. */
+#define	TABLE_FIELD_ID_DST_QID 0xf0
+/* enum: True to drop this packet. */
+#define	TABLE_FIELD_ID_DROP 0xf1
+/* enum: True to strip outer VLAN tag from this packet. */
+#define	TABLE_FIELD_ID_VLAN_STRIP 0xf2
+/* enum: True to override the user mark field with the supplied USER_MARK, or
+ * false to bitwise-OR the USER_MARK into it.
+ */
+#define	TABLE_FIELD_ID_MARK_OVERRIDE 0xf3
+/* enum: True to override the user flag field with the supplied USER_FLAG, or
+ * false to bitwise-OR the USER_FLAG into it.
+ */
+#define	TABLE_FIELD_ID_FLAG_OVERRIDE 0xf4
+/* enum: RSS context ID, indexing the RSS_Context_Table. */
+#define	TABLE_FIELD_ID_RSS_CTX_ID 0xfa
+/* enum: True to enable RSS. */
+#define	TABLE_FIELD_ID_RSS_EN 0xfb
+/* enum: Toeplitz hash key. */
+#define	TABLE_FIELD_ID_KEY 0xfc
+/* enum: Key mode for IPv4 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V4_KEY_MODE 0xfd
+/* enum: Key mode for IPv6 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V6_KEY_MODE 0xfe
+/* enum: Key mode for IPv4 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V4_KEY_MODE 0xff
+/* enum: Key mode for IPv6 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V6_KEY_MODE 0x100
+/* enum: Key mode for other IPv4 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V4_KEY_MODE 0x101
+/* enum: Key mode for other IPv6 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V6_KEY_MODE 0x102
+/* enum: Spreading mode - 0=>indirection; 1=>even. */
+#define	TABLE_FIELD_ID_SPREAD_MODE 0x103
+/* enum: For indirection spreading mode, the base address of a region within
+ * the Indirection_Table. For even spreading mode, the number of queues to
+ * spread across (only values 1-255 are valid for this mode).
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_BASE 0x104
+/* enum: For indirection spreading mode, identifies the length of a region
+ * within the Indirection_Table, where length = 32 << len_id. Must be set to 0
+ * for even spreading mode.
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_LEN_ID 0x105
+/* enum: An offset to be applied to the base destination queue ID. */
+#define	TABLE_FIELD_ID_INDIR_OFFSET 0x106
+/* enum: DPU offload engine profile ID to address. */
+#define	TABLE_FIELD_ID_OE_PROFILE 0x3e8
+/* enum: Width of the CRC to calculate - see CRC_VARIANT enum. */
+#define	TABLE_FIELD_ID_CRC_VARIANT 0x3f2
+/* enum: If set, reflect the bits of each input byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFIN 0x3f3
+/* enum: If set, reflect the bits of each output byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFOUT 0x3f4
+/* enum: If set, invert every bit of the output value. */
+#define	TABLE_FIELD_ID_CRC_INVOUT 0x3f5
+/* enum: The CRC polynomial to use for checksumming, in normal form. See
+ * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Specification for a
+ * description of normal form.
+ */
+#define	TABLE_FIELD_ID_CRC_POLY 0x3f6
+/* enum: Operation for the checksum engine to perform - see DPU_CSUM_OP enum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OP 0x410
+/* enum: Byte offset of checksum relative to region_start (for VALIDATE_*
+ * operations only).
+ */
+#define	TABLE_FIELD_ID_CSUM_OFFSET 0x411
+/* enum: Indicates there is additional data on OPR bus that needs to be
+ * incorporated into the payload checksum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OPR_ADDITIONAL_DATA 0x412
+/* enum: Log2 data size of additional data on OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_DATA_SIZE_LOG2 0x413
+/* enum: 4 byte offset of where to find the additional data on the OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_4B_OFF 0x414
+/* enum: Operation type for the AES-GCM core - see GCM_OP_CODE enum. */
+#define	TABLE_FIELD_ID_GCM_OP_CODE 0x41a
+/* enum: Key length - AES_KEY_LEN enum. */
+#define	TABLE_FIELD_ID_GCM_KEY_LEN 0x41b
+/* enum: OPR 4 byte offset for ICV or GHASH output (only in BULK_* mode) or
+ * IPSEC descrypt output.
+ */
+#define	TABLE_FIELD_ID_GCM_OPR_4B_OFFSET 0x41c
+/* enum: If OP_CODE is BULK_*, indicates Emit GHASH (Fragment mode). Else,
+ * indicates IPSEC-ESN mode.
+ */
+#define	TABLE_FIELD_ID_GCM_EMIT_GHASH_ISESN 0x41d
+/* enum: Replay Protection Enable. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_PROTECT_EN 0x41e
+/* enum: IPSEC Encrypt ESP trailer NEXT_HEADER byte. */
+#define	TABLE_FIELD_ID_GCM_NEXT_HDR 0x41f
+/* enum: Replay Window Size. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_WIN_SIZE 0x420
 
 /* MCDI_EVENT structuredef: The structure of an MCDI_EVENT on Siena/EF10/EF100
  * platforms
@@ -819,7 +1434,7 @@
 #define	MCDI_EVENT_AOE_FPGA_LOAD_FAILED 0xe
 /* enum: Notify that invalid flash type detected */
 #define	MCDI_EVENT_AOE_INVALID_FPGA_FLASH_TYPE 0xf
-/* enum: Notify that the attempt to run FPGA Controller firmware timedout */
+/* enum: Notify that the attempt to run FPGA Controller firmware timed out */
 #define	MCDI_EVENT_AOE_FC_RUN_TIMEDOUT 0x10
 /* enum: Failure to probe one or more FPGA boot flash chips */
 #define	MCDI_EVENT_AOE_FPGA_BOOT_FLASH_INVALID 0x11
@@ -837,7 +1452,7 @@
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_INFO_WIDTH 8
 /* enum: FC Assert happened, but the register information is not available */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_SEEN 0x0
-/* enum: The register information for FC Assert is ready for readinng by driver
+/* enum: The register information for FC Assert is ready for reading by driver
  */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_DATA_READY 0x1
 #define	MCDI_EVENT_AOE_ERR_CODE_FPGA_HEADER_VERIFY_FAILED_OFST 0
@@ -946,6 +1561,12 @@
 #define	MCDI_EVENT_MODULECHANGE_SEQ_OFST 0
 #define	MCDI_EVENT_MODULECHANGE_SEQ_LBN 30
 #define	MCDI_EVENT_MODULECHANGE_SEQ_WIDTH 2
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_LBN 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_WIDTH 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_LBN 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_WIDTH 16
 #define	MCDI_EVENT_DATA_LBN 0
 #define	MCDI_EVENT_DATA_WIDTH 32
 /* Alias for PTP_DATA. */
@@ -1076,6 +1697,18 @@
  * SF-122927-TC for details.
  */
 #define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_DRIVER_ATTACH 0x26
+/* enum: Notification that the mport journal has changed since it was last read
+ * and updates can be read using the MC_CMD_MAE_MPORT_READ_JOURNAL command. The
+ * firmware may moderate the events so that an event is not sent for every
+ * change to the journal.
+ */
+#define	MCDI_EVENT_CODE_MPORT_JOURNAL_CHANGE 0x27
+/* enum: Notification that a source queue is enabled and attached to its proxy
+ * sink queue. SRC field contains the handle of the affected descriptor proxy
+ * function. DATA field contains the relative source queue number and absolute
+ * VI ID.
+ */
+#define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_QUEUE_START 0x28
 /* enum: Artificial event generated by host and posted via MC for test
  * purposes.
  */
@@ -1842,6 +2475,7 @@
 /* Log destination */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_LEN 4
+/* enum property: bitmask */
 /* enum: UART. */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1
 /* enum: Event queue. */
@@ -1888,6 +2522,9 @@
 
 /* MC_CMD_GET_VERSION_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_OUT_LEN 32
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1910,6 +2547,9 @@
 
 /* MC_CMD_GET_VERSION_EXT_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_EXT_OUT_LEN 48
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1940,6 +2580,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V2_OUT_LEN 304
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2079,6 +2722,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V3_OUT_LEN 328
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2225,6 +2871,9 @@
  * version information
  */
 #define	MC_CMD_GET_VERSION_V4_OUT_LEN 392
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2387,6 +3036,9 @@
  * and board version information
  */
 #define	MC_CMD_GET_VERSION_V5_OUT_LEN 424
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2659,7 +3311,9 @@
 #define	MC_CMD_PTP_IN_CMD_LEN 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_OFST 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_LEN 4
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_LEN 4
 /* PTP timestamping mode. Not used from Huntington onwards. */
@@ -3030,7 +3684,9 @@
 #define	MC_CMD_PTP_ENABLE_PPS 0x0
 /* enum: Disable */
 #define	MC_CMD_PTP_DISABLE_PPS 0x1
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_OFST 8
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_LEN 4
 
@@ -3392,6 +4048,87 @@
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_OFST 20
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_LEN 4
 
+/* MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2 msgresponse */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_LEN 40
+/* Time format required/used by for this NIC. Applies to all PTP MCDI
+ * operations that pass times between the host and firmware. If this operation
+ * is not supported (older firmware) a format of seconds and nanoseconds should
+ * be assumed.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_OFST 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_LEN 4
+/* enum: Times are in seconds and nanoseconds */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_NANOSECONDS 0x0
+/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_16SECONDS_8NANOSECONDS 0x1
+/* enum: Major register has units of seconds, minor 2^-27s per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_27FRACTION 0x2
+/* enum: Major register units are seconds, minor units are quarter nanoseconds
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_QTR_NANOSECONDS 0x3
+/* Minimum acceptable value for a corrected synchronization timeset. When
+ * comparing host and NIC clock times, the MC returns a set of samples that
+ * contain the host start and end time, the MC time when the host start was
+ * detected and the time the MC waited between reading the time and detecting
+ * the host end. The corrected sync window is the difference between the host
+ * end and start times minus the time that the MC waited for host end.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_OFST 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_LEN 4
+/* Various PTP capabilities */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_LBN 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_LBN 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_LBN 2
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_LBN 3
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_OFST 12
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_OFST 16
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_OFST 20
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_LEN 4
+/* Minimum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of -0.1 ns should be assumed, which is
+ * equivalent to a -10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LBN 192
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_OFST 28
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LBN 224
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_WIDTH 32
+/* Maximum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of 0.1 ns should be assumed, which is
+ * equivalent to a +10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LBN 256
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_OFST 36
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LBN 288
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_WIDTH 32
+
 /* MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS msgresponse */
 #define	MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN 16
 /* Uncorrected error on PTP transmit timestamps in NIC clock format */
@@ -3443,12 +4180,16 @@
 /***********************************/
 /* MC_CMD_CSR_READ32
  * Read 32bit words from the indirect memory map.
+ *
+ * Note - this command originally belonged to INSECURE category. But access is
+ * required to specific registers for customer diagnostics. The command handler
+ * has additional checks to reject insecure calls.
  */
 #define	MC_CMD_CSR_READ32 0xc
 #define	MC_CMD_CSR_READ32_MSGSET 0xc
 #undef	MC_CMD_0xc_PRIVILEGE_CTG
 
-#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_INSECURE
+#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_ADMIN
 
 /* MC_CMD_CSR_READ32_IN msgrequest */
 #define	MC_CMD_CSR_READ32_IN_LEN 12
@@ -4221,6 +4962,7 @@
 /* Flags associated with this function */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_OFST 4
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_LEN 4
+/* enum property: bitshift */
 /* enum: Labels the lowest-numbered function visible to the OS */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY 0x0
 /* enum: The function can control the link state of the physical port it is
@@ -4454,6 +5196,54 @@
 /* MC_CMD_GET_PHY_CFG_IN msgrequest */
 #define	MC_CMD_GET_PHY_CFG_IN_LEN 0
 
+/* MC_CMD_GET_PHY_CFG_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_CFG_OUT msgresponse */
 #define	MC_CMD_GET_PHY_CFG_OUT_LEN 72
 /* flags */
@@ -4549,6 +5339,9 @@
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_OFST 8
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN 21
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_WIDTH 1
+#define	MC_CMD_PHY_CAP_200000FDX_OFST 8
+#define	MC_CMD_PHY_CAP_200000FDX_LBN 22
+#define	MC_CMD_PHY_CAP_200000FDX_WIDTH 1
 /* ?? */
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_LEN 4
@@ -4582,6 +5375,7 @@
 #define	MC_CMD_MEDIA_DSFP 0x8
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_LEN 4
+/* enum property: bitshift */
 /* enum: Native clause 22 */
 #define	MC_CMD_MMD_CLAUSE22 0x0
 #define	MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
@@ -4847,6 +5641,54 @@
 /* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
 #define	MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
 
+/* MC_CMD_GET_LOOPBACK_MODES_IN_V2 msgrequest */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_LEN 8
+/* Target port to request loopback modes for. Uses MAE_LINK_ENDPOINT_SELECTOR
+ * which identifies a real or virtual network port by MAE port and link end.
+ * See the structure definition for more details
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 40
 /* Supported loopbacks. */
@@ -4860,6 +5702,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 #define	MC_CMD_LOOPBACK_NONE 0x0
 /* enum: Data. */
@@ -4949,6 +5792,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4962,6 +5806,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4975,6 +5820,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4988,6 +5834,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5006,6 +5853,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 /*               MC_CMD_LOOPBACK_NONE 0x0 */
 /* enum: Data. */
@@ -5095,6 +5943,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5108,6 +5957,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5121,6 +5971,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5134,6 +5985,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 25G loopbacks. */
@@ -5147,6 +5999,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LBN 352
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 50 loopbacks. */
@@ -5160,6 +6013,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LBN 416
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 100G loopbacks. */
@@ -5173,6 +6027,214 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LBN 480
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT_V3 msgresponse: Supported loopback modes for
+ * newer NICs with 200G support
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_LEN 72
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_WIDTH 32
+/* enum property: bitshift */
+/* enum: None. */
+/*               MC_CMD_LOOPBACK_NONE 0x0 */
+/* enum: Data. */
+/*               MC_CMD_LOOPBACK_DATA 0x1 */
+/* enum: GMAC. */
+/*               MC_CMD_LOOPBACK_GMAC 0x2 */
+/* enum: XGMII. */
+/*               MC_CMD_LOOPBACK_XGMII 0x3 */
+/* enum: XGXS. */
+/*               MC_CMD_LOOPBACK_XGXS 0x4 */
+/* enum: XAUI. */
+/*               MC_CMD_LOOPBACK_XAUI 0x5 */
+/* enum: GMII. */
+/*               MC_CMD_LOOPBACK_GMII 0x6 */
+/* enum: SGMII. */
+/*               MC_CMD_LOOPBACK_SGMII 0x7 */
+/* enum: XGBR. */
+/*               MC_CMD_LOOPBACK_XGBR 0x8 */
+/* enum: XFI. */
+/*               MC_CMD_LOOPBACK_XFI 0x9 */
+/* enum: XAUI Far. */
+/*               MC_CMD_LOOPBACK_XAUI_FAR 0xa */
+/* enum: GMII Far. */
+/*               MC_CMD_LOOPBACK_GMII_FAR 0xb */
+/* enum: SGMII Far. */
+/*               MC_CMD_LOOPBACK_SGMII_FAR 0xc */
+/* enum: XFI Far. */
+/*               MC_CMD_LOOPBACK_XFI_FAR 0xd */
+/* enum: GPhy. */
+/*               MC_CMD_LOOPBACK_GPHY 0xe */
+/* enum: PhyXS. */
+/*               MC_CMD_LOOPBACK_PHYXS 0xf */
+/* enum: PCS. */
+/*               MC_CMD_LOOPBACK_PCS 0x10 */
+/* enum: PMA-PMD. */
+/*               MC_CMD_LOOPBACK_PMAPMD 0x11 */
+/* enum: Cross-Port. */
+/*               MC_CMD_LOOPBACK_XPORT 0x12 */
+/* enum: XGMII-Wireside. */
+/*               MC_CMD_LOOPBACK_XGMII_WS 0x13 */
+/* enum: XAUI Wireside. */
+/*               MC_CMD_LOOPBACK_XAUI_WS 0x14 */
+/* enum: XAUI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 */
+/* enum: XAUI Wireside near. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 */
+/* enum: GMII Wireside. */
+/*               MC_CMD_LOOPBACK_GMII_WS 0x17 */
+/* enum: XFI Wireside. */
+/*               MC_CMD_LOOPBACK_XFI_WS 0x18 */
+/* enum: XFI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 */
+/* enum: PhyXS Wireside. */
+/*               MC_CMD_LOOPBACK_PHYXS_WS 0x1a */
+/* enum: PMA lanes MAC-Serdes. */
+/*               MC_CMD_LOOPBACK_PMA_INT 0x1b */
+/* enum: KR Serdes Parallel (Encoder). */
+/*               MC_CMD_LOOPBACK_SD_NEAR 0x1c */
+/* enum: KR Serdes Serial. */
+/*               MC_CMD_LOOPBACK_SD_FAR 0x1d */
+/* enum: PMA lanes MAC-Serdes Wireside. */
+/*               MC_CMD_LOOPBACK_PMA_INT_WS 0x1e */
+/* enum: KR Serdes Parallel Wireside (Full PCS). */
+/*               MC_CMD_LOOPBACK_SD_FEP2_WS 0x1f */
+/* enum: KR Serdes Parallel Wireside (Sym Aligner to TX). */
+/*               MC_CMD_LOOPBACK_SD_FEP1_5_WS 0x20 */
+/* enum: KR Serdes Parallel Wireside (Deserializer to Serializer). */
+/*               MC_CMD_LOOPBACK_SD_FEP_WS 0x21 */
+/* enum: KR Serdes Serial Wireside. */
+/*               MC_CMD_LOOPBACK_SD_FES_WS 0x22 */
+/* enum: Near side of AOE Siena side port */
+/*               MC_CMD_LOOPBACK_AOE_INT_NEAR 0x23 */
+/* enum: Medford Wireside datapath loopback */
+/*               MC_CMD_LOOPBACK_DATA_WS 0x24 */
+/* enum: Force link up without setting up any physical loopback (snapper use
+ * only)
+ */
+/*               MC_CMD_LOOPBACK_FORCE_EXT_LINK 0x25 */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LBN 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_OFST 12
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LBN 96
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LBN 128
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_OFST 20
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LBN 160
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LBN 192
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_OFST 28
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LBN 224
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LBN 256
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_OFST 36
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LBN 288
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 25G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LBN 320
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_OFST 44
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LBN 352
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 50 loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LBN 384
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_OFST 52
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LBN 416
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 100G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LBN 448
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_OFST 60
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LBN 480
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 200G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LBN 512
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_OFST 68
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LBN 544
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5222,6 +6284,54 @@
 /* MC_CMD_GET_LINK_IN msgrequest */
 #define	MC_CMD_GET_LINK_IN_LEN 0
 
+/* MC_CMD_GET_LINK_IN_V2 msgrequest */
+#define	MC_CMD_GET_LINK_IN_V2_LEN 8
+/* Target port to request link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LINK_OUT msgresponse */
 #define	MC_CMD_GET_LINK_OUT_LEN 28
 /* Near-side advertised capabilities. Refer to
@@ -5498,6 +6608,95 @@
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_LBN 7
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_WIDTH 1
 
+/* MC_CMD_SET_LINK_IN_V3 msgrequest */
+#define	MC_CMD_SET_LINK_IN_V3_LEN 28
+/* Near-side advertised capabilities. Refer to
+ * MC_CMD_GET_PHY_CFG_OUT/SUPPORTED_CAP for bit definitions.
+ */
+#define	MC_CMD_SET_LINK_IN_V3_CAP_OFST 0
+#define	MC_CMD_SET_LINK_IN_V3_CAP_LEN 4
+/* Flags */
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_LBN 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_LBN 2
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_LBN 3
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_WIDTH 1
+/* Loopback mode. */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_OFST 8
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_LEN 4
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+/* A loopback speed of "0" is supported, and means (choose any available
+ * speed).
+ */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_OFST 12
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_WIDTH 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_LBN 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_WIDTH 1
+/* Padding */
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_OFST 17
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_LEN 3
+/* Target port to set link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_SET_LINK_OUT msgresponse */
 #define	MC_CMD_SET_LINK_OUT_LEN 0
 
@@ -5719,19 +6918,9 @@
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_OFST 28
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_LBN 4
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_WIDTH 1
-/* Identifies the MAC to update by the specifying the end of a logical MAE
- * link. Setting TARGET to MAE_LINK_ENDPOINT_COMPAT is equivalent to using the
- * previous version of the command (MC_CMD_SET_MAC_EXT). Not all possible
- * combinations of MPORT_END and MPORT_SELECTOR in TARGET will work in all
- * circumstances. 1. Some will always work (e.g. a VF can always address its
- * logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC), 2. Some are not
- * meaningful and will always fail with EINVAL (e.g. attempting to address the
- * VNIC end of a link to a physical port), 3. Some are meaningful but require
- * the MCDI client to have the required permission and fail with EPERM
- * otherwise (e.g. trying to set the MAC on a VF the caller cannot administer),
- * and 4. Some could be implementation-specific and fail with ENOTSUP if not
- * available (no examples exist right now). See SF-123581-TC section 4.3 for
- * more details.
+/* Target port to set mac state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
  */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_LEN 8
@@ -5743,6 +6932,7 @@
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LBN 288
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 32
@@ -5938,6 +7128,98 @@
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_OFST 16
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_LEN 4
 
+/* MC_CMD_MAC_STATS_V2_IN msgrequest */
+#define	MC_CMD_MAC_STATS_V2_IN_LEN 28
+/* ??? */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_OFST 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LBN 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_LBN 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_LBN 2
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_LBN 3
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_LBN 4
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_LBN 5
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_LBN 16
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_WIDTH 16
+/* DMA length. Should be set to MAC_STATS_NUM_STATS * sizeof(uint64_t), as
+ * returned by MC_CMD_GET_CAPABILITIES_V4_OUT. For legacy firmware not
+ * supporting MC_CMD_GET_CAPABILITIES_V4_OUT, DMA_LEN should be set to
+ * MC_CMD_MAC_NSTATS * sizeof(uint64_t)
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_OFST 12
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_LEN 4
+/* port id so vadapter stats can be provided */
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_OFST 16
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_LEN 4
+/* Target port to request statistics for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
 #define	MC_CMD_MAC_STATS_OUT_DMA_LEN 0
 
@@ -5954,6 +7236,7 @@
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+/* enum property: index */
 #define	MC_CMD_MAC_GENERATION_START 0x0 /* enum */
 #define	MC_CMD_MAC_DMABUF_START 0x1 /* enum */
 #define	MC_CMD_MAC_TX_PKTS 0x1 /* enum */
@@ -6116,6 +7399,7 @@
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V2
+/* enum property: index */
 /* enum: Start of FEC stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_FEC_DMABUF_START 0x61
 /* enum: Number of uncorrected FEC codewords on link (RS-FEC only for Medford2)
@@ -6155,6 +7439,7 @@
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V3
+/* enum property: index */
 /* enum: Start of CTPIO stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_CTPIO_DMABUF_START 0x68
 /* enum: Number of CTPIO fallbacks because a DMA packet was in progress on the
@@ -6235,6 +7520,7 @@
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V4
+/* enum property: index */
 /* enum: Start of V4 stats buffer space */
 #define	MC_CMD_MAC_V4_DMABUF_START 0x79
 /* enum: RXDP counter: Number of packets truncated because scattering was
@@ -6522,6 +7808,7 @@
 #define	MC_CMD_WOL_FILTER_RESET_IN_LEN 4
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_LEN 4
+/* enum property: bitmask */
 #define	MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
 #define	MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
 
@@ -6566,6 +7853,7 @@
 /* Bit mask of supported types. */
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_LEN 4
+/* enum property: bitshift */
 /* enum: Disabled callisto. */
 #define	MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0
 /* enum: MC firmware. */
@@ -7613,6 +8901,54 @@
 /* MC_CMD_GET_PHY_STATE_IN msgrequest */
 #define	MC_CMD_GET_PHY_STATE_IN_LEN 0
 
+/* MC_CMD_GET_PHY_STATE_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_STATE_OUT msgresponse */
 #define	MC_CMD_GET_PHY_STATE_OUT_LEN 4
 #define	MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
@@ -7884,6 +9220,62 @@
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_LBN 16
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_WIDTH 16
 
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_LEN 12
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_LBN 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_WIDTH 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_LBN 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_WIDTH 16
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 7
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 52
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 48
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 6
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
@@ -9069,27 +10461,22 @@
  * and a generation count for this version of the sensor table. On systems
  * advertising the DYNAMIC_SENSORS capability bit, this replaces the
  * MC_CMD_READ_SENSORS command. On multi-MC systems this may include sensors
- * added by the NMC.
- *
- * Sensor handles are persistent for the lifetime of the sensor and are used to
- * identify sensors in MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
- * MC_CMD_DYNAMIC_SENSORS_GET_VALUES.
- *
- * The generation count is maintained by the MC, is persistent across reboots
- * and will be incremented each time the sensor table is modified. When the
- * table is modified, a CODE_DYNAMIC_SENSORS_CHANGE event will be generated
- * containing the new generation count. The driver should compare this against
- * the current generation count, and if it is different, call
- * MC_CMD_DYNAMIC_SENSORS_LIST again to update it's copy of the sensor table.
- *
- * The sensor count is provided to allow a future path to supporting more than
+ * added by the NMC. Sensor handles are persistent for the lifetime of the
+ * sensor and are used to identify sensors in
+ * MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
+ * MC_CMD_DYNAMIC_SENSORS_GET_VALUES. The generation count is maintained by the
+ * MC, is persistent across reboots and will be incremented each time the
+ * sensor table is modified. When the table is modified, a
+ * CODE_DYNAMIC_SENSORS_CHANGE event will be generated containing the new
+ * generation count. The driver should compare this against the current
+ * generation count, and if it is different, call MC_CMD_DYNAMIC_SENSORS_LIST
+ * again to update it's copy of the sensor table. The sensor count is provided
+ * to allow a future path to supporting more than
  * MC_CMD_DYNAMIC_SENSORS_GET_READINGS_IN_HANDLES_MAXNUM_MCDI2 sensors, i.e.
  * the maximum number that will fit in a single response. As this is a fairly
  * large number (253) it is not anticipated that this will be needed in the
- * near future, so can currently be ignored.
- *
- * On Riverhead this command is implemented as a a wrapper for `list` in the
- * sensor_query SPHINX service.
+ * near future, so can currently be ignored. On Riverhead this command is
+ * implemented as a wrapper for `list` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_LIST 0x66
 #define	MC_CMD_DYNAMIC_SENSORS_LIST_MSGSET 0x66
@@ -9127,15 +10514,13 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS
  * Get descriptions for a set of sensors, specified as an array of sensor
- * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for
- * `get_descriptions` in the sensor_query SPHINX service.
+ * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. Any handles which do not
+ * correspond to a sensor currently managed by the MC will be dropped from from
+ * the response. This may happen when a sensor table update is in progress, and
+ * effectively means the set of usable sensors is the intersection between the
+ * sets of sensors known to the driver and the MC. On Riverhead this command is
+ * implemented as a wrapper for `get_descriptions` in the sensor_query SPHINX
+ * service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS 0x67
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS_MSGSET 0x67
@@ -9173,19 +10558,15 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_READINGS
  * Read the state and value for a set of sensors, specified as an array of
- * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST.
- *
- * In the case of a broken sensor, then the state of the response's
- * MC_CMD_DYNAMIC_SENSORS_VALUE entry will be set to BROKEN, and any value
- * provided should be treated as erroneous.
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for `get_readings`
- * in the sensor_query SPHINX service.
+ * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. In the case of a
+ * broken sensor, then the state of the response's MC_CMD_DYNAMIC_SENSORS_VALUE
+ * entry will be set to BROKEN, and any value provided should be treated as
+ * erroneous. Any handles which do not correspond to a sensor currently managed
+ * by the MC will be dropped from from the response. This may happen when a
+ * sensor table update is in progress, and effectively means the set of usable
+ * sensors is the intersection between the sets of sensors known to the driver
+ * and the MC. On Riverhead this command is implemented as a wrapper for
+ * `get_readings` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS 0x68
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS_MSGSET 0x68
@@ -11629,6 +13010,9 @@
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_LBN 11
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -11833,6 +13217,9 @@
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12118,6 +13505,9 @@
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12663,6 +14053,7 @@
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_OFST 0
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_LEN 4
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_NUM 4
+/* enum property: bitmask */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP0 0x1 /* enum */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP1 0x2 /* enum */
 
@@ -13511,10 +14902,9 @@
 
 /***********************************/
 /* MC_CMD_GET_CAPABILITIES
- * Get device capabilities.
- *
- * This is supplementary to the MC_CMD_GET_BOARD_CFG command, and intended to
- * reference inherent device capabilities as opposed to current NVRAM config.
+ * Get device capabilities. This is supplementary to the MC_CMD_GET_BOARD_CFG
+ * command, and intended to reference inherent device capabilities as opposed
+ * to current NVRAM config.
  */
 #define	MC_CMD_GET_CAPABILITIES 0xbe
 #define	MC_CMD_GET_CAPABILITIES_MSGSET 0xbe
@@ -16473,6 +17863,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 
 /* MC_CMD_GET_CAPABILITIES_V8_OUT msgresponse */
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_LEN 160
@@ -16974,6 +18373,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -17489,6 +18897,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18039,6 +19456,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18134,6 +19560,13 @@
  * are not defined.
  */
 #define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_TSA 0x1
+/* enum: MCDI command used for platform management. Typically, these commands
+ * are used for low-level operations directed at the platform as a whole (e.g.
+ * MMIO device enumeration) rather than individual functions and use a
+ * dedicated comms channel (e.g. RPmsg/IPI). May be handled by the same or
+ * different CPU as MCDI_MESSAGE_TYPE_MC.
+ */
+#define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM 0x2
 
 
 /***********************************/
@@ -22051,8 +23484,8 @@
  * TLV_PORT_MODE_*). A superset of MC_CMD_GET_PORT_MODES_OUT/MODES that
  * contains all modes implemented in firmware for a particular board. Modes
  * listed in MODES are considered production modes and should be exposed in
- * userland tools. Modes listed in in ENGINEERING_MODES, but not in MODES
- * should be considered hidden (not to be exposed in userland tools) and for
+ * userland tools. Modes listed in ENGINEERING_MODES, but not in MODES should
+ * be considered hidden (not to be exposed in userland tools) and for
  * engineering use only. There are no other semantic differences and any mode
  * listed in either MODES or ENGINEERING_MODES can be set on the board.
  */
@@ -26509,6 +27942,7 @@
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MINNUM 0
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM 31
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_PACKETS 0x0 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_BYTES 0x1 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_GOOD_PACKETS 0x2 /* enum */
@@ -26617,6 +28051,65 @@
 /* MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT msgresponse */
 #define	MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT_LEN 0
 
+
+/***********************************/
+/* MC_CMD_GET_BUFTBL_STATS
+ * Currently EF10 only. Read usage and limits for Buffer Table
+ */
+#define	MC_CMD_GET_BUFTBL_STATS 0x6a
+#define	MC_CMD_GET_BUFTBL_STATS_MSGSET 0x6a
+#undef	MC_CMD_0x6a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x6a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_GET_BUFTBL_STATS_IN msgrequest */
+#define	MC_CMD_GET_BUFTBL_STATS_IN_LEN 0
+
+/* MC_CMD_GET_BUFTBL_STATS_OUT msgresponse */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_LEN 40
+/* number of buffer table entries per set */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_OFST 0
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_LEN 4
+/* number of buffer table entries per cluster */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_OFST 4
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_LEN 4
+/* Maximum size buffer table can grow to, in clusters. On EF10, this can
+ * potentially vary depending on the size of the Descriptor Cache.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_OFST 8
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_LEN 4
+/* High water mark for number of buffer table clusters which have been
+ * allocated.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_OFST 12
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_LEN 4
+/* Number of free buffer table clusters on the free cluster list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_OFST 16
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_LEN 4
+/* Number of free buffer table sets on the free set list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_OFST 20
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_LEN 4
+/* Number of chunks of fully-used clusters allocated to the MC for EVQ, RXQ and
+ * TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_OFST 24
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_LEN 4
+/* Number of chunks in partially-used clusters allocated to the MC for EVQ, RXQ
+ * and TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_OFST 28
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_LEN 4
+/* Number of buffer table sets (chunks) allocated to the host via
+ * MC_CMD_ALLOC_BUFTBL_CHUNK.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_OFST 32
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_LEN 4
+/* Maximum number of VIs per NIC. On EF10 this is the current value as used to
+ * size the Descriptor Cache in hardware.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_OFST 36
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_LEN 4
+
 /* CLIENT_HANDLE structuredef: A client is an abstract entity that can make
  * requests of the device and that can own resources managed by the device.
  * Examples of clients include PCIe functions and dynamic clients. A client
@@ -26684,8 +28177,8 @@
 
 /* SCHED_CREDIT_CHECK_RESULT structuredef */
 #define	SCHED_CREDIT_CHECK_RESULT_LEN 16
-/* The instance of the scheduler. Refer to XN-200389-AW for the location of
- * these schedulers in the hardware.
+/* The instance of the scheduler. Refer to XN-200389-AW (snic/hnic) and
+ * XN-200425-TC (cdx) for the location of these schedulers in the hardware.
  */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_OFST 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LEN 1
@@ -26697,6 +28190,18 @@
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_HOST_D 0x5 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_REPLAY 0x6 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_DMAC_H2C 0x7 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_B 0x8 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_REPLAY 0x9 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_ADAPTER_C2H_C 0xa /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A2_H2C_C 0xb /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A3_SOFT_ADAPTOR_C 0xc /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A4_DPU_WRITE_C 0xd /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_JRC_RRU 0xe /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_CDM_SINK 0xf /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PCIE_SINK 0x10 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_UPORT_SINK 0x11 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PSX_SINK 0x12 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A5_DPU_READ_C 0x13 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LBN 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_WIDTH 8
 /* The type of node that this result refers to. */
@@ -26706,6 +28211,10 @@
 #define	SCHED_CREDIT_CHECK_RESULT_DEST 0x0
 /* enum: Source node */
 #define	SCHED_CREDIT_CHECK_RESULT_SOURCE 0x1
+/* enum: Destination node credit type 1 (new to the Keystone schedulers, see
+ * SF-120268-TC)
+ */
+#define	SCHED_CREDIT_CHECK_RESULT_DEST_CREDIT1 0x2
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_LBN 8
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_WIDTH 8
 /* Level of node in scheduler hierarchy (level 0 is the bottom of the
@@ -27813,6 +29322,51 @@
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM 14
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM_MCDI2 62
 
+
+/***********************************/
+/* MC_CMD_TXQ_STATS
+ * Query per-TXQ statistics.
+ */
+#define	MC_CMD_TXQ_STATS 0x1d5
+#define	MC_CMD_TXQ_STATS_MSGSET 0x1d5
+#undef	MC_CMD_0x1d5_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1d5_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TXQ_STATS_IN msgrequest */
+#define	MC_CMD_TXQ_STATS_IN_LEN 8
+/* Instance of TXQ to retrieve statistics for */
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_OFST 0
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_LEN 4
+/* Flags for the request */
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_LEN 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_LBN 0
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_WIDTH 1
+
+/* MC_CMD_TXQ_STATS_OUT msgresponse */
+#define	MC_CMD_TXQ_STATS_OUT_LENMIN 0
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX 248
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX_MCDI2 1016
+#define	MC_CMD_TXQ_STATS_OUT_LEN(num) (0+8*(num))
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_NUM(len) (((len)-0)/8)
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LEN 8
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LBN 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_OFST 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LBN 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MINNUM 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM 31
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
+#define	MC_CMD_TXQ_STATS_CTPIO_MAX_FILL 0x0 /* enum */
+
 /* FUNCTION_PERSONALITY structuredef: The meanings of the personalities are
  * defined in SF-120734-TC with more information in SF-122717-TC.
  */
@@ -28296,6 +29850,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LBN 32
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_VF_OFST 2
@@ -28332,6 +29887,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_VF_OFST 6
@@ -28709,6 +30265,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_VF_OFST 6
@@ -28788,6 +30345,7 @@
 #define	DESC_PROXY_FUNC_MAP_FUNC_HI_WIDTH 32
 #define	DESC_PROXY_FUNC_MAP_FUNC_LBN 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_WIDTH 64
+/* See structuredef: PCIE_FUNCTION */
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_OFST 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LEN 2
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LBN 0
@@ -28851,6 +30409,27 @@
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM 4
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM_MCDI2 19
+/* See structuredef: DESC_PROXY_FUNC_MAP */
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LEN 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LBN 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LBN 64
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_OFST 6
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_OFST 12
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_OFST 16
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_LEN 40
 
 
 /***********************************/
@@ -29015,6 +30594,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM 63
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM_MCDI2 255
+/* See structuredef: QUEUE_ID */
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_REL_QUEUE_LBN 16
@@ -29082,6 +30662,7 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LEN 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LBN 64
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_VF_OFST 6
@@ -29162,6 +30743,7 @@
  * backwards compatibility only, callers should use PCIE_INTERFACE_CALLER.
  */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_PCIE_FUNCTION_INTF_NULL 0xffffffff
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_VF_OFST 6
@@ -29320,6 +30902,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LBN 1096
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_OFST 138
@@ -29333,10 +30916,12 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_WIDTH 8
+/* More generic alias for ENC_VLAN_FLAGS. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS_MASK alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_MASK_OFST 139
@@ -29350,6 +30935,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LBN 1112
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_WIDTH 8
+/* More generic alias for ENC_FLAGS_MASK. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LBN 1112
@@ -29503,6 +31089,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LBN 1152
@@ -29826,6 +31416,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LBN 1152
@@ -30120,7 +31714,7 @@
 /* MAE_MPORT_SELECTOR structuredef: MPORTS are identified by an opaque unsigned
  * integer value (mport_id) that is guaranteed to be representable within
  * 32-bits or within any NIC interface field that needs store the value
- * (whichever is narrowers). This selector structure provides a stable way to
+ * (whichever is narrower). This selector structure provides a stable way to
  * refer to m-ports.
  */
 #define	MAE_MPORT_SELECTOR_LEN 4
@@ -30195,10 +31789,22 @@
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
 /* MAE_LINK_ENDPOINT_SELECTOR structuredef: Structure that identifies a real or
- * virtual network port by MAE port and link end
+ * virtual network port by MAE port and link end. Intended to be used by
+ * network port MCDI commands. Setting FLAT to MAE_LINK_ENDPOINT_COMPAT is
+ * equivalent to using the previous version of the command. Not all possible
+ * combinations of MPORT_END and MPORT_SELECTOR in MAE_LINK_ENDPOINT_SELECTOR
+ * will work in all circumstances. 1. Some will always work (e.g. a VF can
+ * always address its logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC),
+ * 2. Some are not meaningful and will always fail with EINVAL (e.g. attempting
+ * to address the VNIC end of a link to a physical port), 3. Some are
+ * meaningful but require the MCDI client to have the required permission and
+ * fail with EPERM otherwise (e.g. trying to set the MAC on a VF the caller
+ * cannot administer), and 4. Some could be implementation-specific and fail
+ * with ENOTSUP if not available (no examples exist right now). See
+ * SF-123581-TC section 4.3 for more details.
  */
 #define	MAE_LINK_ENDPOINT_SELECTOR_LEN 8
-/* The MAE MPORT of interest */
+/* Identifier for the MAE MPORT of interest */
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_OFST 0
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LEN 4
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LBN 0
@@ -30395,6 +32001,90 @@
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_OFST 56
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_LEN 4
 
+/* MC_CMD_MAE_GET_CAPS_V3_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_LEN 64
+/* The number of field IDs that the NIC supports. Any field with a ID greater
+ * than or equal to the value returned in this field must be treated as having
+ * a support level of MAE_FIELD_UNSUPPORTED in all requests.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_LBN 3
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_WIDTH 1
+/* Deprecated alias for AR_COUNTERS. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_LEN 4
+/* The total number of AR counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_LEN 4
+/* The total number of counters lists available to allocate. A value of zero
+ * indicates that counter lists are not supported by the NIC. (But single
+ * counters may still be.)
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_LEN 4
+/* The number of priorities available for ACTION_RULE filters. It is invalid to
+ * install a MATCH_ACTION filter with a priority number >= ACTION_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_LEN 4
+/* The number of priorities available for OUTER_RULE filters. It is invalid to
+ * install an OUTER_RULE filter with a priority number >= OUTER_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_LEN 4
+/* MAE API major version. Currently 1. If this field is not present in the
+ * response (i.e. response shorter than 384 bits), then its value is zero. If
+ * the value does not match the client's expectations, the client should raise
+ * a fatal error.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_LEN 4
+/* Mask of supported counter types. Each bit position corresponds to a value of
+ * the MAE_COUNTER_TYPE enum. If this field is missing (i.e. V1 response),
+ * clients must assume that only AR counters are supported (i.e.
+ * COUNTER_TYPES_SUPPORTED==0x1). See also
+ * MC_CMD_MAE_COUNTERS_STREAM_START/COUNTER_TYPES_MASK.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_OFST 52
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_LEN 4
+/* The total number of conntrack counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_OFST 56
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_LEN 4
+/* The total number of Outer Rule counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_OFST 60
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_LEN 4
+
 
 /***********************************/
 /* MC_CMD_MAE_GET_AR_CAPS
@@ -30498,10 +32188,13 @@
 /* Generation count. Packets with generation count >= GENERATION_COUNT will
  * contain valid counter values for counter IDs allocated in this call, unless
  * the counter values are zero and zero squash is enabled. Note that there is
- * an independent GENERATION_COUNT object per counter type.
+ * an independent GENERATION_COUNT object per counter type, and that generation
+ * counts wrap from 0xffffffff to 1.
  */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* enum: Generation counter 0 is reserved and unused. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_INVALID 0x0
 /* The number of counter IDs that the NIC allocated. It is never less than 1;
  * failure to allocate a single counter will cause an error to be returned. It
  * is never greater than REQUESTED_COUNT, but may be less.
@@ -30516,6 +32209,8 @@
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2 253
 /* enum: A counter ID that is guaranteed never to represent a real counter */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL 0xffffffff
+/*            Other enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 
 
 /***********************************/
@@ -30577,7 +32272,8 @@
  * values will be written for these counters. If values for these counter IDs
  * are present, the counter ID has been reallocated. A counter ID will not be
  * reallocated within a single read cycle as this would merge increments from
- * the 'old' and 'new' counters.
+ * the 'old' and 'new' counters. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
@@ -30696,7 +32392,8 @@
 /* Generation count for AR counters. The final set of AR counter values will be
  * written out in packets with count == GENERATION_COUNT. An empty packet with
  * count > GENERATION_COUNT indicates that no more counter values of this type
- * will be written to this stream.
+ * will be written to this stream. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
@@ -30712,6 +32409,7 @@
  * final set of counter values will be written out in packets with count ==
  * GENERATION_COUNT. An empty packet with count > GENERATION_COUNT indicates
  * that no more counter values of this type will be written to this stream.
+ * GENERATION_COUNT_INVALID is reserved and unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_LEN 4
@@ -30960,6 +32658,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_LEN 2
@@ -30985,19 +32701,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31041,6 +32761,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_LEN 2
@@ -31066,19 +32804,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31131,6 +32873,172 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_LBN 6
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_WIDTH 1
 
+/* MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN msgrequest: Only supported if
+ * MAE_ACTION_SET_ALLOC_V3_SUPPORTED is advertised in
+ * MC_CMD_GET_CAPABILITIES_V10_OUT.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LEN 53
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_LBN 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_LBN 13
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_LBN 14
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_WIDTH 1
+/* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_LEN 2
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_LEN 4
+/* An m-port selector identifying the m-port that the modified packet should be
+ * delivered to. Set to MPORT_SELECTOR_NULL to request no delivery of the
+ * packet.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_OFST 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_LEN 4
+/* Allows an action set to trigger several counter updates. Set to
+ * MAE_COUNTER_ID_NULL to request no counter action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_OFST 24
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+/* If a driver only wished to update one counter within this action set, then
+ * it can supply a COUNTER_ID instead of allocating a single-element counter
+ * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * COUNTER_ID.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_OFST 28
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_OFST 32
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_LEN 4
+/* Set to MAC_ID_NULL to request no source MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_LEN 4
+/* Source m-port ID to be reported for DO_SET_SRC_MPORT action. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_OFST 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_LEN 4
+/* Actions for modifying the Differentiated Services Code-Point (DSCP) bits
+ * within IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_LEN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_WIDTH 6
+/* Actions for modifying the Explicit Congestion Notification (ECN) bits within
+ * IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_LBN 5
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_LBN 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_WIDTH 1
+/* Actions for overwriting CH_ROUTE subfields. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_WIDTH 1
+/* Override outgoing CH_VC to network port for DO_SET_NET_CHAN action. Cannot
+ * be used in conjunction with DO_SET_SRC_MPORT action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_OFST 52
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_LEN 1
+
 /* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
 /* The MSB of the AS_ID is guaranteed to be clear if the ID is not
@@ -31297,6 +33205,7 @@
  */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+/* Deprecated alias for ACTION_CONTROL. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_LEN 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_OFST 8
@@ -31307,15 +33216,26 @@
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_WIDTH 2
 /*             Enum values, see field(s): */
 /*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_LBN 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_WIDTH 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_LBN 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_WIDTH 16
-/* Reserved for future use. Must be set to zero. */
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_OFST 12
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_LEN 4
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_LEN 4
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_LEN 4
 /* Structure of the format MAE_ENC_FIELD_PAIRS. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_LEN 1
@@ -31367,6 +33287,59 @@
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM 32
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM_MCDI2 32
 
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_UPDATE
+ * Atomically change the response of an Outer Rule.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE 0x17d
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_MSGSET 0x17d
+#undef	MC_CMD_0x17d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x17d_PRIVILEGE_CTG SRIOV_CTG_MAE
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_LEN 16
+/* ID of outer rule to update */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_LEN 4
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_LBN 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_LBN 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_WIDTH 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_LBN 16
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_WIDTH 16
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_LEN 4
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_OUT_LEN 0
+
 /* MAE_ACTION_RULE_RESPONSE structuredef */
 #define	MAE_ACTION_RULE_RESPONSE_LEN 16
 #define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
@@ -31932,6 +33905,7 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_OFST 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_LBN 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_WIDTH 1
+/* The number of MAE_MPORT_DESC structures in MPORT_DESC_DATA. May be zero. */
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_OFST 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_LEN 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC_OFST 8
@@ -31946,4 +33920,407 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM 240
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1008
 
+/* TABLE_FIELD_DESCR structuredef: An individual table field descriptor. This
+ * describes the location and properties of one N-bit field within a wider
+ * M-bit key/mask/response value.
+ */
+#define	TABLE_FIELD_DESCR_LEN 8
+/* Identifier for this field. */
+#define	TABLE_FIELD_DESCR_FIELD_ID_OFST 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_LEN 2
+/*            Enum values, see field(s): */
+/*               TABLE_FIELD_ID */
+#define	TABLE_FIELD_DESCR_FIELD_ID_LBN 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_WIDTH 16
+/* Lowest (least significant) bit number of the bits of this field. */
+#define	TABLE_FIELD_DESCR_LBN_OFST 2
+#define	TABLE_FIELD_DESCR_LBN_LEN 2
+#define	TABLE_FIELD_DESCR_LBN_LBN 16
+#define	TABLE_FIELD_DESCR_LBN_WIDTH 16
+/* Width of this field in bits. */
+#define	TABLE_FIELD_DESCR_WIDTH_OFST 4
+#define	TABLE_FIELD_DESCR_WIDTH_LEN 2
+#define	TABLE_FIELD_DESCR_WIDTH_LBN 32
+#define	TABLE_FIELD_DESCR_WIDTH_WIDTH 16
+/* The mask type for this field. (Note that masking is relevant to keys; fields
+ * of responses are always reported with the EXACT type.)
+ */
+#define	TABLE_FIELD_DESCR_MASK_TYPE_OFST 6
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LEN 1
+/* enum: Field must never be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_NEVER 0x0
+/* enum: Exact match: field must always be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_EXACT 0x1
+/* enum: Ternary match: arbitrary mask bits are allowed. */
+#define	TABLE_FIELD_DESCR_MASK_TERNARY 0x2
+/* enum: Whole field match: mask must be all 1 bits, or all 0 bits. */
+#define	TABLE_FIELD_DESCR_MASK_WHOLE_FIELD 0x3
+/* enum: Longest prefix match: mask must be 1 bit(s) followed by 0 bit(s). */
+#define	TABLE_FIELD_DESCR_MASK_LPM 0x4
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LBN 48
+#define	TABLE_FIELD_DESCR_MASK_TYPE_WIDTH 8
+/* A version code that allows field semantics to be extended. All fields
+ * currently use version 0.
+ */
+#define	TABLE_FIELD_DESCR_SCHEME_OFST 7
+#define	TABLE_FIELD_DESCR_SCHEME_LEN 1
+#define	TABLE_FIELD_DESCR_SCHEME_LBN 56
+#define	TABLE_FIELD_DESCR_SCHEME_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_TABLE_LIST
+ * Return the list of tables which may be accessed via this table API.
+ */
+#define	MC_CMD_TABLE_LIST 0x1c9
+#define	MC_CMD_TABLE_LIST_MSGSET 0x1c9
+#undef	MC_CMD_0x1c9_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1c9_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_LIST_IN msgrequest */
+#define	MC_CMD_TABLE_LIST_IN_LEN 4
+/* Index of the first item to be returned in the TABLE_ID sequence. (Set to 0
+ * for the first call; further calls are only required if the whole sequence
+ * does not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_OFST 0
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_LEN 4
+
+/* MC_CMD_TABLE_LIST_OUT msgresponse */
+#define	MC_CMD_TABLE_LIST_OUT_LENMIN 4
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX 252
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_LIST_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(len) (((len)-4)/4)
+/* The total number of tables. */
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_OFST 0
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_LEN 4
+/* A sequence of table identifiers. If all N_TABLES items do not fit, further
+ * items can be obtained by repeating the call with a non-zero
+ * FIRST_TABLE_ID_INDEX.
+ */
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_OFST 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_LEN 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MINNUM 0
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM 62
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM_MCDI2 254
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+
+
+/***********************************/
+/* MC_CMD_TABLE_DESCRIPTOR
+ * Request the table descriptor for a particular table. This describes
+ * properties of the table and the format of the key and response. May return
+ * EINVAL for unknown table ID.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR 0x1ca
+#define	MC_CMD_TABLE_DESCRIPTOR_MSGSET 0x1ca
+#undef	MC_CMD_0x1ca_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ca_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DESCRIPTOR_IN msgrequest */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_LEN 8
+/* Identifier for this field. */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Index of the first item to be returned in the FIELDS sequence. (Set to 0 for
+ * the first call; further calls are only required if the whole sequence does
+ * not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_LEN 4
+
+/* MC_CMD_TABLE_DESCRIPTOR_OUT msgresponse */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN 28
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX 252
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(num) (20+8*(num))
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(len) (((len)-20)/8)
+/* Maximum number of entries in this table. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_LEN 4
+/* The type of table. (This is really just informational; the important
+ * properties of a table that affect programming can be deduced from other
+ * items in the table or field descriptor.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_LEN 2
+/* enum: Direct table (essentially just an array). Behaves like a BCAM for
+ * programming purposes, where the fact that the key is actually used as an
+ * array index is really just an implementation detail.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_DIRECT 0x1
+/* enum: BCAM (binary CAM) table: exact match on all key fields." */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM 0x2
+/* enum: TCAM (ternary CAM) table: matches fields with a mask. Each entry may
+ * have its own different mask.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_TCAM 0x3
+/* enum: STCAM (semi-TCAM) table: like a TCAM but entries shared a limited
+ * number of unique masks.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_STCAM 0x4
+/* Width of key (and corresponding mask, for TCAM or STCAM) in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_LEN 2
+/* Width of response in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_LEN 2
+/* The total number of fields in the key. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_OFST 10
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_LEN 2
+/* The total number of fields in the response. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_OFST 12
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_LEN 2
+/* Number of priorities for STCAM or TCAM; otherwise 0. The priority of a table
+ * entry (relevant when more than one masked entry matches) ranges from
+ * 0=highest to N_PRIORITIES-1=lowest.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_OFST 14
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_LEN 2
+/* Maximum number of masks for STCAM; otherwise 0. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_OFST 16
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_LEN 2
+/* Flags. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_LEN 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_LBN 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_WIDTH 1
+/* Access scheme version code, allowing the method of accessing table entries
+ * to change semantics in future. A client which does not understand the value
+ * of this field should assume that it cannot program this table. Currently
+ * always set to 0 indicating the original MC_CMD_TABLE_INSERT/UPDATE/DELETE
+ * semantics.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_OFST 19
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_LEN 1
+/* A sequence of TABLE_FIELD_DESCR structures: N_KEY_FIELDS items describing
+ * the key, followed by N_RESP_FIELDS items describing the response. If all
+ * N_KEY_FIELDS+N_RESP_FIELDS items do not fit, further items can be obtained
+ * by repeating the call with a non-zero FIRST_FIELDS_INDEX.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LEN 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LBN 160
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_OFST 24
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LBN 192
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MINNUM 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM 29
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM_MCDI2 125
+
+
+/***********************************/
+/* MC_CMD_TABLE_INSERT
+ * Insert a new entry into a table. The entry must not currently exist. May
+ * return EINVAL for unknown table ID or other bad request parameters, EEXIST
+ * if the entry already exists, ENOSPC if there is no space or EPERM if the
+ * operation is not permitted. In case of an error, the additional MCDI error
+ * argument field returns the raw error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_INSERT 0x1cd
+#define	MC_CMD_TABLE_INSERT_MSGSET 0x1cd
+#undef	MC_CMD_0x1cd_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cd_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_INSERT_IN msgrequest */
+#define	MC_CMD_TABLE_INSERT_IN_LENMIN 16
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX 252
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_INSERT_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_INSERT_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_INSERT_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_INSERT_OUT msgresponse */
+#define	MC_CMD_TABLE_INSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_UPDATE
+ * Update an existing entry in a table with a new response value. May return
+ * EINVAL for unknown table ID or other bad request parameters, ENOENT if the
+ * entry does not already exist, or EPERM if the operation is not permitted. In
+ * case of an error, the additional MCDI error argument field returns the raw
+ * error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_UPDATE 0x1ce
+#define	MC_CMD_TABLE_UPDATE_MSGSET 0x1ce
+#undef	MC_CMD_0x1ce_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ce_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_UPDATE_IN msgrequest */
+#define	MC_CMD_TABLE_UPDATE_IN_LENMIN 16
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX 252
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_UPDATE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_UPDATE_OUT msgresponse */
+#define	MC_CMD_TABLE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_DELETE
+ * Delete an existing entry in a table. May return EINVAL for unknown table ID
+ * or other bad request parameters, ENOENT if the entry does not exist, or
+ * EPERM if the operation is not permitted. In case of an error, the additional
+ * MCDI error argument field returns the raw error code from the underlying CAM
+ * driver.
+ */
+#define	MC_CMD_TABLE_DELETE 0x1cf
+#define	MC_CMD_TABLE_DELETE_MSGSET 0x1cf
+#undef	MC_CMD_0x1cf_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cf_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DELETE_IN msgrequest */
+#define	MC_CMD_TABLE_DELETE_IN_LENMIN 16
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX 252
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DELETE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_DELETE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_DELETE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_DELETE_OUT msgresponse */
+#define	MC_CMD_TABLE_DELETE_OUT_LEN 0
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 02/34] common/sfc_efx/base: detect MCDI Table Access API support
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-01 19:55 ` [PATCH 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Future patches will add an implementation of MCDI Table
Access API in libefx. This patch adds a way to determine
if this API is supported.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h          | 2 ++
 drivers/common/sfc_efx/base/hunt_nic.c     | 2 ++
 drivers/common/sfc_efx/base/medford2_nic.c | 2 ++
 drivers/common/sfc_efx/base/medford_nic.c  | 2 ++
 drivers/common/sfc_efx/base/rhead_nic.c    | 9 +++++++++
 drivers/common/sfc_efx/base/siena_nic.c    | 2 ++
 6 files changed, 19 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 49e29dcc1c..f9b090e35e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1672,6 +1672,8 @@ typedef struct efx_nic_cfg_s {
 	boolean_t		enc_mae_admin;
 	/* NIC support for MAE action set v2 features. */
 	boolean_t		enc_mae_aset_v2_supported;
+	/* NIC support for MCDI Table Access API. */
+	boolean_t		enc_table_api_supported;
 	/* Firmware support for "FLAG" and "MARK" filter actions */
 	boolean_t		enc_filter_action_flag_supported;
 	boolean_t		enc_filter_action_mark_supported;
diff --git a/drivers/common/sfc_efx/base/hunt_nic.c b/drivers/common/sfc_efx/base/hunt_nic.c
index 08ae324482..04595a39c8 100644
--- a/drivers/common/sfc_efx/base/hunt_nic.c
+++ b/drivers/common/sfc_efx/base/hunt_nic.c
@@ -192,6 +192,8 @@ hunt_board_cfg(
 	/* All Huntington devices have a PCIe Gen3, 8 lane connector */
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford2_nic.c b/drivers/common/sfc_efx/base/medford2_nic.c
index 6d19524573..49adabffb2 100644
--- a/drivers/common/sfc_efx/base/medford2_nic.c
+++ b/drivers/common/sfc_efx/base/medford2_nic.c
@@ -152,6 +152,8 @@ medford2_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford_nic.c b/drivers/common/sfc_efx/base/medford_nic.c
index b111e3eded..9a460b2b9b 100644
--- a/drivers/common/sfc_efx/base/medford_nic.c
+++ b/drivers/common/sfc_efx/base/medford_nic.c
@@ -150,6 +150,8 @@ medford_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index eda6c1c4f9..a773aea38d 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -176,6 +176,15 @@ rhead_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	/*
+	 * FIXME: MCDI table API support depends on an EF100 firmware build
+	 * and an EF100 platform. It should be discovered by using a capability
+	 * flag from MCDI that is not implemented yet.
+	 * Right now we can safely rely on the return code from the libefx
+	 * MCDI Table API.
+	 */
+	encp->enc_table_api_supported = B_TRUE;
+
 	return (0);
 
 fail3:
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 9f14faf271..1f1fb7d2af 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -205,6 +205,8 @@ siena_board_cfg(
 	encp->enc_mae_supported = B_FALSE;
 	encp->enc_mae_admin = B_FALSE;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
 
 	return (0);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-01 19:55 ` [PATCH 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
  2023-06-01 19:55 ` [PATCH 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

New MCDI Table Access API allows management of
the HW tables' content.
This part of API helps to list all supported tables.
In the near future, only the CT table is planned
to be used, so only one identifier for this table
was added to the efx.
New table IDs will be added as needed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 15 ++++
 drivers/common/sfc_efx/base/efx_table.c | 94 +++++++++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build |  1 +
 drivers/common/sfc_efx/version.map      |  2 +
 4 files changed, 112 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f9b090e35e..ac6b58b2a4 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5084,6 +5084,21 @@ efx_nic_dma_map(
 	__in		size_t len,
 	__out		efsys_dma_addr_t *nic_addrp);
 
+/* Unique IDs for HW tables */
+typedef enum efx_table_id_e {
+	EFX_TABLE_ID_CONNTRACK = 0x10300,
+} efx_table_id_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
new file mode 100644
index 0000000000..7cfdfea36e
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_LIST_IN_LEN,
+	    MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table IDs */
+	EFX_STATIC_ASSERT(EFX_TABLE_ID_CONNTRACK == TABLE_ID_CONNTRACK_TABLE);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((n_table_ids != 0) &&
+	   ((table_ids == NULL) || (n_table_ids_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_LIST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_LIST_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, entry_ofst);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_LIST_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	if (total_n_tablesp != NULL)
+		*total_n_tablesp = MCDI_OUT_DWORD(req, TABLE_LIST_OUT_N_TABLES);
+
+	n_entries = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(req.emr_out_length_used);
+
+	if (table_ids != NULL) {
+		if (n_entries > n_table_ids) {
+			rc = ENOMEM;
+			goto fail5;
+		}
+
+		for (i = 0; i < n_entries; i++) {
+			table_ids[i] = MCDI_OUT_INDEXED_DWORD(req,
+			    TABLE_LIST_OUT_TABLE_ID, i);
+		}
+	}
+
+	if (n_table_ids_writtenp != NULL)
+		*n_table_ids_writtenp = n_entries;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index ff7f33fb44..7fc04aa57b 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -16,6 +16,7 @@ sources = [
         'efx_lic.c',
         'efx_mac.c',
         'efx_mae.c',
+        'efx_table.c',
         'efx_mcdi.c',
         'efx_mon.c',
         'efx_nic.c',
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d9b04a611d..7c92c1ae09 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,8 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_list;
+
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
 	efx_tunnel_config_udp_remove;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 04/34] common/sfc_efx/base: add macro to get indexed QWORD field
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (2 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Extend MCDI macros to manipulate with fields in indexed QWORDs.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
---
 drivers/common/sfc_efx/base/efx_mcdi.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 14a3833567..f13bf43da6 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -504,6 +504,10 @@ efx_mcdi_set_nic_addr_regions(
 	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
 			(_idx)), _field)
 
+#define	MCDI_OUT_INDEXED_QWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_QWORD_FIELD(*(MCDI_OUT2(_emr, efx_qword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, _type, _arr_ofst, _idx,	\
 		_member_ofst)						\
 	((_type *)(MCDI_OUT2(_emr, uint8_t, _arr_ofst) +		\
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (3 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
                   ` (31 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Table's descriptor and fields' descriptors can be taken
by table ID using a new API.
In the near future, only the CT table is planned
to be used, so only fields that are required for these
purposes were added to the efx.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       |  67 +++++++
 drivers/common/sfc_efx/base/efx_table.c | 256 ++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |   3 +
 3 files changed, 326 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ac6b58b2a4..cf157e17d6 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5099,6 +5099,73 @@ efx_table_list(
 	__in					unsigned int n_table_ids,
 	__out_opt				unsigned int *n_table_ids_writtenp);
 
+LIBEFX_API
+extern	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void);
+
+LIBEFX_API
+extern	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id);
+
+/* Unique IDs for table fields */
+typedef enum efx_table_field_id_e {
+	EFX_TABLE_FIELD_ID_UNUSED = 0x0,
+	EFX_TABLE_FIELD_ID_COUNTER_ID = 0xa,
+	EFX_TABLE_FIELD_ID_ETHER_TYPE = 0x1c,
+	EFX_TABLE_FIELD_ID_SRC_IP = 0x1d,
+	EFX_TABLE_FIELD_ID_DST_IP = 0x1e,
+	EFX_TABLE_FIELD_ID_IP_PROTO = 0x20,
+	EFX_TABLE_FIELD_ID_SRC_PORT = 0x21,
+	EFX_TABLE_FIELD_ID_DST_PORT = 0x22,
+	EFX_TABLE_FIELD_ID_NAT_PORT = 0x7a,
+	EFX_TABLE_FIELD_ID_NAT_IP = 0x7b,
+	EFX_TABLE_FIELD_ID_NAT_DIR = 0x7c,
+	EFX_TABLE_FIELD_ID_CT_MARK = 0x7d,
+} efx_table_field_id_t;
+
+/* Table fields mask types */
+typedef enum efx_table_field_mask_type_e {
+	EFX_TABLE_FIELD_MASK_NEVER = 0x0,
+	EFX_TABLE_FIELD_MASK_EXACT = 0x1,
+} efx_table_field_mask_type_t;
+
+typedef struct efx_table_field_desc_s {
+	efx_table_field_id_t		field_id;
+	uint16_t			lbn;
+	uint16_t			width;
+	efx_table_field_mask_type_t	mask_type;
+	uint8_t				scheme;
+} efx_table_field_descriptor_t;
+
+/* Types of HW tables */
+typedef enum efx_table_type_e {
+	/* Exact match to all key fields of table entry. */
+	EFX_TABLE_TYPE_BCAM = 0x2,
+} efx_table_type_t;
+
+typedef struct efx_table_descriptor_s {
+	efx_table_type_t	type;
+	uint16_t		key_width;
+	uint16_t		resp_width;
+	/* Number of key's fields to match data */
+	uint16_t		n_key_fields;
+	/* Number of fields in match response */
+	uint16_t		n_resp_fields;
+} efx_table_descriptor_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(*n_fields_descsp)	efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 7cfdfea36e..115d86502f 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -6,6 +6,11 @@
 #include "efx.h"
 #include "efx_impl.h"
 
+/* List of HW tables that have support in efx */
+static const efx_table_id_t efx_supported_table_ids[] = {
+	EFX_TABLE_ID_CONNTRACK,
+};
+
 	__checkReturn				efx_rc_t
 efx_table_list(
 	__in					efx_nic_t *enp,
@@ -80,6 +85,257 @@ efx_table_list(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void)
+{
+	return EFX_ARRAY_SIZE(efx_supported_table_ids);
+}
+
+	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id)
+{
+	size_t i;
+
+	for (i = 0; i < efx_table_supported_num_get(); i++) {
+		if (efx_supported_table_ids[i] == table_id)
+			return B_TRUE;
+	}
+
+	return B_FALSE;
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_ct_desc_fields_check(
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+	efx_rc_t rc;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		switch (fields_descsp[i].field_id) {
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+		case EFX_TABLE_FIELD_ID_DST_IP:
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
+				rc = EINVAL;
+				goto fail1;
+			}
+			break;
+		/*
+		 * TODO:
+		 * All fields in the CT table have EXACT mask.
+		 * All the response field descriptors must have the EXACT mask.
+		 * In the current implementation, only the Ethertype, source and
+		 * destination IP address, IP protocol, and source and destination IP
+		 * are used for the lookup by the key.
+		 * FW could use the NEVER mask for the fields in the key that are not
+		 * used for the lookup.
+		 * As an alternative, a new mask could be added for these fields,
+		 * like EXACT_NOT_USED.
+		 */
+		default:
+			if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
+			    (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
+				rc = EINVAL;
+				goto fail2;
+			}
+			break;
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_desc_fields_check(
+	__in				efx_table_id_t table_id,
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	efx_rc_t rc;
+
+	switch (table_id) {
+	case EFX_TABLE_ID_CONNTRACK:
+		rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
+		if (rc != 0)
+			goto fail1;
+		break;
+	default:
+		break;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static					void
+efx_table_desc_fields_get(
+	__in				const efx_mcdi_req_t *req,
+	__out_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		fields_descsp[i].field_id = (efx_table_field_id_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
+
+		fields_descsp[i].lbn =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
+
+		fields_descsp[i].width =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
+
+		fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
+
+		fields_descsp[i].scheme =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
+	}
+}
+
+	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
+	    MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table types */
+	EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
+
+	/* Ensure EFX and MCDI use same values for table fields */
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (!efx_table_is_supported(table_id)) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((n_field_descs != 0) &&
+	    ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	if (table_descp != NULL) {
+		table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_TYPE);
+		table_descp->key_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
+		table_descp->resp_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
+		table_descp->n_key_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
+		table_descp->n_resp_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
+	}
+
+	n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
+
+	if (fields_descs != NULL) {
+		if (n_entries > n_field_descs) {
+			rc = ENOMEM;
+			goto fail6;
+		}
+
+		efx_table_desc_fields_get(&req, fields_descs, n_entries);
+		rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
+		if (rc != 0)
+			goto fail7;
+	}
+
+	if (n_field_descs_writtenp != NULL)
+		*n_field_descs_writtenp = n_entries;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 7c92c1ae09..189dd4fdaf 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,7 +233,10 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_describe;
+	efx_table_is_supported;
 	efx_table_list;
+	efx_table_supported_num_get;
 
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 06/34] common/sfc_efx/base: add API to insert data to HW table
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (4 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to insert data to any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 16 +++++
 drivers/common/sfc_efx/base/efx_table.c | 79 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 96 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cf157e17d6..1683d8ce7b 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5166,6 +5166,22 @@ efx_table_describe(
 	__in					unsigned int n_field_descs,
 	__out_opt				unsigned int *n_field_descs_writtenp);
 
+/* Maximum possible size of data for manipulation of the tables */
+#define EFX_TABLE_ENTRY_LENGTH_MAX	1008
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 115d86502f..63fc319666 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -338,6 +338,85 @@ efx_table_describe(
 	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_INSERT_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_INSERT_IN_LENMAX  * sizeof(uint32_t)) ==
+	    EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_INSERT_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_INSERT_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_INSERT_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_PRIORITY, priority);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_WIDTH, mask_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_RESP_WIDTH, resp_width);
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_INSERT_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 189dd4fdaf..f6a2003c3e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -234,6 +234,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
 	efx_table_supported_num_get;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 07/34] common/sfc_efx/base: add API to delete entry from HW table
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (5 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to delete entry from any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 11 ++++
 drivers/common/sfc_efx/base/efx_table.c | 77 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 89 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 1683d8ce7b..cdf8a99abf 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5182,6 +5182,17 @@ efx_table_entry_insert(
 	__in_bcount(data_size)		uint8_t *entry_datap,
 	__in				unsigned int data_size);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 63fc319666..10a1c2ddcd 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -419,6 +419,83 @@ efx_table_entry_insert(
 
 fail4:
 	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_DELETE_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_DELETE_IN_LENMAX  * sizeof(uint32_t)) ==
+		EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DELETE_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DELETE_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DELETE_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_WIDTH, mask_width);
+
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_DELETE_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f6a2003c3e..b596369c48 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -234,6 +234,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_delete;
 	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 08/34] net/sfc: add MCDI wrappers for BCAM tables
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (6 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

A "table" is structure used for lookups, consisting of a set of
entries which can be matched against an N-bit "request", to
return either a "hit" with an M-bit "response", or a "miss" if
there is no match. There are a number of HW tables of various
types that could be used in MAE.

In some types of table the entry may also be associated with an
N-bit "mask", allowing some bits of the request to be treated as
don't-care, and an integer "priority" to determine which entry is
used if more than one matches.

BCAM tables don't support "mask" and "priority", so the
corresponding fields must be zeroed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_tbls.h | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.h

diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
new file mode 100644
index 0000000000..2a5c87b82c
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBLS_H
+#define _SFC_TBLS_H
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Table types:
+ *   CAM - Content addressable memory
+ *  BCAM - Binary CAM
+ *  TCAM - Ternary CAM
+ * STCAM - Semi-ternary CAM
+ *
+ * Short description:
+ * TCAM:  Each entry has a key, mask, response and priority. An entry matches
+ *        when (key & mask) == (request & mask). In the case of multiple
+ *        matches, the entry with the highest priority wins; Each entry may
+ *        have its own mask, but TCAM table definitions may place constraints
+ *        on the possible masks allowed for each of the individual fields.
+ * STCAM: A limited form of TCAM in which only a limited number of masks and
+ *        associated priorities), up to some maximum fixed by the definition
+ *        of the table, may be in use at any one time.
+ * BCAM:  Each entry has only a key and response, with the whole request
+ *        matched against the key (like a typical hash table or "map").
+ * Direct (sometimes "DCAM", although it's not really content-addressable):
+ *        Essentially just an array, where the key bits are used simply as an
+ *        index.
+ */
+
+/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
+#define SFC_TBLS_BCAM_PRIORITY		0
+
+/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
+#define SFC_TBLS_BCAM_MASK_ID		0
+
+/* Mask is used only for STCAM */
+#define SFC_TBLS_BCAM_MASK_WIDTH	0
+
+static inline int
+sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
+				      SFC_TBLS_BCAM_MASK_ID, key_width,
+				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
+				      data, data_size);
+}
+
+static inline int
+sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
+				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
+				      data, data_size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_TBLS_H */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 09/34] net/sfc: add functions to manipulate MCDI table fields
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (7 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 10/34] net/sfc: attach to HW table API Ivan Malov
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Implemented functions that help to fill user data for
manipulation with HW tables in the required format.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |   1 +
 drivers/net/sfc/sfc_tbls.c  | 140 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbls.h  | 135 ++++++++++++++++++++++++++++++++++
 3 files changed, 276 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.c

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c2d8430810..39c7f24764 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -87,6 +87,7 @@ sources = files(
         'sfc_tso.c',
         'sfc_filter.c',
         'sfc_switch.c',
+        'sfc_tbls.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
new file mode 100644
index 0000000000..db54fc0d40
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc_tbls.h"
+#include "sfc_debug.h"
+
+#include <rte_ip.h>
+
+/* Number of bits in uint32_t type */
+#define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
+
+static uint32_t
+sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t mask;
+
+	if (width == SFC_TBLS_U32_BITS)
+		return value;
+
+	mask = RTE_LEN2MASK(width, uint32_t);
+	value &= mask;
+
+	if (lbn != 0) {
+		mask <<= lbn;
+		value <<= lbn;
+	}
+
+	return (in & (~mask)) | value;
+}
+
+void
+sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	if (lbn + width <= SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, lbn, width, value);
+	} else {
+		*data = sfc_tbls_field_update(*data, lbn,
+					      SFC_TBLS_U32_BITS - lbn, value);
+		value >>= SFC_TBLS_U32_BITS - lbn;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+		*data = sfc_tbls_field_update(*data, 0,
+					      width + lbn - SFC_TBLS_U32_BITS,
+					      value);
+	}
+}
+
+void
+sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, uint16_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      uint16_t width, uint8_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      __rte_unused uint16_t width, const uint32_t *ip)
+{
+	unsigned int i;
+	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
+
+	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
+
+	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
+		sfc_tbls_field_set_u32(data, data_size, lbn,
+				       SFC_TBLS_U32_BITS, ip[i]);
+		lbn += SFC_TBLS_U32_BITS;
+	}
+}
+
+void
+sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint64_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
+	value >>= SFC_TBLS_U32_BITS - lbn;
+	width -= SFC_TBLS_U32_BITS - lbn;
+
+	data_offset++;
+	SFC_ASSERT(data_offset < data_size);
+
+	data++;
+
+	if (width > SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
+		value >>= SFC_TBLS_U32_BITS;
+		width -= SFC_TBLS_U32_BITS;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+	}
+
+	*data = sfc_tbls_field_update(*data, 0, width, value);
+}
+
+void
+sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, bool value)
+{
+	SFC_ASSERT(width == 1);
+
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
+}
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 2a5c87b82c..7b6bb5b341 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -63,6 +63,141 @@ sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key
 				      data, data_size);
 }
 
+/**
+ * All manipulations with HW tables entries require forming
+ * a key and response.
+ * The key and response fields follow, consecutively, each
+ * packed as follows:
+ *  - the key/response is logically treated as a single wide N-bit value;
+ *  - fields have been placed in these logical values per the "lbn" and "width"
+ *    information from the table field descriptors;
+ *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
+ *  - the values are put into the table op request with bits[31:0] of the wide
+ *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
+ *
+ * Below is an API that helps to form  MCDI insertion/deletion request.
+ * Workflow:
+ * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
+ * 2) Read a descriptor of the table that you want to use.
+ * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
+ *    Each field of the key has LBN and width. This information can be
+ *    found in a field's descriptor.
+ * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
+ *    must start. It's required as the key and response need to be
+ *    zero-padded at the MSB end to multiples of 32 bits.
+ * 5) Fill the response the same way.
+ * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
+ *    It will help you to get the real size of the data request.
+ */
+
+/**
+ * Get a pointer to the beginning of the next 32-bit wide fields
+ * that go after a given width.
+ * It should be used to get a pointer to the response's start and the end
+ * of the data for an MCDI request.
+ *
+ * @param data		Pointer to the data to make an offset from
+ * @param width		Width of fields to offset
+ *
+ * @note @p width is expected to be a key's or response's size.
+ *
+ * @return Pointer to the beginning of the next field.
+ */
+static inline uint32_t *
+sfc_tbls_next_req_fields(uint32_t *data, uint16_t width) {
+	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
+}
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint32_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint32_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint16_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint16_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint8_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, uint8_t value);
+
+/**
+ * Insert IP address into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param ip		IP address to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, const uint32_t *ip);
+
+/**
+ * Insert value into a field in the data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint64_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint64_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		Bit value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, bool value);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 10/34] net/sfc: attach to HW table API
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (8 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The patch adds APIs to initialise, manipulate and finalise
HW tables API-specific context in NIC control structure.
The context itself will be used to store HW tables-related info,
like table descriptors and field descriptors.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build          |   4 +-
 drivers/net/sfc/sfc.c                |  18 +-
 drivers/net/sfc/sfc.h                |   2 +
 drivers/net/sfc/sfc_tbl_meta.c       |  71 ++++++++
 drivers/net/sfc/sfc_tbl_meta.h       |  37 ++++
 drivers/net/sfc/sfc_tbl_meta_cache.c | 253 +++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbl_meta_cache.h |  25 +++
 drivers/net/sfc/sfc_tbls.c           |  60 +++++++
 drivers/net/sfc/sfc_tbls.h           |  81 +++++++++
 9 files changed, 549 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 39c7f24764..c9d4264674 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -71,7 +71,7 @@ if not cc.links(atomic_check_code)
     ext_deps += libatomic_dep
 endif
 
-deps += ['common_sfc_efx', 'bus_pci']
+deps += ['common_sfc_efx', 'bus_pci', 'hash']
 sources = files(
         'sfc_ethdev.c',
         'sfc_kvargs.c',
@@ -88,6 +88,8 @@ sources = files(
         'sfc_filter.c',
         'sfc_switch.c',
         'sfc_tbls.c',
+        'sfc_tbl_meta.c',
+        'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 22753e3417..a56521696a 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -491,6 +491,10 @@ sfc_try_start(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_ev_start;
 
+	rc = sfc_tbls_start(sa);
+	if (rc != 0)
+		goto fail_tbls_start;
+
 	rc = sfc_port_start(sa);
 	if (rc != 0)
 		goto fail_port_start;
@@ -526,9 +530,12 @@ sfc_try_start(struct sfc_adapter *sa)
 fail_rx_start:
 	sfc_port_stop(sa);
 
-fail_port_start:
+fail_tbls_start:
 	sfc_ev_stop(sa);
 
+fail_port_start:
+	sfc_tbls_stop(sa);
+
 fail_ev_start:
 	sfc_intr_stop(sa);
 
@@ -626,6 +633,7 @@ sfc_stop(struct sfc_adapter *sa)
 	sfc_tx_stop(sa);
 	sfc_rx_stop(sa);
 	sfc_port_stop(sa);
+	sfc_tbls_stop(sa);
 	sfc_ev_stop(sa);
 	sfc_intr_stop(sa);
 	efx_nic_fini(sa->nic);
@@ -983,6 +991,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_attach;
 
+	rc = sfc_tbls_attach(sa);
+	if (rc != 0)
+		goto fail_tables_attach;
+
 	rc = sfc_mae_switchdev_init(sa);
 	if (rc != 0)
 		goto fail_mae_switchdev_init;
@@ -1025,6 +1037,9 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_mae_switchdev_fini(sa);
 
 fail_mae_switchdev_init:
+	sfc_tbls_detach(sa);
+
+fail_tables_attach:
 	sfc_mae_detach(sa);
 
 fail_mae_attach:
@@ -1088,6 +1103,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
+	sfc_tbls_detach(sa);
 	sfc_mae_detach(sa);
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 730d054aea..6b301aad60 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -31,6 +31,7 @@
 #include "sfc_flow_tunnel.h"
 #include "sfc_sriov.h"
 #include "sfc_mae.h"
+#include "sfc_tbls.h"
 #include "sfc_dp.h"
 #include "sfc_sw_stats.h"
 #include "sfc_repr_proxy.h"
@@ -244,6 +245,7 @@ struct sfc_adapter {
 	struct sfc_ft_ctx		ft_ctx_pool[SFC_FT_MAX_NTUNNELS];
 	struct sfc_filter		filter;
 	struct sfc_mae			mae;
+	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
 	struct sfc_flow_list		flow_list;
diff --git a/drivers/net/sfc/sfc_tbl_meta.c b/drivers/net/sfc/sfc_tbl_meta.c
new file mode 100644
index 0000000000..997082fd74
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_tbl_meta.h"
+#include "sfc_tbl_meta_cache.h"
+
+const struct sfc_tbl_meta *
+sfc_tbl_meta_lookup(struct sfc_adapter *sa, efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta;
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return NULL;
+
+	rc = rte_hash_lookup_data(tables->meta.cache, (const void *)&table_id,
+				  (void **)&meta);
+	if (rc < 0)
+		return NULL;
+
+	SFC_ASSERT(meta != NULL);
+	SFC_ASSERT(meta->table_id == table_id);
+
+	return meta;
+}
+
+int
+sfc_tbl_meta_init(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return 0;
+
+	rc = sfc_tbl_meta_cache_ctor(&meta->cache);
+	if (rc != 0)
+		return rc;
+
+	rc = sfc_tbl_meta_cache_update(meta->cache, sa->nic);
+	if (rc != 0) {
+		sfc_tbl_meta_cache_dtor(&meta->cache);
+		return rc;
+	}
+
+	return 0;
+}
+
+void
+sfc_tbl_meta_fini(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+
+	if (meta->cache == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(tables->status == SFC_TBLS_STATUS_SUPPORTED);
+
+	sfc_tbl_meta_cache_dtor(&meta->cache);
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta.h b/drivers/net/sfc/sfc_tbl_meta.h
new file mode 100644
index 0000000000..7d39957514
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_H
+#define _SFC_TBL_META_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Metadata about table layout */
+struct sfc_tbl_meta {
+	efx_table_id_t			table_id;
+	efx_table_descriptor_t		descriptor;
+	efx_table_field_descriptor_t	*keys;
+	efx_table_field_descriptor_t	*responses;
+};
+
+struct sfc_tbl_meta_cache {
+	struct rte_hash	*cache;
+};
+
+struct sfc_adapter;
+
+const struct sfc_tbl_meta *sfc_tbl_meta_lookup(struct sfc_adapter *sa,
+					       efx_table_id_t table_id);
+
+int sfc_tbl_meta_init(struct sfc_adapter *sa);
+void sfc_tbl_meta_fini(struct sfc_adapter *sa);
+
+#endif /* _SFC_TBL_META_H */
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.c b/drivers/net/sfc/sfc_tbl_meta_cache.c
new file mode 100644
index 0000000000..65ba0b001e
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.c
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include <rte_malloc.h>
+#include <rte_jhash.h>
+
+#include "sfc_tbl_meta_cache.h"
+#include "sfc_debug.h"
+
+/* The minimal size of the table meta cache */
+#define SFC_TBL_META_CACHE_SIZE_MIN	8
+
+int
+sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
+{
+	size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
+				    efx_table_supported_num_get());
+	struct rte_hash *cache = NULL;
+	const struct rte_hash_parameters hash_params = {
+		.name       = "meta_hash_table",
+		.hash_func  = rte_jhash,
+		.entries    = cache_size,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(efx_table_id_t),
+	};
+
+	cache = rte_hash_create(&hash_params);
+	if (!cache)
+		return -ENOMEM;
+
+	*ref_cache = cache;
+
+	return 0;
+}
+
+static void
+sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
+{
+	SFC_ASSERT(meta != NULL);
+
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+	rte_free(meta);
+}
+
+void
+sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
+{
+	struct rte_hash *cache = *ref_cache;
+	const void *next_key;
+	uint32_t iter = 0;
+	void *next_meta;
+
+	if (cache == NULL)
+		return;
+
+	while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
+		sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
+
+	rte_hash_free(cache);
+
+	*ref_cache = NULL;
+}
+
+/**
+ * Table descriptor contains information about the table's
+ * fields that can be associated with both the key and the response.
+ * Save these fields by separating the key from the response in
+ * appropriate places based on their lengths.
+ */
+static int
+sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+			      efx_table_field_descriptor_t *fields,
+			      unsigned int total_n_fields)
+{
+	uint16_t n_key_fields = meta->descriptor.n_key_fields;
+	size_t field_size = sizeof(*fields);
+	unsigned int n_field_descs_written;
+	uint32_t field_offset;
+	int rc;
+
+	for (n_field_descs_written = 0, field_offset = 0;
+	     field_offset < total_n_fields;
+	     field_offset += n_field_descs_written) {
+		rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
+					fields, total_n_fields, &n_field_descs_written);
+		if (rc != 0)
+			return rc;
+
+		if (field_offset + n_field_descs_written > total_n_fields)
+			return -EINVAL;
+
+		if (field_offset < n_key_fields &&
+		    field_offset + n_field_descs_written > n_key_fields) {
+			/*
+			 * Some of the descriptors belong to key,
+			 * the other to response.
+			 */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, (n_key_fields - field_offset) * field_size);
+			rte_memcpy(meta->responses,
+				   RTE_PTR_ADD(fields,
+				   (n_key_fields - field_offset) * field_size),
+				   (field_offset + n_field_descs_written - n_key_fields) *
+				   field_size);
+		} else if (field_offset < n_key_fields) {
+			/* All fields belong to the key */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, n_field_descs_written * field_size);
+		} else {
+			/* All fields belong to the response */
+			rte_memcpy(RTE_PTR_ADD(meta->responses,
+				   (field_offset - n_key_fields) * field_size),
+				   fields, n_field_descs_written * field_size);
+		}
+	}
+
+	return 0;
+}
+
+static int
+sfc_tbl_meta_desc_read(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	efx_table_field_descriptor_t *fields;
+	unsigned int total_n_fields;
+	int rc;
+
+	rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
+
+	fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
+	if (fields == NULL)
+		return -ENOMEM;
+
+	meta->table_id = table_id;
+
+	meta->keys = rte_calloc("efx_table_key_field_descs",
+				meta->descriptor.n_key_fields,
+				sizeof(*meta->keys), 0);
+	if (meta->keys == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_keys;
+	}
+
+	meta->responses = rte_calloc("efx_table_response_field_descs",
+				     meta->descriptor.n_resp_fields,
+				     sizeof(*meta->responses), 0);
+	if (meta->responses == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_responses;
+	}
+
+	rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
+	if (rc != 0)
+		goto fail_copy_fields;
+
+	return 0;
+
+fail_copy_fields:
+	rte_free(meta->responses);
+fail_alloc_responses:
+	rte_free(meta->keys);
+fail_alloc_keys:
+	rte_free(fields);
+
+	return rc;
+}
+
+static int
+sfc_tbl_meta_cache_add(struct rte_hash *cache, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta = NULL;
+	int rc;
+
+	meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
+	if (meta == NULL)
+		return -ENOMEM;
+
+	rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
+	if (rc != 0)
+		goto fail_read_meta;
+
+	rc = rte_hash_add_key_data(cache, &table_id, meta);
+	if (rc != 0)
+		goto fail_add_key;
+
+	return 0;
+
+fail_add_key:
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+fail_read_meta:
+	rte_free(meta);
+
+	return rc;
+}
+
+int
+sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp)
+{
+	efx_table_id_t *table_ids = NULL;
+	unsigned int n_table_ids_written;
+	unsigned int total_n_tables;
+	unsigned int n_table_ids;
+	uint32_t table_index;
+	unsigned int i;
+	int rc = 0;
+
+	rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
+	if (table_ids == NULL)
+		return -ENOMEM;
+
+	n_table_ids = total_n_tables;
+
+	for (table_index = 0, n_table_ids_written = 0;
+	     table_index < total_n_tables;
+	     table_index += n_table_ids_written) {
+		rc = efx_table_list(enp, table_index, NULL,
+				    table_ids, n_table_ids, &n_table_ids_written);
+		if (rc != 0)
+			goto out;
+
+		if (table_index + n_table_ids_written > total_n_tables) {
+			rc = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < n_table_ids_written; i++, table_index++) {
+			if (!efx_table_is_supported(table_ids[i]))
+				continue;
+
+			rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
+			if (rc != 0)
+				goto out;
+		}
+	}
+
+out:
+	rte_free(table_ids);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.h b/drivers/net/sfc/sfc_tbl_meta_cache.h
new file mode 100644
index 0000000000..2deff620a4
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_CACHE_H
+#define _SFC_TBL_META_CACHE_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#include "sfc_tbl_meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache);
+
+void sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache);
+
+int sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp);
+
+#endif /* _SFC_TBLS_DESC_CACHE_H */
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
index db54fc0d40..d41b961454 100644
--- a/drivers/net/sfc/sfc_tbls.c
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2023 Advanced Micro Devices, Inc.
  */
 
+#include "sfc.h"
 #include "sfc_tbls.h"
 #include "sfc_debug.h"
 
@@ -11,6 +12,65 @@
 /* Number of bits in uint32_t type */
 #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
 
+int
+sfc_tbls_attach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	const struct sfc_mae *mae = &sa->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	if (mae->status != SFC_MAE_STATUS_ADMIN ||
+	    !encp->enc_table_api_supported) {
+		tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	tables->status = SFC_TBLS_STATUS_SUPPORTED;
+
+	rc = sfc_tbl_meta_init(sa);
+	if (rc != 0)
+		return rc;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_tbls_detach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+
+	sfc_log_init(sa, "entry");
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		goto done;
+
+	sfc_tbl_meta_fini(sa);
+
+done:
+	sfc_log_init(sa, "done");
+
+	tables->status = SFC_TBLS_STATUS_UNKNOWN;
+}
+
+int
+sfc_tbls_start(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
+		rc = sfc_tbls_attach(sa);
+		return rc;
+	}
+
+	return 0;
+}
+
 static uint32_t
 sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
 {
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 7b6bb5b341..be0abbf161 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -8,6 +8,8 @@
 
 #include "efx.h"
 
+#include "sfc_tbl_meta.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -44,6 +46,85 @@ extern "C" {
 /* Mask is used only for STCAM */
 #define SFC_TBLS_BCAM_MASK_WIDTH	0
 
+/** Options for HW tables support status */
+enum sfc_tbls_status {
+	SFC_TBLS_STATUS_UNKNOWN = 0,
+	SFC_TBLS_STATUS_UNSUPPORTED,
+	SFC_TBLS_STATUS_SUPPORTED,
+};
+
+/**
+ * Entry point to access HW tables
+ *
+ * SFC driver can access hardware (HW) tables.
+ * Interaction with HW tables is done through the MCDI table access API
+ * that is implemented in EFX.
+ *
+ * In order to manipulate data on HW tables it's necessary to
+ * - discover the list of supported tables;
+ * - read a table descriptor to get details of the structure
+ *   of the table;
+ * - get named fields of the table;
+ * - insert/delete/update table entries based on given fields
+ *   and information about the table
+ *
+ * All table layout data should be saved in a cache.
+ * The cache allows to avoid getting the table descriptor each time when you want
+ * to manipulate table entries. It just contains the table
+ * descriptors and all associated data. The cache is based on the RTE hash map and
+ * it uses a table ID as a key.
+ * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
+ * to get all information about the tables without worrying about the cache.
+ *
+ * +------------------------+
+ * | Cache is uninitialized |<----------------------------------+
+ * +------------------------+					|
+ *	|							|
+ *	| sfc_attach()						|
+ *	| sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
+ *	V					^
+ * +------------------------+			|
+ * |  Cache is initialized  |			+-------+
+ * +------------------------+				|
+ *	| sfc_start()					|
+ *	| sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | and valid              |				|
+ * +------------------------+				|
+ *	|						|
+ *	| sfc_restart()					|
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | but can be invalid     |				|
+ * +------------------------+---------------------------+
+ */
+struct sfc_tbls {
+	struct sfc_tbl_meta_cache	meta;
+	enum sfc_tbls_status		status;
+};
+
+struct sfc_adapter;
+
+static inline bool
+sfc_tbls_id_is_supported(struct sfc_adapter *sa,
+			 efx_table_id_t table_id)
+{
+	return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
+}
+
+int sfc_tbls_attach(struct sfc_adapter *sa);
+void sfc_tbls_detach(struct sfc_adapter *sa);
+int sfc_tbls_start(struct sfc_adapter *sa);
+
+static inline void
+sfc_tbls_stop(struct sfc_adapter *sa)
+{
+	sfc_tbls_detach(sa);
+}
+
 static inline int
 sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
 			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 11/34] net/sfc: add API to manage HW Conntrack table
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (9 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 10/34] net/sfc: attach to HW table API Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The new API allows to manipulate entries in
the HW Conntrack table.
It uses a new Table Access API as a backend.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_mae_ct.c | 201 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae_ct.h |  68 ++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c9d4264674..5adde68517 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -92,6 +92,7 @@ sources = files(
         'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
+        'sfc_mae_ct.c',
         'sfc_flow.c',
         'sfc_flow_rss.c',
         'sfc_flow_tunnel.c',
diff --git a/drivers/net/sfc/sfc_mae_ct.c b/drivers/net/sfc/sfc_mae_ct.c
new file mode 100644
index 0000000000..fd6819c8a5
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_mae_ct.h"
+
+/* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
+static void
+sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
+			   const efx_table_field_descriptor_t *fields,
+			   unsigned int n_fields, uint32_t *mcdi_key,
+			   unsigned int key_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+			sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
+					      desc->width, key->ip_proto);
+			break;
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->ether_type_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->src_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->dst_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->src_addr_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->dst_addr_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+/* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
+static void
+sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t *response,
+				     const efx_table_field_descriptor_t *fields,
+				     unsigned int n_fields, uint32_t *mcdi_resp,
+				     unsigned int resp_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		/* Fields of responses are always reported with the EXACT type. */
+		SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_CT_MARK:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->ct_mark);
+			break;
+		case EFX_TABLE_FIELD_ID_COUNTER_ID:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->counter_id);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_DIR:
+			sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
+					      desc->width, response->nat.dir_is_dst);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_IP:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.ip_le);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_PORT:
+			sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.port_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+int
+sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key,
+			 const sfc_mae_conntrack_response_t *response)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int response_size;
+	uint32_t *response_data;
+	unsigned int data_size;
+	unsigned int key_size;
+	uint32_t *start_data;
+	uint16_t resp_width;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+	resp_width = meta->descriptor.resp_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	response_data = sfc_tbls_next_req_fields(key_data, key_width);
+	end_data = sfc_tbls_next_req_fields(response_data, resp_width);
+
+	key_size = RTE_PTR_DIFF(response_data, key_data);
+	response_size = RTE_PTR_DIFF(end_data, response_data);
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields, key_data,
+				   key_size);
+	sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
+					     meta->descriptor.n_resp_fields,
+					     response_data, response_size);
+
+	rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, resp_width, data,
+					data_size);
+
+	return rc;
+}
+
+int
+sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int data_size;
+	uint32_t *start_data;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	end_data = sfc_tbls_next_req_fields(key_data, key_width);
+
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields,
+				   key_data, data_size);
+
+	rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, data, data_size);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae_ct.h b/drivers/net/sfc/sfc_mae_ct.h
new file mode 100644
index 0000000000..b5a3181cd3
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_MAE_CONNTRACK_H
+#define _SFC_MAE_CONNTRACK_H
+
+#include <stdbool.h>
+
+#include <rte_ip.h>
+
+#include "efx.h"
+
+#include "sfc_tbls.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sfc_mae_conntrack_key_s {
+	uint8_t		ip_proto;
+	uint16_t	ether_type_le;
+
+	uint16_t	src_port_le;
+	uint16_t	dst_port_le;
+
+	uint8_t		src_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr)];
+	uint8_t		dst_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, dst_addr)];
+} sfc_mae_conntrack_key_t;
+
+typedef struct sfc_mae_conntrack_nat_s {
+	uint32_t	ip_le;
+	uint16_t	port_le;
+	bool		dir_is_dst;
+} sfc_mae_conntrack_nat_t;
+
+typedef struct sfc_mae_conntrack_response_s {
+	uint32_t		ct_mark;
+	sfc_mae_conntrack_nat_t	nat;
+	uint32_t		counter_id;
+} sfc_mae_conntrack_response_t;
+
+struct sfc_adapter;
+
+static inline bool
+sfc_mae_conntrack_is_supported(struct sfc_adapter *sa)
+{
+	return sfc_tbls_id_is_supported(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+static inline const struct sfc_tbl_meta *
+sfc_mae_conntrack_meta_lookup(struct sfc_adapter *sa)
+{
+	return sfc_tbl_meta_lookup(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+int sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key,
+			     const sfc_mae_conntrack_response_t *response);
+
+int sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_CONNTRACK_H */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 12/34] net/sfc: make entry pointer optional in MAE resource helpers
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (10 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
                   ` (24 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Keep NULL object check in one place rather than repeat it in
all of the callers. That should make the code easier on eyes.
Future code for additional object types will follow this way.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 78 ++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 60b9fdc290..7a3f9761c1 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -402,6 +402,9 @@ sfc_mae_outer_rule_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(rule->refcnt != 0);
 
@@ -429,11 +432,16 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_outer_rule *rule,
 			  efx_mae_match_spec_t *match_spec_action)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(rule->match_spec != NULL);
@@ -480,11 +488,16 @@ static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -1057,6 +1070,9 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(action_set->refcnt != 0);
 
@@ -1092,15 +1108,24 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
-	struct sfc_mae_mac_addr *dst_mac_addr = action_set->dst_mac_addr;
-	struct sfc_mae_mac_addr *src_mac_addr = action_set->src_mac_addr;
-	struct sfc_mae_counter_id *counters = action_set->counters;
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae_mac_addr *dst_mac_addr;
+	struct sfc_mae_mac_addr *src_mac_addr;
+	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	encap_header = action_set->encap_header;
+	dst_mac_addr = action_set->dst_mac_addr;
+	src_mac_addr = action_set->src_mac_addr;
+	counters = action_set->counters;
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
@@ -1167,11 +1192,16 @@ static void
 sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
@@ -1228,11 +1258,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 
-	if (spec_mae->outer_rule != NULL)
-		sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-
-	if (spec_mae->action_set != NULL)
-		sfc_mae_action_set_del(sa, spec_mae->action_set);
+	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
+	sfc_mae_action_set_del(sa, spec_mae->action_set);
 
 	if (spec_mae->match_spec != NULL)
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
@@ -2577,9 +2604,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
 						  &invalid_rule_id);
 	if (rc != 0) {
-		if (*rulep != NULL)
-			sfc_mae_outer_rule_del(sa, *rulep);
-
+		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
 
 		return rte_flow_error_set(error, rc,
@@ -3981,10 +4006,15 @@ static int
 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 				struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
 	struct sfc_mae_outer_rule *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return 0;
+
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
 		/* An active rule is reused. It's class is wittingly valid. */
 		return 0;
@@ -4071,11 +4101,9 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (sa->state != SFC_ETHDEV_STARTED)
 		return EAGAIN;
 
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
-		if (rc != 0)
-			return rc;
-	}
+	rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
+	if (rc != 0)
+		return rc;
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
@@ -4141,8 +4169,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4177,8 +4204,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 13/34] net/sfc: turn flow create/destroy methods into lock wrappers
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (11 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is useful to facilitate driver-internal flow rework.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 42 ++++++++++++++++++++++++++++++--------
 drivers/net/sfc/sfc_flow.h |  9 ++++++++
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index fe1f5ba55f..432295ea62 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2610,16 +2610,32 @@ sfc_flow_create(struct rte_eth_dev *dev,
 		struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow *flow;
+
+	sfc_adapter_lock(sa);
+	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	sfc_adapter_unlock(sa);
+
+	return flow;
+}
+
+struct rte_flow *
+sfc_flow_create_locked(struct sfc_adapter *sa,
+		       const struct rte_flow_attr *attr,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow_error *error)
+{
 	struct rte_flow *flow = NULL;
 	int rc;
 
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
 	flow = sfc_flow_zmalloc(error);
 	if (flow == NULL)
 		goto fail_no_mem;
 
-	sfc_adapter_lock(sa);
-
-	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
@@ -2631,8 +2647,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 			goto fail_flow_insert;
 	}
 
-	sfc_adapter_unlock(sa);
-
 	return flow;
 
 fail_flow_insert:
@@ -2640,7 +2654,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 
 fail_bad_value:
 	sfc_flow_free(sa, flow);
-	sfc_adapter_unlock(sa);
 
 fail_no_mem:
 	return NULL;
@@ -2652,10 +2665,23 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 		 struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	int rc;
+
+	sfc_adapter_lock(sa);
+	rc = sfc_flow_destroy_locked(sa, flow, error);
+	sfc_adapter_unlock(sa);
+
+	return rc;
+}
+
+int
+sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			struct rte_flow_error *error)
+{
 	struct rte_flow *flow_ptr;
 	int rc = EINVAL;
 
-	sfc_adapter_lock(sa);
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
 		if (flow_ptr == flow)
@@ -2675,8 +2701,6 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 	sfc_flow_free(sa, flow);
 
 fail_bad_value:
-	sfc_adapter_unlock(sa);
-
 	return -rc;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 12875344b5..a3ca09f225 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -195,6 +195,15 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+					const struct rte_flow_attr *attr,
+					const struct rte_flow_item pattern[],
+					const struct rte_flow_action actions[],
+					struct rte_flow_error *error);
+
+int sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			    struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 14/34] net/sfc: let driver-internal flows use VF representor action
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (12 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

In the case of VF <--> VF representor pairs, these flows can
only collect VF traffic, so let them use generic flow action
PORT_REPRESENTOR, as part of re-using generic flow mechanism.

Currently, it does not allow to access VF representors since
they have no unique HW logical ports (m-ports). They all sit
on the same (representor proxy) m-port, while demultiplexing
of traffic uses ingress (VF) m-port value in packet metadata.
Traffic from arbitrary sources cannot be identified this way.
But, for VF traffic, it should be right to make an exception.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c            | 25 +++++++++++++++++++------
 drivers/net/sfc/sfc_repr.c           | 20 ++++++++++++++++----
 drivers/net/sfc/sfc_repr_proxy.c     | 15 +++++++++++++++
 drivers/net/sfc/sfc_repr_proxy_api.h |  3 +++
 drivers/net/sfc/sfc_switch.c         |  7 ++-----
 drivers/net/sfc/sfc_switch.h         | 10 ++++++++++
 6 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7a3f9761c1..c0b97b1fe1 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1527,6 +1527,7 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 	const struct rte_flow_item_port_id *spec = NULL;
 	const struct rte_flow_item_port_id *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1558,8 +1559,10 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 					  "The port ID is too large");
 	}
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
-					     spec->id, &mport_sel);
+					     spec->id, type_mask, &mport_sel);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1592,6 +1595,7 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 	const struct rte_flow_item_ethdev *spec = NULL;
 	const struct rte_flow_item_ethdev *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1619,9 +1623,11 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 
 	switch (item->type) {
 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
+		type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_switch_get_ethdev_mport(
 				ctx_mae->sa->mae.switch_domain_id,
-				spec->port_id, &mport_sel);
+				spec->port_id, type_mask, &mport_sel);
 		if (rc != 0) {
 			return rte_flow_error_set(error, rc,
 					RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -3531,6 +3537,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 {
 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
+	unsigned int type_mask;
 	efx_mport_sel_t mport;
 	uint16_t port_id;
 	int rc;
@@ -3540,8 +3547,10 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 
 	port_id = (conf->original != 0) ? sas->port_id : conf->id;
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     port_id, &mport);
+					     port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			port_id, strerror(rc));
@@ -3560,14 +3569,14 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
 		const struct rte_flow_action_ethdev *conf,
-		efx_mae_actions_t *spec)
+		unsigned int type_mask, efx_mae_actions_t *spec)
 {
 	struct sfc_mae *mae = &sa->mae;
 	efx_mport_sel_t mport;
 	int rc;
 
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     conf->port_id, &mport);
+					     conf->port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			conf->port_id, strerror(rc));
@@ -3643,6 +3652,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
+	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
@@ -3759,8 +3769,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
 				       bundle->actions_mask);
+
+		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
-				action->conf, spec);
+				action->conf, switch_port_type_mask, spec);
 		break;
 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index d4134ec91b..6c7727d569 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -933,15 +933,26 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
 	struct sfc_mae_switch_port_request switch_port_request;
 	efx_mport_sel_t ethdev_mport_sel;
+	efx_mport_id_t proxy_mport_id;
 	struct sfc_repr *sr;
 	int ret;
 
 	/*
-	 * Currently there is no mport we can use for representor's
-	 * ethdev. Use an invalid one for now. This way representors
-	 * can be instantiated.
+	 * For each representor, a driver-internal flow has to be installed
+	 * in order to direct traffic coming from the represented entity to
+	 * the "representor proxy". Such internal flows need to find ethdev
+	 * mport by ethdev ID of the representors in question to specify in
+	 * delivery action. So set the representor ethdev's mport to that
+	 * of the "representor proxy" in below switch port request.
 	 */
-	efx_mae_mport_invalid(&ethdev_mport_sel);
+	sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
+
+	ret = efx_mae_mport_by_id(&proxy_mport_id, &ethdev_mport_sel);
+	if (ret != 0) {
+		SFC_GENERIC_LOG(ERR,
+			"%s() failed to get repr proxy mport by ID", __func__);
+		goto fail_get_selector;
+	}
 
 	memset(&switch_port_request, 0, sizeof(switch_port_request));
 	switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
@@ -1033,6 +1044,7 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 
 fail_create_port:
 fail_mae_assign_switch_port:
+fail_get_selector:
 	SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
 	return ret;
 }
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 4ba7683370..74c3494c35 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -1708,3 +1708,18 @@ sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id, uint16_t repr_id,
 
 	return rc;
 }
+
+void
+sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id, efx_mport_id_t *mport_alias)
+{
+	const struct sfc_repr_proxy *rp;
+	struct sfc_adapter *sa;
+
+	sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
+	sfc_adapter_lock(sa);
+	rp = sfc_repr_proxy_by_adapter(sa);
+
+	memcpy(mport_alias, &rp->mport_alias, sizeof(*mport_alias));
+
+	sfc_adapter_unlock(sa);
+}
diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h
index 1d38ab2451..07d79a50cb 100644
--- a/drivers/net/sfc/sfc_repr_proxy_api.h
+++ b/drivers/net/sfc/sfc_repr_proxy_api.h
@@ -46,6 +46,9 @@ int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id);
 int sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id,
 		uint16_t repr_id, const struct rte_ether_addr *mac_addr);
 
+void sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id,
+				    efx_mport_id_t *mport_alias);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 8f1ee97fa8..f80de4e889 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -551,6 +551,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
 int
 sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				uint16_t ethdev_port_id,
+				unsigned int allowed_mae_switch_port_types,
 				efx_mport_sel_t *mport_sel)
 {
 	struct sfc_mae_switch_port *port;
@@ -562,11 +563,7 @@ sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 	if (rc != 0)
 		goto unlock;
 
-	if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) {
-		/*
-		 * The ethdev is a "VF representor". It does not own
-		 * a dedicated m-port suitable for use in flow rules.
-		 */
+	if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
 		rc = ENOTSUP;
 		goto unlock;
 	}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 62aea9b785..6a85ce4dcf 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -102,8 +102,18 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
 			      uint16_t switch_port_id);
 
+/*
+ * For user flows, allowed_mae_switch_port_types can only contain bit
+ * SFC_MAE_SWITCH_PORT_INDEPENDENT, meaning that only those ethdevs
+ * that have their own MAE m-ports can be accessed by a port-based
+ * action. For driver-internal flows, this mask can also contain
+ * bit SFC_MAE_SWITCH_PORT_REPRESENTOR to allow VF traffic to be
+ * sent to the common MAE m-port of all such REPRESENTOR ports
+ * via a port-based action, for default switch interconnection.
+ */
 int sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				    uint16_t ethdev_port_id,
+				    unsigned int allowed_mae_switch_port_types,
 				    efx_mport_sel_t *mport_sel);
 
 int sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 15/34] net/sfc: extend generic flow API to allow for internal flows
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (13 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

At the moment, driver-internal flow rules are provisioned by
functions that are separate from the generic flow management
framework. In order to use the latter for such rules, extend
it accordingly. This will be actually used in the next patch.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc.c      |  9 ++++-----
 drivers/net/sfc/sfc_flow.c | 24 ++++++++++++++++++------
 drivers/net/sfc/sfc_flow.h |  5 ++++-
 drivers/net/sfc/sfc_mae.c  | 31 +++++++++++++++++++++++++++----
 drivers/net/sfc/sfc_mae.h  |  5 +++--
 5 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index a56521696a..2cfff20f47 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -975,6 +975,8 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_rss_attach;
 
+	sfc_flow_init(sa);
+
 	rc = sfc_flow_rss_attach(sa);
 	if (rc != 0)
 		goto fail_flow_rss_attach;
@@ -1006,8 +1008,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
-	sfc_flow_init(sa);
-
 	rc = sfc_sw_xstats_init(sa);
 	if (rc != 0)
 		goto fail_sw_xstats_init;
@@ -1030,7 +1030,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_sw_xstats_close(sa);
 
 fail_sw_xstats_init:
-	sfc_flow_fini(sa);
 	sfc_repr_proxy_detach(sa);
 
 fail_repr_proxy_attach:
@@ -1052,6 +1051,7 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_flow_rss_detach(sa);
 
 fail_flow_rss_attach:
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 
 fail_rss_attach:
@@ -1099,8 +1099,6 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_sriov_vswitch_destroy(sa);
 
-	sfc_flow_fini(sa);
-
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
 	sfc_tbls_detach(sa);
@@ -1108,6 +1106,7 @@ sfc_detach(struct sfc_adapter *sa)
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_flow_rss_detach(sa);
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
 	sfc_ev_detach(sa);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 432295ea62..94696afac0 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <rte_byteorder.h>
 #include <rte_tailq.h>
 #include <rte_common.h>
@@ -2405,7 +2407,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2421,7 +2423,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2613,14 +2615,14 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow;
 
 	sfc_adapter_lock(sa);
-	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
 	sfc_adapter_unlock(sa);
 
 	return flow;
 }
 
 struct rte_flow *
-sfc_flow_create_locked(struct sfc_adapter *sa,
+sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item pattern[],
 		       const struct rte_flow_action actions[],
@@ -2635,6 +2637,8 @@ sfc_flow_create_locked(struct sfc_adapter *sa,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	flow->internal = internal;
+
 	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
@@ -2711,10 +2715,14 @@ sfc_flow_flush(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct rte_flow *flow;
 	int ret = 0;
+	void *tmp;
 
 	sfc_adapter_lock(sa);
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		if (sa->state == SFC_ETHDEV_STARTED) {
 			int rc;
 
@@ -2842,10 +2850,14 @@ void
 sfc_flow_fini(struct sfc_adapter *sa)
 {
 	struct rte_flow *flow;
+	void *tmp;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		TAILQ_REMOVE(&sa->flow_list, flow, entries);
 		sfc_flow_free(sa, flow);
 	}
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index a3ca09f225..ec5e29f257 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -10,6 +10,8 @@
 #ifndef _SFC_FLOW_H
 #define _SFC_FLOW_H
 
+#include <stdbool.h>
+
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
 
@@ -101,6 +103,7 @@ struct sfc_flow_spec {
 struct rte_flow {
 	struct sfc_flow_spec spec;	/* flow specification */
 	TAILQ_ENTRY(rte_flow) entries;	/* flow list entries */
+	bool internal;			/* true for internal rules */
 };
 
 TAILQ_HEAD(sfc_flow_list, rte_flow);
@@ -195,7 +198,7 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
-struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 					const struct rte_flow_attr *attr,
 					const struct rte_flow_item pattern[],
 					const struct rte_flow_action actions[],
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c0b97b1fe1..36eb78d425 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2539,6 +2539,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
+	if (ctx->internal) {
+		/*
+		 * A driver-internal flow may not comprise an outer rule,
+		 * but it must not match on invalid outer rule ID since
+		 * it must catch all missed packets, including those
+		 * that hit an outer rule of another flow entry but
+		 * do not hit a higher-priority action rule later.
+		 * So do not set match on outer rule ID here.
+		 */
+		SFC_ASSERT(ctx->match_spec_outer == NULL);
+		*rulep = NULL;
+		return 0;
+	}
+
 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
 		*rulep = NULL;
 		goto no_or_id;
@@ -2825,9 +2839,10 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
-			   struct sfc_flow_spec_mae *spec,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2835,6 +2850,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
 	ctx_mae.ft_rule_type = spec->ft_rule_type;
+	ctx_mae.internal = flow->internal;
 	ctx_mae.priority = spec->priority;
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
@@ -3644,11 +3660,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct sfc_flow_spec_mae *spec_mae,
+			  const struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
+	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -3772,6 +3789,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
 
+		if (flow->internal) {
+			switch_port_type_mask |=
+					1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
+		}
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
 				action->conf, switch_port_type_mask, spec);
 		break;
@@ -3842,9 +3864,10 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_flow_spec_mae *spec_mae,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
@@ -3901,7 +3924,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
+		rc = sfc_mae_rule_parse_action(sa, action, flow,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d2995ded88..307236ea11 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -363,6 +363,7 @@ struct sfc_mae_parse_ctx {
 	size_t				tunnel_def_mask_size;
 	const void			*tunnel_def_mask;
 	bool				match_mport_set;
+	bool				internal;
 	enum sfc_ft_rule_type		ft_rule_type;
 	struct sfc_mae_pattern_data	pattern_data;
 	efx_tunnel_protocol_t		encap_type;
@@ -376,11 +377,11 @@ void sfc_mae_detach(struct sfc_adapter *sa);
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
 int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       const struct rte_flow_item pattern[],
-			       struct sfc_flow_spec_mae *spec,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_flow_spec_mae *spec_mae,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 16/34] net/sfc: switch driver-internal flows to use generic methods
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (14 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so helps to consolidate flow operation and ensure that
every FW-allocatable resource can be shared by several flows.
That is useful in the light of upcoming support for embedded
conntrack assistance, where several flows will ideally share
everything but unique 5-tuple entries in the conntrack table.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c        | 184 +++++++------------------------
 drivers/net/sfc/sfc_mae.h        |  51 ++-------
 drivers/net/sfc/sfc_repr_proxy.c |  38 ++-----
 drivers/net/sfc/sfc_repr_proxy.h |   2 +-
 4 files changed, 60 insertions(+), 215 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 36eb78d425..15da886f19 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -74,137 +74,48 @@ sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 	sfc_mae_counters_fini(&registry->counters);
 }
 
-static int
-sfc_mae_internal_rule_find_empty_slot(struct sfc_adapter *sa,
-				      struct sfc_mae_rule **rule)
-{
-	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_internal_rules *internal_rules = &mae->internal_rules;
-	unsigned int entry;
-	int rc;
-
-	for (entry = 0; entry < SFC_MAE_NB_RULES_MAX; entry++) {
-		if (internal_rules->rules[entry].spec == NULL)
-			break;
-	}
-
-	if (entry == SFC_MAE_NB_RULES_MAX) {
-		rc = ENOSPC;
-		sfc_err(sa, "failed too many rules (%u rules used)", entry);
-		goto fail_too_many_rules;
-	}
-
-	*rule = &internal_rules->rules[entry];
-
-	return 0;
-
-fail_too_many_rules:
-	return rc;
-}
-
-int
-sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-				     const efx_mport_sel_t *mport_match,
-				     const efx_mport_sel_t *mport_deliver,
-				     int prio, struct sfc_mae_rule **rulep)
+struct rte_flow *
+sfc_mae_repr_flow_create(struct sfc_adapter *sa, int prio, uint16_t port_id,
+			 enum rte_flow_action_type dst_type,
+			 enum rte_flow_item_type src_type)
 {
+	const struct rte_flow_item_ethdev item_spec = { .port_id = port_id };
+	const struct rte_flow_action_ethdev action = { .port_id = port_id };
+	const void *item_mask = &rte_flow_item_ethdev_mask;
+	struct rte_flow_attr attr = { .transfer = 1 };
+	const struct rte_flow_action actions[] = {
+		{ .type = dst_type, .conf = &action },
+		{ .type = RTE_FLOW_ACTION_TYPE_END }
+	};
+	const struct rte_flow_item items[] = {
+		{ .type = src_type, .mask = item_mask, .spec = &item_spec },
+		{ .type = RTE_FLOW_ITEM_TYPE_END }
+	};
 	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_rule *rule;
-	int rc;
-
-	sfc_log_init(sa, "entry");
+	struct rte_flow_error error;
 
 	if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
-		rc = EINVAL;
 		sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
 			mae->nb_action_rule_prios_max);
-		goto fail_invalid_prio;
+		return NULL;
 	}
 	if (prio < 0)
 		prio = mae->nb_action_rule_prios_max - 1;
 
-	rc = sfc_mae_internal_rule_find_empty_slot(sa, &rule);
-	if (rc != 0)
-		goto fail_find_empty_slot;
-
-	sfc_log_init(sa, "init MAE match spec");
-	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
-				     (uint32_t)prio, &rule->spec);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE match spec");
-		goto fail_match_init;
-	}
-
-	rc = efx_mae_match_spec_mport_set(rule->spec, mport_match, NULL);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get MAE match mport selector");
-		goto fail_mport_set;
-	}
-
-	rc = efx_mae_action_set_spec_init(sa->nic, &rule->actions);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE action set");
-		goto fail_action_init;
-	}
+	attr.priority = prio;
 
-	rc = efx_mae_action_set_populate_deliver(rule->actions,
-						 mport_deliver);
-	if (rc != 0) {
-		sfc_err(sa, "failed to populate deliver action");
-		goto fail_populate_deliver;
-	}
-
-	rc = efx_mae_action_set_alloc(sa->nic, rule->actions,
-				      &rule->action_set);
-	if (rc != 0) {
-		sfc_err(sa, "failed to allocate action set");
-		goto fail_action_set_alloc;
-	}
-
-	rc = efx_mae_action_rule_insert(sa->nic, rule->spec, NULL,
-					&rule->action_set,
-					&rule->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to insert action rule");
-		goto fail_rule_insert;
-	}
-
-	*rulep = rule;
-
-	sfc_log_init(sa, "done");
-
-	return 0;
-
-fail_rule_insert:
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-
-fail_action_set_alloc:
-fail_populate_deliver:
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
-
-fail_action_init:
-fail_mport_set:
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
-
-fail_match_init:
-fail_find_empty_slot:
-fail_invalid_prio:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	return sfc_flow_create_locked(sa, true, &attr, items, actions, &error);
 }
 
 void
-sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule)
+sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow)
 {
-	if (rule == NULL || rule->spec == NULL)
-		return;
-
-	efx_mae_action_rule_remove(sa->nic, &rule->rule_id);
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
+	struct rte_flow_error error;
+	int rc;
 
-	rule->spec = NULL;
+	rc = sfc_flow_destroy_locked(sa, flow, &error);
+	if (rc != 0)
+		sfc_err(sa, "failed to destroy the internal flow");
 }
 
 int
@@ -4313,10 +4224,8 @@ sfc_mae_flow_query(struct rte_eth_dev *dev,
 int
 sfc_mae_switchdev_init(struct sfc_adapter *sa)
 {
-	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
-	efx_mport_sel_t pf;
-	efx_mport_sel_t phy;
 	int rc;
 
 	sfc_log_init(sa, "entry");
@@ -4332,31 +4241,20 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 		goto fail_no_mae;
 	}
 
-	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
-					    &pf);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PF mport");
-		goto fail_pf_get;
-	}
-
-	rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PHY mport");
-		goto fail_phy_get;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_pf_to_ext);
-	if (rc != 0) {
+	mae->switchdev_rule_pf_to_ext = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
+					 RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR);
+	if (mae->switchdev_rule_pf_to_ext == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
 		goto fail_pf_add;
 	}
 
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_ext_to_pf);
-	if (rc != 0) {
+	mae->switchdev_rule_ext_to_pf = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+					 RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (mae->switchdev_rule_ext_to_pf == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
 		goto fail_phy_add;
 	}
@@ -4366,11 +4264,9 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 	return 0;
 
 fail_phy_add:
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 
 fail_pf_add:
-fail_phy_get:
-fail_pf_get:
 fail_no_mae:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
@@ -4384,6 +4280,6 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	if (!sa->switchdev)
 		return;
 
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
-	sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 307236ea11..f9434e1ab6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -180,33 +180,6 @@ struct sfc_mae_counter_registry {
 	} polling;
 };
 
-/**
- * MAE rules used to capture traffic generated by VFs and direct it to
- * representors (one for each VF).
- */
-#define SFC_MAE_NB_REPR_RULES_MAX	(64)
-
-/** Rules to forward traffic from PHY port to PF and from PF to PHY port */
-#define SFC_MAE_NB_SWITCHDEV_RULES	(2)
-/** Maximum required internal MAE rules */
-#define SFC_MAE_NB_RULES_MAX		(SFC_MAE_NB_SWITCHDEV_RULES + \
-					 SFC_MAE_NB_REPR_RULES_MAX)
-
-struct sfc_mae_rule {
-	efx_mae_match_spec_t		*spec;
-	efx_mae_actions_t		*actions;
-	efx_mae_aset_id_t		action_set;
-	efx_mae_rule_id_t		rule_id;
-};
-
-struct sfc_mae_internal_rules {
-	/*
-	 * Rules required to sustain switchdev mode or to provide
-	 * port representor functionality.
-	 */
-	struct sfc_mae_rule		rules[SFC_MAE_NB_RULES_MAX];
-};
-
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -234,14 +207,12 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter registry */
 	struct sfc_mae_counter_registry	counter_registry;
-	/** Driver-internal flow rules */
-	struct sfc_mae_internal_rules	internal_rules;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
 	 */
-	struct sfc_mae_rule		*switchdev_rule_pf_to_ext;
-	struct sfc_mae_rule		*switchdev_rule_ext_to_pf;
+	struct rte_flow			*switchdev_rule_pf_to_ext;
+	struct rte_flow			*switchdev_rule_ext_to_pf;
 };
 
 struct sfc_adapter;
@@ -396,16 +367,18 @@ sfc_flow_query_cb_t sfc_mae_flow_query;
 
 /**
  * Insert a driver-internal flow rule that matches traffic originating from
- * some m-port selector and redirects it to another one
- * (eg. PF --> PHY, PHY --> PF).
+ * a source port (REPRESENTED_PORT or PORT_REPRESENTOR) and directs it to
+ * its destination counterpart (PORT_REPRESENTOR or REPRESENTED_PORT).
  *
- * If requested priority is negative, use the lowest priority.
+ * If the prio argument is negative, the lowest level will be picked.
  */
-int sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-					 const efx_mport_sel_t *mport_match,
-					 const efx_mport_sel_t *mport_deliver,
-					 int prio, struct sfc_mae_rule **rulep);
-void sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule);
+struct rte_flow *sfc_mae_repr_flow_create(struct sfc_adapter *sa,
+					  int prio, uint16_t port_id,
+					  enum rte_flow_action_type dst_type,
+					  enum rte_flow_item_type src_type);
+
+void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
+
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 74c3494c35..ff13795c97 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -681,47 +681,25 @@ static int
 sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_repr_proxy *rp = &sa->repr_proxy;
-	efx_mport_sel_t mport_alias_selector;
-	efx_mport_sel_t mport_vf_selector;
-	struct sfc_mae_rule *mae_rule;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
-	rc = efx_mae_mport_by_id(&port->egress_mport,
-				 &mport_vf_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get VF mport for repr %u",
-			port->repr_id);
-		goto fail_get_vf;
-	}
-
-	rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get mport selector for repr %u",
-			port->repr_id);
-		goto fail_get_alias;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
-						  &mport_alias_selector, -1,
-						  &mae_rule);
-	if (rc != 0) {
+	port->mae_rule = sfc_mae_repr_flow_create(sa,
+				    SFC_MAE_RULE_PRIO_LOWEST, port->rte_port_id,
+				    RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+				    RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (port->mae_rule == NULL) {
 		sfc_err(sa, "failed to insert MAE rule for repr %u",
 			port->repr_id);
 		goto fail_rule_add;
 	}
 
-	port->mae_rule = mae_rule;
-
 	sfc_log_init(sa, "done");
 
 	return 0;
 
 fail_rule_add:
-fail_get_alias:
-fail_get_vf:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -730,9 +708,7 @@ static void
 sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_mae_rule *mae_rule = port->mae_rule;
-
-	sfc_mae_rule_del(sa, mae_rule);
+	sfc_mae_repr_flow_destroy(sa, port->mae_rule);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h
index 260e2cab30..0a4dedc3e1 100644
--- a/drivers/net/sfc/sfc_repr_proxy.h
+++ b/drivers/net/sfc/sfc_repr_proxy.h
@@ -67,7 +67,7 @@ struct sfc_repr_proxy_port {
 	uint32_t				remote_vnic_mcdi_client_handle;
 	struct sfc_repr_proxy_rxq		rxq[SFC_REPR_RXQ_MAX];
 	struct sfc_repr_proxy_txq		txq[SFC_REPR_TXQ_MAX];
-	struct sfc_mae_rule			*mae_rule;
+	struct rte_flow				*mae_rule;
 	bool					enabled;
 	bool					started;
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 17/34] net/sfc: move MAE flow parsing method to MAE-specific source
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (15 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so will facilitate easier code restructure in the next
patches required to rework flow housekeeping and indirection.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 47 +-----------------------------
 drivers/net/sfc/sfc_mae.c  | 58 ++++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  | 14 ++++-----
 3 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 94696afac0..821ac74dff 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2395,53 +2395,8 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-	struct sfc_flow_spec *spec = &flow->spec;
-	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	int rc;
-
-	/*
-	 * If the flow is meant to be a TUNNEL rule in a FT context,
-	 * preparse its actions and save its properties in spec_mae.
-	 */
-	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
-	if (rc != 0)
-		goto fail;
-
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
-		/*
-		 * By design, this flow should be represented solely by the
-		 * outer rule. But the HW/FW hasn't got support for setting
-		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
-		 * does it support outer rule counters. As a workaround, an
-		 * action rule of lower priority is used to do the job.
-		 *
-		 * So don't skip sfc_mae_rule_parse_actions() below.
-		 */
-	}
-
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_ctx != NULL) {
-		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
-			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
 
-		++(spec_mae->ft_ctx->refcnt);
-	}
-
-	return 0;
-
-fail:
-	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
-	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
-	spec_mae->ft_ctx = NULL;
-
-	return rc;
+	return sfc_mae_rule_parse(sa, pattern, actions, flow, error);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 15da886f19..f61a859032 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2747,7 +2747,7 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
 
-int
+static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
@@ -3772,7 +3772,7 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
 }
 
-int
+static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
@@ -3935,6 +3935,60 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	return rc;
 }
 
+int
+sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow *flow, struct rte_flow_error *error)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	int rc;
+
+	/*
+	 * If the flow is meant to be a TUNNEL rule in a FT context,
+	 * preparse its actions and save its properties in spec_mae.
+	 */
+	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
+	if (rc != 0)
+		goto fail;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 *
+		 * So don't skip sfc_mae_rule_parse_actions() below.
+		 */
+	}
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_ctx != NULL) {
+		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
+			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
+
+		++(spec_mae->ft_ctx->refcnt);
+	}
+
+	return 0;
+
+fail:
+	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
+	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
+	spec_mae->ft_ctx = NULL;
+
+	return rc;
+}
+
 static bool
 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
 			const efx_mae_match_spec_t *left,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index f9434e1ab6..1d937c9b5b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -345,15 +345,13 @@ struct sfc_mae_parse_ctx {
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 void sfc_mae_detach(struct sfc_adapter *sa);
+
+int sfc_mae_rule_parse(struct sfc_adapter *sa,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow *flow, struct rte_flow_error *error);
+
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
-int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
-			       const struct rte_flow_item pattern[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
-int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
-			       const struct rte_flow_action actions[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
 sfc_flow_remove_cb_t sfc_mae_flow_remove;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 18/34] net/sfc: move MAE counter stream start to action set handler
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (16 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Logically, starting flow counter streaming belongs in action
set enable path. Move it there as a preparation step for the
patch that will make action rules shareable by several flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index f61a859032..74614fe9a5 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1063,6 +1063,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
+		if (action_set->n_counters > 0) {
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_err(sa, "failed to start MAE counters support: %s",
+					rte_strerror(rc));
+				sfc_mae_encap_header_disable(sa, encap_header);
+				sfc_mae_mac_addr_disable(sa, src_mac_addr);
+				sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+				return rc;
+			}
+		}
+
 		rc = sfc_mae_counters_enable(sa, counters,
 					     action_set->n_counters,
 					     action_set->spec);
@@ -4143,15 +4155,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_enable;
 
-	if (action_set->n_counters > 0) {
-		rc = sfc_mae_counter_start(sa);
-		if (rc != 0) {
-			sfc_err(sa, "failed to start MAE counters support: %s",
-				rte_strerror(rc));
-			goto fail_mae_counter_start;
-		}
-	}
-
 	fw_rsrc = &action_set->fw_rsrc;
 
 	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
@@ -4166,7 +4169,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	return 0;
 
 fail_action_rule_insert:
-fail_mae_counter_start:
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 19/34] net/sfc: prepare MAE outer rules for action rule indirection
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (17 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Flows provided by match-action engine (MAE) will be reworked
by the next patch to make action rule (AR) entries shareable.
To ensure correct AR specification comparison on attach path,
augment the way outer rules (OR) are handled, namely, how OR
IDs are indicated in a AR specification on parse and disable.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 44 ++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 74614fe9a5..3d9680f070 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -397,8 +397,10 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
-			   struct sfc_mae_outer_rule *rule)
+			   struct sfc_mae_outer_rule *rule,
+			   efx_mae_match_spec_t *match_spec_action)
 {
+	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -409,6 +411,18 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 
 	fw_rsrc = &rule->fw_rsrc;
 
+	if (match_spec_action == NULL)
+		goto skip_action_rule;
+
+	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
+						  &invalid_rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "cannot restore match on invalid outer rule ID: %s",
+			strerror(rc));
+		return;
+	}
+
+skip_action_rule:
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -2459,7 +2473,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule **rulep,
 			   struct rte_flow_error *error)
 {
-	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
+	efx_mae_rule_id_t or_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
 	if (ctx->internal) {
@@ -2506,13 +2520,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	/* The spec has now been tracked by the outer rule entry. */
 	ctx->match_spec_outer = NULL;
 
+	or_id.id = (*rulep)->fw_rsrc.rule_id.id;
+
 no_or_id:
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
 	case SFC_FT_RULE_TUNNEL:
-		/* No action rule */
-		return 0;
+		/*
+		 * Workaround. TUNNEL flows are not supposed to involve
+		 * MAE action rules, but, due to the currently limited
+		 * HW/FW implementation, action rules are still needed.
+		 * See sfc_mae_rule_parse_pattern().
+		 */
+		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
 		 * Match on recirculation ID rather than
@@ -2538,14 +2559,13 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
 	 * in the action rule specification; this ensures correct behaviour.
 	 *
-	 * If, on the other hand, this flow does have an outer rule, its ID
-	 * may be unknown at the moment (not yet allocated), but OR_ID mask
-	 * has to be set to 0xffffffff anyway for correct class comparisons.
-	 * When the outer rule has been allocated, this match field will be
-	 * overridden by sfc_mae_outer_rule_enable() to use the right value.
+	 * If, however, this flow does have an outer rule, OR_ID match must
+	 * be set to the currently known value for that outer rule. It will
+	 * be either 0xffffffff or some valid ID, depending on whether this
+	 * outer rule is currently active (adapter state is STARTED) or not.
 	 */
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
-						  &invalid_rule_id);
+						  &or_id);
 	if (rc != 0) {
 		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
@@ -4172,7 +4192,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4207,7 +4227,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 20/34] net/sfc: turn MAE flow action rules into shareable resources
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (18 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance. With the new feature, multiple flows that differ
in the 5-tuple match fields but are otherwise identical will
be able to share all FW-allocatable objects except for those
of the conntrack table. That will boost flow engine capacity.

To prepare for that, action rules of the match-action engine
have to be turned into shareable objects, from SW standpoint.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   4 +-
 drivers/net/sfc/sfc_flow.h |  13 +-
 drivers/net/sfc/sfc_mae.c  | 362 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_mae.h  |  13 ++
 4 files changed, 287 insertions(+), 105 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 821ac74dff..6f366c1b06 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1294,9 +1294,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		}
 		spec->type = SFC_FLOW_SPEC_MAE;
 		spec_mae->priority = attr->priority;
-		spec_mae->match_spec = NULL;
-		spec_mae->action_set = NULL;
-		spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+		spec_mae->action_rule = NULL;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index ec5e29f257..10c73d012f 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -75,14 +75,13 @@ struct sfc_flow_spec_mae {
 	struct sfc_ft_ctx		*ft_ctx;
 	/* Desired priority level */
 	unsigned int			priority;
-	/* Outer rule registry entry */
+	/*
+	 * Outer rule registry entry (points to below action_rule->outer_rule
+	 * when action_rule is not NULL; self-sufficient entry otherwise)
+	 */
 	struct sfc_mae_outer_rule	*outer_rule;
-	/* EFX match specification */
-	efx_mae_match_spec_t		*match_spec;
-	/* Action set registry entry */
-	struct sfc_mae_action_set	*action_set;
-	/* Firmware-allocated rule ID */
-	efx_mae_rule_id_t		rule_id;
+	/* Action rule registry entry */
+	struct sfc_mae_action_rule	*action_rule;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 3d9680f070..3da29f5257 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -204,6 +204,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
+	TAILQ_INIT(&mae->action_rules);
 
 	if (encp->enc_mae_admin)
 		mae->status = SFC_MAE_STATUS_ADMIN;
@@ -1174,6 +1175,200 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 	--(fw_rsrc->refcnt);
 }
 
+struct sfc_mae_action_rule_ctx {
+	struct sfc_mae_outer_rule	*outer_rule;
+	struct sfc_mae_action_set	*action_set;
+	efx_mae_match_spec_t		*match_spec;
+};
+
+static int
+sfc_mae_action_rule_attach(struct sfc_adapter *sa,
+			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule **rulep,
+			   __rte_unused struct rte_flow_error *error)
+{
+	struct sfc_mae_action_rule *rule;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	/*
+	 * It is assumed that the caller of this helper has already properly
+	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
+	 * ctx->outer_rule refers to a currently active outer rule) or
+	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
+	 */
+	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->outer_rule != ctx->outer_rule ||
+		    rule->action_set != ctx->action_set)
+			continue;
+
+		if (efx_mae_match_specs_equal(rule->match_spec,
+					      ctx->match_spec)) {
+			sfc_dbg(sa, "attaching to action_rule=%p", rule);
+			++(rule->refcnt);
+			*rulep = rule;
+			return 0;
+		}
+	}
+
+	/*
+	 * No need to set RTE error, as this
+	 * code should be handled gracefully.
+	 */
+	return -ENOENT;
+}
+
+static int
+sfc_mae_action_rule_add(struct sfc_adapter *sa,
+			const struct sfc_mae_action_rule_ctx *ctx,
+			struct sfc_mae_action_rule **rulep)
+{
+	struct sfc_mae_action_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	rule = rte_zmalloc("sfc_mae_action_rule", sizeof(*rule), 0);
+	if (rule == NULL)
+		return ENOMEM;
+
+	rule->refcnt = 1;
+	rule->outer_rule = ctx->outer_rule;
+	rule->action_set = ctx->action_set;
+	rule->match_spec = ctx->match_spec;
+
+	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);
+
+	*rulep = rule;
+
+	sfc_dbg(sa, "added action_rule=%p", rule);
+
+	return 0;
+}
+
+static void
+sfc_mae_action_rule_del(struct sfc_adapter *sa,
+			struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae *mae = &sa->mae;
+	if (rule == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(rule->refcnt != 0);
+
+	--(rule->refcnt);
+
+	if (rule->refcnt != 0)
+		return;
+
+	if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    rule->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u",
+			rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
+	}
+
+	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
+	sfc_mae_action_set_del(sa, rule->action_set);
+	sfc_mae_outer_rule_del(sa, rule->outer_rule);
+
+	TAILQ_REMOVE(&mae->action_rules, rule, entries);
+	rte_free(rule);
+
+	sfc_dbg(sa, "deleted action_rule=%p", rule);
+}
+
+static int
+sfc_mae_action_rule_enable(struct sfc_adapter *sa,
+			   struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->refcnt != 0)
+		goto success;
+
+	rc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);
+	if (rc != 0)
+		goto fail_outer_rule_enable;
+
+	rc = sfc_mae_action_set_enable(sa, rule->action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, NULL,
+					&rule->action_set->fw_rsrc.aset_id,
+					&fw_rsrc->rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "failed to enable action_rule=%p: %s",
+			rule, strerror(rc));
+		goto fail_action_rule_insert;
+	}
+
+success:
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled action_rule=%p: AR_ID=0x%08x",
+			rule, fw_rsrc->rule_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+
+fail_action_rule_insert:
+	sfc_mae_action_set_disable(sa, rule->action_set);
+
+fail_action_set_enable:
+	sfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);
+
+fail_outer_rule_enable:
+	return rc;
+}
+static void
+sfc_mae_action_rule_disable(struct sfc_adapter *sa,
+			    struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u",
+			rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled action_rule=%p with AR_ID=0x%08x",
+				rule, fw_rsrc->rule_id.id);
+		} else {
+			sfc_err(sa, "failed to disable action_rule=%p with AR_ID=0x%08x: %s",
+				rule, fw_rsrc->rule_id.id, strerror(rc));
+		}
+
+		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		sfc_mae_action_set_disable(sa, rule->action_set);
+
+		sfc_mae_outer_rule_disable(sa, rule->outer_rule,
+					   rule->match_spec);
+	}
+
+	--(fw_rsrc->refcnt);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -1193,13 +1388,7 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		--(spec_mae->ft_ctx->refcnt);
 	}
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-	sfc_mae_action_set_del(sa, spec_mae->action_set);
-
-	if (spec_mae->match_spec != NULL)
-		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
 }
 
 static int
@@ -2783,9 +2972,11 @@ static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
+	struct sfc_mae_outer_rule **outer_rulep;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2798,6 +2989,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
 
+	outer_rulep = &action_rule_ctx->outer_rule;
+
 	switch (ctx_mae.ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		/*
@@ -2874,7 +3067,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
-	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
+	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
 
@@ -2886,7 +3079,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		goto fail_validate_match_spec_action;
 	}
 
-	spec->match_spec = ctx_mae.match_spec_action;
+	action_rule_ctx->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
@@ -3808,6 +4001,7 @@ static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
@@ -3929,8 +4123,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		goto fail_check_fate_action;
 	}
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, &ctx);
-	if (spec_mae->action_set != NULL) {
+	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
+	if (action_rule_ctx->action_set != NULL) {
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -3938,7 +4132,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, actions, &ctx,
+				    &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -3974,6 +4169,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule_ctx ctx = {};
 	int rc;
 
 	/*
@@ -3984,7 +4180,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
@@ -4000,10 +4196,30 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	spec_mae->outer_rule = ctx.outer_rule;
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
+	rc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,
+					error);
+	if (rc == 0) {
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+		sfc_mae_action_set_del(sa, ctx.action_set);
+		sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+	} else if (rc == -ENOENT) {
+		rc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);
+		if (rc != 0) {
+			rc = rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to add the entry");
+			goto fail;
+		}
+	} else {
+		goto fail;
+	}
+
 	if (spec_mae->ft_ctx != NULL) {
 		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
 			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
@@ -4014,6 +4230,12 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	return 0;
 
 fail:
+	if (ctx.match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+
+	sfc_mae_action_set_del(sa, ctx.action_set);
+	sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+
 	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
 	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
 	spec_mae->ft_ctx = NULL;
@@ -4073,30 +4295,27 @@ sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
-				 struct sfc_flow_spec_mae *spec)
+				 struct sfc_mae_action_rule *rule)
 {
-	const struct rte_flow *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	const struct sfc_mae_action_rule *entry;
+	struct sfc_mae *mae = &sa->mae;
 
-	if (spec->match_spec == NULL)
+	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* An active rule is reused. Its class is known to be valid. */
 		return 0;
+	}
 
-	TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
-		const struct sfc_flow_spec *entry_spec = &entry->spec;
-		const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
-		const efx_mae_match_spec_t *left = es_mae->match_spec;
-		const efx_mae_match_spec_t *right = spec->match_spec;
+	TAILQ_FOREACH_REVERSE(entry, &mae->action_rules,
+			      sfc_mae_action_rules, entries) {
+		const efx_mae_match_spec_t *left = entry->match_spec;
+		const efx_mae_match_spec_t *right = rule->match_spec;
 
-		switch (entry_spec->type) {
-		case SFC_FLOW_SPEC_FILTER:
-			/* Ignore VNIC-level flows */
-			break;
-		case SFC_FLOW_SPEC_MAE:
-			if (sfc_mae_rules_class_cmp(sa, left, right))
-				return 0;
-			break;
-		default:
-			SFC_ASSERT(false);
-		}
+		if (entry == rule)
+			continue;
+
+		if (sfc_mae_rules_class_cmp(sa, left, right))
+			return 0;
 	}
 
 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
@@ -4126,6 +4345,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	int rc;
 
@@ -4138,7 +4358,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
-	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+	return sfc_mae_action_rule_class_verify(sa, action_rule);
 }
 
 int
@@ -4147,55 +4367,22 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_fw_rsrc *fw_rsrc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	int rc;
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_enable(sa, outer_rule,
-					       spec_mae->match_spec);
-		if (rc != 0)
-			goto fail_outer_rule_enable;
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
 		spec_mae->ft_ctx->reset_tunnel_hit_counter =
 			spec_mae->ft_ctx->switch_hit_counter;
 	}
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "enabled flow=%p (no AR)", flow);
+	if (action_rule == NULL)
 		return 0;
-	}
-
-	rc = sfc_mae_action_set_enable(sa, action_set);
-	if (rc != 0)
-		goto fail_action_set_enable;
-
-	fw_rsrc = &action_set->fw_rsrc;
 
-	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
-					NULL, &fw_rsrc->aset_id,
-					&spec_mae->rule_id);
+	rc = sfc_mae_action_rule_enable(sa, action_rule);
 	if (rc != 0)
-		goto fail_action_rule_insert;
-
-	sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
+		return rc;
 
 	return 0;
-
-fail_action_rule_insert:
-	sfc_mae_action_set_disable(sa, action_set);
-
-fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
-
-fail_outer_rule_enable:
-	return rc;
 }
 
 int
@@ -4204,30 +4391,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	int rc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "disabled flow=%p (no AR)", flow);
-		goto skip_action_rule;
-	}
-
-	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
-
-	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
-			flow, spec_mae->rule_id.id, strerror(rc));
-	}
-	sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
-	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
-
-	sfc_mae_action_set_disable(sa, action_set);
+	if (action_rule == NULL)
+		return 0;
 
-skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
+	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
 }
@@ -4239,17 +4408,20 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 		      struct rte_flow_query_count *data,
 		      struct rte_flow_error *error)
 {
-	struct sfc_mae_action_set *action_set = spec->action_set;
+	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
+	struct sfc_mae_action_set *action_set;
 	unsigned int i;
 	int rc;
 
-	if (action_set == NULL || action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
+	action_set = action_rule->action_set;
+
 	for (i = 0; i < action_set->n_counters; i++) {
 		/*
 		 * Get the first available counter of the flow rule if
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1d937c9b5b..cbe190075c 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -97,6 +97,17 @@ struct sfc_mae_action_set {
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 
+/** Action rule registry entry */
+struct sfc_mae_action_rule {
+	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	struct sfc_mae_outer_rule		*outer_rule;
+	struct sfc_mae_action_set		*action_set;
+	efx_mae_match_spec_t			*match_spec;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+	unsigned int				refcnt;
+};
+TAILQ_HEAD(sfc_mae_action_rules, sfc_mae_action_rule);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -201,6 +212,8 @@ struct sfc_mae {
 	struct sfc_mae_mac_addrs	mac_addrs;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Action rule registry */
+	struct sfc_mae_action_rules	action_rules;
 	/** Encap. header bounce buffer */
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 21/34] common/sfc_efx/base: provide an API to clone MAE match specs
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (19 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

The DPDK driver would like to have a means to make a copy of
the action rule match specification before trying to dissect
it to possibly move out the per-connection 5-tuple data from
it to build up an entry in the HW conntrack assistance table.

Making such a copy at the end of parsing should be preferred
over maintaining DPDK-level structures because the resulting
code is easier on eyes and less prone to errors in this case.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cdf8a99abf..d327a9978f 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4452,6 +4452,13 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_match_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4c33471f28..63eefd6880 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1163,6 +1163,32 @@ efx_mae_match_spec_mport_set(
 
 fail2:
 	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep)
+{
+	efx_mae_match_spec_t *clone;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
+	if (clone == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
+
+	*clonep = clone;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index b596369c48..73ec02d478 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_alloc;
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
+	efx_mae_match_spec_clone;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 22/34] common/sfc_efx/base: add API to read back MAE match criteria
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (20 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
                   ` (14 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance in the DPDK driver. In order to detect flows that
are subject to such assistance, the driver needs to retrieve
5-tuple match data from an already constructed specification.

A dedicated API to selectively read back match criteria will
make a neat solution to keep the implementation less complex.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  10 ++
 drivers/common/sfc_efx/base/efx_mae.c | 131 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   1 +
 3 files changed, 142 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index d327a9978f..fc5c64c2d1 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4430,6 +4430,16 @@ efx_mae_match_spec_field_set(
 	__in				size_t mask_size,
 	__in_bcount(mask_size)		const uint8_t *mask);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask);
+
 /* The corresponding mask will be set to B_TRUE. */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 63eefd6880..48f98e3c42 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1054,6 +1054,137 @@ efx_mae_match_spec_field_set(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	unsigned int desc_set_nentries;
+	const uint8_t *mvp;
+	efx_rc_t rc;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
+	case EFX_MAE_RULE_ACTION:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((unsigned int)field_id >= desc_set_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (descp->emmd_mask_size == 0) {
+		/* The ID points to a gap in the array of field descriptors. */
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (value != NULL && value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (mask != NULL && mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	if (value == NULL && value_size != 0) {
+		rc = EINVAL;
+		goto fail6;
+	}
+
+	if (mask == NULL && mask_size != 0) {
+		rc = EINVAL;
+		goto fail7;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The MCDI request field is in network (big endian) order.
+		 * The mask/value are also big endian.
+		 */
+		memcpy(value, mvp + descp->emmd_value_offset, value_size);
+		memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The MCDI request field is little endian.
+		 * The mask/value are in host byte order.
+		 */
+		switch (value_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_value_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)value =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(value, mvp + descp->emmd_value_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_mask_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)mask =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(mask, mvp + descp->emmd_mask_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 73ec02d478..3ac2fb12f3 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -126,6 +126,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 23/34] common/sfc_efx/base: match on conntrack mark in action rules
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (21 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

EF100 match-action engine (MAE) has conntrack assistance
table. A hit in this table can provide a mark value for
the following lookup stage, which is action rule lookup.

Provide support for setting match on conntrack mark.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 28 +++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index fc5c64c2d1..e923032191 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4276,6 +4276,7 @@ typedef enum efx_mae_field_id_e {
 	 * or by using dedicated field-specific helper APIs.
 	 */
 	EFX_MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_CT_MARK,
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
@@ -4462,6 +4463,12 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_match_spec_clone(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 48f98e3c42..3dcce88928 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -474,6 +474,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
 	EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
 	EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -549,6 +550,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
 	EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
 
 #undef EFX_MAE_MV_DESC
 };
@@ -910,6 +912,32 @@ efx_mae_match_spec_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	mp = (const uint8_t *)&full_mask;
+	vp = (const uint8_t *)&ct_mark;
+
+	rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
+					  sizeof (ct_mark), vp,
+					  sizeof (full_mask), mp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 3ac2fb12f3..d0c7e99686 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -126,6 +126,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_ct_mark_set;
 	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (22 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such can be initiated when a packet hits an outer rule.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  9 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 37 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index e923032191..141481372c 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4679,6 +4679,15 @@ efx_mae_outer_rule_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+/*
+ * Request that packets hitting this rule be submitted
+ * for a lookup in the conntrack assistance table.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec);
+
 LIBEFX_API
 extern	__checkReturn		efx_rc_t
 efx_mae_outer_rule_insert(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 45e99d01c5..34e25ef990 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1761,6 +1761,7 @@ struct efx_mae_match_spec_s {
 		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 	uint8_t				emms_outer_rule_recirc_id;
+	boolean_t			emms_outer_rule_do_ct;
 };
 
 typedef enum efx_mae_action_e {
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 3dcce88928..b3127b6db8 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -2366,6 +2366,26 @@ efx_mae_outer_rule_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec)
+{
+	efx_rc_t rc;
+
+	if (spec->emms_type != EFX_MAE_RULE_OUTER) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	spec->emms_outer_rule_do_ct = B_TRUE;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
@@ -2386,6 +2406,7 @@ efx_mae_outer_rule_insert(
 	uint32_t encap_type_mcdi;
 	efx_mae_rule_id_t or_id;
 	size_t offset;
+	uint8_t do_ct;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
@@ -2448,6 +2469,11 @@ efx_mae_outer_rule_insert(
 	    MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
 	    spec->emms_outer_rule_recirc_id);
 
+	do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
+
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
+	    MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d0c7e99686..f567f667b5 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -144,6 +144,7 @@ INTERNAL {
 	efx_mae_mport_free;
 	efx_mae_mport_id_by_selector;
 	efx_mae_mport_invalid;
+	efx_mae_outer_rule_do_ct_set;
 	efx_mae_outer_rule_insert;
 	efx_mae_outer_rule_recirc_id_set;
 	efx_mae_outer_rule_remove;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 25/34] net/sfc: make use of conntrack assistance for transfer flows
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (23 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
                   ` (11 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

NAT and CT counters will be supported later.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h |   4 +
 drivers/net/sfc/sfc_mae.c  | 314 +++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  |   1 +
 3 files changed, 310 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 10c73d012f..8f706fc589 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -18,6 +18,7 @@
 #include "efx.h"
 
 #include "sfc_flow_rss.h"
+#include "sfc_mae_ct.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +83,9 @@ struct sfc_flow_spec_mae {
 	struct sfc_mae_outer_rule	*outer_rule;
 	/* Action rule registry entry */
 	struct sfc_mae_action_rule	*action_rule;
+	/* Conntrack (CT) assistance table entry key and response */
+	sfc_mae_conntrack_response_t	ct_resp;
+	sfc_mae_conntrack_key_t		ct_key;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 3da29f5257..167426eaf3 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -18,6 +18,7 @@
 #include "sfc.h"
 #include "sfc_flow_tunnel.h"
 #include "sfc_mae_counter.h"
+#include "sfc_mae_ct.h"
 #include "sfc_log.h"
 #include "sfc_switch.h"
 #include "sfc_service.h"
@@ -1179,18 +1180,23 @@ struct sfc_mae_action_rule_ctx {
 	struct sfc_mae_outer_rule	*outer_rule;
 	struct sfc_mae_action_set	*action_set;
 	efx_mae_match_spec_t		*match_spec;
+	uint32_t			ct_mark;
 };
 
 static int
 sfc_mae_action_rule_attach(struct sfc_adapter *sa,
-			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule_ctx *ctx,
 			   struct sfc_mae_action_rule **rulep,
-			   __rte_unused struct rte_flow_error *error)
+			   struct rte_flow_error *error)
 {
+	uint32_t new_ct_mark = ctx->ct_mark;
 	struct sfc_mae_action_rule *rule;
+	int rc;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	SFC_ASSERT(ctx->ct_mark <= 1);
+
 	/*
 	 * It is assumed that the caller of this helper has already properly
 	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
@@ -1198,10 +1204,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
 	 */
 	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->ct_mark == new_ct_mark)
+			++new_ct_mark;
+
 		if (rule->outer_rule != ctx->outer_rule ||
-		    rule->action_set != ctx->action_set)
+		    rule->action_set != ctx->action_set ||
+		    !!rule->ct_mark != !!ctx->ct_mark)
 			continue;
 
+		if (ctx->ct_mark != 0) {
+			rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+							    rule->ct_mark);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark for comparison");
+			}
+		}
+
 		if (efx_mae_match_specs_equal(rule->match_spec,
 					      ctx->match_spec)) {
 			sfc_dbg(sa, "attaching to action_rule=%p", rule);
@@ -1211,6 +1231,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 		}
 	}
 
+	if (ctx->ct_mark != 0) {
+		if (new_ct_mark == UINT32_MAX) {
+			return rte_flow_error_set(error, ERANGE,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to allocate CT mark");
+		}
+
+		rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+						    new_ct_mark);
+		if (rc != 0) {
+			return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark");
+		}
+
+		ctx->ct_mark = new_ct_mark;
+	}
+
 	/*
 	 * No need to set RTE error, as this
 	 * code should be handled gracefully.
@@ -1233,6 +1271,17 @@ sfc_mae_action_rule_add(struct sfc_adapter *sa,
 		return ENOMEM;
 
 	rule->refcnt = 1;
+
+	/*
+	 * It is assumed that the caller invoked sfc_mae_action_rule_attach()
+	 * and got (-ENOENT) before getting here. That ensures a unique CT
+	 * mark value or, if no CT is involved at all, simply zero.
+	 *
+	 * It is also assumed that match on the mark (if non-zero)
+	 * is already set in the action rule match specification.
+	 */
+	rule->ct_mark = ctx->ct_mark;
+
 	rule->outer_rule = ctx->outer_rule;
 	rule->action_set = ctx->action_set;
 	rule->match_spec = ctx->match_spec;
@@ -1804,6 +1853,8 @@ struct sfc_mae_field_locator {
 	size_t				size;
 	/* Field offset in the corresponding rte_flow_item_ struct */
 	size_t				ofst;
+
+	uint8_t				ct_key_field;
 };
 
 static void
@@ -2656,6 +2707,216 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 	},
 };
 
+#define SFC_MAE_CT_KEY_ET 0x01 /* EtherType */
+#define SFC_MAE_CT_KEY_DA 0x02 /* IPv4/IPv6 destination address */
+#define SFC_MAE_CT_KEY_SA 0x04 /* IPv4/IPv6 source address */
+#define SFC_MAE_CT_KEY_L4 0x08 /* IPv4/IPv6 L4 protocol ID */
+#define SFC_MAE_CT_KEY_DP 0x10 /* L4 destination port */
+#define SFC_MAE_CT_KEY_SP 0x20 /* L4 source port */
+
+#define SFC_MAE_CT_KEY_FIELD_SIZE_MAX	sizeof(sfc_mae_conntrack_key_t)
+
+static const struct sfc_mae_field_locator flocs_ct[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ether_type_le),
+		offsetof(sfc_mae_conntrack_key_t, ether_type_le),
+		SFC_MAE_CT_KEY_ET,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_IP_PROTO,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ip_proto),
+		offsetof(sfc_mae_conntrack_key_t, ip_proto),
+		SFC_MAE_CT_KEY_L4,
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, dst_port_le),
+		offsetof(sfc_mae_conntrack_key_t, dst_port_le),
+		SFC_MAE_CT_KEY_DP,
+	},
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, src_port_le),
+		offsetof(sfc_mae_conntrack_key_t, src_port_le),
+		SFC_MAE_CT_KEY_SP,
+	},
+};
+
+static int
+sfc_mae_rule_process_ct(struct sfc_adapter *sa, struct sfc_mae_parse_ctx *pctx,
+			struct sfc_mae_action_rule_ctx *action_rule_ctx,
+			struct sfc_flow_spec_mae *spec,
+			struct rte_flow_error *error)
+{
+	efx_mae_match_spec_t *match_spec_tmp;
+	uint8_t ct_key_missing_fields =
+		SFC_MAE_CT_KEY_ET | SFC_MAE_CT_KEY_DA | SFC_MAE_CT_KEY_SA |
+		SFC_MAE_CT_KEY_L4 | SFC_MAE_CT_KEY_DP | SFC_MAE_CT_KEY_SP;
+	unsigned int i;
+	int rc;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * TUNNEL rules have no network match fields that belong
+		 * in an action rule match specification, so nothing can
+		 * be possibly utilised for conntrack assistance offload.
+		 */
+		return 0;
+	}
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return 0;
+
+	rc = efx_mae_match_spec_clone(sa->nic, pctx->match_spec_action,
+				      &match_spec_tmp);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"AR: failed to clone the match specification");
+	}
+
+	for (i = 0; i < RTE_DIM(flocs_ct); ++i) {
+		const struct sfc_mae_field_locator *fl = &flocs_ct[i];
+		uint8_t mask_full[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask_zero[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t value[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t *ct_key = (uint8_t *)&spec->ct_key;
+		efx_mae_field_id_t fid = fl->field_id;
+		unsigned int j;
+
+		rc = efx_mae_match_spec_field_get(match_spec_tmp, fid,
+						  fl->size, value,
+						  fl->size, mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to extract match field");
+		}
+
+		memset(mask_full, 0xff, fl->size);
+
+		if (memcmp(mask, mask_full, fl->size) != 0)
+			continue;
+
+		memset(mask_zero, 0, fl->size);
+
+		rc = efx_mae_match_spec_field_set(match_spec_tmp, fid,
+						  fl->size, mask_zero,
+						  fl->size, mask_zero);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to erase match field");
+		}
+
+		for (j = 0; j < fl->size; ++j) {
+			uint8_t *byte_dst = ct_key + fl->ofst + fl->size - 1 - j;
+			const uint8_t *byte_src = value + j;
+
+			*byte_dst = *byte_src;
+		}
+
+		ct_key_missing_fields &= ~(fl->ct_key_field);
+	}
+
+	if (ct_key_missing_fields != 0) {
+		efx_mae_match_spec_fini(sa->nic, match_spec_tmp);
+		return 0;
+	}
+
+	efx_mae_match_spec_fini(sa->nic, pctx->match_spec_action);
+	pctx->match_spec_action = match_spec_tmp;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		/*
+		 * A SWITCH rule re-uses the corresponding TUNNEL rule's
+		 * outer rule, where conntrack request should have been
+		 * configured already, so skip outer rule processing.
+		 */
+		goto skip_outer_rule;
+	}
+
+	if (pctx->match_spec_outer == NULL) {
+		const struct sfc_mae_pattern_data *pdata = &pctx->pattern_data;
+		const struct sfc_mae_ethertype *et;
+		struct sfc_mae *mae = &sa->mae;
+
+		rc = efx_mae_match_spec_init(sa->nic,
+					     EFX_MAE_RULE_OUTER,
+					     mae->nb_outer_rule_prios_max - 1,
+					     &pctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to initialise the match specification");
+		}
+
+		/* Match on EtherType appears to be compulsory in outer rules */
+
+		et = &pdata->ethertypes[pdata->nb_vlan_tags];
+
+		rc = efx_mae_match_spec_field_set(pctx->match_spec_outer,
+				EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
+				sizeof(et->value), (const uint8_t *)&et->value,
+				sizeof(et->mask), (const uint8_t *)&et->mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to set match on EtherType");
+		}
+	}
+
+	rc = efx_mae_outer_rule_do_ct_set(pctx->match_spec_outer);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to request CT lookup");
+	}
+
+skip_outer_rule:
+	/* Initial/dummy CT mark value */
+	action_rule_ctx->ct_mark = 1;
+
+	return 0;
+}
+
+#undef SFC_MAE_CT_KEY_ET
+#undef SFC_MAE_CT_KEY_DA
+#undef SFC_MAE_CT_KEY_SA
+#undef SFC_MAE_CT_KEY_L4
+#undef SFC_MAE_CT_KEY_DP
+#undef SFC_MAE_CT_KEY_SP
+
 static int
 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_parse_ctx *ctx,
@@ -2679,13 +2940,11 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
+	if (ctx->match_spec_outer == NULL) {
 		*rulep = NULL;
 		goto no_or_id;
 	}
 
-	SFC_ASSERT(ctx->match_spec_outer != NULL);
-
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -2812,6 +3071,7 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 {
 	const struct rte_flow_item *pattern = ctx->pattern;
 	struct sfc_mae *mae = &sa->mae;
+	bool request_ct = false;
 	uint8_t recirc_id = 0;
 	int rc;
 
@@ -2907,6 +3167,14 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		recirc_id = SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id);
+
+		if (sfc_mae_conntrack_is_supported(sa)) {
+			/*
+			 * Request lookup in conntrack table since SWITCH rules
+			 * are eligible to utilise this type of assistance.
+			 */
+			request_ct = true;
+		}
 		/* FALLTHROUGH */
 	case SFC_FT_RULE_NONE:
 		if (ctx->priority >= mae->nb_outer_rule_prios_max) {
@@ -2940,6 +3208,16 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 					"OR: failed to initialise RECIRC_ID");
 		}
+
+		if (!request_ct)
+			break;
+
+		rc = efx_mae_outer_rule_do_ct_set(ctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to request CT lookup");
+		}
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/* Outermost items -> "ENC" match fields in the action rule. */
@@ -2961,9 +3239,6 @@ static void
 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 			      struct sfc_mae_parse_ctx *ctx)
 {
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
-		return;
-
 	if (ctx->match_spec_outer != NULL)
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
@@ -3067,6 +3342,11 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
+	rc = sfc_mae_rule_process_ct(sa, &ctx_mae, action_rule_ctx,
+				     spec, error);
+	if (rc != 0)
+		goto fail_process_ct;
+
 	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
@@ -3085,6 +3365,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 fail_validate_match_spec_action:
 fail_process_outer:
+fail_process_ct:
 fail_process_pattern_data:
 fail_parse_pattern:
 	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
@@ -4382,6 +4663,18 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
+	if (spec_mae->action_rule->ct_mark != 0) {
+		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
+		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
+					      &spec_mae->ct_resp);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -4396,6 +4689,9 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule == NULL)
 		return 0;
 
+	if (action_rule->ct_mark != 0)
+		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index cbe190075c..67fa2ca5c9 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -100,6 +100,7 @@ TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 /** Action rule registry entry */
 struct sfc_mae_action_rule {
 	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	uint32_t				ct_mark;
 	struct sfc_mae_outer_rule		*outer_rule;
 	struct sfc_mae_action_set		*action_set;
 	efx_mae_match_spec_t			*match_spec;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 26/34] common/sfc_efx/base: support NAT edits in MAE
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (24 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

NAT goes after IP TTL decrement. It can operate
on the outermost frame only. In the case of
prior decapsulation, that maps to the frame
which was (originally) the inner one. Input
data for the action comes from the response
of the HW conntrack assistance table hit.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      | 13 +++++++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 17 +++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 32 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 141481372c..abde5fea2e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4560,6 +4560,19 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_decr_ip_ttl(
 	__in				efx_mae_actions_t *spec);
 
+/*
+ * This only requests NAT action. The replacement IP address and
+ * L4 port number, as well as the edit direction (DST/SRC), come
+ * from the response to a hit in the conntrack assistance table.
+ *
+ * The action amends the outermost frame. In the case of prior
+ * decapsulation, that maps to the (originally) inner frame.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 34e25ef990..f9d60b9eb9 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1771,6 +1771,7 @@ typedef enum efx_mae_action_e {
 	EFX_MAE_ACTION_SET_DST_MAC,
 	EFX_MAE_ACTION_SET_SRC_MAC,
 	EFX_MAE_ACTION_DECR_IP_TTL,
+	EFX_MAE_ACTION_NAT,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_COUNT,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index b3127b6db8..154d2f1942 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1834,6 +1834,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_DECR_IP_TTL] = {
 		.emad_add = efx_mae_action_set_no_op
 	},
+	[EFX_MAE_ACTION_NAT] = {
+		.emad_add = efx_mae_action_set_no_op
+	},
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
@@ -1860,6 +1863,7 @@ static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_SET_DST_MAC) |
 	(1U << EFX_MAE_ACTION_SET_SRC_MAC) |
 	(1U << EFX_MAE_ACTION_DECR_IP_TTL) |
+	(1U << EFX_MAE_ACTION_NAT) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	/*
 	 * HW will conduct action COUNT after
@@ -2035,6 +2039,14 @@ efx_mae_action_set_populate_decr_ip_ttl(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_NAT, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
 	__in				efx_mae_actions_t *spec,
@@ -3090,6 +3102,11 @@ efx_mae_action_set_alloc(
 		    MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
 	}
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
+	}
+
 	if (spec->ema_n_vlan_tags_to_push > 0) {
 		unsigned int outer_tag_idx;
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f567f667b5..f601110f84 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -105,6 +105,7 @@ INTERNAL {
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_mark_reset;
+	efx_mae_action_set_populate_nat;
 	efx_mae_action_set_populate_set_dst_mac;
 	efx_mae_action_set_populate_set_src_mac;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (25 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

For this offload to work, the innermost pattern items must
provide the full set of exact match criteria, which are as
follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
and TP SRC, where the protocol types can be autodetected.

The offload requires that the IPv4 and the TP actions be
requested simultaneously in the same flow by the caller:
SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.

The offload operates on the outermost frame, which,
if action VXLAN_DECAP was requested, maps to the
inner frame of the original packet. The caller
is responsible to request this offload only
when the target header is an IPv4-based one.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini |  4 ++
 doc/guides/nics/sfc_efx.rst      |  8 ++++
 drivers/net/sfc/sfc_mae.c        | 77 ++++++++++++++++++++++++++++----
 3 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index f5ac644278..19d4935ce6 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -75,8 +75,12 @@ port_representor     = Y
 represented_port     = Y
 queue                = Y
 rss                  = Y
+set_ipv4_dst         = Y
+set_ipv4_src         = Y
 set_mac_dst          = Y
 set_mac_src          = Y
+set_tp_dst           = Y
+set_tp_src           = Y
 vf                   = Y
 vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index de0656876b..6e974c3720 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -270,10 +270,18 @@ Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- SET_IPV4_DST
+
+- SET_IPV4_SRC
+
 - SET_MAC_DST
 
 - SET_MAC_SRC
 
+- SET_TP_DST
+
+- SET_TP_SRC
+
 - OF_DEC_NW_TTL
 
 - DEC_TTL
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 167426eaf3..c03a43c6dd 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,6 +9,7 @@
 
 #include <stdbool.h>
 
+#include <rte_byteorder.h>
 #include <rte_bitops.h>
 #include <rte_common.h>
 #include <rte_vxlan.h>
@@ -3446,6 +3447,8 @@ sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
 };
 
 struct sfc_mae_actions_bundle {
@@ -3466,7 +3469,8 @@ struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      efx_mae_actions_t *spec)
+			      struct sfc_flow_spec_mae *flow_spec,
+			      bool ct, efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
@@ -3477,6 +3481,16 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 		rc = efx_mae_action_set_populate_vlan_push(
 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
+		flow_spec->ct_resp.nat.dir_is_dst = true;
+		/* FALLTHROUGH */
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
+		if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
+		    flow_spec->ct_resp.nat.port_le != 0)
+			rc = efx_mae_action_set_populate_nat(spec);
+		else
+			rc = EINVAL;
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -3493,7 +3507,8 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 static int
 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			    struct sfc_mae_actions_bundle *bundle,
-			    efx_mae_actions_t *spec,
+			    struct sfc_flow_spec_mae *flow_spec,
+			    efx_mae_actions_t *spec, bool ct,
 			    struct rte_flow_error *error)
 {
 	enum sfc_mae_actions_bundle_type bundle_type_new;
@@ -3505,6 +3520,14 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -3517,7 +3540,7 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 
 	if (bundle_type_new != bundle->type ||
 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
-		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
 		if (rc != 0)
 			goto fail_submit;
 
@@ -3534,6 +3557,20 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			"Failed to request the (group of) action(s)");
 }
 
+static void
+sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
+				   uint32_t *nat_addr_le)
+{
+	*nat_addr_le = rte_bswap32(conf->ipv4_addr);
+}
+
+static void
+sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
+				   uint16_t *nat_port_le)
+{
+	*nat_port_le = rte_bswap16(conf->port);
+}
+
 static void
 sfc_mae_rule_parse_action_of_push_vlan(
 			    const struct rte_flow_action_of_push_vlan *conf,
@@ -4058,6 +4095,10 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
 	[RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
@@ -4077,12 +4118,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct rte_flow *flow,
+			  struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
-	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4129,6 +4170,24 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_addr(action->conf,
+					&spec_mae->ct_resp.nat.ip_le);
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_port(action->conf,
+						&spec_mae->ct_resp.nat.port_le);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
 				       bundle->actions_mask);
@@ -4287,6 +4346,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
+	bool ct = (action_rule_ctx->ct_mark != 0);
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
 	struct sfc_mae *mae = &sa->mae;
@@ -4337,8 +4397,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_actions_bundle_sync(action, &bundle,
-						 ctx.spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+						 ctx.spec, ct, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
@@ -4348,7 +4408,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			goto fail_rule_parse_action;
 	}
 
-	rc = sfc_mae_actions_bundle_sync(action, &bundle, ctx.spec, error);
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+					 ctx.spec, ct, error);
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 28/34] net/sfc: rename SW structures used by transfer flow counters
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (26 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so facilitates rearrangements of the next patch needed
to make software counter objects shareable across many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 14 +++++++-------
 drivers/net/sfc/sfc_mae.h         | 14 +++++++-------
 drivers/net/sfc/sfc_mae_counter.c | 31 ++++++++++++++++---------------
 drivers/net/sfc/sfc_mae_counter.h | 16 ++++++++--------
 4 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c03a43c6dd..98cc60e04d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -151,7 +151,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		if (rc != 0)
 			goto fail_mae_get_limits;
 
-		sfc_log_init(sa, "init MAE counter registry");
+		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
 						   limits.eml_max_n_counters);
 		if (rc != 0) {
@@ -817,7 +817,7 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counters,
+			struct sfc_mae_counter *counters,
 			unsigned int n_counters,
 			efx_mae_actions_t *action_set_spec)
 {
@@ -833,7 +833,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(n_counters == 1);
 
-	rc = sfc_mae_counter_enable(sa, &counters[0]);
+	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
 	if (rc != 0) {
 		sfc_err(sa, "failed to enable MAE counter %u: %s",
 			counters[0].mae_id.id, rte_strerror(rc));
@@ -851,7 +851,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	return 0;
 
 fail_fill_in_id:
-	(void)sfc_mae_counter_disable(sa, &counters[0]);
+	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 
 fail_counter_add:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
@@ -860,7 +860,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter_id *counters,
+			 struct sfc_mae_counter *counters,
 			 unsigned int n_counters)
 {
 	if (n_counters == 0)
@@ -874,7 +874,7 @@ sfc_mae_counters_disable(struct sfc_adapter *sa,
 		return EALREADY;
 	}
 
-	return sfc_mae_counter_disable(sa, &counters[0]);
+	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 }
 
 struct sfc_mae_aset_ctx {
@@ -1039,7 +1039,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_counter *counters;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 67fa2ca5c9..7337fcf14d 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -68,7 +68,7 @@ struct sfc_mae_encap_header {
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
 /* Counter ID */
-struct sfc_mae_counter_id {
+struct sfc_mae_counter {
 	/* ID of a counter in MAE */
 	efx_counter_t			mae_id;
 	/* ID of a counter in RTE */
@@ -86,7 +86,7 @@ struct sfc_mae_counter_id {
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter_id	*counters;
+	struct sfc_mae_counter		*counters;
 	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
@@ -129,7 +129,7 @@ struct sfc_mae_bounce_eh {
 };
 
 /** Counter collection entry */
-struct sfc_mae_counter {
+struct sfc_mae_counter_record {
 	bool				inuse;
 	uint32_t			generation_count;
 	union sfc_pkts_bytes		value;
@@ -143,9 +143,9 @@ struct sfc_mae_counters_xstats {
 	uint64_t			realloc_update;
 };
 
-struct sfc_mae_counters {
+struct sfc_mae_counter_records {
 	/** An array of all MAE counters */
-	struct sfc_mae_counter		*mae_counters;
+	struct sfc_mae_counter_record	*mae_counters;
 	/** Extra statistics for counters */
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
@@ -162,7 +162,7 @@ enum sfc_mae_counter_polling_mode {
 struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Counters collection */
-	struct sfc_mae_counters		counters;
+	struct sfc_mae_counter_records	counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
@@ -219,7 +219,7 @@ struct sfc_mae {
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
 	bool				counter_rxq_running;
-	/** Counter registry */
+	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 818b4dad4a..8170175991 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -76,12 +76,12 @@ sfc_mae_counter_rxq_required(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_enable(struct sfc_adapter *sa,
-		       struct sfc_mae_counter_id *counterp)
+sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
@@ -147,12 +147,12 @@ sfc_mae_counter_enable(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counter_disable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counter)
+sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
@@ -189,12 +189,13 @@ sfc_mae_counter_disable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_counter_increment(struct sfc_adapter *sa,
-			  struct sfc_mae_counters *counters,
+			  struct sfc_mae_counter_records *counters,
 			  uint32_t mae_counter_id,
 			  uint32_t generation_count,
 			  uint64_t pkts, uint64_t bytes)
 {
-	struct sfc_mae_counter *p = &counters->mae_counters[mae_counter_id];
+	struct sfc_mae_counter_record *p =
+		&counters->mae_counters[mae_counter_id];
 	struct sfc_mae_counters_xstats *xstats = &counters->xstats;
 	union sfc_pkts_bytes cnt_val;
 	bool inuse;
@@ -667,7 +668,7 @@ sfc_mae_counter_thread_spawn(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counters_init(struct sfc_mae_counters *counters,
+sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 		      uint32_t nb_counters_max)
 {
 	int rc;
@@ -691,7 +692,7 @@ sfc_mae_counters_init(struct sfc_mae_counters *counters,
 }
 
 void
-sfc_mae_counters_fini(struct sfc_mae_counters *counters)
+sfc_mae_counters_fini(struct sfc_mae_counter_records *counters)
 {
 	rte_free(counters->mae_counters);
 	counters->mae_counters = NULL;
@@ -942,13 +943,13 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counters *counters,
-		    const struct sfc_mae_counter_id *counter,
+sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
 	uint64_t non_reset_tunnel_hit_counter;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
 	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 28d70f7d69..9c6d8103ac 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -38,15 +38,15 @@ void sfc_mae_counter_rxq_detach(struct sfc_adapter *sa);
 int sfc_mae_counter_rxq_init(struct sfc_adapter *sa);
 void sfc_mae_counter_rxq_fini(struct sfc_adapter *sa);
 
-int sfc_mae_counters_init(struct sfc_mae_counters *counters,
+int sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 			  uint32_t nb_counters_max);
-void sfc_mae_counters_fini(struct sfc_mae_counters *counters);
-int sfc_mae_counter_enable(struct sfc_adapter *sa,
-			   struct sfc_mae_counter_id *counterp);
-int sfc_mae_counter_disable(struct sfc_adapter *sa,
-			    struct sfc_mae_counter_id *counter);
-int sfc_mae_counter_get(struct sfc_mae_counters *counters,
-			const struct sfc_mae_counter_id *counter,
+void sfc_mae_counters_fini(struct sfc_mae_counter_records *counters);
+int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+				   struct sfc_mae_counter *counterp);
+int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				    struct sfc_mae_counter *counter);
+int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
 int sfc_mae_counter_start(struct sfc_adapter *sa);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 29/34] net/sfc: rework MAE action rule counter representation in SW
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (27 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such rework is needed to prepare for INDIRECT action support
and in order to align with the latest HW support perspective.

Currently, the driver supports only one counter per flow. It
was once thought that MAE would support multiple counters in
one action set. That was partly envisaged in code and naming.
But HW support for the feature is no longer planned in EF100.

The code also assumes that a counter object cannot be shared.
This assumption is outdated. The driver may support this now
via action of type INDIRECT provided by generic flow library.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 342 +++++++++++++++++-------------
 drivers/net/sfc/sfc_mae.h         |  17 +-
 drivers/net/sfc/sfc_mae_counter.c |  22 +-
 3 files changed, 211 insertions(+), 170 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 98cc60e04d..d44e066493 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
+	TAILQ_INIT(&mae->counters);
 	TAILQ_INIT(&mae->action_sets);
 	TAILQ_INIT(&mae->action_rules);
 
@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter *counters,
-			unsigned int n_counters,
-			efx_mae_actions_t *action_set_spec)
+sfc_mae_counter_add(struct sfc_adapter *sa,
+		    const struct sfc_mae_counter *counter_tmp,
+		    struct sfc_mae_counter **counterp)
 {
-	int rc;
+	struct sfc_mae_counter *counter;
+	struct sfc_mae *mae = &sa->mae;
 
-	sfc_log_init(sa, "entry");
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	if (n_counters == 0) {
-		sfc_log_init(sa, "no counters - skip");
-		return 0;
+	counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
+	if (counter == NULL)
+		return ENOMEM;
+
+	if (counter_tmp != NULL) {
+		counter->rte_id_valid = counter_tmp->rte_id_valid;
+		counter->rte_id = counter_tmp->rte_id;
 	}
 
-	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
+	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+	counter->refcnt = 1;
 
-	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
-	if (rc != 0) {
-		sfc_err(sa, "failed to enable MAE counter %u: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_counter_add;
-	}
+	TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
+	*counterp = counter;
 
-	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
-						   &counters[0].mae_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_fill_in_id;
-	}
+	sfc_dbg(sa, "added counter=%p", counter);
 
 	return 0;
+}
+
+static void
+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae *mae = &sa->mae;
 
-fail_fill_in_id:
-	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	if (counter == NULL)
+		return;
 
-fail_counter_add:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(counter->refcnt != 0);
+
+	--(counter->refcnt);
+
+	if (counter->refcnt != 0)
+		return;
+
+	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    counter->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
+			counter, counter->fw_rsrc.counter_id.id,
+			counter->fw_rsrc.refcnt);
+	}
+
+	TAILQ_REMOVE(&mae->counters, counter, entries);
+	rte_free(counter);
+
+	sfc_dbg(sa, "deleted counter=%p", counter);
 }
 
 static int
-sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter *counters,
-			 unsigned int n_counters)
+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
+		       efx_mae_actions_t *action_set_spec)
 {
-	if (n_counters == 0)
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
 		return 0;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
 
-	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
-		sfc_err(sa, "failed to disable: already disabled");
-		return EALREADY;
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
+
+		rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
+		if (rc != 0) {
+			sfc_err(sa, "failed to enable counter=%p: %s",
+				counter, rte_strerror(rc));
+			return rc;
+		}
+	}
+
+	if (action_set_spec != NULL) {
+		rc = efx_mae_action_set_fill_in_counter_id(
+					action_set_spec, &fw_rsrc->counter_id);
+		if (rc != 0) {
+			if (fw_rsrc->refcnt == 0) {
+				(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
+				fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+			}
+
+			sfc_err(sa, "cannot fill in counter ID: %s",
+				strerror(rc));
+			return rc;
+		}
+	}
+
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
+			counter, fw_rsrc->counter_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static void
+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
+			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		uint32_t counter_id = fw_rsrc->counter_id.id;
+
+		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
+				counter, counter_id);
+		} else {
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
+				counter, counter_id, strerror(rc));
+		}
+
+		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
 	}
 
-	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	--(fw_rsrc->refcnt);
 }
 
 struct sfc_mae_aset_ctx {
-	uint64_t			*ft_switch_hit_counter;
-	struct sfc_ft_ctx		*counter_ft_ctx;
 	struct sfc_mae_encap_header	*encap_header;
-	unsigned int			n_counters;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_mac_addr		*dst_mac;
 	struct sfc_mae_mac_addr		*src_mac;
 
@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	/*
-	 * Shared counters are not supported, hence, action
-	 * sets with counters are not attachable.
-	 */
-	if (ctx->n_counters != 0)
-		return NULL;
-
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
 		if (action_set->encap_header == ctx->encap_header &&
 		    action_set->dst_mac_addr == ctx->dst_mac &&
 		    action_set->src_mac_addr == ctx->src_mac &&
+		    action_set->counter == ctx->counter &&
 		    efx_mae_action_set_specs_equal(action_set->spec,
 						   ctx->spec)) {
 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
-		       const struct rte_flow_action actions[],
 		       const struct sfc_mae_aset_ctx *ctx,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
 	struct sfc_mae *mae = &sa->mae;
-	unsigned int i;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 		return ENOMEM;
 	}
 
-	if (ctx->n_counters > 0) {
-		const struct rte_flow_action *action;
-
-		action_set->counters = rte_malloc("sfc_mae_counter_ids",
-			sizeof(action_set->counters[0]) * ctx->n_counters, 0);
-		if (action_set->counters == NULL) {
-			rte_free(action_set);
-			sfc_err(sa, "failed to alloc counters");
-			return ENOMEM;
-		}
-
-		for (i = 0; i < ctx->n_counters; ++i) {
-			action_set->counters[i].rte_id_valid = B_FALSE;
-			action_set->counters[i].mae_id.id =
-				EFX_MAE_RSRC_ID_INVALID;
-
-			action_set->counters[i].ft_ctx = ctx->counter_ft_ctx;
-			action_set->counters[i].ft_switch_hit_counter =
-				ctx->ft_switch_hit_counter;
-		}
-
-		for (action = actions, i = 0;
-		     action->type != RTE_FLOW_ACTION_TYPE_END &&
-		     i < ctx->n_counters; ++action) {
-			const struct rte_flow_action_count *conf;
-
-			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
-				continue;
-
-			conf = action->conf;
-
-			action_set->counters[i].rte_id_valid = B_TRUE;
-			action_set->counters[i].rte_id = conf->id;
-			i++;
-		}
-		action_set->n_counters = ctx->n_counters;
-	}
-
 	action_set->refcnt = 1;
 	action_set->spec = ctx->spec;
 	action_set->encap_header = ctx->encap_header;
 	action_set->dst_mac_addr = ctx->dst_mac;
 	action_set->src_mac_addr = ctx->src_mac;
+	action_set->counter = ctx->counter;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
 	sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
-	if (action_set->n_counters > 0) {
-		SFC_ASSERT(action_set->n_counters == 1);
-		SFC_ASSERT(action_set->counters[0].mae_id.id ==
-			   EFX_MAE_RSRC_ID_INVALID);
-		rte_free(action_set->counters);
-	}
+	sfc_mae_counter_del(sa, action_set->counter);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 
@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter *counters;
+	struct sfc_mae_counter *counter;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	encap_header = action_set->encap_header;
 	dst_mac_addr = action_set->dst_mac_addr;
 	src_mac_addr = action_set->src_mac_addr;
-	counters = action_set->counters;
 	fw_rsrc = &action_set->fw_rsrc;
+	counter = action_set->counter;
 
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
-		if (action_set->n_counters > 0) {
+		if (counter != NULL) {
 			rc = sfc_mae_counter_start(sa);
 			if (rc != 0) {
 				sfc_err(sa, "failed to start MAE counters support: %s",
@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			}
 		}
 
-		rc = sfc_mae_counters_enable(sa, counters,
-					     action_set->n_counters,
-					     action_set->spec);
+		rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
 		if (rc != 0) {
-			sfc_err(sa, "failed to enable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			sfc_err(sa, "failed to enable action_set=%p: %s",
 				action_set, strerror(rc));
 
-			(void)sfc_mae_counters_disable(sa, counters,
-						       action_set->n_counters);
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+			sfc_mae_counter_disable(sa, counter);
 			return rc;
 		}
 
@@ -1162,16 +1190,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 		}
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-		rc = sfc_mae_counters_disable(sa, action_set->counters,
-					      action_set->n_counters);
-		if (rc != 0) {
-			sfc_err(sa, "failed to disable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-		}
-
 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
 		sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
 		sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
+		sfc_mae_counter_disable(sa, action_set->counter);
 	}
 
 	--(fw_rsrc->refcnt);
@@ -3931,10 +3953,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
-				const struct rte_flow_action_count *conf
-					__rte_unused,
+				const struct rte_flow_action_count *conf,
+				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
+	struct sfc_mae_counter counter_tmp = {};
 	int rc;
 
 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
@@ -3949,17 +3972,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		goto fail_no_service_core;
 	}
 
-	rc = efx_mae_action_set_populate_count(spec);
-	if (rc != 0) {
-		sfc_err(sa,
-			"failed to populate counters in MAE action set: %s",
-			rte_strerror(rc));
-		goto fail_populate_count;
+	if (*counterp != NULL) {
+		sfc_err(sa, "cannot request more than 1 action COUNT per flow");
+		rc = EINVAL;
+		goto fail_more_than_one;
+	}
+
+	if (spec != NULL) {
+		rc = efx_mae_action_set_populate_count(spec);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to populate counters in MAE action set: %s",
+				rte_strerror(rc));
+			goto fail_populate_count;
+		}
+	}
+
+	if (conf != NULL) {
+		counter_tmp.rte_id_valid = true;
+		counter_tmp.rte_id = conf->id;
 	}
 
+	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
+
 	return 0;
 
 fail_populate_count:
+fail_more_than_one:
 fail_no_service_core:
 fail_counter_queue_uninit:
 
@@ -4126,7 +4165,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
+	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
+	efx_mae_actions_t *spec_ptr = spec;
 	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -4214,7 +4255,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
-		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
+		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
@@ -4364,19 +4406,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
-	for (action = actions;
-	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
-			++(ctx.n_counters);
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		bool have_user_action_count = false;
+
 		/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
 		rc = efx_mae_action_set_populate_decap(ctx.spec);
 		if (rc != 0)
 			goto fail_enforce_ft_decap;
 
-		if (ctx.n_counters == 0 &&
+		for (action = actions;
+		     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+			if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+				have_user_action_count = true;
+				break;
+			}
+		}
+
+		if (!have_user_action_count &&
 		    sfc_mae_counter_stream_enabled(sa)) {
 			/*
 			 * The user opted not to use action COUNT in this rule,
@@ -4388,7 +4434,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			if (rc != 0)
 				goto fail_enforce_ft_count;
 
-			ctx.n_counters = 1;
+			rc = sfc_mae_counter_add(sa, NULL, &ctx.counter);
+			if (rc != 0)
+				goto fail_enforce_ft_count;
 		}
 	}
 
@@ -4418,13 +4466,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_encap_header;
 
-	if (ctx.n_counters > 1) {
-		rc = ENOTSUP;
-		sfc_err(sa, "too many count actions requested: %u",
-			ctx.n_counters);
-		goto fail_nb_count;
-	}
-
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
@@ -4434,7 +4475,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_workaround_tunnel_delivery;
 
-		ctx.counter_ft_ctx = spec_mae->ft_ctx;
+		if (ctx.counter != NULL)
+			(ctx.counter)->ft_ctx = spec_mae->ft_ctx;
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
@@ -4443,7 +4485,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		ctx.ft_switch_hit_counter =
+		(ctx.counter)->ft_switch_hit_counter =
 			&spec_mae->ft_ctx->switch_hit_counter;
 		break;
 	default:
@@ -4467,6 +4509,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
 	if (action_rule_ctx->action_set != NULL) {
+		sfc_mae_counter_del(sa, ctx.counter);
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -4474,8 +4517,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx,
-				    &action_rule_ctx->action_set);
+	rc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -4484,11 +4526,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 fail_action_set_add:
 fail_check_fate_action:
 fail_workaround_tunnel_delivery:
-fail_nb_count:
 	sfc_mae_encap_header_del(sa, ctx.encap_header);
 
 fail_process_encap_header:
 fail_rule_parse_action:
+	sfc_mae_counter_del(sa, ctx.counter);
 	sfc_mae_mac_addr_del(sa, ctx.src_mac);
 	sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 	efx_mae_action_set_spec_fini(sa->nic, ctx.spec);
@@ -4768,28 +4810,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
 	struct sfc_mae_action_set *action_set;
-	unsigned int i;
+	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
 	action_set = action_rule->action_set;
+	counter = action_set->counter;
 
-	for (i = 0; i < action_set->n_counters; i++) {
-		/*
-		 * Get the first available counter of the flow rule if
-		 * counter ID is not specified, provided that this
-		 * counter is not an automatic (implicit) one.
-		 */
-		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
-			continue;
-
+	if (conf == NULL ||
+	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 &action_set->counters[i], data);
+					 counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 7337fcf14d..c73ce0a5e6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	unsigned int			refcnt;
 	RTE_STD_C11
 	union {
+		efx_counter_t		counter_id;
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
 		efx_mae_mac_id_t	mac_id;
@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {
 
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
-/* Counter ID */
+/* Counter object registry entry */
 struct sfc_mae_counter {
-	/* ID of a counter in MAE */
-	efx_counter_t			mae_id;
+	TAILQ_ENTRY(sfc_mae_counter)	entries;
+	unsigned int			refcnt;
+
 	/* ID of a counter in RTE */
 	uint32_t			rte_id;
 	/* RTE counter ID validity status */
@@ -80,18 +82,21 @@ struct sfc_mae_counter {
 	uint64_t			*ft_switch_hit_counter;
 	/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */
 	struct sfc_ft_ctx		*ft_ctx;
+
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter		*counters;
-	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_mac_addr		*dst_mac_addr;
 	struct sfc_mae_mac_addr		*src_mac_addr;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -221,6 +226,8 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
+	/** Counter object registry */
+	struct sfc_mae_counters		counters;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 8170175991..90b89e81c6 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 		goto fail_counter_id_range;
 	}
 
-	counterp->mae_id = mae_counter;
+	counterp->fw_rsrc.counter_id.id = mae_counter.id;
 
 	p = &counters->mae_counters[mae_counter.id];
 
@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
 	struct sfc_mae_counter_records *counters = &reg->counters;
+	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
-	if (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)
-		return 0;
-
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
+	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
 	 * at the beginning of delete operation. Release ordering is
 	 * paired with acquire ordering on load in counter increment operation.
 	 */
-	p = &counters->mae_counters[counter->mae_id.id];
+	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);
+	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
 	if (rc != 0)
 		sfc_err(sa, "failed to free MAE counter %u: %s",
-			counter->mae_id.id, rte_strerror(rc));
+			mae_counter->id, rte_strerror(rc));
 
 	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, counter->mae_id.id,
+		 " bytes=%" PRIu64, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	 * If there's some error, the resulting resource leakage is bad, but
 	 * nothing sensible can be done in this case.
 	 */
-	counter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;
+	mae_counter->id = EFX_MAE_RSRC_ID_INVALID;
 
 	return rc;
 }
@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
-	p = &counters->mae_counters[counter->mae_id.id];
+	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
+	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
 
 	/*
 	 * Ordering is relaxed since it is the only operation on counter value.
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 30/34] net/sfc: support indirect count action in transfer flows
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (28 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Indirect count action is useful to applications that
need to gather aggregated statistics for many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini |   1 +
 doc/guides/nics/sfc_efx.rst      |   2 +
 drivers/net/sfc/sfc.h            |   1 +
 drivers/net/sfc/sfc_flow.c       | 126 +++++++++++++++++++++++
 drivers/net/sfc/sfc_flow.h       |  14 +++
 drivers/net/sfc/sfc_mae.c        | 167 ++++++++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h        |  15 +++
 7 files changed, 325 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index 19d4935ce6..15a97ce8cd 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -62,6 +62,7 @@ count                = Y
 dec_ttl              = Y
 drop                 = Y
 flag                 = Y
+indirect             = P
 jump                 = P
 mark                 = Y
 of_dec_nw_ttl        = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 6e974c3720..ba82b02093 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -306,6 +306,8 @@ Supported actions (***transfer*** rules):
 
 - COUNT
 
+- INDIRECT
+
 - DROP
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 6b301aad60..f84a21009e 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -248,6 +248,7 @@ struct sfc_adapter {
 	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
+	struct sfc_flow_indir_actions	flow_indir_actions;
 	struct sfc_flow_list		flow_list;
 
 	unsigned int			rxq_max;
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 6f366c1b06..283f672d6d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static struct rte_flow_action_handle *
+sfc_flow_action_handle_create(struct rte_eth_dev *dev,
+			      const struct rte_flow_indir_action_conf *conf,
+			      const struct rte_flow_action *action,
+			      struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *handle;
+	int ret;
+
+	if (!conf->transfer) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "non-transfer domain does not support indirect actions");
+		return NULL;
+	}
+
+	if (conf->ingress || conf->egress) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "cannot combine ingress/egress with transfer");
+		return NULL;
+	}
+
+	handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0);
+	if (handle == NULL) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "failed to allocate memory");
+		return NULL;
+	}
+
+	sfc_adapter_lock(sa);
+
+	ret = sfc_mae_indir_action_create(sa, action, handle, error);
+	if (ret != 0) {
+		sfc_adapter_unlock(sa);
+		rte_free(handle);
+		return NULL;
+	}
+
+	TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);
+
+	handle->transfer = (bool)conf->transfer;
+
+	sfc_adapter_unlock(sa);
+
+	return handle;
+}
+
+static int
+sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,
+			       struct rte_flow_action_handle *handle,
+			       struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_destroy(sa, handle,
+							  error);
+			if (rc != 0)
+				goto exit;
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);
+		rte_free(entry);
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
+static int
+sfc_flow_action_handle_query(struct rte_eth_dev *dev,
+			     const struct rte_flow_action_handle *handle,
+			     void *data, struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_query(sa, handle,
+							data, error);
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
 const struct rte_flow_ops sfc_flow_ops = {
 	.validate = sfc_flow_validate,
 	.create = sfc_flow_create,
@@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = {
 	.flush = sfc_flow_flush,
 	.query = sfc_flow_query,
 	.isolate = sfc_flow_isolate,
+	.action_handle_create = sfc_flow_action_handle_create,
+	.action_handle_destroy = sfc_flow_action_handle_destroy,
+	.action_handle_query = sfc_flow_action_handle_query,
 	.tunnel_decap_set = sfc_ft_decap_set,
 	.tunnel_match = sfc_ft_match,
 	.tunnel_action_decap_release = sfc_ft_action_decap_release,
@@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa)
 {
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	TAILQ_INIT(&sa->flow_indir_actions);
 	TAILQ_INIT(&sa->flow_list);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 8f706fc589..af94d0654a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -88,6 +88,20 @@ struct sfc_flow_spec_mae {
 	sfc_mae_conntrack_key_t		ct_key;
 };
 
+/* PMD-specific definition of the opaque type from rte_flow.h */
+struct rte_flow_action_handle {
+	TAILQ_ENTRY(rte_flow_action_handle)	entries;
+
+	bool					transfer;
+	enum rte_flow_action_type		type;
+
+	union {
+		struct sfc_mae_counter		*counter;
+	};
+};
+
+TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle);
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d44e066493..9851690f58 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -4005,6 +4005,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa,
+				   const struct rte_flow_action_handle *handle,
+				   enum sfc_ft_rule_type ft_rule_type,
+				   struct sfc_mae_aset_ctx *ctx,
+				   struct rte_flow_error *error)
+{
+	struct rte_flow_action_handle *entry;
+	int rc;
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry == handle) {
+			sfc_dbg(sa, "attaching to indirect_action=%p", entry);
+
+			switch (entry->type) {
+			case RTE_FLOW_ACTION_TYPE_COUNT:
+				if (ft_rule_type != SFC_FT_RULE_NONE) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot use indirect count action in tunnel model");
+				}
+
+				if (ctx->counter != NULL) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot have multiple actions COUNT in one flow");
+				}
+
+				rc = efx_mae_action_set_populate_count(ctx->spec);
+				if (rc != 0) {
+					return rte_flow_error_set(error, rc,
+					 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					 "failed to add COUNT to MAE action set");
+				}
+
+				ctx->counter = entry->counter;
+				++(ctx->counter->refcnt);
+				break;
+			default:
+				SFC_ASSERT(B_FALSE);
+				break;
+			}
+
+			return 0;
+		}
+	}
+
+	return rte_flow_error_set(error, ENOENT,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				  "indirect action handle not found");
+}
+
 static int
 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
 				const struct rte_flow_action_vf *vf_conf,
@@ -4143,6 +4195,7 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
 	[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
 	[RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT",
+	[RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT",
 	[RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
 	[RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
 	[RTE_FLOW_ACTION_TYPE_PF] = "PF",
@@ -4258,6 +4311,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
 						     counterp, spec_ptr);
 		break;
+	case RTE_FLOW_ACTION_TYPE_INDIRECT:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_indirect(sa, action->conf,
+							spec_mae->ft_rule_type,
+							ctx, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -4813,7 +4874,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
+	if (action_rule == NULL || action_rule->action_set == NULL ||
+	    action_rule->action_set->counter == NULL ||
+	    action_rule->action_set->counter->indirect) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
@@ -4924,3 +4987,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
+
+int
+sfc_mae_indir_action_create(struct sfc_adapter *sa,
+			    const struct rte_flow_action *action,
+			    struct rte_flow_action_handle *handle,
+			    struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      &handle->counter, NULL);
+		if (ret == 0)
+			handle->counter->indirect = true;
+		break;
+	default:
+		ret = ENOTSUP;
+	}
+
+	if (ret != 0) {
+		return rte_flow_error_set(error, ret,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"failed to parse indirect action to mae object");
+	}
+
+	handle->type = action->type;
+
+	return 0;
+}
+
+int
+sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+			     const struct rte_flow_action_handle *handle,
+			     struct rte_flow_error *error)
+{
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		if (handle->counter->refcnt != 1)
+			goto fail;
+
+		sfc_mae_counter_del(sa, handle->counter);
+		break;
+	default:
+		SFC_ASSERT(B_FALSE);
+		break;
+	}
+
+	return 0;
+
+fail:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is still in use");
+}
+
+int
+sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			   const struct rte_flow_action_handle *handle,
+			   void *data, struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		SFC_ASSERT(handle->counter != NULL);
+
+		if (handle->counter->fw_rsrc.refcnt == 0)
+			goto fail_not_in_use;
+
+		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
+					  handle->counter, data);
+		if (ret != 0)
+			goto fail_counter_get;
+
+		break;
+	default:
+		goto fail_unsup;
+	}
+
+	return 0;
+
+fail_not_in_use:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is not in use");
+
+fail_counter_get:
+	return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "failed to collect indirect action COUNT data");
+
+fail_unsup:
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action of this type cannot be queried");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index c73ce0a5e6..e7b7d3a35e 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -84,6 +84,8 @@ struct sfc_mae_counter {
 	struct sfc_ft_ctx		*ft_ctx;
 
 	struct sfc_mae_fw_rsrc		fw_rsrc;
+
+	bool				indirect;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
+int sfc_mae_indir_action_create(struct sfc_adapter *sa,
+				const struct rte_flow_action *action,
+				struct rte_flow_action_handle *handle,
+				struct rte_flow_error *error);
+
+int sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+				 const struct rte_flow_action_handle *handle,
+				 struct rte_flow_error *error);
+
+int sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			       const struct rte_flow_action_handle *handle,
+			       void *data, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (29 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is required to disambiguate counters of different
types supported by the match-action engine (MAE) on EF100.

Currently, the code only supports action rule counters,
but MAE may also support conntrack assistance counters.
Add type-aware allocate and free MCDI handlers and
extend reporting of counter limits accordingly.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  39 +++++++-
 drivers/common/sfc_efx/base/efx_impl.h |   2 +-
 drivers/common/sfc_efx/base/efx_mae.c  | 120 ++++++++++++++++++++-----
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 140 insertions(+), 23 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index abde5fea2e..10908d97ef 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,7 +4191,10 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
 	uint32_t			eml_encap_header_size_limit;
-	uint32_t			eml_max_n_counters;
+	union {
+		uint32_t		eml_max_n_counters;
+		uint32_t		eml_max_n_action_counters;
+	};
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4780,6 +4783,14 @@ efx_mae_action_set_fill_in_eh_id(
 	__in				efx_mae_actions_t *spec,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/*
+ * Counter types that may be supported by the match-action engine.
+ * Each counter type maintains its own counter ID namespace in FW.
+ */
+typedef enum efx_counter_type_e {
+	EFX_COUNTER_TYPE_ACTION = 0,
+} efx_counter_type_t;
+
 typedef struct efx_counter_s {
 	uint32_t id;
 } efx_counter_t;
@@ -4823,6 +4834,8 @@ efx_mae_action_set_alloc(
 	__out				efx_mae_aset_id_t *aset_idp);
 
 /*
+ * Allocates MAE counter(s) of type EFX_COUNTER_TYPE_ACTION.
+ *
  * Generation count has two purposes:
  *
  * 1) Distinguish between counter packets that belong to freed counter
@@ -4846,6 +4859,20 @@ efx_mae_counters_alloc(
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+/*
+ * Allocates MAE counter(s) of the specified type. Other
+ * than that, behaves like efx_mae_counters_alloc().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_alloc_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_counters_free(
@@ -4855,6 +4882,16 @@ efx_mae_counters_free(
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 /* When set, include counters with a value of zero */
 #define	EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE	(1U << 0)
 
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index f9d60b9eb9..7e5701e801 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -841,7 +841,7 @@ typedef struct efx_mae_s {
 	/** Outer rule match field capabilities. */
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
-	uint32_t			em_max_ncounters;
+	uint32_t			em_max_n_action_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 154d2f1942..eddba0e71c 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -67,8 +67,8 @@ efx_mae_get_capabilities(
 	maep->em_max_nfields =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
 
-	maep->em_max_ncounters =
-	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS);
+	maep->em_max_n_action_counters =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
 	return (0);
 
@@ -374,7 +374,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
-	emlp->eml_max_n_counters = maep->em_max_ncounters;
+	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
 
 	return (0);
 
@@ -3263,55 +3263,70 @@ efx_mae_action_set_clear_fw_rsrc_ids(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_alloc(
+efx_mae_counters_alloc_type(
 	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
 	__in				uint32_t n_counters,
 	__out				uint32_t *n_allocatedp,
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_ALLOC_IN_LEN,
+	    MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	uint32_t n_allocated;
 	efx_mcdi_req_t req;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (n_counters > max_n_counters ||
 	    n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
 	    n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
 		rc = EINVAL;
-		goto fail1;
+		goto fail2;
 	}
 
 	req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
 
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
 	    n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_allocated = MCDI_OUT_DWORD(req,
 	    MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
 	if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	for (i = 0; i < n_allocated; i++) {
@@ -3328,6 +3343,8 @@ efx_mae_counters_alloc(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3341,33 +3358,67 @@ efx_mae_counters_alloc(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_free(
+efx_mae_counters_alloc(
 	__in				efx_nic_t *enp,
 	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
+					 n_counters, n_allocatedp,
+					 countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
 	__out				uint32_t *n_freedp,
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	efx_mcdi_req_t req;
 	uint32_t n_freed;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
-	    n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM ||
-	    n_counters >
-	    MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
 		rc = EINVAL;
 		goto fail1;
 	}
 
+	if (n_counters > max_n_counters ||
+	    n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
+	    n_counters >
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
 	req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters);
+	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
 
@@ -3378,23 +3429,25 @@ efx_mae_counters_free(
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
 			  n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
 
 	if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	if (gen_countp != NULL) {
@@ -3406,6 +3459,8 @@ efx_mae_counters_free(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3418,6 +3473,29 @@ efx_mae_counters_free(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_counters_free(
+	__in				efx_nic_t *enp,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
+					n_counters, n_freedp,
+					countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_counters_stream_start(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f601110f84..e91bcbcad8 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -114,7 +114,9 @@ INTERNAL {
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
 	efx_mae_counters_alloc;
+	efx_mae_counters_alloc_type;
 	efx_mae_counters_free;
+	efx_mae_counters_free_type;
 	efx_mae_counters_stream_give_credits;
 	efx_mae_counters_stream_start;
 	efx_mae_counters_stream_stop;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 32/34] net/sfc: indicate MAE counter type in use for transfer flows
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (30 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so assists adding support for additional counter types.

Current implementation is only aware of action rule counters
that are supported by the match-action engine (MAE) on EF100
NICs, but MAE may also support conntrack assistance counters.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 56 ++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |  7 ++-
 drivers/net/sfc/sfc_mae_counter.c | 77 +++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae_counter.h |  2 +-
 4 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 9851690f58..5687fa3af4 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,15 +65,24 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_counters_max)
+			      uint32_t nb_action_counters_max)
 {
-	return sfc_mae_counters_init(&registry->counters, nb_counters_max);
+	int ret;
+
+	ret = sfc_mae_counters_init(&registry->action_counters,
+				    nb_action_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
+
+	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
-	sfc_mae_counters_fini(&registry->counters);
+	sfc_mae_counters_fini(&registry->action_counters);
 }
 
 struct rte_flow *
@@ -153,10 +162,10 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-						   limits.eml_max_n_counters);
+					limits.eml_max_n_action_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init MAE counters registry for %u entries: %s",
-				limits.eml_max_n_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
+				limits.eml_max_n_action_counters, rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -833,6 +842,9 @@ sfc_mae_counter_add(struct sfc_adapter *sa,
 	if (counter_tmp != NULL) {
 		counter->rte_id_valid = counter_tmp->rte_id_valid;
 		counter->rte_id = counter_tmp->rte_id;
+		counter->type = counter_tmp->type;
+	} else {
+		counter->type = EFX_COUNTER_TYPE_ACTION;
 	}
 
 	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -864,8 +876,8 @@ sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
 	    counter->fw_rsrc.refcnt != 0) {
-		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
-			counter, counter->fw_rsrc.counter_id.id,
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, counter->fw_rsrc.counter_id.id,
 			counter->fw_rsrc.refcnt);
 	}
 
@@ -916,8 +928,8 @@ sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
 	}
 
 	if (fw_rsrc->refcnt == 0) {
-		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
-			counter, fw_rsrc->counter_id.id);
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%x-#%u",
+			counter, counter->type, fw_rsrc->counter_id.id);
 	}
 
 	++(fw_rsrc->refcnt);
@@ -940,8 +952,8 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
-		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
-			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
 		return;
 	}
 
@@ -950,11 +962,11 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
 		if (rc == 0) {
-			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
-				counter, counter_id);
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%x-#%u",
+				counter, counter->type, counter_id);
 		} else {
-			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
-				counter, counter_id, strerror(rc));
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%x-#%u: %s",
+				counter, counter->type, counter_id, strerror(rc));
 		}
 
 		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -3954,6 +3966,7 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 				const struct rte_flow_action_count *conf,
+				efx_counter_type_t mae_counter_type,
 				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
@@ -3993,6 +4006,8 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		counter_tmp.rte_id = conf->id;
 	}
 
+	counter_tmp.type = mae_counter_type;
+
 	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
 
 	return 0;
@@ -4217,6 +4232,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
+	efx_counter_type_t mae_counter_type = EFX_COUNTER_TYPE_ACTION;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4309,6 +4325,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     mae_counter_type,
 						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_INDIRECT:
@@ -4887,8 +4904,7 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 
 	if (conf == NULL ||
 	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 counter, data);
+		rc = sfc_mae_counter_get(sa, counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5002,6 +5018,7 @@ sfc_mae_indir_action_create(struct sfc_adapter *sa,
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      EFX_COUNTER_TYPE_ACTION,
 						      &handle->counter, NULL);
 		if (ret == 0)
 			handle->counter->indirect = true;
@@ -5065,8 +5082,7 @@ sfc_mae_indir_action_query(struct sfc_adapter *sa,
 		if (handle->counter->fw_rsrc.refcnt == 0)
 			goto fail_not_in_use;
 
-		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					  handle->counter, data);
+		ret = sfc_mae_counter_get(sa, handle->counter, data);
 		if (ret != 0)
 			goto fail_counter_get;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index e7b7d3a35e..3a3a5225fd 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -86,6 +86,7 @@ struct sfc_mae_counter {
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 
 	bool				indirect;
+	efx_counter_type_t		type;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -157,6 +158,8 @@ struct sfc_mae_counter_records {
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
 	unsigned int			n_mae_counters;
+	/** Counter type, for logging */
+	efx_counter_type_t		type;
 };
 
 /** Options for MAE counter polling mode */
@@ -168,8 +171,8 @@ enum sfc_mae_counter_polling_mode {
 
 struct sfc_mae_counter_registry {
 	/* Common counter information */
-	/** Counters collection */
-	struct sfc_mae_counter_records	counters;
+	/** Action rule counter record collection */
+	struct sfc_mae_counter_records	action_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 90b89e81c6..47448cba15 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -80,19 +80,28 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
 	int rc;
 
+	switch (counterp->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail_counter_type_check;
+	}
+
 	/*
 	 * The actual count of counters allocated is ignored since a failure
 	 * to allocate a single counter is indicated by non-zero return code.
 	 */
-	rc = efx_mae_counters_alloc(sa->nic, 1, &unused, &mae_counter,
-				    &generation_count);
+	rc = efx_mae_counters_alloc_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, &generation_count);
 	if (rc != 0) {
 		sfc_err(sa, "failed to alloc MAE counter: %s",
 			rte_strerror(rc));
@@ -132,16 +141,18 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	 */
 	__atomic_store_n(&p->inuse, true, __ATOMIC_RELEASE);
 
-	sfc_info(sa, "enabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter.id,
+	sfc_info(sa, "enabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counterp->type, mae_counter.id,
 		 p->reset.pkts, p->reset.bytes);
 
 	return 0;
 
 fail_counter_id_range:
-	(void)efx_mae_counters_free(sa->nic, 1, &unused, &mae_counter, NULL);
+	(void)efx_mae_counters_free_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, NULL);
 
 fail_mae_counter_alloc:
+fail_counter_type_check:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -151,12 +162,20 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
 	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		return EINVAL;
+	}
+
 	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
@@ -166,13 +185,14 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
+	rc = efx_mae_counters_free_type(sa->nic, counter->type, 1, &unused,
+					mae_counter, NULL);
 	if (rc != 0)
-		sfc_err(sa, "failed to free MAE counter %u: %s",
-			mae_counter->id, rte_strerror(rc));
+		sfc_err(sa, "failed to free MAE counter 0x%x-#%u: %s",
+			counter->type, mae_counter->id, rte_strerror(rc));
 
-	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter->id,
+	sfc_info(sa, "disabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counter->type, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -243,8 +263,8 @@ sfc_mae_counter_increment(struct sfc_adapter *sa,
 				 __ATOMIC_RELAXED);
 	}
 
-	sfc_info(sa, "update MAE counter #%u: pkts+%" PRIu64 "=%" PRIu64
-		 ", bytes+%" PRIu64 "=%" PRIu64, mae_counter_id,
+	sfc_info(sa, "update MAE counter 0x%x-#%u: pkts+%" PRIu64 "=%" PRIu64
+		 ", bytes+%" PRIu64 "=%" PRIu64, counters->type, mae_counter_id,
 		 pkts, cnt_val.pkts, bytes, cnt_val.bytes);
 }
 
@@ -253,6 +273,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			     struct sfc_mae_counter_registry *counter_registry,
 			     const struct rte_mbuf *m)
 {
+	struct sfc_mae_counter_records *counters;
 	uint32_t generation_count;
 	const efx_xword_t *hdr;
 	const efx_oword_t *counters_data;
@@ -293,7 +314,12 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	}
 
 	id = EFX_XWORD_FIELD(*hdr, ERF_SC_PACKETISER_HEADER_IDENTIFIER);
-	if (unlikely(id != ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR)) {
+
+	switch (id) {
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
+		counters = &counter_registry->action_counters;
+		break;
+	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
 	}
@@ -367,7 +393,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
 		sfc_mae_counter_increment(sa,
-			&counter_registry->counters,
+			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX),
 			generation_count,
@@ -941,14 +967,25 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+sfc_mae_counter_get(struct sfc_adapter *sa,
 		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
+	struct sfc_mae_counter_records *counters;
 	uint64_t non_reset_tunnel_hit_counter;
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
+	bool need_byte_count;
+
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &sa->mae.counter_registry.action_counters;
+		need_byte_count = true;
+		break;
+	default:
+		return EINVAL;
+	}
 
 	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
 	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
@@ -968,7 +1005,7 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 		data->hits += ft_ctx->switch_hit_counter;
 		non_reset_tunnel_hit_counter = data->hits;
 		data->hits -= ft_ctx->reset_tunnel_hit_counter;
-	} else {
+	} else if (need_byte_count) {
 		data->bytes_set = 1;
 		data->bytes = value.bytes - p->reset.bytes;
 	}
@@ -979,7 +1016,9 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 				non_reset_tunnel_hit_counter;
 		} else {
 			p->reset.pkts = value.pkts;
-			p->reset.bytes = value.bytes;
+
+			if (need_byte_count)
+				p->reset.bytes = value.bytes;
 		}
 	}
 
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 9c6d8103ac..effb037799 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -45,7 +45,7 @@ int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 				   struct sfc_mae_counter *counterp);
 int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				    struct sfc_mae_counter *counter);
-int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+int sfc_mae_counter_get(struct sfc_adapter *sa,
 			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 33/34] common/sfc_efx/base: support conntrack assistance counters
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (31 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-01 19:55 ` [PATCH 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Counters that can be referenced by HW conntrack assistance
table work similar to those of the action rules. However,
their IDs belong to a separate (CT-specific) namespace.

These are 1-bit saturating counters with no byte count.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  2 ++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 35 +++++++++++++++++++++++---
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 10908d97ef..0534179381 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4195,6 +4195,7 @@ typedef struct efx_mae_limits_s {
 		uint32_t		eml_max_n_counters;
 		uint32_t		eml_max_n_action_counters;
 	};
+	uint32_t			eml_max_n_conntrack_counters;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4789,6 +4790,7 @@ efx_mae_action_set_fill_in_eh_id(
  */
 typedef enum efx_counter_type_e {
 	EFX_COUNTER_TYPE_ACTION = 0,
+	EFX_COUNTER_TYPE_CONNTRACK,
 } efx_counter_type_t;
 
 typedef struct efx_counter_s {
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 7e5701e801..09b1e95c59 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -842,6 +842,7 @@ typedef struct efx_mae_s {
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
 	uint32_t			em_max_n_action_counters;
+	uint32_t			em_max_n_conntrack_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index eddba0e71c..9ff887e04b 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -16,7 +16,7 @@ efx_mae_get_capabilities(
 	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload,
 	    MC_CMD_MAE_GET_CAPS_IN_LEN,
-	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	    MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
 	struct efx_mae_s *maep = enp->en_maep;
 	efx_rc_t rc;
 
@@ -24,7 +24,7 @@ efx_mae_get_capabilities(
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
 	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_MAE_GET_CAPS_OUT_LEN;
+	req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
 
 	efx_mcdi_execute(enp, &req);
 
@@ -70,6 +70,13 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_counters =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
+	if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
+		maep->em_max_n_conntrack_counters =
+		    MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
+	} else {
+		maep->em_max_n_conntrack_counters = 0;
+	}
+
 	return (0);
 
 fail2:
@@ -375,6 +382,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
+	emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
 
 	return (0);
 
@@ -3282,11 +3290,15 @@ efx_mae_counters_alloc_type(
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
 
 	switch (type) {
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3403,6 +3415,9 @@ efx_mae_counters_free_type(
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3505,8 +3520,11 @@ efx_mae_counters_stream_start(
 	__out				uint32_t *flags_out)
 {
 	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN,
+	EFX_MCDI_DECLARE_BUF(payload,
+			     MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
 			     MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	uint32_t counter_types;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
@@ -3517,7 +3535,7 @@ efx_mae_counters_stream_start(
 
 	req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
 
@@ -3526,6 +3544,15 @@ efx_mae_counters_stream_start(
 			 packet_size);
 	MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
 
+	counter_types = (1U << MAE_COUNTER_TYPE_AR);
+
+	if (maep->em_max_n_conntrack_counters != 0)
+		counter_types |= (1U << MAE_COUNTER_TYPE_CT);
+
+	MCDI_IN_SET_DWORD(req,
+			  MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
+			  counter_types);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH 34/34] net/sfc: use conntrack assistance counters in transfer flows
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (32 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
@ 2023-06-01 19:55 ` Ivan Malov
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-01 19:55 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

These are 1-bit saturating counters which can only be useful
to tell whether a given flow rule has offloaded some packets
since the last query. Byte count is never provided for these.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h        |   2 +
 drivers/net/sfc/sfc_mae.c         | 119 ++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |   2 +
 drivers/net/sfc/sfc_mae_counter.c |  30 ++++++++
 4 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index af94d0654a..601f93e540 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -86,6 +86,8 @@ struct sfc_flow_spec_mae {
 	/* Conntrack (CT) assistance table entry key and response */
 	sfc_mae_conntrack_response_t	ct_resp;
 	sfc_mae_conntrack_key_t		ct_key;
+	/* Conntrack (CT) assistance counter */
+	struct sfc_mae_counter		*ct_counter;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 5687fa3af4..1256335633 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,7 +65,8 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_action_counters_max)
+			      uint32_t nb_action_counters_max,
+			      uint32_t nb_conntrack_counters_max)
 {
 	int ret;
 
@@ -76,12 +77,20 @@ sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
 
 	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
 
+	ret = sfc_mae_counters_init(&registry->conntrack_counters,
+				    nb_conntrack_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
+
 	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
+	sfc_mae_counters_fini(&registry->conntrack_counters);
 	sfc_mae_counters_fini(&registry->action_counters);
 }
 
@@ -162,10 +171,13 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-					limits.eml_max_n_action_counters);
+					limits.eml_max_n_action_counters,
+					limits.eml_max_n_conntrack_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
-				limits.eml_max_n_action_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR and %u CT counters: %s",
+				limits.eml_max_n_action_counters,
+				limits.eml_max_n_conntrack_counters,
+				rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -1473,6 +1485,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 	}
 
 	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
+
+	sfc_mae_counter_del(sa, spec_mae->ct_counter);
 }
 
 static int
@@ -4225,7 +4239,7 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  struct rte_flow *flow,
+			  struct rte_flow *flow, bool ct,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
@@ -4241,6 +4255,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
+	if (ct) {
+		mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
+		counterp = &spec_mae->ct_counter;
+		spec_ptr = NULL;
+	}
+
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
@@ -4528,7 +4548,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, flow,
+		rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
@@ -4563,8 +4583,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		(ctx.counter)->ft_switch_hit_counter =
-			&spec_mae->ft_ctx->switch_hit_counter;
+		if (ctx.counter != NULL) {
+			(ctx.counter)->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		} else if (sfc_mae_counter_stream_enabled(sa)) {
+			SFC_ASSERT(ct);
+
+			spec_mae->ct_counter->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		}
 		break;
 	default:
 		SFC_ASSERT(B_FALSE);
@@ -4845,12 +4872,34 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 		return rc;
 
 	if (spec_mae->action_rule->ct_mark != 0) {
+		struct sfc_mae_counter *counter = spec_mae->ct_counter;
+
+		rc = sfc_mae_counter_enable(sa, counter, NULL);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+
+		if (counter != NULL) {
+			struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
+
+			spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
+
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_mae_action_rule_disable(sa, action_rule);
+				return rc;
+			}
+		} else {
+			spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+		}
+
 		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
-		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
 
 		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
 					      &spec_mae->ct_resp);
 		if (rc != 0) {
+			sfc_mae_counter_disable(sa, counter);
 			sfc_mae_action_rule_disable(sa, action_rule);
 			return rc;
 		}
@@ -4873,6 +4922,8 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule->ct_mark != 0)
 		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
 
+	sfc_mae_counter_disable(sa, spec_mae->ct_counter);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
@@ -4887,31 +4938,41 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 {
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
-	struct sfc_mae_action_set *action_set;
-	struct sfc_mae_counter *counter;
+	struct sfc_mae_counter *counters[1 /* action rule counter */ +
+					 1 /* conntrack counter */];
+	unsigned int i;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set == NULL ||
-	    action_rule->action_set->counter == NULL ||
-	    action_rule->action_set->counter->indirect) {
-		return rte_flow_error_set(error, EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION, action,
-			"Queried flow rule does not have count actions");
-	}
+	/*
+	 * The check for counter unavailability is done based
+	 * on counter traversal results. See error set below.
+	 */
+	if (action_rule != NULL && action_rule->action_set != NULL &&
+	    action_rule->action_set->counter != NULL &&
+	    !action_rule->action_set->counter->indirect)
+		counters[0] = action_rule->action_set->counter;
+	else
+		counters[0] = NULL;
 
-	action_set = action_rule->action_set;
-	counter = action_set->counter;
+	counters[1] = spec->ct_counter;
 
-	if (conf == NULL ||
-	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(sa, counter, data);
-		if (rc != 0) {
-			return rte_flow_error_set(error, EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION, action,
-				"Queried flow rule counter action is invalid");
-		}
+	for (i = 0; i < RTE_DIM(counters); ++i) {
+		struct sfc_mae_counter *counter = counters[i];
 
-		return 0;
+		if (counter == NULL)
+			continue;
+
+		if (conf == NULL ||
+		    (counter->rte_id_valid && conf->id == counter->rte_id)) {
+			rc = sfc_mae_counter_get(sa, counter, data);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION, action,
+					"Queried flow rule counter action is invalid");
+			}
+
+			return 0;
+		}
 	}
 
 	return rte_flow_error_set(error, ENOENT,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3a3a5225fd..80585c0e93 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -173,6 +173,8 @@ struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Action rule counter record collection */
 	struct sfc_mae_counter_records	action_counters;
+	/** Conntrack counter record collection */
+	struct sfc_mae_counter_records	conntrack_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 47448cba15..79043ff7d7 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail_counter_type_check;
@@ -172,6 +175,9 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		return EINVAL;
 	}
@@ -319,6 +325,9 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
 		counters = &counter_registry->action_counters;
 		break;
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT:
+		counters = &counter_registry->conntrack_counters;
+		break;
 	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
@@ -392,6 +401,23 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 		byte_count_hi =
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
+
+		if (id == ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT) {
+			/*
+			 * FIXME:
+			 *
+			 * CT counters are 1-bit saturating counters.
+			 * There is no way to express this in DPDK
+			 * currently, so increment the hit count
+			 * by one to let the application know
+			 * that the flow is still effective.
+			 */
+			packet_count_lo = 1;
+			packet_count_hi = 0;
+			byte_count_lo = 0;
+			byte_count_hi = 0;
+		}
+
 		sfc_mae_counter_increment(sa,
 			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
@@ -983,6 +1009,10 @@ sfc_mae_counter_get(struct sfc_adapter *sa,
 		counters = &sa->mae.counter_registry.action_counters;
 		need_byte_count = true;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &sa->mae.counter_registry.conntrack_counters;
+		need_byte_count = false;
+		break;
 	default:
 		return EINVAL;
 	}
-- 
2.17.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 00/34] net/sfc: support HW conntrack assistance
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (33 preceding siblings ...)
  2023-06-01 19:55 ` [PATCH 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
@ 2023-06-04  0:00 ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
                     ` (33 more replies)
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
  36 siblings, 34 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

Changes in v2:
* Found and fixed my own mistake in [15/34]
* Fixed [16/34] as per 0-day robot report
* Added missing release notes to [27/34]
* Added missing release notes to [30/34]

Denis Pryazhennikov (11):
  common/sfc_efx/base: update MCDI headers
  common/sfc_efx/base: detect MCDI Table Access API support
  common/sfc_efx/base: add API to list HW tables
  common/sfc_efx/base: add macro to get indexed QWORD field
  common/sfc_efx/base: add API to get HW table desc
  common/sfc_efx/base: add API to insert data to HW table
  common/sfc_efx/base: add API to delete entry from HW table
  net/sfc: add MCDI wrappers for BCAM tables
  net/sfc: add functions to manipulate MCDI table fields
  net/sfc: attach to HW table API
  net/sfc: add API to manage HW Conntrack table

Ivan Malov (23):
  net/sfc: make entry pointer optional in MAE resource helpers
  net/sfc: turn flow create/destroy methods into lock wrappers
  net/sfc: let driver-internal flows use VF representor action
  net/sfc: extend generic flow API to allow for internal flows
  net/sfc: switch driver-internal flows to use generic methods
  net/sfc: move MAE flow parsing method to MAE-specific source
  net/sfc: move MAE counter stream start to action set handler
  net/sfc: prepare MAE outer rules for action rule indirection
  net/sfc: turn MAE flow action rules into shareable resources
  common/sfc_efx/base: provide an API to clone MAE match specs
  common/sfc_efx/base: add API to read back MAE match criteria
  common/sfc_efx/base: match on conntrack mark in action rules
  common/sfc_efx/base: add API to request MAE conntrack lookup
  net/sfc: make use of conntrack assistance for transfer flows
  common/sfc_efx/base: support NAT edits in MAE
  net/sfc: add support for IPv4 NAT offload to MAE backend
  net/sfc: rename SW structures used by transfer flow counters
  net/sfc: rework MAE action rule counter representation in SW
  net/sfc: support indirect count action in transfer flows
  common/sfc_efx/base: rework MAE counter provisioning helpers
  net/sfc: indicate MAE counter type in use for transfer flows
  common/sfc_efx/base: support conntrack assistance counters
  net/sfc: use conntrack assistance counters in transfer flows

 doc/guides/nics/features/sfc.ini            |    5 +
 doc/guides/nics/sfc_efx.rst                 |   10 +
 doc/guides/rel_notes/release_23_07.rst      |   18 +
 drivers/common/sfc_efx/base/efx.h           |  198 +-
 drivers/common/sfc_efx/base/efx_impl.h      |    5 +-
 drivers/common/sfc_efx/base/efx_mae.c       |  383 ++-
 drivers/common/sfc_efx/base/efx_mcdi.h      |    4 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 drivers/common/sfc_efx/base/efx_table.c     |  506 ++++
 drivers/common/sfc_efx/base/hunt_nic.c      |    2 +
 drivers/common/sfc_efx/base/medford2_nic.c  |    2 +
 drivers/common/sfc_efx/base/medford_nic.c   |    2 +
 drivers/common/sfc_efx/base/meson.build     |    1 +
 drivers/common/sfc_efx/base/rhead_nic.c     |    9 +
 drivers/common/sfc_efx/base/siena_nic.c     |    2 +
 drivers/common/sfc_efx/version.map          |   14 +
 drivers/net/sfc/meson.build                 |    6 +-
 drivers/net/sfc/sfc.c                       |   27 +-
 drivers/net/sfc/sfc.h                       |    3 +
 drivers/net/sfc/sfc_flow.c                  |  246 +-
 drivers/net/sfc/sfc_flow.h                  |   45 +-
 drivers/net/sfc/sfc_mae.c                   | 1899 ++++++++++----
 drivers/net/sfc/sfc_mae.h                   |  131 +-
 drivers/net/sfc/sfc_mae_counter.c           |  146 +-
 drivers/net/sfc/sfc_mae_counter.h           |   16 +-
 drivers/net/sfc/sfc_mae_ct.c                |  201 ++
 drivers/net/sfc/sfc_mae_ct.h                |   68 +
 drivers/net/sfc/sfc_repr.c                  |   20 +-
 drivers/net/sfc/sfc_repr_proxy.c            |   53 +-
 drivers/net/sfc/sfc_repr_proxy.h            |    2 +-
 drivers/net/sfc/sfc_repr_proxy_api.h        |    3 +
 drivers/net/sfc/sfc_switch.c                |    7 +-
 drivers/net/sfc/sfc_switch.h                |   10 +
 drivers/net/sfc/sfc_tbl_meta.c              |   71 +
 drivers/net/sfc/sfc_tbl_meta.h              |   37 +
 drivers/net/sfc/sfc_tbl_meta_cache.c        |  253 ++
 drivers/net/sfc/sfc_tbl_meta_cache.h        |   25 +
 drivers/net/sfc/sfc_tbls.c                  |  200 ++
 drivers/net/sfc/sfc_tbls.h                  |  285 +++
 39 files changed, 6602 insertions(+), 870 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h
 create mode 100644 drivers/net/sfc/sfc_tbls.c
 create mode 100644 drivers/net/sfc/sfc_tbls.h

-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 01/34] common/sfc_efx/base: update MCDI headers
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Pickup new FW interface definitions.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 1 file changed, 2467 insertions(+), 90 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index d1d8093601..76bd1bf4d9 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -5,7 +5,10 @@
  */
 
 /*
- * This file is automatically generated. DO NOT EDIT IT.
+ * This file is automatically generated, but contains manual changes.
+ * - replaced the autogenerated license header with BSD-3-Clause;
+ * - used tabs for the indentation of MC_CMD_ERR_*.
+ *
  * To make changes, edit the .yml files in smartnic_registry under doc/mcdi/ and
  * rebuild this file with "make mcdi_headers_v5".
  */
@@ -81,19 +84,19 @@
  *               |                      \------- Error
  *               \------------------------------ Resync (always set)
  *
- * The client writes it's request into MC shared memory, and rings the
- * doorbell. Each request is completed by either by the MC writting
- * back into shared memory, or by writting out an event.
+ * The client writes its request into MC shared memory, and rings the
+ * doorbell. Each request is completed either by the MC writing
+ * back into shared memory, or by writing out an event.
  *
  * All MCDI commands support completion by shared memory response. Each
  * request may also contain additional data (accounted for by HEADER.LEN),
- * and some response's may also contain additional data (again, accounted
+ * and some responses may also contain additional data (again, accounted
  * for by HEADER.LEN).
  *
  * Some MCDI commands support completion by event, in which any associated
  * response data is included in the event.
  *
- * The protocol requires one response to be delivered for every request, a
+ * The protocol requires one response to be delivered for every request; a
  * request should not be sent unless the response for the previous request
  * has been received (either by polling shared memory, or by receiving
  * an event).
@@ -339,7 +342,7 @@
 /* enum: The requesting client is not a function */
 #define	MC_CMD_ERR_CLIENT_NOT_FN 0x100c
 /* enum: The requested operation might require the command to be passed between
- * MCs, and thetransport doesn't support that. Should only ever been seen over
+ * MCs, and the transport doesn't support that. Should only ever been seen over
  * the UART.
  */
 #define	MC_CMD_ERR_TRANSPORT_NOPROXY 0x100d
@@ -376,7 +379,7 @@
  * sub-variant switching.
  */
 #define	MC_CMD_ERR_FILTERS_PRESENT 0x1014
-/* enum: The clock whose frequency you've attempted to set set doesn't exist on
+/* enum: The clock whose frequency you've attempted to set doesn't exist on
  * this NIC
  */
 #define	MC_CMD_ERR_NO_CLOCK 0x1015
@@ -658,12 +661,624 @@
  * be allocated by different counter blocks, so e.g. AR counter 42 is different
  * from CT counter 42. Generation counts are also type-specific. This value is
  * also present in the header of streaming counter packets, in the IDENTIFIER
- * field (see packetiser packet format definitions).
+ * field (see packetiser packet format definitions). Also note that LACP
+ * counter IDs are not allocated individually, instead the counter IDs are
+ * directly tied to the LACP balance table indices. These in turn are allocated
+ * in large contiguous blocks as a LAG config. Calling MAE_COUNTER_ALLOC/FREE
+ * with an LACP counter type will return EPERM.
  */
 /* enum: Action Rule counters - can be referenced in AR response. */
 #define	MAE_COUNTER_TYPE_AR 0x0
 /* enum: Conntrack counters - can be referenced in CT response. */
 #define	MAE_COUNTER_TYPE_CT 0x1
+/* enum: Outer Rule counters - can be referenced in OR response. */
+#define	MAE_COUNTER_TYPE_OR 0x2
+/* enum: LACP counters - linked to LACP balance table entries. */
+#define	MAE_COUNTER_TYPE_LACP 0x3
+
+/* MAE_COUNTER_ID enum: ID of allocated counter or counter list. */
+/* enum: A counter ID that is guaranteed never to represent a real counter or
+ * counter list.
+ */
+#define	MAE_COUNTER_ID_NULL 0xffffffff
+
+/* TABLE_ID enum: Unique IDs for tables. The 32-bit ID values have been
+ * structured with bits [31:24] reserved (0), [23:16] indicating which major
+ * block the tables belongs to (0=VNIC TX, none currently; 1=MAE; 2=VNIC RX),
+ * [15:8] a unique ID within the block, and [7:0] reserved for future
+ * variations of the same table. (All of the tables currently defined within
+ * the streaming engines are listed here, but this does not imply that they are
+ * all supported - MC_CMD_TABLE_LIST returns the list of actually supported
+ * tables.) The DPU offload engines' enumerators follow a deliberate pattern:
+ * 0x01010000 + is_dpu_net * 0x10000 + is_wr_or_tx * 0x8000 + is_lite_pipe *
+ * 0x1000 + oe_engine_type * 0x100 + oe_instance_within_pipe * 0x10
+ */
+/* enum: Outer_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_TABLE 0x10000
+/* enum: Outer_Rule_No_CT_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_NO_CT_TABLE 0x10100
+/* enum: Mgmt_Filter_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGMT_FILTER_TABLE 0x10200
+/* enum: Conntrack_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_CONNTRACK_TABLE 0x10300
+/* enum: Action_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ACTION_RULE_TABLE 0x10400
+/* enum: Mgroup_Default_Action_Set_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGROUP_DEFAULT_ACTION_SET_TABLE 0x10500
+/* enum: Encap_Hdr_Part1_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART1_TABLE 0x10600
+/* enum: Encap_Hdr_Part2_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART2_TABLE 0x10700
+/* enum: Replace_Src_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_SRC_MAC_TABLE 0x10800
+/* enum: Replace_Dst_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_DST_MAC_TABLE 0x10900
+/* enum: Dst_Mport_VC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_VC_TABLE 0x10a00
+/* enum: LACP_LAG_Config_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_LAG_CONFIG_TABLE 0x10b00
+/* enum: LACP_Balance_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_BALANCE_TABLE 0x10c00
+/* enum: Dst_Mport_Host_Chan_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_HOST_CHAN_TABLE 0x10d00
+/* enum: VNIC_Rx_Encap_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_VNIC_RX_ENCAP_TABLE 0x20000
+/* enum: Steering_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_STEERING_TABLE 0x20100
+/* enum: RSS_Context_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_RSS_CONTEXT_TABLE 0x20200
+/* enum: Indirection_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_INDIRECTION_TABLE 0x20300
+/* enum: DPU.host read pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC0_OE_PROFILE 0x1010000
+/* enum: DPU.host read pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC1_OE_PROFILE 0x1010010
+/* enum: DPU.host write pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC0_OE_PROFILE 0x1018000
+/* enum: DPU.host write pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC1_OE_PROFILE 0x1018010
+/* enum: DPU.net 'full' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CRC0_OE_PROFILE 0x1020000
+/* enum: DPU.net 'full' receive pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM0_OE_PROFILE 0x1020100
+/* enum: DPU.net 'full' receive pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM1_OE_PROFILE 0x1020110
+/* enum: DPU.net 'full' receive pipe AES-GCM offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_AES_GCM0_OE_PROFILE 0x1020200
+/* enum: DPU.net 'lite' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CRC0_OE_PROFILE 0x1021000
+/* enum: DPU.net 'lite' receive pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CSUM0_OE_PROFILE 0x1021100
+/* enum: DPU.net 'full' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CRC0_OE_PROFILE 0x1028000
+/* enum: DPU.net 'full' transmit pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM0_OE_PROFILE 0x1028100
+/* enum: DPU.net 'full' transmit pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM1_OE_PROFILE 0x1028110
+/* enum: DPU.net 'full' transmit pipe AES-GCM offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_AES_GCM0_OE_PROFILE 0x1028200
+/* enum: DPU.net 'lite' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CRC0_OE_PROFILE 0x1029000
+/* enum: DPU.net 'lite' transmit pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CSUM0_OE_PROFILE 0x1029100
+
+/* TABLE_COMPRESSED_VLAN enum: Compressed VLAN TPID as used by some field
+ * types; can be calculated by (((ether_type_msb >> 2) & 0x4) ^ 0x4) |
+ * (ether_type_msb & 0x3);
+ */
+#define	TABLE_COMPRESSED_VLAN_TPID_8100 0x5 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_88A8 0x4 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9100 0x1 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9200 0x2 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9300 0x3 /* enum */
+
+/* TABLE_NAT_DIR enum: NAT direction. */
+#define	TABLE_NAT_DIR_SOURCE 0x0 /* enum */
+#define	TABLE_NAT_DIR_DEST 0x1 /* enum */
+
+/* TABLE_RSS_KEY_MODE enum: Defines how the value for Toeplitz hashing for RSS
+ * is constructed as a concatenation (indicated here by "++") of packet header
+ * fields.
+ */
+/* enum: IP src addr ++ IP dst addr */
+#define	TABLE_RSS_KEY_MODE_SA_DA 0x0
+/* enum: IP src addr ++ IP dst addr ++ TCP/UDP src port ++ TCP/UDP dst port */
+#define	TABLE_RSS_KEY_MODE_SA_DA_SP_DP 0x1
+/* enum: IP src addr */
+#define	TABLE_RSS_KEY_MODE_SA 0x2
+/* enum: IP dst addr */
+#define	TABLE_RSS_KEY_MODE_DA 0x3
+/* enum: IP src addr ++ TCP/UDP src port */
+#define	TABLE_RSS_KEY_MODE_SA_SP 0x4
+/* enum: IP dest addr ++ TCP dest port */
+#define	TABLE_RSS_KEY_MODE_DA_DP 0x5
+/* enum: Nothing (produces input of 0, resulting in output hash of 0) */
+#define	TABLE_RSS_KEY_MODE_NONE 0x7
+
+/* TABLE_RSS_SPREAD_MODE enum: RSS spreading mode. */
+/* enum: RSS uses Indirection_Table lookup. */
+#define	TABLE_RSS_SPREAD_MODE_INDIRECTION 0x0
+/* enum: RSS uses even spreading calculation. */
+#define	TABLE_RSS_SPREAD_MODE_EVEN 0x1
+
+/* CRC_VARIANT enum: Operation for the DPU CRC engine to perform. */
+/* enum: Calculate a 32-bit CRC. */
+#define	CRC_VARIANT_CRC32 0x1
+/* enum: Calculate a 64-bit CRC. */
+#define	CRC_VARIANT_CRC64 0x2
+
+/* DPU_CSUM_OP enum: Operation for the DPU checksum engine to perform. */
+/* enum: Calculate the checksum for a TCP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_TCP 0x0
+/* enum: Calculate the checksum for a UDP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_UDP 0x1
+/* enum: Calculate the checksum for a TCP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_TCP 0x2
+/* enum: Calculate the checksum for a UDP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_UDP 0x3
+
+/* GCM_OP_CODE enum: Operation for the DPU AES-GCM engine to perform. */
+/* enum: Encrypt/decrypt a stream of data. */
+#define	GCM_OP_CODE_BULK_CRYPT 0x0
+/* enum: Calculate the authentication tag for a stream of data. */
+#define	GCM_OP_CODE_BULK_AUTH 0x1
+/* enum: Encrypt/decrypt an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_CRYPT 0x2
+/* enum: Calculate the authentication tag of an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_AUTH 0x3
+
+/* AES_KEY_LEN enum: Key size for AES crypto operations */
+/* enum: 128 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_128 0x0
+/* enum: 256 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_256 0x1
+
+/* TABLE_FIELD_ID enum: Unique IDs for fields. Related concepts have been
+ * loosely grouped together into blocks with gaps for expansion, but the values
+ * are arbitrary. Field IDs are not specific to particular tables, and in some
+ * cases this sharing means that they are not used with the exact names of the
+ * corresponding table definitions in SF-123102-TC; however, the mapping should
+ * still be clear. The intent is that a list of fields, with their associated
+ * bit widths and semantics version code, unambiguously defines the semantics
+ * of the fields in a key or response. (Again, this list includes all of the
+ * fields currently defined within the streaming engines, but only a subset may
+ * actually be used by the supported list of tables.)
+ */
+/* enum: May appear multiple times within a key or response, and indicates that
+ * the field is unused and should be set to 0 (or masked out if permitted by
+ * the MASK_VALUE for this field).
+ */
+#define	TABLE_FIELD_ID_UNUSED 0x0
+/* enum: Source m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_SRC_MPORT 0x1
+/* enum: Destination m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_DST_MPORT 0x2
+/* enum: Source m-group ID. */
+#define	TABLE_FIELD_ID_SRC_MGROUP_ID 0x3
+/* enum: Physical network port ID (or m-port ID; same thing, for physical
+ * network ports).
+ */
+#define	TABLE_FIELD_ID_NETWORK_PORT_ID 0x4
+/* enum: True if packet arrived via network port, false if it arrived via host.
+ */
+#define	TABLE_FIELD_ID_IS_FROM_NETWORK 0x5
+/* enum: Full virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC 0x6
+/* enum: Low bits of virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC_LOW 0x7
+/* enum: User mark value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_MARK 0x8
+/* enum: User flag value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_FLAG 0x9
+/* enum: Counter ID associated with a response. All-bits-1 is a null value to
+ * suppress counting.
+ */
+#define	TABLE_FIELD_ID_COUNTER_ID 0xa
+/* enum: Discriminator which may be set by plugins in some lookup keys; this
+ * allows plugins to make a reinterpretation of packet fields in these keys
+ * without clashing with the normal interpretation.
+ */
+#define	TABLE_FIELD_ID_DISCRIM 0xb
+/* enum: Destination MAC address. The mapping from bytes in a frame to the
+ * 48-bit value for this field is in network order, i.e. a MAC address of
+ * AA:BB:CC:DD:EE:FF becomes a 48-bit value of 0xAABBCCDDEEFF.
+ */
+#define	TABLE_FIELD_ID_DST_MAC 0x14
+/* enum: Source MAC address (see notes for DST_MAC). */
+#define	TABLE_FIELD_ID_SRC_MAC 0x15
+/* enum: Outer VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_OVLAN_TPID_COMPRESSED 0x16
+/* enum: Full outer VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_OVLAN 0x17
+/* enum: Outer VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_OVLAN_VID 0x18
+/* enum: Inner VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_IVLAN_TPID_COMPRESSED 0x19
+/* enum: Full inner VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_IVLAN 0x1a
+/* enum: Inner VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_IVLAN_VID 0x1b
+/* enum: Ethertype. */
+#define	TABLE_FIELD_ID_ETHER_TYPE 0x1c
+/* enum: Source IP address, either IPv4 or IPv6. The mapping from bytes in a
+ * frame to the 128-bit value for this field is in network order, with IPv4
+ * addresses assumed to have 12 bytes of trailing zeroes. i.e. the IPv6 address
+ * [2345::6789:ABCD] is 0x2345000000000000000000006789ABCD; the IPv4 address
+ * 192.168.1.2 is 0xC0A80102000000000000000000000000.
+ */
+#define	TABLE_FIELD_ID_SRC_IP 0x1d
+/* enum: Destination IP address (see notes for SRC_IP). */
+#define	TABLE_FIELD_ID_DST_IP 0x1e
+/* enum: IPv4 Type-of-Service or IPv6 Traffic Class field. */
+#define	TABLE_FIELD_ID_IP_TOS 0x1f
+/* enum: IP Protocol. */
+#define	TABLE_FIELD_ID_IP_PROTO 0x20
+/* enum: Layer 4 source port. */
+#define	TABLE_FIELD_ID_SRC_PORT 0x21
+/* enum: Layer 4 destination port. */
+#define	TABLE_FIELD_ID_DST_PORT 0x22
+/* enum: TCP flags. */
+#define	TABLE_FIELD_ID_TCP_FLAGS 0x23
+/* enum: Virtual Network Identifier (VXLAN) or Virtual Session ID (NVGRE). */
+#define	TABLE_FIELD_ID_VNI 0x24
+/* enum: True if packet has any tunnel encapsulation header. */
+#define	TABLE_FIELD_ID_HAS_ENCAP 0x32
+/* enum: True if encap header has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_OVLAN 0x33
+/* enum: True if encap header has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_IVLAN 0x34
+/* enum: True if encap header is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP 0x35
+/* enum: True if encap header is specifically IPv4. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP4 0x36
+/* enum: True if encap header is UDP. */
+#define	TABLE_FIELD_ID_HAS_ENC_UDP 0x37
+/* enum: True if only/inner frame has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_OVLAN 0x38
+/* enum: True if only/inner frame has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_IVLAN 0x39
+/* enum: True if only/inner frame is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_IP 0x3a
+/* enum: True if only/inner frame has a recognised L4 IP protocol (TCP or UDP).
+ */
+#define	TABLE_FIELD_ID_HAS_L4 0x3b
+/* enum: True if only/inner frame is an IP fragment. */
+#define	TABLE_FIELD_ID_IP_FRAG 0x3c
+/* enum: True if only/inner frame is the first IP fragment (fragment offset 0).
+ */
+#define	TABLE_FIELD_ID_IP_FIRST_FRAG 0x3d
+/* enum: True if only/inner frame has an IP Time-To-Live of <= 1. (Note: the
+ * implementation calls this "ip_ttl_is_one" but does in fact match packets
+ * with TTL=0 - which we shouldn't be seeing! - as well.)
+ */
+#define	TABLE_FIELD_ID_IP_TTL_LE_ONE 0x3e
+/* enum: True if only/inner frame has any of TCP SYN, FIN or RST flags set. */
+#define	TABLE_FIELD_ID_TCP_INTERESTING_FLAGS 0x3f
+/* enum: Plugin channel selection. */
+#define	TABLE_FIELD_ID_RDP_PL_CHAN 0x50
+/* enum: Enable update of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL_EN 0x51
+/* enum: New value of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL 0x52
+/* enum: Enable update of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL_EN 0x53
+/* enum: New value of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL 0x54
+/* enum: Enable update of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN_EN 0x55
+/* enum: New value of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN 0x56
+/* enum: Recirculation ID for lookup sequences with two action rule lookups. */
+#define	TABLE_FIELD_ID_RECIRC_ID 0x64
+/* enum: Domain ID passed to conntrack and action rule lookups. */
+#define	TABLE_FIELD_ID_DOMAIN 0x65
+/* enum: Construction mode for encap_tunnel_id - see MAE_CT_VNI_MODE enum. */
+#define	TABLE_FIELD_ID_CT_VNI_MODE 0x66
+/* enum: True to inhibit conntrack lookup if TCP SYN, FIN or RST flag is set.
+ */
+#define	TABLE_FIELD_ID_CT_TCP_FLAGS_INHIBIT 0x67
+/* enum: True to do conntrack lookups for IPv4 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_TCP 0x68
+/* enum: True to do conntrack lookups for IPv4 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_UDP 0x69
+/* enum: True to do conntrack lookups for IPv6 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_TCP 0x6a
+/* enum: True to do conntrack lookups for IPv6 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_UDP 0x6b
+/* enum: Outer rule identifier. */
+#define	TABLE_FIELD_ID_OUTER_RULE_ID 0x6c
+/* enum: Encapsulation type - see MAE_MCDI_ENCAP_TYPE enum. */
+#define	TABLE_FIELD_ID_ENCAP_TYPE 0x6d
+/* enum: Encap tunnel ID for conntrack lookups from VNI, VLAN tag(s), or 0,
+ * depending on CT_VNI_MODE.
+ */
+#define	TABLE_FIELD_ID_ENCAP_TUNNEL_ID 0x78
+/* enum: A conntrack entry identifier, passed to plugins. */
+#define	TABLE_FIELD_ID_CT_ENTRY_ID 0x79
+/* enum: Either source or destination NAT replacement port. */
+#define	TABLE_FIELD_ID_NAT_PORT 0x7a
+/* enum: Either source or destination NAT replacement IPv4 address. Note that
+ * this is specifically an IPv4 address (IPv6 is not supported for NAT), with
+ * byte mapped to a 32-bit value in network order, i.e. the IPv4 address
+ * 192.168.1.2 is the value 0xC0A80102.
+ */
+#define	TABLE_FIELD_ID_NAT_IP 0x7b
+/* enum: NAT direction: 0=>source, 1=>destination. */
+#define	TABLE_FIELD_ID_NAT_DIR 0x7c
+/* enum: Conntrack mark value, passed to action rule lookup. Note that this is
+ * not related to the "user mark" in the metadata / packet prefix.
+ */
+#define	TABLE_FIELD_ID_CT_MARK 0x7d
+/* enum: Private flags for conntrack, passed to action rule lookup. */
+#define	TABLE_FIELD_ID_CT_PRIV_FLAGS 0x7e
+/* enum: True if the conntrack lookup resulted in a hit. */
+#define	TABLE_FIELD_ID_CT_HIT 0x7f
+/* enum: True to suppress delivery when source and destination m-ports match.
+ */
+#define	TABLE_FIELD_ID_SUPPRESS_SELF_DELIVERY 0x8c
+/* enum: True to perform tunnel decapsulation. */
+#define	TABLE_FIELD_ID_DO_DECAP 0x8d
+/* enum: True to copy outer frame DSCP to inner on decap. */
+#define	TABLE_FIELD_ID_DECAP_DSCP_COPY 0x8e
+/* enum: True to map outer frame ECN to inner on decap, by RFC 6040 rules. */
+#define	TABLE_FIELD_ID_DECAP_ECN_RFC6040 0x8f
+/* enum: True to replace DSCP field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_DSCP 0x90
+/* enum: True to replace ECN field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_ECN 0x91
+/* enum: True to decrement IP Time-To-Live. */
+#define	TABLE_FIELD_ID_DO_DECR_IP_TTL 0x92
+/* enum: True to replace source MAC address. */
+#define	TABLE_FIELD_ID_DO_SRC_MAC 0x93
+/* enum: True to replace destination MAC address. */
+#define	TABLE_FIELD_ID_DO_DST_MAC 0x94
+/* enum: Number of VLAN tags to pop. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_POP 0x95
+/* enum: Number of VLANs tags to push. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_PUSH 0x96
+/* enum: True to count this packet. */
+#define	TABLE_FIELD_ID_DO_COUNT 0x97
+/* enum: True to perform tunnel encapsulation. */
+#define	TABLE_FIELD_ID_DO_ENCAP 0x98
+/* enum: True to copy inner frame DSCP to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_DSCP_COPY 0x99
+/* enum: True to copy inner frame ECN to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_ECN_COPY 0x9a
+/* enum: True to deliver the packet (otherwise it is dropped). */
+#define	TABLE_FIELD_ID_DO_DELIVER 0x9b
+/* enum: True to set the user flag in the metadata. */
+#define	TABLE_FIELD_ID_DO_FLAG 0x9c
+/* enum: True to update the user mark in the metadata. */
+#define	TABLE_FIELD_ID_DO_MARK 0x9d
+/* enum: True to override the capsule virtual channel for network deliveries.
+ */
+#define	TABLE_FIELD_ID_DO_SET_NET_CHAN 0x9e
+/* enum: True to override the reported source m-port for host deliveries. */
+#define	TABLE_FIELD_ID_DO_SET_SRC_MPORT 0x9f
+/* enum: Encap header ID for DO_ENCAP, indexing Encap_Hdr_Part1/2_Table. */
+#define	TABLE_FIELD_ID_ENCAP_HDR_ID 0xaa
+/* enum: New DSCP value for DO_REPLACE_DSCP. */
+#define	TABLE_FIELD_ID_DSCP_VALUE 0xab
+/* enum: If DO_REPLACE_ECN is set, the new value for the ECN field. If
+ * DO_REPLACE_ECN is not set, ECN_CONTROL[0] and ECN_CONTROL[1] are set to
+ * request remapping of ECT0 and ECT1 ECN codepoints respectively to CE.
+ */
+#define	TABLE_FIELD_ID_ECN_CONTROL 0xac
+/* enum: Source MAC ID for DO_SRC_MAC, indexing Replace_Src_MAC_Table. */
+#define	TABLE_FIELD_ID_SRC_MAC_ID 0xad
+/* enum: Destination MAC ID for DO_DST_MAC, indexing Replace_Dst_MAC_Table. */
+#define	TABLE_FIELD_ID_DST_MAC_ID 0xae
+/* enum: Parameter for either DO_SET_NET_CHAN (only bottom 6 bits used in this
+ * case) or DO_SET_SRC_MPORT.
+ */
+#define	TABLE_FIELD_ID_REPORTED_SRC_MPORT_OR_NET_CHAN 0xaf
+/* enum: 64-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK64 0xb4
+/* enum: 32-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK32 0xb5
+/* enum: 16-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK16 0xb6
+/* enum: 8-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK8 0xb7
+/* enum: 4-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK4 0xb8
+/* enum: 2-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK2 0xb9
+/* enum: Added encapsulation header length in words. */
+#define	TABLE_FIELD_ID_HDR_LEN_W 0xba
+/* enum: Static value for layer 2/3 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L23 0xbb
+/* enum: Static value for layer 4 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L4 0xbc
+/* enum: True to use the static ENC_LACP_HASH values for the encap header
+ * instead of the calculated values for the inner frame when delivering a newly
+ * encapsulated packet to a LAG m-port.
+ */
+#define	TABLE_FIELD_ID_USE_ENC_LACP_HASHES 0xbd
+/* enum: True to trigger conntrack from first action rule lookup (AR=>CT=>AR
+ * sequence).
+ */
+#define	TABLE_FIELD_ID_DO_CT 0xc8
+/* enum: True to perform NAT using parameters from conntrack lookup response.
+ */
+#define	TABLE_FIELD_ID_DO_NAT 0xc9
+/* enum: True to trigger recirculated action rule lookup (AR=>AR sequence). */
+#define	TABLE_FIELD_ID_DO_RECIRC 0xca
+/* enum: Next action set payload ID for replay. The null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_PAYLOAD 0xcb
+/* enum: Next action set row ID for replay. The null value is all-1-bits. */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_ROW 0xcc
+/* enum: Action set payload ID for additional delivery to management CPU. The
+ * null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_PAYLOAD 0xcd
+/* enum: Action set row ID for additional delivery to management CPU. The null
+ * value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_ROW 0xce
+/* enum: True to include layer 4 in LACP hash on delivery to a LAG m-port. */
+#define	TABLE_FIELD_ID_LACP_INC_L4 0xdc
+/* enum: True to request that LACP is performed by a plugin. */
+#define	TABLE_FIELD_ID_LACP_PLUGIN 0xdd
+/* enum: LACP_Balance_Table base address divided by 64. */
+#define	TABLE_FIELD_ID_BAL_TBL_BASE_DIV64 0xde
+/* enum: Length of balance table region: 0=>64, 1=>128, 2=>256. */
+#define	TABLE_FIELD_ID_BAL_TBL_LEN_ID 0xdf
+/* enum: LACP LAG ID (i.e. the low 3 bits of LACP LAG mport ID), indexing
+ * LACP_LAG_Config_Table. Refer to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_LACP_LAG_ID 0xe0
+/* enum: Address in LACP_Balance_Table. The balance table is partitioned
+ * between LAGs according to the settings in LACP_LAG_Config_Table and then
+ * indexed by the LACP hash, providing the mapping to destination mports. Refer
+ * to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_BAL_TBL_ADDR 0xe1
+/* enum: UDP port to match for UDP-based encapsulations; required to be 0 for
+ * other encapsulation types.
+ */
+#define	TABLE_FIELD_ID_UDP_PORT 0xe6
+/* enum: True to perform RSS based on outer fields rather than inner fields. */
+#define	TABLE_FIELD_ID_RSS_ON_OUTER 0xe7
+/* enum: True to perform steering table lookup on outer fields rather than
+ * inner fields.
+ */
+#define	TABLE_FIELD_ID_STEER_ON_OUTER 0xe8
+/* enum: Destination queue ID for host delivery. */
+#define	TABLE_FIELD_ID_DST_QID 0xf0
+/* enum: True to drop this packet. */
+#define	TABLE_FIELD_ID_DROP 0xf1
+/* enum: True to strip outer VLAN tag from this packet. */
+#define	TABLE_FIELD_ID_VLAN_STRIP 0xf2
+/* enum: True to override the user mark field with the supplied USER_MARK, or
+ * false to bitwise-OR the USER_MARK into it.
+ */
+#define	TABLE_FIELD_ID_MARK_OVERRIDE 0xf3
+/* enum: True to override the user flag field with the supplied USER_FLAG, or
+ * false to bitwise-OR the USER_FLAG into it.
+ */
+#define	TABLE_FIELD_ID_FLAG_OVERRIDE 0xf4
+/* enum: RSS context ID, indexing the RSS_Context_Table. */
+#define	TABLE_FIELD_ID_RSS_CTX_ID 0xfa
+/* enum: True to enable RSS. */
+#define	TABLE_FIELD_ID_RSS_EN 0xfb
+/* enum: Toeplitz hash key. */
+#define	TABLE_FIELD_ID_KEY 0xfc
+/* enum: Key mode for IPv4 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V4_KEY_MODE 0xfd
+/* enum: Key mode for IPv6 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V6_KEY_MODE 0xfe
+/* enum: Key mode for IPv4 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V4_KEY_MODE 0xff
+/* enum: Key mode for IPv6 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V6_KEY_MODE 0x100
+/* enum: Key mode for other IPv4 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V4_KEY_MODE 0x101
+/* enum: Key mode for other IPv6 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V6_KEY_MODE 0x102
+/* enum: Spreading mode - 0=>indirection; 1=>even. */
+#define	TABLE_FIELD_ID_SPREAD_MODE 0x103
+/* enum: For indirection spreading mode, the base address of a region within
+ * the Indirection_Table. For even spreading mode, the number of queues to
+ * spread across (only values 1-255 are valid for this mode).
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_BASE 0x104
+/* enum: For indirection spreading mode, identifies the length of a region
+ * within the Indirection_Table, where length = 32 << len_id. Must be set to 0
+ * for even spreading mode.
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_LEN_ID 0x105
+/* enum: An offset to be applied to the base destination queue ID. */
+#define	TABLE_FIELD_ID_INDIR_OFFSET 0x106
+/* enum: DPU offload engine profile ID to address. */
+#define	TABLE_FIELD_ID_OE_PROFILE 0x3e8
+/* enum: Width of the CRC to calculate - see CRC_VARIANT enum. */
+#define	TABLE_FIELD_ID_CRC_VARIANT 0x3f2
+/* enum: If set, reflect the bits of each input byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFIN 0x3f3
+/* enum: If set, reflect the bits of each output byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFOUT 0x3f4
+/* enum: If set, invert every bit of the output value. */
+#define	TABLE_FIELD_ID_CRC_INVOUT 0x3f5
+/* enum: The CRC polynomial to use for checksumming, in normal form. See
+ * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Specification for a
+ * description of normal form.
+ */
+#define	TABLE_FIELD_ID_CRC_POLY 0x3f6
+/* enum: Operation for the checksum engine to perform - see DPU_CSUM_OP enum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OP 0x410
+/* enum: Byte offset of checksum relative to region_start (for VALIDATE_*
+ * operations only).
+ */
+#define	TABLE_FIELD_ID_CSUM_OFFSET 0x411
+/* enum: Indicates there is additional data on OPR bus that needs to be
+ * incorporated into the payload checksum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OPR_ADDITIONAL_DATA 0x412
+/* enum: Log2 data size of additional data on OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_DATA_SIZE_LOG2 0x413
+/* enum: 4 byte offset of where to find the additional data on the OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_4B_OFF 0x414
+/* enum: Operation type for the AES-GCM core - see GCM_OP_CODE enum. */
+#define	TABLE_FIELD_ID_GCM_OP_CODE 0x41a
+/* enum: Key length - AES_KEY_LEN enum. */
+#define	TABLE_FIELD_ID_GCM_KEY_LEN 0x41b
+/* enum: OPR 4 byte offset for ICV or GHASH output (only in BULK_* mode) or
+ * IPSEC descrypt output.
+ */
+#define	TABLE_FIELD_ID_GCM_OPR_4B_OFFSET 0x41c
+/* enum: If OP_CODE is BULK_*, indicates Emit GHASH (Fragment mode). Else,
+ * indicates IPSEC-ESN mode.
+ */
+#define	TABLE_FIELD_ID_GCM_EMIT_GHASH_ISESN 0x41d
+/* enum: Replay Protection Enable. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_PROTECT_EN 0x41e
+/* enum: IPSEC Encrypt ESP trailer NEXT_HEADER byte. */
+#define	TABLE_FIELD_ID_GCM_NEXT_HDR 0x41f
+/* enum: Replay Window Size. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_WIN_SIZE 0x420
 
 /* MCDI_EVENT structuredef: The structure of an MCDI_EVENT on Siena/EF10/EF100
  * platforms
@@ -819,7 +1434,7 @@
 #define	MCDI_EVENT_AOE_FPGA_LOAD_FAILED 0xe
 /* enum: Notify that invalid flash type detected */
 #define	MCDI_EVENT_AOE_INVALID_FPGA_FLASH_TYPE 0xf
-/* enum: Notify that the attempt to run FPGA Controller firmware timedout */
+/* enum: Notify that the attempt to run FPGA Controller firmware timed out */
 #define	MCDI_EVENT_AOE_FC_RUN_TIMEDOUT 0x10
 /* enum: Failure to probe one or more FPGA boot flash chips */
 #define	MCDI_EVENT_AOE_FPGA_BOOT_FLASH_INVALID 0x11
@@ -837,7 +1452,7 @@
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_INFO_WIDTH 8
 /* enum: FC Assert happened, but the register information is not available */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_SEEN 0x0
-/* enum: The register information for FC Assert is ready for readinng by driver
+/* enum: The register information for FC Assert is ready for reading by driver
  */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_DATA_READY 0x1
 #define	MCDI_EVENT_AOE_ERR_CODE_FPGA_HEADER_VERIFY_FAILED_OFST 0
@@ -946,6 +1561,12 @@
 #define	MCDI_EVENT_MODULECHANGE_SEQ_OFST 0
 #define	MCDI_EVENT_MODULECHANGE_SEQ_LBN 30
 #define	MCDI_EVENT_MODULECHANGE_SEQ_WIDTH 2
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_LBN 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_WIDTH 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_LBN 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_WIDTH 16
 #define	MCDI_EVENT_DATA_LBN 0
 #define	MCDI_EVENT_DATA_WIDTH 32
 /* Alias for PTP_DATA. */
@@ -1076,6 +1697,18 @@
  * SF-122927-TC for details.
  */
 #define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_DRIVER_ATTACH 0x26
+/* enum: Notification that the mport journal has changed since it was last read
+ * and updates can be read using the MC_CMD_MAE_MPORT_READ_JOURNAL command. The
+ * firmware may moderate the events so that an event is not sent for every
+ * change to the journal.
+ */
+#define	MCDI_EVENT_CODE_MPORT_JOURNAL_CHANGE 0x27
+/* enum: Notification that a source queue is enabled and attached to its proxy
+ * sink queue. SRC field contains the handle of the affected descriptor proxy
+ * function. DATA field contains the relative source queue number and absolute
+ * VI ID.
+ */
+#define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_QUEUE_START 0x28
 /* enum: Artificial event generated by host and posted via MC for test
  * purposes.
  */
@@ -1842,6 +2475,7 @@
 /* Log destination */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_LEN 4
+/* enum property: bitmask */
 /* enum: UART. */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1
 /* enum: Event queue. */
@@ -1888,6 +2522,9 @@
 
 /* MC_CMD_GET_VERSION_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_OUT_LEN 32
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1910,6 +2547,9 @@
 
 /* MC_CMD_GET_VERSION_EXT_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_EXT_OUT_LEN 48
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1940,6 +2580,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V2_OUT_LEN 304
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2079,6 +2722,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V3_OUT_LEN 328
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2225,6 +2871,9 @@
  * version information
  */
 #define	MC_CMD_GET_VERSION_V4_OUT_LEN 392
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2387,6 +3036,9 @@
  * and board version information
  */
 #define	MC_CMD_GET_VERSION_V5_OUT_LEN 424
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2659,7 +3311,9 @@
 #define	MC_CMD_PTP_IN_CMD_LEN 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_OFST 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_LEN 4
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_LEN 4
 /* PTP timestamping mode. Not used from Huntington onwards. */
@@ -3030,7 +3684,9 @@
 #define	MC_CMD_PTP_ENABLE_PPS 0x0
 /* enum: Disable */
 #define	MC_CMD_PTP_DISABLE_PPS 0x1
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_OFST 8
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_LEN 4
 
@@ -3392,6 +4048,87 @@
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_OFST 20
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_LEN 4
 
+/* MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2 msgresponse */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_LEN 40
+/* Time format required/used by for this NIC. Applies to all PTP MCDI
+ * operations that pass times between the host and firmware. If this operation
+ * is not supported (older firmware) a format of seconds and nanoseconds should
+ * be assumed.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_OFST 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_LEN 4
+/* enum: Times are in seconds and nanoseconds */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_NANOSECONDS 0x0
+/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_16SECONDS_8NANOSECONDS 0x1
+/* enum: Major register has units of seconds, minor 2^-27s per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_27FRACTION 0x2
+/* enum: Major register units are seconds, minor units are quarter nanoseconds
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_QTR_NANOSECONDS 0x3
+/* Minimum acceptable value for a corrected synchronization timeset. When
+ * comparing host and NIC clock times, the MC returns a set of samples that
+ * contain the host start and end time, the MC time when the host start was
+ * detected and the time the MC waited between reading the time and detecting
+ * the host end. The corrected sync window is the difference between the host
+ * end and start times minus the time that the MC waited for host end.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_OFST 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_LEN 4
+/* Various PTP capabilities */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_LBN 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_LBN 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_LBN 2
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_LBN 3
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_OFST 12
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_OFST 16
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_OFST 20
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_LEN 4
+/* Minimum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of -0.1 ns should be assumed, which is
+ * equivalent to a -10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LBN 192
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_OFST 28
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LBN 224
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_WIDTH 32
+/* Maximum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of 0.1 ns should be assumed, which is
+ * equivalent to a +10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LBN 256
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_OFST 36
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LBN 288
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_WIDTH 32
+
 /* MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS msgresponse */
 #define	MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN 16
 /* Uncorrected error on PTP transmit timestamps in NIC clock format */
@@ -3443,12 +4180,16 @@
 /***********************************/
 /* MC_CMD_CSR_READ32
  * Read 32bit words from the indirect memory map.
+ *
+ * Note - this command originally belonged to INSECURE category. But access is
+ * required to specific registers for customer diagnostics. The command handler
+ * has additional checks to reject insecure calls.
  */
 #define	MC_CMD_CSR_READ32 0xc
 #define	MC_CMD_CSR_READ32_MSGSET 0xc
 #undef	MC_CMD_0xc_PRIVILEGE_CTG
 
-#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_INSECURE
+#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_ADMIN
 
 /* MC_CMD_CSR_READ32_IN msgrequest */
 #define	MC_CMD_CSR_READ32_IN_LEN 12
@@ -4221,6 +4962,7 @@
 /* Flags associated with this function */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_OFST 4
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_LEN 4
+/* enum property: bitshift */
 /* enum: Labels the lowest-numbered function visible to the OS */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY 0x0
 /* enum: The function can control the link state of the physical port it is
@@ -4454,6 +5196,54 @@
 /* MC_CMD_GET_PHY_CFG_IN msgrequest */
 #define	MC_CMD_GET_PHY_CFG_IN_LEN 0
 
+/* MC_CMD_GET_PHY_CFG_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_CFG_OUT msgresponse */
 #define	MC_CMD_GET_PHY_CFG_OUT_LEN 72
 /* flags */
@@ -4549,6 +5339,9 @@
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_OFST 8
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN 21
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_WIDTH 1
+#define	MC_CMD_PHY_CAP_200000FDX_OFST 8
+#define	MC_CMD_PHY_CAP_200000FDX_LBN 22
+#define	MC_CMD_PHY_CAP_200000FDX_WIDTH 1
 /* ?? */
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_LEN 4
@@ -4582,6 +5375,7 @@
 #define	MC_CMD_MEDIA_DSFP 0x8
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_LEN 4
+/* enum property: bitshift */
 /* enum: Native clause 22 */
 #define	MC_CMD_MMD_CLAUSE22 0x0
 #define	MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
@@ -4847,6 +5641,54 @@
 /* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
 #define	MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
 
+/* MC_CMD_GET_LOOPBACK_MODES_IN_V2 msgrequest */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_LEN 8
+/* Target port to request loopback modes for. Uses MAE_LINK_ENDPOINT_SELECTOR
+ * which identifies a real or virtual network port by MAE port and link end.
+ * See the structure definition for more details
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 40
 /* Supported loopbacks. */
@@ -4860,6 +5702,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 #define	MC_CMD_LOOPBACK_NONE 0x0
 /* enum: Data. */
@@ -4949,6 +5792,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4962,6 +5806,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4975,6 +5820,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4988,6 +5834,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5006,6 +5853,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 /*               MC_CMD_LOOPBACK_NONE 0x0 */
 /* enum: Data. */
@@ -5095,6 +5943,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5108,6 +5957,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5121,6 +5971,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5134,6 +5985,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 25G loopbacks. */
@@ -5147,6 +5999,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LBN 352
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 50 loopbacks. */
@@ -5160,6 +6013,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LBN 416
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 100G loopbacks. */
@@ -5173,6 +6027,214 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LBN 480
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT_V3 msgresponse: Supported loopback modes for
+ * newer NICs with 200G support
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_LEN 72
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_WIDTH 32
+/* enum property: bitshift */
+/* enum: None. */
+/*               MC_CMD_LOOPBACK_NONE 0x0 */
+/* enum: Data. */
+/*               MC_CMD_LOOPBACK_DATA 0x1 */
+/* enum: GMAC. */
+/*               MC_CMD_LOOPBACK_GMAC 0x2 */
+/* enum: XGMII. */
+/*               MC_CMD_LOOPBACK_XGMII 0x3 */
+/* enum: XGXS. */
+/*               MC_CMD_LOOPBACK_XGXS 0x4 */
+/* enum: XAUI. */
+/*               MC_CMD_LOOPBACK_XAUI 0x5 */
+/* enum: GMII. */
+/*               MC_CMD_LOOPBACK_GMII 0x6 */
+/* enum: SGMII. */
+/*               MC_CMD_LOOPBACK_SGMII 0x7 */
+/* enum: XGBR. */
+/*               MC_CMD_LOOPBACK_XGBR 0x8 */
+/* enum: XFI. */
+/*               MC_CMD_LOOPBACK_XFI 0x9 */
+/* enum: XAUI Far. */
+/*               MC_CMD_LOOPBACK_XAUI_FAR 0xa */
+/* enum: GMII Far. */
+/*               MC_CMD_LOOPBACK_GMII_FAR 0xb */
+/* enum: SGMII Far. */
+/*               MC_CMD_LOOPBACK_SGMII_FAR 0xc */
+/* enum: XFI Far. */
+/*               MC_CMD_LOOPBACK_XFI_FAR 0xd */
+/* enum: GPhy. */
+/*               MC_CMD_LOOPBACK_GPHY 0xe */
+/* enum: PhyXS. */
+/*               MC_CMD_LOOPBACK_PHYXS 0xf */
+/* enum: PCS. */
+/*               MC_CMD_LOOPBACK_PCS 0x10 */
+/* enum: PMA-PMD. */
+/*               MC_CMD_LOOPBACK_PMAPMD 0x11 */
+/* enum: Cross-Port. */
+/*               MC_CMD_LOOPBACK_XPORT 0x12 */
+/* enum: XGMII-Wireside. */
+/*               MC_CMD_LOOPBACK_XGMII_WS 0x13 */
+/* enum: XAUI Wireside. */
+/*               MC_CMD_LOOPBACK_XAUI_WS 0x14 */
+/* enum: XAUI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 */
+/* enum: XAUI Wireside near. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 */
+/* enum: GMII Wireside. */
+/*               MC_CMD_LOOPBACK_GMII_WS 0x17 */
+/* enum: XFI Wireside. */
+/*               MC_CMD_LOOPBACK_XFI_WS 0x18 */
+/* enum: XFI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 */
+/* enum: PhyXS Wireside. */
+/*               MC_CMD_LOOPBACK_PHYXS_WS 0x1a */
+/* enum: PMA lanes MAC-Serdes. */
+/*               MC_CMD_LOOPBACK_PMA_INT 0x1b */
+/* enum: KR Serdes Parallel (Encoder). */
+/*               MC_CMD_LOOPBACK_SD_NEAR 0x1c */
+/* enum: KR Serdes Serial. */
+/*               MC_CMD_LOOPBACK_SD_FAR 0x1d */
+/* enum: PMA lanes MAC-Serdes Wireside. */
+/*               MC_CMD_LOOPBACK_PMA_INT_WS 0x1e */
+/* enum: KR Serdes Parallel Wireside (Full PCS). */
+/*               MC_CMD_LOOPBACK_SD_FEP2_WS 0x1f */
+/* enum: KR Serdes Parallel Wireside (Sym Aligner to TX). */
+/*               MC_CMD_LOOPBACK_SD_FEP1_5_WS 0x20 */
+/* enum: KR Serdes Parallel Wireside (Deserializer to Serializer). */
+/*               MC_CMD_LOOPBACK_SD_FEP_WS 0x21 */
+/* enum: KR Serdes Serial Wireside. */
+/*               MC_CMD_LOOPBACK_SD_FES_WS 0x22 */
+/* enum: Near side of AOE Siena side port */
+/*               MC_CMD_LOOPBACK_AOE_INT_NEAR 0x23 */
+/* enum: Medford Wireside datapath loopback */
+/*               MC_CMD_LOOPBACK_DATA_WS 0x24 */
+/* enum: Force link up without setting up any physical loopback (snapper use
+ * only)
+ */
+/*               MC_CMD_LOOPBACK_FORCE_EXT_LINK 0x25 */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LBN 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_OFST 12
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LBN 96
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LBN 128
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_OFST 20
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LBN 160
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LBN 192
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_OFST 28
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LBN 224
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LBN 256
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_OFST 36
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LBN 288
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 25G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LBN 320
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_OFST 44
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LBN 352
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 50 loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LBN 384
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_OFST 52
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LBN 416
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 100G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LBN 448
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_OFST 60
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LBN 480
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 200G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LBN 512
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_OFST 68
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LBN 544
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5222,6 +6284,54 @@
 /* MC_CMD_GET_LINK_IN msgrequest */
 #define	MC_CMD_GET_LINK_IN_LEN 0
 
+/* MC_CMD_GET_LINK_IN_V2 msgrequest */
+#define	MC_CMD_GET_LINK_IN_V2_LEN 8
+/* Target port to request link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LINK_OUT msgresponse */
 #define	MC_CMD_GET_LINK_OUT_LEN 28
 /* Near-side advertised capabilities. Refer to
@@ -5498,6 +6608,95 @@
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_LBN 7
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_WIDTH 1
 
+/* MC_CMD_SET_LINK_IN_V3 msgrequest */
+#define	MC_CMD_SET_LINK_IN_V3_LEN 28
+/* Near-side advertised capabilities. Refer to
+ * MC_CMD_GET_PHY_CFG_OUT/SUPPORTED_CAP for bit definitions.
+ */
+#define	MC_CMD_SET_LINK_IN_V3_CAP_OFST 0
+#define	MC_CMD_SET_LINK_IN_V3_CAP_LEN 4
+/* Flags */
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_LBN 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_LBN 2
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_LBN 3
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_WIDTH 1
+/* Loopback mode. */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_OFST 8
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_LEN 4
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+/* A loopback speed of "0" is supported, and means (choose any available
+ * speed).
+ */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_OFST 12
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_WIDTH 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_LBN 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_WIDTH 1
+/* Padding */
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_OFST 17
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_LEN 3
+/* Target port to set link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_SET_LINK_OUT msgresponse */
 #define	MC_CMD_SET_LINK_OUT_LEN 0
 
@@ -5719,19 +6918,9 @@
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_OFST 28
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_LBN 4
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_WIDTH 1
-/* Identifies the MAC to update by the specifying the end of a logical MAE
- * link. Setting TARGET to MAE_LINK_ENDPOINT_COMPAT is equivalent to using the
- * previous version of the command (MC_CMD_SET_MAC_EXT). Not all possible
- * combinations of MPORT_END and MPORT_SELECTOR in TARGET will work in all
- * circumstances. 1. Some will always work (e.g. a VF can always address its
- * logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC), 2. Some are not
- * meaningful and will always fail with EINVAL (e.g. attempting to address the
- * VNIC end of a link to a physical port), 3. Some are meaningful but require
- * the MCDI client to have the required permission and fail with EPERM
- * otherwise (e.g. trying to set the MAC on a VF the caller cannot administer),
- * and 4. Some could be implementation-specific and fail with ENOTSUP if not
- * available (no examples exist right now). See SF-123581-TC section 4.3 for
- * more details.
+/* Target port to set mac state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
  */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_LEN 8
@@ -5743,6 +6932,7 @@
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LBN 288
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 32
@@ -5938,6 +7128,98 @@
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_OFST 16
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_LEN 4
 
+/* MC_CMD_MAC_STATS_V2_IN msgrequest */
+#define	MC_CMD_MAC_STATS_V2_IN_LEN 28
+/* ??? */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_OFST 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LBN 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_LBN 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_LBN 2
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_LBN 3
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_LBN 4
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_LBN 5
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_LBN 16
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_WIDTH 16
+/* DMA length. Should be set to MAC_STATS_NUM_STATS * sizeof(uint64_t), as
+ * returned by MC_CMD_GET_CAPABILITIES_V4_OUT. For legacy firmware not
+ * supporting MC_CMD_GET_CAPABILITIES_V4_OUT, DMA_LEN should be set to
+ * MC_CMD_MAC_NSTATS * sizeof(uint64_t)
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_OFST 12
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_LEN 4
+/* port id so vadapter stats can be provided */
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_OFST 16
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_LEN 4
+/* Target port to request statistics for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
 #define	MC_CMD_MAC_STATS_OUT_DMA_LEN 0
 
@@ -5954,6 +7236,7 @@
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+/* enum property: index */
 #define	MC_CMD_MAC_GENERATION_START 0x0 /* enum */
 #define	MC_CMD_MAC_DMABUF_START 0x1 /* enum */
 #define	MC_CMD_MAC_TX_PKTS 0x1 /* enum */
@@ -6116,6 +7399,7 @@
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V2
+/* enum property: index */
 /* enum: Start of FEC stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_FEC_DMABUF_START 0x61
 /* enum: Number of uncorrected FEC codewords on link (RS-FEC only for Medford2)
@@ -6155,6 +7439,7 @@
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V3
+/* enum property: index */
 /* enum: Start of CTPIO stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_CTPIO_DMABUF_START 0x68
 /* enum: Number of CTPIO fallbacks because a DMA packet was in progress on the
@@ -6235,6 +7520,7 @@
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V4
+/* enum property: index */
 /* enum: Start of V4 stats buffer space */
 #define	MC_CMD_MAC_V4_DMABUF_START 0x79
 /* enum: RXDP counter: Number of packets truncated because scattering was
@@ -6522,6 +7808,7 @@
 #define	MC_CMD_WOL_FILTER_RESET_IN_LEN 4
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_LEN 4
+/* enum property: bitmask */
 #define	MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
 #define	MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
 
@@ -6566,6 +7853,7 @@
 /* Bit mask of supported types. */
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_LEN 4
+/* enum property: bitshift */
 /* enum: Disabled callisto. */
 #define	MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0
 /* enum: MC firmware. */
@@ -7613,6 +8901,54 @@
 /* MC_CMD_GET_PHY_STATE_IN msgrequest */
 #define	MC_CMD_GET_PHY_STATE_IN_LEN 0
 
+/* MC_CMD_GET_PHY_STATE_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_STATE_OUT msgresponse */
 #define	MC_CMD_GET_PHY_STATE_OUT_LEN 4
 #define	MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
@@ -7884,6 +9220,62 @@
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_LBN 16
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_WIDTH 16
 
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_LEN 12
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_LBN 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_WIDTH 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_LBN 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_WIDTH 16
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 7
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 52
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 48
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 6
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
@@ -9069,27 +10461,22 @@
  * and a generation count for this version of the sensor table. On systems
  * advertising the DYNAMIC_SENSORS capability bit, this replaces the
  * MC_CMD_READ_SENSORS command. On multi-MC systems this may include sensors
- * added by the NMC.
- *
- * Sensor handles are persistent for the lifetime of the sensor and are used to
- * identify sensors in MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
- * MC_CMD_DYNAMIC_SENSORS_GET_VALUES.
- *
- * The generation count is maintained by the MC, is persistent across reboots
- * and will be incremented each time the sensor table is modified. When the
- * table is modified, a CODE_DYNAMIC_SENSORS_CHANGE event will be generated
- * containing the new generation count. The driver should compare this against
- * the current generation count, and if it is different, call
- * MC_CMD_DYNAMIC_SENSORS_LIST again to update it's copy of the sensor table.
- *
- * The sensor count is provided to allow a future path to supporting more than
+ * added by the NMC. Sensor handles are persistent for the lifetime of the
+ * sensor and are used to identify sensors in
+ * MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
+ * MC_CMD_DYNAMIC_SENSORS_GET_VALUES. The generation count is maintained by the
+ * MC, is persistent across reboots and will be incremented each time the
+ * sensor table is modified. When the table is modified, a
+ * CODE_DYNAMIC_SENSORS_CHANGE event will be generated containing the new
+ * generation count. The driver should compare this against the current
+ * generation count, and if it is different, call MC_CMD_DYNAMIC_SENSORS_LIST
+ * again to update it's copy of the sensor table. The sensor count is provided
+ * to allow a future path to supporting more than
  * MC_CMD_DYNAMIC_SENSORS_GET_READINGS_IN_HANDLES_MAXNUM_MCDI2 sensors, i.e.
  * the maximum number that will fit in a single response. As this is a fairly
  * large number (253) it is not anticipated that this will be needed in the
- * near future, so can currently be ignored.
- *
- * On Riverhead this command is implemented as a a wrapper for `list` in the
- * sensor_query SPHINX service.
+ * near future, so can currently be ignored. On Riverhead this command is
+ * implemented as a wrapper for `list` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_LIST 0x66
 #define	MC_CMD_DYNAMIC_SENSORS_LIST_MSGSET 0x66
@@ -9127,15 +10514,13 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS
  * Get descriptions for a set of sensors, specified as an array of sensor
- * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for
- * `get_descriptions` in the sensor_query SPHINX service.
+ * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. Any handles which do not
+ * correspond to a sensor currently managed by the MC will be dropped from from
+ * the response. This may happen when a sensor table update is in progress, and
+ * effectively means the set of usable sensors is the intersection between the
+ * sets of sensors known to the driver and the MC. On Riverhead this command is
+ * implemented as a wrapper for `get_descriptions` in the sensor_query SPHINX
+ * service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS 0x67
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS_MSGSET 0x67
@@ -9173,19 +10558,15 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_READINGS
  * Read the state and value for a set of sensors, specified as an array of
- * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST.
- *
- * In the case of a broken sensor, then the state of the response's
- * MC_CMD_DYNAMIC_SENSORS_VALUE entry will be set to BROKEN, and any value
- * provided should be treated as erroneous.
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for `get_readings`
- * in the sensor_query SPHINX service.
+ * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. In the case of a
+ * broken sensor, then the state of the response's MC_CMD_DYNAMIC_SENSORS_VALUE
+ * entry will be set to BROKEN, and any value provided should be treated as
+ * erroneous. Any handles which do not correspond to a sensor currently managed
+ * by the MC will be dropped from from the response. This may happen when a
+ * sensor table update is in progress, and effectively means the set of usable
+ * sensors is the intersection between the sets of sensors known to the driver
+ * and the MC. On Riverhead this command is implemented as a wrapper for
+ * `get_readings` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS 0x68
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS_MSGSET 0x68
@@ -11629,6 +13010,9 @@
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_LBN 11
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -11833,6 +13217,9 @@
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12118,6 +13505,9 @@
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12663,6 +14053,7 @@
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_OFST 0
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_LEN 4
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_NUM 4
+/* enum property: bitmask */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP0 0x1 /* enum */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP1 0x2 /* enum */
 
@@ -13511,10 +14902,9 @@
 
 /***********************************/
 /* MC_CMD_GET_CAPABILITIES
- * Get device capabilities.
- *
- * This is supplementary to the MC_CMD_GET_BOARD_CFG command, and intended to
- * reference inherent device capabilities as opposed to current NVRAM config.
+ * Get device capabilities. This is supplementary to the MC_CMD_GET_BOARD_CFG
+ * command, and intended to reference inherent device capabilities as opposed
+ * to current NVRAM config.
  */
 #define	MC_CMD_GET_CAPABILITIES 0xbe
 #define	MC_CMD_GET_CAPABILITIES_MSGSET 0xbe
@@ -16473,6 +17863,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 
 /* MC_CMD_GET_CAPABILITIES_V8_OUT msgresponse */
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_LEN 160
@@ -16974,6 +18373,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -17489,6 +18897,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18039,6 +19456,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18134,6 +19560,13 @@
  * are not defined.
  */
 #define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_TSA 0x1
+/* enum: MCDI command used for platform management. Typically, these commands
+ * are used for low-level operations directed at the platform as a whole (e.g.
+ * MMIO device enumeration) rather than individual functions and use a
+ * dedicated comms channel (e.g. RPmsg/IPI). May be handled by the same or
+ * different CPU as MCDI_MESSAGE_TYPE_MC.
+ */
+#define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM 0x2
 
 
 /***********************************/
@@ -22051,8 +23484,8 @@
  * TLV_PORT_MODE_*). A superset of MC_CMD_GET_PORT_MODES_OUT/MODES that
  * contains all modes implemented in firmware for a particular board. Modes
  * listed in MODES are considered production modes and should be exposed in
- * userland tools. Modes listed in in ENGINEERING_MODES, but not in MODES
- * should be considered hidden (not to be exposed in userland tools) and for
+ * userland tools. Modes listed in ENGINEERING_MODES, but not in MODES should
+ * be considered hidden (not to be exposed in userland tools) and for
  * engineering use only. There are no other semantic differences and any mode
  * listed in either MODES or ENGINEERING_MODES can be set on the board.
  */
@@ -26509,6 +27942,7 @@
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MINNUM 0
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM 31
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_PACKETS 0x0 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_BYTES 0x1 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_GOOD_PACKETS 0x2 /* enum */
@@ -26617,6 +28051,65 @@
 /* MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT msgresponse */
 #define	MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT_LEN 0
 
+
+/***********************************/
+/* MC_CMD_GET_BUFTBL_STATS
+ * Currently EF10 only. Read usage and limits for Buffer Table
+ */
+#define	MC_CMD_GET_BUFTBL_STATS 0x6a
+#define	MC_CMD_GET_BUFTBL_STATS_MSGSET 0x6a
+#undef	MC_CMD_0x6a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x6a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_GET_BUFTBL_STATS_IN msgrequest */
+#define	MC_CMD_GET_BUFTBL_STATS_IN_LEN 0
+
+/* MC_CMD_GET_BUFTBL_STATS_OUT msgresponse */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_LEN 40
+/* number of buffer table entries per set */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_OFST 0
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_LEN 4
+/* number of buffer table entries per cluster */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_OFST 4
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_LEN 4
+/* Maximum size buffer table can grow to, in clusters. On EF10, this can
+ * potentially vary depending on the size of the Descriptor Cache.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_OFST 8
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_LEN 4
+/* High water mark for number of buffer table clusters which have been
+ * allocated.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_OFST 12
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_LEN 4
+/* Number of free buffer table clusters on the free cluster list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_OFST 16
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_LEN 4
+/* Number of free buffer table sets on the free set list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_OFST 20
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_LEN 4
+/* Number of chunks of fully-used clusters allocated to the MC for EVQ, RXQ and
+ * TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_OFST 24
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_LEN 4
+/* Number of chunks in partially-used clusters allocated to the MC for EVQ, RXQ
+ * and TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_OFST 28
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_LEN 4
+/* Number of buffer table sets (chunks) allocated to the host via
+ * MC_CMD_ALLOC_BUFTBL_CHUNK.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_OFST 32
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_LEN 4
+/* Maximum number of VIs per NIC. On EF10 this is the current value as used to
+ * size the Descriptor Cache in hardware.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_OFST 36
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_LEN 4
+
 /* CLIENT_HANDLE structuredef: A client is an abstract entity that can make
  * requests of the device and that can own resources managed by the device.
  * Examples of clients include PCIe functions and dynamic clients. A client
@@ -26684,8 +28177,8 @@
 
 /* SCHED_CREDIT_CHECK_RESULT structuredef */
 #define	SCHED_CREDIT_CHECK_RESULT_LEN 16
-/* The instance of the scheduler. Refer to XN-200389-AW for the location of
- * these schedulers in the hardware.
+/* The instance of the scheduler. Refer to XN-200389-AW (snic/hnic) and
+ * XN-200425-TC (cdx) for the location of these schedulers in the hardware.
  */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_OFST 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LEN 1
@@ -26697,6 +28190,18 @@
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_HOST_D 0x5 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_REPLAY 0x6 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_DMAC_H2C 0x7 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_B 0x8 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_REPLAY 0x9 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_ADAPTER_C2H_C 0xa /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A2_H2C_C 0xb /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A3_SOFT_ADAPTOR_C 0xc /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A4_DPU_WRITE_C 0xd /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_JRC_RRU 0xe /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_CDM_SINK 0xf /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PCIE_SINK 0x10 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_UPORT_SINK 0x11 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PSX_SINK 0x12 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A5_DPU_READ_C 0x13 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LBN 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_WIDTH 8
 /* The type of node that this result refers to. */
@@ -26706,6 +28211,10 @@
 #define	SCHED_CREDIT_CHECK_RESULT_DEST 0x0
 /* enum: Source node */
 #define	SCHED_CREDIT_CHECK_RESULT_SOURCE 0x1
+/* enum: Destination node credit type 1 (new to the Keystone schedulers, see
+ * SF-120268-TC)
+ */
+#define	SCHED_CREDIT_CHECK_RESULT_DEST_CREDIT1 0x2
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_LBN 8
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_WIDTH 8
 /* Level of node in scheduler hierarchy (level 0 is the bottom of the
@@ -27813,6 +29322,51 @@
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM 14
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM_MCDI2 62
 
+
+/***********************************/
+/* MC_CMD_TXQ_STATS
+ * Query per-TXQ statistics.
+ */
+#define	MC_CMD_TXQ_STATS 0x1d5
+#define	MC_CMD_TXQ_STATS_MSGSET 0x1d5
+#undef	MC_CMD_0x1d5_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1d5_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TXQ_STATS_IN msgrequest */
+#define	MC_CMD_TXQ_STATS_IN_LEN 8
+/* Instance of TXQ to retrieve statistics for */
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_OFST 0
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_LEN 4
+/* Flags for the request */
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_LEN 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_LBN 0
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_WIDTH 1
+
+/* MC_CMD_TXQ_STATS_OUT msgresponse */
+#define	MC_CMD_TXQ_STATS_OUT_LENMIN 0
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX 248
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX_MCDI2 1016
+#define	MC_CMD_TXQ_STATS_OUT_LEN(num) (0+8*(num))
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_NUM(len) (((len)-0)/8)
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LEN 8
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LBN 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_OFST 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LBN 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MINNUM 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM 31
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
+#define	MC_CMD_TXQ_STATS_CTPIO_MAX_FILL 0x0 /* enum */
+
 /* FUNCTION_PERSONALITY structuredef: The meanings of the personalities are
  * defined in SF-120734-TC with more information in SF-122717-TC.
  */
@@ -28296,6 +29850,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LBN 32
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_VF_OFST 2
@@ -28332,6 +29887,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_VF_OFST 6
@@ -28709,6 +30265,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_VF_OFST 6
@@ -28788,6 +30345,7 @@
 #define	DESC_PROXY_FUNC_MAP_FUNC_HI_WIDTH 32
 #define	DESC_PROXY_FUNC_MAP_FUNC_LBN 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_WIDTH 64
+/* See structuredef: PCIE_FUNCTION */
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_OFST 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LEN 2
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LBN 0
@@ -28851,6 +30409,27 @@
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM 4
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM_MCDI2 19
+/* See structuredef: DESC_PROXY_FUNC_MAP */
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LEN 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LBN 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LBN 64
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_OFST 6
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_OFST 12
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_OFST 16
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_LEN 40
 
 
 /***********************************/
@@ -29015,6 +30594,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM 63
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM_MCDI2 255
+/* See structuredef: QUEUE_ID */
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_REL_QUEUE_LBN 16
@@ -29082,6 +30662,7 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LEN 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LBN 64
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_VF_OFST 6
@@ -29162,6 +30743,7 @@
  * backwards compatibility only, callers should use PCIE_INTERFACE_CALLER.
  */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_PCIE_FUNCTION_INTF_NULL 0xffffffff
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_VF_OFST 6
@@ -29320,6 +30902,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LBN 1096
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_OFST 138
@@ -29333,10 +30916,12 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_WIDTH 8
+/* More generic alias for ENC_VLAN_FLAGS. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS_MASK alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_MASK_OFST 139
@@ -29350,6 +30935,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LBN 1112
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_WIDTH 8
+/* More generic alias for ENC_FLAGS_MASK. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LBN 1112
@@ -29503,6 +31089,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LBN 1152
@@ -29826,6 +31416,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LBN 1152
@@ -30120,7 +31714,7 @@
 /* MAE_MPORT_SELECTOR structuredef: MPORTS are identified by an opaque unsigned
  * integer value (mport_id) that is guaranteed to be representable within
  * 32-bits or within any NIC interface field that needs store the value
- * (whichever is narrowers). This selector structure provides a stable way to
+ * (whichever is narrower). This selector structure provides a stable way to
  * refer to m-ports.
  */
 #define	MAE_MPORT_SELECTOR_LEN 4
@@ -30195,10 +31789,22 @@
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
 /* MAE_LINK_ENDPOINT_SELECTOR structuredef: Structure that identifies a real or
- * virtual network port by MAE port and link end
+ * virtual network port by MAE port and link end. Intended to be used by
+ * network port MCDI commands. Setting FLAT to MAE_LINK_ENDPOINT_COMPAT is
+ * equivalent to using the previous version of the command. Not all possible
+ * combinations of MPORT_END and MPORT_SELECTOR in MAE_LINK_ENDPOINT_SELECTOR
+ * will work in all circumstances. 1. Some will always work (e.g. a VF can
+ * always address its logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC),
+ * 2. Some are not meaningful and will always fail with EINVAL (e.g. attempting
+ * to address the VNIC end of a link to a physical port), 3. Some are
+ * meaningful but require the MCDI client to have the required permission and
+ * fail with EPERM otherwise (e.g. trying to set the MAC on a VF the caller
+ * cannot administer), and 4. Some could be implementation-specific and fail
+ * with ENOTSUP if not available (no examples exist right now). See
+ * SF-123581-TC section 4.3 for more details.
  */
 #define	MAE_LINK_ENDPOINT_SELECTOR_LEN 8
-/* The MAE MPORT of interest */
+/* Identifier for the MAE MPORT of interest */
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_OFST 0
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LEN 4
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LBN 0
@@ -30395,6 +32001,90 @@
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_OFST 56
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_LEN 4
 
+/* MC_CMD_MAE_GET_CAPS_V3_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_LEN 64
+/* The number of field IDs that the NIC supports. Any field with a ID greater
+ * than or equal to the value returned in this field must be treated as having
+ * a support level of MAE_FIELD_UNSUPPORTED in all requests.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_LBN 3
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_WIDTH 1
+/* Deprecated alias for AR_COUNTERS. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_LEN 4
+/* The total number of AR counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_LEN 4
+/* The total number of counters lists available to allocate. A value of zero
+ * indicates that counter lists are not supported by the NIC. (But single
+ * counters may still be.)
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_LEN 4
+/* The number of priorities available for ACTION_RULE filters. It is invalid to
+ * install a MATCH_ACTION filter with a priority number >= ACTION_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_LEN 4
+/* The number of priorities available for OUTER_RULE filters. It is invalid to
+ * install an OUTER_RULE filter with a priority number >= OUTER_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_LEN 4
+/* MAE API major version. Currently 1. If this field is not present in the
+ * response (i.e. response shorter than 384 bits), then its value is zero. If
+ * the value does not match the client's expectations, the client should raise
+ * a fatal error.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_LEN 4
+/* Mask of supported counter types. Each bit position corresponds to a value of
+ * the MAE_COUNTER_TYPE enum. If this field is missing (i.e. V1 response),
+ * clients must assume that only AR counters are supported (i.e.
+ * COUNTER_TYPES_SUPPORTED==0x1). See also
+ * MC_CMD_MAE_COUNTERS_STREAM_START/COUNTER_TYPES_MASK.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_OFST 52
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_LEN 4
+/* The total number of conntrack counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_OFST 56
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_LEN 4
+/* The total number of Outer Rule counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_OFST 60
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_LEN 4
+
 
 /***********************************/
 /* MC_CMD_MAE_GET_AR_CAPS
@@ -30498,10 +32188,13 @@
 /* Generation count. Packets with generation count >= GENERATION_COUNT will
  * contain valid counter values for counter IDs allocated in this call, unless
  * the counter values are zero and zero squash is enabled. Note that there is
- * an independent GENERATION_COUNT object per counter type.
+ * an independent GENERATION_COUNT object per counter type, and that generation
+ * counts wrap from 0xffffffff to 1.
  */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* enum: Generation counter 0 is reserved and unused. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_INVALID 0x0
 /* The number of counter IDs that the NIC allocated. It is never less than 1;
  * failure to allocate a single counter will cause an error to be returned. It
  * is never greater than REQUESTED_COUNT, but may be less.
@@ -30516,6 +32209,8 @@
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2 253
 /* enum: A counter ID that is guaranteed never to represent a real counter */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL 0xffffffff
+/*            Other enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 
 
 /***********************************/
@@ -30577,7 +32272,8 @@
  * values will be written for these counters. If values for these counter IDs
  * are present, the counter ID has been reallocated. A counter ID will not be
  * reallocated within a single read cycle as this would merge increments from
- * the 'old' and 'new' counters.
+ * the 'old' and 'new' counters. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
@@ -30696,7 +32392,8 @@
 /* Generation count for AR counters. The final set of AR counter values will be
  * written out in packets with count == GENERATION_COUNT. An empty packet with
  * count > GENERATION_COUNT indicates that no more counter values of this type
- * will be written to this stream.
+ * will be written to this stream. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
@@ -30712,6 +32409,7 @@
  * final set of counter values will be written out in packets with count ==
  * GENERATION_COUNT. An empty packet with count > GENERATION_COUNT indicates
  * that no more counter values of this type will be written to this stream.
+ * GENERATION_COUNT_INVALID is reserved and unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_LEN 4
@@ -30960,6 +32658,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_LEN 2
@@ -30985,19 +32701,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31041,6 +32761,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_LEN 2
@@ -31066,19 +32804,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31131,6 +32873,172 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_LBN 6
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_WIDTH 1
 
+/* MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN msgrequest: Only supported if
+ * MAE_ACTION_SET_ALLOC_V3_SUPPORTED is advertised in
+ * MC_CMD_GET_CAPABILITIES_V10_OUT.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LEN 53
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_LBN 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_LBN 13
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_LBN 14
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_WIDTH 1
+/* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_LEN 2
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_LEN 4
+/* An m-port selector identifying the m-port that the modified packet should be
+ * delivered to. Set to MPORT_SELECTOR_NULL to request no delivery of the
+ * packet.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_OFST 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_LEN 4
+/* Allows an action set to trigger several counter updates. Set to
+ * MAE_COUNTER_ID_NULL to request no counter action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_OFST 24
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+/* If a driver only wished to update one counter within this action set, then
+ * it can supply a COUNTER_ID instead of allocating a single-element counter
+ * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * COUNTER_ID.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_OFST 28
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_OFST 32
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_LEN 4
+/* Set to MAC_ID_NULL to request no source MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_LEN 4
+/* Source m-port ID to be reported for DO_SET_SRC_MPORT action. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_OFST 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_LEN 4
+/* Actions for modifying the Differentiated Services Code-Point (DSCP) bits
+ * within IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_LEN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_WIDTH 6
+/* Actions for modifying the Explicit Congestion Notification (ECN) bits within
+ * IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_LBN 5
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_LBN 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_WIDTH 1
+/* Actions for overwriting CH_ROUTE subfields. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_WIDTH 1
+/* Override outgoing CH_VC to network port for DO_SET_NET_CHAN action. Cannot
+ * be used in conjunction with DO_SET_SRC_MPORT action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_OFST 52
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_LEN 1
+
 /* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
 /* The MSB of the AS_ID is guaranteed to be clear if the ID is not
@@ -31297,6 +33205,7 @@
  */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+/* Deprecated alias for ACTION_CONTROL. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_LEN 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_OFST 8
@@ -31307,15 +33216,26 @@
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_WIDTH 2
 /*             Enum values, see field(s): */
 /*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_LBN 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_WIDTH 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_LBN 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_WIDTH 16
-/* Reserved for future use. Must be set to zero. */
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_OFST 12
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_LEN 4
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_LEN 4
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_LEN 4
 /* Structure of the format MAE_ENC_FIELD_PAIRS. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_LEN 1
@@ -31367,6 +33287,59 @@
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM 32
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM_MCDI2 32
 
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_UPDATE
+ * Atomically change the response of an Outer Rule.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE 0x17d
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_MSGSET 0x17d
+#undef	MC_CMD_0x17d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x17d_PRIVILEGE_CTG SRIOV_CTG_MAE
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_LEN 16
+/* ID of outer rule to update */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_LEN 4
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_LBN 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_LBN 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_WIDTH 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_LBN 16
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_WIDTH 16
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_LEN 4
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_OUT_LEN 0
+
 /* MAE_ACTION_RULE_RESPONSE structuredef */
 #define	MAE_ACTION_RULE_RESPONSE_LEN 16
 #define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
@@ -31932,6 +33905,7 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_OFST 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_LBN 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_WIDTH 1
+/* The number of MAE_MPORT_DESC structures in MPORT_DESC_DATA. May be zero. */
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_OFST 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_LEN 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC_OFST 8
@@ -31946,4 +33920,407 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM 240
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1008
 
+/* TABLE_FIELD_DESCR structuredef: An individual table field descriptor. This
+ * describes the location and properties of one N-bit field within a wider
+ * M-bit key/mask/response value.
+ */
+#define	TABLE_FIELD_DESCR_LEN 8
+/* Identifier for this field. */
+#define	TABLE_FIELD_DESCR_FIELD_ID_OFST 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_LEN 2
+/*            Enum values, see field(s): */
+/*               TABLE_FIELD_ID */
+#define	TABLE_FIELD_DESCR_FIELD_ID_LBN 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_WIDTH 16
+/* Lowest (least significant) bit number of the bits of this field. */
+#define	TABLE_FIELD_DESCR_LBN_OFST 2
+#define	TABLE_FIELD_DESCR_LBN_LEN 2
+#define	TABLE_FIELD_DESCR_LBN_LBN 16
+#define	TABLE_FIELD_DESCR_LBN_WIDTH 16
+/* Width of this field in bits. */
+#define	TABLE_FIELD_DESCR_WIDTH_OFST 4
+#define	TABLE_FIELD_DESCR_WIDTH_LEN 2
+#define	TABLE_FIELD_DESCR_WIDTH_LBN 32
+#define	TABLE_FIELD_DESCR_WIDTH_WIDTH 16
+/* The mask type for this field. (Note that masking is relevant to keys; fields
+ * of responses are always reported with the EXACT type.)
+ */
+#define	TABLE_FIELD_DESCR_MASK_TYPE_OFST 6
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LEN 1
+/* enum: Field must never be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_NEVER 0x0
+/* enum: Exact match: field must always be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_EXACT 0x1
+/* enum: Ternary match: arbitrary mask bits are allowed. */
+#define	TABLE_FIELD_DESCR_MASK_TERNARY 0x2
+/* enum: Whole field match: mask must be all 1 bits, or all 0 bits. */
+#define	TABLE_FIELD_DESCR_MASK_WHOLE_FIELD 0x3
+/* enum: Longest prefix match: mask must be 1 bit(s) followed by 0 bit(s). */
+#define	TABLE_FIELD_DESCR_MASK_LPM 0x4
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LBN 48
+#define	TABLE_FIELD_DESCR_MASK_TYPE_WIDTH 8
+/* A version code that allows field semantics to be extended. All fields
+ * currently use version 0.
+ */
+#define	TABLE_FIELD_DESCR_SCHEME_OFST 7
+#define	TABLE_FIELD_DESCR_SCHEME_LEN 1
+#define	TABLE_FIELD_DESCR_SCHEME_LBN 56
+#define	TABLE_FIELD_DESCR_SCHEME_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_TABLE_LIST
+ * Return the list of tables which may be accessed via this table API.
+ */
+#define	MC_CMD_TABLE_LIST 0x1c9
+#define	MC_CMD_TABLE_LIST_MSGSET 0x1c9
+#undef	MC_CMD_0x1c9_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1c9_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_LIST_IN msgrequest */
+#define	MC_CMD_TABLE_LIST_IN_LEN 4
+/* Index of the first item to be returned in the TABLE_ID sequence. (Set to 0
+ * for the first call; further calls are only required if the whole sequence
+ * does not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_OFST 0
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_LEN 4
+
+/* MC_CMD_TABLE_LIST_OUT msgresponse */
+#define	MC_CMD_TABLE_LIST_OUT_LENMIN 4
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX 252
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_LIST_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(len) (((len)-4)/4)
+/* The total number of tables. */
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_OFST 0
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_LEN 4
+/* A sequence of table identifiers. If all N_TABLES items do not fit, further
+ * items can be obtained by repeating the call with a non-zero
+ * FIRST_TABLE_ID_INDEX.
+ */
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_OFST 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_LEN 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MINNUM 0
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM 62
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM_MCDI2 254
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+
+
+/***********************************/
+/* MC_CMD_TABLE_DESCRIPTOR
+ * Request the table descriptor for a particular table. This describes
+ * properties of the table and the format of the key and response. May return
+ * EINVAL for unknown table ID.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR 0x1ca
+#define	MC_CMD_TABLE_DESCRIPTOR_MSGSET 0x1ca
+#undef	MC_CMD_0x1ca_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ca_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DESCRIPTOR_IN msgrequest */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_LEN 8
+/* Identifier for this field. */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Index of the first item to be returned in the FIELDS sequence. (Set to 0 for
+ * the first call; further calls are only required if the whole sequence does
+ * not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_LEN 4
+
+/* MC_CMD_TABLE_DESCRIPTOR_OUT msgresponse */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN 28
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX 252
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(num) (20+8*(num))
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(len) (((len)-20)/8)
+/* Maximum number of entries in this table. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_LEN 4
+/* The type of table. (This is really just informational; the important
+ * properties of a table that affect programming can be deduced from other
+ * items in the table or field descriptor.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_LEN 2
+/* enum: Direct table (essentially just an array). Behaves like a BCAM for
+ * programming purposes, where the fact that the key is actually used as an
+ * array index is really just an implementation detail.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_DIRECT 0x1
+/* enum: BCAM (binary CAM) table: exact match on all key fields." */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM 0x2
+/* enum: TCAM (ternary CAM) table: matches fields with a mask. Each entry may
+ * have its own different mask.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_TCAM 0x3
+/* enum: STCAM (semi-TCAM) table: like a TCAM but entries shared a limited
+ * number of unique masks.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_STCAM 0x4
+/* Width of key (and corresponding mask, for TCAM or STCAM) in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_LEN 2
+/* Width of response in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_LEN 2
+/* The total number of fields in the key. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_OFST 10
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_LEN 2
+/* The total number of fields in the response. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_OFST 12
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_LEN 2
+/* Number of priorities for STCAM or TCAM; otherwise 0. The priority of a table
+ * entry (relevant when more than one masked entry matches) ranges from
+ * 0=highest to N_PRIORITIES-1=lowest.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_OFST 14
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_LEN 2
+/* Maximum number of masks for STCAM; otherwise 0. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_OFST 16
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_LEN 2
+/* Flags. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_LEN 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_LBN 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_WIDTH 1
+/* Access scheme version code, allowing the method of accessing table entries
+ * to change semantics in future. A client which does not understand the value
+ * of this field should assume that it cannot program this table. Currently
+ * always set to 0 indicating the original MC_CMD_TABLE_INSERT/UPDATE/DELETE
+ * semantics.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_OFST 19
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_LEN 1
+/* A sequence of TABLE_FIELD_DESCR structures: N_KEY_FIELDS items describing
+ * the key, followed by N_RESP_FIELDS items describing the response. If all
+ * N_KEY_FIELDS+N_RESP_FIELDS items do not fit, further items can be obtained
+ * by repeating the call with a non-zero FIRST_FIELDS_INDEX.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LEN 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LBN 160
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_OFST 24
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LBN 192
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MINNUM 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM 29
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM_MCDI2 125
+
+
+/***********************************/
+/* MC_CMD_TABLE_INSERT
+ * Insert a new entry into a table. The entry must not currently exist. May
+ * return EINVAL for unknown table ID or other bad request parameters, EEXIST
+ * if the entry already exists, ENOSPC if there is no space or EPERM if the
+ * operation is not permitted. In case of an error, the additional MCDI error
+ * argument field returns the raw error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_INSERT 0x1cd
+#define	MC_CMD_TABLE_INSERT_MSGSET 0x1cd
+#undef	MC_CMD_0x1cd_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cd_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_INSERT_IN msgrequest */
+#define	MC_CMD_TABLE_INSERT_IN_LENMIN 16
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX 252
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_INSERT_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_INSERT_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_INSERT_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_INSERT_OUT msgresponse */
+#define	MC_CMD_TABLE_INSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_UPDATE
+ * Update an existing entry in a table with a new response value. May return
+ * EINVAL for unknown table ID or other bad request parameters, ENOENT if the
+ * entry does not already exist, or EPERM if the operation is not permitted. In
+ * case of an error, the additional MCDI error argument field returns the raw
+ * error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_UPDATE 0x1ce
+#define	MC_CMD_TABLE_UPDATE_MSGSET 0x1ce
+#undef	MC_CMD_0x1ce_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ce_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_UPDATE_IN msgrequest */
+#define	MC_CMD_TABLE_UPDATE_IN_LENMIN 16
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX 252
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_UPDATE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_UPDATE_OUT msgresponse */
+#define	MC_CMD_TABLE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_DELETE
+ * Delete an existing entry in a table. May return EINVAL for unknown table ID
+ * or other bad request parameters, ENOENT if the entry does not exist, or
+ * EPERM if the operation is not permitted. In case of an error, the additional
+ * MCDI error argument field returns the raw error code from the underlying CAM
+ * driver.
+ */
+#define	MC_CMD_TABLE_DELETE 0x1cf
+#define	MC_CMD_TABLE_DELETE_MSGSET 0x1cf
+#undef	MC_CMD_0x1cf_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cf_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DELETE_IN msgrequest */
+#define	MC_CMD_TABLE_DELETE_IN_LENMIN 16
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX 252
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DELETE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_DELETE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_DELETE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_DELETE_OUT msgresponse */
+#define	MC_CMD_TABLE_DELETE_OUT_LEN 0
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 02/34] common/sfc_efx/base: detect MCDI Table Access API support
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
                     ` (31 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Future patches will add an implementation of MCDI Table
Access API in libefx. This patch adds a way to determine
if this API is supported.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h          | 2 ++
 drivers/common/sfc_efx/base/hunt_nic.c     | 2 ++
 drivers/common/sfc_efx/base/medford2_nic.c | 2 ++
 drivers/common/sfc_efx/base/medford_nic.c  | 2 ++
 drivers/common/sfc_efx/base/rhead_nic.c    | 9 +++++++++
 drivers/common/sfc_efx/base/siena_nic.c    | 2 ++
 6 files changed, 19 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 49e29dcc1c..f9b090e35e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1672,6 +1672,8 @@ typedef struct efx_nic_cfg_s {
 	boolean_t		enc_mae_admin;
 	/* NIC support for MAE action set v2 features. */
 	boolean_t		enc_mae_aset_v2_supported;
+	/* NIC support for MCDI Table Access API. */
+	boolean_t		enc_table_api_supported;
 	/* Firmware support for "FLAG" and "MARK" filter actions */
 	boolean_t		enc_filter_action_flag_supported;
 	boolean_t		enc_filter_action_mark_supported;
diff --git a/drivers/common/sfc_efx/base/hunt_nic.c b/drivers/common/sfc_efx/base/hunt_nic.c
index 08ae324482..04595a39c8 100644
--- a/drivers/common/sfc_efx/base/hunt_nic.c
+++ b/drivers/common/sfc_efx/base/hunt_nic.c
@@ -192,6 +192,8 @@ hunt_board_cfg(
 	/* All Huntington devices have a PCIe Gen3, 8 lane connector */
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford2_nic.c b/drivers/common/sfc_efx/base/medford2_nic.c
index 6d19524573..49adabffb2 100644
--- a/drivers/common/sfc_efx/base/medford2_nic.c
+++ b/drivers/common/sfc_efx/base/medford2_nic.c
@@ -152,6 +152,8 @@ medford2_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford_nic.c b/drivers/common/sfc_efx/base/medford_nic.c
index b111e3eded..9a460b2b9b 100644
--- a/drivers/common/sfc_efx/base/medford_nic.c
+++ b/drivers/common/sfc_efx/base/medford_nic.c
@@ -150,6 +150,8 @@ medford_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index eda6c1c4f9..a773aea38d 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -176,6 +176,15 @@ rhead_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	/*
+	 * FIXME: MCDI table API support depends on an EF100 firmware build
+	 * and an EF100 platform. It should be discovered by using a capability
+	 * flag from MCDI that is not implemented yet.
+	 * Right now we can safely rely on the return code from the libefx
+	 * MCDI Table API.
+	 */
+	encp->enc_table_api_supported = B_TRUE;
+
 	return (0);
 
 fail3:
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 9f14faf271..1f1fb7d2af 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -205,6 +205,8 @@ siena_board_cfg(
 	encp->enc_mae_supported = B_FALSE;
 	encp->enc_mae_admin = B_FALSE;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
 
 	return (0);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
                     ` (30 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

New MCDI Table Access API allows management of
the HW tables' content.
This part of API helps to list all supported tables.
In the near future, only the CT table is planned
to be used, so only one identifier for this table
was added to the efx.
New table IDs will be added as needed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 15 ++++
 drivers/common/sfc_efx/base/efx_table.c | 94 +++++++++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build |  1 +
 drivers/common/sfc_efx/version.map      |  2 +
 4 files changed, 112 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f9b090e35e..ac6b58b2a4 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5084,6 +5084,21 @@ efx_nic_dma_map(
 	__in		size_t len,
 	__out		efsys_dma_addr_t *nic_addrp);
 
+/* Unique IDs for HW tables */
+typedef enum efx_table_id_e {
+	EFX_TABLE_ID_CONNTRACK = 0x10300,
+} efx_table_id_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
new file mode 100644
index 0000000000..7cfdfea36e
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_LIST_IN_LEN,
+	    MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table IDs */
+	EFX_STATIC_ASSERT(EFX_TABLE_ID_CONNTRACK == TABLE_ID_CONNTRACK_TABLE);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((n_table_ids != 0) &&
+	   ((table_ids == NULL) || (n_table_ids_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_LIST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_LIST_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, entry_ofst);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_LIST_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	if (total_n_tablesp != NULL)
+		*total_n_tablesp = MCDI_OUT_DWORD(req, TABLE_LIST_OUT_N_TABLES);
+
+	n_entries = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(req.emr_out_length_used);
+
+	if (table_ids != NULL) {
+		if (n_entries > n_table_ids) {
+			rc = ENOMEM;
+			goto fail5;
+		}
+
+		for (i = 0; i < n_entries; i++) {
+			table_ids[i] = MCDI_OUT_INDEXED_DWORD(req,
+			    TABLE_LIST_OUT_TABLE_ID, i);
+		}
+	}
+
+	if (n_table_ids_writtenp != NULL)
+		*n_table_ids_writtenp = n_entries;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index ff7f33fb44..7fc04aa57b 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -16,6 +16,7 @@ sources = [
         'efx_lic.c',
         'efx_mac.c',
         'efx_mae.c',
+        'efx_table.c',
         'efx_mcdi.c',
         'efx_mon.c',
         'efx_nic.c',
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d9b04a611d..7c92c1ae09 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,8 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_list;
+
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
 	efx_tunnel_config_udp_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 04/34] common/sfc_efx/base: add macro to get indexed QWORD field
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (2 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
                     ` (29 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Extend MCDI macros to manipulate with fields in indexed QWORDs.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
---
 drivers/common/sfc_efx/base/efx_mcdi.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 14a3833567..f13bf43da6 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -504,6 +504,10 @@ efx_mcdi_set_nic_addr_regions(
 	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
 			(_idx)), _field)
 
+#define	MCDI_OUT_INDEXED_QWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_QWORD_FIELD(*(MCDI_OUT2(_emr, efx_qword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, _type, _arr_ofst, _idx,	\
 		_member_ofst)						\
 	((_type *)(MCDI_OUT2(_emr, uint8_t, _arr_ofst) +		\
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (3 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
                     ` (28 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Table's descriptor and fields' descriptors can be taken
by table ID using a new API.
In the near future, only the CT table is planned
to be used, so only fields that are required for these
purposes were added to the efx.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       |  67 +++++++
 drivers/common/sfc_efx/base/efx_table.c | 256 ++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |   3 +
 3 files changed, 326 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ac6b58b2a4..cf157e17d6 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5099,6 +5099,73 @@ efx_table_list(
 	__in					unsigned int n_table_ids,
 	__out_opt				unsigned int *n_table_ids_writtenp);
 
+LIBEFX_API
+extern	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void);
+
+LIBEFX_API
+extern	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id);
+
+/* Unique IDs for table fields */
+typedef enum efx_table_field_id_e {
+	EFX_TABLE_FIELD_ID_UNUSED = 0x0,
+	EFX_TABLE_FIELD_ID_COUNTER_ID = 0xa,
+	EFX_TABLE_FIELD_ID_ETHER_TYPE = 0x1c,
+	EFX_TABLE_FIELD_ID_SRC_IP = 0x1d,
+	EFX_TABLE_FIELD_ID_DST_IP = 0x1e,
+	EFX_TABLE_FIELD_ID_IP_PROTO = 0x20,
+	EFX_TABLE_FIELD_ID_SRC_PORT = 0x21,
+	EFX_TABLE_FIELD_ID_DST_PORT = 0x22,
+	EFX_TABLE_FIELD_ID_NAT_PORT = 0x7a,
+	EFX_TABLE_FIELD_ID_NAT_IP = 0x7b,
+	EFX_TABLE_FIELD_ID_NAT_DIR = 0x7c,
+	EFX_TABLE_FIELD_ID_CT_MARK = 0x7d,
+} efx_table_field_id_t;
+
+/* Table fields mask types */
+typedef enum efx_table_field_mask_type_e {
+	EFX_TABLE_FIELD_MASK_NEVER = 0x0,
+	EFX_TABLE_FIELD_MASK_EXACT = 0x1,
+} efx_table_field_mask_type_t;
+
+typedef struct efx_table_field_desc_s {
+	efx_table_field_id_t		field_id;
+	uint16_t			lbn;
+	uint16_t			width;
+	efx_table_field_mask_type_t	mask_type;
+	uint8_t				scheme;
+} efx_table_field_descriptor_t;
+
+/* Types of HW tables */
+typedef enum efx_table_type_e {
+	/* Exact match to all key fields of table entry. */
+	EFX_TABLE_TYPE_BCAM = 0x2,
+} efx_table_type_t;
+
+typedef struct efx_table_descriptor_s {
+	efx_table_type_t	type;
+	uint16_t		key_width;
+	uint16_t		resp_width;
+	/* Number of key's fields to match data */
+	uint16_t		n_key_fields;
+	/* Number of fields in match response */
+	uint16_t		n_resp_fields;
+} efx_table_descriptor_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(*n_fields_descsp)	efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 7cfdfea36e..115d86502f 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -6,6 +6,11 @@
 #include "efx.h"
 #include "efx_impl.h"
 
+/* List of HW tables that have support in efx */
+static const efx_table_id_t efx_supported_table_ids[] = {
+	EFX_TABLE_ID_CONNTRACK,
+};
+
 	__checkReturn				efx_rc_t
 efx_table_list(
 	__in					efx_nic_t *enp,
@@ -80,6 +85,257 @@ efx_table_list(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void)
+{
+	return EFX_ARRAY_SIZE(efx_supported_table_ids);
+}
+
+	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id)
+{
+	size_t i;
+
+	for (i = 0; i < efx_table_supported_num_get(); i++) {
+		if (efx_supported_table_ids[i] == table_id)
+			return B_TRUE;
+	}
+
+	return B_FALSE;
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_ct_desc_fields_check(
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+	efx_rc_t rc;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		switch (fields_descsp[i].field_id) {
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+		case EFX_TABLE_FIELD_ID_DST_IP:
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
+				rc = EINVAL;
+				goto fail1;
+			}
+			break;
+		/*
+		 * TODO:
+		 * All fields in the CT table have EXACT mask.
+		 * All the response field descriptors must have the EXACT mask.
+		 * In the current implementation, only the Ethertype, source and
+		 * destination IP address, IP protocol, and source and destination IP
+		 * are used for the lookup by the key.
+		 * FW could use the NEVER mask for the fields in the key that are not
+		 * used for the lookup.
+		 * As an alternative, a new mask could be added for these fields,
+		 * like EXACT_NOT_USED.
+		 */
+		default:
+			if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
+			    (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
+				rc = EINVAL;
+				goto fail2;
+			}
+			break;
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_desc_fields_check(
+	__in				efx_table_id_t table_id,
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	efx_rc_t rc;
+
+	switch (table_id) {
+	case EFX_TABLE_ID_CONNTRACK:
+		rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
+		if (rc != 0)
+			goto fail1;
+		break;
+	default:
+		break;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static					void
+efx_table_desc_fields_get(
+	__in				const efx_mcdi_req_t *req,
+	__out_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		fields_descsp[i].field_id = (efx_table_field_id_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
+
+		fields_descsp[i].lbn =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
+
+		fields_descsp[i].width =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
+
+		fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
+
+		fields_descsp[i].scheme =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
+	}
+}
+
+	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
+	    MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table types */
+	EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
+
+	/* Ensure EFX and MCDI use same values for table fields */
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (!efx_table_is_supported(table_id)) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((n_field_descs != 0) &&
+	    ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	if (table_descp != NULL) {
+		table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_TYPE);
+		table_descp->key_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
+		table_descp->resp_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
+		table_descp->n_key_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
+		table_descp->n_resp_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
+	}
+
+	n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
+
+	if (fields_descs != NULL) {
+		if (n_entries > n_field_descs) {
+			rc = ENOMEM;
+			goto fail6;
+		}
+
+		efx_table_desc_fields_get(&req, fields_descs, n_entries);
+		rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
+		if (rc != 0)
+			goto fail7;
+	}
+
+	if (n_field_descs_writtenp != NULL)
+		*n_field_descs_writtenp = n_entries;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 7c92c1ae09..189dd4fdaf 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,7 +233,10 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_describe;
+	efx_table_is_supported;
 	efx_table_list;
+	efx_table_supported_num_get;
 
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 06/34] common/sfc_efx/base: add API to insert data to HW table
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (4 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
                     ` (27 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to insert data to any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 16 +++++
 drivers/common/sfc_efx/base/efx_table.c | 79 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 96 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cf157e17d6..1683d8ce7b 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5166,6 +5166,22 @@ efx_table_describe(
 	__in					unsigned int n_field_descs,
 	__out_opt				unsigned int *n_field_descs_writtenp);
 
+/* Maximum possible size of data for manipulation of the tables */
+#define EFX_TABLE_ENTRY_LENGTH_MAX	1008
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 115d86502f..63fc319666 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -338,6 +338,85 @@ efx_table_describe(
 	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_INSERT_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_INSERT_IN_LENMAX  * sizeof(uint32_t)) ==
+	    EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_INSERT_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_INSERT_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_INSERT_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_PRIORITY, priority);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_WIDTH, mask_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_RESP_WIDTH, resp_width);
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_INSERT_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 189dd4fdaf..f6a2003c3e 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -234,6 +234,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
 	efx_table_supported_num_get;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 07/34] common/sfc_efx/base: add API to delete entry from HW table
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (5 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
                     ` (26 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to delete entry from any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 11 ++++
 drivers/common/sfc_efx/base/efx_table.c | 77 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 89 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 1683d8ce7b..cdf8a99abf 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5182,6 +5182,17 @@ efx_table_entry_insert(
 	__in_bcount(data_size)		uint8_t *entry_datap,
 	__in				unsigned int data_size);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 63fc319666..10a1c2ddcd 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -419,6 +419,83 @@ efx_table_entry_insert(
 
 fail4:
 	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_DELETE_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_DELETE_IN_LENMAX  * sizeof(uint32_t)) ==
+		EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DELETE_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DELETE_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DELETE_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_WIDTH, mask_width);
+
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_DELETE_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f6a2003c3e..b596369c48 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -234,6 +234,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_delete;
 	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 08/34] net/sfc: add MCDI wrappers for BCAM tables
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (6 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
                     ` (25 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

A "table" is structure used for lookups, consisting of a set of
entries which can be matched against an N-bit "request", to
return either a "hit" with an M-bit "response", or a "miss" if
there is no match. There are a number of HW tables of various
types that could be used in MAE.

In some types of table the entry may also be associated with an
N-bit "mask", allowing some bits of the request to be treated as
don't-care, and an integer "priority" to determine which entry is
used if more than one matches.

BCAM tables don't support "mask" and "priority", so the
corresponding fields must be zeroed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_tbls.h | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.h

diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
new file mode 100644
index 0000000000..2a5c87b82c
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBLS_H
+#define _SFC_TBLS_H
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Table types:
+ *   CAM - Content addressable memory
+ *  BCAM - Binary CAM
+ *  TCAM - Ternary CAM
+ * STCAM - Semi-ternary CAM
+ *
+ * Short description:
+ * TCAM:  Each entry has a key, mask, response and priority. An entry matches
+ *        when (key & mask) == (request & mask). In the case of multiple
+ *        matches, the entry with the highest priority wins; Each entry may
+ *        have its own mask, but TCAM table definitions may place constraints
+ *        on the possible masks allowed for each of the individual fields.
+ * STCAM: A limited form of TCAM in which only a limited number of masks and
+ *        associated priorities), up to some maximum fixed by the definition
+ *        of the table, may be in use at any one time.
+ * BCAM:  Each entry has only a key and response, with the whole request
+ *        matched against the key (like a typical hash table or "map").
+ * Direct (sometimes "DCAM", although it's not really content-addressable):
+ *        Essentially just an array, where the key bits are used simply as an
+ *        index.
+ */
+
+/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
+#define SFC_TBLS_BCAM_PRIORITY		0
+
+/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
+#define SFC_TBLS_BCAM_MASK_ID		0
+
+/* Mask is used only for STCAM */
+#define SFC_TBLS_BCAM_MASK_WIDTH	0
+
+static inline int
+sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
+				      SFC_TBLS_BCAM_MASK_ID, key_width,
+				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
+				      data, data_size);
+}
+
+static inline int
+sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
+				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
+				      data, data_size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_TBLS_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 09/34] net/sfc: add functions to manipulate MCDI table fields
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (7 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 10/34] net/sfc: attach to HW table API Ivan Malov
                     ` (24 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Implemented functions that help to fill user data for
manipulation with HW tables in the required format.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |   1 +
 drivers/net/sfc/sfc_tbls.c  | 140 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbls.h  | 135 ++++++++++++++++++++++++++++++++++
 3 files changed, 276 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.c

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c2d8430810..39c7f24764 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -87,6 +87,7 @@ sources = files(
         'sfc_tso.c',
         'sfc_filter.c',
         'sfc_switch.c',
+        'sfc_tbls.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
new file mode 100644
index 0000000000..db54fc0d40
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc_tbls.h"
+#include "sfc_debug.h"
+
+#include <rte_ip.h>
+
+/* Number of bits in uint32_t type */
+#define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
+
+static uint32_t
+sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t mask;
+
+	if (width == SFC_TBLS_U32_BITS)
+		return value;
+
+	mask = RTE_LEN2MASK(width, uint32_t);
+	value &= mask;
+
+	if (lbn != 0) {
+		mask <<= lbn;
+		value <<= lbn;
+	}
+
+	return (in & (~mask)) | value;
+}
+
+void
+sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	if (lbn + width <= SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, lbn, width, value);
+	} else {
+		*data = sfc_tbls_field_update(*data, lbn,
+					      SFC_TBLS_U32_BITS - lbn, value);
+		value >>= SFC_TBLS_U32_BITS - lbn;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+		*data = sfc_tbls_field_update(*data, 0,
+					      width + lbn - SFC_TBLS_U32_BITS,
+					      value);
+	}
+}
+
+void
+sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, uint16_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      uint16_t width, uint8_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      __rte_unused uint16_t width, const uint32_t *ip)
+{
+	unsigned int i;
+	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
+
+	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
+
+	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
+		sfc_tbls_field_set_u32(data, data_size, lbn,
+				       SFC_TBLS_U32_BITS, ip[i]);
+		lbn += SFC_TBLS_U32_BITS;
+	}
+}
+
+void
+sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint64_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
+	value >>= SFC_TBLS_U32_BITS - lbn;
+	width -= SFC_TBLS_U32_BITS - lbn;
+
+	data_offset++;
+	SFC_ASSERT(data_offset < data_size);
+
+	data++;
+
+	if (width > SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
+		value >>= SFC_TBLS_U32_BITS;
+		width -= SFC_TBLS_U32_BITS;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+	}
+
+	*data = sfc_tbls_field_update(*data, 0, width, value);
+}
+
+void
+sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, bool value)
+{
+	SFC_ASSERT(width == 1);
+
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
+}
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 2a5c87b82c..7b6bb5b341 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -63,6 +63,141 @@ sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key
 				      data, data_size);
 }
 
+/**
+ * All manipulations with HW tables entries require forming
+ * a key and response.
+ * The key and response fields follow, consecutively, each
+ * packed as follows:
+ *  - the key/response is logically treated as a single wide N-bit value;
+ *  - fields have been placed in these logical values per the "lbn" and "width"
+ *    information from the table field descriptors;
+ *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
+ *  - the values are put into the table op request with bits[31:0] of the wide
+ *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
+ *
+ * Below is an API that helps to form  MCDI insertion/deletion request.
+ * Workflow:
+ * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
+ * 2) Read a descriptor of the table that you want to use.
+ * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
+ *    Each field of the key has LBN and width. This information can be
+ *    found in a field's descriptor.
+ * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
+ *    must start. It's required as the key and response need to be
+ *    zero-padded at the MSB end to multiples of 32 bits.
+ * 5) Fill the response the same way.
+ * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
+ *    It will help you to get the real size of the data request.
+ */
+
+/**
+ * Get a pointer to the beginning of the next 32-bit wide fields
+ * that go after a given width.
+ * It should be used to get a pointer to the response's start and the end
+ * of the data for an MCDI request.
+ *
+ * @param data		Pointer to the data to make an offset from
+ * @param width		Width of fields to offset
+ *
+ * @note @p width is expected to be a key's or response's size.
+ *
+ * @return Pointer to the beginning of the next field.
+ */
+static inline uint32_t *
+sfc_tbls_next_req_fields(uint32_t *data, uint16_t width) {
+	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
+}
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint32_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint32_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint16_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint16_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint8_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, uint8_t value);
+
+/**
+ * Insert IP address into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param ip		IP address to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, const uint32_t *ip);
+
+/**
+ * Insert value into a field in the data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint64_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint64_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		Bit value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, bool value);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 10/34] net/sfc: attach to HW table API
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (8 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
                     ` (23 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The patch adds APIs to initialise, manipulate and finalise
HW tables API-specific context in NIC control structure.
The context itself will be used to store HW tables-related info,
like table descriptors and field descriptors.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build          |   4 +-
 drivers/net/sfc/sfc.c                |  18 +-
 drivers/net/sfc/sfc.h                |   2 +
 drivers/net/sfc/sfc_tbl_meta.c       |  71 ++++++++
 drivers/net/sfc/sfc_tbl_meta.h       |  37 ++++
 drivers/net/sfc/sfc_tbl_meta_cache.c | 253 +++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbl_meta_cache.h |  25 +++
 drivers/net/sfc/sfc_tbls.c           |  60 +++++++
 drivers/net/sfc/sfc_tbls.h           |  81 +++++++++
 9 files changed, 549 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 39c7f24764..c9d4264674 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -71,7 +71,7 @@ if not cc.links(atomic_check_code)
     ext_deps += libatomic_dep
 endif
 
-deps += ['common_sfc_efx', 'bus_pci']
+deps += ['common_sfc_efx', 'bus_pci', 'hash']
 sources = files(
         'sfc_ethdev.c',
         'sfc_kvargs.c',
@@ -88,6 +88,8 @@ sources = files(
         'sfc_filter.c',
         'sfc_switch.c',
         'sfc_tbls.c',
+        'sfc_tbl_meta.c',
+        'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 22753e3417..a56521696a 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -491,6 +491,10 @@ sfc_try_start(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_ev_start;
 
+	rc = sfc_tbls_start(sa);
+	if (rc != 0)
+		goto fail_tbls_start;
+
 	rc = sfc_port_start(sa);
 	if (rc != 0)
 		goto fail_port_start;
@@ -526,9 +530,12 @@ sfc_try_start(struct sfc_adapter *sa)
 fail_rx_start:
 	sfc_port_stop(sa);
 
-fail_port_start:
+fail_tbls_start:
 	sfc_ev_stop(sa);
 
+fail_port_start:
+	sfc_tbls_stop(sa);
+
 fail_ev_start:
 	sfc_intr_stop(sa);
 
@@ -626,6 +633,7 @@ sfc_stop(struct sfc_adapter *sa)
 	sfc_tx_stop(sa);
 	sfc_rx_stop(sa);
 	sfc_port_stop(sa);
+	sfc_tbls_stop(sa);
 	sfc_ev_stop(sa);
 	sfc_intr_stop(sa);
 	efx_nic_fini(sa->nic);
@@ -983,6 +991,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_attach;
 
+	rc = sfc_tbls_attach(sa);
+	if (rc != 0)
+		goto fail_tables_attach;
+
 	rc = sfc_mae_switchdev_init(sa);
 	if (rc != 0)
 		goto fail_mae_switchdev_init;
@@ -1025,6 +1037,9 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_mae_switchdev_fini(sa);
 
 fail_mae_switchdev_init:
+	sfc_tbls_detach(sa);
+
+fail_tables_attach:
 	sfc_mae_detach(sa);
 
 fail_mae_attach:
@@ -1088,6 +1103,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
+	sfc_tbls_detach(sa);
 	sfc_mae_detach(sa);
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 730d054aea..6b301aad60 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -31,6 +31,7 @@
 #include "sfc_flow_tunnel.h"
 #include "sfc_sriov.h"
 #include "sfc_mae.h"
+#include "sfc_tbls.h"
 #include "sfc_dp.h"
 #include "sfc_sw_stats.h"
 #include "sfc_repr_proxy.h"
@@ -244,6 +245,7 @@ struct sfc_adapter {
 	struct sfc_ft_ctx		ft_ctx_pool[SFC_FT_MAX_NTUNNELS];
 	struct sfc_filter		filter;
 	struct sfc_mae			mae;
+	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
 	struct sfc_flow_list		flow_list;
diff --git a/drivers/net/sfc/sfc_tbl_meta.c b/drivers/net/sfc/sfc_tbl_meta.c
new file mode 100644
index 0000000000..997082fd74
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_tbl_meta.h"
+#include "sfc_tbl_meta_cache.h"
+
+const struct sfc_tbl_meta *
+sfc_tbl_meta_lookup(struct sfc_adapter *sa, efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta;
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return NULL;
+
+	rc = rte_hash_lookup_data(tables->meta.cache, (const void *)&table_id,
+				  (void **)&meta);
+	if (rc < 0)
+		return NULL;
+
+	SFC_ASSERT(meta != NULL);
+	SFC_ASSERT(meta->table_id == table_id);
+
+	return meta;
+}
+
+int
+sfc_tbl_meta_init(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return 0;
+
+	rc = sfc_tbl_meta_cache_ctor(&meta->cache);
+	if (rc != 0)
+		return rc;
+
+	rc = sfc_tbl_meta_cache_update(meta->cache, sa->nic);
+	if (rc != 0) {
+		sfc_tbl_meta_cache_dtor(&meta->cache);
+		return rc;
+	}
+
+	return 0;
+}
+
+void
+sfc_tbl_meta_fini(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+
+	if (meta->cache == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(tables->status == SFC_TBLS_STATUS_SUPPORTED);
+
+	sfc_tbl_meta_cache_dtor(&meta->cache);
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta.h b/drivers/net/sfc/sfc_tbl_meta.h
new file mode 100644
index 0000000000..7d39957514
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_H
+#define _SFC_TBL_META_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Metadata about table layout */
+struct sfc_tbl_meta {
+	efx_table_id_t			table_id;
+	efx_table_descriptor_t		descriptor;
+	efx_table_field_descriptor_t	*keys;
+	efx_table_field_descriptor_t	*responses;
+};
+
+struct sfc_tbl_meta_cache {
+	struct rte_hash	*cache;
+};
+
+struct sfc_adapter;
+
+const struct sfc_tbl_meta *sfc_tbl_meta_lookup(struct sfc_adapter *sa,
+					       efx_table_id_t table_id);
+
+int sfc_tbl_meta_init(struct sfc_adapter *sa);
+void sfc_tbl_meta_fini(struct sfc_adapter *sa);
+
+#endif /* _SFC_TBL_META_H */
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.c b/drivers/net/sfc/sfc_tbl_meta_cache.c
new file mode 100644
index 0000000000..65ba0b001e
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.c
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include <rte_malloc.h>
+#include <rte_jhash.h>
+
+#include "sfc_tbl_meta_cache.h"
+#include "sfc_debug.h"
+
+/* The minimal size of the table meta cache */
+#define SFC_TBL_META_CACHE_SIZE_MIN	8
+
+int
+sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
+{
+	size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
+				    efx_table_supported_num_get());
+	struct rte_hash *cache = NULL;
+	const struct rte_hash_parameters hash_params = {
+		.name       = "meta_hash_table",
+		.hash_func  = rte_jhash,
+		.entries    = cache_size,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(efx_table_id_t),
+	};
+
+	cache = rte_hash_create(&hash_params);
+	if (!cache)
+		return -ENOMEM;
+
+	*ref_cache = cache;
+
+	return 0;
+}
+
+static void
+sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
+{
+	SFC_ASSERT(meta != NULL);
+
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+	rte_free(meta);
+}
+
+void
+sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
+{
+	struct rte_hash *cache = *ref_cache;
+	const void *next_key;
+	uint32_t iter = 0;
+	void *next_meta;
+
+	if (cache == NULL)
+		return;
+
+	while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
+		sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
+
+	rte_hash_free(cache);
+
+	*ref_cache = NULL;
+}
+
+/**
+ * Table descriptor contains information about the table's
+ * fields that can be associated with both the key and the response.
+ * Save these fields by separating the key from the response in
+ * appropriate places based on their lengths.
+ */
+static int
+sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+			      efx_table_field_descriptor_t *fields,
+			      unsigned int total_n_fields)
+{
+	uint16_t n_key_fields = meta->descriptor.n_key_fields;
+	size_t field_size = sizeof(*fields);
+	unsigned int n_field_descs_written;
+	uint32_t field_offset;
+	int rc;
+
+	for (n_field_descs_written = 0, field_offset = 0;
+	     field_offset < total_n_fields;
+	     field_offset += n_field_descs_written) {
+		rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
+					fields, total_n_fields, &n_field_descs_written);
+		if (rc != 0)
+			return rc;
+
+		if (field_offset + n_field_descs_written > total_n_fields)
+			return -EINVAL;
+
+		if (field_offset < n_key_fields &&
+		    field_offset + n_field_descs_written > n_key_fields) {
+			/*
+			 * Some of the descriptors belong to key,
+			 * the other to response.
+			 */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, (n_key_fields - field_offset) * field_size);
+			rte_memcpy(meta->responses,
+				   RTE_PTR_ADD(fields,
+				   (n_key_fields - field_offset) * field_size),
+				   (field_offset + n_field_descs_written - n_key_fields) *
+				   field_size);
+		} else if (field_offset < n_key_fields) {
+			/* All fields belong to the key */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, n_field_descs_written * field_size);
+		} else {
+			/* All fields belong to the response */
+			rte_memcpy(RTE_PTR_ADD(meta->responses,
+				   (field_offset - n_key_fields) * field_size),
+				   fields, n_field_descs_written * field_size);
+		}
+	}
+
+	return 0;
+}
+
+static int
+sfc_tbl_meta_desc_read(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	efx_table_field_descriptor_t *fields;
+	unsigned int total_n_fields;
+	int rc;
+
+	rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
+
+	fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
+	if (fields == NULL)
+		return -ENOMEM;
+
+	meta->table_id = table_id;
+
+	meta->keys = rte_calloc("efx_table_key_field_descs",
+				meta->descriptor.n_key_fields,
+				sizeof(*meta->keys), 0);
+	if (meta->keys == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_keys;
+	}
+
+	meta->responses = rte_calloc("efx_table_response_field_descs",
+				     meta->descriptor.n_resp_fields,
+				     sizeof(*meta->responses), 0);
+	if (meta->responses == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_responses;
+	}
+
+	rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
+	if (rc != 0)
+		goto fail_copy_fields;
+
+	return 0;
+
+fail_copy_fields:
+	rte_free(meta->responses);
+fail_alloc_responses:
+	rte_free(meta->keys);
+fail_alloc_keys:
+	rte_free(fields);
+
+	return rc;
+}
+
+static int
+sfc_tbl_meta_cache_add(struct rte_hash *cache, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta = NULL;
+	int rc;
+
+	meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
+	if (meta == NULL)
+		return -ENOMEM;
+
+	rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
+	if (rc != 0)
+		goto fail_read_meta;
+
+	rc = rte_hash_add_key_data(cache, &table_id, meta);
+	if (rc != 0)
+		goto fail_add_key;
+
+	return 0;
+
+fail_add_key:
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+fail_read_meta:
+	rte_free(meta);
+
+	return rc;
+}
+
+int
+sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp)
+{
+	efx_table_id_t *table_ids = NULL;
+	unsigned int n_table_ids_written;
+	unsigned int total_n_tables;
+	unsigned int n_table_ids;
+	uint32_t table_index;
+	unsigned int i;
+	int rc = 0;
+
+	rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
+	if (table_ids == NULL)
+		return -ENOMEM;
+
+	n_table_ids = total_n_tables;
+
+	for (table_index = 0, n_table_ids_written = 0;
+	     table_index < total_n_tables;
+	     table_index += n_table_ids_written) {
+		rc = efx_table_list(enp, table_index, NULL,
+				    table_ids, n_table_ids, &n_table_ids_written);
+		if (rc != 0)
+			goto out;
+
+		if (table_index + n_table_ids_written > total_n_tables) {
+			rc = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < n_table_ids_written; i++, table_index++) {
+			if (!efx_table_is_supported(table_ids[i]))
+				continue;
+
+			rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
+			if (rc != 0)
+				goto out;
+		}
+	}
+
+out:
+	rte_free(table_ids);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.h b/drivers/net/sfc/sfc_tbl_meta_cache.h
new file mode 100644
index 0000000000..2deff620a4
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_CACHE_H
+#define _SFC_TBL_META_CACHE_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#include "sfc_tbl_meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache);
+
+void sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache);
+
+int sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp);
+
+#endif /* _SFC_TBLS_DESC_CACHE_H */
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
index db54fc0d40..d41b961454 100644
--- a/drivers/net/sfc/sfc_tbls.c
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2023 Advanced Micro Devices, Inc.
  */
 
+#include "sfc.h"
 #include "sfc_tbls.h"
 #include "sfc_debug.h"
 
@@ -11,6 +12,65 @@
 /* Number of bits in uint32_t type */
 #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
 
+int
+sfc_tbls_attach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	const struct sfc_mae *mae = &sa->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	if (mae->status != SFC_MAE_STATUS_ADMIN ||
+	    !encp->enc_table_api_supported) {
+		tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	tables->status = SFC_TBLS_STATUS_SUPPORTED;
+
+	rc = sfc_tbl_meta_init(sa);
+	if (rc != 0)
+		return rc;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_tbls_detach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+
+	sfc_log_init(sa, "entry");
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		goto done;
+
+	sfc_tbl_meta_fini(sa);
+
+done:
+	sfc_log_init(sa, "done");
+
+	tables->status = SFC_TBLS_STATUS_UNKNOWN;
+}
+
+int
+sfc_tbls_start(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
+		rc = sfc_tbls_attach(sa);
+		return rc;
+	}
+
+	return 0;
+}
+
 static uint32_t
 sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
 {
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 7b6bb5b341..be0abbf161 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -8,6 +8,8 @@
 
 #include "efx.h"
 
+#include "sfc_tbl_meta.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -44,6 +46,85 @@ extern "C" {
 /* Mask is used only for STCAM */
 #define SFC_TBLS_BCAM_MASK_WIDTH	0
 
+/** Options for HW tables support status */
+enum sfc_tbls_status {
+	SFC_TBLS_STATUS_UNKNOWN = 0,
+	SFC_TBLS_STATUS_UNSUPPORTED,
+	SFC_TBLS_STATUS_SUPPORTED,
+};
+
+/**
+ * Entry point to access HW tables
+ *
+ * SFC driver can access hardware (HW) tables.
+ * Interaction with HW tables is done through the MCDI table access API
+ * that is implemented in EFX.
+ *
+ * In order to manipulate data on HW tables it's necessary to
+ * - discover the list of supported tables;
+ * - read a table descriptor to get details of the structure
+ *   of the table;
+ * - get named fields of the table;
+ * - insert/delete/update table entries based on given fields
+ *   and information about the table
+ *
+ * All table layout data should be saved in a cache.
+ * The cache allows to avoid getting the table descriptor each time when you want
+ * to manipulate table entries. It just contains the table
+ * descriptors and all associated data. The cache is based on the RTE hash map and
+ * it uses a table ID as a key.
+ * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
+ * to get all information about the tables without worrying about the cache.
+ *
+ * +------------------------+
+ * | Cache is uninitialized |<----------------------------------+
+ * +------------------------+					|
+ *	|							|
+ *	| sfc_attach()						|
+ *	| sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
+ *	V					^
+ * +------------------------+			|
+ * |  Cache is initialized  |			+-------+
+ * +------------------------+				|
+ *	| sfc_start()					|
+ *	| sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | and valid              |				|
+ * +------------------------+				|
+ *	|						|
+ *	| sfc_restart()					|
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | but can be invalid     |				|
+ * +------------------------+---------------------------+
+ */
+struct sfc_tbls {
+	struct sfc_tbl_meta_cache	meta;
+	enum sfc_tbls_status		status;
+};
+
+struct sfc_adapter;
+
+static inline bool
+sfc_tbls_id_is_supported(struct sfc_adapter *sa,
+			 efx_table_id_t table_id)
+{
+	return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
+}
+
+int sfc_tbls_attach(struct sfc_adapter *sa);
+void sfc_tbls_detach(struct sfc_adapter *sa);
+int sfc_tbls_start(struct sfc_adapter *sa);
+
+static inline void
+sfc_tbls_stop(struct sfc_adapter *sa)
+{
+	sfc_tbls_detach(sa);
+}
+
 static inline int
 sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
 			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 11/34] net/sfc: add API to manage HW Conntrack table
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (9 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 10/34] net/sfc: attach to HW table API Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
                     ` (22 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The new API allows to manipulate entries in
the HW Conntrack table.
It uses a new Table Access API as a backend.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_mae_ct.c | 201 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae_ct.h |  68 ++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c9d4264674..5adde68517 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -92,6 +92,7 @@ sources = files(
         'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
+        'sfc_mae_ct.c',
         'sfc_flow.c',
         'sfc_flow_rss.c',
         'sfc_flow_tunnel.c',
diff --git a/drivers/net/sfc/sfc_mae_ct.c b/drivers/net/sfc/sfc_mae_ct.c
new file mode 100644
index 0000000000..fd6819c8a5
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_mae_ct.h"
+
+/* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
+static void
+sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
+			   const efx_table_field_descriptor_t *fields,
+			   unsigned int n_fields, uint32_t *mcdi_key,
+			   unsigned int key_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+			sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
+					      desc->width, key->ip_proto);
+			break;
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->ether_type_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->src_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->dst_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->src_addr_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->dst_addr_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+/* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
+static void
+sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t *response,
+				     const efx_table_field_descriptor_t *fields,
+				     unsigned int n_fields, uint32_t *mcdi_resp,
+				     unsigned int resp_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		/* Fields of responses are always reported with the EXACT type. */
+		SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_CT_MARK:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->ct_mark);
+			break;
+		case EFX_TABLE_FIELD_ID_COUNTER_ID:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->counter_id);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_DIR:
+			sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
+					      desc->width, response->nat.dir_is_dst);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_IP:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.ip_le);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_PORT:
+			sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.port_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+int
+sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key,
+			 const sfc_mae_conntrack_response_t *response)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int response_size;
+	uint32_t *response_data;
+	unsigned int data_size;
+	unsigned int key_size;
+	uint32_t *start_data;
+	uint16_t resp_width;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+	resp_width = meta->descriptor.resp_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	response_data = sfc_tbls_next_req_fields(key_data, key_width);
+	end_data = sfc_tbls_next_req_fields(response_data, resp_width);
+
+	key_size = RTE_PTR_DIFF(response_data, key_data);
+	response_size = RTE_PTR_DIFF(end_data, response_data);
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields, key_data,
+				   key_size);
+	sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
+					     meta->descriptor.n_resp_fields,
+					     response_data, response_size);
+
+	rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, resp_width, data,
+					data_size);
+
+	return rc;
+}
+
+int
+sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int data_size;
+	uint32_t *start_data;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	end_data = sfc_tbls_next_req_fields(key_data, key_width);
+
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields,
+				   key_data, data_size);
+
+	rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, data, data_size);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae_ct.h b/drivers/net/sfc/sfc_mae_ct.h
new file mode 100644
index 0000000000..b5a3181cd3
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_MAE_CONNTRACK_H
+#define _SFC_MAE_CONNTRACK_H
+
+#include <stdbool.h>
+
+#include <rte_ip.h>
+
+#include "efx.h"
+
+#include "sfc_tbls.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sfc_mae_conntrack_key_s {
+	uint8_t		ip_proto;
+	uint16_t	ether_type_le;
+
+	uint16_t	src_port_le;
+	uint16_t	dst_port_le;
+
+	uint8_t		src_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr)];
+	uint8_t		dst_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, dst_addr)];
+} sfc_mae_conntrack_key_t;
+
+typedef struct sfc_mae_conntrack_nat_s {
+	uint32_t	ip_le;
+	uint16_t	port_le;
+	bool		dir_is_dst;
+} sfc_mae_conntrack_nat_t;
+
+typedef struct sfc_mae_conntrack_response_s {
+	uint32_t		ct_mark;
+	sfc_mae_conntrack_nat_t	nat;
+	uint32_t		counter_id;
+} sfc_mae_conntrack_response_t;
+
+struct sfc_adapter;
+
+static inline bool
+sfc_mae_conntrack_is_supported(struct sfc_adapter *sa)
+{
+	return sfc_tbls_id_is_supported(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+static inline const struct sfc_tbl_meta *
+sfc_mae_conntrack_meta_lookup(struct sfc_adapter *sa)
+{
+	return sfc_tbl_meta_lookup(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+int sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key,
+			     const sfc_mae_conntrack_response_t *response);
+
+int sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_CONNTRACK_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 12/34] net/sfc: make entry pointer optional in MAE resource helpers
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (10 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
                     ` (21 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Keep NULL object check in one place rather than repeat it in
all of the callers. That should make the code easier on eyes.
Future code for additional object types will follow this way.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 78 ++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 60b9fdc290..7a3f9761c1 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -402,6 +402,9 @@ sfc_mae_outer_rule_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(rule->refcnt != 0);
 
@@ -429,11 +432,16 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_outer_rule *rule,
 			  efx_mae_match_spec_t *match_spec_action)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(rule->match_spec != NULL);
@@ -480,11 +488,16 @@ static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -1057,6 +1070,9 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(action_set->refcnt != 0);
 
@@ -1092,15 +1108,24 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
-	struct sfc_mae_mac_addr *dst_mac_addr = action_set->dst_mac_addr;
-	struct sfc_mae_mac_addr *src_mac_addr = action_set->src_mac_addr;
-	struct sfc_mae_counter_id *counters = action_set->counters;
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae_mac_addr *dst_mac_addr;
+	struct sfc_mae_mac_addr *src_mac_addr;
+	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	encap_header = action_set->encap_header;
+	dst_mac_addr = action_set->dst_mac_addr;
+	src_mac_addr = action_set->src_mac_addr;
+	counters = action_set->counters;
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
@@ -1167,11 +1192,16 @@ static void
 sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
@@ -1228,11 +1258,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 
-	if (spec_mae->outer_rule != NULL)
-		sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-
-	if (spec_mae->action_set != NULL)
-		sfc_mae_action_set_del(sa, spec_mae->action_set);
+	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
+	sfc_mae_action_set_del(sa, spec_mae->action_set);
 
 	if (spec_mae->match_spec != NULL)
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
@@ -2577,9 +2604,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
 						  &invalid_rule_id);
 	if (rc != 0) {
-		if (*rulep != NULL)
-			sfc_mae_outer_rule_del(sa, *rulep);
-
+		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
 
 		return rte_flow_error_set(error, rc,
@@ -3981,10 +4006,15 @@ static int
 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 				struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
 	struct sfc_mae_outer_rule *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return 0;
+
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
 		/* An active rule is reused. It's class is wittingly valid. */
 		return 0;
@@ -4071,11 +4101,9 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (sa->state != SFC_ETHDEV_STARTED)
 		return EAGAIN;
 
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
-		if (rc != 0)
-			return rc;
-	}
+	rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
+	if (rc != 0)
+		return rc;
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
@@ -4141,8 +4169,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4177,8 +4204,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 13/34] net/sfc: turn flow create/destroy methods into lock wrappers
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (11 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
                     ` (20 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is useful to facilitate driver-internal flow rework.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 42 ++++++++++++++++++++++++++++++--------
 drivers/net/sfc/sfc_flow.h |  9 ++++++++
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index fe1f5ba55f..432295ea62 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2610,16 +2610,32 @@ sfc_flow_create(struct rte_eth_dev *dev,
 		struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow *flow;
+
+	sfc_adapter_lock(sa);
+	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	sfc_adapter_unlock(sa);
+
+	return flow;
+}
+
+struct rte_flow *
+sfc_flow_create_locked(struct sfc_adapter *sa,
+		       const struct rte_flow_attr *attr,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow_error *error)
+{
 	struct rte_flow *flow = NULL;
 	int rc;
 
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
 	flow = sfc_flow_zmalloc(error);
 	if (flow == NULL)
 		goto fail_no_mem;
 
-	sfc_adapter_lock(sa);
-
-	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
@@ -2631,8 +2647,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 			goto fail_flow_insert;
 	}
 
-	sfc_adapter_unlock(sa);
-
 	return flow;
 
 fail_flow_insert:
@@ -2640,7 +2654,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 
 fail_bad_value:
 	sfc_flow_free(sa, flow);
-	sfc_adapter_unlock(sa);
 
 fail_no_mem:
 	return NULL;
@@ -2652,10 +2665,23 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 		 struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	int rc;
+
+	sfc_adapter_lock(sa);
+	rc = sfc_flow_destroy_locked(sa, flow, error);
+	sfc_adapter_unlock(sa);
+
+	return rc;
+}
+
+int
+sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			struct rte_flow_error *error)
+{
 	struct rte_flow *flow_ptr;
 	int rc = EINVAL;
 
-	sfc_adapter_lock(sa);
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
 		if (flow_ptr == flow)
@@ -2675,8 +2701,6 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 	sfc_flow_free(sa, flow);
 
 fail_bad_value:
-	sfc_adapter_unlock(sa);
-
 	return -rc;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 12875344b5..a3ca09f225 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -195,6 +195,15 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+					const struct rte_flow_attr *attr,
+					const struct rte_flow_item pattern[],
+					const struct rte_flow_action actions[],
+					struct rte_flow_error *error);
+
+int sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			    struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 14/34] net/sfc: let driver-internal flows use VF representor action
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (12 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
                     ` (19 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

In the case of VF <--> VF representor pairs, these flows can
only collect VF traffic, so let them use generic flow action
PORT_REPRESENTOR, as part of re-using generic flow mechanism.

Currently, it does not allow to access VF representors since
they have no unique HW logical ports (m-ports). They all sit
on the same (representor proxy) m-port, while demultiplexing
of traffic uses ingress (VF) m-port value in packet metadata.
Traffic from arbitrary sources cannot be identified this way.
But, for VF traffic, it should be right to make an exception.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c            | 25 +++++++++++++++++++------
 drivers/net/sfc/sfc_repr.c           | 20 ++++++++++++++++----
 drivers/net/sfc/sfc_repr_proxy.c     | 15 +++++++++++++++
 drivers/net/sfc/sfc_repr_proxy_api.h |  3 +++
 drivers/net/sfc/sfc_switch.c         |  7 ++-----
 drivers/net/sfc/sfc_switch.h         | 10 ++++++++++
 6 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7a3f9761c1..c0b97b1fe1 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1527,6 +1527,7 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 	const struct rte_flow_item_port_id *spec = NULL;
 	const struct rte_flow_item_port_id *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1558,8 +1559,10 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 					  "The port ID is too large");
 	}
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
-					     spec->id, &mport_sel);
+					     spec->id, type_mask, &mport_sel);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1592,6 +1595,7 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 	const struct rte_flow_item_ethdev *spec = NULL;
 	const struct rte_flow_item_ethdev *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1619,9 +1623,11 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 
 	switch (item->type) {
 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
+		type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_switch_get_ethdev_mport(
 				ctx_mae->sa->mae.switch_domain_id,
-				spec->port_id, &mport_sel);
+				spec->port_id, type_mask, &mport_sel);
 		if (rc != 0) {
 			return rte_flow_error_set(error, rc,
 					RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -3531,6 +3537,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 {
 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
+	unsigned int type_mask;
 	efx_mport_sel_t mport;
 	uint16_t port_id;
 	int rc;
@@ -3540,8 +3547,10 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 
 	port_id = (conf->original != 0) ? sas->port_id : conf->id;
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     port_id, &mport);
+					     port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			port_id, strerror(rc));
@@ -3560,14 +3569,14 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
 		const struct rte_flow_action_ethdev *conf,
-		efx_mae_actions_t *spec)
+		unsigned int type_mask, efx_mae_actions_t *spec)
 {
 	struct sfc_mae *mae = &sa->mae;
 	efx_mport_sel_t mport;
 	int rc;
 
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     conf->port_id, &mport);
+					     conf->port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			conf->port_id, strerror(rc));
@@ -3643,6 +3652,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
+	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
@@ -3759,8 +3769,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
 				       bundle->actions_mask);
+
+		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
-				action->conf, spec);
+				action->conf, switch_port_type_mask, spec);
 		break;
 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index d4134ec91b..6c7727d569 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -933,15 +933,26 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
 	struct sfc_mae_switch_port_request switch_port_request;
 	efx_mport_sel_t ethdev_mport_sel;
+	efx_mport_id_t proxy_mport_id;
 	struct sfc_repr *sr;
 	int ret;
 
 	/*
-	 * Currently there is no mport we can use for representor's
-	 * ethdev. Use an invalid one for now. This way representors
-	 * can be instantiated.
+	 * For each representor, a driver-internal flow has to be installed
+	 * in order to direct traffic coming from the represented entity to
+	 * the "representor proxy". Such internal flows need to find ethdev
+	 * mport by ethdev ID of the representors in question to specify in
+	 * delivery action. So set the representor ethdev's mport to that
+	 * of the "representor proxy" in below switch port request.
 	 */
-	efx_mae_mport_invalid(&ethdev_mport_sel);
+	sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
+
+	ret = efx_mae_mport_by_id(&proxy_mport_id, &ethdev_mport_sel);
+	if (ret != 0) {
+		SFC_GENERIC_LOG(ERR,
+			"%s() failed to get repr proxy mport by ID", __func__);
+		goto fail_get_selector;
+	}
 
 	memset(&switch_port_request, 0, sizeof(switch_port_request));
 	switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
@@ -1033,6 +1044,7 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 
 fail_create_port:
 fail_mae_assign_switch_port:
+fail_get_selector:
 	SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
 	return ret;
 }
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 4ba7683370..74c3494c35 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -1708,3 +1708,18 @@ sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id, uint16_t repr_id,
 
 	return rc;
 }
+
+void
+sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id, efx_mport_id_t *mport_alias)
+{
+	const struct sfc_repr_proxy *rp;
+	struct sfc_adapter *sa;
+
+	sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
+	sfc_adapter_lock(sa);
+	rp = sfc_repr_proxy_by_adapter(sa);
+
+	memcpy(mport_alias, &rp->mport_alias, sizeof(*mport_alias));
+
+	sfc_adapter_unlock(sa);
+}
diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h
index 1d38ab2451..07d79a50cb 100644
--- a/drivers/net/sfc/sfc_repr_proxy_api.h
+++ b/drivers/net/sfc/sfc_repr_proxy_api.h
@@ -46,6 +46,9 @@ int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id);
 int sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id,
 		uint16_t repr_id, const struct rte_ether_addr *mac_addr);
 
+void sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id,
+				    efx_mport_id_t *mport_alias);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 8f1ee97fa8..f80de4e889 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -551,6 +551,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
 int
 sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				uint16_t ethdev_port_id,
+				unsigned int allowed_mae_switch_port_types,
 				efx_mport_sel_t *mport_sel)
 {
 	struct sfc_mae_switch_port *port;
@@ -562,11 +563,7 @@ sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 	if (rc != 0)
 		goto unlock;
 
-	if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) {
-		/*
-		 * The ethdev is a "VF representor". It does not own
-		 * a dedicated m-port suitable for use in flow rules.
-		 */
+	if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
 		rc = ENOTSUP;
 		goto unlock;
 	}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 62aea9b785..6a85ce4dcf 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -102,8 +102,18 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
 			      uint16_t switch_port_id);
 
+/*
+ * For user flows, allowed_mae_switch_port_types can only contain bit
+ * SFC_MAE_SWITCH_PORT_INDEPENDENT, meaning that only those ethdevs
+ * that have their own MAE m-ports can be accessed by a port-based
+ * action. For driver-internal flows, this mask can also contain
+ * bit SFC_MAE_SWITCH_PORT_REPRESENTOR to allow VF traffic to be
+ * sent to the common MAE m-port of all such REPRESENTOR ports
+ * via a port-based action, for default switch interconnection.
+ */
 int sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				    uint16_t ethdev_port_id,
+				    unsigned int allowed_mae_switch_port_types,
 				    efx_mport_sel_t *mport_sel);
 
 int sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 15/34] net/sfc: extend generic flow API to allow for internal flows
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (13 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
                     ` (18 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

At the moment, driver-internal flow rules are provisioned by
functions that are separate from the generic flow management
framework. In order to use the latter for such rules, extend
it accordingly. This will be actually used in the next patch.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc.c      |  9 ++++-----
 drivers/net/sfc/sfc_flow.c | 37 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_flow.h |  5 ++++-
 drivers/net/sfc/sfc_mae.c  | 31 +++++++++++++++++++++++++++----
 drivers/net/sfc/sfc_mae.h  |  5 +++--
 5 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index a56521696a..2cfff20f47 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -975,6 +975,8 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_rss_attach;
 
+	sfc_flow_init(sa);
+
 	rc = sfc_flow_rss_attach(sa);
 	if (rc != 0)
 		goto fail_flow_rss_attach;
@@ -1006,8 +1008,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
-	sfc_flow_init(sa);
-
 	rc = sfc_sw_xstats_init(sa);
 	if (rc != 0)
 		goto fail_sw_xstats_init;
@@ -1030,7 +1030,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_sw_xstats_close(sa);
 
 fail_sw_xstats_init:
-	sfc_flow_fini(sa);
 	sfc_repr_proxy_detach(sa);
 
 fail_repr_proxy_attach:
@@ -1052,6 +1051,7 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_flow_rss_detach(sa);
 
 fail_flow_rss_attach:
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 
 fail_rss_attach:
@@ -1099,8 +1099,6 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_sriov_vswitch_destroy(sa);
 
-	sfc_flow_fini(sa);
-
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
 	sfc_tbls_detach(sa);
@@ -1108,6 +1106,7 @@ sfc_detach(struct sfc_adapter *sa)
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_flow_rss_detach(sa);
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
 	sfc_ev_detach(sa);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 432295ea62..f6d1ae2a5b 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <rte_byteorder.h>
 #include <rte_tailq.h>
 #include <rte_common.h>
@@ -2405,7 +2407,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2421,7 +2423,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2613,14 +2615,14 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow;
 
 	sfc_adapter_lock(sa);
-	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
 	sfc_adapter_unlock(sa);
 
 	return flow;
 }
 
 struct rte_flow *
-sfc_flow_create_locked(struct sfc_adapter *sa,
+sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item pattern[],
 		       const struct rte_flow_action actions[],
@@ -2635,13 +2637,15 @@ sfc_flow_create_locked(struct sfc_adapter *sa,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	flow->internal = internal;
+
 	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
 	TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
 
-	if (sa->state == SFC_ETHDEV_STARTED) {
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED) {
 		rc = sfc_flow_insert(sa, flow, error);
 		if (rc != 0)
 			goto fail_flow_insert;
@@ -2694,7 +2698,7 @@ sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
 		goto fail_bad_value;
 	}
 
-	if (sa->state == SFC_ETHDEV_STARTED)
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED)
 		rc = sfc_flow_remove(sa, flow, error);
 
 	TAILQ_REMOVE(&sa->flow_list, flow, entries);
@@ -2711,10 +2715,14 @@ sfc_flow_flush(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct rte_flow *flow;
 	int ret = 0;
+	void *tmp;
 
 	sfc_adapter_lock(sa);
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		if (sa->state == SFC_ETHDEV_STARTED) {
 			int rc;
 
@@ -2842,10 +2850,14 @@ void
 sfc_flow_fini(struct sfc_adapter *sa)
 {
 	struct rte_flow *flow;
+	void *tmp;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		TAILQ_REMOVE(&sa->flow_list, flow, entries);
 		sfc_flow_free(sa, flow);
 	}
@@ -2858,8 +2870,10 @@ sfc_flow_stop(struct sfc_adapter *sa)
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	TAILQ_FOREACH(flow, &sa->flow_list, entries)
-		sfc_flow_remove(sa, flow, NULL);
+	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (!flow->internal)
+			sfc_flow_remove(sa, flow, NULL);
+	}
 
 	/*
 	 * MAE counter service is not stopped on flow rule remove to avoid
@@ -2881,6 +2895,9 @@ sfc_flow_start(struct sfc_adapter *sa)
 	sfc_ft_counters_reset(sa);
 
 	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (flow->internal)
+			continue;
+
 		rc = sfc_flow_insert(sa, flow, NULL);
 		if (rc != 0)
 			goto fail_bad_flow;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index a3ca09f225..ec5e29f257 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -10,6 +10,8 @@
 #ifndef _SFC_FLOW_H
 #define _SFC_FLOW_H
 
+#include <stdbool.h>
+
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
 
@@ -101,6 +103,7 @@ struct sfc_flow_spec {
 struct rte_flow {
 	struct sfc_flow_spec spec;	/* flow specification */
 	TAILQ_ENTRY(rte_flow) entries;	/* flow list entries */
+	bool internal;			/* true for internal rules */
 };
 
 TAILQ_HEAD(sfc_flow_list, rte_flow);
@@ -195,7 +198,7 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
-struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 					const struct rte_flow_attr *attr,
 					const struct rte_flow_item pattern[],
 					const struct rte_flow_action actions[],
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c0b97b1fe1..36eb78d425 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2539,6 +2539,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
+	if (ctx->internal) {
+		/*
+		 * A driver-internal flow may not comprise an outer rule,
+		 * but it must not match on invalid outer rule ID since
+		 * it must catch all missed packets, including those
+		 * that hit an outer rule of another flow entry but
+		 * do not hit a higher-priority action rule later.
+		 * So do not set match on outer rule ID here.
+		 */
+		SFC_ASSERT(ctx->match_spec_outer == NULL);
+		*rulep = NULL;
+		return 0;
+	}
+
 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
 		*rulep = NULL;
 		goto no_or_id;
@@ -2825,9 +2839,10 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
-			   struct sfc_flow_spec_mae *spec,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2835,6 +2850,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
 	ctx_mae.ft_rule_type = spec->ft_rule_type;
+	ctx_mae.internal = flow->internal;
 	ctx_mae.priority = spec->priority;
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
@@ -3644,11 +3660,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct sfc_flow_spec_mae *spec_mae,
+			  const struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
+	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -3772,6 +3789,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
 
+		if (flow->internal) {
+			switch_port_type_mask |=
+					1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
+		}
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
 				action->conf, switch_port_type_mask, spec);
 		break;
@@ -3842,9 +3864,10 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_flow_spec_mae *spec_mae,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
@@ -3901,7 +3924,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
+		rc = sfc_mae_rule_parse_action(sa, action, flow,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d2995ded88..307236ea11 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -363,6 +363,7 @@ struct sfc_mae_parse_ctx {
 	size_t				tunnel_def_mask_size;
 	const void			*tunnel_def_mask;
 	bool				match_mport_set;
+	bool				internal;
 	enum sfc_ft_rule_type		ft_rule_type;
 	struct sfc_mae_pattern_data	pattern_data;
 	efx_tunnel_protocol_t		encap_type;
@@ -376,11 +377,11 @@ void sfc_mae_detach(struct sfc_adapter *sa);
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
 int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       const struct rte_flow_item pattern[],
-			       struct sfc_flow_spec_mae *spec,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_flow_spec_mae *spec_mae,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 16/34] net/sfc: switch driver-internal flows to use generic methods
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (14 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
                     ` (17 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so helps to consolidate flow operation and ensure that
every FW-allocatable resource can be shared by several flows.
That is useful in the light of upcoming support for embedded
conntrack assistance, where several flows will ideally share
everything but unique 5-tuple entries in the conntrack table.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c        | 186 +++++++------------------------
 drivers/net/sfc/sfc_mae.h        |  51 ++-------
 drivers/net/sfc/sfc_repr_proxy.c |  38 ++-----
 drivers/net/sfc/sfc_repr_proxy.h |   2 +-
 4 files changed, 61 insertions(+), 216 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 36eb78d425..e1008c2f6f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -74,137 +74,48 @@ sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 	sfc_mae_counters_fini(&registry->counters);
 }
 
-static int
-sfc_mae_internal_rule_find_empty_slot(struct sfc_adapter *sa,
-				      struct sfc_mae_rule **rule)
-{
-	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_internal_rules *internal_rules = &mae->internal_rules;
-	unsigned int entry;
-	int rc;
-
-	for (entry = 0; entry < SFC_MAE_NB_RULES_MAX; entry++) {
-		if (internal_rules->rules[entry].spec == NULL)
-			break;
-	}
-
-	if (entry == SFC_MAE_NB_RULES_MAX) {
-		rc = ENOSPC;
-		sfc_err(sa, "failed too many rules (%u rules used)", entry);
-		goto fail_too_many_rules;
-	}
-
-	*rule = &internal_rules->rules[entry];
-
-	return 0;
-
-fail_too_many_rules:
-	return rc;
-}
-
-int
-sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-				     const efx_mport_sel_t *mport_match,
-				     const efx_mport_sel_t *mport_deliver,
-				     int prio, struct sfc_mae_rule **rulep)
+struct rte_flow *
+sfc_mae_repr_flow_create(struct sfc_adapter *sa, int prio, uint16_t port_id,
+			 enum rte_flow_action_type dst_type,
+			 enum rte_flow_item_type src_type)
 {
+	const struct rte_flow_item_ethdev item_spec = { .port_id = port_id };
+	const struct rte_flow_action_ethdev action = { .port_id = port_id };
+	const void *item_mask = &rte_flow_item_ethdev_mask;
+	struct rte_flow_attr attr = { .transfer = 1 };
+	const struct rte_flow_action actions[] = {
+		{ .type = dst_type, .conf = &action },
+		{ .type = RTE_FLOW_ACTION_TYPE_END }
+	};
+	const struct rte_flow_item items[] = {
+		{ .type = src_type, .mask = item_mask, .spec = &item_spec },
+		{ .type = RTE_FLOW_ITEM_TYPE_END }
+	};
 	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_rule *rule;
-	int rc;
-
-	sfc_log_init(sa, "entry");
+	struct rte_flow_error error;
 
 	if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
-		rc = EINVAL;
 		sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
 			mae->nb_action_rule_prios_max);
-		goto fail_invalid_prio;
+		return NULL;
 	}
 	if (prio < 0)
 		prio = mae->nb_action_rule_prios_max - 1;
 
-	rc = sfc_mae_internal_rule_find_empty_slot(sa, &rule);
-	if (rc != 0)
-		goto fail_find_empty_slot;
-
-	sfc_log_init(sa, "init MAE match spec");
-	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
-				     (uint32_t)prio, &rule->spec);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE match spec");
-		goto fail_match_init;
-	}
-
-	rc = efx_mae_match_spec_mport_set(rule->spec, mport_match, NULL);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get MAE match mport selector");
-		goto fail_mport_set;
-	}
-
-	rc = efx_mae_action_set_spec_init(sa->nic, &rule->actions);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE action set");
-		goto fail_action_init;
-	}
-
-	rc = efx_mae_action_set_populate_deliver(rule->actions,
-						 mport_deliver);
-	if (rc != 0) {
-		sfc_err(sa, "failed to populate deliver action");
-		goto fail_populate_deliver;
-	}
-
-	rc = efx_mae_action_set_alloc(sa->nic, rule->actions,
-				      &rule->action_set);
-	if (rc != 0) {
-		sfc_err(sa, "failed to allocate action set");
-		goto fail_action_set_alloc;
-	}
-
-	rc = efx_mae_action_rule_insert(sa->nic, rule->spec, NULL,
-					&rule->action_set,
-					&rule->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to insert action rule");
-		goto fail_rule_insert;
-	}
-
-	*rulep = rule;
-
-	sfc_log_init(sa, "done");
-
-	return 0;
-
-fail_rule_insert:
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-
-fail_action_set_alloc:
-fail_populate_deliver:
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
+	attr.priority = prio;
 
-fail_action_init:
-fail_mport_set:
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
-
-fail_match_init:
-fail_find_empty_slot:
-fail_invalid_prio:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	return sfc_flow_create_locked(sa, true, &attr, items, actions, &error);
 }
 
 void
-sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule)
+sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow)
 {
-	if (rule == NULL || rule->spec == NULL)
-		return;
-
-	efx_mae_action_rule_remove(sa->nic, &rule->rule_id);
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
+	struct rte_flow_error error;
+	int rc;
 
-	rule->spec = NULL;
+	rc = sfc_flow_destroy_locked(sa, flow, &error);
+	if (rc != 0)
+		sfc_err(sa, "failed to destroy the internal flow");
 }
 
 int
@@ -4313,11 +4224,9 @@ sfc_mae_flow_query(struct rte_eth_dev *dev,
 int
 sfc_mae_switchdev_init(struct sfc_adapter *sa)
 {
-	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
-	efx_mport_sel_t pf;
-	efx_mport_sel_t phy;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
@@ -4332,31 +4241,20 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 		goto fail_no_mae;
 	}
 
-	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
-					    &pf);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PF mport");
-		goto fail_pf_get;
-	}
-
-	rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PHY mport");
-		goto fail_phy_get;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_pf_to_ext);
-	if (rc != 0) {
+	mae->switchdev_rule_pf_to_ext = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
+					 RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR);
+	if (mae->switchdev_rule_pf_to_ext == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
 		goto fail_pf_add;
 	}
 
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_ext_to_pf);
-	if (rc != 0) {
+	mae->switchdev_rule_ext_to_pf = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+					 RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (mae->switchdev_rule_ext_to_pf == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
 		goto fail_phy_add;
 	}
@@ -4366,11 +4264,9 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 	return 0;
 
 fail_phy_add:
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 
 fail_pf_add:
-fail_phy_get:
-fail_pf_get:
 fail_no_mae:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
@@ -4384,6 +4280,6 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	if (!sa->switchdev)
 		return;
 
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
-	sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 307236ea11..f9434e1ab6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -180,33 +180,6 @@ struct sfc_mae_counter_registry {
 	} polling;
 };
 
-/**
- * MAE rules used to capture traffic generated by VFs and direct it to
- * representors (one for each VF).
- */
-#define SFC_MAE_NB_REPR_RULES_MAX	(64)
-
-/** Rules to forward traffic from PHY port to PF and from PF to PHY port */
-#define SFC_MAE_NB_SWITCHDEV_RULES	(2)
-/** Maximum required internal MAE rules */
-#define SFC_MAE_NB_RULES_MAX		(SFC_MAE_NB_SWITCHDEV_RULES + \
-					 SFC_MAE_NB_REPR_RULES_MAX)
-
-struct sfc_mae_rule {
-	efx_mae_match_spec_t		*spec;
-	efx_mae_actions_t		*actions;
-	efx_mae_aset_id_t		action_set;
-	efx_mae_rule_id_t		rule_id;
-};
-
-struct sfc_mae_internal_rules {
-	/*
-	 * Rules required to sustain switchdev mode or to provide
-	 * port representor functionality.
-	 */
-	struct sfc_mae_rule		rules[SFC_MAE_NB_RULES_MAX];
-};
-
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -234,14 +207,12 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter registry */
 	struct sfc_mae_counter_registry	counter_registry;
-	/** Driver-internal flow rules */
-	struct sfc_mae_internal_rules	internal_rules;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
 	 */
-	struct sfc_mae_rule		*switchdev_rule_pf_to_ext;
-	struct sfc_mae_rule		*switchdev_rule_ext_to_pf;
+	struct rte_flow			*switchdev_rule_pf_to_ext;
+	struct rte_flow			*switchdev_rule_ext_to_pf;
 };
 
 struct sfc_adapter;
@@ -396,16 +367,18 @@ sfc_flow_query_cb_t sfc_mae_flow_query;
 
 /**
  * Insert a driver-internal flow rule that matches traffic originating from
- * some m-port selector and redirects it to another one
- * (eg. PF --> PHY, PHY --> PF).
+ * a source port (REPRESENTED_PORT or PORT_REPRESENTOR) and directs it to
+ * its destination counterpart (PORT_REPRESENTOR or REPRESENTED_PORT).
  *
- * If requested priority is negative, use the lowest priority.
+ * If the prio argument is negative, the lowest level will be picked.
  */
-int sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-					 const efx_mport_sel_t *mport_match,
-					 const efx_mport_sel_t *mport_deliver,
-					 int prio, struct sfc_mae_rule **rulep);
-void sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule);
+struct rte_flow *sfc_mae_repr_flow_create(struct sfc_adapter *sa,
+					  int prio, uint16_t port_id,
+					  enum rte_flow_action_type dst_type,
+					  enum rte_flow_item_type src_type);
+
+void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
+
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 74c3494c35..ff13795c97 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -681,47 +681,25 @@ static int
 sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_repr_proxy *rp = &sa->repr_proxy;
-	efx_mport_sel_t mport_alias_selector;
-	efx_mport_sel_t mport_vf_selector;
-	struct sfc_mae_rule *mae_rule;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
-	rc = efx_mae_mport_by_id(&port->egress_mport,
-				 &mport_vf_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get VF mport for repr %u",
-			port->repr_id);
-		goto fail_get_vf;
-	}
-
-	rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get mport selector for repr %u",
-			port->repr_id);
-		goto fail_get_alias;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
-						  &mport_alias_selector, -1,
-						  &mae_rule);
-	if (rc != 0) {
+	port->mae_rule = sfc_mae_repr_flow_create(sa,
+				    SFC_MAE_RULE_PRIO_LOWEST, port->rte_port_id,
+				    RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+				    RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (port->mae_rule == NULL) {
 		sfc_err(sa, "failed to insert MAE rule for repr %u",
 			port->repr_id);
 		goto fail_rule_add;
 	}
 
-	port->mae_rule = mae_rule;
-
 	sfc_log_init(sa, "done");
 
 	return 0;
 
 fail_rule_add:
-fail_get_alias:
-fail_get_vf:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -730,9 +708,7 @@ static void
 sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_mae_rule *mae_rule = port->mae_rule;
-
-	sfc_mae_rule_del(sa, mae_rule);
+	sfc_mae_repr_flow_destroy(sa, port->mae_rule);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h
index 260e2cab30..0a4dedc3e1 100644
--- a/drivers/net/sfc/sfc_repr_proxy.h
+++ b/drivers/net/sfc/sfc_repr_proxy.h
@@ -67,7 +67,7 @@ struct sfc_repr_proxy_port {
 	uint32_t				remote_vnic_mcdi_client_handle;
 	struct sfc_repr_proxy_rxq		rxq[SFC_REPR_RXQ_MAX];
 	struct sfc_repr_proxy_txq		txq[SFC_REPR_TXQ_MAX];
-	struct sfc_mae_rule			*mae_rule;
+	struct rte_flow				*mae_rule;
 	bool					enabled;
 	bool					started;
 };
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 17/34] net/sfc: move MAE flow parsing method to MAE-specific source
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (15 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
                     ` (16 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so will facilitate easier code restructure in the next
patches required to rework flow housekeeping and indirection.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 47 +-----------------------------
 drivers/net/sfc/sfc_mae.c  | 58 ++++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  | 14 ++++-----
 3 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f6d1ae2a5b..6dfbbfd022 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2395,53 +2395,8 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-	struct sfc_flow_spec *spec = &flow->spec;
-	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	int rc;
-
-	/*
-	 * If the flow is meant to be a TUNNEL rule in a FT context,
-	 * preparse its actions and save its properties in spec_mae.
-	 */
-	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
-	if (rc != 0)
-		goto fail;
-
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
-		/*
-		 * By design, this flow should be represented solely by the
-		 * outer rule. But the HW/FW hasn't got support for setting
-		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
-		 * does it support outer rule counters. As a workaround, an
-		 * action rule of lower priority is used to do the job.
-		 *
-		 * So don't skip sfc_mae_rule_parse_actions() below.
-		 */
-	}
-
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_ctx != NULL) {
-		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
-			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
 
-		++(spec_mae->ft_ctx->refcnt);
-	}
-
-	return 0;
-
-fail:
-	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
-	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
-	spec_mae->ft_ctx = NULL;
-
-	return rc;
+	return sfc_mae_rule_parse(sa, pattern, actions, flow, error);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e1008c2f6f..2f34ca7ad3 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2747,7 +2747,7 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
 
-int
+static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
@@ -3772,7 +3772,7 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
 }
 
-int
+static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
@@ -3935,6 +3935,60 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	return rc;
 }
 
+int
+sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow *flow, struct rte_flow_error *error)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	int rc;
+
+	/*
+	 * If the flow is meant to be a TUNNEL rule in a FT context,
+	 * preparse its actions and save its properties in spec_mae.
+	 */
+	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
+	if (rc != 0)
+		goto fail;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 *
+		 * So don't skip sfc_mae_rule_parse_actions() below.
+		 */
+	}
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_ctx != NULL) {
+		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
+			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
+
+		++(spec_mae->ft_ctx->refcnt);
+	}
+
+	return 0;
+
+fail:
+	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
+	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
+	spec_mae->ft_ctx = NULL;
+
+	return rc;
+}
+
 static bool
 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
 			const efx_mae_match_spec_t *left,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index f9434e1ab6..1d937c9b5b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -345,15 +345,13 @@ struct sfc_mae_parse_ctx {
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 void sfc_mae_detach(struct sfc_adapter *sa);
+
+int sfc_mae_rule_parse(struct sfc_adapter *sa,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow *flow, struct rte_flow_error *error);
+
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
-int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
-			       const struct rte_flow_item pattern[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
-int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
-			       const struct rte_flow_action actions[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
 sfc_flow_remove_cb_t sfc_mae_flow_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 18/34] net/sfc: move MAE counter stream start to action set handler
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (16 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
                     ` (15 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Logically, starting flow counter streaming belongs in action
set enable path. Move it there as a preparation step for the
patch that will make action rules shareable by several flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2f34ca7ad3..131e8a8a86 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1063,6 +1063,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
+		if (action_set->n_counters > 0) {
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_err(sa, "failed to start MAE counters support: %s",
+					rte_strerror(rc));
+				sfc_mae_encap_header_disable(sa, encap_header);
+				sfc_mae_mac_addr_disable(sa, src_mac_addr);
+				sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+				return rc;
+			}
+		}
+
 		rc = sfc_mae_counters_enable(sa, counters,
 					     action_set->n_counters,
 					     action_set->spec);
@@ -4143,15 +4155,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_enable;
 
-	if (action_set->n_counters > 0) {
-		rc = sfc_mae_counter_start(sa);
-		if (rc != 0) {
-			sfc_err(sa, "failed to start MAE counters support: %s",
-				rte_strerror(rc));
-			goto fail_mae_counter_start;
-		}
-	}
-
 	fw_rsrc = &action_set->fw_rsrc;
 
 	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
@@ -4166,7 +4169,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	return 0;
 
 fail_action_rule_insert:
-fail_mae_counter_start:
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 19/34] net/sfc: prepare MAE outer rules for action rule indirection
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (17 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
                     ` (14 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Flows provided by match-action engine (MAE) will be reworked
by the next patch to make action rule (AR) entries shareable.
To ensure correct AR specification comparison on attach path,
augment the way outer rules (OR) are handled, namely, how OR
IDs are indicated in a AR specification on parse and disable.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 44 ++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 131e8a8a86..ba5ac5850f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -397,8 +397,10 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
-			   struct sfc_mae_outer_rule *rule)
+			   struct sfc_mae_outer_rule *rule,
+			   efx_mae_match_spec_t *match_spec_action)
 {
+	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -409,6 +411,18 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 
 	fw_rsrc = &rule->fw_rsrc;
 
+	if (match_spec_action == NULL)
+		goto skip_action_rule;
+
+	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
+						  &invalid_rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "cannot restore match on invalid outer rule ID: %s",
+			strerror(rc));
+		return;
+	}
+
+skip_action_rule:
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -2459,7 +2473,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule **rulep,
 			   struct rte_flow_error *error)
 {
-	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
+	efx_mae_rule_id_t or_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
 	if (ctx->internal) {
@@ -2506,13 +2520,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	/* The spec has now been tracked by the outer rule entry. */
 	ctx->match_spec_outer = NULL;
 
+	or_id.id = (*rulep)->fw_rsrc.rule_id.id;
+
 no_or_id:
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
 	case SFC_FT_RULE_TUNNEL:
-		/* No action rule */
-		return 0;
+		/*
+		 * Workaround. TUNNEL flows are not supposed to involve
+		 * MAE action rules, but, due to the currently limited
+		 * HW/FW implementation, action rules are still needed.
+		 * See sfc_mae_rule_parse_pattern().
+		 */
+		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
 		 * Match on recirculation ID rather than
@@ -2538,14 +2559,13 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
 	 * in the action rule specification; this ensures correct behaviour.
 	 *
-	 * If, on the other hand, this flow does have an outer rule, its ID
-	 * may be unknown at the moment (not yet allocated), but OR_ID mask
-	 * has to be set to 0xffffffff anyway for correct class comparisons.
-	 * When the outer rule has been allocated, this match field will be
-	 * overridden by sfc_mae_outer_rule_enable() to use the right value.
+	 * If, however, this flow does have an outer rule, OR_ID match must
+	 * be set to the currently known value for that outer rule. It will
+	 * be either 0xffffffff or some valid ID, depending on whether this
+	 * outer rule is currently active (adapter state is STARTED) or not.
 	 */
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
-						  &invalid_rule_id);
+						  &or_id);
 	if (rc != 0) {
 		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
@@ -4172,7 +4192,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4207,7 +4227,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 20/34] net/sfc: turn MAE flow action rules into shareable resources
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (18 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
                     ` (13 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance. With the new feature, multiple flows that differ
in the 5-tuple match fields but are otherwise identical will
be able to share all FW-allocatable objects except for those
of the conntrack table. That will boost flow engine capacity.

To prepare for that, action rules of the match-action engine
have to be turned into shareable objects, from SW standpoint.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   4 +-
 drivers/net/sfc/sfc_flow.h |  13 +-
 drivers/net/sfc/sfc_mae.c  | 362 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_mae.h  |  13 ++
 4 files changed, 287 insertions(+), 105 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 6dfbbfd022..0abeabfbf2 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1294,9 +1294,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		}
 		spec->type = SFC_FLOW_SPEC_MAE;
 		spec_mae->priority = attr->priority;
-		spec_mae->match_spec = NULL;
-		spec_mae->action_set = NULL;
-		spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+		spec_mae->action_rule = NULL;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index ec5e29f257..10c73d012f 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -75,14 +75,13 @@ struct sfc_flow_spec_mae {
 	struct sfc_ft_ctx		*ft_ctx;
 	/* Desired priority level */
 	unsigned int			priority;
-	/* Outer rule registry entry */
+	/*
+	 * Outer rule registry entry (points to below action_rule->outer_rule
+	 * when action_rule is not NULL; self-sufficient entry otherwise)
+	 */
 	struct sfc_mae_outer_rule	*outer_rule;
-	/* EFX match specification */
-	efx_mae_match_spec_t		*match_spec;
-	/* Action set registry entry */
-	struct sfc_mae_action_set	*action_set;
-	/* Firmware-allocated rule ID */
-	efx_mae_rule_id_t		rule_id;
+	/* Action rule registry entry */
+	struct sfc_mae_action_rule	*action_rule;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index ba5ac5850f..c0b93a57a6 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -204,6 +204,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
+	TAILQ_INIT(&mae->action_rules);
 
 	if (encp->enc_mae_admin)
 		mae->status = SFC_MAE_STATUS_ADMIN;
@@ -1174,6 +1175,200 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 	--(fw_rsrc->refcnt);
 }
 
+struct sfc_mae_action_rule_ctx {
+	struct sfc_mae_outer_rule	*outer_rule;
+	struct sfc_mae_action_set	*action_set;
+	efx_mae_match_spec_t		*match_spec;
+};
+
+static int
+sfc_mae_action_rule_attach(struct sfc_adapter *sa,
+			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule **rulep,
+			   __rte_unused struct rte_flow_error *error)
+{
+	struct sfc_mae_action_rule *rule;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	/*
+	 * It is assumed that the caller of this helper has already properly
+	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
+	 * ctx->outer_rule refers to a currently active outer rule) or
+	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
+	 */
+	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->outer_rule != ctx->outer_rule ||
+		    rule->action_set != ctx->action_set)
+			continue;
+
+		if (efx_mae_match_specs_equal(rule->match_spec,
+					      ctx->match_spec)) {
+			sfc_dbg(sa, "attaching to action_rule=%p", rule);
+			++(rule->refcnt);
+			*rulep = rule;
+			return 0;
+		}
+	}
+
+	/*
+	 * No need to set RTE error, as this
+	 * code should be handled gracefully.
+	 */
+	return -ENOENT;
+}
+
+static int
+sfc_mae_action_rule_add(struct sfc_adapter *sa,
+			const struct sfc_mae_action_rule_ctx *ctx,
+			struct sfc_mae_action_rule **rulep)
+{
+	struct sfc_mae_action_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	rule = rte_zmalloc("sfc_mae_action_rule", sizeof(*rule), 0);
+	if (rule == NULL)
+		return ENOMEM;
+
+	rule->refcnt = 1;
+	rule->outer_rule = ctx->outer_rule;
+	rule->action_set = ctx->action_set;
+	rule->match_spec = ctx->match_spec;
+
+	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);
+
+	*rulep = rule;
+
+	sfc_dbg(sa, "added action_rule=%p", rule);
+
+	return 0;
+}
+
+static void
+sfc_mae_action_rule_del(struct sfc_adapter *sa,
+			struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae *mae = &sa->mae;
+	if (rule == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(rule->refcnt != 0);
+
+	--(rule->refcnt);
+
+	if (rule->refcnt != 0)
+		return;
+
+	if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    rule->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u",
+			rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
+	}
+
+	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
+	sfc_mae_action_set_del(sa, rule->action_set);
+	sfc_mae_outer_rule_del(sa, rule->outer_rule);
+
+	TAILQ_REMOVE(&mae->action_rules, rule, entries);
+	rte_free(rule);
+
+	sfc_dbg(sa, "deleted action_rule=%p", rule);
+}
+
+static int
+sfc_mae_action_rule_enable(struct sfc_adapter *sa,
+			   struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->refcnt != 0)
+		goto success;
+
+	rc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);
+	if (rc != 0)
+		goto fail_outer_rule_enable;
+
+	rc = sfc_mae_action_set_enable(sa, rule->action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, NULL,
+					&rule->action_set->fw_rsrc.aset_id,
+					&fw_rsrc->rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "failed to enable action_rule=%p: %s",
+			rule, strerror(rc));
+		goto fail_action_rule_insert;
+	}
+
+success:
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled action_rule=%p: AR_ID=0x%08x",
+			rule, fw_rsrc->rule_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+
+fail_action_rule_insert:
+	sfc_mae_action_set_disable(sa, rule->action_set);
+
+fail_action_set_enable:
+	sfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);
+
+fail_outer_rule_enable:
+	return rc;
+}
+static void
+sfc_mae_action_rule_disable(struct sfc_adapter *sa,
+			    struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u",
+			rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled action_rule=%p with AR_ID=0x%08x",
+				rule, fw_rsrc->rule_id.id);
+		} else {
+			sfc_err(sa, "failed to disable action_rule=%p with AR_ID=0x%08x: %s",
+				rule, fw_rsrc->rule_id.id, strerror(rc));
+		}
+
+		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		sfc_mae_action_set_disable(sa, rule->action_set);
+
+		sfc_mae_outer_rule_disable(sa, rule->outer_rule,
+					   rule->match_spec);
+	}
+
+	--(fw_rsrc->refcnt);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -1193,13 +1388,7 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		--(spec_mae->ft_ctx->refcnt);
 	}
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-	sfc_mae_action_set_del(sa, spec_mae->action_set);
-
-	if (spec_mae->match_spec != NULL)
-		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
 }
 
 static int
@@ -2783,9 +2972,11 @@ static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
+	struct sfc_mae_outer_rule **outer_rulep;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2798,6 +2989,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
 
+	outer_rulep = &action_rule_ctx->outer_rule;
+
 	switch (ctx_mae.ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		/*
@@ -2874,7 +3067,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
-	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
+	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
 
@@ -2886,7 +3079,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		goto fail_validate_match_spec_action;
 	}
 
-	spec->match_spec = ctx_mae.match_spec_action;
+	action_rule_ctx->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
@@ -3808,6 +4001,7 @@ static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
@@ -3929,8 +4123,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		goto fail_check_fate_action;
 	}
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, &ctx);
-	if (spec_mae->action_set != NULL) {
+	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
+	if (action_rule_ctx->action_set != NULL) {
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -3938,7 +4132,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, actions, &ctx,
+				    &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -3974,6 +4169,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule_ctx ctx = {};
 	int rc;
 
 	/*
@@ -3984,7 +4180,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
@@ -4000,10 +4196,30 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	spec_mae->outer_rule = ctx.outer_rule;
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
+	rc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,
+					error);
+	if (rc == 0) {
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+		sfc_mae_action_set_del(sa, ctx.action_set);
+		sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+	} else if (rc == -ENOENT) {
+		rc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);
+		if (rc != 0) {
+			rc = rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to add the entry");
+			goto fail;
+		}
+	} else {
+		goto fail;
+	}
+
 	if (spec_mae->ft_ctx != NULL) {
 		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
 			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
@@ -4014,6 +4230,12 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	return 0;
 
 fail:
+	if (ctx.match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+
+	sfc_mae_action_set_del(sa, ctx.action_set);
+	sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+
 	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
 	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
 	spec_mae->ft_ctx = NULL;
@@ -4073,30 +4295,27 @@ sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
-				 struct sfc_flow_spec_mae *spec)
+				 struct sfc_mae_action_rule *rule)
 {
-	const struct rte_flow *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	const struct sfc_mae_action_rule *entry;
+	struct sfc_mae *mae = &sa->mae;
 
-	if (spec->match_spec == NULL)
+	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* An active rule is reused. Its class is known to be valid. */
 		return 0;
+	}
 
-	TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
-		const struct sfc_flow_spec *entry_spec = &entry->spec;
-		const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
-		const efx_mae_match_spec_t *left = es_mae->match_spec;
-		const efx_mae_match_spec_t *right = spec->match_spec;
+	TAILQ_FOREACH_REVERSE(entry, &mae->action_rules,
+			      sfc_mae_action_rules, entries) {
+		const efx_mae_match_spec_t *left = entry->match_spec;
+		const efx_mae_match_spec_t *right = rule->match_spec;
 
-		switch (entry_spec->type) {
-		case SFC_FLOW_SPEC_FILTER:
-			/* Ignore VNIC-level flows */
-			break;
-		case SFC_FLOW_SPEC_MAE:
-			if (sfc_mae_rules_class_cmp(sa, left, right))
-				return 0;
-			break;
-		default:
-			SFC_ASSERT(false);
-		}
+		if (entry == rule)
+			continue;
+
+		if (sfc_mae_rules_class_cmp(sa, left, right))
+			return 0;
 	}
 
 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
@@ -4126,6 +4345,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	int rc;
 
@@ -4138,7 +4358,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
-	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+	return sfc_mae_action_rule_class_verify(sa, action_rule);
 }
 
 int
@@ -4147,55 +4367,22 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_fw_rsrc *fw_rsrc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	int rc;
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_enable(sa, outer_rule,
-					       spec_mae->match_spec);
-		if (rc != 0)
-			goto fail_outer_rule_enable;
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
 		spec_mae->ft_ctx->reset_tunnel_hit_counter =
 			spec_mae->ft_ctx->switch_hit_counter;
 	}
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "enabled flow=%p (no AR)", flow);
+	if (action_rule == NULL)
 		return 0;
-	}
-
-	rc = sfc_mae_action_set_enable(sa, action_set);
-	if (rc != 0)
-		goto fail_action_set_enable;
-
-	fw_rsrc = &action_set->fw_rsrc;
 
-	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
-					NULL, &fw_rsrc->aset_id,
-					&spec_mae->rule_id);
+	rc = sfc_mae_action_rule_enable(sa, action_rule);
 	if (rc != 0)
-		goto fail_action_rule_insert;
-
-	sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
+		return rc;
 
 	return 0;
-
-fail_action_rule_insert:
-	sfc_mae_action_set_disable(sa, action_set);
-
-fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
-
-fail_outer_rule_enable:
-	return rc;
 }
 
 int
@@ -4204,30 +4391,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	int rc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "disabled flow=%p (no AR)", flow);
-		goto skip_action_rule;
-	}
-
-	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
-
-	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
-			flow, spec_mae->rule_id.id, strerror(rc));
-	}
-	sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
-	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
-
-	sfc_mae_action_set_disable(sa, action_set);
+	if (action_rule == NULL)
+		return 0;
 
-skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
+	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
 }
@@ -4239,17 +4408,20 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 		      struct rte_flow_query_count *data,
 		      struct rte_flow_error *error)
 {
-	struct sfc_mae_action_set *action_set = spec->action_set;
+	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
+	struct sfc_mae_action_set *action_set;
 	unsigned int i;
 	int rc;
 
-	if (action_set == NULL || action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
+	action_set = action_rule->action_set;
+
 	for (i = 0; i < action_set->n_counters; i++) {
 		/*
 		 * Get the first available counter of the flow rule if
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1d937c9b5b..cbe190075c 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -97,6 +97,17 @@ struct sfc_mae_action_set {
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 
+/** Action rule registry entry */
+struct sfc_mae_action_rule {
+	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	struct sfc_mae_outer_rule		*outer_rule;
+	struct sfc_mae_action_set		*action_set;
+	efx_mae_match_spec_t			*match_spec;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+	unsigned int				refcnt;
+};
+TAILQ_HEAD(sfc_mae_action_rules, sfc_mae_action_rule);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -201,6 +212,8 @@ struct sfc_mae {
 	struct sfc_mae_mac_addrs	mac_addrs;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Action rule registry */
+	struct sfc_mae_action_rules	action_rules;
 	/** Encap. header bounce buffer */
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 21/34] common/sfc_efx/base: provide an API to clone MAE match specs
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (19 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
                     ` (12 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

The DPDK driver would like to have a means to make a copy of
the action rule match specification before trying to dissect
it to possibly move out the per-connection 5-tuple data from
it to build up an entry in the HW conntrack assistance table.

Making such a copy at the end of parsing should be preferred
over maintaining DPDK-level structures because the resulting
code is easier on eyes and less prone to errors in this case.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cdf8a99abf..d327a9978f 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4452,6 +4452,13 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_match_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4c33471f28..63eefd6880 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1163,6 +1163,32 @@ efx_mae_match_spec_mport_set(
 
 fail2:
 	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep)
+{
+	efx_mae_match_spec_t *clone;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
+	if (clone == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
+
+	*clonep = clone;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index b596369c48..73ec02d478 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_alloc;
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
+	efx_mae_match_spec_clone;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 22/34] common/sfc_efx/base: add API to read back MAE match criteria
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (20 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
                     ` (11 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance in the DPDK driver. In order to detect flows that
are subject to such assistance, the driver needs to retrieve
5-tuple match data from an already constructed specification.

A dedicated API to selectively read back match criteria will
make a neat solution to keep the implementation less complex.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  10 ++
 drivers/common/sfc_efx/base/efx_mae.c | 131 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   1 +
 3 files changed, 142 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index d327a9978f..fc5c64c2d1 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4430,6 +4430,16 @@ efx_mae_match_spec_field_set(
 	__in				size_t mask_size,
 	__in_bcount(mask_size)		const uint8_t *mask);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask);
+
 /* The corresponding mask will be set to B_TRUE. */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 63eefd6880..48f98e3c42 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1054,6 +1054,137 @@ efx_mae_match_spec_field_set(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	unsigned int desc_set_nentries;
+	const uint8_t *mvp;
+	efx_rc_t rc;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
+	case EFX_MAE_RULE_ACTION:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((unsigned int)field_id >= desc_set_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (descp->emmd_mask_size == 0) {
+		/* The ID points to a gap in the array of field descriptors. */
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (value != NULL && value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (mask != NULL && mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	if (value == NULL && value_size != 0) {
+		rc = EINVAL;
+		goto fail6;
+	}
+
+	if (mask == NULL && mask_size != 0) {
+		rc = EINVAL;
+		goto fail7;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The MCDI request field is in network (big endian) order.
+		 * The mask/value are also big endian.
+		 */
+		memcpy(value, mvp + descp->emmd_value_offset, value_size);
+		memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The MCDI request field is little endian.
+		 * The mask/value are in host byte order.
+		 */
+		switch (value_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_value_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)value =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(value, mvp + descp->emmd_value_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_mask_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)mask =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(mask, mvp + descp->emmd_mask_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 73ec02d478..3ac2fb12f3 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -126,6 +126,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 23/34] common/sfc_efx/base: match on conntrack mark in action rules
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (21 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
                     ` (10 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

EF100 match-action engine (MAE) has conntrack assistance
table. A hit in this table can provide a mark value for
the following lookup stage, which is action rule lookup.

Provide support for setting match on conntrack mark.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 28 +++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index fc5c64c2d1..e923032191 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4276,6 +4276,7 @@ typedef enum efx_mae_field_id_e {
 	 * or by using dedicated field-specific helper APIs.
 	 */
 	EFX_MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_CT_MARK,
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
@@ -4462,6 +4463,12 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_match_spec_clone(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 48f98e3c42..3dcce88928 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -474,6 +474,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
 	EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
 	EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -549,6 +550,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
 	EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
 
 #undef EFX_MAE_MV_DESC
 };
@@ -910,6 +912,32 @@ efx_mae_match_spec_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	mp = (const uint8_t *)&full_mask;
+	vp = (const uint8_t *)&ct_mark;
+
+	rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
+					  sizeof (ct_mark), vp,
+					  sizeof (full_mask), mp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 3ac2fb12f3..d0c7e99686 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -126,6 +126,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_ct_mark_set;
 	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (22 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
                     ` (9 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such can be initiated when a packet hits an outer rule.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  9 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 37 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index e923032191..141481372c 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4679,6 +4679,15 @@ efx_mae_outer_rule_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+/*
+ * Request that packets hitting this rule be submitted
+ * for a lookup in the conntrack assistance table.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec);
+
 LIBEFX_API
 extern	__checkReturn		efx_rc_t
 efx_mae_outer_rule_insert(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 45e99d01c5..34e25ef990 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1761,6 +1761,7 @@ struct efx_mae_match_spec_s {
 		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 	uint8_t				emms_outer_rule_recirc_id;
+	boolean_t			emms_outer_rule_do_ct;
 };
 
 typedef enum efx_mae_action_e {
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 3dcce88928..b3127b6db8 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -2366,6 +2366,26 @@ efx_mae_outer_rule_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec)
+{
+	efx_rc_t rc;
+
+	if (spec->emms_type != EFX_MAE_RULE_OUTER) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	spec->emms_outer_rule_do_ct = B_TRUE;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
@@ -2386,6 +2406,7 @@ efx_mae_outer_rule_insert(
 	uint32_t encap_type_mcdi;
 	efx_mae_rule_id_t or_id;
 	size_t offset;
+	uint8_t do_ct;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
@@ -2448,6 +2469,11 @@ efx_mae_outer_rule_insert(
 	    MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
 	    spec->emms_outer_rule_recirc_id);
 
+	do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
+
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
+	    MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d0c7e99686..f567f667b5 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -144,6 +144,7 @@ INTERNAL {
 	efx_mae_mport_free;
 	efx_mae_mport_id_by_selector;
 	efx_mae_mport_invalid;
+	efx_mae_outer_rule_do_ct_set;
 	efx_mae_outer_rule_insert;
 	efx_mae_outer_rule_recirc_id_set;
 	efx_mae_outer_rule_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 25/34] net/sfc: make use of conntrack assistance for transfer flows
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (23 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
                     ` (8 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

NAT and CT counters will be supported later.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h |   4 +
 drivers/net/sfc/sfc_mae.c  | 314 +++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  |   1 +
 3 files changed, 310 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 10c73d012f..8f706fc589 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -18,6 +18,7 @@
 #include "efx.h"
 
 #include "sfc_flow_rss.h"
+#include "sfc_mae_ct.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +83,9 @@ struct sfc_flow_spec_mae {
 	struct sfc_mae_outer_rule	*outer_rule;
 	/* Action rule registry entry */
 	struct sfc_mae_action_rule	*action_rule;
+	/* Conntrack (CT) assistance table entry key and response */
+	sfc_mae_conntrack_response_t	ct_resp;
+	sfc_mae_conntrack_key_t		ct_key;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c0b93a57a6..07bcf39b05 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -18,6 +18,7 @@
 #include "sfc.h"
 #include "sfc_flow_tunnel.h"
 #include "sfc_mae_counter.h"
+#include "sfc_mae_ct.h"
 #include "sfc_log.h"
 #include "sfc_switch.h"
 #include "sfc_service.h"
@@ -1179,18 +1180,23 @@ struct sfc_mae_action_rule_ctx {
 	struct sfc_mae_outer_rule	*outer_rule;
 	struct sfc_mae_action_set	*action_set;
 	efx_mae_match_spec_t		*match_spec;
+	uint32_t			ct_mark;
 };
 
 static int
 sfc_mae_action_rule_attach(struct sfc_adapter *sa,
-			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule_ctx *ctx,
 			   struct sfc_mae_action_rule **rulep,
-			   __rte_unused struct rte_flow_error *error)
+			   struct rte_flow_error *error)
 {
+	uint32_t new_ct_mark = ctx->ct_mark;
 	struct sfc_mae_action_rule *rule;
+	int rc;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	SFC_ASSERT(ctx->ct_mark <= 1);
+
 	/*
 	 * It is assumed that the caller of this helper has already properly
 	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
@@ -1198,10 +1204,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
 	 */
 	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->ct_mark == new_ct_mark)
+			++new_ct_mark;
+
 		if (rule->outer_rule != ctx->outer_rule ||
-		    rule->action_set != ctx->action_set)
+		    rule->action_set != ctx->action_set ||
+		    !!rule->ct_mark != !!ctx->ct_mark)
 			continue;
 
+		if (ctx->ct_mark != 0) {
+			rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+							    rule->ct_mark);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark for comparison");
+			}
+		}
+
 		if (efx_mae_match_specs_equal(rule->match_spec,
 					      ctx->match_spec)) {
 			sfc_dbg(sa, "attaching to action_rule=%p", rule);
@@ -1211,6 +1231,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 		}
 	}
 
+	if (ctx->ct_mark != 0) {
+		if (new_ct_mark == UINT32_MAX) {
+			return rte_flow_error_set(error, ERANGE,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to allocate CT mark");
+		}
+
+		rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+						    new_ct_mark);
+		if (rc != 0) {
+			return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark");
+		}
+
+		ctx->ct_mark = new_ct_mark;
+	}
+
 	/*
 	 * No need to set RTE error, as this
 	 * code should be handled gracefully.
@@ -1233,6 +1271,17 @@ sfc_mae_action_rule_add(struct sfc_adapter *sa,
 		return ENOMEM;
 
 	rule->refcnt = 1;
+
+	/*
+	 * It is assumed that the caller invoked sfc_mae_action_rule_attach()
+	 * and got (-ENOENT) before getting here. That ensures a unique CT
+	 * mark value or, if no CT is involved at all, simply zero.
+	 *
+	 * It is also assumed that match on the mark (if non-zero)
+	 * is already set in the action rule match specification.
+	 */
+	rule->ct_mark = ctx->ct_mark;
+
 	rule->outer_rule = ctx->outer_rule;
 	rule->action_set = ctx->action_set;
 	rule->match_spec = ctx->match_spec;
@@ -1804,6 +1853,8 @@ struct sfc_mae_field_locator {
 	size_t				size;
 	/* Field offset in the corresponding rte_flow_item_ struct */
 	size_t				ofst;
+
+	uint8_t				ct_key_field;
 };
 
 static void
@@ -2656,6 +2707,216 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 	},
 };
 
+#define SFC_MAE_CT_KEY_ET 0x01 /* EtherType */
+#define SFC_MAE_CT_KEY_DA 0x02 /* IPv4/IPv6 destination address */
+#define SFC_MAE_CT_KEY_SA 0x04 /* IPv4/IPv6 source address */
+#define SFC_MAE_CT_KEY_L4 0x08 /* IPv4/IPv6 L4 protocol ID */
+#define SFC_MAE_CT_KEY_DP 0x10 /* L4 destination port */
+#define SFC_MAE_CT_KEY_SP 0x20 /* L4 source port */
+
+#define SFC_MAE_CT_KEY_FIELD_SIZE_MAX	sizeof(sfc_mae_conntrack_key_t)
+
+static const struct sfc_mae_field_locator flocs_ct[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ether_type_le),
+		offsetof(sfc_mae_conntrack_key_t, ether_type_le),
+		SFC_MAE_CT_KEY_ET,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_IP_PROTO,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ip_proto),
+		offsetof(sfc_mae_conntrack_key_t, ip_proto),
+		SFC_MAE_CT_KEY_L4,
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, dst_port_le),
+		offsetof(sfc_mae_conntrack_key_t, dst_port_le),
+		SFC_MAE_CT_KEY_DP,
+	},
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, src_port_le),
+		offsetof(sfc_mae_conntrack_key_t, src_port_le),
+		SFC_MAE_CT_KEY_SP,
+	},
+};
+
+static int
+sfc_mae_rule_process_ct(struct sfc_adapter *sa, struct sfc_mae_parse_ctx *pctx,
+			struct sfc_mae_action_rule_ctx *action_rule_ctx,
+			struct sfc_flow_spec_mae *spec,
+			struct rte_flow_error *error)
+{
+	efx_mae_match_spec_t *match_spec_tmp;
+	uint8_t ct_key_missing_fields =
+		SFC_MAE_CT_KEY_ET | SFC_MAE_CT_KEY_DA | SFC_MAE_CT_KEY_SA |
+		SFC_MAE_CT_KEY_L4 | SFC_MAE_CT_KEY_DP | SFC_MAE_CT_KEY_SP;
+	unsigned int i;
+	int rc;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * TUNNEL rules have no network match fields that belong
+		 * in an action rule match specification, so nothing can
+		 * be possibly utilised for conntrack assistance offload.
+		 */
+		return 0;
+	}
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return 0;
+
+	rc = efx_mae_match_spec_clone(sa->nic, pctx->match_spec_action,
+				      &match_spec_tmp);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"AR: failed to clone the match specification");
+	}
+
+	for (i = 0; i < RTE_DIM(flocs_ct); ++i) {
+		const struct sfc_mae_field_locator *fl = &flocs_ct[i];
+		uint8_t mask_full[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask_zero[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t value[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t *ct_key = (uint8_t *)&spec->ct_key;
+		efx_mae_field_id_t fid = fl->field_id;
+		unsigned int j;
+
+		rc = efx_mae_match_spec_field_get(match_spec_tmp, fid,
+						  fl->size, value,
+						  fl->size, mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to extract match field");
+		}
+
+		memset(mask_full, 0xff, fl->size);
+
+		if (memcmp(mask, mask_full, fl->size) != 0)
+			continue;
+
+		memset(mask_zero, 0, fl->size);
+
+		rc = efx_mae_match_spec_field_set(match_spec_tmp, fid,
+						  fl->size, mask_zero,
+						  fl->size, mask_zero);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to erase match field");
+		}
+
+		for (j = 0; j < fl->size; ++j) {
+			uint8_t *byte_dst = ct_key + fl->ofst + fl->size - 1 - j;
+			const uint8_t *byte_src = value + j;
+
+			*byte_dst = *byte_src;
+		}
+
+		ct_key_missing_fields &= ~(fl->ct_key_field);
+	}
+
+	if (ct_key_missing_fields != 0) {
+		efx_mae_match_spec_fini(sa->nic, match_spec_tmp);
+		return 0;
+	}
+
+	efx_mae_match_spec_fini(sa->nic, pctx->match_spec_action);
+	pctx->match_spec_action = match_spec_tmp;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		/*
+		 * A SWITCH rule re-uses the corresponding TUNNEL rule's
+		 * outer rule, where conntrack request should have been
+		 * configured already, so skip outer rule processing.
+		 */
+		goto skip_outer_rule;
+	}
+
+	if (pctx->match_spec_outer == NULL) {
+		const struct sfc_mae_pattern_data *pdata = &pctx->pattern_data;
+		const struct sfc_mae_ethertype *et;
+		struct sfc_mae *mae = &sa->mae;
+
+		rc = efx_mae_match_spec_init(sa->nic,
+					     EFX_MAE_RULE_OUTER,
+					     mae->nb_outer_rule_prios_max - 1,
+					     &pctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to initialise the match specification");
+		}
+
+		/* Match on EtherType appears to be compulsory in outer rules */
+
+		et = &pdata->ethertypes[pdata->nb_vlan_tags];
+
+		rc = efx_mae_match_spec_field_set(pctx->match_spec_outer,
+				EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
+				sizeof(et->value), (const uint8_t *)&et->value,
+				sizeof(et->mask), (const uint8_t *)&et->mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to set match on EtherType");
+		}
+	}
+
+	rc = efx_mae_outer_rule_do_ct_set(pctx->match_spec_outer);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to request CT lookup");
+	}
+
+skip_outer_rule:
+	/* Initial/dummy CT mark value */
+	action_rule_ctx->ct_mark = 1;
+
+	return 0;
+}
+
+#undef SFC_MAE_CT_KEY_ET
+#undef SFC_MAE_CT_KEY_DA
+#undef SFC_MAE_CT_KEY_SA
+#undef SFC_MAE_CT_KEY_L4
+#undef SFC_MAE_CT_KEY_DP
+#undef SFC_MAE_CT_KEY_SP
+
 static int
 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_parse_ctx *ctx,
@@ -2679,13 +2940,11 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
+	if (ctx->match_spec_outer == NULL) {
 		*rulep = NULL;
 		goto no_or_id;
 	}
 
-	SFC_ASSERT(ctx->match_spec_outer != NULL);
-
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -2812,6 +3071,7 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 {
 	const struct rte_flow_item *pattern = ctx->pattern;
 	struct sfc_mae *mae = &sa->mae;
+	bool request_ct = false;
 	uint8_t recirc_id = 0;
 	int rc;
 
@@ -2907,6 +3167,14 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		recirc_id = SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id);
+
+		if (sfc_mae_conntrack_is_supported(sa)) {
+			/*
+			 * Request lookup in conntrack table since SWITCH rules
+			 * are eligible to utilise this type of assistance.
+			 */
+			request_ct = true;
+		}
 		/* FALLTHROUGH */
 	case SFC_FT_RULE_NONE:
 		if (ctx->priority >= mae->nb_outer_rule_prios_max) {
@@ -2940,6 +3208,16 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 					"OR: failed to initialise RECIRC_ID");
 		}
+
+		if (!request_ct)
+			break;
+
+		rc = efx_mae_outer_rule_do_ct_set(ctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to request CT lookup");
+		}
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/* Outermost items -> "ENC" match fields in the action rule. */
@@ -2961,9 +3239,6 @@ static void
 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 			      struct sfc_mae_parse_ctx *ctx)
 {
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
-		return;
-
 	if (ctx->match_spec_outer != NULL)
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
@@ -3067,6 +3342,11 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
+	rc = sfc_mae_rule_process_ct(sa, &ctx_mae, action_rule_ctx,
+				     spec, error);
+	if (rc != 0)
+		goto fail_process_ct;
+
 	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
@@ -3085,6 +3365,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 fail_validate_match_spec_action:
 fail_process_outer:
+fail_process_ct:
 fail_process_pattern_data:
 fail_parse_pattern:
 	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
@@ -4382,6 +4663,18 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
+	if (spec_mae->action_rule->ct_mark != 0) {
+		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
+		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
+					      &spec_mae->ct_resp);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -4396,6 +4689,9 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule == NULL)
 		return 0;
 
+	if (action_rule->ct_mark != 0)
+		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index cbe190075c..67fa2ca5c9 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -100,6 +100,7 @@ TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 /** Action rule registry entry */
 struct sfc_mae_action_rule {
 	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	uint32_t				ct_mark;
 	struct sfc_mae_outer_rule		*outer_rule;
 	struct sfc_mae_action_set		*action_set;
 	efx_mae_match_spec_t			*match_spec;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 26/34] common/sfc_efx/base: support NAT edits in MAE
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (24 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
                     ` (7 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

NAT goes after IP TTL decrement. It can operate
on the outermost frame only. In the case of
prior decapsulation, that maps to the frame
which was (originally) the inner one. Input
data for the action comes from the response
of the HW conntrack assistance table hit.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      | 13 +++++++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 17 +++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 32 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 141481372c..abde5fea2e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4560,6 +4560,19 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_decr_ip_ttl(
 	__in				efx_mae_actions_t *spec);
 
+/*
+ * This only requests NAT action. The replacement IP address and
+ * L4 port number, as well as the edit direction (DST/SRC), come
+ * from the response to a hit in the conntrack assistance table.
+ *
+ * The action amends the outermost frame. In the case of prior
+ * decapsulation, that maps to the (originally) inner frame.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 34e25ef990..f9d60b9eb9 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1771,6 +1771,7 @@ typedef enum efx_mae_action_e {
 	EFX_MAE_ACTION_SET_DST_MAC,
 	EFX_MAE_ACTION_SET_SRC_MAC,
 	EFX_MAE_ACTION_DECR_IP_TTL,
+	EFX_MAE_ACTION_NAT,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_COUNT,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index b3127b6db8..154d2f1942 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1834,6 +1834,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_DECR_IP_TTL] = {
 		.emad_add = efx_mae_action_set_no_op
 	},
+	[EFX_MAE_ACTION_NAT] = {
+		.emad_add = efx_mae_action_set_no_op
+	},
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
@@ -1860,6 +1863,7 @@ static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_SET_DST_MAC) |
 	(1U << EFX_MAE_ACTION_SET_SRC_MAC) |
 	(1U << EFX_MAE_ACTION_DECR_IP_TTL) |
+	(1U << EFX_MAE_ACTION_NAT) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	/*
 	 * HW will conduct action COUNT after
@@ -2035,6 +2039,14 @@ efx_mae_action_set_populate_decr_ip_ttl(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_NAT, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
 	__in				efx_mae_actions_t *spec,
@@ -3090,6 +3102,11 @@ efx_mae_action_set_alloc(
 		    MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
 	}
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
+	}
+
 	if (spec->ema_n_vlan_tags_to_push > 0) {
 		unsigned int outer_tag_idx;
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f567f667b5..f601110f84 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -105,6 +105,7 @@ INTERNAL {
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_mark_reset;
+	efx_mae_action_set_populate_nat;
 	efx_mae_action_set_populate_set_dst_mac;
 	efx_mae_action_set_populate_set_src_mac;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (25 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
                     ` (6 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

For this offload to work, the innermost pattern items must
provide the full set of exact match criteria, which are as
follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
and TP SRC, where the protocol types can be autodetected.

The offload requires that the IPv4 and the TP actions be
requested simultaneously in the same flow by the caller:
SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.

The offload operates on the outermost frame, which,
if action VXLAN_DECAP was requested, maps to the
inner frame of the original packet. The caller
is responsible to request this offload only
when the target header is an IPv4-based one.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini       |  4 ++
 doc/guides/nics/sfc_efx.rst            |  8 +++
 doc/guides/rel_notes/release_23_07.rst | 15 +++++
 drivers/net/sfc/sfc_mae.c              | 77 +++++++++++++++++++++++---
 4 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index f5ac644278..19d4935ce6 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -75,8 +75,12 @@ port_representor     = Y
 represented_port     = Y
 queue                = Y
 rss                  = Y
+set_ipv4_dst         = Y
+set_ipv4_src         = Y
 set_mac_dst          = Y
 set_mac_src          = Y
+set_tp_dst           = Y
+set_tp_src           = Y
 vf                   = Y
 vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index de0656876b..6e974c3720 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -270,10 +270,18 @@ Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- SET_IPV4_DST
+
+- SET_IPV4_SRC
+
 - SET_MAC_DST
 
 - SET_MAC_SRC
 
+- SET_TP_DST
+
+- SET_TP_SRC
+
 - OF_DEC_NW_TTL
 
 - DEC_TTL
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index 0b5561a6c6..8d4a541fea 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -89,6 +89,21 @@ New Features
   for new capability registers, large passthrough BAR and some
   performance enhancements for UPT.
 
+* **Updated Solarflare network PMD.**
+
+  Updated the Solarflare ``sfc_efx`` driver with changes including:
+
+  * Added partial support for transfer flow actions SET_IPV4_DST,
+    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
+    It is required that the innermost pattern items provide the
+    full set of exact match criteria: EtherType, IP DST, IP SRC,
+    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
+    must be requested simultaneously in the same flow. These
+    actions operate on the outermost frame, at the point
+    where action VXLAN_ENCAP (if any) has done its job.
+    The caller is responsible to request this offload
+    only when the target header is an IPv4-based one.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 07bcf39b05..5330bbf78e 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,6 +9,7 @@
 
 #include <stdbool.h>
 
+#include <rte_byteorder.h>
 #include <rte_bitops.h>
 #include <rte_common.h>
 #include <rte_vxlan.h>
@@ -3446,6 +3447,8 @@ sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
 };
 
 struct sfc_mae_actions_bundle {
@@ -3466,7 +3469,8 @@ struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      efx_mae_actions_t *spec)
+			      struct sfc_flow_spec_mae *flow_spec,
+			      bool ct, efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
@@ -3477,6 +3481,16 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 		rc = efx_mae_action_set_populate_vlan_push(
 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
+		flow_spec->ct_resp.nat.dir_is_dst = true;
+		/* FALLTHROUGH */
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
+		if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
+		    flow_spec->ct_resp.nat.port_le != 0)
+			rc = efx_mae_action_set_populate_nat(spec);
+		else
+			rc = EINVAL;
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -3493,7 +3507,8 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 static int
 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			    struct sfc_mae_actions_bundle *bundle,
-			    efx_mae_actions_t *spec,
+			    struct sfc_flow_spec_mae *flow_spec,
+			    efx_mae_actions_t *spec, bool ct,
 			    struct rte_flow_error *error)
 {
 	enum sfc_mae_actions_bundle_type bundle_type_new;
@@ -3505,6 +3520,14 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -3517,7 +3540,7 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 
 	if (bundle_type_new != bundle->type ||
 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
-		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
 		if (rc != 0)
 			goto fail_submit;
 
@@ -3534,6 +3557,20 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			"Failed to request the (group of) action(s)");
 }
 
+static void
+sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
+				   uint32_t *nat_addr_le)
+{
+	*nat_addr_le = rte_bswap32(conf->ipv4_addr);
+}
+
+static void
+sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
+				   uint16_t *nat_port_le)
+{
+	*nat_port_le = rte_bswap16(conf->port);
+}
+
 static void
 sfc_mae_rule_parse_action_of_push_vlan(
 			    const struct rte_flow_action_of_push_vlan *conf,
@@ -4058,6 +4095,10 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
 	[RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
@@ -4077,12 +4118,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct rte_flow *flow,
+			  struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
-	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4129,6 +4170,24 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_addr(action->conf,
+					&spec_mae->ct_resp.nat.ip_le);
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_port(action->conf,
+						&spec_mae->ct_resp.nat.port_le);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
 				       bundle->actions_mask);
@@ -4287,6 +4346,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
+	bool ct = (action_rule_ctx->ct_mark != 0);
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
 	struct sfc_mae *mae = &sa->mae;
@@ -4337,8 +4397,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_actions_bundle_sync(action, &bundle,
-						 ctx.spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+						 ctx.spec, ct, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
@@ -4348,7 +4408,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			goto fail_rule_parse_action;
 	}
 
-	rc = sfc_mae_actions_bundle_sync(action, &bundle, ctx.spec, error);
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+					 ctx.spec, ct, error);
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 28/34] net/sfc: rename SW structures used by transfer flow counters
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (26 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
                     ` (5 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so facilitates rearrangements of the next patch needed
to make software counter objects shareable across many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 14 +++++++-------
 drivers/net/sfc/sfc_mae.h         | 14 +++++++-------
 drivers/net/sfc/sfc_mae_counter.c | 31 ++++++++++++++++---------------
 drivers/net/sfc/sfc_mae_counter.h | 16 ++++++++--------
 4 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 5330bbf78e..eccd6727f2 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -151,7 +151,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		if (rc != 0)
 			goto fail_mae_get_limits;
 
-		sfc_log_init(sa, "init MAE counter registry");
+		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
 						   limits.eml_max_n_counters);
 		if (rc != 0) {
@@ -817,7 +817,7 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counters,
+			struct sfc_mae_counter *counters,
 			unsigned int n_counters,
 			efx_mae_actions_t *action_set_spec)
 {
@@ -833,7 +833,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(n_counters == 1);
 
-	rc = sfc_mae_counter_enable(sa, &counters[0]);
+	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
 	if (rc != 0) {
 		sfc_err(sa, "failed to enable MAE counter %u: %s",
 			counters[0].mae_id.id, rte_strerror(rc));
@@ -851,7 +851,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	return 0;
 
 fail_fill_in_id:
-	(void)sfc_mae_counter_disable(sa, &counters[0]);
+	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 
 fail_counter_add:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
@@ -860,7 +860,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter_id *counters,
+			 struct sfc_mae_counter *counters,
 			 unsigned int n_counters)
 {
 	if (n_counters == 0)
@@ -874,7 +874,7 @@ sfc_mae_counters_disable(struct sfc_adapter *sa,
 		return EALREADY;
 	}
 
-	return sfc_mae_counter_disable(sa, &counters[0]);
+	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 }
 
 struct sfc_mae_aset_ctx {
@@ -1039,7 +1039,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_counter *counters;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 67fa2ca5c9..7337fcf14d 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -68,7 +68,7 @@ struct sfc_mae_encap_header {
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
 /* Counter ID */
-struct sfc_mae_counter_id {
+struct sfc_mae_counter {
 	/* ID of a counter in MAE */
 	efx_counter_t			mae_id;
 	/* ID of a counter in RTE */
@@ -86,7 +86,7 @@ struct sfc_mae_counter_id {
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter_id	*counters;
+	struct sfc_mae_counter		*counters;
 	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
@@ -129,7 +129,7 @@ struct sfc_mae_bounce_eh {
 };
 
 /** Counter collection entry */
-struct sfc_mae_counter {
+struct sfc_mae_counter_record {
 	bool				inuse;
 	uint32_t			generation_count;
 	union sfc_pkts_bytes		value;
@@ -143,9 +143,9 @@ struct sfc_mae_counters_xstats {
 	uint64_t			realloc_update;
 };
 
-struct sfc_mae_counters {
+struct sfc_mae_counter_records {
 	/** An array of all MAE counters */
-	struct sfc_mae_counter		*mae_counters;
+	struct sfc_mae_counter_record	*mae_counters;
 	/** Extra statistics for counters */
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
@@ -162,7 +162,7 @@ enum sfc_mae_counter_polling_mode {
 struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Counters collection */
-	struct sfc_mae_counters		counters;
+	struct sfc_mae_counter_records	counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
@@ -219,7 +219,7 @@ struct sfc_mae {
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
 	bool				counter_rxq_running;
-	/** Counter registry */
+	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 818b4dad4a..8170175991 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -76,12 +76,12 @@ sfc_mae_counter_rxq_required(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_enable(struct sfc_adapter *sa,
-		       struct sfc_mae_counter_id *counterp)
+sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
@@ -147,12 +147,12 @@ sfc_mae_counter_enable(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counter_disable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counter)
+sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
@@ -189,12 +189,13 @@ sfc_mae_counter_disable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_counter_increment(struct sfc_adapter *sa,
-			  struct sfc_mae_counters *counters,
+			  struct sfc_mae_counter_records *counters,
 			  uint32_t mae_counter_id,
 			  uint32_t generation_count,
 			  uint64_t pkts, uint64_t bytes)
 {
-	struct sfc_mae_counter *p = &counters->mae_counters[mae_counter_id];
+	struct sfc_mae_counter_record *p =
+		&counters->mae_counters[mae_counter_id];
 	struct sfc_mae_counters_xstats *xstats = &counters->xstats;
 	union sfc_pkts_bytes cnt_val;
 	bool inuse;
@@ -667,7 +668,7 @@ sfc_mae_counter_thread_spawn(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counters_init(struct sfc_mae_counters *counters,
+sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 		      uint32_t nb_counters_max)
 {
 	int rc;
@@ -691,7 +692,7 @@ sfc_mae_counters_init(struct sfc_mae_counters *counters,
 }
 
 void
-sfc_mae_counters_fini(struct sfc_mae_counters *counters)
+sfc_mae_counters_fini(struct sfc_mae_counter_records *counters)
 {
 	rte_free(counters->mae_counters);
 	counters->mae_counters = NULL;
@@ -942,13 +943,13 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counters *counters,
-		    const struct sfc_mae_counter_id *counter,
+sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
 	uint64_t non_reset_tunnel_hit_counter;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
 	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 28d70f7d69..9c6d8103ac 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -38,15 +38,15 @@ void sfc_mae_counter_rxq_detach(struct sfc_adapter *sa);
 int sfc_mae_counter_rxq_init(struct sfc_adapter *sa);
 void sfc_mae_counter_rxq_fini(struct sfc_adapter *sa);
 
-int sfc_mae_counters_init(struct sfc_mae_counters *counters,
+int sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 			  uint32_t nb_counters_max);
-void sfc_mae_counters_fini(struct sfc_mae_counters *counters);
-int sfc_mae_counter_enable(struct sfc_adapter *sa,
-			   struct sfc_mae_counter_id *counterp);
-int sfc_mae_counter_disable(struct sfc_adapter *sa,
-			    struct sfc_mae_counter_id *counter);
-int sfc_mae_counter_get(struct sfc_mae_counters *counters,
-			const struct sfc_mae_counter_id *counter,
+void sfc_mae_counters_fini(struct sfc_mae_counter_records *counters);
+int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+				   struct sfc_mae_counter *counterp);
+int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				    struct sfc_mae_counter *counter);
+int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
 int sfc_mae_counter_start(struct sfc_adapter *sa);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 29/34] net/sfc: rework MAE action rule counter representation in SW
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (27 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
                     ` (4 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such rework is needed to prepare for INDIRECT action support
and in order to align with the latest HW support perspective.

Currently, the driver supports only one counter per flow. It
was once thought that MAE would support multiple counters in
one action set. That was partly envisaged in code and naming.
But HW support for the feature is no longer planned in EF100.

The code also assumes that a counter object cannot be shared.
This assumption is outdated. The driver may support this now
via action of type INDIRECT provided by generic flow library.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 342 +++++++++++++++++-------------
 drivers/net/sfc/sfc_mae.h         |  17 +-
 drivers/net/sfc/sfc_mae_counter.c |  22 +-
 3 files changed, 211 insertions(+), 170 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index eccd6727f2..e79d88265c 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
+	TAILQ_INIT(&mae->counters);
 	TAILQ_INIT(&mae->action_sets);
 	TAILQ_INIT(&mae->action_rules);
 
@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter *counters,
-			unsigned int n_counters,
-			efx_mae_actions_t *action_set_spec)
+sfc_mae_counter_add(struct sfc_adapter *sa,
+		    const struct sfc_mae_counter *counter_tmp,
+		    struct sfc_mae_counter **counterp)
 {
-	int rc;
+	struct sfc_mae_counter *counter;
+	struct sfc_mae *mae = &sa->mae;
 
-	sfc_log_init(sa, "entry");
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	if (n_counters == 0) {
-		sfc_log_init(sa, "no counters - skip");
-		return 0;
+	counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
+	if (counter == NULL)
+		return ENOMEM;
+
+	if (counter_tmp != NULL) {
+		counter->rte_id_valid = counter_tmp->rte_id_valid;
+		counter->rte_id = counter_tmp->rte_id;
 	}
 
-	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
+	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+	counter->refcnt = 1;
 
-	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
-	if (rc != 0) {
-		sfc_err(sa, "failed to enable MAE counter %u: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_counter_add;
-	}
+	TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
+	*counterp = counter;
 
-	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
-						   &counters[0].mae_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_fill_in_id;
-	}
+	sfc_dbg(sa, "added counter=%p", counter);
 
 	return 0;
+}
+
+static void
+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae *mae = &sa->mae;
 
-fail_fill_in_id:
-	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	if (counter == NULL)
+		return;
 
-fail_counter_add:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(counter->refcnt != 0);
+
+	--(counter->refcnt);
+
+	if (counter->refcnt != 0)
+		return;
+
+	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    counter->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
+			counter, counter->fw_rsrc.counter_id.id,
+			counter->fw_rsrc.refcnt);
+	}
+
+	TAILQ_REMOVE(&mae->counters, counter, entries);
+	rte_free(counter);
+
+	sfc_dbg(sa, "deleted counter=%p", counter);
 }
 
 static int
-sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter *counters,
-			 unsigned int n_counters)
+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
+		       efx_mae_actions_t *action_set_spec)
 {
-	if (n_counters == 0)
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
 		return 0;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
 
-	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
-		sfc_err(sa, "failed to disable: already disabled");
-		return EALREADY;
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
+
+		rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
+		if (rc != 0) {
+			sfc_err(sa, "failed to enable counter=%p: %s",
+				counter, rte_strerror(rc));
+			return rc;
+		}
+	}
+
+	if (action_set_spec != NULL) {
+		rc = efx_mae_action_set_fill_in_counter_id(
+					action_set_spec, &fw_rsrc->counter_id);
+		if (rc != 0) {
+			if (fw_rsrc->refcnt == 0) {
+				(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
+				fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+			}
+
+			sfc_err(sa, "cannot fill in counter ID: %s",
+				strerror(rc));
+			return rc;
+		}
+	}
+
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
+			counter, fw_rsrc->counter_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static void
+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
+			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		uint32_t counter_id = fw_rsrc->counter_id.id;
+
+		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
+				counter, counter_id);
+		} else {
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
+				counter, counter_id, strerror(rc));
+		}
+
+		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
 	}
 
-	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	--(fw_rsrc->refcnt);
 }
 
 struct sfc_mae_aset_ctx {
-	uint64_t			*ft_switch_hit_counter;
-	struct sfc_ft_ctx		*counter_ft_ctx;
 	struct sfc_mae_encap_header	*encap_header;
-	unsigned int			n_counters;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_mac_addr		*dst_mac;
 	struct sfc_mae_mac_addr		*src_mac;
 
@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	/*
-	 * Shared counters are not supported, hence, action
-	 * sets with counters are not attachable.
-	 */
-	if (ctx->n_counters != 0)
-		return NULL;
-
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
 		if (action_set->encap_header == ctx->encap_header &&
 		    action_set->dst_mac_addr == ctx->dst_mac &&
 		    action_set->src_mac_addr == ctx->src_mac &&
+		    action_set->counter == ctx->counter &&
 		    efx_mae_action_set_specs_equal(action_set->spec,
 						   ctx->spec)) {
 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
-		       const struct rte_flow_action actions[],
 		       const struct sfc_mae_aset_ctx *ctx,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
 	struct sfc_mae *mae = &sa->mae;
-	unsigned int i;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 		return ENOMEM;
 	}
 
-	if (ctx->n_counters > 0) {
-		const struct rte_flow_action *action;
-
-		action_set->counters = rte_malloc("sfc_mae_counter_ids",
-			sizeof(action_set->counters[0]) * ctx->n_counters, 0);
-		if (action_set->counters == NULL) {
-			rte_free(action_set);
-			sfc_err(sa, "failed to alloc counters");
-			return ENOMEM;
-		}
-
-		for (i = 0; i < ctx->n_counters; ++i) {
-			action_set->counters[i].rte_id_valid = B_FALSE;
-			action_set->counters[i].mae_id.id =
-				EFX_MAE_RSRC_ID_INVALID;
-
-			action_set->counters[i].ft_ctx = ctx->counter_ft_ctx;
-			action_set->counters[i].ft_switch_hit_counter =
-				ctx->ft_switch_hit_counter;
-		}
-
-		for (action = actions, i = 0;
-		     action->type != RTE_FLOW_ACTION_TYPE_END &&
-		     i < ctx->n_counters; ++action) {
-			const struct rte_flow_action_count *conf;
-
-			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
-				continue;
-
-			conf = action->conf;
-
-			action_set->counters[i].rte_id_valid = B_TRUE;
-			action_set->counters[i].rte_id = conf->id;
-			i++;
-		}
-		action_set->n_counters = ctx->n_counters;
-	}
-
 	action_set->refcnt = 1;
 	action_set->spec = ctx->spec;
 	action_set->encap_header = ctx->encap_header;
 	action_set->dst_mac_addr = ctx->dst_mac;
 	action_set->src_mac_addr = ctx->src_mac;
+	action_set->counter = ctx->counter;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
 	sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
-	if (action_set->n_counters > 0) {
-		SFC_ASSERT(action_set->n_counters == 1);
-		SFC_ASSERT(action_set->counters[0].mae_id.id ==
-			   EFX_MAE_RSRC_ID_INVALID);
-		rte_free(action_set->counters);
-	}
+	sfc_mae_counter_del(sa, action_set->counter);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 
@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter *counters;
+	struct sfc_mae_counter *counter;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	encap_header = action_set->encap_header;
 	dst_mac_addr = action_set->dst_mac_addr;
 	src_mac_addr = action_set->src_mac_addr;
-	counters = action_set->counters;
 	fw_rsrc = &action_set->fw_rsrc;
+	counter = action_set->counter;
 
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
-		if (action_set->n_counters > 0) {
+		if (counter != NULL) {
 			rc = sfc_mae_counter_start(sa);
 			if (rc != 0) {
 				sfc_err(sa, "failed to start MAE counters support: %s",
@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			}
 		}
 
-		rc = sfc_mae_counters_enable(sa, counters,
-					     action_set->n_counters,
-					     action_set->spec);
+		rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
 		if (rc != 0) {
-			sfc_err(sa, "failed to enable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			sfc_err(sa, "failed to enable action_set=%p: %s",
 				action_set, strerror(rc));
 
-			(void)sfc_mae_counters_disable(sa, counters,
-						       action_set->n_counters);
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+			sfc_mae_counter_disable(sa, counter);
 			return rc;
 		}
 
@@ -1162,16 +1190,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 		}
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-		rc = sfc_mae_counters_disable(sa, action_set->counters,
-					      action_set->n_counters);
-		if (rc != 0) {
-			sfc_err(sa, "failed to disable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-		}
-
 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
 		sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
 		sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
+		sfc_mae_counter_disable(sa, action_set->counter);
 	}
 
 	--(fw_rsrc->refcnt);
@@ -3931,10 +3953,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
-				const struct rte_flow_action_count *conf
-					__rte_unused,
+				const struct rte_flow_action_count *conf,
+				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
+	struct sfc_mae_counter counter_tmp = {};
 	int rc;
 
 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
@@ -3949,17 +3972,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		goto fail_no_service_core;
 	}
 
-	rc = efx_mae_action_set_populate_count(spec);
-	if (rc != 0) {
-		sfc_err(sa,
-			"failed to populate counters in MAE action set: %s",
-			rte_strerror(rc));
-		goto fail_populate_count;
+	if (*counterp != NULL) {
+		sfc_err(sa, "cannot request more than 1 action COUNT per flow");
+		rc = EINVAL;
+		goto fail_more_than_one;
+	}
+
+	if (spec != NULL) {
+		rc = efx_mae_action_set_populate_count(spec);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to populate counters in MAE action set: %s",
+				rte_strerror(rc));
+			goto fail_populate_count;
+		}
+	}
+
+	if (conf != NULL) {
+		counter_tmp.rte_id_valid = true;
+		counter_tmp.rte_id = conf->id;
 	}
 
+	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
+
 	return 0;
 
 fail_populate_count:
+fail_more_than_one:
 fail_no_service_core:
 fail_counter_queue_uninit:
 
@@ -4126,7 +4165,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
+	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
+	efx_mae_actions_t *spec_ptr = spec;
 	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -4214,7 +4255,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
-		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
+		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
@@ -4364,19 +4406,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
-	for (action = actions;
-	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
-			++(ctx.n_counters);
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		bool have_user_action_count = false;
+
 		/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
 		rc = efx_mae_action_set_populate_decap(ctx.spec);
 		if (rc != 0)
 			goto fail_enforce_ft_decap;
 
-		if (ctx.n_counters == 0 &&
+		for (action = actions;
+		     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+			if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+				have_user_action_count = true;
+				break;
+			}
+		}
+
+		if (!have_user_action_count &&
 		    sfc_mae_counter_stream_enabled(sa)) {
 			/*
 			 * The user opted not to use action COUNT in this rule,
@@ -4388,7 +4434,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			if (rc != 0)
 				goto fail_enforce_ft_count;
 
-			ctx.n_counters = 1;
+			rc = sfc_mae_counter_add(sa, NULL, &ctx.counter);
+			if (rc != 0)
+				goto fail_enforce_ft_count;
 		}
 	}
 
@@ -4418,13 +4466,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_encap_header;
 
-	if (ctx.n_counters > 1) {
-		rc = ENOTSUP;
-		sfc_err(sa, "too many count actions requested: %u",
-			ctx.n_counters);
-		goto fail_nb_count;
-	}
-
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
@@ -4434,7 +4475,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_workaround_tunnel_delivery;
 
-		ctx.counter_ft_ctx = spec_mae->ft_ctx;
+		if (ctx.counter != NULL)
+			(ctx.counter)->ft_ctx = spec_mae->ft_ctx;
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
@@ -4443,7 +4485,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		ctx.ft_switch_hit_counter =
+		(ctx.counter)->ft_switch_hit_counter =
 			&spec_mae->ft_ctx->switch_hit_counter;
 		break;
 	default:
@@ -4467,6 +4509,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
 	if (action_rule_ctx->action_set != NULL) {
+		sfc_mae_counter_del(sa, ctx.counter);
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -4474,8 +4517,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx,
-				    &action_rule_ctx->action_set);
+	rc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -4484,11 +4526,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 fail_action_set_add:
 fail_check_fate_action:
 fail_workaround_tunnel_delivery:
-fail_nb_count:
 	sfc_mae_encap_header_del(sa, ctx.encap_header);
 
 fail_process_encap_header:
 fail_rule_parse_action:
+	sfc_mae_counter_del(sa, ctx.counter);
 	sfc_mae_mac_addr_del(sa, ctx.src_mac);
 	sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 	efx_mae_action_set_spec_fini(sa->nic, ctx.spec);
@@ -4768,28 +4810,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
 	struct sfc_mae_action_set *action_set;
-	unsigned int i;
+	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
 	action_set = action_rule->action_set;
+	counter = action_set->counter;
 
-	for (i = 0; i < action_set->n_counters; i++) {
-		/*
-		 * Get the first available counter of the flow rule if
-		 * counter ID is not specified, provided that this
-		 * counter is not an automatic (implicit) one.
-		 */
-		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
-			continue;
-
+	if (conf == NULL ||
+	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 &action_set->counters[i], data);
+					 counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 7337fcf14d..c73ce0a5e6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	unsigned int			refcnt;
 	RTE_STD_C11
 	union {
+		efx_counter_t		counter_id;
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
 		efx_mae_mac_id_t	mac_id;
@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {
 
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
-/* Counter ID */
+/* Counter object registry entry */
 struct sfc_mae_counter {
-	/* ID of a counter in MAE */
-	efx_counter_t			mae_id;
+	TAILQ_ENTRY(sfc_mae_counter)	entries;
+	unsigned int			refcnt;
+
 	/* ID of a counter in RTE */
 	uint32_t			rte_id;
 	/* RTE counter ID validity status */
@@ -80,18 +82,21 @@ struct sfc_mae_counter {
 	uint64_t			*ft_switch_hit_counter;
 	/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */
 	struct sfc_ft_ctx		*ft_ctx;
+
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter		*counters;
-	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_mac_addr		*dst_mac_addr;
 	struct sfc_mae_mac_addr		*src_mac_addr;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -221,6 +226,8 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
+	/** Counter object registry */
+	struct sfc_mae_counters		counters;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 8170175991..90b89e81c6 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 		goto fail_counter_id_range;
 	}
 
-	counterp->mae_id = mae_counter;
+	counterp->fw_rsrc.counter_id.id = mae_counter.id;
 
 	p = &counters->mae_counters[mae_counter.id];
 
@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
 	struct sfc_mae_counter_records *counters = &reg->counters;
+	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
-	if (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)
-		return 0;
-
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
+	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
 	 * at the beginning of delete operation. Release ordering is
 	 * paired with acquire ordering on load in counter increment operation.
 	 */
-	p = &counters->mae_counters[counter->mae_id.id];
+	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);
+	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
 	if (rc != 0)
 		sfc_err(sa, "failed to free MAE counter %u: %s",
-			counter->mae_id.id, rte_strerror(rc));
+			mae_counter->id, rte_strerror(rc));
 
 	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, counter->mae_id.id,
+		 " bytes=%" PRIu64, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	 * If there's some error, the resulting resource leakage is bad, but
 	 * nothing sensible can be done in this case.
 	 */
-	counter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;
+	mae_counter->id = EFX_MAE_RSRC_ID_INVALID;
 
 	return rc;
 }
@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
-	p = &counters->mae_counters[counter->mae_id.id];
+	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
+	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
 
 	/*
 	 * Ordering is relaxed since it is the only operation on counter value.
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 30/34] net/sfc: support indirect count action in transfer flows
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (28 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
                     ` (3 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Indirect count action is useful to applications that
need to gather aggregated statistics for many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst            |   2 +
 doc/guides/rel_notes/release_23_07.rst |   3 +
 drivers/net/sfc/sfc.h                  |   1 +
 drivers/net/sfc/sfc_flow.c             | 126 +++++++++++++++++++
 drivers/net/sfc/sfc_flow.h             |  14 +++
 drivers/net/sfc/sfc_mae.c              | 167 ++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h              |  15 +++
 7 files changed, 327 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 6e974c3720..ba82b02093 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -306,6 +306,8 @@ Supported actions (***transfer*** rules):
 
 - COUNT
 
+- INDIRECT
+
 - DROP
 
 Validating flow rules depends on the firmware variant.
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index 058897219e..4feffaff40 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -98,6 +98,9 @@ New Features
     The caller is responsible to request this offload
     only when the target header is an IPv4-based one.
 
+  * Added support for transfer flow action INDIRECT
+    with subtype COUNT, for aggregated statistics.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 6b301aad60..f84a21009e 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -248,6 +248,7 @@ struct sfc_adapter {
 	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
+	struct sfc_flow_indir_actions	flow_indir_actions;
 	struct sfc_flow_list		flow_list;
 
 	unsigned int			rxq_max;
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 0abeabfbf2..a35f20770d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static struct rte_flow_action_handle *
+sfc_flow_action_handle_create(struct rte_eth_dev *dev,
+			      const struct rte_flow_indir_action_conf *conf,
+			      const struct rte_flow_action *action,
+			      struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *handle;
+	int ret;
+
+	if (!conf->transfer) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "non-transfer domain does not support indirect actions");
+		return NULL;
+	}
+
+	if (conf->ingress || conf->egress) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "cannot combine ingress/egress with transfer");
+		return NULL;
+	}
+
+	handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0);
+	if (handle == NULL) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "failed to allocate memory");
+		return NULL;
+	}
+
+	sfc_adapter_lock(sa);
+
+	ret = sfc_mae_indir_action_create(sa, action, handle, error);
+	if (ret != 0) {
+		sfc_adapter_unlock(sa);
+		rte_free(handle);
+		return NULL;
+	}
+
+	TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);
+
+	handle->transfer = (bool)conf->transfer;
+
+	sfc_adapter_unlock(sa);
+
+	return handle;
+}
+
+static int
+sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,
+			       struct rte_flow_action_handle *handle,
+			       struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_destroy(sa, handle,
+							  error);
+			if (rc != 0)
+				goto exit;
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);
+		rte_free(entry);
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
+static int
+sfc_flow_action_handle_query(struct rte_eth_dev *dev,
+			     const struct rte_flow_action_handle *handle,
+			     void *data, struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_query(sa, handle,
+							data, error);
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
 const struct rte_flow_ops sfc_flow_ops = {
 	.validate = sfc_flow_validate,
 	.create = sfc_flow_create,
@@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = {
 	.flush = sfc_flow_flush,
 	.query = sfc_flow_query,
 	.isolate = sfc_flow_isolate,
+	.action_handle_create = sfc_flow_action_handle_create,
+	.action_handle_destroy = sfc_flow_action_handle_destroy,
+	.action_handle_query = sfc_flow_action_handle_query,
 	.tunnel_decap_set = sfc_ft_decap_set,
 	.tunnel_match = sfc_ft_match,
 	.tunnel_action_decap_release = sfc_ft_action_decap_release,
@@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa)
 {
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	TAILQ_INIT(&sa->flow_indir_actions);
 	TAILQ_INIT(&sa->flow_list);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 8f706fc589..af94d0654a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -88,6 +88,20 @@ struct sfc_flow_spec_mae {
 	sfc_mae_conntrack_key_t		ct_key;
 };
 
+/* PMD-specific definition of the opaque type from rte_flow.h */
+struct rte_flow_action_handle {
+	TAILQ_ENTRY(rte_flow_action_handle)	entries;
+
+	bool					transfer;
+	enum rte_flow_action_type		type;
+
+	union {
+		struct sfc_mae_counter		*counter;
+	};
+};
+
+TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle);
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e79d88265c..72646afe4d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -4005,6 +4005,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa,
+				   const struct rte_flow_action_handle *handle,
+				   enum sfc_ft_rule_type ft_rule_type,
+				   struct sfc_mae_aset_ctx *ctx,
+				   struct rte_flow_error *error)
+{
+	struct rte_flow_action_handle *entry;
+	int rc;
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry == handle) {
+			sfc_dbg(sa, "attaching to indirect_action=%p", entry);
+
+			switch (entry->type) {
+			case RTE_FLOW_ACTION_TYPE_COUNT:
+				if (ft_rule_type != SFC_FT_RULE_NONE) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot use indirect count action in tunnel model");
+				}
+
+				if (ctx->counter != NULL) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot have multiple actions COUNT in one flow");
+				}
+
+				rc = efx_mae_action_set_populate_count(ctx->spec);
+				if (rc != 0) {
+					return rte_flow_error_set(error, rc,
+					 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					 "failed to add COUNT to MAE action set");
+				}
+
+				ctx->counter = entry->counter;
+				++(ctx->counter->refcnt);
+				break;
+			default:
+				SFC_ASSERT(B_FALSE);
+				break;
+			}
+
+			return 0;
+		}
+	}
+
+	return rte_flow_error_set(error, ENOENT,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				  "indirect action handle not found");
+}
+
 static int
 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
 				const struct rte_flow_action_vf *vf_conf,
@@ -4143,6 +4195,7 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
 	[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
 	[RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT",
+	[RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT",
 	[RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
 	[RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
 	[RTE_FLOW_ACTION_TYPE_PF] = "PF",
@@ -4258,6 +4311,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
 						     counterp, spec_ptr);
 		break;
+	case RTE_FLOW_ACTION_TYPE_INDIRECT:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_indirect(sa, action->conf,
+							spec_mae->ft_rule_type,
+							ctx, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -4813,7 +4874,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
+	if (action_rule == NULL || action_rule->action_set == NULL ||
+	    action_rule->action_set->counter == NULL ||
+	    action_rule->action_set->counter->indirect) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
@@ -4924,3 +4987,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
+
+int
+sfc_mae_indir_action_create(struct sfc_adapter *sa,
+			    const struct rte_flow_action *action,
+			    struct rte_flow_action_handle *handle,
+			    struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      &handle->counter, NULL);
+		if (ret == 0)
+			handle->counter->indirect = true;
+		break;
+	default:
+		ret = ENOTSUP;
+	}
+
+	if (ret != 0) {
+		return rte_flow_error_set(error, ret,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"failed to parse indirect action to mae object");
+	}
+
+	handle->type = action->type;
+
+	return 0;
+}
+
+int
+sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+			     const struct rte_flow_action_handle *handle,
+			     struct rte_flow_error *error)
+{
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		if (handle->counter->refcnt != 1)
+			goto fail;
+
+		sfc_mae_counter_del(sa, handle->counter);
+		break;
+	default:
+		SFC_ASSERT(B_FALSE);
+		break;
+	}
+
+	return 0;
+
+fail:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is still in use");
+}
+
+int
+sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			   const struct rte_flow_action_handle *handle,
+			   void *data, struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		SFC_ASSERT(handle->counter != NULL);
+
+		if (handle->counter->fw_rsrc.refcnt == 0)
+			goto fail_not_in_use;
+
+		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
+					  handle->counter, data);
+		if (ret != 0)
+			goto fail_counter_get;
+
+		break;
+	default:
+		goto fail_unsup;
+	}
+
+	return 0;
+
+fail_not_in_use:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is not in use");
+
+fail_counter_get:
+	return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "failed to collect indirect action COUNT data");
+
+fail_unsup:
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action of this type cannot be queried");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index c73ce0a5e6..e7b7d3a35e 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -84,6 +84,8 @@ struct sfc_mae_counter {
 	struct sfc_ft_ctx		*ft_ctx;
 
 	struct sfc_mae_fw_rsrc		fw_rsrc;
+
+	bool				indirect;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
+int sfc_mae_indir_action_create(struct sfc_adapter *sa,
+				const struct rte_flow_action *action,
+				struct rte_flow_action_handle *handle,
+				struct rte_flow_error *error);
+
+int sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+				 const struct rte_flow_action_handle *handle,
+				 struct rte_flow_error *error);
+
+int sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			       const struct rte_flow_action_handle *handle,
+			       void *data, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.31.1


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (29 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
                     ` (2 subsequent siblings)
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is required to disambiguate counters of different
types supported by the match-action engine (MAE) on EF100.

Currently, the code only supports action rule counters,
but MAE may also support conntrack assistance counters.
Add type-aware allocate and free MCDI handlers and
extend reporting of counter limits accordingly.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  39 +++++++-
 drivers/common/sfc_efx/base/efx_impl.h |   2 +-
 drivers/common/sfc_efx/base/efx_mae.c  | 120 ++++++++++++++++++++-----
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 140 insertions(+), 23 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index abde5fea2e..10908d97ef 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,7 +4191,10 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
 	uint32_t			eml_encap_header_size_limit;
-	uint32_t			eml_max_n_counters;
+	union {
+		uint32_t		eml_max_n_counters;
+		uint32_t		eml_max_n_action_counters;
+	};
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4780,6 +4783,14 @@ efx_mae_action_set_fill_in_eh_id(
 	__in				efx_mae_actions_t *spec,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/*
+ * Counter types that may be supported by the match-action engine.
+ * Each counter type maintains its own counter ID namespace in FW.
+ */
+typedef enum efx_counter_type_e {
+	EFX_COUNTER_TYPE_ACTION = 0,
+} efx_counter_type_t;
+
 typedef struct efx_counter_s {
 	uint32_t id;
 } efx_counter_t;
@@ -4823,6 +4834,8 @@ efx_mae_action_set_alloc(
 	__out				efx_mae_aset_id_t *aset_idp);
 
 /*
+ * Allocates MAE counter(s) of type EFX_COUNTER_TYPE_ACTION.
+ *
  * Generation count has two purposes:
  *
  * 1) Distinguish between counter packets that belong to freed counter
@@ -4846,6 +4859,20 @@ efx_mae_counters_alloc(
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+/*
+ * Allocates MAE counter(s) of the specified type. Other
+ * than that, behaves like efx_mae_counters_alloc().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_alloc_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_counters_free(
@@ -4855,6 +4882,16 @@ efx_mae_counters_free(
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 /* When set, include counters with a value of zero */
 #define	EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE	(1U << 0)
 
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index f9d60b9eb9..7e5701e801 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -841,7 +841,7 @@ typedef struct efx_mae_s {
 	/** Outer rule match field capabilities. */
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
-	uint32_t			em_max_ncounters;
+	uint32_t			em_max_n_action_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 154d2f1942..eddba0e71c 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -67,8 +67,8 @@ efx_mae_get_capabilities(
 	maep->em_max_nfields =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
 
-	maep->em_max_ncounters =
-	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS);
+	maep->em_max_n_action_counters =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
 	return (0);
 
@@ -374,7 +374,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
-	emlp->eml_max_n_counters = maep->em_max_ncounters;
+	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
 
 	return (0);
 
@@ -3263,55 +3263,70 @@ efx_mae_action_set_clear_fw_rsrc_ids(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_alloc(
+efx_mae_counters_alloc_type(
 	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
 	__in				uint32_t n_counters,
 	__out				uint32_t *n_allocatedp,
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_ALLOC_IN_LEN,
+	    MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	uint32_t n_allocated;
 	efx_mcdi_req_t req;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (n_counters > max_n_counters ||
 	    n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
 	    n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
 		rc = EINVAL;
-		goto fail1;
+		goto fail2;
 	}
 
 	req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
 
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
 	    n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_allocated = MCDI_OUT_DWORD(req,
 	    MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
 	if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	for (i = 0; i < n_allocated; i++) {
@@ -3328,6 +3343,8 @@ efx_mae_counters_alloc(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3341,33 +3358,67 @@ efx_mae_counters_alloc(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_free(
+efx_mae_counters_alloc(
 	__in				efx_nic_t *enp,
 	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
+					 n_counters, n_allocatedp,
+					 countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
 	__out				uint32_t *n_freedp,
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	efx_mcdi_req_t req;
 	uint32_t n_freed;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
-	    n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM ||
-	    n_counters >
-	    MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
 		rc = EINVAL;
 		goto fail1;
 	}
 
+	if (n_counters > max_n_counters ||
+	    n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
+	    n_counters >
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
 	req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters);
+	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
 
@@ -3378,23 +3429,25 @@ efx_mae_counters_free(
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
 			  n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
 
 	if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	if (gen_countp != NULL) {
@@ -3406,6 +3459,8 @@ efx_mae_counters_free(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3418,6 +3473,29 @@ efx_mae_counters_free(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_counters_free(
+	__in				efx_nic_t *enp,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
+					n_counters, n_freedp,
+					countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_counters_stream_start(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index f601110f84..e91bcbcad8 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -114,7 +114,9 @@ INTERNAL {
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
 	efx_mae_counters_alloc;
+	efx_mae_counters_alloc_type;
 	efx_mae_counters_free;
+	efx_mae_counters_free_type;
 	efx_mae_counters_stream_give_credits;
 	efx_mae_counters_stream_start;
 	efx_mae_counters_stream_stop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 32/34] net/sfc: indicate MAE counter type in use for transfer flows
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (30 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so assists adding support for additional counter types.

Current implementation is only aware of action rule counters
that are supported by the match-action engine (MAE) on EF100
NICs, but MAE may also support conntrack assistance counters.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 56 ++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |  7 ++-
 drivers/net/sfc/sfc_mae_counter.c | 77 +++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae_counter.h |  2 +-
 4 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 72646afe4d..e9d1cb26b3 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,15 +65,24 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_counters_max)
+			      uint32_t nb_action_counters_max)
 {
-	return sfc_mae_counters_init(&registry->counters, nb_counters_max);
+	int ret;
+
+	ret = sfc_mae_counters_init(&registry->action_counters,
+				    nb_action_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
+
+	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
-	sfc_mae_counters_fini(&registry->counters);
+	sfc_mae_counters_fini(&registry->action_counters);
 }
 
 struct rte_flow *
@@ -153,10 +162,10 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-						   limits.eml_max_n_counters);
+					limits.eml_max_n_action_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init MAE counters registry for %u entries: %s",
-				limits.eml_max_n_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
+				limits.eml_max_n_action_counters, rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -833,6 +842,9 @@ sfc_mae_counter_add(struct sfc_adapter *sa,
 	if (counter_tmp != NULL) {
 		counter->rte_id_valid = counter_tmp->rte_id_valid;
 		counter->rte_id = counter_tmp->rte_id;
+		counter->type = counter_tmp->type;
+	} else {
+		counter->type = EFX_COUNTER_TYPE_ACTION;
 	}
 
 	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -864,8 +876,8 @@ sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
 	    counter->fw_rsrc.refcnt != 0) {
-		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
-			counter, counter->fw_rsrc.counter_id.id,
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, counter->fw_rsrc.counter_id.id,
 			counter->fw_rsrc.refcnt);
 	}
 
@@ -916,8 +928,8 @@ sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
 	}
 
 	if (fw_rsrc->refcnt == 0) {
-		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
-			counter, fw_rsrc->counter_id.id);
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%x-#%u",
+			counter, counter->type, fw_rsrc->counter_id.id);
 	}
 
 	++(fw_rsrc->refcnt);
@@ -940,8 +952,8 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
-		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
-			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
 		return;
 	}
 
@@ -950,11 +962,11 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
 		if (rc == 0) {
-			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
-				counter, counter_id);
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%x-#%u",
+				counter, counter->type, counter_id);
 		} else {
-			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
-				counter, counter_id, strerror(rc));
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%x-#%u: %s",
+				counter, counter->type, counter_id, strerror(rc));
 		}
 
 		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -3954,6 +3966,7 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 				const struct rte_flow_action_count *conf,
+				efx_counter_type_t mae_counter_type,
 				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
@@ -3993,6 +4006,8 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		counter_tmp.rte_id = conf->id;
 	}
 
+	counter_tmp.type = mae_counter_type;
+
 	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
 
 	return 0;
@@ -4217,6 +4232,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
+	efx_counter_type_t mae_counter_type = EFX_COUNTER_TYPE_ACTION;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4309,6 +4325,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     mae_counter_type,
 						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_INDIRECT:
@@ -4887,8 +4904,7 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 
 	if (conf == NULL ||
 	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 counter, data);
+		rc = sfc_mae_counter_get(sa, counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5002,6 +5018,7 @@ sfc_mae_indir_action_create(struct sfc_adapter *sa,
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      EFX_COUNTER_TYPE_ACTION,
 						      &handle->counter, NULL);
 		if (ret == 0)
 			handle->counter->indirect = true;
@@ -5065,8 +5082,7 @@ sfc_mae_indir_action_query(struct sfc_adapter *sa,
 		if (handle->counter->fw_rsrc.refcnt == 0)
 			goto fail_not_in_use;
 
-		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					  handle->counter, data);
+		ret = sfc_mae_counter_get(sa, handle->counter, data);
 		if (ret != 0)
 			goto fail_counter_get;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index e7b7d3a35e..3a3a5225fd 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -86,6 +86,7 @@ struct sfc_mae_counter {
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 
 	bool				indirect;
+	efx_counter_type_t		type;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -157,6 +158,8 @@ struct sfc_mae_counter_records {
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
 	unsigned int			n_mae_counters;
+	/** Counter type, for logging */
+	efx_counter_type_t		type;
 };
 
 /** Options for MAE counter polling mode */
@@ -168,8 +171,8 @@ enum sfc_mae_counter_polling_mode {
 
 struct sfc_mae_counter_registry {
 	/* Common counter information */
-	/** Counters collection */
-	struct sfc_mae_counter_records	counters;
+	/** Action rule counter record collection */
+	struct sfc_mae_counter_records	action_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 90b89e81c6..47448cba15 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -80,19 +80,28 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
 	int rc;
 
+	switch (counterp->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail_counter_type_check;
+	}
+
 	/*
 	 * The actual count of counters allocated is ignored since a failure
 	 * to allocate a single counter is indicated by non-zero return code.
 	 */
-	rc = efx_mae_counters_alloc(sa->nic, 1, &unused, &mae_counter,
-				    &generation_count);
+	rc = efx_mae_counters_alloc_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, &generation_count);
 	if (rc != 0) {
 		sfc_err(sa, "failed to alloc MAE counter: %s",
 			rte_strerror(rc));
@@ -132,16 +141,18 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	 */
 	__atomic_store_n(&p->inuse, true, __ATOMIC_RELEASE);
 
-	sfc_info(sa, "enabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter.id,
+	sfc_info(sa, "enabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counterp->type, mae_counter.id,
 		 p->reset.pkts, p->reset.bytes);
 
 	return 0;
 
 fail_counter_id_range:
-	(void)efx_mae_counters_free(sa->nic, 1, &unused, &mae_counter, NULL);
+	(void)efx_mae_counters_free_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, NULL);
 
 fail_mae_counter_alloc:
+fail_counter_type_check:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -151,12 +162,20 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
 	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		return EINVAL;
+	}
+
 	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
@@ -166,13 +185,14 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
+	rc = efx_mae_counters_free_type(sa->nic, counter->type, 1, &unused,
+					mae_counter, NULL);
 	if (rc != 0)
-		sfc_err(sa, "failed to free MAE counter %u: %s",
-			mae_counter->id, rte_strerror(rc));
+		sfc_err(sa, "failed to free MAE counter 0x%x-#%u: %s",
+			counter->type, mae_counter->id, rte_strerror(rc));
 
-	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter->id,
+	sfc_info(sa, "disabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counter->type, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -243,8 +263,8 @@ sfc_mae_counter_increment(struct sfc_adapter *sa,
 				 __ATOMIC_RELAXED);
 	}
 
-	sfc_info(sa, "update MAE counter #%u: pkts+%" PRIu64 "=%" PRIu64
-		 ", bytes+%" PRIu64 "=%" PRIu64, mae_counter_id,
+	sfc_info(sa, "update MAE counter 0x%x-#%u: pkts+%" PRIu64 "=%" PRIu64
+		 ", bytes+%" PRIu64 "=%" PRIu64, counters->type, mae_counter_id,
 		 pkts, cnt_val.pkts, bytes, cnt_val.bytes);
 }
 
@@ -253,6 +273,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			     struct sfc_mae_counter_registry *counter_registry,
 			     const struct rte_mbuf *m)
 {
+	struct sfc_mae_counter_records *counters;
 	uint32_t generation_count;
 	const efx_xword_t *hdr;
 	const efx_oword_t *counters_data;
@@ -293,7 +314,12 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	}
 
 	id = EFX_XWORD_FIELD(*hdr, ERF_SC_PACKETISER_HEADER_IDENTIFIER);
-	if (unlikely(id != ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR)) {
+
+	switch (id) {
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
+		counters = &counter_registry->action_counters;
+		break;
+	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
 	}
@@ -367,7 +393,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
 		sfc_mae_counter_increment(sa,
-			&counter_registry->counters,
+			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX),
 			generation_count,
@@ -941,14 +967,25 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+sfc_mae_counter_get(struct sfc_adapter *sa,
 		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
+	struct sfc_mae_counter_records *counters;
 	uint64_t non_reset_tunnel_hit_counter;
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
+	bool need_byte_count;
+
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &sa->mae.counter_registry.action_counters;
+		need_byte_count = true;
+		break;
+	default:
+		return EINVAL;
+	}
 
 	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
 	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
@@ -968,7 +1005,7 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 		data->hits += ft_ctx->switch_hit_counter;
 		non_reset_tunnel_hit_counter = data->hits;
 		data->hits -= ft_ctx->reset_tunnel_hit_counter;
-	} else {
+	} else if (need_byte_count) {
 		data->bytes_set = 1;
 		data->bytes = value.bytes - p->reset.bytes;
 	}
@@ -979,7 +1016,9 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 				non_reset_tunnel_hit_counter;
 		} else {
 			p->reset.pkts = value.pkts;
-			p->reset.bytes = value.bytes;
+
+			if (need_byte_count)
+				p->reset.bytes = value.bytes;
 		}
 	}
 
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 9c6d8103ac..effb037799 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -45,7 +45,7 @@ int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 				   struct sfc_mae_counter *counterp);
 int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				    struct sfc_mae_counter *counter);
-int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+int sfc_mae_counter_get(struct sfc_adapter *sa,
 			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 33/34] common/sfc_efx/base: support conntrack assistance counters
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (31 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  2023-06-04  0:00   ` [PATCH v2 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Counters that can be referenced by HW conntrack assistance
table work similar to those of the action rules. However,
their IDs belong to a separate (CT-specific) namespace.

These are 1-bit saturating counters with no byte count.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  2 ++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 35 +++++++++++++++++++++++---
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 10908d97ef..0534179381 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4195,6 +4195,7 @@ typedef struct efx_mae_limits_s {
 		uint32_t		eml_max_n_counters;
 		uint32_t		eml_max_n_action_counters;
 	};
+	uint32_t			eml_max_n_conntrack_counters;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4789,6 +4790,7 @@ efx_mae_action_set_fill_in_eh_id(
  */
 typedef enum efx_counter_type_e {
 	EFX_COUNTER_TYPE_ACTION = 0,
+	EFX_COUNTER_TYPE_CONNTRACK,
 } efx_counter_type_t;
 
 typedef struct efx_counter_s {
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 7e5701e801..09b1e95c59 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -842,6 +842,7 @@ typedef struct efx_mae_s {
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
 	uint32_t			em_max_n_action_counters;
+	uint32_t			em_max_n_conntrack_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index eddba0e71c..9ff887e04b 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -16,7 +16,7 @@ efx_mae_get_capabilities(
 	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload,
 	    MC_CMD_MAE_GET_CAPS_IN_LEN,
-	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	    MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
 	struct efx_mae_s *maep = enp->en_maep;
 	efx_rc_t rc;
 
@@ -24,7 +24,7 @@ efx_mae_get_capabilities(
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
 	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_MAE_GET_CAPS_OUT_LEN;
+	req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
 
 	efx_mcdi_execute(enp, &req);
 
@@ -70,6 +70,13 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_counters =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
+	if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
+		maep->em_max_n_conntrack_counters =
+		    MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
+	} else {
+		maep->em_max_n_conntrack_counters = 0;
+	}
+
 	return (0);
 
 fail2:
@@ -375,6 +382,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
+	emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
 
 	return (0);
 
@@ -3282,11 +3290,15 @@ efx_mae_counters_alloc_type(
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
 
 	switch (type) {
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3403,6 +3415,9 @@ efx_mae_counters_free_type(
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3505,8 +3520,11 @@ efx_mae_counters_stream_start(
 	__out				uint32_t *flags_out)
 {
 	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN,
+	EFX_MCDI_DECLARE_BUF(payload,
+			     MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
 			     MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	uint32_t counter_types;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
@@ -3517,7 +3535,7 @@ efx_mae_counters_stream_start(
 
 	req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
 
@@ -3526,6 +3544,15 @@ efx_mae_counters_stream_start(
 			 packet_size);
 	MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
 
+	counter_types = (1U << MAE_COUNTER_TYPE_AR);
+
+	if (maep->em_max_n_conntrack_counters != 0)
+		counter_types |= (1U << MAE_COUNTER_TYPE_CT);
+
+	MCDI_IN_SET_DWORD(req,
+			  MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
+			  counter_types);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v2 34/34] net/sfc: use conntrack assistance counters in transfer flows
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (32 preceding siblings ...)
  2023-06-04  0:00   ` [PATCH v2 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
@ 2023-06-04  0:00   ` Ivan Malov
  33 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04  0:00 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

These are 1-bit saturating counters which can only be useful
to tell whether a given flow rule has offloaded some packets
since the last query. Byte count is never provided for these.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h        |   2 +
 drivers/net/sfc/sfc_mae.c         | 119 ++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |   2 +
 drivers/net/sfc/sfc_mae_counter.c |  30 ++++++++
 4 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index af94d0654a..601f93e540 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -86,6 +86,8 @@ struct sfc_flow_spec_mae {
 	/* Conntrack (CT) assistance table entry key and response */
 	sfc_mae_conntrack_response_t	ct_resp;
 	sfc_mae_conntrack_key_t		ct_key;
+	/* Conntrack (CT) assistance counter */
+	struct sfc_mae_counter		*ct_counter;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e9d1cb26b3..a3131c244d 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,7 +65,8 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_action_counters_max)
+			      uint32_t nb_action_counters_max,
+			      uint32_t nb_conntrack_counters_max)
 {
 	int ret;
 
@@ -76,12 +77,20 @@ sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
 
 	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
 
+	ret = sfc_mae_counters_init(&registry->conntrack_counters,
+				    nb_conntrack_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
+
 	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
+	sfc_mae_counters_fini(&registry->conntrack_counters);
 	sfc_mae_counters_fini(&registry->action_counters);
 }
 
@@ -162,10 +171,13 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-					limits.eml_max_n_action_counters);
+					limits.eml_max_n_action_counters,
+					limits.eml_max_n_conntrack_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
-				limits.eml_max_n_action_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR and %u CT counters: %s",
+				limits.eml_max_n_action_counters,
+				limits.eml_max_n_conntrack_counters,
+				rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -1473,6 +1485,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 	}
 
 	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
+
+	sfc_mae_counter_del(sa, spec_mae->ct_counter);
 }
 
 static int
@@ -4225,7 +4239,7 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  struct rte_flow *flow,
+			  struct rte_flow *flow, bool ct,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
@@ -4241,6 +4255,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
+	if (ct) {
+		mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
+		counterp = &spec_mae->ct_counter;
+		spec_ptr = NULL;
+	}
+
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
@@ -4528,7 +4548,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, flow,
+		rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
@@ -4563,8 +4583,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		(ctx.counter)->ft_switch_hit_counter =
-			&spec_mae->ft_ctx->switch_hit_counter;
+		if (ctx.counter != NULL) {
+			(ctx.counter)->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		} else if (sfc_mae_counter_stream_enabled(sa)) {
+			SFC_ASSERT(ct);
+
+			spec_mae->ct_counter->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		}
 		break;
 	default:
 		SFC_ASSERT(B_FALSE);
@@ -4845,12 +4872,34 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 		return rc;
 
 	if (spec_mae->action_rule->ct_mark != 0) {
+		struct sfc_mae_counter *counter = spec_mae->ct_counter;
+
+		rc = sfc_mae_counter_enable(sa, counter, NULL);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+
+		if (counter != NULL) {
+			struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
+
+			spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
+
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_mae_action_rule_disable(sa, action_rule);
+				return rc;
+			}
+		} else {
+			spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+		}
+
 		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
-		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
 
 		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
 					      &spec_mae->ct_resp);
 		if (rc != 0) {
+			sfc_mae_counter_disable(sa, counter);
 			sfc_mae_action_rule_disable(sa, action_rule);
 			return rc;
 		}
@@ -4873,6 +4922,8 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule->ct_mark != 0)
 		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
 
+	sfc_mae_counter_disable(sa, spec_mae->ct_counter);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
@@ -4887,31 +4938,41 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 {
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
-	struct sfc_mae_action_set *action_set;
-	struct sfc_mae_counter *counter;
+	struct sfc_mae_counter *counters[1 /* action rule counter */ +
+					 1 /* conntrack counter */];
+	unsigned int i;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set == NULL ||
-	    action_rule->action_set->counter == NULL ||
-	    action_rule->action_set->counter->indirect) {
-		return rte_flow_error_set(error, EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION, action,
-			"Queried flow rule does not have count actions");
-	}
+	/*
+	 * The check for counter unavailability is done based
+	 * on counter traversal results. See error set below.
+	 */
+	if (action_rule != NULL && action_rule->action_set != NULL &&
+	    action_rule->action_set->counter != NULL &&
+	    !action_rule->action_set->counter->indirect)
+		counters[0] = action_rule->action_set->counter;
+	else
+		counters[0] = NULL;
 
-	action_set = action_rule->action_set;
-	counter = action_set->counter;
+	counters[1] = spec->ct_counter;
 
-	if (conf == NULL ||
-	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(sa, counter, data);
-		if (rc != 0) {
-			return rte_flow_error_set(error, EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION, action,
-				"Queried flow rule counter action is invalid");
-		}
+	for (i = 0; i < RTE_DIM(counters); ++i) {
+		struct sfc_mae_counter *counter = counters[i];
 
-		return 0;
+		if (counter == NULL)
+			continue;
+
+		if (conf == NULL ||
+		    (counter->rte_id_valid && conf->id == counter->rte_id)) {
+			rc = sfc_mae_counter_get(sa, counter, data);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION, action,
+					"Queried flow rule counter action is invalid");
+			}
+
+			return 0;
+		}
 	}
 
 	return rte_flow_error_set(error, ENOENT,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3a3a5225fd..80585c0e93 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -173,6 +173,8 @@ struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Action rule counter record collection */
 	struct sfc_mae_counter_records	action_counters;
+	/** Conntrack counter record collection */
+	struct sfc_mae_counter_records	conntrack_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 47448cba15..79043ff7d7 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail_counter_type_check;
@@ -172,6 +175,9 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		return EINVAL;
 	}
@@ -319,6 +325,9 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
 		counters = &counter_registry->action_counters;
 		break;
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT:
+		counters = &counter_registry->conntrack_counters;
+		break;
 	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
@@ -392,6 +401,23 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 		byte_count_hi =
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
+
+		if (id == ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT) {
+			/*
+			 * FIXME:
+			 *
+			 * CT counters are 1-bit saturating counters.
+			 * There is no way to express this in DPDK
+			 * currently, so increment the hit count
+			 * by one to let the application know
+			 * that the flow is still effective.
+			 */
+			packet_count_lo = 1;
+			packet_count_hi = 0;
+			byte_count_lo = 0;
+			byte_count_hi = 0;
+		}
+
 		sfc_mae_counter_increment(sa,
 			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
@@ -983,6 +1009,10 @@ sfc_mae_counter_get(struct sfc_adapter *sa,
 		counters = &sa->mae.counter_registry.action_counters;
 		need_byte_count = true;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &sa->mae.counter_registry.conntrack_counters;
+		need_byte_count = false;
+		break;
 	default:
 		return EINVAL;
 	}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 00/34] net/sfc: support HW conntrack assistance
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (34 preceding siblings ...)
  2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
@ 2023-06-04 23:24 ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
                     ` (34 more replies)
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
  36 siblings, 35 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

Changes in v2:
* Found and fixed my own mistake in [15/34]
* Fixed [16/34] as per 0-day robot report
* Added missing release notes to [27/34]
* Added missing release notes to [30/34]

Changes in v3:
* Fixed release notes in [27/34]
* Rebased on dpdk to fix CI

Denis Pryazhennikov (11):
  common/sfc_efx/base: update MCDI headers
  common/sfc_efx/base: detect MCDI Table Access API support
  common/sfc_efx/base: add API to list HW tables
  common/sfc_efx/base: add macro to get indexed QWORD field
  common/sfc_efx/base: add API to get HW table desc
  common/sfc_efx/base: add API to insert data to HW table
  common/sfc_efx/base: add API to delete entry from HW table
  net/sfc: add MCDI wrappers for BCAM tables
  net/sfc: add functions to manipulate MCDI table fields
  net/sfc: attach to HW table API
  net/sfc: add API to manage HW Conntrack table

Ivan Malov (23):
  net/sfc: make entry pointer optional in MAE resource helpers
  net/sfc: turn flow create/destroy methods into lock wrappers
  net/sfc: let driver-internal flows use VF representor action
  net/sfc: extend generic flow API to allow for internal flows
  net/sfc: switch driver-internal flows to use generic methods
  net/sfc: move MAE flow parsing method to MAE-specific source
  net/sfc: move MAE counter stream start to action set handler
  net/sfc: prepare MAE outer rules for action rule indirection
  net/sfc: turn MAE flow action rules into shareable resources
  common/sfc_efx/base: provide an API to clone MAE match specs
  common/sfc_efx/base: add API to read back MAE match criteria
  common/sfc_efx/base: match on conntrack mark in action rules
  common/sfc_efx/base: add API to request MAE conntrack lookup
  net/sfc: make use of conntrack assistance for transfer flows
  common/sfc_efx/base: support NAT edits in MAE
  net/sfc: add support for IPv4 NAT offload to MAE backend
  net/sfc: rename SW structures used by transfer flow counters
  net/sfc: rework MAE action rule counter representation in SW
  net/sfc: support indirect count action in transfer flows
  common/sfc_efx/base: rework MAE counter provisioning helpers
  net/sfc: indicate MAE counter type in use for transfer flows
  common/sfc_efx/base: support conntrack assistance counters
  net/sfc: use conntrack assistance counters in transfer flows

 doc/guides/nics/features/sfc.ini            |    4 +
 doc/guides/nics/sfc_efx.rst                 |   10 +
 doc/guides/rel_notes/release_23_07.rst      |   18 +
 drivers/common/sfc_efx/base/efx.h           |  198 +-
 drivers/common/sfc_efx/base/efx_impl.h      |    5 +-
 drivers/common/sfc_efx/base/efx_mae.c       |  383 ++-
 drivers/common/sfc_efx/base/efx_mcdi.h      |    4 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 drivers/common/sfc_efx/base/efx_table.c     |  506 ++++
 drivers/common/sfc_efx/base/hunt_nic.c      |    2 +
 drivers/common/sfc_efx/base/medford2_nic.c  |    2 +
 drivers/common/sfc_efx/base/medford_nic.c   |    2 +
 drivers/common/sfc_efx/base/meson.build     |    1 +
 drivers/common/sfc_efx/base/rhead_nic.c     |    9 +
 drivers/common/sfc_efx/base/siena_nic.c     |    2 +
 drivers/common/sfc_efx/version.map          |   14 +
 drivers/net/sfc/meson.build                 |    6 +-
 drivers/net/sfc/sfc.c                       |   27 +-
 drivers/net/sfc/sfc.h                       |    3 +
 drivers/net/sfc/sfc_flow.c                  |  246 +-
 drivers/net/sfc/sfc_flow.h                  |   45 +-
 drivers/net/sfc/sfc_mae.c                   | 1899 ++++++++++----
 drivers/net/sfc/sfc_mae.h                   |  131 +-
 drivers/net/sfc/sfc_mae_counter.c           |  146 +-
 drivers/net/sfc/sfc_mae_counter.h           |   16 +-
 drivers/net/sfc/sfc_mae_ct.c                |  201 ++
 drivers/net/sfc/sfc_mae_ct.h                |   68 +
 drivers/net/sfc/sfc_repr.c                  |   20 +-
 drivers/net/sfc/sfc_repr_proxy.c            |   53 +-
 drivers/net/sfc/sfc_repr_proxy.h            |    2 +-
 drivers/net/sfc/sfc_repr_proxy_api.h        |    3 +
 drivers/net/sfc/sfc_switch.c                |    7 +-
 drivers/net/sfc/sfc_switch.h                |   10 +
 drivers/net/sfc/sfc_tbl_meta.c              |   71 +
 drivers/net/sfc/sfc_tbl_meta.h              |   37 +
 drivers/net/sfc/sfc_tbl_meta_cache.c        |  253 ++
 drivers/net/sfc/sfc_tbl_meta_cache.h        |   25 +
 drivers/net/sfc/sfc_tbls.c                  |  200 ++
 drivers/net/sfc/sfc_tbls.h                  |  285 +++
 39 files changed, 6601 insertions(+), 870 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h
 create mode 100644 drivers/net/sfc/sfc_tbls.c
 create mode 100644 drivers/net/sfc/sfc_tbls.h

-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 01/34] common/sfc_efx/base: update MCDI headers
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
                     ` (33 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Pickup new FW interface definitions.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 1 file changed, 2467 insertions(+), 90 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index d1d8093601..76bd1bf4d9 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -5,7 +5,10 @@
  */
 
 /*
- * This file is automatically generated. DO NOT EDIT IT.
+ * This file is automatically generated, but contains manual changes.
+ * - replaced the autogenerated license header with BSD-3-Clause;
+ * - used tabs for the indentation of MC_CMD_ERR_*.
+ *
  * To make changes, edit the .yml files in smartnic_registry under doc/mcdi/ and
  * rebuild this file with "make mcdi_headers_v5".
  */
@@ -81,19 +84,19 @@
  *               |                      \------- Error
  *               \------------------------------ Resync (always set)
  *
- * The client writes it's request into MC shared memory, and rings the
- * doorbell. Each request is completed by either by the MC writting
- * back into shared memory, or by writting out an event.
+ * The client writes its request into MC shared memory, and rings the
+ * doorbell. Each request is completed either by the MC writing
+ * back into shared memory, or by writing out an event.
  *
  * All MCDI commands support completion by shared memory response. Each
  * request may also contain additional data (accounted for by HEADER.LEN),
- * and some response's may also contain additional data (again, accounted
+ * and some responses may also contain additional data (again, accounted
  * for by HEADER.LEN).
  *
  * Some MCDI commands support completion by event, in which any associated
  * response data is included in the event.
  *
- * The protocol requires one response to be delivered for every request, a
+ * The protocol requires one response to be delivered for every request; a
  * request should not be sent unless the response for the previous request
  * has been received (either by polling shared memory, or by receiving
  * an event).
@@ -339,7 +342,7 @@
 /* enum: The requesting client is not a function */
 #define	MC_CMD_ERR_CLIENT_NOT_FN 0x100c
 /* enum: The requested operation might require the command to be passed between
- * MCs, and thetransport doesn't support that. Should only ever been seen over
+ * MCs, and the transport doesn't support that. Should only ever been seen over
  * the UART.
  */
 #define	MC_CMD_ERR_TRANSPORT_NOPROXY 0x100d
@@ -376,7 +379,7 @@
  * sub-variant switching.
  */
 #define	MC_CMD_ERR_FILTERS_PRESENT 0x1014
-/* enum: The clock whose frequency you've attempted to set set doesn't exist on
+/* enum: The clock whose frequency you've attempted to set doesn't exist on
  * this NIC
  */
 #define	MC_CMD_ERR_NO_CLOCK 0x1015
@@ -658,12 +661,624 @@
  * be allocated by different counter blocks, so e.g. AR counter 42 is different
  * from CT counter 42. Generation counts are also type-specific. This value is
  * also present in the header of streaming counter packets, in the IDENTIFIER
- * field (see packetiser packet format definitions).
+ * field (see packetiser packet format definitions). Also note that LACP
+ * counter IDs are not allocated individually, instead the counter IDs are
+ * directly tied to the LACP balance table indices. These in turn are allocated
+ * in large contiguous blocks as a LAG config. Calling MAE_COUNTER_ALLOC/FREE
+ * with an LACP counter type will return EPERM.
  */
 /* enum: Action Rule counters - can be referenced in AR response. */
 #define	MAE_COUNTER_TYPE_AR 0x0
 /* enum: Conntrack counters - can be referenced in CT response. */
 #define	MAE_COUNTER_TYPE_CT 0x1
+/* enum: Outer Rule counters - can be referenced in OR response. */
+#define	MAE_COUNTER_TYPE_OR 0x2
+/* enum: LACP counters - linked to LACP balance table entries. */
+#define	MAE_COUNTER_TYPE_LACP 0x3
+
+/* MAE_COUNTER_ID enum: ID of allocated counter or counter list. */
+/* enum: A counter ID that is guaranteed never to represent a real counter or
+ * counter list.
+ */
+#define	MAE_COUNTER_ID_NULL 0xffffffff
+
+/* TABLE_ID enum: Unique IDs for tables. The 32-bit ID values have been
+ * structured with bits [31:24] reserved (0), [23:16] indicating which major
+ * block the tables belongs to (0=VNIC TX, none currently; 1=MAE; 2=VNIC RX),
+ * [15:8] a unique ID within the block, and [7:0] reserved for future
+ * variations of the same table. (All of the tables currently defined within
+ * the streaming engines are listed here, but this does not imply that they are
+ * all supported - MC_CMD_TABLE_LIST returns the list of actually supported
+ * tables.) The DPU offload engines' enumerators follow a deliberate pattern:
+ * 0x01010000 + is_dpu_net * 0x10000 + is_wr_or_tx * 0x8000 + is_lite_pipe *
+ * 0x1000 + oe_engine_type * 0x100 + oe_instance_within_pipe * 0x10
+ */
+/* enum: Outer_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_TABLE 0x10000
+/* enum: Outer_Rule_No_CT_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_NO_CT_TABLE 0x10100
+/* enum: Mgmt_Filter_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGMT_FILTER_TABLE 0x10200
+/* enum: Conntrack_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_CONNTRACK_TABLE 0x10300
+/* enum: Action_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ACTION_RULE_TABLE 0x10400
+/* enum: Mgroup_Default_Action_Set_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGROUP_DEFAULT_ACTION_SET_TABLE 0x10500
+/* enum: Encap_Hdr_Part1_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART1_TABLE 0x10600
+/* enum: Encap_Hdr_Part2_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART2_TABLE 0x10700
+/* enum: Replace_Src_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_SRC_MAC_TABLE 0x10800
+/* enum: Replace_Dst_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_DST_MAC_TABLE 0x10900
+/* enum: Dst_Mport_VC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_VC_TABLE 0x10a00
+/* enum: LACP_LAG_Config_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_LAG_CONFIG_TABLE 0x10b00
+/* enum: LACP_Balance_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_BALANCE_TABLE 0x10c00
+/* enum: Dst_Mport_Host_Chan_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_HOST_CHAN_TABLE 0x10d00
+/* enum: VNIC_Rx_Encap_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_VNIC_RX_ENCAP_TABLE 0x20000
+/* enum: Steering_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_STEERING_TABLE 0x20100
+/* enum: RSS_Context_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_RSS_CONTEXT_TABLE 0x20200
+/* enum: Indirection_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_INDIRECTION_TABLE 0x20300
+/* enum: DPU.host read pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC0_OE_PROFILE 0x1010000
+/* enum: DPU.host read pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC1_OE_PROFILE 0x1010010
+/* enum: DPU.host write pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC0_OE_PROFILE 0x1018000
+/* enum: DPU.host write pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC1_OE_PROFILE 0x1018010
+/* enum: DPU.net 'full' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CRC0_OE_PROFILE 0x1020000
+/* enum: DPU.net 'full' receive pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM0_OE_PROFILE 0x1020100
+/* enum: DPU.net 'full' receive pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM1_OE_PROFILE 0x1020110
+/* enum: DPU.net 'full' receive pipe AES-GCM offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_AES_GCM0_OE_PROFILE 0x1020200
+/* enum: DPU.net 'lite' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CRC0_OE_PROFILE 0x1021000
+/* enum: DPU.net 'lite' receive pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CSUM0_OE_PROFILE 0x1021100
+/* enum: DPU.net 'full' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CRC0_OE_PROFILE 0x1028000
+/* enum: DPU.net 'full' transmit pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM0_OE_PROFILE 0x1028100
+/* enum: DPU.net 'full' transmit pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM1_OE_PROFILE 0x1028110
+/* enum: DPU.net 'full' transmit pipe AES-GCM offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_AES_GCM0_OE_PROFILE 0x1028200
+/* enum: DPU.net 'lite' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CRC0_OE_PROFILE 0x1029000
+/* enum: DPU.net 'lite' transmit pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CSUM0_OE_PROFILE 0x1029100
+
+/* TABLE_COMPRESSED_VLAN enum: Compressed VLAN TPID as used by some field
+ * types; can be calculated by (((ether_type_msb >> 2) & 0x4) ^ 0x4) |
+ * (ether_type_msb & 0x3);
+ */
+#define	TABLE_COMPRESSED_VLAN_TPID_8100 0x5 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_88A8 0x4 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9100 0x1 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9200 0x2 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9300 0x3 /* enum */
+
+/* TABLE_NAT_DIR enum: NAT direction. */
+#define	TABLE_NAT_DIR_SOURCE 0x0 /* enum */
+#define	TABLE_NAT_DIR_DEST 0x1 /* enum */
+
+/* TABLE_RSS_KEY_MODE enum: Defines how the value for Toeplitz hashing for RSS
+ * is constructed as a concatenation (indicated here by "++") of packet header
+ * fields.
+ */
+/* enum: IP src addr ++ IP dst addr */
+#define	TABLE_RSS_KEY_MODE_SA_DA 0x0
+/* enum: IP src addr ++ IP dst addr ++ TCP/UDP src port ++ TCP/UDP dst port */
+#define	TABLE_RSS_KEY_MODE_SA_DA_SP_DP 0x1
+/* enum: IP src addr */
+#define	TABLE_RSS_KEY_MODE_SA 0x2
+/* enum: IP dst addr */
+#define	TABLE_RSS_KEY_MODE_DA 0x3
+/* enum: IP src addr ++ TCP/UDP src port */
+#define	TABLE_RSS_KEY_MODE_SA_SP 0x4
+/* enum: IP dest addr ++ TCP dest port */
+#define	TABLE_RSS_KEY_MODE_DA_DP 0x5
+/* enum: Nothing (produces input of 0, resulting in output hash of 0) */
+#define	TABLE_RSS_KEY_MODE_NONE 0x7
+
+/* TABLE_RSS_SPREAD_MODE enum: RSS spreading mode. */
+/* enum: RSS uses Indirection_Table lookup. */
+#define	TABLE_RSS_SPREAD_MODE_INDIRECTION 0x0
+/* enum: RSS uses even spreading calculation. */
+#define	TABLE_RSS_SPREAD_MODE_EVEN 0x1
+
+/* CRC_VARIANT enum: Operation for the DPU CRC engine to perform. */
+/* enum: Calculate a 32-bit CRC. */
+#define	CRC_VARIANT_CRC32 0x1
+/* enum: Calculate a 64-bit CRC. */
+#define	CRC_VARIANT_CRC64 0x2
+
+/* DPU_CSUM_OP enum: Operation for the DPU checksum engine to perform. */
+/* enum: Calculate the checksum for a TCP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_TCP 0x0
+/* enum: Calculate the checksum for a UDP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_UDP 0x1
+/* enum: Calculate the checksum for a TCP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_TCP 0x2
+/* enum: Calculate the checksum for a UDP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_UDP 0x3
+
+/* GCM_OP_CODE enum: Operation for the DPU AES-GCM engine to perform. */
+/* enum: Encrypt/decrypt a stream of data. */
+#define	GCM_OP_CODE_BULK_CRYPT 0x0
+/* enum: Calculate the authentication tag for a stream of data. */
+#define	GCM_OP_CODE_BULK_AUTH 0x1
+/* enum: Encrypt/decrypt an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_CRYPT 0x2
+/* enum: Calculate the authentication tag of an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_AUTH 0x3
+
+/* AES_KEY_LEN enum: Key size for AES crypto operations */
+/* enum: 128 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_128 0x0
+/* enum: 256 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_256 0x1
+
+/* TABLE_FIELD_ID enum: Unique IDs for fields. Related concepts have been
+ * loosely grouped together into blocks with gaps for expansion, but the values
+ * are arbitrary. Field IDs are not specific to particular tables, and in some
+ * cases this sharing means that they are not used with the exact names of the
+ * corresponding table definitions in SF-123102-TC; however, the mapping should
+ * still be clear. The intent is that a list of fields, with their associated
+ * bit widths and semantics version code, unambiguously defines the semantics
+ * of the fields in a key or response. (Again, this list includes all of the
+ * fields currently defined within the streaming engines, but only a subset may
+ * actually be used by the supported list of tables.)
+ */
+/* enum: May appear multiple times within a key or response, and indicates that
+ * the field is unused and should be set to 0 (or masked out if permitted by
+ * the MASK_VALUE for this field).
+ */
+#define	TABLE_FIELD_ID_UNUSED 0x0
+/* enum: Source m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_SRC_MPORT 0x1
+/* enum: Destination m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_DST_MPORT 0x2
+/* enum: Source m-group ID. */
+#define	TABLE_FIELD_ID_SRC_MGROUP_ID 0x3
+/* enum: Physical network port ID (or m-port ID; same thing, for physical
+ * network ports).
+ */
+#define	TABLE_FIELD_ID_NETWORK_PORT_ID 0x4
+/* enum: True if packet arrived via network port, false if it arrived via host.
+ */
+#define	TABLE_FIELD_ID_IS_FROM_NETWORK 0x5
+/* enum: Full virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC 0x6
+/* enum: Low bits of virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC_LOW 0x7
+/* enum: User mark value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_MARK 0x8
+/* enum: User flag value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_FLAG 0x9
+/* enum: Counter ID associated with a response. All-bits-1 is a null value to
+ * suppress counting.
+ */
+#define	TABLE_FIELD_ID_COUNTER_ID 0xa
+/* enum: Discriminator which may be set by plugins in some lookup keys; this
+ * allows plugins to make a reinterpretation of packet fields in these keys
+ * without clashing with the normal interpretation.
+ */
+#define	TABLE_FIELD_ID_DISCRIM 0xb
+/* enum: Destination MAC address. The mapping from bytes in a frame to the
+ * 48-bit value for this field is in network order, i.e. a MAC address of
+ * AA:BB:CC:DD:EE:FF becomes a 48-bit value of 0xAABBCCDDEEFF.
+ */
+#define	TABLE_FIELD_ID_DST_MAC 0x14
+/* enum: Source MAC address (see notes for DST_MAC). */
+#define	TABLE_FIELD_ID_SRC_MAC 0x15
+/* enum: Outer VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_OVLAN_TPID_COMPRESSED 0x16
+/* enum: Full outer VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_OVLAN 0x17
+/* enum: Outer VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_OVLAN_VID 0x18
+/* enum: Inner VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_IVLAN_TPID_COMPRESSED 0x19
+/* enum: Full inner VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_IVLAN 0x1a
+/* enum: Inner VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_IVLAN_VID 0x1b
+/* enum: Ethertype. */
+#define	TABLE_FIELD_ID_ETHER_TYPE 0x1c
+/* enum: Source IP address, either IPv4 or IPv6. The mapping from bytes in a
+ * frame to the 128-bit value for this field is in network order, with IPv4
+ * addresses assumed to have 12 bytes of trailing zeroes. i.e. the IPv6 address
+ * [2345::6789:ABCD] is 0x2345000000000000000000006789ABCD; the IPv4 address
+ * 192.168.1.2 is 0xC0A80102000000000000000000000000.
+ */
+#define	TABLE_FIELD_ID_SRC_IP 0x1d
+/* enum: Destination IP address (see notes for SRC_IP). */
+#define	TABLE_FIELD_ID_DST_IP 0x1e
+/* enum: IPv4 Type-of-Service or IPv6 Traffic Class field. */
+#define	TABLE_FIELD_ID_IP_TOS 0x1f
+/* enum: IP Protocol. */
+#define	TABLE_FIELD_ID_IP_PROTO 0x20
+/* enum: Layer 4 source port. */
+#define	TABLE_FIELD_ID_SRC_PORT 0x21
+/* enum: Layer 4 destination port. */
+#define	TABLE_FIELD_ID_DST_PORT 0x22
+/* enum: TCP flags. */
+#define	TABLE_FIELD_ID_TCP_FLAGS 0x23
+/* enum: Virtual Network Identifier (VXLAN) or Virtual Session ID (NVGRE). */
+#define	TABLE_FIELD_ID_VNI 0x24
+/* enum: True if packet has any tunnel encapsulation header. */
+#define	TABLE_FIELD_ID_HAS_ENCAP 0x32
+/* enum: True if encap header has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_OVLAN 0x33
+/* enum: True if encap header has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_IVLAN 0x34
+/* enum: True if encap header is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP 0x35
+/* enum: True if encap header is specifically IPv4. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP4 0x36
+/* enum: True if encap header is UDP. */
+#define	TABLE_FIELD_ID_HAS_ENC_UDP 0x37
+/* enum: True if only/inner frame has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_OVLAN 0x38
+/* enum: True if only/inner frame has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_IVLAN 0x39
+/* enum: True if only/inner frame is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_IP 0x3a
+/* enum: True if only/inner frame has a recognised L4 IP protocol (TCP or UDP).
+ */
+#define	TABLE_FIELD_ID_HAS_L4 0x3b
+/* enum: True if only/inner frame is an IP fragment. */
+#define	TABLE_FIELD_ID_IP_FRAG 0x3c
+/* enum: True if only/inner frame is the first IP fragment (fragment offset 0).
+ */
+#define	TABLE_FIELD_ID_IP_FIRST_FRAG 0x3d
+/* enum: True if only/inner frame has an IP Time-To-Live of <= 1. (Note: the
+ * implementation calls this "ip_ttl_is_one" but does in fact match packets
+ * with TTL=0 - which we shouldn't be seeing! - as well.)
+ */
+#define	TABLE_FIELD_ID_IP_TTL_LE_ONE 0x3e
+/* enum: True if only/inner frame has any of TCP SYN, FIN or RST flags set. */
+#define	TABLE_FIELD_ID_TCP_INTERESTING_FLAGS 0x3f
+/* enum: Plugin channel selection. */
+#define	TABLE_FIELD_ID_RDP_PL_CHAN 0x50
+/* enum: Enable update of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL_EN 0x51
+/* enum: New value of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL 0x52
+/* enum: Enable update of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL_EN 0x53
+/* enum: New value of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL 0x54
+/* enum: Enable update of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN_EN 0x55
+/* enum: New value of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN 0x56
+/* enum: Recirculation ID for lookup sequences with two action rule lookups. */
+#define	TABLE_FIELD_ID_RECIRC_ID 0x64
+/* enum: Domain ID passed to conntrack and action rule lookups. */
+#define	TABLE_FIELD_ID_DOMAIN 0x65
+/* enum: Construction mode for encap_tunnel_id - see MAE_CT_VNI_MODE enum. */
+#define	TABLE_FIELD_ID_CT_VNI_MODE 0x66
+/* enum: True to inhibit conntrack lookup if TCP SYN, FIN or RST flag is set.
+ */
+#define	TABLE_FIELD_ID_CT_TCP_FLAGS_INHIBIT 0x67
+/* enum: True to do conntrack lookups for IPv4 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_TCP 0x68
+/* enum: True to do conntrack lookups for IPv4 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_UDP 0x69
+/* enum: True to do conntrack lookups for IPv6 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_TCP 0x6a
+/* enum: True to do conntrack lookups for IPv6 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_UDP 0x6b
+/* enum: Outer rule identifier. */
+#define	TABLE_FIELD_ID_OUTER_RULE_ID 0x6c
+/* enum: Encapsulation type - see MAE_MCDI_ENCAP_TYPE enum. */
+#define	TABLE_FIELD_ID_ENCAP_TYPE 0x6d
+/* enum: Encap tunnel ID for conntrack lookups from VNI, VLAN tag(s), or 0,
+ * depending on CT_VNI_MODE.
+ */
+#define	TABLE_FIELD_ID_ENCAP_TUNNEL_ID 0x78
+/* enum: A conntrack entry identifier, passed to plugins. */
+#define	TABLE_FIELD_ID_CT_ENTRY_ID 0x79
+/* enum: Either source or destination NAT replacement port. */
+#define	TABLE_FIELD_ID_NAT_PORT 0x7a
+/* enum: Either source or destination NAT replacement IPv4 address. Note that
+ * this is specifically an IPv4 address (IPv6 is not supported for NAT), with
+ * byte mapped to a 32-bit value in network order, i.e. the IPv4 address
+ * 192.168.1.2 is the value 0xC0A80102.
+ */
+#define	TABLE_FIELD_ID_NAT_IP 0x7b
+/* enum: NAT direction: 0=>source, 1=>destination. */
+#define	TABLE_FIELD_ID_NAT_DIR 0x7c
+/* enum: Conntrack mark value, passed to action rule lookup. Note that this is
+ * not related to the "user mark" in the metadata / packet prefix.
+ */
+#define	TABLE_FIELD_ID_CT_MARK 0x7d
+/* enum: Private flags for conntrack, passed to action rule lookup. */
+#define	TABLE_FIELD_ID_CT_PRIV_FLAGS 0x7e
+/* enum: True if the conntrack lookup resulted in a hit. */
+#define	TABLE_FIELD_ID_CT_HIT 0x7f
+/* enum: True to suppress delivery when source and destination m-ports match.
+ */
+#define	TABLE_FIELD_ID_SUPPRESS_SELF_DELIVERY 0x8c
+/* enum: True to perform tunnel decapsulation. */
+#define	TABLE_FIELD_ID_DO_DECAP 0x8d
+/* enum: True to copy outer frame DSCP to inner on decap. */
+#define	TABLE_FIELD_ID_DECAP_DSCP_COPY 0x8e
+/* enum: True to map outer frame ECN to inner on decap, by RFC 6040 rules. */
+#define	TABLE_FIELD_ID_DECAP_ECN_RFC6040 0x8f
+/* enum: True to replace DSCP field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_DSCP 0x90
+/* enum: True to replace ECN field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_ECN 0x91
+/* enum: True to decrement IP Time-To-Live. */
+#define	TABLE_FIELD_ID_DO_DECR_IP_TTL 0x92
+/* enum: True to replace source MAC address. */
+#define	TABLE_FIELD_ID_DO_SRC_MAC 0x93
+/* enum: True to replace destination MAC address. */
+#define	TABLE_FIELD_ID_DO_DST_MAC 0x94
+/* enum: Number of VLAN tags to pop. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_POP 0x95
+/* enum: Number of VLANs tags to push. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_PUSH 0x96
+/* enum: True to count this packet. */
+#define	TABLE_FIELD_ID_DO_COUNT 0x97
+/* enum: True to perform tunnel encapsulation. */
+#define	TABLE_FIELD_ID_DO_ENCAP 0x98
+/* enum: True to copy inner frame DSCP to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_DSCP_COPY 0x99
+/* enum: True to copy inner frame ECN to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_ECN_COPY 0x9a
+/* enum: True to deliver the packet (otherwise it is dropped). */
+#define	TABLE_FIELD_ID_DO_DELIVER 0x9b
+/* enum: True to set the user flag in the metadata. */
+#define	TABLE_FIELD_ID_DO_FLAG 0x9c
+/* enum: True to update the user mark in the metadata. */
+#define	TABLE_FIELD_ID_DO_MARK 0x9d
+/* enum: True to override the capsule virtual channel for network deliveries.
+ */
+#define	TABLE_FIELD_ID_DO_SET_NET_CHAN 0x9e
+/* enum: True to override the reported source m-port for host deliveries. */
+#define	TABLE_FIELD_ID_DO_SET_SRC_MPORT 0x9f
+/* enum: Encap header ID for DO_ENCAP, indexing Encap_Hdr_Part1/2_Table. */
+#define	TABLE_FIELD_ID_ENCAP_HDR_ID 0xaa
+/* enum: New DSCP value for DO_REPLACE_DSCP. */
+#define	TABLE_FIELD_ID_DSCP_VALUE 0xab
+/* enum: If DO_REPLACE_ECN is set, the new value for the ECN field. If
+ * DO_REPLACE_ECN is not set, ECN_CONTROL[0] and ECN_CONTROL[1] are set to
+ * request remapping of ECT0 and ECT1 ECN codepoints respectively to CE.
+ */
+#define	TABLE_FIELD_ID_ECN_CONTROL 0xac
+/* enum: Source MAC ID for DO_SRC_MAC, indexing Replace_Src_MAC_Table. */
+#define	TABLE_FIELD_ID_SRC_MAC_ID 0xad
+/* enum: Destination MAC ID for DO_DST_MAC, indexing Replace_Dst_MAC_Table. */
+#define	TABLE_FIELD_ID_DST_MAC_ID 0xae
+/* enum: Parameter for either DO_SET_NET_CHAN (only bottom 6 bits used in this
+ * case) or DO_SET_SRC_MPORT.
+ */
+#define	TABLE_FIELD_ID_REPORTED_SRC_MPORT_OR_NET_CHAN 0xaf
+/* enum: 64-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK64 0xb4
+/* enum: 32-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK32 0xb5
+/* enum: 16-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK16 0xb6
+/* enum: 8-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK8 0xb7
+/* enum: 4-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK4 0xb8
+/* enum: 2-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK2 0xb9
+/* enum: Added encapsulation header length in words. */
+#define	TABLE_FIELD_ID_HDR_LEN_W 0xba
+/* enum: Static value for layer 2/3 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L23 0xbb
+/* enum: Static value for layer 4 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L4 0xbc
+/* enum: True to use the static ENC_LACP_HASH values for the encap header
+ * instead of the calculated values for the inner frame when delivering a newly
+ * encapsulated packet to a LAG m-port.
+ */
+#define	TABLE_FIELD_ID_USE_ENC_LACP_HASHES 0xbd
+/* enum: True to trigger conntrack from first action rule lookup (AR=>CT=>AR
+ * sequence).
+ */
+#define	TABLE_FIELD_ID_DO_CT 0xc8
+/* enum: True to perform NAT using parameters from conntrack lookup response.
+ */
+#define	TABLE_FIELD_ID_DO_NAT 0xc9
+/* enum: True to trigger recirculated action rule lookup (AR=>AR sequence). */
+#define	TABLE_FIELD_ID_DO_RECIRC 0xca
+/* enum: Next action set payload ID for replay. The null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_PAYLOAD 0xcb
+/* enum: Next action set row ID for replay. The null value is all-1-bits. */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_ROW 0xcc
+/* enum: Action set payload ID for additional delivery to management CPU. The
+ * null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_PAYLOAD 0xcd
+/* enum: Action set row ID for additional delivery to management CPU. The null
+ * value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_ROW 0xce
+/* enum: True to include layer 4 in LACP hash on delivery to a LAG m-port. */
+#define	TABLE_FIELD_ID_LACP_INC_L4 0xdc
+/* enum: True to request that LACP is performed by a plugin. */
+#define	TABLE_FIELD_ID_LACP_PLUGIN 0xdd
+/* enum: LACP_Balance_Table base address divided by 64. */
+#define	TABLE_FIELD_ID_BAL_TBL_BASE_DIV64 0xde
+/* enum: Length of balance table region: 0=>64, 1=>128, 2=>256. */
+#define	TABLE_FIELD_ID_BAL_TBL_LEN_ID 0xdf
+/* enum: LACP LAG ID (i.e. the low 3 bits of LACP LAG mport ID), indexing
+ * LACP_LAG_Config_Table. Refer to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_LACP_LAG_ID 0xe0
+/* enum: Address in LACP_Balance_Table. The balance table is partitioned
+ * between LAGs according to the settings in LACP_LAG_Config_Table and then
+ * indexed by the LACP hash, providing the mapping to destination mports. Refer
+ * to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_BAL_TBL_ADDR 0xe1
+/* enum: UDP port to match for UDP-based encapsulations; required to be 0 for
+ * other encapsulation types.
+ */
+#define	TABLE_FIELD_ID_UDP_PORT 0xe6
+/* enum: True to perform RSS based on outer fields rather than inner fields. */
+#define	TABLE_FIELD_ID_RSS_ON_OUTER 0xe7
+/* enum: True to perform steering table lookup on outer fields rather than
+ * inner fields.
+ */
+#define	TABLE_FIELD_ID_STEER_ON_OUTER 0xe8
+/* enum: Destination queue ID for host delivery. */
+#define	TABLE_FIELD_ID_DST_QID 0xf0
+/* enum: True to drop this packet. */
+#define	TABLE_FIELD_ID_DROP 0xf1
+/* enum: True to strip outer VLAN tag from this packet. */
+#define	TABLE_FIELD_ID_VLAN_STRIP 0xf2
+/* enum: True to override the user mark field with the supplied USER_MARK, or
+ * false to bitwise-OR the USER_MARK into it.
+ */
+#define	TABLE_FIELD_ID_MARK_OVERRIDE 0xf3
+/* enum: True to override the user flag field with the supplied USER_FLAG, or
+ * false to bitwise-OR the USER_FLAG into it.
+ */
+#define	TABLE_FIELD_ID_FLAG_OVERRIDE 0xf4
+/* enum: RSS context ID, indexing the RSS_Context_Table. */
+#define	TABLE_FIELD_ID_RSS_CTX_ID 0xfa
+/* enum: True to enable RSS. */
+#define	TABLE_FIELD_ID_RSS_EN 0xfb
+/* enum: Toeplitz hash key. */
+#define	TABLE_FIELD_ID_KEY 0xfc
+/* enum: Key mode for IPv4 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V4_KEY_MODE 0xfd
+/* enum: Key mode for IPv6 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V6_KEY_MODE 0xfe
+/* enum: Key mode for IPv4 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V4_KEY_MODE 0xff
+/* enum: Key mode for IPv6 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V6_KEY_MODE 0x100
+/* enum: Key mode for other IPv4 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V4_KEY_MODE 0x101
+/* enum: Key mode for other IPv6 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V6_KEY_MODE 0x102
+/* enum: Spreading mode - 0=>indirection; 1=>even. */
+#define	TABLE_FIELD_ID_SPREAD_MODE 0x103
+/* enum: For indirection spreading mode, the base address of a region within
+ * the Indirection_Table. For even spreading mode, the number of queues to
+ * spread across (only values 1-255 are valid for this mode).
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_BASE 0x104
+/* enum: For indirection spreading mode, identifies the length of a region
+ * within the Indirection_Table, where length = 32 << len_id. Must be set to 0
+ * for even spreading mode.
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_LEN_ID 0x105
+/* enum: An offset to be applied to the base destination queue ID. */
+#define	TABLE_FIELD_ID_INDIR_OFFSET 0x106
+/* enum: DPU offload engine profile ID to address. */
+#define	TABLE_FIELD_ID_OE_PROFILE 0x3e8
+/* enum: Width of the CRC to calculate - see CRC_VARIANT enum. */
+#define	TABLE_FIELD_ID_CRC_VARIANT 0x3f2
+/* enum: If set, reflect the bits of each input byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFIN 0x3f3
+/* enum: If set, reflect the bits of each output byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFOUT 0x3f4
+/* enum: If set, invert every bit of the output value. */
+#define	TABLE_FIELD_ID_CRC_INVOUT 0x3f5
+/* enum: The CRC polynomial to use for checksumming, in normal form. See
+ * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Specification for a
+ * description of normal form.
+ */
+#define	TABLE_FIELD_ID_CRC_POLY 0x3f6
+/* enum: Operation for the checksum engine to perform - see DPU_CSUM_OP enum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OP 0x410
+/* enum: Byte offset of checksum relative to region_start (for VALIDATE_*
+ * operations only).
+ */
+#define	TABLE_FIELD_ID_CSUM_OFFSET 0x411
+/* enum: Indicates there is additional data on OPR bus that needs to be
+ * incorporated into the payload checksum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OPR_ADDITIONAL_DATA 0x412
+/* enum: Log2 data size of additional data on OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_DATA_SIZE_LOG2 0x413
+/* enum: 4 byte offset of where to find the additional data on the OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_4B_OFF 0x414
+/* enum: Operation type for the AES-GCM core - see GCM_OP_CODE enum. */
+#define	TABLE_FIELD_ID_GCM_OP_CODE 0x41a
+/* enum: Key length - AES_KEY_LEN enum. */
+#define	TABLE_FIELD_ID_GCM_KEY_LEN 0x41b
+/* enum: OPR 4 byte offset for ICV or GHASH output (only in BULK_* mode) or
+ * IPSEC descrypt output.
+ */
+#define	TABLE_FIELD_ID_GCM_OPR_4B_OFFSET 0x41c
+/* enum: If OP_CODE is BULK_*, indicates Emit GHASH (Fragment mode). Else,
+ * indicates IPSEC-ESN mode.
+ */
+#define	TABLE_FIELD_ID_GCM_EMIT_GHASH_ISESN 0x41d
+/* enum: Replay Protection Enable. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_PROTECT_EN 0x41e
+/* enum: IPSEC Encrypt ESP trailer NEXT_HEADER byte. */
+#define	TABLE_FIELD_ID_GCM_NEXT_HDR 0x41f
+/* enum: Replay Window Size. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_WIN_SIZE 0x420
 
 /* MCDI_EVENT structuredef: The structure of an MCDI_EVENT on Siena/EF10/EF100
  * platforms
@@ -819,7 +1434,7 @@
 #define	MCDI_EVENT_AOE_FPGA_LOAD_FAILED 0xe
 /* enum: Notify that invalid flash type detected */
 #define	MCDI_EVENT_AOE_INVALID_FPGA_FLASH_TYPE 0xf
-/* enum: Notify that the attempt to run FPGA Controller firmware timedout */
+/* enum: Notify that the attempt to run FPGA Controller firmware timed out */
 #define	MCDI_EVENT_AOE_FC_RUN_TIMEDOUT 0x10
 /* enum: Failure to probe one or more FPGA boot flash chips */
 #define	MCDI_EVENT_AOE_FPGA_BOOT_FLASH_INVALID 0x11
@@ -837,7 +1452,7 @@
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_INFO_WIDTH 8
 /* enum: FC Assert happened, but the register information is not available */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_SEEN 0x0
-/* enum: The register information for FC Assert is ready for readinng by driver
+/* enum: The register information for FC Assert is ready for reading by driver
  */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_DATA_READY 0x1
 #define	MCDI_EVENT_AOE_ERR_CODE_FPGA_HEADER_VERIFY_FAILED_OFST 0
@@ -946,6 +1561,12 @@
 #define	MCDI_EVENT_MODULECHANGE_SEQ_OFST 0
 #define	MCDI_EVENT_MODULECHANGE_SEQ_LBN 30
 #define	MCDI_EVENT_MODULECHANGE_SEQ_WIDTH 2
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_LBN 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_WIDTH 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_LBN 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_WIDTH 16
 #define	MCDI_EVENT_DATA_LBN 0
 #define	MCDI_EVENT_DATA_WIDTH 32
 /* Alias for PTP_DATA. */
@@ -1076,6 +1697,18 @@
  * SF-122927-TC for details.
  */
 #define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_DRIVER_ATTACH 0x26
+/* enum: Notification that the mport journal has changed since it was last read
+ * and updates can be read using the MC_CMD_MAE_MPORT_READ_JOURNAL command. The
+ * firmware may moderate the events so that an event is not sent for every
+ * change to the journal.
+ */
+#define	MCDI_EVENT_CODE_MPORT_JOURNAL_CHANGE 0x27
+/* enum: Notification that a source queue is enabled and attached to its proxy
+ * sink queue. SRC field contains the handle of the affected descriptor proxy
+ * function. DATA field contains the relative source queue number and absolute
+ * VI ID.
+ */
+#define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_QUEUE_START 0x28
 /* enum: Artificial event generated by host and posted via MC for test
  * purposes.
  */
@@ -1842,6 +2475,7 @@
 /* Log destination */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_LEN 4
+/* enum property: bitmask */
 /* enum: UART. */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1
 /* enum: Event queue. */
@@ -1888,6 +2522,9 @@
 
 /* MC_CMD_GET_VERSION_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_OUT_LEN 32
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1910,6 +2547,9 @@
 
 /* MC_CMD_GET_VERSION_EXT_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_EXT_OUT_LEN 48
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1940,6 +2580,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V2_OUT_LEN 304
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2079,6 +2722,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V3_OUT_LEN 328
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2225,6 +2871,9 @@
  * version information
  */
 #define	MC_CMD_GET_VERSION_V4_OUT_LEN 392
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2387,6 +3036,9 @@
  * and board version information
  */
 #define	MC_CMD_GET_VERSION_V5_OUT_LEN 424
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2659,7 +3311,9 @@
 #define	MC_CMD_PTP_IN_CMD_LEN 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_OFST 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_LEN 4
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_LEN 4
 /* PTP timestamping mode. Not used from Huntington onwards. */
@@ -3030,7 +3684,9 @@
 #define	MC_CMD_PTP_ENABLE_PPS 0x0
 /* enum: Disable */
 #define	MC_CMD_PTP_DISABLE_PPS 0x1
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_OFST 8
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_LEN 4
 
@@ -3392,6 +4048,87 @@
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_OFST 20
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_LEN 4
 
+/* MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2 msgresponse */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_LEN 40
+/* Time format required/used by for this NIC. Applies to all PTP MCDI
+ * operations that pass times between the host and firmware. If this operation
+ * is not supported (older firmware) a format of seconds and nanoseconds should
+ * be assumed.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_OFST 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_LEN 4
+/* enum: Times are in seconds and nanoseconds */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_NANOSECONDS 0x0
+/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_16SECONDS_8NANOSECONDS 0x1
+/* enum: Major register has units of seconds, minor 2^-27s per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_27FRACTION 0x2
+/* enum: Major register units are seconds, minor units are quarter nanoseconds
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_QTR_NANOSECONDS 0x3
+/* Minimum acceptable value for a corrected synchronization timeset. When
+ * comparing host and NIC clock times, the MC returns a set of samples that
+ * contain the host start and end time, the MC time when the host start was
+ * detected and the time the MC waited between reading the time and detecting
+ * the host end. The corrected sync window is the difference between the host
+ * end and start times minus the time that the MC waited for host end.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_OFST 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_LEN 4
+/* Various PTP capabilities */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_LBN 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_LBN 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_LBN 2
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_LBN 3
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_OFST 12
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_OFST 16
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_OFST 20
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_LEN 4
+/* Minimum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of -0.1 ns should be assumed, which is
+ * equivalent to a -10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LBN 192
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_OFST 28
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LBN 224
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_WIDTH 32
+/* Maximum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of 0.1 ns should be assumed, which is
+ * equivalent to a +10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LBN 256
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_OFST 36
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LBN 288
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_WIDTH 32
+
 /* MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS msgresponse */
 #define	MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN 16
 /* Uncorrected error on PTP transmit timestamps in NIC clock format */
@@ -3443,12 +4180,16 @@
 /***********************************/
 /* MC_CMD_CSR_READ32
  * Read 32bit words from the indirect memory map.
+ *
+ * Note - this command originally belonged to INSECURE category. But access is
+ * required to specific registers for customer diagnostics. The command handler
+ * has additional checks to reject insecure calls.
  */
 #define	MC_CMD_CSR_READ32 0xc
 #define	MC_CMD_CSR_READ32_MSGSET 0xc
 #undef	MC_CMD_0xc_PRIVILEGE_CTG
 
-#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_INSECURE
+#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_ADMIN
 
 /* MC_CMD_CSR_READ32_IN msgrequest */
 #define	MC_CMD_CSR_READ32_IN_LEN 12
@@ -4221,6 +4962,7 @@
 /* Flags associated with this function */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_OFST 4
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_LEN 4
+/* enum property: bitshift */
 /* enum: Labels the lowest-numbered function visible to the OS */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY 0x0
 /* enum: The function can control the link state of the physical port it is
@@ -4454,6 +5196,54 @@
 /* MC_CMD_GET_PHY_CFG_IN msgrequest */
 #define	MC_CMD_GET_PHY_CFG_IN_LEN 0
 
+/* MC_CMD_GET_PHY_CFG_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_CFG_OUT msgresponse */
 #define	MC_CMD_GET_PHY_CFG_OUT_LEN 72
 /* flags */
@@ -4549,6 +5339,9 @@
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_OFST 8
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN 21
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_WIDTH 1
+#define	MC_CMD_PHY_CAP_200000FDX_OFST 8
+#define	MC_CMD_PHY_CAP_200000FDX_LBN 22
+#define	MC_CMD_PHY_CAP_200000FDX_WIDTH 1
 /* ?? */
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_LEN 4
@@ -4582,6 +5375,7 @@
 #define	MC_CMD_MEDIA_DSFP 0x8
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_LEN 4
+/* enum property: bitshift */
 /* enum: Native clause 22 */
 #define	MC_CMD_MMD_CLAUSE22 0x0
 #define	MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
@@ -4847,6 +5641,54 @@
 /* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
 #define	MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
 
+/* MC_CMD_GET_LOOPBACK_MODES_IN_V2 msgrequest */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_LEN 8
+/* Target port to request loopback modes for. Uses MAE_LINK_ENDPOINT_SELECTOR
+ * which identifies a real or virtual network port by MAE port and link end.
+ * See the structure definition for more details
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 40
 /* Supported loopbacks. */
@@ -4860,6 +5702,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 #define	MC_CMD_LOOPBACK_NONE 0x0
 /* enum: Data. */
@@ -4949,6 +5792,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4962,6 +5806,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4975,6 +5820,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4988,6 +5834,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5006,6 +5853,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 /*               MC_CMD_LOOPBACK_NONE 0x0 */
 /* enum: Data. */
@@ -5095,6 +5943,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5108,6 +5957,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5121,6 +5971,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5134,6 +5985,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 25G loopbacks. */
@@ -5147,6 +5999,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LBN 352
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 50 loopbacks. */
@@ -5160,6 +6013,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LBN 416
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 100G loopbacks. */
@@ -5173,6 +6027,214 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LBN 480
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT_V3 msgresponse: Supported loopback modes for
+ * newer NICs with 200G support
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_LEN 72
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_WIDTH 32
+/* enum property: bitshift */
+/* enum: None. */
+/*               MC_CMD_LOOPBACK_NONE 0x0 */
+/* enum: Data. */
+/*               MC_CMD_LOOPBACK_DATA 0x1 */
+/* enum: GMAC. */
+/*               MC_CMD_LOOPBACK_GMAC 0x2 */
+/* enum: XGMII. */
+/*               MC_CMD_LOOPBACK_XGMII 0x3 */
+/* enum: XGXS. */
+/*               MC_CMD_LOOPBACK_XGXS 0x4 */
+/* enum: XAUI. */
+/*               MC_CMD_LOOPBACK_XAUI 0x5 */
+/* enum: GMII. */
+/*               MC_CMD_LOOPBACK_GMII 0x6 */
+/* enum: SGMII. */
+/*               MC_CMD_LOOPBACK_SGMII 0x7 */
+/* enum: XGBR. */
+/*               MC_CMD_LOOPBACK_XGBR 0x8 */
+/* enum: XFI. */
+/*               MC_CMD_LOOPBACK_XFI 0x9 */
+/* enum: XAUI Far. */
+/*               MC_CMD_LOOPBACK_XAUI_FAR 0xa */
+/* enum: GMII Far. */
+/*               MC_CMD_LOOPBACK_GMII_FAR 0xb */
+/* enum: SGMII Far. */
+/*               MC_CMD_LOOPBACK_SGMII_FAR 0xc */
+/* enum: XFI Far. */
+/*               MC_CMD_LOOPBACK_XFI_FAR 0xd */
+/* enum: GPhy. */
+/*               MC_CMD_LOOPBACK_GPHY 0xe */
+/* enum: PhyXS. */
+/*               MC_CMD_LOOPBACK_PHYXS 0xf */
+/* enum: PCS. */
+/*               MC_CMD_LOOPBACK_PCS 0x10 */
+/* enum: PMA-PMD. */
+/*               MC_CMD_LOOPBACK_PMAPMD 0x11 */
+/* enum: Cross-Port. */
+/*               MC_CMD_LOOPBACK_XPORT 0x12 */
+/* enum: XGMII-Wireside. */
+/*               MC_CMD_LOOPBACK_XGMII_WS 0x13 */
+/* enum: XAUI Wireside. */
+/*               MC_CMD_LOOPBACK_XAUI_WS 0x14 */
+/* enum: XAUI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 */
+/* enum: XAUI Wireside near. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 */
+/* enum: GMII Wireside. */
+/*               MC_CMD_LOOPBACK_GMII_WS 0x17 */
+/* enum: XFI Wireside. */
+/*               MC_CMD_LOOPBACK_XFI_WS 0x18 */
+/* enum: XFI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 */
+/* enum: PhyXS Wireside. */
+/*               MC_CMD_LOOPBACK_PHYXS_WS 0x1a */
+/* enum: PMA lanes MAC-Serdes. */
+/*               MC_CMD_LOOPBACK_PMA_INT 0x1b */
+/* enum: KR Serdes Parallel (Encoder). */
+/*               MC_CMD_LOOPBACK_SD_NEAR 0x1c */
+/* enum: KR Serdes Serial. */
+/*               MC_CMD_LOOPBACK_SD_FAR 0x1d */
+/* enum: PMA lanes MAC-Serdes Wireside. */
+/*               MC_CMD_LOOPBACK_PMA_INT_WS 0x1e */
+/* enum: KR Serdes Parallel Wireside (Full PCS). */
+/*               MC_CMD_LOOPBACK_SD_FEP2_WS 0x1f */
+/* enum: KR Serdes Parallel Wireside (Sym Aligner to TX). */
+/*               MC_CMD_LOOPBACK_SD_FEP1_5_WS 0x20 */
+/* enum: KR Serdes Parallel Wireside (Deserializer to Serializer). */
+/*               MC_CMD_LOOPBACK_SD_FEP_WS 0x21 */
+/* enum: KR Serdes Serial Wireside. */
+/*               MC_CMD_LOOPBACK_SD_FES_WS 0x22 */
+/* enum: Near side of AOE Siena side port */
+/*               MC_CMD_LOOPBACK_AOE_INT_NEAR 0x23 */
+/* enum: Medford Wireside datapath loopback */
+/*               MC_CMD_LOOPBACK_DATA_WS 0x24 */
+/* enum: Force link up without setting up any physical loopback (snapper use
+ * only)
+ */
+/*               MC_CMD_LOOPBACK_FORCE_EXT_LINK 0x25 */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LBN 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_OFST 12
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LBN 96
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LBN 128
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_OFST 20
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LBN 160
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LBN 192
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_OFST 28
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LBN 224
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LBN 256
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_OFST 36
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LBN 288
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 25G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LBN 320
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_OFST 44
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LBN 352
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 50 loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LBN 384
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_OFST 52
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LBN 416
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 100G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LBN 448
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_OFST 60
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LBN 480
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 200G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LBN 512
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_OFST 68
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LBN 544
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5222,6 +6284,54 @@
 /* MC_CMD_GET_LINK_IN msgrequest */
 #define	MC_CMD_GET_LINK_IN_LEN 0
 
+/* MC_CMD_GET_LINK_IN_V2 msgrequest */
+#define	MC_CMD_GET_LINK_IN_V2_LEN 8
+/* Target port to request link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LINK_OUT msgresponse */
 #define	MC_CMD_GET_LINK_OUT_LEN 28
 /* Near-side advertised capabilities. Refer to
@@ -5498,6 +6608,95 @@
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_LBN 7
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_WIDTH 1
 
+/* MC_CMD_SET_LINK_IN_V3 msgrequest */
+#define	MC_CMD_SET_LINK_IN_V3_LEN 28
+/* Near-side advertised capabilities. Refer to
+ * MC_CMD_GET_PHY_CFG_OUT/SUPPORTED_CAP for bit definitions.
+ */
+#define	MC_CMD_SET_LINK_IN_V3_CAP_OFST 0
+#define	MC_CMD_SET_LINK_IN_V3_CAP_LEN 4
+/* Flags */
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_LBN 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_LBN 2
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_LBN 3
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_WIDTH 1
+/* Loopback mode. */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_OFST 8
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_LEN 4
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+/* A loopback speed of "0" is supported, and means (choose any available
+ * speed).
+ */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_OFST 12
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_WIDTH 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_LBN 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_WIDTH 1
+/* Padding */
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_OFST 17
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_LEN 3
+/* Target port to set link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_SET_LINK_OUT msgresponse */
 #define	MC_CMD_SET_LINK_OUT_LEN 0
 
@@ -5719,19 +6918,9 @@
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_OFST 28
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_LBN 4
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_WIDTH 1
-/* Identifies the MAC to update by the specifying the end of a logical MAE
- * link. Setting TARGET to MAE_LINK_ENDPOINT_COMPAT is equivalent to using the
- * previous version of the command (MC_CMD_SET_MAC_EXT). Not all possible
- * combinations of MPORT_END and MPORT_SELECTOR in TARGET will work in all
- * circumstances. 1. Some will always work (e.g. a VF can always address its
- * logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC), 2. Some are not
- * meaningful and will always fail with EINVAL (e.g. attempting to address the
- * VNIC end of a link to a physical port), 3. Some are meaningful but require
- * the MCDI client to have the required permission and fail with EPERM
- * otherwise (e.g. trying to set the MAC on a VF the caller cannot administer),
- * and 4. Some could be implementation-specific and fail with ENOTSUP if not
- * available (no examples exist right now). See SF-123581-TC section 4.3 for
- * more details.
+/* Target port to set mac state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
  */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_LEN 8
@@ -5743,6 +6932,7 @@
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LBN 288
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 32
@@ -5938,6 +7128,98 @@
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_OFST 16
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_LEN 4
 
+/* MC_CMD_MAC_STATS_V2_IN msgrequest */
+#define	MC_CMD_MAC_STATS_V2_IN_LEN 28
+/* ??? */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_OFST 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LBN 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_LBN 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_LBN 2
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_LBN 3
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_LBN 4
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_LBN 5
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_LBN 16
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_WIDTH 16
+/* DMA length. Should be set to MAC_STATS_NUM_STATS * sizeof(uint64_t), as
+ * returned by MC_CMD_GET_CAPABILITIES_V4_OUT. For legacy firmware not
+ * supporting MC_CMD_GET_CAPABILITIES_V4_OUT, DMA_LEN should be set to
+ * MC_CMD_MAC_NSTATS * sizeof(uint64_t)
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_OFST 12
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_LEN 4
+/* port id so vadapter stats can be provided */
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_OFST 16
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_LEN 4
+/* Target port to request statistics for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
 #define	MC_CMD_MAC_STATS_OUT_DMA_LEN 0
 
@@ -5954,6 +7236,7 @@
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+/* enum property: index */
 #define	MC_CMD_MAC_GENERATION_START 0x0 /* enum */
 #define	MC_CMD_MAC_DMABUF_START 0x1 /* enum */
 #define	MC_CMD_MAC_TX_PKTS 0x1 /* enum */
@@ -6116,6 +7399,7 @@
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V2
+/* enum property: index */
 /* enum: Start of FEC stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_FEC_DMABUF_START 0x61
 /* enum: Number of uncorrected FEC codewords on link (RS-FEC only for Medford2)
@@ -6155,6 +7439,7 @@
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V3
+/* enum property: index */
 /* enum: Start of CTPIO stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_CTPIO_DMABUF_START 0x68
 /* enum: Number of CTPIO fallbacks because a DMA packet was in progress on the
@@ -6235,6 +7520,7 @@
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V4
+/* enum property: index */
 /* enum: Start of V4 stats buffer space */
 #define	MC_CMD_MAC_V4_DMABUF_START 0x79
 /* enum: RXDP counter: Number of packets truncated because scattering was
@@ -6522,6 +7808,7 @@
 #define	MC_CMD_WOL_FILTER_RESET_IN_LEN 4
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_LEN 4
+/* enum property: bitmask */
 #define	MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
 #define	MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
 
@@ -6566,6 +7853,7 @@
 /* Bit mask of supported types. */
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_LEN 4
+/* enum property: bitshift */
 /* enum: Disabled callisto. */
 #define	MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0
 /* enum: MC firmware. */
@@ -7613,6 +8901,54 @@
 /* MC_CMD_GET_PHY_STATE_IN msgrequest */
 #define	MC_CMD_GET_PHY_STATE_IN_LEN 0
 
+/* MC_CMD_GET_PHY_STATE_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_STATE_OUT msgresponse */
 #define	MC_CMD_GET_PHY_STATE_OUT_LEN 4
 #define	MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
@@ -7884,6 +9220,62 @@
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_LBN 16
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_WIDTH 16
 
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_LEN 12
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_LBN 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_WIDTH 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_LBN 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_WIDTH 16
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 7
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 52
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 48
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 6
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
@@ -9069,27 +10461,22 @@
  * and a generation count for this version of the sensor table. On systems
  * advertising the DYNAMIC_SENSORS capability bit, this replaces the
  * MC_CMD_READ_SENSORS command. On multi-MC systems this may include sensors
- * added by the NMC.
- *
- * Sensor handles are persistent for the lifetime of the sensor and are used to
- * identify sensors in MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
- * MC_CMD_DYNAMIC_SENSORS_GET_VALUES.
- *
- * The generation count is maintained by the MC, is persistent across reboots
- * and will be incremented each time the sensor table is modified. When the
- * table is modified, a CODE_DYNAMIC_SENSORS_CHANGE event will be generated
- * containing the new generation count. The driver should compare this against
- * the current generation count, and if it is different, call
- * MC_CMD_DYNAMIC_SENSORS_LIST again to update it's copy of the sensor table.
- *
- * The sensor count is provided to allow a future path to supporting more than
+ * added by the NMC. Sensor handles are persistent for the lifetime of the
+ * sensor and are used to identify sensors in
+ * MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
+ * MC_CMD_DYNAMIC_SENSORS_GET_VALUES. The generation count is maintained by the
+ * MC, is persistent across reboots and will be incremented each time the
+ * sensor table is modified. When the table is modified, a
+ * CODE_DYNAMIC_SENSORS_CHANGE event will be generated containing the new
+ * generation count. The driver should compare this against the current
+ * generation count, and if it is different, call MC_CMD_DYNAMIC_SENSORS_LIST
+ * again to update it's copy of the sensor table. The sensor count is provided
+ * to allow a future path to supporting more than
  * MC_CMD_DYNAMIC_SENSORS_GET_READINGS_IN_HANDLES_MAXNUM_MCDI2 sensors, i.e.
  * the maximum number that will fit in a single response. As this is a fairly
  * large number (253) it is not anticipated that this will be needed in the
- * near future, so can currently be ignored.
- *
- * On Riverhead this command is implemented as a a wrapper for `list` in the
- * sensor_query SPHINX service.
+ * near future, so can currently be ignored. On Riverhead this command is
+ * implemented as a wrapper for `list` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_LIST 0x66
 #define	MC_CMD_DYNAMIC_SENSORS_LIST_MSGSET 0x66
@@ -9127,15 +10514,13 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS
  * Get descriptions for a set of sensors, specified as an array of sensor
- * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for
- * `get_descriptions` in the sensor_query SPHINX service.
+ * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. Any handles which do not
+ * correspond to a sensor currently managed by the MC will be dropped from from
+ * the response. This may happen when a sensor table update is in progress, and
+ * effectively means the set of usable sensors is the intersection between the
+ * sets of sensors known to the driver and the MC. On Riverhead this command is
+ * implemented as a wrapper for `get_descriptions` in the sensor_query SPHINX
+ * service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS 0x67
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS_MSGSET 0x67
@@ -9173,19 +10558,15 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_READINGS
  * Read the state and value for a set of sensors, specified as an array of
- * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST.
- *
- * In the case of a broken sensor, then the state of the response's
- * MC_CMD_DYNAMIC_SENSORS_VALUE entry will be set to BROKEN, and any value
- * provided should be treated as erroneous.
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for `get_readings`
- * in the sensor_query SPHINX service.
+ * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. In the case of a
+ * broken sensor, then the state of the response's MC_CMD_DYNAMIC_SENSORS_VALUE
+ * entry will be set to BROKEN, and any value provided should be treated as
+ * erroneous. Any handles which do not correspond to a sensor currently managed
+ * by the MC will be dropped from from the response. This may happen when a
+ * sensor table update is in progress, and effectively means the set of usable
+ * sensors is the intersection between the sets of sensors known to the driver
+ * and the MC. On Riverhead this command is implemented as a wrapper for
+ * `get_readings` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS 0x68
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS_MSGSET 0x68
@@ -11629,6 +13010,9 @@
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_LBN 11
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -11833,6 +13217,9 @@
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12118,6 +13505,9 @@
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12663,6 +14053,7 @@
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_OFST 0
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_LEN 4
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_NUM 4
+/* enum property: bitmask */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP0 0x1 /* enum */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP1 0x2 /* enum */
 
@@ -13511,10 +14902,9 @@
 
 /***********************************/
 /* MC_CMD_GET_CAPABILITIES
- * Get device capabilities.
- *
- * This is supplementary to the MC_CMD_GET_BOARD_CFG command, and intended to
- * reference inherent device capabilities as opposed to current NVRAM config.
+ * Get device capabilities. This is supplementary to the MC_CMD_GET_BOARD_CFG
+ * command, and intended to reference inherent device capabilities as opposed
+ * to current NVRAM config.
  */
 #define	MC_CMD_GET_CAPABILITIES 0xbe
 #define	MC_CMD_GET_CAPABILITIES_MSGSET 0xbe
@@ -16473,6 +17863,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 
 /* MC_CMD_GET_CAPABILITIES_V8_OUT msgresponse */
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_LEN 160
@@ -16974,6 +18373,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -17489,6 +18897,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18039,6 +19456,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18134,6 +19560,13 @@
  * are not defined.
  */
 #define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_TSA 0x1
+/* enum: MCDI command used for platform management. Typically, these commands
+ * are used for low-level operations directed at the platform as a whole (e.g.
+ * MMIO device enumeration) rather than individual functions and use a
+ * dedicated comms channel (e.g. RPmsg/IPI). May be handled by the same or
+ * different CPU as MCDI_MESSAGE_TYPE_MC.
+ */
+#define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM 0x2
 
 
 /***********************************/
@@ -22051,8 +23484,8 @@
  * TLV_PORT_MODE_*). A superset of MC_CMD_GET_PORT_MODES_OUT/MODES that
  * contains all modes implemented in firmware for a particular board. Modes
  * listed in MODES are considered production modes and should be exposed in
- * userland tools. Modes listed in in ENGINEERING_MODES, but not in MODES
- * should be considered hidden (not to be exposed in userland tools) and for
+ * userland tools. Modes listed in ENGINEERING_MODES, but not in MODES should
+ * be considered hidden (not to be exposed in userland tools) and for
  * engineering use only. There are no other semantic differences and any mode
  * listed in either MODES or ENGINEERING_MODES can be set on the board.
  */
@@ -26509,6 +27942,7 @@
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MINNUM 0
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM 31
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_PACKETS 0x0 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_BYTES 0x1 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_GOOD_PACKETS 0x2 /* enum */
@@ -26617,6 +28051,65 @@
 /* MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT msgresponse */
 #define	MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT_LEN 0
 
+
+/***********************************/
+/* MC_CMD_GET_BUFTBL_STATS
+ * Currently EF10 only. Read usage and limits for Buffer Table
+ */
+#define	MC_CMD_GET_BUFTBL_STATS 0x6a
+#define	MC_CMD_GET_BUFTBL_STATS_MSGSET 0x6a
+#undef	MC_CMD_0x6a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x6a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_GET_BUFTBL_STATS_IN msgrequest */
+#define	MC_CMD_GET_BUFTBL_STATS_IN_LEN 0
+
+/* MC_CMD_GET_BUFTBL_STATS_OUT msgresponse */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_LEN 40
+/* number of buffer table entries per set */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_OFST 0
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_LEN 4
+/* number of buffer table entries per cluster */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_OFST 4
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_LEN 4
+/* Maximum size buffer table can grow to, in clusters. On EF10, this can
+ * potentially vary depending on the size of the Descriptor Cache.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_OFST 8
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_LEN 4
+/* High water mark for number of buffer table clusters which have been
+ * allocated.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_OFST 12
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_LEN 4
+/* Number of free buffer table clusters on the free cluster list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_OFST 16
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_LEN 4
+/* Number of free buffer table sets on the free set list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_OFST 20
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_LEN 4
+/* Number of chunks of fully-used clusters allocated to the MC for EVQ, RXQ and
+ * TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_OFST 24
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_LEN 4
+/* Number of chunks in partially-used clusters allocated to the MC for EVQ, RXQ
+ * and TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_OFST 28
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_LEN 4
+/* Number of buffer table sets (chunks) allocated to the host via
+ * MC_CMD_ALLOC_BUFTBL_CHUNK.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_OFST 32
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_LEN 4
+/* Maximum number of VIs per NIC. On EF10 this is the current value as used to
+ * size the Descriptor Cache in hardware.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_OFST 36
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_LEN 4
+
 /* CLIENT_HANDLE structuredef: A client is an abstract entity that can make
  * requests of the device and that can own resources managed by the device.
  * Examples of clients include PCIe functions and dynamic clients. A client
@@ -26684,8 +28177,8 @@
 
 /* SCHED_CREDIT_CHECK_RESULT structuredef */
 #define	SCHED_CREDIT_CHECK_RESULT_LEN 16
-/* The instance of the scheduler. Refer to XN-200389-AW for the location of
- * these schedulers in the hardware.
+/* The instance of the scheduler. Refer to XN-200389-AW (snic/hnic) and
+ * XN-200425-TC (cdx) for the location of these schedulers in the hardware.
  */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_OFST 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LEN 1
@@ -26697,6 +28190,18 @@
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_HOST_D 0x5 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_REPLAY 0x6 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_DMAC_H2C 0x7 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_B 0x8 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_REPLAY 0x9 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_ADAPTER_C2H_C 0xa /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A2_H2C_C 0xb /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A3_SOFT_ADAPTOR_C 0xc /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A4_DPU_WRITE_C 0xd /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_JRC_RRU 0xe /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_CDM_SINK 0xf /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PCIE_SINK 0x10 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_UPORT_SINK 0x11 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PSX_SINK 0x12 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A5_DPU_READ_C 0x13 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LBN 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_WIDTH 8
 /* The type of node that this result refers to. */
@@ -26706,6 +28211,10 @@
 #define	SCHED_CREDIT_CHECK_RESULT_DEST 0x0
 /* enum: Source node */
 #define	SCHED_CREDIT_CHECK_RESULT_SOURCE 0x1
+/* enum: Destination node credit type 1 (new to the Keystone schedulers, see
+ * SF-120268-TC)
+ */
+#define	SCHED_CREDIT_CHECK_RESULT_DEST_CREDIT1 0x2
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_LBN 8
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_WIDTH 8
 /* Level of node in scheduler hierarchy (level 0 is the bottom of the
@@ -27813,6 +29322,51 @@
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM 14
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM_MCDI2 62
 
+
+/***********************************/
+/* MC_CMD_TXQ_STATS
+ * Query per-TXQ statistics.
+ */
+#define	MC_CMD_TXQ_STATS 0x1d5
+#define	MC_CMD_TXQ_STATS_MSGSET 0x1d5
+#undef	MC_CMD_0x1d5_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1d5_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TXQ_STATS_IN msgrequest */
+#define	MC_CMD_TXQ_STATS_IN_LEN 8
+/* Instance of TXQ to retrieve statistics for */
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_OFST 0
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_LEN 4
+/* Flags for the request */
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_LEN 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_LBN 0
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_WIDTH 1
+
+/* MC_CMD_TXQ_STATS_OUT msgresponse */
+#define	MC_CMD_TXQ_STATS_OUT_LENMIN 0
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX 248
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX_MCDI2 1016
+#define	MC_CMD_TXQ_STATS_OUT_LEN(num) (0+8*(num))
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_NUM(len) (((len)-0)/8)
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LEN 8
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LBN 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_OFST 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LBN 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MINNUM 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM 31
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
+#define	MC_CMD_TXQ_STATS_CTPIO_MAX_FILL 0x0 /* enum */
+
 /* FUNCTION_PERSONALITY structuredef: The meanings of the personalities are
  * defined in SF-120734-TC with more information in SF-122717-TC.
  */
@@ -28296,6 +29850,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LBN 32
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_VF_OFST 2
@@ -28332,6 +29887,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_VF_OFST 6
@@ -28709,6 +30265,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_VF_OFST 6
@@ -28788,6 +30345,7 @@
 #define	DESC_PROXY_FUNC_MAP_FUNC_HI_WIDTH 32
 #define	DESC_PROXY_FUNC_MAP_FUNC_LBN 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_WIDTH 64
+/* See structuredef: PCIE_FUNCTION */
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_OFST 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LEN 2
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LBN 0
@@ -28851,6 +30409,27 @@
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM 4
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM_MCDI2 19
+/* See structuredef: DESC_PROXY_FUNC_MAP */
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LEN 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LBN 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LBN 64
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_OFST 6
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_OFST 12
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_OFST 16
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_LEN 40
 
 
 /***********************************/
@@ -29015,6 +30594,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM 63
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM_MCDI2 255
+/* See structuredef: QUEUE_ID */
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_REL_QUEUE_LBN 16
@@ -29082,6 +30662,7 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LEN 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LBN 64
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_VF_OFST 6
@@ -29162,6 +30743,7 @@
  * backwards compatibility only, callers should use PCIE_INTERFACE_CALLER.
  */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_PCIE_FUNCTION_INTF_NULL 0xffffffff
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_VF_OFST 6
@@ -29320,6 +30902,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LBN 1096
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_OFST 138
@@ -29333,10 +30916,12 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_WIDTH 8
+/* More generic alias for ENC_VLAN_FLAGS. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS_MASK alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_MASK_OFST 139
@@ -29350,6 +30935,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LBN 1112
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_WIDTH 8
+/* More generic alias for ENC_FLAGS_MASK. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LBN 1112
@@ -29503,6 +31089,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LBN 1152
@@ -29826,6 +31416,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LBN 1152
@@ -30120,7 +31714,7 @@
 /* MAE_MPORT_SELECTOR structuredef: MPORTS are identified by an opaque unsigned
  * integer value (mport_id) that is guaranteed to be representable within
  * 32-bits or within any NIC interface field that needs store the value
- * (whichever is narrowers). This selector structure provides a stable way to
+ * (whichever is narrower). This selector structure provides a stable way to
  * refer to m-ports.
  */
 #define	MAE_MPORT_SELECTOR_LEN 4
@@ -30195,10 +31789,22 @@
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
 /* MAE_LINK_ENDPOINT_SELECTOR structuredef: Structure that identifies a real or
- * virtual network port by MAE port and link end
+ * virtual network port by MAE port and link end. Intended to be used by
+ * network port MCDI commands. Setting FLAT to MAE_LINK_ENDPOINT_COMPAT is
+ * equivalent to using the previous version of the command. Not all possible
+ * combinations of MPORT_END and MPORT_SELECTOR in MAE_LINK_ENDPOINT_SELECTOR
+ * will work in all circumstances. 1. Some will always work (e.g. a VF can
+ * always address its logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC),
+ * 2. Some are not meaningful and will always fail with EINVAL (e.g. attempting
+ * to address the VNIC end of a link to a physical port), 3. Some are
+ * meaningful but require the MCDI client to have the required permission and
+ * fail with EPERM otherwise (e.g. trying to set the MAC on a VF the caller
+ * cannot administer), and 4. Some could be implementation-specific and fail
+ * with ENOTSUP if not available (no examples exist right now). See
+ * SF-123581-TC section 4.3 for more details.
  */
 #define	MAE_LINK_ENDPOINT_SELECTOR_LEN 8
-/* The MAE MPORT of interest */
+/* Identifier for the MAE MPORT of interest */
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_OFST 0
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LEN 4
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LBN 0
@@ -30395,6 +32001,90 @@
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_OFST 56
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_LEN 4
 
+/* MC_CMD_MAE_GET_CAPS_V3_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_LEN 64
+/* The number of field IDs that the NIC supports. Any field with a ID greater
+ * than or equal to the value returned in this field must be treated as having
+ * a support level of MAE_FIELD_UNSUPPORTED in all requests.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_LBN 3
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_WIDTH 1
+/* Deprecated alias for AR_COUNTERS. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_LEN 4
+/* The total number of AR counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_LEN 4
+/* The total number of counters lists available to allocate. A value of zero
+ * indicates that counter lists are not supported by the NIC. (But single
+ * counters may still be.)
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_LEN 4
+/* The number of priorities available for ACTION_RULE filters. It is invalid to
+ * install a MATCH_ACTION filter with a priority number >= ACTION_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_LEN 4
+/* The number of priorities available for OUTER_RULE filters. It is invalid to
+ * install an OUTER_RULE filter with a priority number >= OUTER_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_LEN 4
+/* MAE API major version. Currently 1. If this field is not present in the
+ * response (i.e. response shorter than 384 bits), then its value is zero. If
+ * the value does not match the client's expectations, the client should raise
+ * a fatal error.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_LEN 4
+/* Mask of supported counter types. Each bit position corresponds to a value of
+ * the MAE_COUNTER_TYPE enum. If this field is missing (i.e. V1 response),
+ * clients must assume that only AR counters are supported (i.e.
+ * COUNTER_TYPES_SUPPORTED==0x1). See also
+ * MC_CMD_MAE_COUNTERS_STREAM_START/COUNTER_TYPES_MASK.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_OFST 52
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_LEN 4
+/* The total number of conntrack counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_OFST 56
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_LEN 4
+/* The total number of Outer Rule counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_OFST 60
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_LEN 4
+
 
 /***********************************/
 /* MC_CMD_MAE_GET_AR_CAPS
@@ -30498,10 +32188,13 @@
 /* Generation count. Packets with generation count >= GENERATION_COUNT will
  * contain valid counter values for counter IDs allocated in this call, unless
  * the counter values are zero and zero squash is enabled. Note that there is
- * an independent GENERATION_COUNT object per counter type.
+ * an independent GENERATION_COUNT object per counter type, and that generation
+ * counts wrap from 0xffffffff to 1.
  */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* enum: Generation counter 0 is reserved and unused. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_INVALID 0x0
 /* The number of counter IDs that the NIC allocated. It is never less than 1;
  * failure to allocate a single counter will cause an error to be returned. It
  * is never greater than REQUESTED_COUNT, but may be less.
@@ -30516,6 +32209,8 @@
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2 253
 /* enum: A counter ID that is guaranteed never to represent a real counter */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL 0xffffffff
+/*            Other enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 
 
 /***********************************/
@@ -30577,7 +32272,8 @@
  * values will be written for these counters. If values for these counter IDs
  * are present, the counter ID has been reallocated. A counter ID will not be
  * reallocated within a single read cycle as this would merge increments from
- * the 'old' and 'new' counters.
+ * the 'old' and 'new' counters. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
@@ -30696,7 +32392,8 @@
 /* Generation count for AR counters. The final set of AR counter values will be
  * written out in packets with count == GENERATION_COUNT. An empty packet with
  * count > GENERATION_COUNT indicates that no more counter values of this type
- * will be written to this stream.
+ * will be written to this stream. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
@@ -30712,6 +32409,7 @@
  * final set of counter values will be written out in packets with count ==
  * GENERATION_COUNT. An empty packet with count > GENERATION_COUNT indicates
  * that no more counter values of this type will be written to this stream.
+ * GENERATION_COUNT_INVALID is reserved and unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_LEN 4
@@ -30960,6 +32658,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_LEN 2
@@ -30985,19 +32701,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31041,6 +32761,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_LEN 2
@@ -31066,19 +32804,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31131,6 +32873,172 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_LBN 6
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_WIDTH 1
 
+/* MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN msgrequest: Only supported if
+ * MAE_ACTION_SET_ALLOC_V3_SUPPORTED is advertised in
+ * MC_CMD_GET_CAPABILITIES_V10_OUT.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LEN 53
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_LBN 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_LBN 13
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_LBN 14
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_WIDTH 1
+/* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_LEN 2
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_LEN 4
+/* An m-port selector identifying the m-port that the modified packet should be
+ * delivered to. Set to MPORT_SELECTOR_NULL to request no delivery of the
+ * packet.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_OFST 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_LEN 4
+/* Allows an action set to trigger several counter updates. Set to
+ * MAE_COUNTER_ID_NULL to request no counter action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_OFST 24
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+/* If a driver only wished to update one counter within this action set, then
+ * it can supply a COUNTER_ID instead of allocating a single-element counter
+ * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * COUNTER_ID.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_OFST 28
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_OFST 32
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_LEN 4
+/* Set to MAC_ID_NULL to request no source MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_LEN 4
+/* Source m-port ID to be reported for DO_SET_SRC_MPORT action. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_OFST 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_LEN 4
+/* Actions for modifying the Differentiated Services Code-Point (DSCP) bits
+ * within IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_LEN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_WIDTH 6
+/* Actions for modifying the Explicit Congestion Notification (ECN) bits within
+ * IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_LBN 5
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_LBN 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_WIDTH 1
+/* Actions for overwriting CH_ROUTE subfields. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_WIDTH 1
+/* Override outgoing CH_VC to network port for DO_SET_NET_CHAN action. Cannot
+ * be used in conjunction with DO_SET_SRC_MPORT action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_OFST 52
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_LEN 1
+
 /* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
 /* The MSB of the AS_ID is guaranteed to be clear if the ID is not
@@ -31297,6 +33205,7 @@
  */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+/* Deprecated alias for ACTION_CONTROL. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_LEN 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_OFST 8
@@ -31307,15 +33216,26 @@
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_WIDTH 2
 /*             Enum values, see field(s): */
 /*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_LBN 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_WIDTH 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_LBN 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_WIDTH 16
-/* Reserved for future use. Must be set to zero. */
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_OFST 12
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_LEN 4
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_LEN 4
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_LEN 4
 /* Structure of the format MAE_ENC_FIELD_PAIRS. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_LEN 1
@@ -31367,6 +33287,59 @@
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM 32
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM_MCDI2 32
 
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_UPDATE
+ * Atomically change the response of an Outer Rule.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE 0x17d
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_MSGSET 0x17d
+#undef	MC_CMD_0x17d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x17d_PRIVILEGE_CTG SRIOV_CTG_MAE
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_LEN 16
+/* ID of outer rule to update */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_LEN 4
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_LBN 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_LBN 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_WIDTH 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_LBN 16
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_WIDTH 16
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_LEN 4
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_OUT_LEN 0
+
 /* MAE_ACTION_RULE_RESPONSE structuredef */
 #define	MAE_ACTION_RULE_RESPONSE_LEN 16
 #define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
@@ -31932,6 +33905,7 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_OFST 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_LBN 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_WIDTH 1
+/* The number of MAE_MPORT_DESC structures in MPORT_DESC_DATA. May be zero. */
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_OFST 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_LEN 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC_OFST 8
@@ -31946,4 +33920,407 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM 240
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1008
 
+/* TABLE_FIELD_DESCR structuredef: An individual table field descriptor. This
+ * describes the location and properties of one N-bit field within a wider
+ * M-bit key/mask/response value.
+ */
+#define	TABLE_FIELD_DESCR_LEN 8
+/* Identifier for this field. */
+#define	TABLE_FIELD_DESCR_FIELD_ID_OFST 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_LEN 2
+/*            Enum values, see field(s): */
+/*               TABLE_FIELD_ID */
+#define	TABLE_FIELD_DESCR_FIELD_ID_LBN 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_WIDTH 16
+/* Lowest (least significant) bit number of the bits of this field. */
+#define	TABLE_FIELD_DESCR_LBN_OFST 2
+#define	TABLE_FIELD_DESCR_LBN_LEN 2
+#define	TABLE_FIELD_DESCR_LBN_LBN 16
+#define	TABLE_FIELD_DESCR_LBN_WIDTH 16
+/* Width of this field in bits. */
+#define	TABLE_FIELD_DESCR_WIDTH_OFST 4
+#define	TABLE_FIELD_DESCR_WIDTH_LEN 2
+#define	TABLE_FIELD_DESCR_WIDTH_LBN 32
+#define	TABLE_FIELD_DESCR_WIDTH_WIDTH 16
+/* The mask type for this field. (Note that masking is relevant to keys; fields
+ * of responses are always reported with the EXACT type.)
+ */
+#define	TABLE_FIELD_DESCR_MASK_TYPE_OFST 6
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LEN 1
+/* enum: Field must never be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_NEVER 0x0
+/* enum: Exact match: field must always be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_EXACT 0x1
+/* enum: Ternary match: arbitrary mask bits are allowed. */
+#define	TABLE_FIELD_DESCR_MASK_TERNARY 0x2
+/* enum: Whole field match: mask must be all 1 bits, or all 0 bits. */
+#define	TABLE_FIELD_DESCR_MASK_WHOLE_FIELD 0x3
+/* enum: Longest prefix match: mask must be 1 bit(s) followed by 0 bit(s). */
+#define	TABLE_FIELD_DESCR_MASK_LPM 0x4
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LBN 48
+#define	TABLE_FIELD_DESCR_MASK_TYPE_WIDTH 8
+/* A version code that allows field semantics to be extended. All fields
+ * currently use version 0.
+ */
+#define	TABLE_FIELD_DESCR_SCHEME_OFST 7
+#define	TABLE_FIELD_DESCR_SCHEME_LEN 1
+#define	TABLE_FIELD_DESCR_SCHEME_LBN 56
+#define	TABLE_FIELD_DESCR_SCHEME_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_TABLE_LIST
+ * Return the list of tables which may be accessed via this table API.
+ */
+#define	MC_CMD_TABLE_LIST 0x1c9
+#define	MC_CMD_TABLE_LIST_MSGSET 0x1c9
+#undef	MC_CMD_0x1c9_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1c9_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_LIST_IN msgrequest */
+#define	MC_CMD_TABLE_LIST_IN_LEN 4
+/* Index of the first item to be returned in the TABLE_ID sequence. (Set to 0
+ * for the first call; further calls are only required if the whole sequence
+ * does not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_OFST 0
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_LEN 4
+
+/* MC_CMD_TABLE_LIST_OUT msgresponse */
+#define	MC_CMD_TABLE_LIST_OUT_LENMIN 4
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX 252
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_LIST_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(len) (((len)-4)/4)
+/* The total number of tables. */
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_OFST 0
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_LEN 4
+/* A sequence of table identifiers. If all N_TABLES items do not fit, further
+ * items can be obtained by repeating the call with a non-zero
+ * FIRST_TABLE_ID_INDEX.
+ */
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_OFST 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_LEN 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MINNUM 0
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM 62
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM_MCDI2 254
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+
+
+/***********************************/
+/* MC_CMD_TABLE_DESCRIPTOR
+ * Request the table descriptor for a particular table. This describes
+ * properties of the table and the format of the key and response. May return
+ * EINVAL for unknown table ID.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR 0x1ca
+#define	MC_CMD_TABLE_DESCRIPTOR_MSGSET 0x1ca
+#undef	MC_CMD_0x1ca_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ca_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DESCRIPTOR_IN msgrequest */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_LEN 8
+/* Identifier for this field. */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Index of the first item to be returned in the FIELDS sequence. (Set to 0 for
+ * the first call; further calls are only required if the whole sequence does
+ * not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_LEN 4
+
+/* MC_CMD_TABLE_DESCRIPTOR_OUT msgresponse */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN 28
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX 252
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(num) (20+8*(num))
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(len) (((len)-20)/8)
+/* Maximum number of entries in this table. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_LEN 4
+/* The type of table. (This is really just informational; the important
+ * properties of a table that affect programming can be deduced from other
+ * items in the table or field descriptor.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_LEN 2
+/* enum: Direct table (essentially just an array). Behaves like a BCAM for
+ * programming purposes, where the fact that the key is actually used as an
+ * array index is really just an implementation detail.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_DIRECT 0x1
+/* enum: BCAM (binary CAM) table: exact match on all key fields." */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM 0x2
+/* enum: TCAM (ternary CAM) table: matches fields with a mask. Each entry may
+ * have its own different mask.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_TCAM 0x3
+/* enum: STCAM (semi-TCAM) table: like a TCAM but entries shared a limited
+ * number of unique masks.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_STCAM 0x4
+/* Width of key (and corresponding mask, for TCAM or STCAM) in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_LEN 2
+/* Width of response in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_LEN 2
+/* The total number of fields in the key. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_OFST 10
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_LEN 2
+/* The total number of fields in the response. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_OFST 12
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_LEN 2
+/* Number of priorities for STCAM or TCAM; otherwise 0. The priority of a table
+ * entry (relevant when more than one masked entry matches) ranges from
+ * 0=highest to N_PRIORITIES-1=lowest.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_OFST 14
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_LEN 2
+/* Maximum number of masks for STCAM; otherwise 0. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_OFST 16
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_LEN 2
+/* Flags. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_LEN 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_LBN 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_WIDTH 1
+/* Access scheme version code, allowing the method of accessing table entries
+ * to change semantics in future. A client which does not understand the value
+ * of this field should assume that it cannot program this table. Currently
+ * always set to 0 indicating the original MC_CMD_TABLE_INSERT/UPDATE/DELETE
+ * semantics.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_OFST 19
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_LEN 1
+/* A sequence of TABLE_FIELD_DESCR structures: N_KEY_FIELDS items describing
+ * the key, followed by N_RESP_FIELDS items describing the response. If all
+ * N_KEY_FIELDS+N_RESP_FIELDS items do not fit, further items can be obtained
+ * by repeating the call with a non-zero FIRST_FIELDS_INDEX.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LEN 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LBN 160
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_OFST 24
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LBN 192
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MINNUM 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM 29
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM_MCDI2 125
+
+
+/***********************************/
+/* MC_CMD_TABLE_INSERT
+ * Insert a new entry into a table. The entry must not currently exist. May
+ * return EINVAL for unknown table ID or other bad request parameters, EEXIST
+ * if the entry already exists, ENOSPC if there is no space or EPERM if the
+ * operation is not permitted. In case of an error, the additional MCDI error
+ * argument field returns the raw error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_INSERT 0x1cd
+#define	MC_CMD_TABLE_INSERT_MSGSET 0x1cd
+#undef	MC_CMD_0x1cd_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cd_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_INSERT_IN msgrequest */
+#define	MC_CMD_TABLE_INSERT_IN_LENMIN 16
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX 252
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_INSERT_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_INSERT_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_INSERT_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_INSERT_OUT msgresponse */
+#define	MC_CMD_TABLE_INSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_UPDATE
+ * Update an existing entry in a table with a new response value. May return
+ * EINVAL for unknown table ID or other bad request parameters, ENOENT if the
+ * entry does not already exist, or EPERM if the operation is not permitted. In
+ * case of an error, the additional MCDI error argument field returns the raw
+ * error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_UPDATE 0x1ce
+#define	MC_CMD_TABLE_UPDATE_MSGSET 0x1ce
+#undef	MC_CMD_0x1ce_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ce_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_UPDATE_IN msgrequest */
+#define	MC_CMD_TABLE_UPDATE_IN_LENMIN 16
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX 252
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_UPDATE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_UPDATE_OUT msgresponse */
+#define	MC_CMD_TABLE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_DELETE
+ * Delete an existing entry in a table. May return EINVAL for unknown table ID
+ * or other bad request parameters, ENOENT if the entry does not exist, or
+ * EPERM if the operation is not permitted. In case of an error, the additional
+ * MCDI error argument field returns the raw error code from the underlying CAM
+ * driver.
+ */
+#define	MC_CMD_TABLE_DELETE 0x1cf
+#define	MC_CMD_TABLE_DELETE_MSGSET 0x1cf
+#undef	MC_CMD_0x1cf_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cf_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DELETE_IN msgrequest */
+#define	MC_CMD_TABLE_DELETE_IN_LENMIN 16
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX 252
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DELETE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_DELETE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_DELETE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_DELETE_OUT msgresponse */
+#define	MC_CMD_TABLE_DELETE_OUT_LEN 0
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 02/34] common/sfc_efx/base: detect MCDI Table Access API support
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
                     ` (32 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Future patches will add an implementation of MCDI Table
Access API in libefx. This patch adds a way to determine
if this API is supported.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h          | 2 ++
 drivers/common/sfc_efx/base/hunt_nic.c     | 2 ++
 drivers/common/sfc_efx/base/medford2_nic.c | 2 ++
 drivers/common/sfc_efx/base/medford_nic.c  | 2 ++
 drivers/common/sfc_efx/base/rhead_nic.c    | 9 +++++++++
 drivers/common/sfc_efx/base/siena_nic.c    | 2 ++
 6 files changed, 19 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f4fa88f169..520674a602 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1672,6 +1672,8 @@ typedef struct efx_nic_cfg_s {
 	boolean_t		enc_mae_admin;
 	/* NIC support for MAE action set v2 features. */
 	boolean_t		enc_mae_aset_v2_supported;
+	/* NIC support for MCDI Table Access API. */
+	boolean_t		enc_table_api_supported;
 	/* Firmware support for "FLAG" and "MARK" filter actions */
 	boolean_t		enc_filter_action_flag_supported;
 	boolean_t		enc_filter_action_mark_supported;
diff --git a/drivers/common/sfc_efx/base/hunt_nic.c b/drivers/common/sfc_efx/base/hunt_nic.c
index 08ae324482..04595a39c8 100644
--- a/drivers/common/sfc_efx/base/hunt_nic.c
+++ b/drivers/common/sfc_efx/base/hunt_nic.c
@@ -192,6 +192,8 @@ hunt_board_cfg(
 	/* All Huntington devices have a PCIe Gen3, 8 lane connector */
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford2_nic.c b/drivers/common/sfc_efx/base/medford2_nic.c
index 6d19524573..49adabffb2 100644
--- a/drivers/common/sfc_efx/base/medford2_nic.c
+++ b/drivers/common/sfc_efx/base/medford2_nic.c
@@ -152,6 +152,8 @@ medford2_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford_nic.c b/drivers/common/sfc_efx/base/medford_nic.c
index b111e3eded..9a460b2b9b 100644
--- a/drivers/common/sfc_efx/base/medford_nic.c
+++ b/drivers/common/sfc_efx/base/medford_nic.c
@@ -150,6 +150,8 @@ medford_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index eda6c1c4f9..a773aea38d 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -176,6 +176,15 @@ rhead_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	/*
+	 * FIXME: MCDI table API support depends on an EF100 firmware build
+	 * and an EF100 platform. It should be discovered by using a capability
+	 * flag from MCDI that is not implemented yet.
+	 * Right now we can safely rely on the return code from the libefx
+	 * MCDI Table API.
+	 */
+	encp->enc_table_api_supported = B_TRUE;
+
 	return (0);
 
 fail3:
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 9f14faf271..1f1fb7d2af 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -205,6 +205,8 @@ siena_board_cfg(
 	encp->enc_mae_supported = B_FALSE;
 	encp->enc_mae_admin = B_FALSE;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
 
 	return (0);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
                     ` (31 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

New MCDI Table Access API allows management of
the HW tables' content.
This part of API helps to list all supported tables.
In the near future, only the CT table is planned
to be used, so only one identifier for this table
was added to the efx.
New table IDs will be added as needed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 15 ++++
 drivers/common/sfc_efx/base/efx_table.c | 94 +++++++++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build |  1 +
 drivers/common/sfc_efx/version.map      |  2 +
 4 files changed, 112 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 520674a602..2de08d1230 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5070,6 +5070,21 @@ efx_nic_dma_map(
 	__in		size_t len,
 	__out		efsys_dma_addr_t *nic_addrp);
 
+/* Unique IDs for HW tables */
+typedef enum efx_table_id_e {
+	EFX_TABLE_ID_CONNTRACK = 0x10300,
+} efx_table_id_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
new file mode 100644
index 0000000000..7cfdfea36e
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_LIST_IN_LEN,
+	    MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table IDs */
+	EFX_STATIC_ASSERT(EFX_TABLE_ID_CONNTRACK == TABLE_ID_CONNTRACK_TABLE);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((n_table_ids != 0) &&
+	   ((table_ids == NULL) || (n_table_ids_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_LIST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_LIST_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, entry_ofst);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_LIST_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	if (total_n_tablesp != NULL)
+		*total_n_tablesp = MCDI_OUT_DWORD(req, TABLE_LIST_OUT_N_TABLES);
+
+	n_entries = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(req.emr_out_length_used);
+
+	if (table_ids != NULL) {
+		if (n_entries > n_table_ids) {
+			rc = ENOMEM;
+			goto fail5;
+		}
+
+		for (i = 0; i < n_entries; i++) {
+			table_ids[i] = MCDI_OUT_INDEXED_DWORD(req,
+			    TABLE_LIST_OUT_TABLE_ID, i);
+		}
+	}
+
+	if (n_table_ids_writtenp != NULL)
+		*n_table_ids_writtenp = n_entries;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index ff7f33fb44..7fc04aa57b 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -16,6 +16,7 @@ sources = [
         'efx_lic.c',
         'efx_mac.c',
         'efx_mae.c',
+        'efx_table.c',
         'efx_mcdi.c',
         'efx_mon.c',
         'efx_nic.c',
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index aabc354118..5717cc0ed2 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -232,6 +232,8 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_list;
+
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
 	efx_tunnel_config_udp_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 04/34] common/sfc_efx/base: add macro to get indexed QWORD field
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (2 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
                     ` (30 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Extend MCDI macros to manipulate with fields in indexed QWORDs.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
---
 drivers/common/sfc_efx/base/efx_mcdi.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 14a3833567..f13bf43da6 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -504,6 +504,10 @@ efx_mcdi_set_nic_addr_regions(
 	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
 			(_idx)), _field)
 
+#define	MCDI_OUT_INDEXED_QWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_QWORD_FIELD(*(MCDI_OUT2(_emr, efx_qword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, _type, _arr_ofst, _idx,	\
 		_member_ofst)						\
 	((_type *)(MCDI_OUT2(_emr, uint8_t, _arr_ofst) +		\
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (3 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-07 11:47     ` Andrew Rybchenko
  2023-06-07 12:06     ` Andrew Rybchenko
  2023-06-04 23:24   ` [PATCH v3 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
                     ` (29 subsequent siblings)
  34 siblings, 2 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Table's descriptor and fields' descriptors can be taken
by table ID using a new API.
In the near future, only the CT table is planned
to be used, so only fields that are required for these
purposes were added to the efx.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       |  67 +++++++
 drivers/common/sfc_efx/base/efx_table.c | 256 ++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |   3 +
 3 files changed, 326 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 2de08d1230..8860e4ebbe 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5085,6 +5085,73 @@ efx_table_list(
 	__in					unsigned int n_table_ids,
 	__out_opt				unsigned int *n_table_ids_writtenp);
 
+LIBEFX_API
+extern	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void);
+
+LIBEFX_API
+extern	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id);
+
+/* Unique IDs for table fields */
+typedef enum efx_table_field_id_e {
+	EFX_TABLE_FIELD_ID_UNUSED = 0x0,
+	EFX_TABLE_FIELD_ID_COUNTER_ID = 0xa,
+	EFX_TABLE_FIELD_ID_ETHER_TYPE = 0x1c,
+	EFX_TABLE_FIELD_ID_SRC_IP = 0x1d,
+	EFX_TABLE_FIELD_ID_DST_IP = 0x1e,
+	EFX_TABLE_FIELD_ID_IP_PROTO = 0x20,
+	EFX_TABLE_FIELD_ID_SRC_PORT = 0x21,
+	EFX_TABLE_FIELD_ID_DST_PORT = 0x22,
+	EFX_TABLE_FIELD_ID_NAT_PORT = 0x7a,
+	EFX_TABLE_FIELD_ID_NAT_IP = 0x7b,
+	EFX_TABLE_FIELD_ID_NAT_DIR = 0x7c,
+	EFX_TABLE_FIELD_ID_CT_MARK = 0x7d,
+} efx_table_field_id_t;
+
+/* Table fields mask types */
+typedef enum efx_table_field_mask_type_e {
+	EFX_TABLE_FIELD_MASK_NEVER = 0x0,
+	EFX_TABLE_FIELD_MASK_EXACT = 0x1,
+} efx_table_field_mask_type_t;
+
+typedef struct efx_table_field_desc_s {
+	efx_table_field_id_t		field_id;
+	uint16_t			lbn;
+	uint16_t			width;
+	efx_table_field_mask_type_t	mask_type;
+	uint8_t				scheme;
+} efx_table_field_descriptor_t;
+
+/* Types of HW tables */
+typedef enum efx_table_type_e {
+	/* Exact match to all key fields of table entry. */
+	EFX_TABLE_TYPE_BCAM = 0x2,
+} efx_table_type_t;
+
+typedef struct efx_table_descriptor_s {
+	efx_table_type_t	type;
+	uint16_t		key_width;
+	uint16_t		resp_width;
+	/* Number of key's fields to match data */
+	uint16_t		n_key_fields;
+	/* Number of fields in match response */
+	uint16_t		n_resp_fields;
+} efx_table_descriptor_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(*n_fields_descsp)	efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 7cfdfea36e..115d86502f 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -6,6 +6,11 @@
 #include "efx.h"
 #include "efx_impl.h"
 
+/* List of HW tables that have support in efx */
+static const efx_table_id_t efx_supported_table_ids[] = {
+	EFX_TABLE_ID_CONNTRACK,
+};
+
 	__checkReturn				efx_rc_t
 efx_table_list(
 	__in					efx_nic_t *enp,
@@ -80,6 +85,257 @@ efx_table_list(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void)
+{
+	return EFX_ARRAY_SIZE(efx_supported_table_ids);
+}
+
+	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id)
+{
+	size_t i;
+
+	for (i = 0; i < efx_table_supported_num_get(); i++) {
+		if (efx_supported_table_ids[i] == table_id)
+			return B_TRUE;
+	}
+
+	return B_FALSE;
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_ct_desc_fields_check(
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+	efx_rc_t rc;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		switch (fields_descsp[i].field_id) {
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+		case EFX_TABLE_FIELD_ID_DST_IP:
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
+				rc = EINVAL;
+				goto fail1;
+			}
+			break;
+		/*
+		 * TODO:
+		 * All fields in the CT table have EXACT mask.
+		 * All the response field descriptors must have the EXACT mask.
+		 * In the current implementation, only the Ethertype, source and
+		 * destination IP address, IP protocol, and source and destination IP
+		 * are used for the lookup by the key.
+		 * FW could use the NEVER mask for the fields in the key that are not
+		 * used for the lookup.
+		 * As an alternative, a new mask could be added for these fields,
+		 * like EXACT_NOT_USED.
+		 */
+		default:
+			if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
+			    (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
+				rc = EINVAL;
+				goto fail2;
+			}
+			break;
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_desc_fields_check(
+	__in				efx_table_id_t table_id,
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	efx_rc_t rc;
+
+	switch (table_id) {
+	case EFX_TABLE_ID_CONNTRACK:
+		rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
+		if (rc != 0)
+			goto fail1;
+		break;
+	default:
+		break;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static					void
+efx_table_desc_fields_get(
+	__in				const efx_mcdi_req_t *req,
+	__out_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		fields_descsp[i].field_id = (efx_table_field_id_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
+
+		fields_descsp[i].lbn =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
+
+		fields_descsp[i].width =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
+
+		fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
+
+		fields_descsp[i].scheme =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
+	}
+}
+
+	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
+	    MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table types */
+	EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
+
+	/* Ensure EFX and MCDI use same values for table fields */
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (!efx_table_is_supported(table_id)) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((n_field_descs != 0) &&
+	    ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	if (table_descp != NULL) {
+		table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_TYPE);
+		table_descp->key_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
+		table_descp->resp_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
+		table_descp->n_key_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
+		table_descp->n_resp_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
+	}
+
+	n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
+
+	if (fields_descs != NULL) {
+		if (n_entries > n_field_descs) {
+			rc = ENOMEM;
+			goto fail6;
+		}
+
+		efx_table_desc_fields_get(&req, fields_descs, n_entries);
+		rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
+		if (rc != 0)
+			goto fail7;
+	}
+
+	if (n_field_descs_writtenp != NULL)
+		*n_field_descs_writtenp = n_entries;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 5717cc0ed2..a87cb1bba5 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -232,7 +232,10 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_describe;
+	efx_table_is_supported;
 	efx_table_list;
+	efx_table_supported_num_get;
 
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 06/34] common/sfc_efx/base: add API to insert data to HW table
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (4 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
                     ` (28 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to insert data to any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 16 +++++
 drivers/common/sfc_efx/base/efx_table.c | 79 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 96 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 8860e4ebbe..1b01a8ec8b 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5152,6 +5152,22 @@ efx_table_describe(
 	__in					unsigned int n_field_descs,
 	__out_opt				unsigned int *n_field_descs_writtenp);
 
+/* Maximum possible size of data for manipulation of the tables */
+#define EFX_TABLE_ENTRY_LENGTH_MAX	1008
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 115d86502f..63fc319666 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -338,6 +338,85 @@ efx_table_describe(
 	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_INSERT_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_INSERT_IN_LENMAX  * sizeof(uint32_t)) ==
+	    EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_INSERT_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_INSERT_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_INSERT_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_PRIORITY, priority);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_WIDTH, mask_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_RESP_WIDTH, resp_width);
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_INSERT_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index a87cb1bba5..2be519e0e1 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
 	efx_table_supported_num_get;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 07/34] common/sfc_efx/base: add API to delete entry from HW table
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (5 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-04 23:24   ` [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
                     ` (27 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to delete entry from any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 11 ++++
 drivers/common/sfc_efx/base/efx_table.c | 77 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 89 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 1b01a8ec8b..f96e398460 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5168,6 +5168,17 @@ efx_table_entry_insert(
 	__in_bcount(data_size)		uint8_t *entry_datap,
 	__in				unsigned int data_size);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 63fc319666..10a1c2ddcd 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -419,6 +419,83 @@ efx_table_entry_insert(
 
 fail4:
 	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_DELETE_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_DELETE_IN_LENMAX  * sizeof(uint32_t)) ==
+		EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DELETE_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DELETE_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DELETE_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_WIDTH, mask_width);
+
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_DELETE_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 2be519e0e1..d083a54a03 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_delete;
 	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (6 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-07 11:53     ` Andrew Rybchenko
  2023-06-04 23:24   ` [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
                     ` (26 subsequent siblings)
  34 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

A "table" is structure used for lookups, consisting of a set of
entries which can be matched against an N-bit "request", to
return either a "hit" with an M-bit "response", or a "miss" if
there is no match. There are a number of HW tables of various
types that could be used in MAE.

In some types of table the entry may also be associated with an
N-bit "mask", allowing some bits of the request to be treated as
don't-care, and an integer "priority" to determine which entry is
used if more than one matches.

BCAM tables don't support "mask" and "priority", so the
corresponding fields must be zeroed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_tbls.h | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.h

diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
new file mode 100644
index 0000000000..2a5c87b82c
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBLS_H
+#define _SFC_TBLS_H
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Table types:
+ *   CAM - Content addressable memory
+ *  BCAM - Binary CAM
+ *  TCAM - Ternary CAM
+ * STCAM - Semi-ternary CAM
+ *
+ * Short description:
+ * TCAM:  Each entry has a key, mask, response and priority. An entry matches
+ *        when (key & mask) == (request & mask). In the case of multiple
+ *        matches, the entry with the highest priority wins; Each entry may
+ *        have its own mask, but TCAM table definitions may place constraints
+ *        on the possible masks allowed for each of the individual fields.
+ * STCAM: A limited form of TCAM in which only a limited number of masks and
+ *        associated priorities), up to some maximum fixed by the definition
+ *        of the table, may be in use at any one time.
+ * BCAM:  Each entry has only a key and response, with the whole request
+ *        matched against the key (like a typical hash table or "map").
+ * Direct (sometimes "DCAM", although it's not really content-addressable):
+ *        Essentially just an array, where the key bits are used simply as an
+ *        index.
+ */
+
+/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
+#define SFC_TBLS_BCAM_PRIORITY		0
+
+/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
+#define SFC_TBLS_BCAM_MASK_ID		0
+
+/* Mask is used only for STCAM */
+#define SFC_TBLS_BCAM_MASK_WIDTH	0
+
+static inline int
+sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
+				      SFC_TBLS_BCAM_MASK_ID, key_width,
+				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
+				      data, data_size);
+}
+
+static inline int
+sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
+				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
+				      data, data_size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_TBLS_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (7 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-07 12:00     ` Andrew Rybchenko
  2023-06-04 23:24   ` [PATCH v3 10/34] net/sfc: attach to HW table API Ivan Malov
                     ` (25 subsequent siblings)
  34 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Implemented functions that help to fill user data for
manipulation with HW tables in the required format.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |   1 +
 drivers/net/sfc/sfc_tbls.c  | 140 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbls.h  | 135 ++++++++++++++++++++++++++++++++++
 3 files changed, 276 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.c

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c2d8430810..39c7f24764 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -87,6 +87,7 @@ sources = files(
         'sfc_tso.c',
         'sfc_filter.c',
         'sfc_switch.c',
+        'sfc_tbls.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
new file mode 100644
index 0000000000..db54fc0d40
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc_tbls.h"
+#include "sfc_debug.h"
+
+#include <rte_ip.h>
+
+/* Number of bits in uint32_t type */
+#define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
+
+static uint32_t
+sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t mask;
+
+	if (width == SFC_TBLS_U32_BITS)
+		return value;
+
+	mask = RTE_LEN2MASK(width, uint32_t);
+	value &= mask;
+
+	if (lbn != 0) {
+		mask <<= lbn;
+		value <<= lbn;
+	}
+
+	return (in & (~mask)) | value;
+}
+
+void
+sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	if (lbn + width <= SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, lbn, width, value);
+	} else {
+		*data = sfc_tbls_field_update(*data, lbn,
+					      SFC_TBLS_U32_BITS - lbn, value);
+		value >>= SFC_TBLS_U32_BITS - lbn;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+		*data = sfc_tbls_field_update(*data, 0,
+					      width + lbn - SFC_TBLS_U32_BITS,
+					      value);
+	}
+}
+
+void
+sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, uint16_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      uint16_t width, uint8_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      __rte_unused uint16_t width, const uint32_t *ip)
+{
+	unsigned int i;
+	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
+
+	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
+
+	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
+		sfc_tbls_field_set_u32(data, data_size, lbn,
+				       SFC_TBLS_U32_BITS, ip[i]);
+		lbn += SFC_TBLS_U32_BITS;
+	}
+}
+
+void
+sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint64_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
+	value >>= SFC_TBLS_U32_BITS - lbn;
+	width -= SFC_TBLS_U32_BITS - lbn;
+
+	data_offset++;
+	SFC_ASSERT(data_offset < data_size);
+
+	data++;
+
+	if (width > SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
+		value >>= SFC_TBLS_U32_BITS;
+		width -= SFC_TBLS_U32_BITS;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+	}
+
+	*data = sfc_tbls_field_update(*data, 0, width, value);
+}
+
+void
+sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, bool value)
+{
+	SFC_ASSERT(width == 1);
+
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
+}
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 2a5c87b82c..7b6bb5b341 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -63,6 +63,141 @@ sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key
 				      data, data_size);
 }
 
+/**
+ * All manipulations with HW tables entries require forming
+ * a key and response.
+ * The key and response fields follow, consecutively, each
+ * packed as follows:
+ *  - the key/response is logically treated as a single wide N-bit value;
+ *  - fields have been placed in these logical values per the "lbn" and "width"
+ *    information from the table field descriptors;
+ *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
+ *  - the values are put into the table op request with bits[31:0] of the wide
+ *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
+ *
+ * Below is an API that helps to form  MCDI insertion/deletion request.
+ * Workflow:
+ * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
+ * 2) Read a descriptor of the table that you want to use.
+ * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
+ *    Each field of the key has LBN and width. This information can be
+ *    found in a field's descriptor.
+ * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
+ *    must start. It's required as the key and response need to be
+ *    zero-padded at the MSB end to multiples of 32 bits.
+ * 5) Fill the response the same way.
+ * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
+ *    It will help you to get the real size of the data request.
+ */
+
+/**
+ * Get a pointer to the beginning of the next 32-bit wide fields
+ * that go after a given width.
+ * It should be used to get a pointer to the response's start and the end
+ * of the data for an MCDI request.
+ *
+ * @param data		Pointer to the data to make an offset from
+ * @param width		Width of fields to offset
+ *
+ * @note @p width is expected to be a key's or response's size.
+ *
+ * @return Pointer to the beginning of the next field.
+ */
+static inline uint32_t *
+sfc_tbls_next_req_fields(uint32_t *data, uint16_t width) {
+	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
+}
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint32_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint32_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint16_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint16_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint8_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, uint8_t value);
+
+/**
+ * Insert IP address into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param ip		IP address to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, const uint32_t *ip);
+
+/**
+ * Insert value into a field in the data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint64_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint64_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		Bit value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, bool value);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 10/34] net/sfc: attach to HW table API
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (8 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
@ 2023-06-04 23:24   ` Ivan Malov
  2023-06-07 12:08     ` Andrew Rybchenko
  2023-06-04 23:25   ` [PATCH v3 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
                     ` (24 subsequent siblings)
  34 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:24 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The patch adds APIs to initialise, manipulate and finalise
HW tables API-specific context in NIC control structure.
The context itself will be used to store HW tables-related info,
like table descriptors and field descriptors.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build          |   4 +-
 drivers/net/sfc/sfc.c                |  18 +-
 drivers/net/sfc/sfc.h                |   2 +
 drivers/net/sfc/sfc_tbl_meta.c       |  71 ++++++++
 drivers/net/sfc/sfc_tbl_meta.h       |  37 ++++
 drivers/net/sfc/sfc_tbl_meta_cache.c | 253 +++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbl_meta_cache.h |  25 +++
 drivers/net/sfc/sfc_tbls.c           |  60 +++++++
 drivers/net/sfc/sfc_tbls.h           |  81 +++++++++
 9 files changed, 549 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 39c7f24764..c9d4264674 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -71,7 +71,7 @@ if not cc.links(atomic_check_code)
     ext_deps += libatomic_dep
 endif
 
-deps += ['common_sfc_efx', 'bus_pci']
+deps += ['common_sfc_efx', 'bus_pci', 'hash']
 sources = files(
         'sfc_ethdev.c',
         'sfc_kvargs.c',
@@ -88,6 +88,8 @@ sources = files(
         'sfc_filter.c',
         'sfc_switch.c',
         'sfc_tbls.c',
+        'sfc_tbl_meta.c',
+        'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 22753e3417..a56521696a 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -491,6 +491,10 @@ sfc_try_start(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_ev_start;
 
+	rc = sfc_tbls_start(sa);
+	if (rc != 0)
+		goto fail_tbls_start;
+
 	rc = sfc_port_start(sa);
 	if (rc != 0)
 		goto fail_port_start;
@@ -526,9 +530,12 @@ sfc_try_start(struct sfc_adapter *sa)
 fail_rx_start:
 	sfc_port_stop(sa);
 
-fail_port_start:
+fail_tbls_start:
 	sfc_ev_stop(sa);
 
+fail_port_start:
+	sfc_tbls_stop(sa);
+
 fail_ev_start:
 	sfc_intr_stop(sa);
 
@@ -626,6 +633,7 @@ sfc_stop(struct sfc_adapter *sa)
 	sfc_tx_stop(sa);
 	sfc_rx_stop(sa);
 	sfc_port_stop(sa);
+	sfc_tbls_stop(sa);
 	sfc_ev_stop(sa);
 	sfc_intr_stop(sa);
 	efx_nic_fini(sa->nic);
@@ -983,6 +991,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_attach;
 
+	rc = sfc_tbls_attach(sa);
+	if (rc != 0)
+		goto fail_tables_attach;
+
 	rc = sfc_mae_switchdev_init(sa);
 	if (rc != 0)
 		goto fail_mae_switchdev_init;
@@ -1025,6 +1037,9 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_mae_switchdev_fini(sa);
 
 fail_mae_switchdev_init:
+	sfc_tbls_detach(sa);
+
+fail_tables_attach:
 	sfc_mae_detach(sa);
 
 fail_mae_attach:
@@ -1088,6 +1103,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
+	sfc_tbls_detach(sa);
 	sfc_mae_detach(sa);
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 730d054aea..6b301aad60 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -31,6 +31,7 @@
 #include "sfc_flow_tunnel.h"
 #include "sfc_sriov.h"
 #include "sfc_mae.h"
+#include "sfc_tbls.h"
 #include "sfc_dp.h"
 #include "sfc_sw_stats.h"
 #include "sfc_repr_proxy.h"
@@ -244,6 +245,7 @@ struct sfc_adapter {
 	struct sfc_ft_ctx		ft_ctx_pool[SFC_FT_MAX_NTUNNELS];
 	struct sfc_filter		filter;
 	struct sfc_mae			mae;
+	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
 	struct sfc_flow_list		flow_list;
diff --git a/drivers/net/sfc/sfc_tbl_meta.c b/drivers/net/sfc/sfc_tbl_meta.c
new file mode 100644
index 0000000000..997082fd74
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_tbl_meta.h"
+#include "sfc_tbl_meta_cache.h"
+
+const struct sfc_tbl_meta *
+sfc_tbl_meta_lookup(struct sfc_adapter *sa, efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta;
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return NULL;
+
+	rc = rte_hash_lookup_data(tables->meta.cache, (const void *)&table_id,
+				  (void **)&meta);
+	if (rc < 0)
+		return NULL;
+
+	SFC_ASSERT(meta != NULL);
+	SFC_ASSERT(meta->table_id == table_id);
+
+	return meta;
+}
+
+int
+sfc_tbl_meta_init(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return 0;
+
+	rc = sfc_tbl_meta_cache_ctor(&meta->cache);
+	if (rc != 0)
+		return rc;
+
+	rc = sfc_tbl_meta_cache_update(meta->cache, sa->nic);
+	if (rc != 0) {
+		sfc_tbl_meta_cache_dtor(&meta->cache);
+		return rc;
+	}
+
+	return 0;
+}
+
+void
+sfc_tbl_meta_fini(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+
+	if (meta->cache == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(tables->status == SFC_TBLS_STATUS_SUPPORTED);
+
+	sfc_tbl_meta_cache_dtor(&meta->cache);
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta.h b/drivers/net/sfc/sfc_tbl_meta.h
new file mode 100644
index 0000000000..7d39957514
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_H
+#define _SFC_TBL_META_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Metadata about table layout */
+struct sfc_tbl_meta {
+	efx_table_id_t			table_id;
+	efx_table_descriptor_t		descriptor;
+	efx_table_field_descriptor_t	*keys;
+	efx_table_field_descriptor_t	*responses;
+};
+
+struct sfc_tbl_meta_cache {
+	struct rte_hash	*cache;
+};
+
+struct sfc_adapter;
+
+const struct sfc_tbl_meta *sfc_tbl_meta_lookup(struct sfc_adapter *sa,
+					       efx_table_id_t table_id);
+
+int sfc_tbl_meta_init(struct sfc_adapter *sa);
+void sfc_tbl_meta_fini(struct sfc_adapter *sa);
+
+#endif /* _SFC_TBL_META_H */
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.c b/drivers/net/sfc/sfc_tbl_meta_cache.c
new file mode 100644
index 0000000000..65ba0b001e
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.c
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include <rte_malloc.h>
+#include <rte_jhash.h>
+
+#include "sfc_tbl_meta_cache.h"
+#include "sfc_debug.h"
+
+/* The minimal size of the table meta cache */
+#define SFC_TBL_META_CACHE_SIZE_MIN	8
+
+int
+sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
+{
+	size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
+				    efx_table_supported_num_get());
+	struct rte_hash *cache = NULL;
+	const struct rte_hash_parameters hash_params = {
+		.name       = "meta_hash_table",
+		.hash_func  = rte_jhash,
+		.entries    = cache_size,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(efx_table_id_t),
+	};
+
+	cache = rte_hash_create(&hash_params);
+	if (!cache)
+		return -ENOMEM;
+
+	*ref_cache = cache;
+
+	return 0;
+}
+
+static void
+sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
+{
+	SFC_ASSERT(meta != NULL);
+
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+	rte_free(meta);
+}
+
+void
+sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
+{
+	struct rte_hash *cache = *ref_cache;
+	const void *next_key;
+	uint32_t iter = 0;
+	void *next_meta;
+
+	if (cache == NULL)
+		return;
+
+	while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
+		sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
+
+	rte_hash_free(cache);
+
+	*ref_cache = NULL;
+}
+
+/**
+ * Table descriptor contains information about the table's
+ * fields that can be associated with both the key and the response.
+ * Save these fields by separating the key from the response in
+ * appropriate places based on their lengths.
+ */
+static int
+sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+			      efx_table_field_descriptor_t *fields,
+			      unsigned int total_n_fields)
+{
+	uint16_t n_key_fields = meta->descriptor.n_key_fields;
+	size_t field_size = sizeof(*fields);
+	unsigned int n_field_descs_written;
+	uint32_t field_offset;
+	int rc;
+
+	for (n_field_descs_written = 0, field_offset = 0;
+	     field_offset < total_n_fields;
+	     field_offset += n_field_descs_written) {
+		rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
+					fields, total_n_fields, &n_field_descs_written);
+		if (rc != 0)
+			return rc;
+
+		if (field_offset + n_field_descs_written > total_n_fields)
+			return -EINVAL;
+
+		if (field_offset < n_key_fields &&
+		    field_offset + n_field_descs_written > n_key_fields) {
+			/*
+			 * Some of the descriptors belong to key,
+			 * the other to response.
+			 */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, (n_key_fields - field_offset) * field_size);
+			rte_memcpy(meta->responses,
+				   RTE_PTR_ADD(fields,
+				   (n_key_fields - field_offset) * field_size),
+				   (field_offset + n_field_descs_written - n_key_fields) *
+				   field_size);
+		} else if (field_offset < n_key_fields) {
+			/* All fields belong to the key */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, n_field_descs_written * field_size);
+		} else {
+			/* All fields belong to the response */
+			rte_memcpy(RTE_PTR_ADD(meta->responses,
+				   (field_offset - n_key_fields) * field_size),
+				   fields, n_field_descs_written * field_size);
+		}
+	}
+
+	return 0;
+}
+
+static int
+sfc_tbl_meta_desc_read(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	efx_table_field_descriptor_t *fields;
+	unsigned int total_n_fields;
+	int rc;
+
+	rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
+
+	fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
+	if (fields == NULL)
+		return -ENOMEM;
+
+	meta->table_id = table_id;
+
+	meta->keys = rte_calloc("efx_table_key_field_descs",
+				meta->descriptor.n_key_fields,
+				sizeof(*meta->keys), 0);
+	if (meta->keys == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_keys;
+	}
+
+	meta->responses = rte_calloc("efx_table_response_field_descs",
+				     meta->descriptor.n_resp_fields,
+				     sizeof(*meta->responses), 0);
+	if (meta->responses == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_responses;
+	}
+
+	rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
+	if (rc != 0)
+		goto fail_copy_fields;
+
+	return 0;
+
+fail_copy_fields:
+	rte_free(meta->responses);
+fail_alloc_responses:
+	rte_free(meta->keys);
+fail_alloc_keys:
+	rte_free(fields);
+
+	return rc;
+}
+
+static int
+sfc_tbl_meta_cache_add(struct rte_hash *cache, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta = NULL;
+	int rc;
+
+	meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
+	if (meta == NULL)
+		return -ENOMEM;
+
+	rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
+	if (rc != 0)
+		goto fail_read_meta;
+
+	rc = rte_hash_add_key_data(cache, &table_id, meta);
+	if (rc != 0)
+		goto fail_add_key;
+
+	return 0;
+
+fail_add_key:
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+fail_read_meta:
+	rte_free(meta);
+
+	return rc;
+}
+
+int
+sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp)
+{
+	efx_table_id_t *table_ids = NULL;
+	unsigned int n_table_ids_written;
+	unsigned int total_n_tables;
+	unsigned int n_table_ids;
+	uint32_t table_index;
+	unsigned int i;
+	int rc = 0;
+
+	rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
+	if (table_ids == NULL)
+		return -ENOMEM;
+
+	n_table_ids = total_n_tables;
+
+	for (table_index = 0, n_table_ids_written = 0;
+	     table_index < total_n_tables;
+	     table_index += n_table_ids_written) {
+		rc = efx_table_list(enp, table_index, NULL,
+				    table_ids, n_table_ids, &n_table_ids_written);
+		if (rc != 0)
+			goto out;
+
+		if (table_index + n_table_ids_written > total_n_tables) {
+			rc = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < n_table_ids_written; i++, table_index++) {
+			if (!efx_table_is_supported(table_ids[i]))
+				continue;
+
+			rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
+			if (rc != 0)
+				goto out;
+		}
+	}
+
+out:
+	rte_free(table_ids);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.h b/drivers/net/sfc/sfc_tbl_meta_cache.h
new file mode 100644
index 0000000000..2deff620a4
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_CACHE_H
+#define _SFC_TBL_META_CACHE_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#include "sfc_tbl_meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache);
+
+void sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache);
+
+int sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp);
+
+#endif /* _SFC_TBLS_DESC_CACHE_H */
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
index db54fc0d40..d41b961454 100644
--- a/drivers/net/sfc/sfc_tbls.c
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2023 Advanced Micro Devices, Inc.
  */
 
+#include "sfc.h"
 #include "sfc_tbls.h"
 #include "sfc_debug.h"
 
@@ -11,6 +12,65 @@
 /* Number of bits in uint32_t type */
 #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
 
+int
+sfc_tbls_attach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	const struct sfc_mae *mae = &sa->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	if (mae->status != SFC_MAE_STATUS_ADMIN ||
+	    !encp->enc_table_api_supported) {
+		tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	tables->status = SFC_TBLS_STATUS_SUPPORTED;
+
+	rc = sfc_tbl_meta_init(sa);
+	if (rc != 0)
+		return rc;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_tbls_detach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+
+	sfc_log_init(sa, "entry");
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		goto done;
+
+	sfc_tbl_meta_fini(sa);
+
+done:
+	sfc_log_init(sa, "done");
+
+	tables->status = SFC_TBLS_STATUS_UNKNOWN;
+}
+
+int
+sfc_tbls_start(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
+		rc = sfc_tbls_attach(sa);
+		return rc;
+	}
+
+	return 0;
+}
+
 static uint32_t
 sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
 {
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 7b6bb5b341..be0abbf161 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -8,6 +8,8 @@
 
 #include "efx.h"
 
+#include "sfc_tbl_meta.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -44,6 +46,85 @@ extern "C" {
 /* Mask is used only for STCAM */
 #define SFC_TBLS_BCAM_MASK_WIDTH	0
 
+/** Options for HW tables support status */
+enum sfc_tbls_status {
+	SFC_TBLS_STATUS_UNKNOWN = 0,
+	SFC_TBLS_STATUS_UNSUPPORTED,
+	SFC_TBLS_STATUS_SUPPORTED,
+};
+
+/**
+ * Entry point to access HW tables
+ *
+ * SFC driver can access hardware (HW) tables.
+ * Interaction with HW tables is done through the MCDI table access API
+ * that is implemented in EFX.
+ *
+ * In order to manipulate data on HW tables it's necessary to
+ * - discover the list of supported tables;
+ * - read a table descriptor to get details of the structure
+ *   of the table;
+ * - get named fields of the table;
+ * - insert/delete/update table entries based on given fields
+ *   and information about the table
+ *
+ * All table layout data should be saved in a cache.
+ * The cache allows to avoid getting the table descriptor each time when you want
+ * to manipulate table entries. It just contains the table
+ * descriptors and all associated data. The cache is based on the RTE hash map and
+ * it uses a table ID as a key.
+ * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
+ * to get all information about the tables without worrying about the cache.
+ *
+ * +------------------------+
+ * | Cache is uninitialized |<----------------------------------+
+ * +------------------------+					|
+ *	|							|
+ *	| sfc_attach()						|
+ *	| sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
+ *	V					^
+ * +------------------------+			|
+ * |  Cache is initialized  |			+-------+
+ * +------------------------+				|
+ *	| sfc_start()					|
+ *	| sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | and valid              |				|
+ * +------------------------+				|
+ *	|						|
+ *	| sfc_restart()					|
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | but can be invalid     |				|
+ * +------------------------+---------------------------+
+ */
+struct sfc_tbls {
+	struct sfc_tbl_meta_cache	meta;
+	enum sfc_tbls_status		status;
+};
+
+struct sfc_adapter;
+
+static inline bool
+sfc_tbls_id_is_supported(struct sfc_adapter *sa,
+			 efx_table_id_t table_id)
+{
+	return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
+}
+
+int sfc_tbls_attach(struct sfc_adapter *sa);
+void sfc_tbls_detach(struct sfc_adapter *sa);
+int sfc_tbls_start(struct sfc_adapter *sa);
+
+static inline void
+sfc_tbls_stop(struct sfc_adapter *sa)
+{
+	sfc_tbls_detach(sa);
+}
+
 static inline int
 sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
 			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 11/34] net/sfc: add API to manage HW Conntrack table
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (9 preceding siblings ...)
  2023-06-04 23:24   ` [PATCH v3 10/34] net/sfc: attach to HW table API Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
                     ` (23 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The new API allows to manipulate entries in
the HW Conntrack table.
It uses a new Table Access API as a backend.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_mae_ct.c | 201 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae_ct.h |  68 ++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c9d4264674..5adde68517 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -92,6 +92,7 @@ sources = files(
         'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
+        'sfc_mae_ct.c',
         'sfc_flow.c',
         'sfc_flow_rss.c',
         'sfc_flow_tunnel.c',
diff --git a/drivers/net/sfc/sfc_mae_ct.c b/drivers/net/sfc/sfc_mae_ct.c
new file mode 100644
index 0000000000..fd6819c8a5
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_mae_ct.h"
+
+/* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
+static void
+sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
+			   const efx_table_field_descriptor_t *fields,
+			   unsigned int n_fields, uint32_t *mcdi_key,
+			   unsigned int key_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+			sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
+					      desc->width, key->ip_proto);
+			break;
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->ether_type_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->src_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->dst_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->src_addr_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->dst_addr_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+/* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
+static void
+sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t *response,
+				     const efx_table_field_descriptor_t *fields,
+				     unsigned int n_fields, uint32_t *mcdi_resp,
+				     unsigned int resp_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		/* Fields of responses are always reported with the EXACT type. */
+		SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_CT_MARK:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->ct_mark);
+			break;
+		case EFX_TABLE_FIELD_ID_COUNTER_ID:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->counter_id);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_DIR:
+			sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
+					      desc->width, response->nat.dir_is_dst);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_IP:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.ip_le);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_PORT:
+			sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.port_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+int
+sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key,
+			 const sfc_mae_conntrack_response_t *response)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int response_size;
+	uint32_t *response_data;
+	unsigned int data_size;
+	unsigned int key_size;
+	uint32_t *start_data;
+	uint16_t resp_width;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+	resp_width = meta->descriptor.resp_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	response_data = sfc_tbls_next_req_fields(key_data, key_width);
+	end_data = sfc_tbls_next_req_fields(response_data, resp_width);
+
+	key_size = RTE_PTR_DIFF(response_data, key_data);
+	response_size = RTE_PTR_DIFF(end_data, response_data);
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields, key_data,
+				   key_size);
+	sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
+					     meta->descriptor.n_resp_fields,
+					     response_data, response_size);
+
+	rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, resp_width, data,
+					data_size);
+
+	return rc;
+}
+
+int
+sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int data_size;
+	uint32_t *start_data;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	end_data = sfc_tbls_next_req_fields(key_data, key_width);
+
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields,
+				   key_data, data_size);
+
+	rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, data, data_size);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae_ct.h b/drivers/net/sfc/sfc_mae_ct.h
new file mode 100644
index 0000000000..b5a3181cd3
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_MAE_CONNTRACK_H
+#define _SFC_MAE_CONNTRACK_H
+
+#include <stdbool.h>
+
+#include <rte_ip.h>
+
+#include "efx.h"
+
+#include "sfc_tbls.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sfc_mae_conntrack_key_s {
+	uint8_t		ip_proto;
+	uint16_t	ether_type_le;
+
+	uint16_t	src_port_le;
+	uint16_t	dst_port_le;
+
+	uint8_t		src_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr)];
+	uint8_t		dst_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, dst_addr)];
+} sfc_mae_conntrack_key_t;
+
+typedef struct sfc_mae_conntrack_nat_s {
+	uint32_t	ip_le;
+	uint16_t	port_le;
+	bool		dir_is_dst;
+} sfc_mae_conntrack_nat_t;
+
+typedef struct sfc_mae_conntrack_response_s {
+	uint32_t		ct_mark;
+	sfc_mae_conntrack_nat_t	nat;
+	uint32_t		counter_id;
+} sfc_mae_conntrack_response_t;
+
+struct sfc_adapter;
+
+static inline bool
+sfc_mae_conntrack_is_supported(struct sfc_adapter *sa)
+{
+	return sfc_tbls_id_is_supported(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+static inline const struct sfc_tbl_meta *
+sfc_mae_conntrack_meta_lookup(struct sfc_adapter *sa)
+{
+	return sfc_tbl_meta_lookup(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+int sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key,
+			     const sfc_mae_conntrack_response_t *response);
+
+int sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_CONNTRACK_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 12/34] net/sfc: make entry pointer optional in MAE resource helpers
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (10 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
                     ` (22 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Keep NULL object check in one place rather than repeat it in
all of the callers. That should make the code easier on eyes.
Future code for additional object types will follow this way.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 78 ++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e5e9257998..1928d58779 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -402,6 +402,9 @@ sfc_mae_outer_rule_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(rule->refcnt != 0);
 
@@ -429,11 +432,16 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_outer_rule *rule,
 			  efx_mae_match_spec_t *match_spec_action)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(rule->match_spec != NULL);
@@ -480,11 +488,16 @@ static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -1057,6 +1070,9 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(action_set->refcnt != 0);
 
@@ -1092,15 +1108,24 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
-	struct sfc_mae_mac_addr *dst_mac_addr = action_set->dst_mac_addr;
-	struct sfc_mae_mac_addr *src_mac_addr = action_set->src_mac_addr;
-	struct sfc_mae_counter_id *counters = action_set->counters;
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae_mac_addr *dst_mac_addr;
+	struct sfc_mae_mac_addr *src_mac_addr;
+	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	encap_header = action_set->encap_header;
+	dst_mac_addr = action_set->dst_mac_addr;
+	src_mac_addr = action_set->src_mac_addr;
+	counters = action_set->counters;
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
@@ -1167,11 +1192,16 @@ static void
 sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
@@ -1226,11 +1256,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 
-	if (spec_mae->outer_rule != NULL)
-		sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-
-	if (spec_mae->action_set != NULL)
-		sfc_mae_action_set_del(sa, spec_mae->action_set);
+	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
+	sfc_mae_action_set_del(sa, spec_mae->action_set);
 
 	if (spec_mae->match_spec != NULL)
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
@@ -2575,9 +2602,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
 						  &invalid_rule_id);
 	if (rc != 0) {
-		if (*rulep != NULL)
-			sfc_mae_outer_rule_del(sa, *rulep);
-
+		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
 
 		return rte_flow_error_set(error, rc,
@@ -3979,10 +4004,15 @@ static int
 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 				struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
 	struct sfc_mae_outer_rule *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return 0;
+
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
 		/* An active rule is reused. It's class is wittingly valid. */
 		return 0;
@@ -4069,11 +4099,9 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (sa->state != SFC_ETHDEV_STARTED)
 		return EAGAIN;
 
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
-		if (rc != 0)
-			return rc;
-	}
+	rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
+	if (rc != 0)
+		return rc;
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
@@ -4139,8 +4167,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4175,8 +4202,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 13/34] net/sfc: turn flow create/destroy methods into lock wrappers
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (11 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
                     ` (21 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is useful to facilitate driver-internal flow rework.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 42 ++++++++++++++++++++++++++++++--------
 drivers/net/sfc/sfc_flow.h |  9 ++++++++
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index fe1f5ba55f..432295ea62 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2610,16 +2610,32 @@ sfc_flow_create(struct rte_eth_dev *dev,
 		struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow *flow;
+
+	sfc_adapter_lock(sa);
+	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	sfc_adapter_unlock(sa);
+
+	return flow;
+}
+
+struct rte_flow *
+sfc_flow_create_locked(struct sfc_adapter *sa,
+		       const struct rte_flow_attr *attr,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow_error *error)
+{
 	struct rte_flow *flow = NULL;
 	int rc;
 
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
 	flow = sfc_flow_zmalloc(error);
 	if (flow == NULL)
 		goto fail_no_mem;
 
-	sfc_adapter_lock(sa);
-
-	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
@@ -2631,8 +2647,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 			goto fail_flow_insert;
 	}
 
-	sfc_adapter_unlock(sa);
-
 	return flow;
 
 fail_flow_insert:
@@ -2640,7 +2654,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 
 fail_bad_value:
 	sfc_flow_free(sa, flow);
-	sfc_adapter_unlock(sa);
 
 fail_no_mem:
 	return NULL;
@@ -2652,10 +2665,23 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 		 struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	int rc;
+
+	sfc_adapter_lock(sa);
+	rc = sfc_flow_destroy_locked(sa, flow, error);
+	sfc_adapter_unlock(sa);
+
+	return rc;
+}
+
+int
+sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			struct rte_flow_error *error)
+{
 	struct rte_flow *flow_ptr;
 	int rc = EINVAL;
 
-	sfc_adapter_lock(sa);
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
 		if (flow_ptr == flow)
@@ -2675,8 +2701,6 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 	sfc_flow_free(sa, flow);
 
 fail_bad_value:
-	sfc_adapter_unlock(sa);
-
 	return -rc;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 12875344b5..a3ca09f225 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -195,6 +195,15 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+					const struct rte_flow_attr *attr,
+					const struct rte_flow_item pattern[],
+					const struct rte_flow_action actions[],
+					struct rte_flow_error *error);
+
+int sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			    struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 14/34] net/sfc: let driver-internal flows use VF representor action
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (12 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
                     ` (20 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

In the case of VF <--> VF representor pairs, these flows can
only collect VF traffic, so let them use generic flow action
PORT_REPRESENTOR, as part of re-using generic flow mechanism.

Currently, it does not allow to access VF representors since
they have no unique HW logical ports (m-ports). They all sit
on the same (representor proxy) m-port, while demultiplexing
of traffic uses ingress (VF) m-port value in packet metadata.
Traffic from arbitrary sources cannot be identified this way.
But, for VF traffic, it should be right to make an exception.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c            | 25 +++++++++++++++++++------
 drivers/net/sfc/sfc_repr.c           | 20 ++++++++++++++++----
 drivers/net/sfc/sfc_repr_proxy.c     | 15 +++++++++++++++
 drivers/net/sfc/sfc_repr_proxy_api.h |  3 +++
 drivers/net/sfc/sfc_switch.c         |  7 ++-----
 drivers/net/sfc/sfc_switch.h         | 10 ++++++++++
 6 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 1928d58779..89fa75281f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1525,6 +1525,7 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 	const struct rte_flow_item_port_id *spec = NULL;
 	const struct rte_flow_item_port_id *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1556,8 +1557,10 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 					  "The port ID is too large");
 	}
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
-					     spec->id, &mport_sel);
+					     spec->id, type_mask, &mport_sel);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1590,6 +1593,7 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 	const struct rte_flow_item_ethdev *spec = NULL;
 	const struct rte_flow_item_ethdev *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1617,9 +1621,11 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 
 	switch (item->type) {
 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
+		type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_switch_get_ethdev_mport(
 				ctx_mae->sa->mae.switch_domain_id,
-				spec->port_id, &mport_sel);
+				spec->port_id, type_mask, &mport_sel);
 		if (rc != 0) {
 			return rte_flow_error_set(error, rc,
 					RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -3529,6 +3535,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 {
 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
+	unsigned int type_mask;
 	efx_mport_sel_t mport;
 	uint16_t port_id;
 	int rc;
@@ -3538,8 +3545,10 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 
 	port_id = (conf->original != 0) ? sas->port_id : conf->id;
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     port_id, &mport);
+					     port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			port_id, strerror(rc));
@@ -3558,14 +3567,14 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
 		const struct rte_flow_action_ethdev *conf,
-		efx_mae_actions_t *spec)
+		unsigned int type_mask, efx_mae_actions_t *spec)
 {
 	struct sfc_mae *mae = &sa->mae;
 	efx_mport_sel_t mport;
 	int rc;
 
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     conf->port_id, &mport);
+					     conf->port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			conf->port_id, strerror(rc));
@@ -3641,6 +3650,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
+	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
@@ -3757,8 +3767,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
 				       bundle->actions_mask);
+
+		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
-				action->conf, spec);
+				action->conf, switch_port_type_mask, spec);
 		break;
 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index d4134ec91b..6c7727d569 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -933,15 +933,26 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
 	struct sfc_mae_switch_port_request switch_port_request;
 	efx_mport_sel_t ethdev_mport_sel;
+	efx_mport_id_t proxy_mport_id;
 	struct sfc_repr *sr;
 	int ret;
 
 	/*
-	 * Currently there is no mport we can use for representor's
-	 * ethdev. Use an invalid one for now. This way representors
-	 * can be instantiated.
+	 * For each representor, a driver-internal flow has to be installed
+	 * in order to direct traffic coming from the represented entity to
+	 * the "representor proxy". Such internal flows need to find ethdev
+	 * mport by ethdev ID of the representors in question to specify in
+	 * delivery action. So set the representor ethdev's mport to that
+	 * of the "representor proxy" in below switch port request.
 	 */
-	efx_mae_mport_invalid(&ethdev_mport_sel);
+	sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
+
+	ret = efx_mae_mport_by_id(&proxy_mport_id, &ethdev_mport_sel);
+	if (ret != 0) {
+		SFC_GENERIC_LOG(ERR,
+			"%s() failed to get repr proxy mport by ID", __func__);
+		goto fail_get_selector;
+	}
 
 	memset(&switch_port_request, 0, sizeof(switch_port_request));
 	switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
@@ -1033,6 +1044,7 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 
 fail_create_port:
 fail_mae_assign_switch_port:
+fail_get_selector:
 	SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
 	return ret;
 }
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 4ba7683370..74c3494c35 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -1708,3 +1708,18 @@ sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id, uint16_t repr_id,
 
 	return rc;
 }
+
+void
+sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id, efx_mport_id_t *mport_alias)
+{
+	const struct sfc_repr_proxy *rp;
+	struct sfc_adapter *sa;
+
+	sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
+	sfc_adapter_lock(sa);
+	rp = sfc_repr_proxy_by_adapter(sa);
+
+	memcpy(mport_alias, &rp->mport_alias, sizeof(*mport_alias));
+
+	sfc_adapter_unlock(sa);
+}
diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h
index 1d38ab2451..07d79a50cb 100644
--- a/drivers/net/sfc/sfc_repr_proxy_api.h
+++ b/drivers/net/sfc/sfc_repr_proxy_api.h
@@ -46,6 +46,9 @@ int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id);
 int sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id,
 		uint16_t repr_id, const struct rte_ether_addr *mac_addr);
 
+void sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id,
+				    efx_mport_id_t *mport_alias);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 8f1ee97fa8..f80de4e889 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -551,6 +551,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
 int
 sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				uint16_t ethdev_port_id,
+				unsigned int allowed_mae_switch_port_types,
 				efx_mport_sel_t *mport_sel)
 {
 	struct sfc_mae_switch_port *port;
@@ -562,11 +563,7 @@ sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 	if (rc != 0)
 		goto unlock;
 
-	if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) {
-		/*
-		 * The ethdev is a "VF representor". It does not own
-		 * a dedicated m-port suitable for use in flow rules.
-		 */
+	if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
 		rc = ENOTSUP;
 		goto unlock;
 	}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 62aea9b785..6a85ce4dcf 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -102,8 +102,18 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
 			      uint16_t switch_port_id);
 
+/*
+ * For user flows, allowed_mae_switch_port_types can only contain bit
+ * SFC_MAE_SWITCH_PORT_INDEPENDENT, meaning that only those ethdevs
+ * that have their own MAE m-ports can be accessed by a port-based
+ * action. For driver-internal flows, this mask can also contain
+ * bit SFC_MAE_SWITCH_PORT_REPRESENTOR to allow VF traffic to be
+ * sent to the common MAE m-port of all such REPRESENTOR ports
+ * via a port-based action, for default switch interconnection.
+ */
 int sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				    uint16_t ethdev_port_id,
+				    unsigned int allowed_mae_switch_port_types,
 				    efx_mport_sel_t *mport_sel);
 
 int sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 15/34] net/sfc: extend generic flow API to allow for internal flows
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (13 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
                     ` (19 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

At the moment, driver-internal flow rules are provisioned by
functions that are separate from the generic flow management
framework. In order to use the latter for such rules, extend
it accordingly. This will be actually used in the next patch.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc.c      |  9 ++++-----
 drivers/net/sfc/sfc_flow.c | 37 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_flow.h |  5 ++++-
 drivers/net/sfc/sfc_mae.c  | 31 +++++++++++++++++++++++++++----
 drivers/net/sfc/sfc_mae.h  |  5 +++--
 5 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index a56521696a..2cfff20f47 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -975,6 +975,8 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_rss_attach;
 
+	sfc_flow_init(sa);
+
 	rc = sfc_flow_rss_attach(sa);
 	if (rc != 0)
 		goto fail_flow_rss_attach;
@@ -1006,8 +1008,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
-	sfc_flow_init(sa);
-
 	rc = sfc_sw_xstats_init(sa);
 	if (rc != 0)
 		goto fail_sw_xstats_init;
@@ -1030,7 +1030,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_sw_xstats_close(sa);
 
 fail_sw_xstats_init:
-	sfc_flow_fini(sa);
 	sfc_repr_proxy_detach(sa);
 
 fail_repr_proxy_attach:
@@ -1052,6 +1051,7 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_flow_rss_detach(sa);
 
 fail_flow_rss_attach:
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 
 fail_rss_attach:
@@ -1099,8 +1099,6 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_sriov_vswitch_destroy(sa);
 
-	sfc_flow_fini(sa);
-
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
 	sfc_tbls_detach(sa);
@@ -1108,6 +1106,7 @@ sfc_detach(struct sfc_adapter *sa)
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_flow_rss_detach(sa);
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
 	sfc_ev_detach(sa);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 432295ea62..f6d1ae2a5b 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <rte_byteorder.h>
 #include <rte_tailq.h>
 #include <rte_common.h>
@@ -2405,7 +2407,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2421,7 +2423,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2613,14 +2615,14 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow;
 
 	sfc_adapter_lock(sa);
-	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
 	sfc_adapter_unlock(sa);
 
 	return flow;
 }
 
 struct rte_flow *
-sfc_flow_create_locked(struct sfc_adapter *sa,
+sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item pattern[],
 		       const struct rte_flow_action actions[],
@@ -2635,13 +2637,15 @@ sfc_flow_create_locked(struct sfc_adapter *sa,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	flow->internal = internal;
+
 	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
 	TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
 
-	if (sa->state == SFC_ETHDEV_STARTED) {
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED) {
 		rc = sfc_flow_insert(sa, flow, error);
 		if (rc != 0)
 			goto fail_flow_insert;
@@ -2694,7 +2698,7 @@ sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
 		goto fail_bad_value;
 	}
 
-	if (sa->state == SFC_ETHDEV_STARTED)
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED)
 		rc = sfc_flow_remove(sa, flow, error);
 
 	TAILQ_REMOVE(&sa->flow_list, flow, entries);
@@ -2711,10 +2715,14 @@ sfc_flow_flush(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct rte_flow *flow;
 	int ret = 0;
+	void *tmp;
 
 	sfc_adapter_lock(sa);
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		if (sa->state == SFC_ETHDEV_STARTED) {
 			int rc;
 
@@ -2842,10 +2850,14 @@ void
 sfc_flow_fini(struct sfc_adapter *sa)
 {
 	struct rte_flow *flow;
+	void *tmp;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		TAILQ_REMOVE(&sa->flow_list, flow, entries);
 		sfc_flow_free(sa, flow);
 	}
@@ -2858,8 +2870,10 @@ sfc_flow_stop(struct sfc_adapter *sa)
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	TAILQ_FOREACH(flow, &sa->flow_list, entries)
-		sfc_flow_remove(sa, flow, NULL);
+	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (!flow->internal)
+			sfc_flow_remove(sa, flow, NULL);
+	}
 
 	/*
 	 * MAE counter service is not stopped on flow rule remove to avoid
@@ -2881,6 +2895,9 @@ sfc_flow_start(struct sfc_adapter *sa)
 	sfc_ft_counters_reset(sa);
 
 	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (flow->internal)
+			continue;
+
 		rc = sfc_flow_insert(sa, flow, NULL);
 		if (rc != 0)
 			goto fail_bad_flow;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index a3ca09f225..ec5e29f257 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -10,6 +10,8 @@
 #ifndef _SFC_FLOW_H
 #define _SFC_FLOW_H
 
+#include <stdbool.h>
+
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
 
@@ -101,6 +103,7 @@ struct sfc_flow_spec {
 struct rte_flow {
 	struct sfc_flow_spec spec;	/* flow specification */
 	TAILQ_ENTRY(rte_flow) entries;	/* flow list entries */
+	bool internal;			/* true for internal rules */
 };
 
 TAILQ_HEAD(sfc_flow_list, rte_flow);
@@ -195,7 +198,7 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
-struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 					const struct rte_flow_attr *attr,
 					const struct rte_flow_item pattern[],
 					const struct rte_flow_action actions[],
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 89fa75281f..f7bf682c11 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2537,6 +2537,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
+	if (ctx->internal) {
+		/*
+		 * A driver-internal flow may not comprise an outer rule,
+		 * but it must not match on invalid outer rule ID since
+		 * it must catch all missed packets, including those
+		 * that hit an outer rule of another flow entry but
+		 * do not hit a higher-priority action rule later.
+		 * So do not set match on outer rule ID here.
+		 */
+		SFC_ASSERT(ctx->match_spec_outer == NULL);
+		*rulep = NULL;
+		return 0;
+	}
+
 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
 		*rulep = NULL;
 		goto no_or_id;
@@ -2823,9 +2837,10 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
-			   struct sfc_flow_spec_mae *spec,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2833,6 +2848,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
 	ctx_mae.ft_rule_type = spec->ft_rule_type;
+	ctx_mae.internal = flow->internal;
 	ctx_mae.priority = spec->priority;
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
@@ -3642,11 +3658,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct sfc_flow_spec_mae *spec_mae,
+			  const struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
+	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -3770,6 +3787,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
 
+		if (flow->internal) {
+			switch_port_type_mask |=
+					1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
+		}
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
 				action->conf, switch_port_type_mask, spec);
 		break;
@@ -3840,9 +3862,10 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_flow_spec_mae *spec_mae,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
@@ -3899,7 +3922,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
+		rc = sfc_mae_rule_parse_action(sa, action, flow,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d2995ded88..307236ea11 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -363,6 +363,7 @@ struct sfc_mae_parse_ctx {
 	size_t				tunnel_def_mask_size;
 	const void			*tunnel_def_mask;
 	bool				match_mport_set;
+	bool				internal;
 	enum sfc_ft_rule_type		ft_rule_type;
 	struct sfc_mae_pattern_data	pattern_data;
 	efx_tunnel_protocol_t		encap_type;
@@ -376,11 +377,11 @@ void sfc_mae_detach(struct sfc_adapter *sa);
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
 int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       const struct rte_flow_item pattern[],
-			       struct sfc_flow_spec_mae *spec,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_flow_spec_mae *spec_mae,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 16/34] net/sfc: switch driver-internal flows to use generic methods
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (14 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
                     ` (18 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so helps to consolidate flow operation and ensure that
every FW-allocatable resource can be shared by several flows.
That is useful in the light of upcoming support for embedded
conntrack assistance, where several flows will ideally share
everything but unique 5-tuple entries in the conntrack table.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c        | 186 +++++++------------------------
 drivers/net/sfc/sfc_mae.h        |  51 ++-------
 drivers/net/sfc/sfc_repr_proxy.c |  38 ++-----
 drivers/net/sfc/sfc_repr_proxy.h |   2 +-
 4 files changed, 61 insertions(+), 216 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index f7bf682c11..51b2a22357 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -74,137 +74,48 @@ sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 	sfc_mae_counters_fini(&registry->counters);
 }
 
-static int
-sfc_mae_internal_rule_find_empty_slot(struct sfc_adapter *sa,
-				      struct sfc_mae_rule **rule)
-{
-	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_internal_rules *internal_rules = &mae->internal_rules;
-	unsigned int entry;
-	int rc;
-
-	for (entry = 0; entry < SFC_MAE_NB_RULES_MAX; entry++) {
-		if (internal_rules->rules[entry].spec == NULL)
-			break;
-	}
-
-	if (entry == SFC_MAE_NB_RULES_MAX) {
-		rc = ENOSPC;
-		sfc_err(sa, "failed too many rules (%u rules used)", entry);
-		goto fail_too_many_rules;
-	}
-
-	*rule = &internal_rules->rules[entry];
-
-	return 0;
-
-fail_too_many_rules:
-	return rc;
-}
-
-int
-sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-				     const efx_mport_sel_t *mport_match,
-				     const efx_mport_sel_t *mport_deliver,
-				     int prio, struct sfc_mae_rule **rulep)
+struct rte_flow *
+sfc_mae_repr_flow_create(struct sfc_adapter *sa, int prio, uint16_t port_id,
+			 enum rte_flow_action_type dst_type,
+			 enum rte_flow_item_type src_type)
 {
+	const struct rte_flow_item_ethdev item_spec = { .port_id = port_id };
+	const struct rte_flow_action_ethdev action = { .port_id = port_id };
+	const void *item_mask = &rte_flow_item_ethdev_mask;
+	struct rte_flow_attr attr = { .transfer = 1 };
+	const struct rte_flow_action actions[] = {
+		{ .type = dst_type, .conf = &action },
+		{ .type = RTE_FLOW_ACTION_TYPE_END }
+	};
+	const struct rte_flow_item items[] = {
+		{ .type = src_type, .mask = item_mask, .spec = &item_spec },
+		{ .type = RTE_FLOW_ITEM_TYPE_END }
+	};
 	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_rule *rule;
-	int rc;
-
-	sfc_log_init(sa, "entry");
+	struct rte_flow_error error;
 
 	if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
-		rc = EINVAL;
 		sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
 			mae->nb_action_rule_prios_max);
-		goto fail_invalid_prio;
+		return NULL;
 	}
 	if (prio < 0)
 		prio = mae->nb_action_rule_prios_max - 1;
 
-	rc = sfc_mae_internal_rule_find_empty_slot(sa, &rule);
-	if (rc != 0)
-		goto fail_find_empty_slot;
-
-	sfc_log_init(sa, "init MAE match spec");
-	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
-				     (uint32_t)prio, &rule->spec);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE match spec");
-		goto fail_match_init;
-	}
-
-	rc = efx_mae_match_spec_mport_set(rule->spec, mport_match, NULL);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get MAE match mport selector");
-		goto fail_mport_set;
-	}
-
-	rc = efx_mae_action_set_spec_init(sa->nic, &rule->actions);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE action set");
-		goto fail_action_init;
-	}
-
-	rc = efx_mae_action_set_populate_deliver(rule->actions,
-						 mport_deliver);
-	if (rc != 0) {
-		sfc_err(sa, "failed to populate deliver action");
-		goto fail_populate_deliver;
-	}
-
-	rc = efx_mae_action_set_alloc(sa->nic, rule->actions,
-				      &rule->action_set);
-	if (rc != 0) {
-		sfc_err(sa, "failed to allocate action set");
-		goto fail_action_set_alloc;
-	}
-
-	rc = efx_mae_action_rule_insert(sa->nic, rule->spec, NULL,
-					&rule->action_set,
-					&rule->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to insert action rule");
-		goto fail_rule_insert;
-	}
-
-	*rulep = rule;
-
-	sfc_log_init(sa, "done");
-
-	return 0;
-
-fail_rule_insert:
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-
-fail_action_set_alloc:
-fail_populate_deliver:
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
+	attr.priority = prio;
 
-fail_action_init:
-fail_mport_set:
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
-
-fail_match_init:
-fail_find_empty_slot:
-fail_invalid_prio:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	return sfc_flow_create_locked(sa, true, &attr, items, actions, &error);
 }
 
 void
-sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule)
+sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow)
 {
-	if (rule == NULL || rule->spec == NULL)
-		return;
-
-	efx_mae_action_rule_remove(sa->nic, &rule->rule_id);
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
+	struct rte_flow_error error;
+	int rc;
 
-	rule->spec = NULL;
+	rc = sfc_flow_destroy_locked(sa, flow, &error);
+	if (rc != 0)
+		sfc_err(sa, "failed to destroy the internal flow");
 }
 
 int
@@ -4311,11 +4222,9 @@ sfc_mae_flow_query(struct rte_eth_dev *dev,
 int
 sfc_mae_switchdev_init(struct sfc_adapter *sa)
 {
-	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
-	efx_mport_sel_t pf;
-	efx_mport_sel_t phy;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
@@ -4330,31 +4239,20 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 		goto fail_no_mae;
 	}
 
-	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
-					    &pf);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PF mport");
-		goto fail_pf_get;
-	}
-
-	rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PHY mport");
-		goto fail_phy_get;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_pf_to_ext);
-	if (rc != 0) {
+	mae->switchdev_rule_pf_to_ext = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
+					 RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR);
+	if (mae->switchdev_rule_pf_to_ext == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
 		goto fail_pf_add;
 	}
 
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_ext_to_pf);
-	if (rc != 0) {
+	mae->switchdev_rule_ext_to_pf = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+					 RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (mae->switchdev_rule_ext_to_pf == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
 		goto fail_phy_add;
 	}
@@ -4364,11 +4262,9 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 	return 0;
 
 fail_phy_add:
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 
 fail_pf_add:
-fail_phy_get:
-fail_pf_get:
 fail_no_mae:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
@@ -4382,6 +4278,6 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	if (!sa->switchdev)
 		return;
 
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
-	sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 307236ea11..f9434e1ab6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -180,33 +180,6 @@ struct sfc_mae_counter_registry {
 	} polling;
 };
 
-/**
- * MAE rules used to capture traffic generated by VFs and direct it to
- * representors (one for each VF).
- */
-#define SFC_MAE_NB_REPR_RULES_MAX	(64)
-
-/** Rules to forward traffic from PHY port to PF and from PF to PHY port */
-#define SFC_MAE_NB_SWITCHDEV_RULES	(2)
-/** Maximum required internal MAE rules */
-#define SFC_MAE_NB_RULES_MAX		(SFC_MAE_NB_SWITCHDEV_RULES + \
-					 SFC_MAE_NB_REPR_RULES_MAX)
-
-struct sfc_mae_rule {
-	efx_mae_match_spec_t		*spec;
-	efx_mae_actions_t		*actions;
-	efx_mae_aset_id_t		action_set;
-	efx_mae_rule_id_t		rule_id;
-};
-
-struct sfc_mae_internal_rules {
-	/*
-	 * Rules required to sustain switchdev mode or to provide
-	 * port representor functionality.
-	 */
-	struct sfc_mae_rule		rules[SFC_MAE_NB_RULES_MAX];
-};
-
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -234,14 +207,12 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter registry */
 	struct sfc_mae_counter_registry	counter_registry;
-	/** Driver-internal flow rules */
-	struct sfc_mae_internal_rules	internal_rules;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
 	 */
-	struct sfc_mae_rule		*switchdev_rule_pf_to_ext;
-	struct sfc_mae_rule		*switchdev_rule_ext_to_pf;
+	struct rte_flow			*switchdev_rule_pf_to_ext;
+	struct rte_flow			*switchdev_rule_ext_to_pf;
 };
 
 struct sfc_adapter;
@@ -396,16 +367,18 @@ sfc_flow_query_cb_t sfc_mae_flow_query;
 
 /**
  * Insert a driver-internal flow rule that matches traffic originating from
- * some m-port selector and redirects it to another one
- * (eg. PF --> PHY, PHY --> PF).
+ * a source port (REPRESENTED_PORT or PORT_REPRESENTOR) and directs it to
+ * its destination counterpart (PORT_REPRESENTOR or REPRESENTED_PORT).
  *
- * If requested priority is negative, use the lowest priority.
+ * If the prio argument is negative, the lowest level will be picked.
  */
-int sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-					 const efx_mport_sel_t *mport_match,
-					 const efx_mport_sel_t *mport_deliver,
-					 int prio, struct sfc_mae_rule **rulep);
-void sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule);
+struct rte_flow *sfc_mae_repr_flow_create(struct sfc_adapter *sa,
+					  int prio, uint16_t port_id,
+					  enum rte_flow_action_type dst_type,
+					  enum rte_flow_item_type src_type);
+
+void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
+
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 74c3494c35..ff13795c97 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -681,47 +681,25 @@ static int
 sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_repr_proxy *rp = &sa->repr_proxy;
-	efx_mport_sel_t mport_alias_selector;
-	efx_mport_sel_t mport_vf_selector;
-	struct sfc_mae_rule *mae_rule;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
-	rc = efx_mae_mport_by_id(&port->egress_mport,
-				 &mport_vf_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get VF mport for repr %u",
-			port->repr_id);
-		goto fail_get_vf;
-	}
-
-	rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get mport selector for repr %u",
-			port->repr_id);
-		goto fail_get_alias;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
-						  &mport_alias_selector, -1,
-						  &mae_rule);
-	if (rc != 0) {
+	port->mae_rule = sfc_mae_repr_flow_create(sa,
+				    SFC_MAE_RULE_PRIO_LOWEST, port->rte_port_id,
+				    RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+				    RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (port->mae_rule == NULL) {
 		sfc_err(sa, "failed to insert MAE rule for repr %u",
 			port->repr_id);
 		goto fail_rule_add;
 	}
 
-	port->mae_rule = mae_rule;
-
 	sfc_log_init(sa, "done");
 
 	return 0;
 
 fail_rule_add:
-fail_get_alias:
-fail_get_vf:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -730,9 +708,7 @@ static void
 sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_mae_rule *mae_rule = port->mae_rule;
-
-	sfc_mae_rule_del(sa, mae_rule);
+	sfc_mae_repr_flow_destroy(sa, port->mae_rule);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h
index 260e2cab30..0a4dedc3e1 100644
--- a/drivers/net/sfc/sfc_repr_proxy.h
+++ b/drivers/net/sfc/sfc_repr_proxy.h
@@ -67,7 +67,7 @@ struct sfc_repr_proxy_port {
 	uint32_t				remote_vnic_mcdi_client_handle;
 	struct sfc_repr_proxy_rxq		rxq[SFC_REPR_RXQ_MAX];
 	struct sfc_repr_proxy_txq		txq[SFC_REPR_TXQ_MAX];
-	struct sfc_mae_rule			*mae_rule;
+	struct rte_flow				*mae_rule;
 	bool					enabled;
 	bool					started;
 };
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 17/34] net/sfc: move MAE flow parsing method to MAE-specific source
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (15 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
                     ` (17 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so will facilitate easier code restructure in the next
patches required to rework flow housekeeping and indirection.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 47 +-----------------------------
 drivers/net/sfc/sfc_mae.c  | 58 ++++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  | 14 ++++-----
 3 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f6d1ae2a5b..6dfbbfd022 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2395,53 +2395,8 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-	struct sfc_flow_spec *spec = &flow->spec;
-	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	int rc;
-
-	/*
-	 * If the flow is meant to be a TUNNEL rule in a FT context,
-	 * preparse its actions and save its properties in spec_mae.
-	 */
-	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
-	if (rc != 0)
-		goto fail;
-
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
-		/*
-		 * By design, this flow should be represented solely by the
-		 * outer rule. But the HW/FW hasn't got support for setting
-		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
-		 * does it support outer rule counters. As a workaround, an
-		 * action rule of lower priority is used to do the job.
-		 *
-		 * So don't skip sfc_mae_rule_parse_actions() below.
-		 */
-	}
-
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_ctx != NULL) {
-		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
-			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
 
-		++(spec_mae->ft_ctx->refcnt);
-	}
-
-	return 0;
-
-fail:
-	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
-	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
-	spec_mae->ft_ctx = NULL;
-
-	return rc;
+	return sfc_mae_rule_parse(sa, pattern, actions, flow, error);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 51b2a22357..e2f098ea53 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2745,7 +2745,7 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
 
-int
+static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
@@ -3770,7 +3770,7 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
 }
 
-int
+static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
@@ -3933,6 +3933,60 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	return rc;
 }
 
+int
+sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow *flow, struct rte_flow_error *error)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	int rc;
+
+	/*
+	 * If the flow is meant to be a TUNNEL rule in a FT context,
+	 * preparse its actions and save its properties in spec_mae.
+	 */
+	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
+	if (rc != 0)
+		goto fail;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 *
+		 * So don't skip sfc_mae_rule_parse_actions() below.
+		 */
+	}
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_ctx != NULL) {
+		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
+			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
+
+		++(spec_mae->ft_ctx->refcnt);
+	}
+
+	return 0;
+
+fail:
+	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
+	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
+	spec_mae->ft_ctx = NULL;
+
+	return rc;
+}
+
 static bool
 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
 			const efx_mae_match_spec_t *left,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index f9434e1ab6..1d937c9b5b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -345,15 +345,13 @@ struct sfc_mae_parse_ctx {
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 void sfc_mae_detach(struct sfc_adapter *sa);
+
+int sfc_mae_rule_parse(struct sfc_adapter *sa,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow *flow, struct rte_flow_error *error);
+
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
-int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
-			       const struct rte_flow_item pattern[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
-int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
-			       const struct rte_flow_action actions[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
 sfc_flow_remove_cb_t sfc_mae_flow_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 18/34] net/sfc: move MAE counter stream start to action set handler
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (16 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
                     ` (16 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Logically, starting flow counter streaming belongs in action
set enable path. Move it there as a preparation step for the
patch that will make action rules shareable by several flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e2f098ea53..37292f5d7c 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1063,6 +1063,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
+		if (action_set->n_counters > 0) {
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_err(sa, "failed to start MAE counters support: %s",
+					rte_strerror(rc));
+				sfc_mae_encap_header_disable(sa, encap_header);
+				sfc_mae_mac_addr_disable(sa, src_mac_addr);
+				sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+				return rc;
+			}
+		}
+
 		rc = sfc_mae_counters_enable(sa, counters,
 					     action_set->n_counters,
 					     action_set->spec);
@@ -4141,15 +4153,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_enable;
 
-	if (action_set->n_counters > 0) {
-		rc = sfc_mae_counter_start(sa);
-		if (rc != 0) {
-			sfc_err(sa, "failed to start MAE counters support: %s",
-				rte_strerror(rc));
-			goto fail_mae_counter_start;
-		}
-	}
-
 	fw_rsrc = &action_set->fw_rsrc;
 
 	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
@@ -4164,7 +4167,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	return 0;
 
 fail_action_rule_insert:
-fail_mae_counter_start:
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 19/34] net/sfc: prepare MAE outer rules for action rule indirection
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (17 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
                     ` (15 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Flows provided by match-action engine (MAE) will be reworked
by the next patch to make action rule (AR) entries shareable.
To ensure correct AR specification comparison on attach path,
augment the way outer rules (OR) are handled, namely, how OR
IDs are indicated in a AR specification on parse and disable.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 44 ++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 37292f5d7c..624be53269 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -397,8 +397,10 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
-			   struct sfc_mae_outer_rule *rule)
+			   struct sfc_mae_outer_rule *rule,
+			   efx_mae_match_spec_t *match_spec_action)
 {
+	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -409,6 +411,18 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 
 	fw_rsrc = &rule->fw_rsrc;
 
+	if (match_spec_action == NULL)
+		goto skip_action_rule;
+
+	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
+						  &invalid_rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "cannot restore match on invalid outer rule ID: %s",
+			strerror(rc));
+		return;
+	}
+
+skip_action_rule:
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -2457,7 +2471,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule **rulep,
 			   struct rte_flow_error *error)
 {
-	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
+	efx_mae_rule_id_t or_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
 	if (ctx->internal) {
@@ -2504,13 +2518,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	/* The spec has now been tracked by the outer rule entry. */
 	ctx->match_spec_outer = NULL;
 
+	or_id.id = (*rulep)->fw_rsrc.rule_id.id;
+
 no_or_id:
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
 	case SFC_FT_RULE_TUNNEL:
-		/* No action rule */
-		return 0;
+		/*
+		 * Workaround. TUNNEL flows are not supposed to involve
+		 * MAE action rules, but, due to the currently limited
+		 * HW/FW implementation, action rules are still needed.
+		 * See sfc_mae_rule_parse_pattern().
+		 */
+		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
 		 * Match on recirculation ID rather than
@@ -2536,14 +2557,13 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
 	 * in the action rule specification; this ensures correct behaviour.
 	 *
-	 * If, on the other hand, this flow does have an outer rule, its ID
-	 * may be unknown at the moment (not yet allocated), but OR_ID mask
-	 * has to be set to 0xffffffff anyway for correct class comparisons.
-	 * When the outer rule has been allocated, this match field will be
-	 * overridden by sfc_mae_outer_rule_enable() to use the right value.
+	 * If, however, this flow does have an outer rule, OR_ID match must
+	 * be set to the currently known value for that outer rule. It will
+	 * be either 0xffffffff or some valid ID, depending on whether this
+	 * outer rule is currently active (adapter state is STARTED) or not.
 	 */
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
-						  &invalid_rule_id);
+						  &or_id);
 	if (rc != 0) {
 		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
@@ -4170,7 +4190,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4205,7 +4225,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 20/34] net/sfc: turn MAE flow action rules into shareable resources
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (18 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
                     ` (14 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance. With the new feature, multiple flows that differ
in the 5-tuple match fields but are otherwise identical will
be able to share all FW-allocatable objects except for those
of the conntrack table. That will boost flow engine capacity.

To prepare for that, action rules of the match-action engine
have to be turned into shareable objects, from SW standpoint.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   4 +-
 drivers/net/sfc/sfc_flow.h |  13 +-
 drivers/net/sfc/sfc_mae.c  | 362 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_mae.h  |  13 ++
 4 files changed, 287 insertions(+), 105 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 6dfbbfd022..0abeabfbf2 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1294,9 +1294,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		}
 		spec->type = SFC_FLOW_SPEC_MAE;
 		spec_mae->priority = attr->priority;
-		spec_mae->match_spec = NULL;
-		spec_mae->action_set = NULL;
-		spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+		spec_mae->action_rule = NULL;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index ec5e29f257..10c73d012f 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -75,14 +75,13 @@ struct sfc_flow_spec_mae {
 	struct sfc_ft_ctx		*ft_ctx;
 	/* Desired priority level */
 	unsigned int			priority;
-	/* Outer rule registry entry */
+	/*
+	 * Outer rule registry entry (points to below action_rule->outer_rule
+	 * when action_rule is not NULL; self-sufficient entry otherwise)
+	 */
 	struct sfc_mae_outer_rule	*outer_rule;
-	/* EFX match specification */
-	efx_mae_match_spec_t		*match_spec;
-	/* Action set registry entry */
-	struct sfc_mae_action_set	*action_set;
-	/* Firmware-allocated rule ID */
-	efx_mae_rule_id_t		rule_id;
+	/* Action rule registry entry */
+	struct sfc_mae_action_rule	*action_rule;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 624be53269..addcad2843 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -204,6 +204,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
+	TAILQ_INIT(&mae->action_rules);
 
 	if (encp->enc_mae_admin)
 		mae->status = SFC_MAE_STATUS_ADMIN;
@@ -1172,6 +1173,200 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 	--(fw_rsrc->refcnt);
 }
 
+struct sfc_mae_action_rule_ctx {
+	struct sfc_mae_outer_rule	*outer_rule;
+	struct sfc_mae_action_set	*action_set;
+	efx_mae_match_spec_t		*match_spec;
+};
+
+static int
+sfc_mae_action_rule_attach(struct sfc_adapter *sa,
+			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule **rulep,
+			   __rte_unused struct rte_flow_error *error)
+{
+	struct sfc_mae_action_rule *rule;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	/*
+	 * It is assumed that the caller of this helper has already properly
+	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
+	 * ctx->outer_rule refers to a currently active outer rule) or
+	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
+	 */
+	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->outer_rule != ctx->outer_rule ||
+		    rule->action_set != ctx->action_set)
+			continue;
+
+		if (efx_mae_match_specs_equal(rule->match_spec,
+					      ctx->match_spec)) {
+			sfc_dbg(sa, "attaching to action_rule=%p", rule);
+			++(rule->refcnt);
+			*rulep = rule;
+			return 0;
+		}
+	}
+
+	/*
+	 * No need to set RTE error, as this
+	 * code should be handled gracefully.
+	 */
+	return -ENOENT;
+}
+
+static int
+sfc_mae_action_rule_add(struct sfc_adapter *sa,
+			const struct sfc_mae_action_rule_ctx *ctx,
+			struct sfc_mae_action_rule **rulep)
+{
+	struct sfc_mae_action_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	rule = rte_zmalloc("sfc_mae_action_rule", sizeof(*rule), 0);
+	if (rule == NULL)
+		return ENOMEM;
+
+	rule->refcnt = 1;
+	rule->outer_rule = ctx->outer_rule;
+	rule->action_set = ctx->action_set;
+	rule->match_spec = ctx->match_spec;
+
+	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);
+
+	*rulep = rule;
+
+	sfc_dbg(sa, "added action_rule=%p", rule);
+
+	return 0;
+}
+
+static void
+sfc_mae_action_rule_del(struct sfc_adapter *sa,
+			struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae *mae = &sa->mae;
+	if (rule == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(rule->refcnt != 0);
+
+	--(rule->refcnt);
+
+	if (rule->refcnt != 0)
+		return;
+
+	if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    rule->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u",
+			rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
+	}
+
+	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
+	sfc_mae_action_set_del(sa, rule->action_set);
+	sfc_mae_outer_rule_del(sa, rule->outer_rule);
+
+	TAILQ_REMOVE(&mae->action_rules, rule, entries);
+	rte_free(rule);
+
+	sfc_dbg(sa, "deleted action_rule=%p", rule);
+}
+
+static int
+sfc_mae_action_rule_enable(struct sfc_adapter *sa,
+			   struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->refcnt != 0)
+		goto success;
+
+	rc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);
+	if (rc != 0)
+		goto fail_outer_rule_enable;
+
+	rc = sfc_mae_action_set_enable(sa, rule->action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, NULL,
+					&rule->action_set->fw_rsrc.aset_id,
+					&fw_rsrc->rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "failed to enable action_rule=%p: %s",
+			rule, strerror(rc));
+		goto fail_action_rule_insert;
+	}
+
+success:
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled action_rule=%p: AR_ID=0x%08x",
+			rule, fw_rsrc->rule_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+
+fail_action_rule_insert:
+	sfc_mae_action_set_disable(sa, rule->action_set);
+
+fail_action_set_enable:
+	sfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);
+
+fail_outer_rule_enable:
+	return rc;
+}
+static void
+sfc_mae_action_rule_disable(struct sfc_adapter *sa,
+			    struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u",
+			rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled action_rule=%p with AR_ID=0x%08x",
+				rule, fw_rsrc->rule_id.id);
+		} else {
+			sfc_err(sa, "failed to disable action_rule=%p with AR_ID=0x%08x: %s",
+				rule, fw_rsrc->rule_id.id, strerror(rc));
+		}
+
+		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		sfc_mae_action_set_disable(sa, rule->action_set);
+
+		sfc_mae_outer_rule_disable(sa, rule->outer_rule,
+					   rule->match_spec);
+	}
+
+	--(fw_rsrc->refcnt);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -1191,13 +1386,7 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		--(spec_mae->ft_ctx->refcnt);
 	}
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-	sfc_mae_action_set_del(sa, spec_mae->action_set);
-
-	if (spec_mae->match_spec != NULL)
-		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
 }
 
 static int
@@ -2781,9 +2970,11 @@ static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
+	struct sfc_mae_outer_rule **outer_rulep;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2796,6 +2987,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
 
+	outer_rulep = &action_rule_ctx->outer_rule;
+
 	switch (ctx_mae.ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		/*
@@ -2872,7 +3065,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
-	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
+	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
 
@@ -2884,7 +3077,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		goto fail_validate_match_spec_action;
 	}
 
-	spec->match_spec = ctx_mae.match_spec_action;
+	action_rule_ctx->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
@@ -3806,6 +3999,7 @@ static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
@@ -3927,8 +4121,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		goto fail_check_fate_action;
 	}
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, &ctx);
-	if (spec_mae->action_set != NULL) {
+	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
+	if (action_rule_ctx->action_set != NULL) {
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -3936,7 +4130,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, actions, &ctx,
+				    &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -3972,6 +4167,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule_ctx ctx = {};
 	int rc;
 
 	/*
@@ -3982,7 +4178,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
@@ -3998,10 +4194,30 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	spec_mae->outer_rule = ctx.outer_rule;
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
+	rc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,
+					error);
+	if (rc == 0) {
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+		sfc_mae_action_set_del(sa, ctx.action_set);
+		sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+	} else if (rc == -ENOENT) {
+		rc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);
+		if (rc != 0) {
+			rc = rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to add the entry");
+			goto fail;
+		}
+	} else {
+		goto fail;
+	}
+
 	if (spec_mae->ft_ctx != NULL) {
 		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
 			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
@@ -4012,6 +4228,12 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	return 0;
 
 fail:
+	if (ctx.match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+
+	sfc_mae_action_set_del(sa, ctx.action_set);
+	sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+
 	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
 	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
 	spec_mae->ft_ctx = NULL;
@@ -4071,30 +4293,27 @@ sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
-				 struct sfc_flow_spec_mae *spec)
+				 struct sfc_mae_action_rule *rule)
 {
-	const struct rte_flow *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	const struct sfc_mae_action_rule *entry;
+	struct sfc_mae *mae = &sa->mae;
 
-	if (spec->match_spec == NULL)
+	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* An active rule is reused. Its class is known to be valid. */
 		return 0;
+	}
 
-	TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
-		const struct sfc_flow_spec *entry_spec = &entry->spec;
-		const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
-		const efx_mae_match_spec_t *left = es_mae->match_spec;
-		const efx_mae_match_spec_t *right = spec->match_spec;
+	TAILQ_FOREACH_REVERSE(entry, &mae->action_rules,
+			      sfc_mae_action_rules, entries) {
+		const efx_mae_match_spec_t *left = entry->match_spec;
+		const efx_mae_match_spec_t *right = rule->match_spec;
 
-		switch (entry_spec->type) {
-		case SFC_FLOW_SPEC_FILTER:
-			/* Ignore VNIC-level flows */
-			break;
-		case SFC_FLOW_SPEC_MAE:
-			if (sfc_mae_rules_class_cmp(sa, left, right))
-				return 0;
-			break;
-		default:
-			SFC_ASSERT(false);
-		}
+		if (entry == rule)
+			continue;
+
+		if (sfc_mae_rules_class_cmp(sa, left, right))
+			return 0;
 	}
 
 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
@@ -4124,6 +4343,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	int rc;
 
@@ -4136,7 +4356,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
-	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+	return sfc_mae_action_rule_class_verify(sa, action_rule);
 }
 
 int
@@ -4145,55 +4365,22 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_fw_rsrc *fw_rsrc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	int rc;
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_enable(sa, outer_rule,
-					       spec_mae->match_spec);
-		if (rc != 0)
-			goto fail_outer_rule_enable;
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
 		spec_mae->ft_ctx->reset_tunnel_hit_counter =
 			spec_mae->ft_ctx->switch_hit_counter;
 	}
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "enabled flow=%p (no AR)", flow);
+	if (action_rule == NULL)
 		return 0;
-	}
-
-	rc = sfc_mae_action_set_enable(sa, action_set);
-	if (rc != 0)
-		goto fail_action_set_enable;
-
-	fw_rsrc = &action_set->fw_rsrc;
 
-	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
-					NULL, &fw_rsrc->aset_id,
-					&spec_mae->rule_id);
+	rc = sfc_mae_action_rule_enable(sa, action_rule);
 	if (rc != 0)
-		goto fail_action_rule_insert;
-
-	sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
+		return rc;
 
 	return 0;
-
-fail_action_rule_insert:
-	sfc_mae_action_set_disable(sa, action_set);
-
-fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
-
-fail_outer_rule_enable:
-	return rc;
 }
 
 int
@@ -4202,30 +4389,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	int rc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "disabled flow=%p (no AR)", flow);
-		goto skip_action_rule;
-	}
-
-	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
-
-	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
-			flow, spec_mae->rule_id.id, strerror(rc));
-	}
-	sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
-	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
-
-	sfc_mae_action_set_disable(sa, action_set);
+	if (action_rule == NULL)
+		return 0;
 
-skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
+	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
 }
@@ -4237,17 +4406,20 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 		      struct rte_flow_query_count *data,
 		      struct rte_flow_error *error)
 {
-	struct sfc_mae_action_set *action_set = spec->action_set;
+	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
+	struct sfc_mae_action_set *action_set;
 	unsigned int i;
 	int rc;
 
-	if (action_set == NULL || action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
+	action_set = action_rule->action_set;
+
 	for (i = 0; i < action_set->n_counters; i++) {
 		/*
 		 * Get the first available counter of the flow rule if
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1d937c9b5b..cbe190075c 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -97,6 +97,17 @@ struct sfc_mae_action_set {
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 
+/** Action rule registry entry */
+struct sfc_mae_action_rule {
+	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	struct sfc_mae_outer_rule		*outer_rule;
+	struct sfc_mae_action_set		*action_set;
+	efx_mae_match_spec_t			*match_spec;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+	unsigned int				refcnt;
+};
+TAILQ_HEAD(sfc_mae_action_rules, sfc_mae_action_rule);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -201,6 +212,8 @@ struct sfc_mae {
 	struct sfc_mae_mac_addrs	mac_addrs;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Action rule registry */
+	struct sfc_mae_action_rules	action_rules;
 	/** Encap. header bounce buffer */
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 21/34] common/sfc_efx/base: provide an API to clone MAE match specs
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (19 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
                     ` (13 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

The DPDK driver would like to have a means to make a copy of
the action rule match specification before trying to dissect
it to possibly move out the per-connection 5-tuple data from
it to build up an entry in the HW conntrack assistance table.

Making such a copy at the end of parsing should be preferred
over maintaining DPDK-level structures because the resulting
code is easier on eyes and less prone to errors in this case.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f96e398460..ee1ea81a35 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4452,6 +4452,13 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_match_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 7732d99992..43dfba518a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1163,6 +1163,32 @@ efx_mae_match_spec_mport_set(
 
 fail2:
 	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep)
+{
+	efx_mae_match_spec_t *clone;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
+	if (clone == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
+
+	*clonep = clone;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d083a54a03..931d556e80 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -124,6 +124,7 @@ INTERNAL {
 	efx_mae_mac_addr_alloc;
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
+	efx_mae_match_spec_clone;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 22/34] common/sfc_efx/base: add API to read back MAE match criteria
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (20 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
                     ` (12 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance in the DPDK driver. In order to detect flows that
are subject to such assistance, the driver needs to retrieve
5-tuple match data from an already constructed specification.

A dedicated API to selectively read back match criteria will
make a neat solution to keep the implementation less complex.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  10 ++
 drivers/common/sfc_efx/base/efx_mae.c | 131 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   1 +
 3 files changed, 142 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ee1ea81a35..8c6095f747 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4430,6 +4430,16 @@ efx_mae_match_spec_field_set(
 	__in				size_t mask_size,
 	__in_bcount(mask_size)		const uint8_t *mask);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask);
+
 /* The corresponding mask will be set to B_TRUE. */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 43dfba518a..011f38d298 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1054,6 +1054,137 @@ efx_mae_match_spec_field_set(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	unsigned int desc_set_nentries;
+	const uint8_t *mvp;
+	efx_rc_t rc;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
+	case EFX_MAE_RULE_ACTION:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((unsigned int)field_id >= desc_set_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (descp->emmd_mask_size == 0) {
+		/* The ID points to a gap in the array of field descriptors. */
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (value != NULL && value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (mask != NULL && mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	if (value == NULL && value_size != 0) {
+		rc = EINVAL;
+		goto fail6;
+	}
+
+	if (mask == NULL && mask_size != 0) {
+		rc = EINVAL;
+		goto fail7;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The MCDI request field is in network (big endian) order.
+		 * The mask/value are also big endian.
+		 */
+		memcpy(value, mvp + descp->emmd_value_offset, value_size);
+		memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The MCDI request field is little endian.
+		 * The mask/value are in host byte order.
+		 */
+		switch (value_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_value_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)value =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(value, mvp + descp->emmd_value_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_mask_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)mask =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(mask, mvp + descp->emmd_mask_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 931d556e80..b1ca8e1215 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 23/34] common/sfc_efx/base: match on conntrack mark in action rules
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (21 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
                     ` (11 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

EF100 match-action engine (MAE) has conntrack assistance
table. A hit in this table can provide a mark value for
the following lookup stage, which is action rule lookup.

Provide support for setting match on conntrack mark.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 28 +++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 8c6095f747..dd9d4f29e8 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4276,6 +4276,7 @@ typedef enum efx_mae_field_id_e {
 	 * or by using dedicated field-specific helper APIs.
 	 */
 	EFX_MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_CT_MARK,
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
@@ -4462,6 +4463,12 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_match_spec_clone(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 011f38d298..b00ed2ec7a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -474,6 +474,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
 	EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
 	EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -549,6 +550,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
 	EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
 
 #undef EFX_MAE_MV_DESC
 };
@@ -910,6 +912,32 @@ efx_mae_match_spec_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	mp = (const uint8_t *)&full_mask;
+	vp = (const uint8_t *)&ct_mark;
+
+	rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
+					  sizeof (ct_mark), vp,
+					  sizeof (full_mask), mp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index b1ca8e1215..d972896210 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_ct_mark_set;
 	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (22 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
                     ` (10 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such can be initiated when a packet hits an outer rule.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  9 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 37 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index dd9d4f29e8..99ef0ce957 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4679,6 +4679,15 @@ efx_mae_outer_rule_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+/*
+ * Request that packets hitting this rule be submitted
+ * for a lookup in the conntrack assistance table.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec);
+
 LIBEFX_API
 extern	__checkReturn		efx_rc_t
 efx_mae_outer_rule_insert(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 9a5d465fa0..0a6a489d2c 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1761,6 +1761,7 @@ struct efx_mae_match_spec_s {
 		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 	uint8_t				emms_outer_rule_recirc_id;
+	boolean_t			emms_outer_rule_do_ct;
 };
 
 typedef enum efx_mae_action_e {
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index b00ed2ec7a..546c743a02 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -2369,6 +2369,26 @@ efx_mae_outer_rule_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec)
+{
+	efx_rc_t rc;
+
+	if (spec->emms_type != EFX_MAE_RULE_OUTER) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	spec->emms_outer_rule_do_ct = B_TRUE;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
@@ -2389,6 +2409,7 @@ efx_mae_outer_rule_insert(
 	uint32_t encap_type_mcdi;
 	efx_mae_rule_id_t or_id;
 	size_t offset;
+	uint8_t do_ct;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
@@ -2451,6 +2472,11 @@ efx_mae_outer_rule_insert(
 	    MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
 	    spec->emms_outer_rule_recirc_id);
 
+	do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
+
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
+	    MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d972896210..28a2be0a95 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -143,6 +143,7 @@ INTERNAL {
 	efx_mae_mport_free;
 	efx_mae_mport_id_by_selector;
 	efx_mae_mport_invalid;
+	efx_mae_outer_rule_do_ct_set;
 	efx_mae_outer_rule_insert;
 	efx_mae_outer_rule_recirc_id_set;
 	efx_mae_outer_rule_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 25/34] net/sfc: make use of conntrack assistance for transfer flows
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (23 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
                     ` (9 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

NAT and CT counters will be supported later.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h |   4 +
 drivers/net/sfc/sfc_mae.c  | 314 +++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  |   1 +
 3 files changed, 310 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 10c73d012f..8f706fc589 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -18,6 +18,7 @@
 #include "efx.h"
 
 #include "sfc_flow_rss.h"
+#include "sfc_mae_ct.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +83,9 @@ struct sfc_flow_spec_mae {
 	struct sfc_mae_outer_rule	*outer_rule;
 	/* Action rule registry entry */
 	struct sfc_mae_action_rule	*action_rule;
+	/* Conntrack (CT) assistance table entry key and response */
+	sfc_mae_conntrack_response_t	ct_resp;
+	sfc_mae_conntrack_key_t		ct_key;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index addcad2843..d3b4099213 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -18,6 +18,7 @@
 #include "sfc.h"
 #include "sfc_flow_tunnel.h"
 #include "sfc_mae_counter.h"
+#include "sfc_mae_ct.h"
 #include "sfc_log.h"
 #include "sfc_switch.h"
 #include "sfc_service.h"
@@ -1177,18 +1178,23 @@ struct sfc_mae_action_rule_ctx {
 	struct sfc_mae_outer_rule	*outer_rule;
 	struct sfc_mae_action_set	*action_set;
 	efx_mae_match_spec_t		*match_spec;
+	uint32_t			ct_mark;
 };
 
 static int
 sfc_mae_action_rule_attach(struct sfc_adapter *sa,
-			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule_ctx *ctx,
 			   struct sfc_mae_action_rule **rulep,
-			   __rte_unused struct rte_flow_error *error)
+			   struct rte_flow_error *error)
 {
+	uint32_t new_ct_mark = ctx->ct_mark;
 	struct sfc_mae_action_rule *rule;
+	int rc;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	SFC_ASSERT(ctx->ct_mark <= 1);
+
 	/*
 	 * It is assumed that the caller of this helper has already properly
 	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
@@ -1196,10 +1202,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
 	 */
 	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->ct_mark == new_ct_mark)
+			++new_ct_mark;
+
 		if (rule->outer_rule != ctx->outer_rule ||
-		    rule->action_set != ctx->action_set)
+		    rule->action_set != ctx->action_set ||
+		    !!rule->ct_mark != !!ctx->ct_mark)
 			continue;
 
+		if (ctx->ct_mark != 0) {
+			rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+							    rule->ct_mark);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark for comparison");
+			}
+		}
+
 		if (efx_mae_match_specs_equal(rule->match_spec,
 					      ctx->match_spec)) {
 			sfc_dbg(sa, "attaching to action_rule=%p", rule);
@@ -1209,6 +1229,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 		}
 	}
 
+	if (ctx->ct_mark != 0) {
+		if (new_ct_mark == UINT32_MAX) {
+			return rte_flow_error_set(error, ERANGE,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to allocate CT mark");
+		}
+
+		rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+						    new_ct_mark);
+		if (rc != 0) {
+			return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark");
+		}
+
+		ctx->ct_mark = new_ct_mark;
+	}
+
 	/*
 	 * No need to set RTE error, as this
 	 * code should be handled gracefully.
@@ -1231,6 +1269,17 @@ sfc_mae_action_rule_add(struct sfc_adapter *sa,
 		return ENOMEM;
 
 	rule->refcnt = 1;
+
+	/*
+	 * It is assumed that the caller invoked sfc_mae_action_rule_attach()
+	 * and got (-ENOENT) before getting here. That ensures a unique CT
+	 * mark value or, if no CT is involved at all, simply zero.
+	 *
+	 * It is also assumed that match on the mark (if non-zero)
+	 * is already set in the action rule match specification.
+	 */
+	rule->ct_mark = ctx->ct_mark;
+
 	rule->outer_rule = ctx->outer_rule;
 	rule->action_set = ctx->action_set;
 	rule->match_spec = ctx->match_spec;
@@ -1802,6 +1851,8 @@ struct sfc_mae_field_locator {
 	size_t				size;
 	/* Field offset in the corresponding rte_flow_item_ struct */
 	size_t				ofst;
+
+	uint8_t				ct_key_field;
 };
 
 static void
@@ -2654,6 +2705,216 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 	},
 };
 
+#define SFC_MAE_CT_KEY_ET 0x01 /* EtherType */
+#define SFC_MAE_CT_KEY_DA 0x02 /* IPv4/IPv6 destination address */
+#define SFC_MAE_CT_KEY_SA 0x04 /* IPv4/IPv6 source address */
+#define SFC_MAE_CT_KEY_L4 0x08 /* IPv4/IPv6 L4 protocol ID */
+#define SFC_MAE_CT_KEY_DP 0x10 /* L4 destination port */
+#define SFC_MAE_CT_KEY_SP 0x20 /* L4 source port */
+
+#define SFC_MAE_CT_KEY_FIELD_SIZE_MAX	sizeof(sfc_mae_conntrack_key_t)
+
+static const struct sfc_mae_field_locator flocs_ct[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ether_type_le),
+		offsetof(sfc_mae_conntrack_key_t, ether_type_le),
+		SFC_MAE_CT_KEY_ET,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_IP_PROTO,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ip_proto),
+		offsetof(sfc_mae_conntrack_key_t, ip_proto),
+		SFC_MAE_CT_KEY_L4,
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, dst_port_le),
+		offsetof(sfc_mae_conntrack_key_t, dst_port_le),
+		SFC_MAE_CT_KEY_DP,
+	},
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, src_port_le),
+		offsetof(sfc_mae_conntrack_key_t, src_port_le),
+		SFC_MAE_CT_KEY_SP,
+	},
+};
+
+static int
+sfc_mae_rule_process_ct(struct sfc_adapter *sa, struct sfc_mae_parse_ctx *pctx,
+			struct sfc_mae_action_rule_ctx *action_rule_ctx,
+			struct sfc_flow_spec_mae *spec,
+			struct rte_flow_error *error)
+{
+	efx_mae_match_spec_t *match_spec_tmp;
+	uint8_t ct_key_missing_fields =
+		SFC_MAE_CT_KEY_ET | SFC_MAE_CT_KEY_DA | SFC_MAE_CT_KEY_SA |
+		SFC_MAE_CT_KEY_L4 | SFC_MAE_CT_KEY_DP | SFC_MAE_CT_KEY_SP;
+	unsigned int i;
+	int rc;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * TUNNEL rules have no network match fields that belong
+		 * in an action rule match specification, so nothing can
+		 * be possibly utilised for conntrack assistance offload.
+		 */
+		return 0;
+	}
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return 0;
+
+	rc = efx_mae_match_spec_clone(sa->nic, pctx->match_spec_action,
+				      &match_spec_tmp);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"AR: failed to clone the match specification");
+	}
+
+	for (i = 0; i < RTE_DIM(flocs_ct); ++i) {
+		const struct sfc_mae_field_locator *fl = &flocs_ct[i];
+		uint8_t mask_full[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask_zero[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t value[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t *ct_key = (uint8_t *)&spec->ct_key;
+		efx_mae_field_id_t fid = fl->field_id;
+		unsigned int j;
+
+		rc = efx_mae_match_spec_field_get(match_spec_tmp, fid,
+						  fl->size, value,
+						  fl->size, mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to extract match field");
+		}
+
+		memset(mask_full, 0xff, fl->size);
+
+		if (memcmp(mask, mask_full, fl->size) != 0)
+			continue;
+
+		memset(mask_zero, 0, fl->size);
+
+		rc = efx_mae_match_spec_field_set(match_spec_tmp, fid,
+						  fl->size, mask_zero,
+						  fl->size, mask_zero);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to erase match field");
+		}
+
+		for (j = 0; j < fl->size; ++j) {
+			uint8_t *byte_dst = ct_key + fl->ofst + fl->size - 1 - j;
+			const uint8_t *byte_src = value + j;
+
+			*byte_dst = *byte_src;
+		}
+
+		ct_key_missing_fields &= ~(fl->ct_key_field);
+	}
+
+	if (ct_key_missing_fields != 0) {
+		efx_mae_match_spec_fini(sa->nic, match_spec_tmp);
+		return 0;
+	}
+
+	efx_mae_match_spec_fini(sa->nic, pctx->match_spec_action);
+	pctx->match_spec_action = match_spec_tmp;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		/*
+		 * A SWITCH rule re-uses the corresponding TUNNEL rule's
+		 * outer rule, where conntrack request should have been
+		 * configured already, so skip outer rule processing.
+		 */
+		goto skip_outer_rule;
+	}
+
+	if (pctx->match_spec_outer == NULL) {
+		const struct sfc_mae_pattern_data *pdata = &pctx->pattern_data;
+		const struct sfc_mae_ethertype *et;
+		struct sfc_mae *mae = &sa->mae;
+
+		rc = efx_mae_match_spec_init(sa->nic,
+					     EFX_MAE_RULE_OUTER,
+					     mae->nb_outer_rule_prios_max - 1,
+					     &pctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to initialise the match specification");
+		}
+
+		/* Match on EtherType appears to be compulsory in outer rules */
+
+		et = &pdata->ethertypes[pdata->nb_vlan_tags];
+
+		rc = efx_mae_match_spec_field_set(pctx->match_spec_outer,
+				EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
+				sizeof(et->value), (const uint8_t *)&et->value,
+				sizeof(et->mask), (const uint8_t *)&et->mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to set match on EtherType");
+		}
+	}
+
+	rc = efx_mae_outer_rule_do_ct_set(pctx->match_spec_outer);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to request CT lookup");
+	}
+
+skip_outer_rule:
+	/* Initial/dummy CT mark value */
+	action_rule_ctx->ct_mark = 1;
+
+	return 0;
+}
+
+#undef SFC_MAE_CT_KEY_ET
+#undef SFC_MAE_CT_KEY_DA
+#undef SFC_MAE_CT_KEY_SA
+#undef SFC_MAE_CT_KEY_L4
+#undef SFC_MAE_CT_KEY_DP
+#undef SFC_MAE_CT_KEY_SP
+
 static int
 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_parse_ctx *ctx,
@@ -2677,13 +2938,11 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
+	if (ctx->match_spec_outer == NULL) {
 		*rulep = NULL;
 		goto no_or_id;
 	}
 
-	SFC_ASSERT(ctx->match_spec_outer != NULL);
-
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -2810,6 +3069,7 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 {
 	const struct rte_flow_item *pattern = ctx->pattern;
 	struct sfc_mae *mae = &sa->mae;
+	bool request_ct = false;
 	uint8_t recirc_id = 0;
 	int rc;
 
@@ -2905,6 +3165,14 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		recirc_id = SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id);
+
+		if (sfc_mae_conntrack_is_supported(sa)) {
+			/*
+			 * Request lookup in conntrack table since SWITCH rules
+			 * are eligible to utilise this type of assistance.
+			 */
+			request_ct = true;
+		}
 		/* FALLTHROUGH */
 	case SFC_FT_RULE_NONE:
 		if (ctx->priority >= mae->nb_outer_rule_prios_max) {
@@ -2938,6 +3206,16 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 					"OR: failed to initialise RECIRC_ID");
 		}
+
+		if (!request_ct)
+			break;
+
+		rc = efx_mae_outer_rule_do_ct_set(ctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to request CT lookup");
+		}
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/* Outermost items -> "ENC" match fields in the action rule. */
@@ -2959,9 +3237,6 @@ static void
 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 			      struct sfc_mae_parse_ctx *ctx)
 {
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
-		return;
-
 	if (ctx->match_spec_outer != NULL)
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
@@ -3065,6 +3340,11 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
+	rc = sfc_mae_rule_process_ct(sa, &ctx_mae, action_rule_ctx,
+				     spec, error);
+	if (rc != 0)
+		goto fail_process_ct;
+
 	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
@@ -3083,6 +3363,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 fail_validate_match_spec_action:
 fail_process_outer:
+fail_process_ct:
 fail_process_pattern_data:
 fail_parse_pattern:
 	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
@@ -4380,6 +4661,18 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
+	if (spec_mae->action_rule->ct_mark != 0) {
+		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
+		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
+					      &spec_mae->ct_resp);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -4394,6 +4687,9 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule == NULL)
 		return 0;
 
+	if (action_rule->ct_mark != 0)
+		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index cbe190075c..67fa2ca5c9 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -100,6 +100,7 @@ TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 /** Action rule registry entry */
 struct sfc_mae_action_rule {
 	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	uint32_t				ct_mark;
 	struct sfc_mae_outer_rule		*outer_rule;
 	struct sfc_mae_action_set		*action_set;
 	efx_mae_match_spec_t			*match_spec;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 26/34] common/sfc_efx/base: support NAT edits in MAE
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (24 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
                     ` (8 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

NAT goes after IP TTL decrement. It can operate
on the outermost frame only. In the case of
prior decapsulation, that maps to the frame
which was (originally) the inner one. Input
data for the action comes from the response
of the HW conntrack assistance table hit.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      | 13 +++++++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 17 +++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 32 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 99ef0ce957..0a08b490e5 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4560,6 +4560,19 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_decr_ip_ttl(
 	__in				efx_mae_actions_t *spec);
 
+/*
+ * This only requests NAT action. The replacement IP address and
+ * L4 port number, as well as the edit direction (DST/SRC), come
+ * from the response to a hit in the conntrack assistance table.
+ *
+ * The action amends the outermost frame. In the case of prior
+ * decapsulation, that maps to the (originally) inner frame.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 0a6a489d2c..e978ad0de8 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1771,6 +1771,7 @@ typedef enum efx_mae_action_e {
 	EFX_MAE_ACTION_SET_DST_MAC,
 	EFX_MAE_ACTION_SET_SRC_MAC,
 	EFX_MAE_ACTION_DECR_IP_TTL,
+	EFX_MAE_ACTION_NAT,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_COUNT,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 546c743a02..aaea38c933 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1837,6 +1837,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_DECR_IP_TTL] = {
 		.emad_add = efx_mae_action_set_no_op
 	},
+	[EFX_MAE_ACTION_NAT] = {
+		.emad_add = efx_mae_action_set_no_op
+	},
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
@@ -1863,6 +1866,7 @@ static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_SET_DST_MAC) |
 	(1U << EFX_MAE_ACTION_SET_SRC_MAC) |
 	(1U << EFX_MAE_ACTION_DECR_IP_TTL) |
+	(1U << EFX_MAE_ACTION_NAT) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	/*
 	 * HW will conduct action COUNT after
@@ -2038,6 +2042,14 @@ efx_mae_action_set_populate_decr_ip_ttl(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_NAT, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
 	__in				efx_mae_actions_t *spec,
@@ -3093,6 +3105,11 @@ efx_mae_action_set_alloc(
 		    MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
 	}
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
+	}
+
 	if (spec->ema_n_vlan_tags_to_push > 0) {
 		unsigned int outer_tag_idx;
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 28a2be0a95..1ff760a024 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -104,6 +104,7 @@ INTERNAL {
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_mark_reset;
+	efx_mae_action_set_populate_nat;
 	efx_mae_action_set_populate_set_dst_mac;
 	efx_mae_action_set_populate_set_src_mac;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (25 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
                     ` (7 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

For this offload to work, the innermost pattern items must
provide the full set of exact match criteria, which are as
follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
and TP SRC, where the protocol types can be autodetected.

The offload requires that the IPv4 and the TP actions be
requested simultaneously in the same flow by the caller:
SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.

The offload operates on the outermost frame, which,
if action VXLAN_DECAP was requested, maps to the
inner frame of the original packet. The caller
is responsible to request this offload only
when the target header is an IPv4-based one.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini       |  4 ++
 doc/guides/nics/sfc_efx.rst            |  8 +++
 doc/guides/rel_notes/release_23_07.rst | 15 +++++
 drivers/net/sfc/sfc_mae.c              | 77 +++++++++++++++++++++++---
 4 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index f5ac644278..19d4935ce6 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -75,8 +75,12 @@ port_representor     = Y
 represented_port     = Y
 queue                = Y
 rss                  = Y
+set_ipv4_dst         = Y
+set_ipv4_src         = Y
 set_mac_dst          = Y
 set_mac_src          = Y
+set_tp_dst           = Y
+set_tp_src           = Y
 vf                   = Y
 vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index de0656876b..6e974c3720 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -270,10 +270,18 @@ Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- SET_IPV4_DST
+
+- SET_IPV4_SRC
+
 - SET_MAC_DST
 
 - SET_MAC_SRC
 
+- SET_TP_DST
+
+- SET_TP_SRC
+
 - OF_DEC_NW_TTL
 
 - DEC_TTL
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index a9b1293689..6fae4eb0a7 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -55,6 +55,21 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Updated Solarflare network PMD.**
+
+  Updated the Solarflare ``sfc_efx`` driver with changes including:
+
+  * Added partial support for transfer flow actions SET_IPV4_DST,
+    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
+    It is required that the innermost pattern items provide the
+    full set of exact match criteria: EtherType, IP DST, IP SRC,
+    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
+    must be requested simultaneously in the same flow. These
+    actions operate on the outermost frame, at the point
+    where action VXLAN_DECAP (if any) has done its job.
+    The caller is responsible to request this offload
+    only when the target header is an IPv4-based one.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d3b4099213..c58a2520da 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,6 +9,7 @@
 
 #include <stdbool.h>
 
+#include <rte_byteorder.h>
 #include <rte_bitops.h>
 #include <rte_common.h>
 #include <rte_vxlan.h>
@@ -3444,6 +3445,8 @@ sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
 };
 
 struct sfc_mae_actions_bundle {
@@ -3464,7 +3467,8 @@ struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      efx_mae_actions_t *spec)
+			      struct sfc_flow_spec_mae *flow_spec,
+			      bool ct, efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
@@ -3475,6 +3479,16 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 		rc = efx_mae_action_set_populate_vlan_push(
 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
+		flow_spec->ct_resp.nat.dir_is_dst = true;
+		/* FALLTHROUGH */
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
+		if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
+		    flow_spec->ct_resp.nat.port_le != 0)
+			rc = efx_mae_action_set_populate_nat(spec);
+		else
+			rc = EINVAL;
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -3491,7 +3505,8 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 static int
 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			    struct sfc_mae_actions_bundle *bundle,
-			    efx_mae_actions_t *spec,
+			    struct sfc_flow_spec_mae *flow_spec,
+			    efx_mae_actions_t *spec, bool ct,
 			    struct rte_flow_error *error)
 {
 	enum sfc_mae_actions_bundle_type bundle_type_new;
@@ -3503,6 +3518,14 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -3515,7 +3538,7 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 
 	if (bundle_type_new != bundle->type ||
 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
-		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
 		if (rc != 0)
 			goto fail_submit;
 
@@ -3532,6 +3555,20 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			"Failed to request the (group of) action(s)");
 }
 
+static void
+sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
+				   uint32_t *nat_addr_le)
+{
+	*nat_addr_le = rte_bswap32(conf->ipv4_addr);
+}
+
+static void
+sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
+				   uint16_t *nat_port_le)
+{
+	*nat_port_le = rte_bswap16(conf->port);
+}
+
 static void
 sfc_mae_rule_parse_action_of_push_vlan(
 			    const struct rte_flow_action_of_push_vlan *conf,
@@ -4056,6 +4093,10 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
 	[RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
@@ -4075,12 +4116,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct rte_flow *flow,
+			  struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
-	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4127,6 +4168,24 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_addr(action->conf,
+					&spec_mae->ct_resp.nat.ip_le);
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_port(action->conf,
+						&spec_mae->ct_resp.nat.port_le);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
 				       bundle->actions_mask);
@@ -4285,6 +4344,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
+	bool ct = (action_rule_ctx->ct_mark != 0);
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
 	struct sfc_mae *mae = &sa->mae;
@@ -4335,8 +4395,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_actions_bundle_sync(action, &bundle,
-						 ctx.spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+						 ctx.spec, ct, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
@@ -4346,7 +4406,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			goto fail_rule_parse_action;
 	}
 
-	rc = sfc_mae_actions_bundle_sync(action, &bundle, ctx.spec, error);
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+					 ctx.spec, ct, error);
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 28/34] net/sfc: rename SW structures used by transfer flow counters
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (26 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
                     ` (6 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so facilitates rearrangements of the next patch needed
to make software counter objects shareable across many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 14 +++++++-------
 drivers/net/sfc/sfc_mae.h         | 14 +++++++-------
 drivers/net/sfc/sfc_mae_counter.c | 31 ++++++++++++++++---------------
 drivers/net/sfc/sfc_mae_counter.h | 16 ++++++++--------
 4 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c58a2520da..2b4c821883 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -151,7 +151,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		if (rc != 0)
 			goto fail_mae_get_limits;
 
-		sfc_log_init(sa, "init MAE counter registry");
+		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
 						   limits.eml_max_n_counters);
 		if (rc != 0) {
@@ -817,7 +817,7 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counters,
+			struct sfc_mae_counter *counters,
 			unsigned int n_counters,
 			efx_mae_actions_t *action_set_spec)
 {
@@ -833,7 +833,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(n_counters == 1);
 
-	rc = sfc_mae_counter_enable(sa, &counters[0]);
+	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
 	if (rc != 0) {
 		sfc_err(sa, "failed to enable MAE counter %u: %s",
 			counters[0].mae_id.id, rte_strerror(rc));
@@ -851,7 +851,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	return 0;
 
 fail_fill_in_id:
-	(void)sfc_mae_counter_disable(sa, &counters[0]);
+	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 
 fail_counter_add:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
@@ -860,7 +860,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter_id *counters,
+			 struct sfc_mae_counter *counters,
 			 unsigned int n_counters)
 {
 	if (n_counters == 0)
@@ -874,7 +874,7 @@ sfc_mae_counters_disable(struct sfc_adapter *sa,
 		return EALREADY;
 	}
 
-	return sfc_mae_counter_disable(sa, &counters[0]);
+	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 }
 
 struct sfc_mae_aset_ctx {
@@ -1039,7 +1039,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_counter *counters;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 67fa2ca5c9..7337fcf14d 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -68,7 +68,7 @@ struct sfc_mae_encap_header {
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
 /* Counter ID */
-struct sfc_mae_counter_id {
+struct sfc_mae_counter {
 	/* ID of a counter in MAE */
 	efx_counter_t			mae_id;
 	/* ID of a counter in RTE */
@@ -86,7 +86,7 @@ struct sfc_mae_counter_id {
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter_id	*counters;
+	struct sfc_mae_counter		*counters;
 	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
@@ -129,7 +129,7 @@ struct sfc_mae_bounce_eh {
 };
 
 /** Counter collection entry */
-struct sfc_mae_counter {
+struct sfc_mae_counter_record {
 	bool				inuse;
 	uint32_t			generation_count;
 	union sfc_pkts_bytes		value;
@@ -143,9 +143,9 @@ struct sfc_mae_counters_xstats {
 	uint64_t			realloc_update;
 };
 
-struct sfc_mae_counters {
+struct sfc_mae_counter_records {
 	/** An array of all MAE counters */
-	struct sfc_mae_counter		*mae_counters;
+	struct sfc_mae_counter_record	*mae_counters;
 	/** Extra statistics for counters */
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
@@ -162,7 +162,7 @@ enum sfc_mae_counter_polling_mode {
 struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Counters collection */
-	struct sfc_mae_counters		counters;
+	struct sfc_mae_counter_records	counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
@@ -219,7 +219,7 @@ struct sfc_mae {
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
 	bool				counter_rxq_running;
-	/** Counter registry */
+	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 818b4dad4a..8170175991 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -76,12 +76,12 @@ sfc_mae_counter_rxq_required(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_enable(struct sfc_adapter *sa,
-		       struct sfc_mae_counter_id *counterp)
+sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
@@ -147,12 +147,12 @@ sfc_mae_counter_enable(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counter_disable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counter)
+sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
@@ -189,12 +189,13 @@ sfc_mae_counter_disable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_counter_increment(struct sfc_adapter *sa,
-			  struct sfc_mae_counters *counters,
+			  struct sfc_mae_counter_records *counters,
 			  uint32_t mae_counter_id,
 			  uint32_t generation_count,
 			  uint64_t pkts, uint64_t bytes)
 {
-	struct sfc_mae_counter *p = &counters->mae_counters[mae_counter_id];
+	struct sfc_mae_counter_record *p =
+		&counters->mae_counters[mae_counter_id];
 	struct sfc_mae_counters_xstats *xstats = &counters->xstats;
 	union sfc_pkts_bytes cnt_val;
 	bool inuse;
@@ -667,7 +668,7 @@ sfc_mae_counter_thread_spawn(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counters_init(struct sfc_mae_counters *counters,
+sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 		      uint32_t nb_counters_max)
 {
 	int rc;
@@ -691,7 +692,7 @@ sfc_mae_counters_init(struct sfc_mae_counters *counters,
 }
 
 void
-sfc_mae_counters_fini(struct sfc_mae_counters *counters)
+sfc_mae_counters_fini(struct sfc_mae_counter_records *counters)
 {
 	rte_free(counters->mae_counters);
 	counters->mae_counters = NULL;
@@ -942,13 +943,13 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counters *counters,
-		    const struct sfc_mae_counter_id *counter,
+sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
 	uint64_t non_reset_tunnel_hit_counter;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
 	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 28d70f7d69..9c6d8103ac 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -38,15 +38,15 @@ void sfc_mae_counter_rxq_detach(struct sfc_adapter *sa);
 int sfc_mae_counter_rxq_init(struct sfc_adapter *sa);
 void sfc_mae_counter_rxq_fini(struct sfc_adapter *sa);
 
-int sfc_mae_counters_init(struct sfc_mae_counters *counters,
+int sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 			  uint32_t nb_counters_max);
-void sfc_mae_counters_fini(struct sfc_mae_counters *counters);
-int sfc_mae_counter_enable(struct sfc_adapter *sa,
-			   struct sfc_mae_counter_id *counterp);
-int sfc_mae_counter_disable(struct sfc_adapter *sa,
-			    struct sfc_mae_counter_id *counter);
-int sfc_mae_counter_get(struct sfc_mae_counters *counters,
-			const struct sfc_mae_counter_id *counter,
+void sfc_mae_counters_fini(struct sfc_mae_counter_records *counters);
+int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+				   struct sfc_mae_counter *counterp);
+int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				    struct sfc_mae_counter *counter);
+int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
 int sfc_mae_counter_start(struct sfc_adapter *sa);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 29/34] net/sfc: rework MAE action rule counter representation in SW
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (27 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
                     ` (5 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such rework is needed to prepare for INDIRECT action support
and in order to align with the latest HW support perspective.

Currently, the driver supports only one counter per flow. It
was once thought that MAE would support multiple counters in
one action set. That was partly envisaged in code and naming.
But HW support for the feature is no longer planned in EF100.

The code also assumes that a counter object cannot be shared.
This assumption is outdated. The driver may support this now
via action of type INDIRECT provided by generic flow library.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 342 +++++++++++++++++-------------
 drivers/net/sfc/sfc_mae.h         |  17 +-
 drivers/net/sfc/sfc_mae_counter.c |  22 +-
 3 files changed, 211 insertions(+), 170 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2b4c821883..4d3778eaba 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
+	TAILQ_INIT(&mae->counters);
 	TAILQ_INIT(&mae->action_sets);
 	TAILQ_INIT(&mae->action_rules);
 
@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter *counters,
-			unsigned int n_counters,
-			efx_mae_actions_t *action_set_spec)
+sfc_mae_counter_add(struct sfc_adapter *sa,
+		    const struct sfc_mae_counter *counter_tmp,
+		    struct sfc_mae_counter **counterp)
 {
-	int rc;
+	struct sfc_mae_counter *counter;
+	struct sfc_mae *mae = &sa->mae;
 
-	sfc_log_init(sa, "entry");
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	if (n_counters == 0) {
-		sfc_log_init(sa, "no counters - skip");
-		return 0;
+	counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
+	if (counter == NULL)
+		return ENOMEM;
+
+	if (counter_tmp != NULL) {
+		counter->rte_id_valid = counter_tmp->rte_id_valid;
+		counter->rte_id = counter_tmp->rte_id;
 	}
 
-	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
+	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+	counter->refcnt = 1;
 
-	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
-	if (rc != 0) {
-		sfc_err(sa, "failed to enable MAE counter %u: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_counter_add;
-	}
+	TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
+	*counterp = counter;
 
-	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
-						   &counters[0].mae_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_fill_in_id;
-	}
+	sfc_dbg(sa, "added counter=%p", counter);
 
 	return 0;
+}
+
+static void
+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae *mae = &sa->mae;
 
-fail_fill_in_id:
-	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	if (counter == NULL)
+		return;
 
-fail_counter_add:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(counter->refcnt != 0);
+
+	--(counter->refcnt);
+
+	if (counter->refcnt != 0)
+		return;
+
+	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    counter->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
+			counter, counter->fw_rsrc.counter_id.id,
+			counter->fw_rsrc.refcnt);
+	}
+
+	TAILQ_REMOVE(&mae->counters, counter, entries);
+	rte_free(counter);
+
+	sfc_dbg(sa, "deleted counter=%p", counter);
 }
 
 static int
-sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter *counters,
-			 unsigned int n_counters)
+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
+		       efx_mae_actions_t *action_set_spec)
 {
-	if (n_counters == 0)
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
 		return 0;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
 
-	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
-		sfc_err(sa, "failed to disable: already disabled");
-		return EALREADY;
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
+
+		rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
+		if (rc != 0) {
+			sfc_err(sa, "failed to enable counter=%p: %s",
+				counter, rte_strerror(rc));
+			return rc;
+		}
+	}
+
+	if (action_set_spec != NULL) {
+		rc = efx_mae_action_set_fill_in_counter_id(
+					action_set_spec, &fw_rsrc->counter_id);
+		if (rc != 0) {
+			if (fw_rsrc->refcnt == 0) {
+				(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
+				fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+			}
+
+			sfc_err(sa, "cannot fill in counter ID: %s",
+				strerror(rc));
+			return rc;
+		}
+	}
+
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
+			counter, fw_rsrc->counter_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static void
+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
+			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		uint32_t counter_id = fw_rsrc->counter_id.id;
+
+		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
+				counter, counter_id);
+		} else {
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
+				counter, counter_id, strerror(rc));
+		}
+
+		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
 	}
 
-	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	--(fw_rsrc->refcnt);
 }
 
 struct sfc_mae_aset_ctx {
-	uint64_t			*ft_switch_hit_counter;
-	struct sfc_ft_ctx		*counter_ft_ctx;
 	struct sfc_mae_encap_header	*encap_header;
-	unsigned int			n_counters;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_mac_addr		*dst_mac;
 	struct sfc_mae_mac_addr		*src_mac;
 
@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	/*
-	 * Shared counters are not supported, hence, action
-	 * sets with counters are not attachable.
-	 */
-	if (ctx->n_counters != 0)
-		return NULL;
-
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
 		if (action_set->encap_header == ctx->encap_header &&
 		    action_set->dst_mac_addr == ctx->dst_mac &&
 		    action_set->src_mac_addr == ctx->src_mac &&
+		    action_set->counter == ctx->counter &&
 		    efx_mae_action_set_specs_equal(action_set->spec,
 						   ctx->spec)) {
 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
-		       const struct rte_flow_action actions[],
 		       const struct sfc_mae_aset_ctx *ctx,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
 	struct sfc_mae *mae = &sa->mae;
-	unsigned int i;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 		return ENOMEM;
 	}
 
-	if (ctx->n_counters > 0) {
-		const struct rte_flow_action *action;
-
-		action_set->counters = rte_malloc("sfc_mae_counter_ids",
-			sizeof(action_set->counters[0]) * ctx->n_counters, 0);
-		if (action_set->counters == NULL) {
-			rte_free(action_set);
-			sfc_err(sa, "failed to alloc counters");
-			return ENOMEM;
-		}
-
-		for (i = 0; i < ctx->n_counters; ++i) {
-			action_set->counters[i].rte_id_valid = B_FALSE;
-			action_set->counters[i].mae_id.id =
-				EFX_MAE_RSRC_ID_INVALID;
-
-			action_set->counters[i].ft_ctx = ctx->counter_ft_ctx;
-			action_set->counters[i].ft_switch_hit_counter =
-				ctx->ft_switch_hit_counter;
-		}
-
-		for (action = actions, i = 0;
-		     action->type != RTE_FLOW_ACTION_TYPE_END &&
-		     i < ctx->n_counters; ++action) {
-			const struct rte_flow_action_count *conf;
-
-			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
-				continue;
-
-			conf = action->conf;
-
-			action_set->counters[i].rte_id_valid = B_TRUE;
-			action_set->counters[i].rte_id = conf->id;
-			i++;
-		}
-		action_set->n_counters = ctx->n_counters;
-	}
-
 	action_set->refcnt = 1;
 	action_set->spec = ctx->spec;
 	action_set->encap_header = ctx->encap_header;
 	action_set->dst_mac_addr = ctx->dst_mac;
 	action_set->src_mac_addr = ctx->src_mac;
+	action_set->counter = ctx->counter;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
 	sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
-	if (action_set->n_counters > 0) {
-		SFC_ASSERT(action_set->n_counters == 1);
-		SFC_ASSERT(action_set->counters[0].mae_id.id ==
-			   EFX_MAE_RSRC_ID_INVALID);
-		rte_free(action_set->counters);
-	}
+	sfc_mae_counter_del(sa, action_set->counter);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 
@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter *counters;
+	struct sfc_mae_counter *counter;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	encap_header = action_set->encap_header;
 	dst_mac_addr = action_set->dst_mac_addr;
 	src_mac_addr = action_set->src_mac_addr;
-	counters = action_set->counters;
 	fw_rsrc = &action_set->fw_rsrc;
+	counter = action_set->counter;
 
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
-		if (action_set->n_counters > 0) {
+		if (counter != NULL) {
 			rc = sfc_mae_counter_start(sa);
 			if (rc != 0) {
 				sfc_err(sa, "failed to start MAE counters support: %s",
@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			}
 		}
 
-		rc = sfc_mae_counters_enable(sa, counters,
-					     action_set->n_counters,
-					     action_set->spec);
+		rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
 		if (rc != 0) {
-			sfc_err(sa, "failed to enable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			sfc_err(sa, "failed to enable action_set=%p: %s",
 				action_set, strerror(rc));
 
-			(void)sfc_mae_counters_disable(sa, counters,
-						       action_set->n_counters);
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+			sfc_mae_counter_disable(sa, counter);
 			return rc;
 		}
 
@@ -1160,16 +1188,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 		}
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-		rc = sfc_mae_counters_disable(sa, action_set->counters,
-					      action_set->n_counters);
-		if (rc != 0) {
-			sfc_err(sa, "failed to disable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-		}
-
 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
 		sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
 		sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
+		sfc_mae_counter_disable(sa, action_set->counter);
 	}
 
 	--(fw_rsrc->refcnt);
@@ -3929,10 +3951,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
-				const struct rte_flow_action_count *conf
-					__rte_unused,
+				const struct rte_flow_action_count *conf,
+				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
+	struct sfc_mae_counter counter_tmp = {};
 	int rc;
 
 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
@@ -3947,17 +3970,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		goto fail_no_service_core;
 	}
 
-	rc = efx_mae_action_set_populate_count(spec);
-	if (rc != 0) {
-		sfc_err(sa,
-			"failed to populate counters in MAE action set: %s",
-			rte_strerror(rc));
-		goto fail_populate_count;
+	if (*counterp != NULL) {
+		sfc_err(sa, "cannot request more than 1 action COUNT per flow");
+		rc = EINVAL;
+		goto fail_more_than_one;
+	}
+
+	if (spec != NULL) {
+		rc = efx_mae_action_set_populate_count(spec);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to populate counters in MAE action set: %s",
+				rte_strerror(rc));
+			goto fail_populate_count;
+		}
+	}
+
+	if (conf != NULL) {
+		counter_tmp.rte_id_valid = true;
+		counter_tmp.rte_id = conf->id;
 	}
 
+	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
+
 	return 0;
 
 fail_populate_count:
+fail_more_than_one:
 fail_no_service_core:
 fail_counter_queue_uninit:
 
@@ -4124,7 +4163,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
+	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
+	efx_mae_actions_t *spec_ptr = spec;
 	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -4212,7 +4253,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
-		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
+		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
@@ -4362,19 +4404,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
-	for (action = actions;
-	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
-			++(ctx.n_counters);
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		bool have_user_action_count = false;
+
 		/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
 		rc = efx_mae_action_set_populate_decap(ctx.spec);
 		if (rc != 0)
 			goto fail_enforce_ft_decap;
 
-		if (ctx.n_counters == 0 &&
+		for (action = actions;
+		     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+			if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+				have_user_action_count = true;
+				break;
+			}
+		}
+
+		if (!have_user_action_count &&
 		    sfc_mae_counter_stream_enabled(sa)) {
 			/*
 			 * The user opted not to use action COUNT in this rule,
@@ -4386,7 +4432,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			if (rc != 0)
 				goto fail_enforce_ft_count;
 
-			ctx.n_counters = 1;
+			rc = sfc_mae_counter_add(sa, NULL, &ctx.counter);
+			if (rc != 0)
+				goto fail_enforce_ft_count;
 		}
 	}
 
@@ -4416,13 +4464,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_encap_header;
 
-	if (ctx.n_counters > 1) {
-		rc = ENOTSUP;
-		sfc_err(sa, "too many count actions requested: %u",
-			ctx.n_counters);
-		goto fail_nb_count;
-	}
-
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
@@ -4432,7 +4473,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_workaround_tunnel_delivery;
 
-		ctx.counter_ft_ctx = spec_mae->ft_ctx;
+		if (ctx.counter != NULL)
+			(ctx.counter)->ft_ctx = spec_mae->ft_ctx;
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
@@ -4441,7 +4483,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		ctx.ft_switch_hit_counter =
+		(ctx.counter)->ft_switch_hit_counter =
 			&spec_mae->ft_ctx->switch_hit_counter;
 		break;
 	default:
@@ -4465,6 +4507,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
 	if (action_rule_ctx->action_set != NULL) {
+		sfc_mae_counter_del(sa, ctx.counter);
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -4472,8 +4515,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx,
-				    &action_rule_ctx->action_set);
+	rc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -4482,11 +4524,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 fail_action_set_add:
 fail_check_fate_action:
 fail_workaround_tunnel_delivery:
-fail_nb_count:
 	sfc_mae_encap_header_del(sa, ctx.encap_header);
 
 fail_process_encap_header:
 fail_rule_parse_action:
+	sfc_mae_counter_del(sa, ctx.counter);
 	sfc_mae_mac_addr_del(sa, ctx.src_mac);
 	sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 	efx_mae_action_set_spec_fini(sa->nic, ctx.spec);
@@ -4766,28 +4808,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
 	struct sfc_mae_action_set *action_set;
-	unsigned int i;
+	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
 	action_set = action_rule->action_set;
+	counter = action_set->counter;
 
-	for (i = 0; i < action_set->n_counters; i++) {
-		/*
-		 * Get the first available counter of the flow rule if
-		 * counter ID is not specified, provided that this
-		 * counter is not an automatic (implicit) one.
-		 */
-		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
-			continue;
-
+	if (conf == NULL ||
+	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 &action_set->counters[i], data);
+					 counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 7337fcf14d..c73ce0a5e6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	unsigned int			refcnt;
 	RTE_STD_C11
 	union {
+		efx_counter_t		counter_id;
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
 		efx_mae_mac_id_t	mac_id;
@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {
 
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
-/* Counter ID */
+/* Counter object registry entry */
 struct sfc_mae_counter {
-	/* ID of a counter in MAE */
-	efx_counter_t			mae_id;
+	TAILQ_ENTRY(sfc_mae_counter)	entries;
+	unsigned int			refcnt;
+
 	/* ID of a counter in RTE */
 	uint32_t			rte_id;
 	/* RTE counter ID validity status */
@@ -80,18 +82,21 @@ struct sfc_mae_counter {
 	uint64_t			*ft_switch_hit_counter;
 	/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */
 	struct sfc_ft_ctx		*ft_ctx;
+
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter		*counters;
-	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_mac_addr		*dst_mac_addr;
 	struct sfc_mae_mac_addr		*src_mac_addr;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -221,6 +226,8 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
+	/** Counter object registry */
+	struct sfc_mae_counters		counters;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 8170175991..90b89e81c6 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 		goto fail_counter_id_range;
 	}
 
-	counterp->mae_id = mae_counter;
+	counterp->fw_rsrc.counter_id.id = mae_counter.id;
 
 	p = &counters->mae_counters[mae_counter.id];
 
@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
 	struct sfc_mae_counter_records *counters = &reg->counters;
+	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
-	if (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)
-		return 0;
-
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
+	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
 	 * at the beginning of delete operation. Release ordering is
 	 * paired with acquire ordering on load in counter increment operation.
 	 */
-	p = &counters->mae_counters[counter->mae_id.id];
+	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);
+	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
 	if (rc != 0)
 		sfc_err(sa, "failed to free MAE counter %u: %s",
-			counter->mae_id.id, rte_strerror(rc));
+			mae_counter->id, rte_strerror(rc));
 
 	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, counter->mae_id.id,
+		 " bytes=%" PRIu64, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	 * If there's some error, the resulting resource leakage is bad, but
 	 * nothing sensible can be done in this case.
 	 */
-	counter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;
+	mae_counter->id = EFX_MAE_RSRC_ID_INVALID;
 
 	return rc;
 }
@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
-	p = &counters->mae_counters[counter->mae_id.id];
+	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
+	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
 
 	/*
 	 * Ordering is relaxed since it is the only operation on counter value.
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 30/34] net/sfc: support indirect count action in transfer flows
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (28 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
                     ` (4 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Indirect count action is useful to applications that
need to gather aggregated statistics for many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst            |   2 +
 doc/guides/rel_notes/release_23_07.rst |   3 +
 drivers/net/sfc/sfc.h                  |   1 +
 drivers/net/sfc/sfc_flow.c             | 126 +++++++++++++++++++
 drivers/net/sfc/sfc_flow.h             |  14 +++
 drivers/net/sfc/sfc_mae.c              | 167 ++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h              |  15 +++
 7 files changed, 327 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 6e974c3720..ba82b02093 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -306,6 +306,8 @@ Supported actions (***transfer*** rules):
 
 - COUNT
 
+- INDIRECT
+
 - DROP
 
 Validating flow rules depends on the firmware variant.
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index 6fae4eb0a7..5a77b71d0a 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -70,6 +70,9 @@ New Features
     The caller is responsible to request this offload
     only when the target header is an IPv4-based one.
 
+  * Added support for transfer flow action INDIRECT
+    with subtype COUNT, for aggregated statistics.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 6b301aad60..f84a21009e 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -248,6 +248,7 @@ struct sfc_adapter {
 	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
+	struct sfc_flow_indir_actions	flow_indir_actions;
 	struct sfc_flow_list		flow_list;
 
 	unsigned int			rxq_max;
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 0abeabfbf2..a35f20770d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static struct rte_flow_action_handle *
+sfc_flow_action_handle_create(struct rte_eth_dev *dev,
+			      const struct rte_flow_indir_action_conf *conf,
+			      const struct rte_flow_action *action,
+			      struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *handle;
+	int ret;
+
+	if (!conf->transfer) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "non-transfer domain does not support indirect actions");
+		return NULL;
+	}
+
+	if (conf->ingress || conf->egress) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "cannot combine ingress/egress with transfer");
+		return NULL;
+	}
+
+	handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0);
+	if (handle == NULL) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "failed to allocate memory");
+		return NULL;
+	}
+
+	sfc_adapter_lock(sa);
+
+	ret = sfc_mae_indir_action_create(sa, action, handle, error);
+	if (ret != 0) {
+		sfc_adapter_unlock(sa);
+		rte_free(handle);
+		return NULL;
+	}
+
+	TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);
+
+	handle->transfer = (bool)conf->transfer;
+
+	sfc_adapter_unlock(sa);
+
+	return handle;
+}
+
+static int
+sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,
+			       struct rte_flow_action_handle *handle,
+			       struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_destroy(sa, handle,
+							  error);
+			if (rc != 0)
+				goto exit;
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);
+		rte_free(entry);
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
+static int
+sfc_flow_action_handle_query(struct rte_eth_dev *dev,
+			     const struct rte_flow_action_handle *handle,
+			     void *data, struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_query(sa, handle,
+							data, error);
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
 const struct rte_flow_ops sfc_flow_ops = {
 	.validate = sfc_flow_validate,
 	.create = sfc_flow_create,
@@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = {
 	.flush = sfc_flow_flush,
 	.query = sfc_flow_query,
 	.isolate = sfc_flow_isolate,
+	.action_handle_create = sfc_flow_action_handle_create,
+	.action_handle_destroy = sfc_flow_action_handle_destroy,
+	.action_handle_query = sfc_flow_action_handle_query,
 	.tunnel_decap_set = sfc_ft_decap_set,
 	.tunnel_match = sfc_ft_match,
 	.tunnel_action_decap_release = sfc_ft_action_decap_release,
@@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa)
 {
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	TAILQ_INIT(&sa->flow_indir_actions);
 	TAILQ_INIT(&sa->flow_list);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 8f706fc589..af94d0654a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -88,6 +88,20 @@ struct sfc_flow_spec_mae {
 	sfc_mae_conntrack_key_t		ct_key;
 };
 
+/* PMD-specific definition of the opaque type from rte_flow.h */
+struct rte_flow_action_handle {
+	TAILQ_ENTRY(rte_flow_action_handle)	entries;
+
+	bool					transfer;
+	enum rte_flow_action_type		type;
+
+	union {
+		struct sfc_mae_counter		*counter;
+	};
+};
+
+TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle);
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 4d3778eaba..e79df3b56a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -4003,6 +4003,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa,
+				   const struct rte_flow_action_handle *handle,
+				   enum sfc_ft_rule_type ft_rule_type,
+				   struct sfc_mae_aset_ctx *ctx,
+				   struct rte_flow_error *error)
+{
+	struct rte_flow_action_handle *entry;
+	int rc;
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry == handle) {
+			sfc_dbg(sa, "attaching to indirect_action=%p", entry);
+
+			switch (entry->type) {
+			case RTE_FLOW_ACTION_TYPE_COUNT:
+				if (ft_rule_type != SFC_FT_RULE_NONE) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot use indirect count action in tunnel model");
+				}
+
+				if (ctx->counter != NULL) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot have multiple actions COUNT in one flow");
+				}
+
+				rc = efx_mae_action_set_populate_count(ctx->spec);
+				if (rc != 0) {
+					return rte_flow_error_set(error, rc,
+					 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					 "failed to add COUNT to MAE action set");
+				}
+
+				ctx->counter = entry->counter;
+				++(ctx->counter->refcnt);
+				break;
+			default:
+				SFC_ASSERT(B_FALSE);
+				break;
+			}
+
+			return 0;
+		}
+	}
+
+	return rte_flow_error_set(error, ENOENT,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				  "indirect action handle not found");
+}
+
 static int
 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
 				const struct rte_flow_action_vf *vf_conf,
@@ -4141,6 +4193,7 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
 	[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
 	[RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT",
+	[RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT",
 	[RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
 	[RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
 	[RTE_FLOW_ACTION_TYPE_PF] = "PF",
@@ -4256,6 +4309,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
 						     counterp, spec_ptr);
 		break;
+	case RTE_FLOW_ACTION_TYPE_INDIRECT:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_indirect(sa, action->conf,
+							spec_mae->ft_rule_type,
+							ctx, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -4811,7 +4872,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
+	if (action_rule == NULL || action_rule->action_set == NULL ||
+	    action_rule->action_set->counter == NULL ||
+	    action_rule->action_set->counter->indirect) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
@@ -4922,3 +4985,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
+
+int
+sfc_mae_indir_action_create(struct sfc_adapter *sa,
+			    const struct rte_flow_action *action,
+			    struct rte_flow_action_handle *handle,
+			    struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      &handle->counter, NULL);
+		if (ret == 0)
+			handle->counter->indirect = true;
+		break;
+	default:
+		ret = ENOTSUP;
+	}
+
+	if (ret != 0) {
+		return rte_flow_error_set(error, ret,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"failed to parse indirect action to mae object");
+	}
+
+	handle->type = action->type;
+
+	return 0;
+}
+
+int
+sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+			     const struct rte_flow_action_handle *handle,
+			     struct rte_flow_error *error)
+{
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		if (handle->counter->refcnt != 1)
+			goto fail;
+
+		sfc_mae_counter_del(sa, handle->counter);
+		break;
+	default:
+		SFC_ASSERT(B_FALSE);
+		break;
+	}
+
+	return 0;
+
+fail:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is still in use");
+}
+
+int
+sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			   const struct rte_flow_action_handle *handle,
+			   void *data, struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		SFC_ASSERT(handle->counter != NULL);
+
+		if (handle->counter->fw_rsrc.refcnt == 0)
+			goto fail_not_in_use;
+
+		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
+					  handle->counter, data);
+		if (ret != 0)
+			goto fail_counter_get;
+
+		break;
+	default:
+		goto fail_unsup;
+	}
+
+	return 0;
+
+fail_not_in_use:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is not in use");
+
+fail_counter_get:
+	return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "failed to collect indirect action COUNT data");
+
+fail_unsup:
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action of this type cannot be queried");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index c73ce0a5e6..e7b7d3a35e 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -84,6 +84,8 @@ struct sfc_mae_counter {
 	struct sfc_ft_ctx		*ft_ctx;
 
 	struct sfc_mae_fw_rsrc		fw_rsrc;
+
+	bool				indirect;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
+int sfc_mae_indir_action_create(struct sfc_adapter *sa,
+				const struct rte_flow_action *action,
+				struct rte_flow_action_handle *handle,
+				struct rte_flow_error *error);
+
+int sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+				 const struct rte_flow_action_handle *handle,
+				 struct rte_flow_error *error);
+
+int sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			       const struct rte_flow_action_handle *handle,
+			       void *data, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (29 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
                     ` (3 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is required to disambiguate counters of different
types supported by the match-action engine (MAE) on EF100.

Currently, the code only supports action rule counters,
but MAE may also support conntrack assistance counters.
Add type-aware allocate and free MCDI handlers and
extend reporting of counter limits accordingly.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  39 +++++++-
 drivers/common/sfc_efx/base/efx_impl.h |   2 +-
 drivers/common/sfc_efx/base/efx_mae.c  | 120 ++++++++++++++++++++-----
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 140 insertions(+), 23 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 0a08b490e5..5b992ec723 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,7 +4191,10 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
 	uint32_t			eml_encap_header_size_limit;
-	uint32_t			eml_max_n_counters;
+	union {
+		uint32_t		eml_max_n_counters;
+		uint32_t		eml_max_n_action_counters;
+	};
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4780,6 +4783,14 @@ efx_mae_action_set_fill_in_eh_id(
 	__in				efx_mae_actions_t *spec,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/*
+ * Counter types that may be supported by the match-action engine.
+ * Each counter type maintains its own counter ID namespace in FW.
+ */
+typedef enum efx_counter_type_e {
+	EFX_COUNTER_TYPE_ACTION = 0,
+} efx_counter_type_t;
+
 typedef struct efx_counter_s {
 	uint32_t id;
 } efx_counter_t;
@@ -4809,6 +4820,8 @@ efx_mae_action_set_alloc(
 	__out				efx_mae_aset_id_t *aset_idp);
 
 /*
+ * Allocates MAE counter(s) of type EFX_COUNTER_TYPE_ACTION.
+ *
  * Generation count has two purposes:
  *
  * 1) Distinguish between counter packets that belong to freed counter
@@ -4832,6 +4845,20 @@ efx_mae_counters_alloc(
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+/*
+ * Allocates MAE counter(s) of the specified type. Other
+ * than that, behaves like efx_mae_counters_alloc().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_alloc_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_counters_free(
@@ -4841,6 +4868,16 @@ efx_mae_counters_free(
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 /* When set, include counters with a value of zero */
 #define	EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE	(1U << 0)
 
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index e978ad0de8..f6b472c160 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -841,7 +841,7 @@ typedef struct efx_mae_s {
 	/** Outer rule match field capabilities. */
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
-	uint32_t			em_max_ncounters;
+	uint32_t			em_max_n_action_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index aaea38c933..4078146741 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -67,8 +67,8 @@ efx_mae_get_capabilities(
 	maep->em_max_nfields =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
 
-	maep->em_max_ncounters =
-	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS);
+	maep->em_max_n_action_counters =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
 	return (0);
 
@@ -374,7 +374,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
-	emlp->eml_max_n_counters = maep->em_max_ncounters;
+	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
 
 	return (0);
 
@@ -3256,55 +3256,70 @@ efx_mae_action_set_fill_in_counter_id(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_alloc(
+efx_mae_counters_alloc_type(
 	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
 	__in				uint32_t n_counters,
 	__out				uint32_t *n_allocatedp,
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_ALLOC_IN_LEN,
+	    MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	uint32_t n_allocated;
 	efx_mcdi_req_t req;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (n_counters > max_n_counters ||
 	    n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
 	    n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
 		rc = EINVAL;
-		goto fail1;
+		goto fail2;
 	}
 
 	req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
 
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
 	    n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_allocated = MCDI_OUT_DWORD(req,
 	    MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
 	if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	for (i = 0; i < n_allocated; i++) {
@@ -3321,6 +3336,8 @@ efx_mae_counters_alloc(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3334,33 +3351,67 @@ efx_mae_counters_alloc(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_free(
+efx_mae_counters_alloc(
 	__in				efx_nic_t *enp,
 	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
+					 n_counters, n_allocatedp,
+					 countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
 	__out				uint32_t *n_freedp,
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	efx_mcdi_req_t req;
 	uint32_t n_freed;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
-	    n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM ||
-	    n_counters >
-	    MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
 		rc = EINVAL;
 		goto fail1;
 	}
 
+	if (n_counters > max_n_counters ||
+	    n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
+	    n_counters >
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
 	req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters);
+	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
 
@@ -3371,23 +3422,25 @@ efx_mae_counters_free(
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
 			  n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
 
 	if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	if (gen_countp != NULL) {
@@ -3399,6 +3452,8 @@ efx_mae_counters_free(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3411,6 +3466,29 @@ efx_mae_counters_free(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_counters_free(
+	__in				efx_nic_t *enp,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
+					n_counters, n_freedp,
+					countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_counters_stream_start(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 1ff760a024..e550b64be6 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -113,7 +113,9 @@ INTERNAL {
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
 	efx_mae_counters_alloc;
+	efx_mae_counters_alloc_type;
 	efx_mae_counters_free;
+	efx_mae_counters_free_type;
 	efx_mae_counters_stream_give_credits;
 	efx_mae_counters_stream_start;
 	efx_mae_counters_stream_stop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 32/34] net/sfc: indicate MAE counter type in use for transfer flows
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (30 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
                     ` (2 subsequent siblings)
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so assists adding support for additional counter types.

Current implementation is only aware of action rule counters
that are supported by the match-action engine (MAE) on EF100
NICs, but MAE may also support conntrack assistance counters.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 56 ++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |  7 ++-
 drivers/net/sfc/sfc_mae_counter.c | 77 +++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae_counter.h |  2 +-
 4 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e79df3b56a..7353d04af8 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,15 +65,24 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_counters_max)
+			      uint32_t nb_action_counters_max)
 {
-	return sfc_mae_counters_init(&registry->counters, nb_counters_max);
+	int ret;
+
+	ret = sfc_mae_counters_init(&registry->action_counters,
+				    nb_action_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
+
+	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
-	sfc_mae_counters_fini(&registry->counters);
+	sfc_mae_counters_fini(&registry->action_counters);
 }
 
 struct rte_flow *
@@ -153,10 +162,10 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-						   limits.eml_max_n_counters);
+					limits.eml_max_n_action_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init MAE counters registry for %u entries: %s",
-				limits.eml_max_n_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
+				limits.eml_max_n_action_counters, rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -833,6 +842,9 @@ sfc_mae_counter_add(struct sfc_adapter *sa,
 	if (counter_tmp != NULL) {
 		counter->rte_id_valid = counter_tmp->rte_id_valid;
 		counter->rte_id = counter_tmp->rte_id;
+		counter->type = counter_tmp->type;
+	} else {
+		counter->type = EFX_COUNTER_TYPE_ACTION;
 	}
 
 	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -864,8 +876,8 @@ sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
 	    counter->fw_rsrc.refcnt != 0) {
-		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
-			counter, counter->fw_rsrc.counter_id.id,
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, counter->fw_rsrc.counter_id.id,
 			counter->fw_rsrc.refcnt);
 	}
 
@@ -916,8 +928,8 @@ sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
 	}
 
 	if (fw_rsrc->refcnt == 0) {
-		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
-			counter, fw_rsrc->counter_id.id);
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%x-#%u",
+			counter, counter->type, fw_rsrc->counter_id.id);
 	}
 
 	++(fw_rsrc->refcnt);
@@ -940,8 +952,8 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
-		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
-			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
 		return;
 	}
 
@@ -950,11 +962,11 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
 		if (rc == 0) {
-			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
-				counter, counter_id);
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%x-#%u",
+				counter, counter->type, counter_id);
 		} else {
-			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
-				counter, counter_id, strerror(rc));
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%x-#%u: %s",
+				counter, counter->type, counter_id, strerror(rc));
 		}
 
 		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -3952,6 +3964,7 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 				const struct rte_flow_action_count *conf,
+				efx_counter_type_t mae_counter_type,
 				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
@@ -3991,6 +4004,8 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		counter_tmp.rte_id = conf->id;
 	}
 
+	counter_tmp.type = mae_counter_type;
+
 	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
 
 	return 0;
@@ -4215,6 +4230,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
+	efx_counter_type_t mae_counter_type = EFX_COUNTER_TYPE_ACTION;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4307,6 +4323,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     mae_counter_type,
 						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_INDIRECT:
@@ -4885,8 +4902,7 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 
 	if (conf == NULL ||
 	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 counter, data);
+		rc = sfc_mae_counter_get(sa, counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5000,6 +5016,7 @@ sfc_mae_indir_action_create(struct sfc_adapter *sa,
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      EFX_COUNTER_TYPE_ACTION,
 						      &handle->counter, NULL);
 		if (ret == 0)
 			handle->counter->indirect = true;
@@ -5063,8 +5080,7 @@ sfc_mae_indir_action_query(struct sfc_adapter *sa,
 		if (handle->counter->fw_rsrc.refcnt == 0)
 			goto fail_not_in_use;
 
-		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					  handle->counter, data);
+		ret = sfc_mae_counter_get(sa, handle->counter, data);
 		if (ret != 0)
 			goto fail_counter_get;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index e7b7d3a35e..3a3a5225fd 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -86,6 +86,7 @@ struct sfc_mae_counter {
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 
 	bool				indirect;
+	efx_counter_type_t		type;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -157,6 +158,8 @@ struct sfc_mae_counter_records {
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
 	unsigned int			n_mae_counters;
+	/** Counter type, for logging */
+	efx_counter_type_t		type;
 };
 
 /** Options for MAE counter polling mode */
@@ -168,8 +171,8 @@ enum sfc_mae_counter_polling_mode {
 
 struct sfc_mae_counter_registry {
 	/* Common counter information */
-	/** Counters collection */
-	struct sfc_mae_counter_records	counters;
+	/** Action rule counter record collection */
+	struct sfc_mae_counter_records	action_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 90b89e81c6..47448cba15 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -80,19 +80,28 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
 	int rc;
 
+	switch (counterp->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail_counter_type_check;
+	}
+
 	/*
 	 * The actual count of counters allocated is ignored since a failure
 	 * to allocate a single counter is indicated by non-zero return code.
 	 */
-	rc = efx_mae_counters_alloc(sa->nic, 1, &unused, &mae_counter,
-				    &generation_count);
+	rc = efx_mae_counters_alloc_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, &generation_count);
 	if (rc != 0) {
 		sfc_err(sa, "failed to alloc MAE counter: %s",
 			rte_strerror(rc));
@@ -132,16 +141,18 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	 */
 	__atomic_store_n(&p->inuse, true, __ATOMIC_RELEASE);
 
-	sfc_info(sa, "enabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter.id,
+	sfc_info(sa, "enabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counterp->type, mae_counter.id,
 		 p->reset.pkts, p->reset.bytes);
 
 	return 0;
 
 fail_counter_id_range:
-	(void)efx_mae_counters_free(sa->nic, 1, &unused, &mae_counter, NULL);
+	(void)efx_mae_counters_free_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, NULL);
 
 fail_mae_counter_alloc:
+fail_counter_type_check:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -151,12 +162,20 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
 	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		return EINVAL;
+	}
+
 	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
@@ -166,13 +185,14 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
+	rc = efx_mae_counters_free_type(sa->nic, counter->type, 1, &unused,
+					mae_counter, NULL);
 	if (rc != 0)
-		sfc_err(sa, "failed to free MAE counter %u: %s",
-			mae_counter->id, rte_strerror(rc));
+		sfc_err(sa, "failed to free MAE counter 0x%x-#%u: %s",
+			counter->type, mae_counter->id, rte_strerror(rc));
 
-	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter->id,
+	sfc_info(sa, "disabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counter->type, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -243,8 +263,8 @@ sfc_mae_counter_increment(struct sfc_adapter *sa,
 				 __ATOMIC_RELAXED);
 	}
 
-	sfc_info(sa, "update MAE counter #%u: pkts+%" PRIu64 "=%" PRIu64
-		 ", bytes+%" PRIu64 "=%" PRIu64, mae_counter_id,
+	sfc_info(sa, "update MAE counter 0x%x-#%u: pkts+%" PRIu64 "=%" PRIu64
+		 ", bytes+%" PRIu64 "=%" PRIu64, counters->type, mae_counter_id,
 		 pkts, cnt_val.pkts, bytes, cnt_val.bytes);
 }
 
@@ -253,6 +273,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			     struct sfc_mae_counter_registry *counter_registry,
 			     const struct rte_mbuf *m)
 {
+	struct sfc_mae_counter_records *counters;
 	uint32_t generation_count;
 	const efx_xword_t *hdr;
 	const efx_oword_t *counters_data;
@@ -293,7 +314,12 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	}
 
 	id = EFX_XWORD_FIELD(*hdr, ERF_SC_PACKETISER_HEADER_IDENTIFIER);
-	if (unlikely(id != ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR)) {
+
+	switch (id) {
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
+		counters = &counter_registry->action_counters;
+		break;
+	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
 	}
@@ -367,7 +393,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
 		sfc_mae_counter_increment(sa,
-			&counter_registry->counters,
+			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX),
 			generation_count,
@@ -941,14 +967,25 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+sfc_mae_counter_get(struct sfc_adapter *sa,
 		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
+	struct sfc_mae_counter_records *counters;
 	uint64_t non_reset_tunnel_hit_counter;
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
+	bool need_byte_count;
+
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &sa->mae.counter_registry.action_counters;
+		need_byte_count = true;
+		break;
+	default:
+		return EINVAL;
+	}
 
 	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
 	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
@@ -968,7 +1005,7 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 		data->hits += ft_ctx->switch_hit_counter;
 		non_reset_tunnel_hit_counter = data->hits;
 		data->hits -= ft_ctx->reset_tunnel_hit_counter;
-	} else {
+	} else if (need_byte_count) {
 		data->bytes_set = 1;
 		data->bytes = value.bytes - p->reset.bytes;
 	}
@@ -979,7 +1016,9 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 				non_reset_tunnel_hit_counter;
 		} else {
 			p->reset.pkts = value.pkts;
-			p->reset.bytes = value.bytes;
+
+			if (need_byte_count)
+				p->reset.bytes = value.bytes;
 		}
 	}
 
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 9c6d8103ac..effb037799 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -45,7 +45,7 @@ int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 				   struct sfc_mae_counter *counterp);
 int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				    struct sfc_mae_counter *counter);
-int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+int sfc_mae_counter_get(struct sfc_adapter *sa,
 			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 33/34] common/sfc_efx/base: support conntrack assistance counters
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (31 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-04 23:25   ` [PATCH v3 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
  2023-06-07 12:19   ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Counters that can be referenced by HW conntrack assistance
table work similar to those of the action rules. However,
their IDs belong to a separate (CT-specific) namespace.

These are 1-bit saturating counters with no byte count.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  2 ++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 35 +++++++++++++++++++++++---
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 5b992ec723..e3830cb494 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4195,6 +4195,7 @@ typedef struct efx_mae_limits_s {
 		uint32_t		eml_max_n_counters;
 		uint32_t		eml_max_n_action_counters;
 	};
+	uint32_t			eml_max_n_conntrack_counters;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4789,6 +4790,7 @@ efx_mae_action_set_fill_in_eh_id(
  */
 typedef enum efx_counter_type_e {
 	EFX_COUNTER_TYPE_ACTION = 0,
+	EFX_COUNTER_TYPE_CONNTRACK,
 } efx_counter_type_t;
 
 typedef struct efx_counter_s {
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index f6b472c160..a0dde1b1b4 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -842,6 +842,7 @@ typedef struct efx_mae_s {
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
 	uint32_t			em_max_n_action_counters;
+	uint32_t			em_max_n_conntrack_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4078146741..6457f39ccf 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -16,7 +16,7 @@ efx_mae_get_capabilities(
 	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload,
 	    MC_CMD_MAE_GET_CAPS_IN_LEN,
-	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	    MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
 	struct efx_mae_s *maep = enp->en_maep;
 	efx_rc_t rc;
 
@@ -24,7 +24,7 @@ efx_mae_get_capabilities(
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
 	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_MAE_GET_CAPS_OUT_LEN;
+	req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
 
 	efx_mcdi_execute(enp, &req);
 
@@ -70,6 +70,13 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_counters =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
+	if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
+		maep->em_max_n_conntrack_counters =
+		    MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
+	} else {
+		maep->em_max_n_conntrack_counters = 0;
+	}
+
 	return (0);
 
 fail2:
@@ -375,6 +382,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
+	emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
 
 	return (0);
 
@@ -3275,11 +3283,15 @@ efx_mae_counters_alloc_type(
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
 
 	switch (type) {
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3396,6 +3408,9 @@ efx_mae_counters_free_type(
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3498,8 +3513,11 @@ efx_mae_counters_stream_start(
 	__out				uint32_t *flags_out)
 {
 	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN,
+	EFX_MCDI_DECLARE_BUF(payload,
+			     MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
 			     MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	uint32_t counter_types;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
@@ -3510,7 +3528,7 @@ efx_mae_counters_stream_start(
 
 	req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
 
@@ -3519,6 +3537,15 @@ efx_mae_counters_stream_start(
 			 packet_size);
 	MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
 
+	counter_types = (1U << MAE_COUNTER_TYPE_AR);
+
+	if (maep->em_max_n_conntrack_counters != 0)
+		counter_types |= (1U << MAE_COUNTER_TYPE_CT);
+
+	MCDI_IN_SET_DWORD(req,
+			  MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
+			  counter_types);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v3 34/34] net/sfc: use conntrack assistance counters in transfer flows
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (32 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
@ 2023-06-04 23:25   ` Ivan Malov
  2023-06-07 12:19   ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
  34 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-04 23:25 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

These are 1-bit saturating counters which can only be useful
to tell whether a given flow rule has offloaded some packets
since the last query. Byte count is never provided for these.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h        |   2 +
 drivers/net/sfc/sfc_mae.c         | 119 ++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |   2 +
 drivers/net/sfc/sfc_mae_counter.c |  30 ++++++++
 4 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index af94d0654a..601f93e540 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -86,6 +86,8 @@ struct sfc_flow_spec_mae {
 	/* Conntrack (CT) assistance table entry key and response */
 	sfc_mae_conntrack_response_t	ct_resp;
 	sfc_mae_conntrack_key_t		ct_key;
+	/* Conntrack (CT) assistance counter */
+	struct sfc_mae_counter		*ct_counter;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7353d04af8..ab315853d5 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,7 +65,8 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_action_counters_max)
+			      uint32_t nb_action_counters_max,
+			      uint32_t nb_conntrack_counters_max)
 {
 	int ret;
 
@@ -76,12 +77,20 @@ sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
 
 	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
 
+	ret = sfc_mae_counters_init(&registry->conntrack_counters,
+				    nb_conntrack_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
+
 	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
+	sfc_mae_counters_fini(&registry->conntrack_counters);
 	sfc_mae_counters_fini(&registry->action_counters);
 }
 
@@ -162,10 +171,13 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-					limits.eml_max_n_action_counters);
+					limits.eml_max_n_action_counters,
+					limits.eml_max_n_conntrack_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
-				limits.eml_max_n_action_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR and %u CT counters: %s",
+				limits.eml_max_n_action_counters,
+				limits.eml_max_n_conntrack_counters,
+				rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -1471,6 +1483,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 	}
 
 	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
+
+	sfc_mae_counter_del(sa, spec_mae->ct_counter);
 }
 
 static int
@@ -4223,7 +4237,7 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  struct rte_flow *flow,
+			  struct rte_flow *flow, bool ct,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
@@ -4239,6 +4253,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
+	if (ct) {
+		mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
+		counterp = &spec_mae->ct_counter;
+		spec_ptr = NULL;
+	}
+
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
@@ -4526,7 +4546,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, flow,
+		rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
@@ -4561,8 +4581,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		(ctx.counter)->ft_switch_hit_counter =
-			&spec_mae->ft_ctx->switch_hit_counter;
+		if (ctx.counter != NULL) {
+			(ctx.counter)->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		} else if (sfc_mae_counter_stream_enabled(sa)) {
+			SFC_ASSERT(ct);
+
+			spec_mae->ct_counter->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		}
 		break;
 	default:
 		SFC_ASSERT(B_FALSE);
@@ -4843,12 +4870,34 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 		return rc;
 
 	if (spec_mae->action_rule->ct_mark != 0) {
+		struct sfc_mae_counter *counter = spec_mae->ct_counter;
+
+		rc = sfc_mae_counter_enable(sa, counter, NULL);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+
+		if (counter != NULL) {
+			struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
+
+			spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
+
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_mae_action_rule_disable(sa, action_rule);
+				return rc;
+			}
+		} else {
+			spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+		}
+
 		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
-		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
 
 		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
 					      &spec_mae->ct_resp);
 		if (rc != 0) {
+			sfc_mae_counter_disable(sa, counter);
 			sfc_mae_action_rule_disable(sa, action_rule);
 			return rc;
 		}
@@ -4871,6 +4920,8 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule->ct_mark != 0)
 		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
 
+	sfc_mae_counter_disable(sa, spec_mae->ct_counter);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
@@ -4885,31 +4936,41 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 {
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
-	struct sfc_mae_action_set *action_set;
-	struct sfc_mae_counter *counter;
+	struct sfc_mae_counter *counters[1 /* action rule counter */ +
+					 1 /* conntrack counter */];
+	unsigned int i;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set == NULL ||
-	    action_rule->action_set->counter == NULL ||
-	    action_rule->action_set->counter->indirect) {
-		return rte_flow_error_set(error, EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION, action,
-			"Queried flow rule does not have count actions");
-	}
+	/*
+	 * The check for counter unavailability is done based
+	 * on counter traversal results. See error set below.
+	 */
+	if (action_rule != NULL && action_rule->action_set != NULL &&
+	    action_rule->action_set->counter != NULL &&
+	    !action_rule->action_set->counter->indirect)
+		counters[0] = action_rule->action_set->counter;
+	else
+		counters[0] = NULL;
 
-	action_set = action_rule->action_set;
-	counter = action_set->counter;
+	counters[1] = spec->ct_counter;
 
-	if (conf == NULL ||
-	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(sa, counter, data);
-		if (rc != 0) {
-			return rte_flow_error_set(error, EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION, action,
-				"Queried flow rule counter action is invalid");
-		}
+	for (i = 0; i < RTE_DIM(counters); ++i) {
+		struct sfc_mae_counter *counter = counters[i];
 
-		return 0;
+		if (counter == NULL)
+			continue;
+
+		if (conf == NULL ||
+		    (counter->rte_id_valid && conf->id == counter->rte_id)) {
+			rc = sfc_mae_counter_get(sa, counter, data);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION, action,
+					"Queried flow rule counter action is invalid");
+			}
+
+			return 0;
+		}
 	}
 
 	return rte_flow_error_set(error, ENOENT,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3a3a5225fd..80585c0e93 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -173,6 +173,8 @@ struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Action rule counter record collection */
 	struct sfc_mae_counter_records	action_counters;
+	/** Conntrack counter record collection */
+	struct sfc_mae_counter_records	conntrack_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 47448cba15..79043ff7d7 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail_counter_type_check;
@@ -172,6 +175,9 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		return EINVAL;
 	}
@@ -319,6 +325,9 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
 		counters = &counter_registry->action_counters;
 		break;
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT:
+		counters = &counter_registry->conntrack_counters;
+		break;
 	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
@@ -392,6 +401,23 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 		byte_count_hi =
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
+
+		if (id == ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT) {
+			/*
+			 * FIXME:
+			 *
+			 * CT counters are 1-bit saturating counters.
+			 * There is no way to express this in DPDK
+			 * currently, so increment the hit count
+			 * by one to let the application know
+			 * that the flow is still effective.
+			 */
+			packet_count_lo = 1;
+			packet_count_hi = 0;
+			byte_count_lo = 0;
+			byte_count_hi = 0;
+		}
+
 		sfc_mae_counter_increment(sa,
 			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
@@ -983,6 +1009,10 @@ sfc_mae_counter_get(struct sfc_adapter *sa,
 		counters = &sa->mae.counter_registry.action_counters;
 		need_byte_count = true;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &sa->mae.counter_registry.conntrack_counters;
+		need_byte_count = false;
+		break;
 	default:
 		return EINVAL;
 	}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-04 23:24   ` [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
@ 2023-06-07 11:47     ` Andrew Rybchenko
  2023-06-07 12:06     ` Andrew Rybchenko
  1 sibling, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 11:47 UTC (permalink / raw)
  To: Ivan Malov, dev
  Cc: Ferruh Yigit, Denis Pryazhennikov, Viacheslav Galaktionov, Andy Moreton

On 6/5/23 02:24, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> Table's descriptor and fields' descriptors can be taken
> by table ID using a new API.
> In the near future, only the CT table is planned
> to be used, so only fields that are required for these
> purposes were added to the efx.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

[snip]

> +LIBEFX_API
> +extern	__checkReturn				efx_rc_t
> +efx_table_describe(
> +	__in					efx_nic_t *enp,
> +	__in					efx_table_id_t table_id,
> +	__in					uint32_t field_offset,
> +	__out_opt				efx_table_descriptor_t *table_descp,
> +	__out_ecount_opt(*n_fields_descsp)	efx_table_field_descriptor_t *fields_descs,

There is no such parameter n_fields_descsp

> +	__in					unsigned int n_field_descs,
> +	__out_opt				unsigned int *n_field_descs_writtenp);
> +
>   #ifdef	__cplusplus
>   }
>   #endif


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables
  2023-06-04 23:24   ` [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
@ 2023-06-07 11:53     ` Andrew Rybchenko
  0 siblings, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 11:53 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

On 6/5/23 02:24, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> A "table" is structure used for lookups, consisting of a set of
> entries which can be matched against an N-bit "request", to
> return either a "hit" with an M-bit "response", or a "miss" if
> there is no match. There are a number of HW tables of various
> types that could be used in MAE.
> 
> In some types of table the entry may also be associated with an
> N-bit "mask", allowing some bits of the request to be treated as
> don't-care, and an integer "priority" to determine which entry is
> used if more than one matches.
> 
> BCAM tables don't support "mask" and "priority", so the
> corresponding fields must be zeroed.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>   drivers/net/sfc/sfc_tbls.h | 69 ++++++++++++++++++++++++++++++++++++++
>   1 file changed, 69 insertions(+)
>   create mode 100644 drivers/net/sfc/sfc_tbls.h
> 
> diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
> new file mode 100644
> index 0000000000..2a5c87b82c
> --- /dev/null
> +++ b/drivers/net/sfc/sfc_tbls.h
> @@ -0,0 +1,69 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 2023 Advanced Micro Devices, Inc.
> + */
> +
> +#ifndef _SFC_TBLS_H
> +#define _SFC_TBLS_H
> +
> +#include "efx.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**

Why is it Doxygen-style comment?

> + * Table types:
> + *   CAM - Content addressable memory
> + *  BCAM - Binary CAM
> + *  TCAM - Ternary CAM
> + * STCAM - Semi-ternary CAM
> + *
> + * Short description:
> + * TCAM:  Each entry has a key, mask, response and priority. An entry matches
> + *        when (key & mask) == (request & mask). In the case of multiple
> + *        matches, the entry with the highest priority wins; Each entry may
> + *        have its own mask, but TCAM table definitions may place constraints
> + *        on the possible masks allowed for each of the individual fields.
> + * STCAM: A limited form of TCAM in which only a limited number of masks and
> + *        associated priorities), up to some maximum fixed by the definition
> + *        of the table, may be in use at any one time.
> + * BCAM:  Each entry has only a key and response, with the whole request
> + *        matched against the key (like a typical hash table or "map").
> + * Direct (sometimes "DCAM", although it's not really content-addressable):
> + *        Essentially just an array, where the key bits are used simply as an
> + *        index.
> + */
> +
> +/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
> +#define SFC_TBLS_BCAM_PRIORITY		0
> +
> +/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
> +#define SFC_TBLS_BCAM_MASK_ID		0
> +
> +/* Mask is used only for STCAM */
> +#define SFC_TBLS_BCAM_MASK_WIDTH	0
> +
> +static inline int
> +sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
> +			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
> +{
> +	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
> +				      SFC_TBLS_BCAM_MASK_ID, key_width,
> +				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
> +				      data, data_size);
> +}
> +
> +static inline int
> +sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
> +			   uint8_t *data, unsigned int data_size)
> +{
> +	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
> +				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
> +				      data, data_size);
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +#endif /* _SFC_TBLS_H */


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields
  2023-06-04 23:24   ` [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
@ 2023-06-07 12:00     ` Andrew Rybchenko
  0 siblings, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 12:00 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

On 6/5/23 02:24, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> Implemented functions that help to fill user data for
> manipulation with HW tables in the required format.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>   drivers/net/sfc/meson.build |   1 +
>   drivers/net/sfc/sfc_tbls.c  | 140 ++++++++++++++++++++++++++++++++++++
>   drivers/net/sfc/sfc_tbls.h  | 135 ++++++++++++++++++++++++++++++++++
>   3 files changed, 276 insertions(+)
>   create mode 100644 drivers/net/sfc/sfc_tbls.c
> 
> diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
> index c2d8430810..39c7f24764 100644
> --- a/drivers/net/sfc/meson.build
> +++ b/drivers/net/sfc/meson.build
> @@ -87,6 +87,7 @@ sources = files(
>           'sfc_tso.c',
>           'sfc_filter.c',
>           'sfc_switch.c',
> +        'sfc_tbls.c',
>           'sfc_mae.c',
>           'sfc_mae_counter.c',
>           'sfc_flow.c',
> diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
> new file mode 100644
> index 0000000000..db54fc0d40
> --- /dev/null
> +++ b/drivers/net/sfc/sfc_tbls.c
> @@ -0,0 +1,140 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 2023 Advanced Micro Devices, Inc.
> + */
> +
> +#include "sfc_tbls.h"
> +#include "sfc_debug.h"
> +
> +#include <rte_ip.h>
> +
> +/* Number of bits in uint32_t type */
> +#define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
> +
> +static uint32_t
> +sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
> +{
> +	uint32_t mask;
> +
> +	if (width == SFC_TBLS_U32_BITS)
> +		return value;
> +
> +	mask = RTE_LEN2MASK(width, uint32_t);

What should/will happen if width is more than 32?

> +	value &= mask;
> +
> +	if (lbn != 0) {
> +		mask <<= lbn;
> +		value <<= lbn;
> +	}
> +
> +	return (in & (~mask)) | value;
> +}
> +
> +void
> +sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
> +		       uint16_t lbn, uint16_t width, uint32_t value)
> +{
> +	uint32_t data_offset = 0;
> +
> +	if (lbn >= SFC_TBLS_U32_BITS) {
> +		data_offset = lbn / SFC_TBLS_U32_BITS;
> +
> +		SFC_ASSERT(data_offset < data_size);
> +
> +		data += data_offset;
> +		lbn %= SFC_TBLS_U32_BITS;
> +	}
> +
> +	if (lbn + width <= SFC_TBLS_U32_BITS) {
> +		*data = sfc_tbls_field_update(*data, lbn, width, value);
> +	} else {
> +		*data = sfc_tbls_field_update(*data, lbn,
> +					      SFC_TBLS_U32_BITS - lbn, value);
> +		value >>= SFC_TBLS_U32_BITS - lbn;
> +
> +		data_offset++;
> +		SFC_ASSERT(data_offset < data_size);
> +
> +		data++;
> +		*data = sfc_tbls_field_update(*data, 0,
> +					      width + lbn - SFC_TBLS_U32_BITS,
> +					      value);
> +	}
> +}
> +
> +void
> +sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
> +		       uint16_t width, uint16_t value)
> +{
> +	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
> +}
> +
> +void
> +sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
> +		      uint16_t width, uint8_t value)
> +{
> +	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
> +}
> +
> +void
> +sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
> +		      __rte_unused uint16_t width, const uint32_t *ip)
> +{
> +	unsigned int i;
> +	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);

It is unclear why the function is about IPv6 address only. Could you add 
a comment to explain IPv4 case.

> +
> +	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
> +
> +	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
> +		sfc_tbls_field_set_u32(data, data_size, lbn,
> +				       SFC_TBLS_U32_BITS, ip[i]);
> +		lbn += SFC_TBLS_U32_BITS;
> +	}
> +}
> +
> +void
> +sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
> +		       uint16_t lbn, uint16_t width, uint64_t value)
> +{
> +	uint32_t data_offset = 0;
> +
> +	if (lbn >= SFC_TBLS_U32_BITS) {
> +		data_offset = lbn / SFC_TBLS_U32_BITS;
> +
> +		SFC_ASSERT(data_offset < data_size);
> +
> +		data += data_offset;
> +		lbn %= SFC_TBLS_U32_BITS;
> +	}
> +
> +	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
> +	value >>= SFC_TBLS_U32_BITS - lbn;
> +	width -= SFC_TBLS_U32_BITS - lbn;
> +
> +	data_offset++;
> +	SFC_ASSERT(data_offset < data_size);
> +
> +	data++;
> +
> +	if (width > SFC_TBLS_U32_BITS) {
> +		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
> +		value >>= SFC_TBLS_U32_BITS;
> +		width -= SFC_TBLS_U32_BITS;
> +
> +		data_offset++;
> +		SFC_ASSERT(data_offset < data_size);
> +
> +		data++;
> +	}
> +
> +	*data = sfc_tbls_field_update(*data, 0, width, value);
> +}
> +
> +void
> +sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
> +		       uint16_t width, bool value)
> +{
> +	SFC_ASSERT(width == 1);
> +
> +	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
> +}
> diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
> index 2a5c87b82c..7b6bb5b341 100644
> --- a/drivers/net/sfc/sfc_tbls.h
> +++ b/drivers/net/sfc/sfc_tbls.h
> @@ -63,6 +63,141 @@ sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key
>   				      data, data_size);
>   }
>   
> +/**
> + * All manipulations with HW tables entries require forming
> + * a key and response.
> + * The key and response fields follow, consecutively, each
> + * packed as follows:
> + *  - the key/response is logically treated as a single wide N-bit value;
> + *  - fields have been placed in these logical values per the "lbn" and "width"
> + *    information from the table field descriptors;
> + *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
> + *  - the values are put into the table op request with bits[31:0] of the wide
> + *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
> + *
> + * Below is an API that helps to form  MCDI insertion/deletion request.
> + * Workflow:
> + * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
> + * 2) Read a descriptor of the table that you want to use.
> + * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
> + *    Each field of the key has LBN and width. This information can be
> + *    found in a field's descriptor.
> + * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
> + *    must start. It's required as the key and response need to be
> + *    zero-padded at the MSB end to multiples of 32 bits.
> + * 5) Fill the response the same way.
> + * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
> + *    It will help you to get the real size of the data request.
> + */
> +
> +/**
> + * Get a pointer to the beginning of the next 32-bit wide fields
> + * that go after a given width.
> + * It should be used to get a pointer to the response's start and the end
> + * of the data for an MCDI request.
> + *
> + * @param data		Pointer to the data to make an offset from
> + * @param width		Width of fields to offset
> + *
> + * @note @p width is expected to be a key's or response's size.
> + *
> + * @return Pointer to the beginning of the next field.
> + */
> +static inline uint32_t *
> +sfc_tbls_next_req_fields(uint32_t *data, uint16_t width) {

Wrong position of open curly bracket.

> +	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
> +}
> +
> +/**
> + * Insert value into a field in the @p data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param value		uint32_t value to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
> +			    uint16_t lbn, uint16_t width, uint32_t value);
> +
> +/**
> + * Insert value into a field in the @p data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param value		uint16_t value to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
> +			    uint16_t lbn, uint16_t width, uint16_t value);
> +
> +/**
> + * Insert value into a field in the @p data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param value		uint8_t value to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
> +			   uint16_t lbn, uint16_t width, uint8_t value);
> +
> +/**
> + * Insert IP address into a field in the @p data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param ip		IP address to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
> +			   uint16_t lbn, uint16_t width, const uint32_t *ip);
> +
> +/**
> + * Insert value into a field in the data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param value		uint64_t value to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
> +			    uint16_t lbn, uint16_t width, uint64_t value);
> +
> +/**
> + * Insert value into a field in the @p data buffer starting at
> + * bit offset @p lbn and containing @p width bits.
> + *
> + * @param data		Data buffer
> + * @param data_size	Size of the data buffer
> + * @param lbn		Offset
> + * @param width		Width of @p value in bits
> + * @param value		Bit value to insert
> + *
> + * @note @p width and @p lbn must to be obtained from the field's descriptor.
> + */
> +void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
> +			    uint16_t lbn, uint16_t width, bool value);
> +
>   #ifdef __cplusplus
>   }
>   #endif


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-04 23:24   ` [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
  2023-06-07 11:47     ` Andrew Rybchenko
@ 2023-06-07 12:06     ` Andrew Rybchenko
  1 sibling, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 12:06 UTC (permalink / raw)
  To: Ivan Malov, dev
  Cc: Ferruh Yigit, Denis Pryazhennikov, Viacheslav Galaktionov, Andy Moreton

On 6/5/23 02:24, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> Table's descriptor and fields' descriptors can be taken
> by table ID using a new API.
> In the near future, only the CT table is planned
> to be used, so only fields that are required for these
> purposes were added to the efx.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
> ---
>   drivers/common/sfc_efx/base/efx.h       |  67 +++++++
>   drivers/common/sfc_efx/base/efx_table.c | 256 ++++++++++++++++++++++++
>   drivers/common/sfc_efx/version.map      |   3 +
>   3 files changed, 326 insertions(+)
> 
> diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
> index 2de08d1230..8860e4ebbe 100644
> --- a/drivers/common/sfc_efx/base/efx.h
> +++ b/drivers/common/sfc_efx/base/efx.h
> @@ -5085,6 +5085,73 @@ efx_table_list(
>   	__in					unsigned int n_table_ids,
>   	__out_opt				unsigned int *n_table_ids_writtenp);
>   
> +LIBEFX_API
> +extern	__checkReturn		size_t
> +efx_table_supported_num_get(
> +	__in			void);
> +
> +LIBEFX_API
> +extern	__checkReturn		boolean_t
> +efx_table_is_supported(
> +	__in			efx_table_id_t table_id);
> +
> +/* Unique IDs for table fields */
> +typedef enum efx_table_field_id_e {
> +	EFX_TABLE_FIELD_ID_UNUSED = 0x0,
> +	EFX_TABLE_FIELD_ID_COUNTER_ID = 0xa,
> +	EFX_TABLE_FIELD_ID_ETHER_TYPE = 0x1c,
> +	EFX_TABLE_FIELD_ID_SRC_IP = 0x1d,
> +	EFX_TABLE_FIELD_ID_DST_IP = 0x1e,
> +	EFX_TABLE_FIELD_ID_IP_PROTO = 0x20,
> +	EFX_TABLE_FIELD_ID_SRC_PORT = 0x21,
> +	EFX_TABLE_FIELD_ID_DST_PORT = 0x22,
> +	EFX_TABLE_FIELD_ID_NAT_PORT = 0x7a,
> +	EFX_TABLE_FIELD_ID_NAT_IP = 0x7b,
> +	EFX_TABLE_FIELD_ID_NAT_DIR = 0x7c,
> +	EFX_TABLE_FIELD_ID_CT_MARK = 0x7d,
> +} efx_table_field_id_t;
> +
> +/* Table fields mask types */
> +typedef enum efx_table_field_mask_type_e {
> +	EFX_TABLE_FIELD_MASK_NEVER = 0x0,
> +	EFX_TABLE_FIELD_MASK_EXACT = 0x1,
> +} efx_table_field_mask_type_t;
> +
> +typedef struct efx_table_field_desc_s {
> +	efx_table_field_id_t		field_id;
> +	uint16_t			lbn;
> +	uint16_t			width;
> +	efx_table_field_mask_type_t	mask_type;
> +	uint8_t				scheme;
> +} efx_table_field_descriptor_t;
> +
> +/* Types of HW tables */
> +typedef enum efx_table_type_e {
> +	/* Exact match to all key fields of table entry. */
> +	EFX_TABLE_TYPE_BCAM = 0x2,
> +} efx_table_type_t;
> +
> +typedef struct efx_table_descriptor_s {
> +	efx_table_type_t	type;
> +	uint16_t		key_width;
> +	uint16_t		resp_width;
> +	/* Number of key's fields to match data */
> +	uint16_t		n_key_fields;
> +	/* Number of fields in match response */
> +	uint16_t		n_resp_fields;
> +} efx_table_descriptor_t;
> +
> +LIBEFX_API
> +extern	__checkReturn				efx_rc_t
> +efx_table_describe(
> +	__in					efx_nic_t *enp,
> +	__in					efx_table_id_t table_id,
> +	__in					uint32_t field_offset,
> +	__out_opt				efx_table_descriptor_t *table_descp,
> +	__out_ecount_opt(*n_fields_descsp)	efx_table_field_descriptor_t *fields_descs,
> +	__in					unsigned int n_field_descs,
> +	__out_opt				unsigned int *n_field_descs_writtenp);
> +
>   #ifdef	__cplusplus
>   }
>   #endif
> diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
> index 7cfdfea36e..115d86502f 100644
> --- a/drivers/common/sfc_efx/base/efx_table.c
> +++ b/drivers/common/sfc_efx/base/efx_table.c
> @@ -6,6 +6,11 @@
>   #include "efx.h"
>   #include "efx_impl.h"
>   
> +/* List of HW tables that have support in efx */
> +static const efx_table_id_t efx_supported_table_ids[] = {
> +	EFX_TABLE_ID_CONNTRACK,
> +};
> +
>   	__checkReturn				efx_rc_t
>   efx_table_list(
>   	__in					efx_nic_t *enp,
> @@ -80,6 +85,257 @@ efx_table_list(
>   
>   	return (0);
>   
> +fail5:
> +	EFSYS_PROBE(fail5);
> +fail4:
> +	EFSYS_PROBE(fail4);
> +fail3:
> +	EFSYS_PROBE(fail3);
> +fail2:
> +	EFSYS_PROBE(fail2);
> +fail1:
> +	EFSYS_PROBE1(fail1, efx_rc_t, rc);
> +	return (rc);
> +}
> +
> +	__checkReturn		size_t
> +efx_table_supported_num_get(
> +	__in			void)
> +{
> +	return EFX_ARRAY_SIZE(efx_supported_table_ids);

Return value should be in parenthesis in libefx

> +}
> +
> +	__checkReturn		boolean_t
> +efx_table_is_supported(
> +	__in			efx_table_id_t table_id)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < efx_table_supported_num_get(); i++) {
> +		if (efx_supported_table_ids[i] == table_id)
> +			return B_TRUE;

Return value should be in parenthesis in libefx

> +	}
> +
> +	return B_FALSE;

Return value should be in parenthesis in libefx

> +}
> +
> +static	__checkReturn			efx_rc_t
> +efx_table_ct_desc_fields_check(
> +	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
> +	__in				unsigned int n_fields_descs)
> +{
> +	unsigned int i;
> +	efx_rc_t rc;
> +
> +	for (i = 0; i < n_fields_descs; i++) {
> +		switch (fields_descsp[i].field_id) {
> +		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
> +		case EFX_TABLE_FIELD_ID_SRC_IP:
> +		case EFX_TABLE_FIELD_ID_DST_IP:
> +		case EFX_TABLE_FIELD_ID_IP_PROTO:
> +		case EFX_TABLE_FIELD_ID_SRC_PORT:
> +		case EFX_TABLE_FIELD_ID_DST_PORT:
> +			if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
> +				rc = EINVAL;
> +				goto fail1;
> +			}
> +			break;
> +		/*
> +		 * TODO:
> +		 * All fields in the CT table have EXACT mask.
> +		 * All the response field descriptors must have the EXACT mask.
> +		 * In the current implementation, only the Ethertype, source and
> +		 * destination IP address, IP protocol, and source and destination IP
> +		 * are used for the lookup by the key.
> +		 * FW could use the NEVER mask for the fields in the key that are not
> +		 * used for the lookup.
> +		 * As an alternative, a new mask could be added for these fields,
> +		 * like EXACT_NOT_USED.
> +		 */
> +		default:
> +			if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
> +			    (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
> +				rc = EINVAL;
> +				goto fail2;
> +			}
> +			break;
> +		}
> +	}
> +
> +	return (0);
> +
> +fail2:
> +	EFSYS_PROBE(fail2);
> +fail1:
> +	EFSYS_PROBE1(fail1, efx_rc_t, rc);
> +	return (rc);
> +}
> +
> +static	__checkReturn			efx_rc_t
> +efx_table_desc_fields_check(
> +	__in				efx_table_id_t table_id,
> +	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
> +	__in				unsigned int n_fields_descs)
> +{
> +	efx_rc_t rc;
> +
> +	switch (table_id) {
> +	case EFX_TABLE_ID_CONNTRACK:
> +		rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
> +		if (rc != 0)
> +			goto fail1;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return (0);
> +
> +fail1:
> +	EFSYS_PROBE1(fail1, efx_rc_t, rc);
> +	return (rc);
> +}
> +
> +static					void
> +efx_table_desc_fields_get(
> +	__in				const efx_mcdi_req_t *req,
> +	__out_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
> +	__in				unsigned int n_fields_descs)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < n_fields_descs; i++) {
> +		fields_descsp[i].field_id = (efx_table_field_id_t)
> +		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
> +			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
> +
> +		fields_descsp[i].lbn =
> +		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
> +			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
> +
> +		fields_descsp[i].width =
> +		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
> +			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
> +
> +		fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
> +		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
> +			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
> +
> +		fields_descsp[i].scheme =
> +		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
> +			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
> +	}
> +}
> +
> +	__checkReturn				efx_rc_t
> +efx_table_describe(
> +	__in					efx_nic_t *enp,
> +	__in					efx_table_id_t table_id,
> +	__in					uint32_t field_offset,
> +	__out_opt				efx_table_descriptor_t *table_descp,
> +	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
> +	__in					unsigned int n_field_descs,
> +	__out_opt				unsigned int *n_field_descs_writtenp)
> +{
> +	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
> +	unsigned int n_entries;
> +	efx_mcdi_req_t req;
> +	unsigned int i;
> +	efx_rc_t rc;
> +	EFX_MCDI_DECLARE_BUF(payload,
> +	    MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
> +	    MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
> +
> +	/* Ensure EFX and MCDI use same values for table types */
> +	EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
> +
> +	/* Ensure EFX and MCDI use same values for table fields */
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
> +	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
> +
> +	if (encp->enc_table_api_supported == B_FALSE) {
> +		rc = ENOTSUP;
> +		goto fail1;
> +	}
> +
> +	if (!efx_table_is_supported(table_id)) {
> +		rc = ENOTSUP;
> +		goto fail2;
> +	}
> +
> +	if ((n_field_descs != 0) &&
> +	    ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
> +		rc = EINVAL;
> +		goto fail3;
> +	}
> +
> +	req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
> +	req.emr_in_buf = payload;
> +	req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
> +	req.emr_out_buf = payload;
> +	req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
> +
> +	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
> +	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
> +
> +	efx_mcdi_execute(enp, &req);
> +
> +	if (req.emr_rc != 0) {
> +		rc = req.emr_rc;
> +		goto fail4;
> +	}
> +
> +	if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
> +		rc = EMSGSIZE;
> +		goto fail5;
> +	}
> +
> +	if (table_descp != NULL) {
> +		table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
> +		    req, TABLE_DESCRIPTOR_OUT_TYPE);
> +		table_descp->key_width = MCDI_OUT_WORD(
> +		    req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
> +		table_descp->resp_width = MCDI_OUT_WORD(
> +		    req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
> +		table_descp->n_key_fields = MCDI_OUT_WORD(
> +		    req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
> +		table_descp->n_resp_fields = MCDI_OUT_WORD(
> +		    req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
> +	}
> +
> +	n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
> +
> +	if (fields_descs != NULL) {
> +		if (n_entries > n_field_descs) {
> +			rc = ENOMEM;
> +			goto fail6;
> +		}
> +
> +		efx_table_desc_fields_get(&req, fields_descs, n_entries);
> +		rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
> +		if (rc != 0)
> +			goto fail7;
> +	}
> +
> +	if (n_field_descs_writtenp != NULL)
> +		*n_field_descs_writtenp = n_entries;
> +
> +	return (0);
> +
> +fail7:
> +	EFSYS_PROBE(fail7);
> +fail6:
> +	EFSYS_PROBE(fail6);
>   fail5:
>   	EFSYS_PROBE(fail5);
>   fail4:
> diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
> index 5717cc0ed2..a87cb1bba5 100644
> --- a/drivers/common/sfc_efx/version.map
> +++ b/drivers/common/sfc_efx/version.map
> @@ -232,7 +232,10 @@ INTERNAL {
>   	efx_sram_buf_tbl_clear;
>   	efx_sram_buf_tbl_set;
>   
> +	efx_table_describe;
> +	efx_table_is_supported;
>   	efx_table_list;
> +	efx_table_supported_num_get;
>   
>   	efx_tunnel_config_clear;
>   	efx_tunnel_config_udp_add;


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 10/34] net/sfc: attach to HW table API
  2023-06-04 23:24   ` [PATCH v3 10/34] net/sfc: attach to HW table API Ivan Malov
@ 2023-06-07 12:08     ` Andrew Rybchenko
  0 siblings, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 12:08 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

On 6/5/23 02:24, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> The patch adds APIs to initialise, manipulate and finalise
> HW tables API-specific context in NIC control structure.
> The context itself will be used to store HW tables-related info,
> like table descriptors and field descriptors.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

[snip]

> +int
> +sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
> +{
> +	size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
> +				    efx_table_supported_num_get());
> +	struct rte_hash *cache = NULL;
> +	const struct rte_hash_parameters hash_params = {
> +		.name       = "meta_hash_table",
> +		.hash_func  = rte_jhash,
> +		.entries    = cache_size,
> +		.socket_id  = rte_socket_id(),
> +		.key_len    = sizeof(efx_table_id_t),
> +	};
> +
> +	cache = rte_hash_create(&hash_params);
> +	if (!cache)

Compare vs NULL as DPDK coding style says

> +		return -ENOMEM;
> +
> +	*ref_cache = cache;
> +
> +	return 0;
> +}


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v3 00/34] net/sfc: support HW conntrack assistance
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                     ` (33 preceding siblings ...)
  2023-06-04 23:25   ` [PATCH v3 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
@ 2023-06-07 12:19   ` Andrew Rybchenko
  34 siblings, 0 replies; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-07 12:19 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Ferruh Yigit

On 6/5/23 02:24, Ivan Malov wrote:
> On EF100 hardware, match-action engine (MAE) can be equipped
> with an assistance table for connection tracking (CT). In it,
> an entry key is a set of exact match fields: an EtherType, a
> pair of IP addresses, a L4 protocol ID and a pair of L4 port
> numbers. An entry response can provide matching packets with
> a mark value and additional data to be plumbed to NAT action.
> In addition, an update to mark-and-sweep counter can be done.
> 
> This table was designed with larger capacity in mind,
> so moving the above match criteria out of an action
> rule (AR) specification to a CT entry increases the
> likelihood of reusing AR entries and improves the
> total flow engine capacity. Make use of that.
> 
> Changes in v2:
> * Found and fixed my own mistake in [15/34]
> * Fixed [16/34] as per 0-day robot report
> * Added missing release notes to [27/34]
> * Added missing release notes to [30/34]
> 
> Changes in v3:
> * Fixed release notes in [27/34]
> * Rebased on dpdk to fix CI
> 
> Denis Pryazhennikov (11):
>    common/sfc_efx/base: update MCDI headers
>    common/sfc_efx/base: detect MCDI Table Access API support
>    common/sfc_efx/base: add API to list HW tables
>    common/sfc_efx/base: add macro to get indexed QWORD field
>    common/sfc_efx/base: add API to get HW table desc
>    common/sfc_efx/base: add API to insert data to HW table
>    common/sfc_efx/base: add API to delete entry from HW table
>    net/sfc: add MCDI wrappers for BCAM tables
>    net/sfc: add functions to manipulate MCDI table fields
>    net/sfc: attach to HW table API
>    net/sfc: add API to manage HW Conntrack table
> 
> Ivan Malov (23):
>    net/sfc: make entry pointer optional in MAE resource helpers
>    net/sfc: turn flow create/destroy methods into lock wrappers
>    net/sfc: let driver-internal flows use VF representor action
>    net/sfc: extend generic flow API to allow for internal flows
>    net/sfc: switch driver-internal flows to use generic methods
>    net/sfc: move MAE flow parsing method to MAE-specific source
>    net/sfc: move MAE counter stream start to action set handler
>    net/sfc: prepare MAE outer rules for action rule indirection
>    net/sfc: turn MAE flow action rules into shareable resources
>    common/sfc_efx/base: provide an API to clone MAE match specs
>    common/sfc_efx/base: add API to read back MAE match criteria
>    common/sfc_efx/base: match on conntrack mark in action rules
>    common/sfc_efx/base: add API to request MAE conntrack lookup
>    net/sfc: make use of conntrack assistance for transfer flows
>    common/sfc_efx/base: support NAT edits in MAE
>    net/sfc: add support for IPv4 NAT offload to MAE backend
>    net/sfc: rename SW structures used by transfer flow counters
>    net/sfc: rework MAE action rule counter representation in SW
>    net/sfc: support indirect count action in transfer flows
>    common/sfc_efx/base: rework MAE counter provisioning helpers
>    net/sfc: indicate MAE counter type in use for transfer flows
>    common/sfc_efx/base: support conntrack assistance counters
>    net/sfc: use conntrack assistance counters in transfer flows
> 
>   doc/guides/nics/features/sfc.ini            |    4 +
>   doc/guides/nics/sfc_efx.rst                 |   10 +
>   doc/guides/rel_notes/release_23_07.rst      |   18 +
>   drivers/common/sfc_efx/base/efx.h           |  198 +-
>   drivers/common/sfc_efx/base/efx_impl.h      |    5 +-
>   drivers/common/sfc_efx/base/efx_mae.c       |  383 ++-
>   drivers/common/sfc_efx/base/efx_mcdi.h      |    4 +
>   drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
>   drivers/common/sfc_efx/base/efx_table.c     |  506 ++++
>   drivers/common/sfc_efx/base/hunt_nic.c      |    2 +
>   drivers/common/sfc_efx/base/medford2_nic.c  |    2 +
>   drivers/common/sfc_efx/base/medford_nic.c   |    2 +
>   drivers/common/sfc_efx/base/meson.build     |    1 +
>   drivers/common/sfc_efx/base/rhead_nic.c     |    9 +
>   drivers/common/sfc_efx/base/siena_nic.c     |    2 +
>   drivers/common/sfc_efx/version.map          |   14 +
>   drivers/net/sfc/meson.build                 |    6 +-
>   drivers/net/sfc/sfc.c                       |   27 +-
>   drivers/net/sfc/sfc.h                       |    3 +
>   drivers/net/sfc/sfc_flow.c                  |  246 +-
>   drivers/net/sfc/sfc_flow.h                  |   45 +-
>   drivers/net/sfc/sfc_mae.c                   | 1899 ++++++++++----
>   drivers/net/sfc/sfc_mae.h                   |  131 +-
>   drivers/net/sfc/sfc_mae_counter.c           |  146 +-
>   drivers/net/sfc/sfc_mae_counter.h           |   16 +-
>   drivers/net/sfc/sfc_mae_ct.c                |  201 ++
>   drivers/net/sfc/sfc_mae_ct.h                |   68 +
>   drivers/net/sfc/sfc_repr.c                  |   20 +-
>   drivers/net/sfc/sfc_repr_proxy.c            |   53 +-
>   drivers/net/sfc/sfc_repr_proxy.h            |    2 +-
>   drivers/net/sfc/sfc_repr_proxy_api.h        |    3 +
>   drivers/net/sfc/sfc_switch.c                |    7 +-
>   drivers/net/sfc/sfc_switch.h                |   10 +
>   drivers/net/sfc/sfc_tbl_meta.c              |   71 +
>   drivers/net/sfc/sfc_tbl_meta.h              |   37 +
>   drivers/net/sfc/sfc_tbl_meta_cache.c        |  253 ++
>   drivers/net/sfc/sfc_tbl_meta_cache.h        |   25 +
>   drivers/net/sfc/sfc_tbls.c                  |  200 ++
>   drivers/net/sfc/sfc_tbls.h                  |  285 +++
>   39 files changed, 6601 insertions(+), 870 deletions(-)
>   create mode 100644 drivers/common/sfc_efx/base/efx_table.c
>   create mode 100644 drivers/net/sfc/sfc_mae_ct.c
>   create mode 100644 drivers/net/sfc/sfc_mae_ct.h
>   create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
>   create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
>   create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
>   create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h
>   create mode 100644 drivers/net/sfc/sfc_tbls.c
>   create mode 100644 drivers/net/sfc/sfc_tbls.h
> 

With minor notes on some patches fixed

Series-acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>

^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 00/34] net/sfc: support HW conntrack assistance
  2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
                   ` (35 preceding siblings ...)
  2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
@ 2023-06-07 13:02 ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
                     ` (36 more replies)
  36 siblings, 37 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

Changes in v2:
* Found and fixed my own mistake in [15/34]
* Fixed [16/34] as per 0-day robot report
* Added missing release notes to [27/34]
* Added missing release notes to [30/34]

Changes in v3:
* Fixed release notes in [27/34]
* Rebased on dpdk to fix CI

Changes in v4:
* Applied review notes in [05/34], [08/34], [09/34] and [10/34].

Denis Pryazhennikov (11):
  common/sfc_efx/base: update MCDI headers
  common/sfc_efx/base: detect MCDI Table Access API support
  common/sfc_efx/base: add API to list HW tables
  common/sfc_efx/base: add macro to get indexed QWORD field
  common/sfc_efx/base: add API to get HW table desc
  common/sfc_efx/base: add API to insert data to HW table
  common/sfc_efx/base: add API to delete entry from HW table
  net/sfc: add MCDI wrappers for BCAM tables
  net/sfc: add functions to manipulate MCDI table fields
  net/sfc: attach to HW table API
  net/sfc: add API to manage HW Conntrack table

Ivan Malov (23):
  net/sfc: make entry pointer optional in MAE resource helpers
  net/sfc: turn flow create/destroy methods into lock wrappers
  net/sfc: let driver-internal flows use VF representor action
  net/sfc: extend generic flow API to allow for internal flows
  net/sfc: switch driver-internal flows to use generic methods
  net/sfc: move MAE flow parsing method to MAE-specific source
  net/sfc: move MAE counter stream start to action set handler
  net/sfc: prepare MAE outer rules for action rule indirection
  net/sfc: turn MAE flow action rules into shareable resources
  common/sfc_efx/base: provide an API to clone MAE match specs
  common/sfc_efx/base: add API to read back MAE match criteria
  common/sfc_efx/base: match on conntrack mark in action rules
  common/sfc_efx/base: add API to request MAE conntrack lookup
  net/sfc: make use of conntrack assistance for transfer flows
  common/sfc_efx/base: support NAT edits in MAE
  net/sfc: add support for IPv4 NAT offload to MAE backend
  net/sfc: rename SW structures used by transfer flow counters
  net/sfc: rework MAE action rule counter representation in SW
  net/sfc: support indirect count action in transfer flows
  common/sfc_efx/base: rework MAE counter provisioning helpers
  net/sfc: indicate MAE counter type in use for transfer flows
  common/sfc_efx/base: support conntrack assistance counters
  net/sfc: use conntrack assistance counters in transfer flows

 doc/guides/nics/features/sfc.ini            |    4 +
 doc/guides/nics/sfc_efx.rst                 |   10 +
 doc/guides/rel_notes/release_23_07.rst      |   18 +
 drivers/common/sfc_efx/base/efx.h           |  198 +-
 drivers/common/sfc_efx/base/efx_impl.h      |    5 +-
 drivers/common/sfc_efx/base/efx_mae.c       |  383 ++-
 drivers/common/sfc_efx/base/efx_mcdi.h      |    4 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 drivers/common/sfc_efx/base/efx_table.c     |  506 ++++
 drivers/common/sfc_efx/base/hunt_nic.c      |    2 +
 drivers/common/sfc_efx/base/medford2_nic.c  |    2 +
 drivers/common/sfc_efx/base/medford_nic.c   |    2 +
 drivers/common/sfc_efx/base/meson.build     |    1 +
 drivers/common/sfc_efx/base/rhead_nic.c     |    9 +
 drivers/common/sfc_efx/base/siena_nic.c     |    2 +
 drivers/common/sfc_efx/version.map          |   14 +
 drivers/net/sfc/meson.build                 |    6 +-
 drivers/net/sfc/sfc.c                       |   27 +-
 drivers/net/sfc/sfc.h                       |    3 +
 drivers/net/sfc/sfc_flow.c                  |  246 +-
 drivers/net/sfc/sfc_flow.h                  |   45 +-
 drivers/net/sfc/sfc_mae.c                   | 1899 ++++++++++----
 drivers/net/sfc/sfc_mae.h                   |  131 +-
 drivers/net/sfc/sfc_mae_counter.c           |  146 +-
 drivers/net/sfc/sfc_mae_counter.h           |   16 +-
 drivers/net/sfc/sfc_mae_ct.c                |  201 ++
 drivers/net/sfc/sfc_mae_ct.h                |   68 +
 drivers/net/sfc/sfc_repr.c                  |   20 +-
 drivers/net/sfc/sfc_repr_proxy.c            |   53 +-
 drivers/net/sfc/sfc_repr_proxy.h            |    2 +-
 drivers/net/sfc/sfc_repr_proxy_api.h        |    3 +
 drivers/net/sfc/sfc_switch.c                |    7 +-
 drivers/net/sfc/sfc_switch.h                |   10 +
 drivers/net/sfc/sfc_tbl_meta.c              |   71 +
 drivers/net/sfc/sfc_tbl_meta.h              |   37 +
 drivers/net/sfc/sfc_tbl_meta_cache.c        |  253 ++
 drivers/net/sfc/sfc_tbl_meta_cache.h        |   25 +
 drivers/net/sfc/sfc_tbls.c                  |  207 ++
 drivers/net/sfc/sfc_tbls.h                  |  286 +++
 39 files changed, 6609 insertions(+), 870 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h
 create mode 100644 drivers/net/sfc/sfc_tbls.c
 create mode 100644 drivers/net/sfc/sfc_tbls.h

-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-21 16:52     ` Ferruh Yigit
  2023-06-07 13:02   ` [PATCH v4 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
                     ` (35 subsequent siblings)
  36 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Pickup new FW interface definitions.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2557 ++++++++++++++++++-
 1 file changed, 2467 insertions(+), 90 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index d1d8093601..76bd1bf4d9 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -5,7 +5,10 @@
  */
 
 /*
- * This file is automatically generated. DO NOT EDIT IT.
+ * This file is automatically generated, but contains manual changes.
+ * - replaced the autogenerated license header with BSD-3-Clause;
+ * - used tabs for the indentation of MC_CMD_ERR_*.
+ *
  * To make changes, edit the .yml files in smartnic_registry under doc/mcdi/ and
  * rebuild this file with "make mcdi_headers_v5".
  */
@@ -81,19 +84,19 @@
  *               |                      \------- Error
  *               \------------------------------ Resync (always set)
  *
- * The client writes it's request into MC shared memory, and rings the
- * doorbell. Each request is completed by either by the MC writting
- * back into shared memory, or by writting out an event.
+ * The client writes its request into MC shared memory, and rings the
+ * doorbell. Each request is completed either by the MC writing
+ * back into shared memory, or by writing out an event.
  *
  * All MCDI commands support completion by shared memory response. Each
  * request may also contain additional data (accounted for by HEADER.LEN),
- * and some response's may also contain additional data (again, accounted
+ * and some responses may also contain additional data (again, accounted
  * for by HEADER.LEN).
  *
  * Some MCDI commands support completion by event, in which any associated
  * response data is included in the event.
  *
- * The protocol requires one response to be delivered for every request, a
+ * The protocol requires one response to be delivered for every request; a
  * request should not be sent unless the response for the previous request
  * has been received (either by polling shared memory, or by receiving
  * an event).
@@ -339,7 +342,7 @@
 /* enum: The requesting client is not a function */
 #define	MC_CMD_ERR_CLIENT_NOT_FN 0x100c
 /* enum: The requested operation might require the command to be passed between
- * MCs, and thetransport doesn't support that. Should only ever been seen over
+ * MCs, and the transport doesn't support that. Should only ever been seen over
  * the UART.
  */
 #define	MC_CMD_ERR_TRANSPORT_NOPROXY 0x100d
@@ -376,7 +379,7 @@
  * sub-variant switching.
  */
 #define	MC_CMD_ERR_FILTERS_PRESENT 0x1014
-/* enum: The clock whose frequency you've attempted to set set doesn't exist on
+/* enum: The clock whose frequency you've attempted to set doesn't exist on
  * this NIC
  */
 #define	MC_CMD_ERR_NO_CLOCK 0x1015
@@ -658,12 +661,624 @@
  * be allocated by different counter blocks, so e.g. AR counter 42 is different
  * from CT counter 42. Generation counts are also type-specific. This value is
  * also present in the header of streaming counter packets, in the IDENTIFIER
- * field (see packetiser packet format definitions).
+ * field (see packetiser packet format definitions). Also note that LACP
+ * counter IDs are not allocated individually, instead the counter IDs are
+ * directly tied to the LACP balance table indices. These in turn are allocated
+ * in large contiguous blocks as a LAG config. Calling MAE_COUNTER_ALLOC/FREE
+ * with an LACP counter type will return EPERM.
  */
 /* enum: Action Rule counters - can be referenced in AR response. */
 #define	MAE_COUNTER_TYPE_AR 0x0
 /* enum: Conntrack counters - can be referenced in CT response. */
 #define	MAE_COUNTER_TYPE_CT 0x1
+/* enum: Outer Rule counters - can be referenced in OR response. */
+#define	MAE_COUNTER_TYPE_OR 0x2
+/* enum: LACP counters - linked to LACP balance table entries. */
+#define	MAE_COUNTER_TYPE_LACP 0x3
+
+/* MAE_COUNTER_ID enum: ID of allocated counter or counter list. */
+/* enum: A counter ID that is guaranteed never to represent a real counter or
+ * counter list.
+ */
+#define	MAE_COUNTER_ID_NULL 0xffffffff
+
+/* TABLE_ID enum: Unique IDs for tables. The 32-bit ID values have been
+ * structured with bits [31:24] reserved (0), [23:16] indicating which major
+ * block the tables belongs to (0=VNIC TX, none currently; 1=MAE; 2=VNIC RX),
+ * [15:8] a unique ID within the block, and [7:0] reserved for future
+ * variations of the same table. (All of the tables currently defined within
+ * the streaming engines are listed here, but this does not imply that they are
+ * all supported - MC_CMD_TABLE_LIST returns the list of actually supported
+ * tables.) The DPU offload engines' enumerators follow a deliberate pattern:
+ * 0x01010000 + is_dpu_net * 0x10000 + is_wr_or_tx * 0x8000 + is_lite_pipe *
+ * 0x1000 + oe_engine_type * 0x100 + oe_instance_within_pipe * 0x10
+ */
+/* enum: Outer_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_TABLE 0x10000
+/* enum: Outer_Rule_No_CT_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_OUTER_RULE_NO_CT_TABLE 0x10100
+/* enum: Mgmt_Filter_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGMT_FILTER_TABLE 0x10200
+/* enum: Conntrack_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_CONNTRACK_TABLE 0x10300
+/* enum: Action_Rule_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ACTION_RULE_TABLE 0x10400
+/* enum: Mgroup_Default_Action_Set_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_MGROUP_DEFAULT_ACTION_SET_TABLE 0x10500
+/* enum: Encap_Hdr_Part1_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART1_TABLE 0x10600
+/* enum: Encap_Hdr_Part2_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_ENCAP_HDR_PART2_TABLE 0x10700
+/* enum: Replace_Src_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_SRC_MAC_TABLE 0x10800
+/* enum: Replace_Dst_MAC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_REPLACE_DST_MAC_TABLE 0x10900
+/* enum: Dst_Mport_VC_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_VC_TABLE 0x10a00
+/* enum: LACP_LAG_Config_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_LAG_CONFIG_TABLE 0x10b00
+/* enum: LACP_Balance_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_LACP_BALANCE_TABLE 0x10c00
+/* enum: Dst_Mport_Host_Chan_Table in the MAE - refer to SF-123102-TC. */
+#define	TABLE_ID_DST_MPORT_HOST_CHAN_TABLE 0x10d00
+/* enum: VNIC_Rx_Encap_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_VNIC_RX_ENCAP_TABLE 0x20000
+/* enum: Steering_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_STEERING_TABLE 0x20100
+/* enum: RSS_Context_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_RSS_CONTEXT_TABLE 0x20200
+/* enum: Indirection_Table in VNIC Rx - refer to SF-123102-TC. */
+#define	TABLE_ID_INDIRECTION_TABLE 0x20300
+/* enum: DPU.host read pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC0_OE_PROFILE 0x1010000
+/* enum: DPU.host read pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_RD_CRC1_OE_PROFILE 0x1010010
+/* enum: DPU.host write pipe first CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC0_OE_PROFILE 0x1018000
+/* enum: DPU.host write pipe second CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_HOST_WR_CRC1_OE_PROFILE 0x1018010
+/* enum: DPU.net 'full' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CRC0_OE_PROFILE 0x1020000
+/* enum: DPU.net 'full' receive pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM0_OE_PROFILE 0x1020100
+/* enum: DPU.net 'full' receive pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_CSUM1_OE_PROFILE 0x1020110
+/* enum: DPU.net 'full' receive pipe AES-GCM offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RX_AES_GCM0_OE_PROFILE 0x1020200
+/* enum: DPU.net 'lite' receive pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CRC0_OE_PROFILE 0x1021000
+/* enum: DPU.net 'lite' receive pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_RXLITE_CSUM0_OE_PROFILE 0x1021100
+/* enum: DPU.net 'full' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CRC0_OE_PROFILE 0x1028000
+/* enum: DPU.net 'full' transmit pipe first checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM0_OE_PROFILE 0x1028100
+/* enum: DPU.net 'full' transmit pipe second checksum offload engine profiles -
+ * refer to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_CSUM1_OE_PROFILE 0x1028110
+/* enum: DPU.net 'full' transmit pipe AES-GCM offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TX_AES_GCM0_OE_PROFILE 0x1028200
+/* enum: DPU.net 'lite' transmit pipe CRC offload engine profiles - refer to
+ * XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CRC0_OE_PROFILE 0x1029000
+/* enum: DPU.net 'lite' transmit pipe checksum offload engine profiles - refer
+ * to XN-200147-AN.
+ */
+#define	TABLE_ID_DPU_NET_TXLITE_CSUM0_OE_PROFILE 0x1029100
+
+/* TABLE_COMPRESSED_VLAN enum: Compressed VLAN TPID as used by some field
+ * types; can be calculated by (((ether_type_msb >> 2) & 0x4) ^ 0x4) |
+ * (ether_type_msb & 0x3);
+ */
+#define	TABLE_COMPRESSED_VLAN_TPID_8100 0x5 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_88A8 0x4 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9100 0x1 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9200 0x2 /* enum */
+#define	TABLE_COMPRESSED_VLAN_TPID_9300 0x3 /* enum */
+
+/* TABLE_NAT_DIR enum: NAT direction. */
+#define	TABLE_NAT_DIR_SOURCE 0x0 /* enum */
+#define	TABLE_NAT_DIR_DEST 0x1 /* enum */
+
+/* TABLE_RSS_KEY_MODE enum: Defines how the value for Toeplitz hashing for RSS
+ * is constructed as a concatenation (indicated here by "++") of packet header
+ * fields.
+ */
+/* enum: IP src addr ++ IP dst addr */
+#define	TABLE_RSS_KEY_MODE_SA_DA 0x0
+/* enum: IP src addr ++ IP dst addr ++ TCP/UDP src port ++ TCP/UDP dst port */
+#define	TABLE_RSS_KEY_MODE_SA_DA_SP_DP 0x1
+/* enum: IP src addr */
+#define	TABLE_RSS_KEY_MODE_SA 0x2
+/* enum: IP dst addr */
+#define	TABLE_RSS_KEY_MODE_DA 0x3
+/* enum: IP src addr ++ TCP/UDP src port */
+#define	TABLE_RSS_KEY_MODE_SA_SP 0x4
+/* enum: IP dest addr ++ TCP dest port */
+#define	TABLE_RSS_KEY_MODE_DA_DP 0x5
+/* enum: Nothing (produces input of 0, resulting in output hash of 0) */
+#define	TABLE_RSS_KEY_MODE_NONE 0x7
+
+/* TABLE_RSS_SPREAD_MODE enum: RSS spreading mode. */
+/* enum: RSS uses Indirection_Table lookup. */
+#define	TABLE_RSS_SPREAD_MODE_INDIRECTION 0x0
+/* enum: RSS uses even spreading calculation. */
+#define	TABLE_RSS_SPREAD_MODE_EVEN 0x1
+
+/* CRC_VARIANT enum: Operation for the DPU CRC engine to perform. */
+/* enum: Calculate a 32-bit CRC. */
+#define	CRC_VARIANT_CRC32 0x1
+/* enum: Calculate a 64-bit CRC. */
+#define	CRC_VARIANT_CRC64 0x2
+
+/* DPU_CSUM_OP enum: Operation for the DPU checksum engine to perform. */
+/* enum: Calculate the checksum for a TCP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_TCP 0x0
+/* enum: Calculate the checksum for a UDP payload, output result on OPR bus. */
+#define	DPU_CSUM_OP_CALC_UDP 0x1
+/* enum: Calculate the checksum for a TCP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_TCP 0x2
+/* enum: Calculate the checksum for a UDP payload, output match/not match value
+ * on OPR bus.
+ */
+#define	DPU_CSUM_OP_VALIDATE_UDP 0x3
+
+/* GCM_OP_CODE enum: Operation for the DPU AES-GCM engine to perform. */
+/* enum: Encrypt/decrypt a stream of data. */
+#define	GCM_OP_CODE_BULK_CRYPT 0x0
+/* enum: Calculate the authentication tag for a stream of data. */
+#define	GCM_OP_CODE_BULK_AUTH 0x1
+/* enum: Encrypt/decrypt an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_CRYPT 0x2
+/* enum: Calculate the authentication tag of an IPsec packet. */
+#define	GCM_OP_CODE_IPSEC_AUTH 0x3
+
+/* AES_KEY_LEN enum: Key size for AES crypto operations */
+/* enum: 128 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_128 0x0
+/* enum: 256 bit key size. */
+#define	AES_KEY_LEN_AES_KEY_256 0x1
+
+/* TABLE_FIELD_ID enum: Unique IDs for fields. Related concepts have been
+ * loosely grouped together into blocks with gaps for expansion, but the values
+ * are arbitrary. Field IDs are not specific to particular tables, and in some
+ * cases this sharing means that they are not used with the exact names of the
+ * corresponding table definitions in SF-123102-TC; however, the mapping should
+ * still be clear. The intent is that a list of fields, with their associated
+ * bit widths and semantics version code, unambiguously defines the semantics
+ * of the fields in a key or response. (Again, this list includes all of the
+ * fields currently defined within the streaming engines, but only a subset may
+ * actually be used by the supported list of tables.)
+ */
+/* enum: May appear multiple times within a key or response, and indicates that
+ * the field is unused and should be set to 0 (or masked out if permitted by
+ * the MASK_VALUE for this field).
+ */
+#define	TABLE_FIELD_ID_UNUSED 0x0
+/* enum: Source m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_SRC_MPORT 0x1
+/* enum: Destination m-port (a full m-port label). */
+#define	TABLE_FIELD_ID_DST_MPORT 0x2
+/* enum: Source m-group ID. */
+#define	TABLE_FIELD_ID_SRC_MGROUP_ID 0x3
+/* enum: Physical network port ID (or m-port ID; same thing, for physical
+ * network ports).
+ */
+#define	TABLE_FIELD_ID_NETWORK_PORT_ID 0x4
+/* enum: True if packet arrived via network port, false if it arrived via host.
+ */
+#define	TABLE_FIELD_ID_IS_FROM_NETWORK 0x5
+/* enum: Full virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC 0x6
+/* enum: Low bits of virtual channel from capsule header. */
+#define	TABLE_FIELD_ID_CH_VC_LOW 0x7
+/* enum: User mark value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_MARK 0x8
+/* enum: User flag value in metadata and packet prefix. */
+#define	TABLE_FIELD_ID_USER_FLAG 0x9
+/* enum: Counter ID associated with a response. All-bits-1 is a null value to
+ * suppress counting.
+ */
+#define	TABLE_FIELD_ID_COUNTER_ID 0xa
+/* enum: Discriminator which may be set by plugins in some lookup keys; this
+ * allows plugins to make a reinterpretation of packet fields in these keys
+ * without clashing with the normal interpretation.
+ */
+#define	TABLE_FIELD_ID_DISCRIM 0xb
+/* enum: Destination MAC address. The mapping from bytes in a frame to the
+ * 48-bit value for this field is in network order, i.e. a MAC address of
+ * AA:BB:CC:DD:EE:FF becomes a 48-bit value of 0xAABBCCDDEEFF.
+ */
+#define	TABLE_FIELD_ID_DST_MAC 0x14
+/* enum: Source MAC address (see notes for DST_MAC). */
+#define	TABLE_FIELD_ID_SRC_MAC 0x15
+/* enum: Outer VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_OVLAN_TPID_COMPRESSED 0x16
+/* enum: Full outer VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_OVLAN 0x17
+/* enum: Outer VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_OVLAN_VID 0x18
+/* enum: Inner VLAN tag TPID, compressed to an enumeration. */
+#define	TABLE_FIELD_ID_IVLAN_TPID_COMPRESSED 0x19
+/* enum: Full inner VLAN tag TCI (16 bits). */
+#define	TABLE_FIELD_ID_IVLAN 0x1a
+/* enum: Inner VLAN ID (least significant 12 bits of full 16-bit TCI) only. */
+#define	TABLE_FIELD_ID_IVLAN_VID 0x1b
+/* enum: Ethertype. */
+#define	TABLE_FIELD_ID_ETHER_TYPE 0x1c
+/* enum: Source IP address, either IPv4 or IPv6. The mapping from bytes in a
+ * frame to the 128-bit value for this field is in network order, with IPv4
+ * addresses assumed to have 12 bytes of trailing zeroes. i.e. the IPv6 address
+ * [2345::6789:ABCD] is 0x2345000000000000000000006789ABCD; the IPv4 address
+ * 192.168.1.2 is 0xC0A80102000000000000000000000000.
+ */
+#define	TABLE_FIELD_ID_SRC_IP 0x1d
+/* enum: Destination IP address (see notes for SRC_IP). */
+#define	TABLE_FIELD_ID_DST_IP 0x1e
+/* enum: IPv4 Type-of-Service or IPv6 Traffic Class field. */
+#define	TABLE_FIELD_ID_IP_TOS 0x1f
+/* enum: IP Protocol. */
+#define	TABLE_FIELD_ID_IP_PROTO 0x20
+/* enum: Layer 4 source port. */
+#define	TABLE_FIELD_ID_SRC_PORT 0x21
+/* enum: Layer 4 destination port. */
+#define	TABLE_FIELD_ID_DST_PORT 0x22
+/* enum: TCP flags. */
+#define	TABLE_FIELD_ID_TCP_FLAGS 0x23
+/* enum: Virtual Network Identifier (VXLAN) or Virtual Session ID (NVGRE). */
+#define	TABLE_FIELD_ID_VNI 0x24
+/* enum: True if packet has any tunnel encapsulation header. */
+#define	TABLE_FIELD_ID_HAS_ENCAP 0x32
+/* enum: True if encap header has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_OVLAN 0x33
+/* enum: True if encap header has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_ENC_IVLAN 0x34
+/* enum: True if encap header is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP 0x35
+/* enum: True if encap header is specifically IPv4. */
+#define	TABLE_FIELD_ID_HAS_ENC_IP4 0x36
+/* enum: True if encap header is UDP. */
+#define	TABLE_FIELD_ID_HAS_ENC_UDP 0x37
+/* enum: True if only/inner frame has an outer VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_OVLAN 0x38
+/* enum: True if only/inner frame has an inner VLAN tag. */
+#define	TABLE_FIELD_ID_HAS_IVLAN 0x39
+/* enum: True if only/inner frame is some sort of IP. */
+#define	TABLE_FIELD_ID_HAS_IP 0x3a
+/* enum: True if only/inner frame has a recognised L4 IP protocol (TCP or UDP).
+ */
+#define	TABLE_FIELD_ID_HAS_L4 0x3b
+/* enum: True if only/inner frame is an IP fragment. */
+#define	TABLE_FIELD_ID_IP_FRAG 0x3c
+/* enum: True if only/inner frame is the first IP fragment (fragment offset 0).
+ */
+#define	TABLE_FIELD_ID_IP_FIRST_FRAG 0x3d
+/* enum: True if only/inner frame has an IP Time-To-Live of <= 1. (Note: the
+ * implementation calls this "ip_ttl_is_one" but does in fact match packets
+ * with TTL=0 - which we shouldn't be seeing! - as well.)
+ */
+#define	TABLE_FIELD_ID_IP_TTL_LE_ONE 0x3e
+/* enum: True if only/inner frame has any of TCP SYN, FIN or RST flags set. */
+#define	TABLE_FIELD_ID_TCP_INTERESTING_FLAGS 0x3f
+/* enum: Plugin channel selection. */
+#define	TABLE_FIELD_ID_RDP_PL_CHAN 0x50
+/* enum: Enable update of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL_EN 0x51
+/* enum: New value of CH_ROUTE_RDP_C_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_C_PL 0x52
+/* enum: Enable update of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL_EN 0x53
+/* enum: New value of CH_ROUTE_RDP_D_PL route bit. */
+#define	TABLE_FIELD_ID_RDP_D_PL 0x54
+/* enum: Enable update of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN_EN 0x55
+/* enum: New value of CH_ROUTE_RDP_OUT_HOST_CHAN route bit. */
+#define	TABLE_FIELD_ID_RDP_OUT_HOST_CHAN 0x56
+/* enum: Recirculation ID for lookup sequences with two action rule lookups. */
+#define	TABLE_FIELD_ID_RECIRC_ID 0x64
+/* enum: Domain ID passed to conntrack and action rule lookups. */
+#define	TABLE_FIELD_ID_DOMAIN 0x65
+/* enum: Construction mode for encap_tunnel_id - see MAE_CT_VNI_MODE enum. */
+#define	TABLE_FIELD_ID_CT_VNI_MODE 0x66
+/* enum: True to inhibit conntrack lookup if TCP SYN, FIN or RST flag is set.
+ */
+#define	TABLE_FIELD_ID_CT_TCP_FLAGS_INHIBIT 0x67
+/* enum: True to do conntrack lookups for IPv4 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_TCP 0x68
+/* enum: True to do conntrack lookups for IPv4 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP4_UDP 0x69
+/* enum: True to do conntrack lookups for IPv6 TCP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_TCP 0x6a
+/* enum: True to do conntrack lookups for IPv6 UDP packets. */
+#define	TABLE_FIELD_ID_DO_CT_IP6_UDP 0x6b
+/* enum: Outer rule identifier. */
+#define	TABLE_FIELD_ID_OUTER_RULE_ID 0x6c
+/* enum: Encapsulation type - see MAE_MCDI_ENCAP_TYPE enum. */
+#define	TABLE_FIELD_ID_ENCAP_TYPE 0x6d
+/* enum: Encap tunnel ID for conntrack lookups from VNI, VLAN tag(s), or 0,
+ * depending on CT_VNI_MODE.
+ */
+#define	TABLE_FIELD_ID_ENCAP_TUNNEL_ID 0x78
+/* enum: A conntrack entry identifier, passed to plugins. */
+#define	TABLE_FIELD_ID_CT_ENTRY_ID 0x79
+/* enum: Either source or destination NAT replacement port. */
+#define	TABLE_FIELD_ID_NAT_PORT 0x7a
+/* enum: Either source or destination NAT replacement IPv4 address. Note that
+ * this is specifically an IPv4 address (IPv6 is not supported for NAT), with
+ * byte mapped to a 32-bit value in network order, i.e. the IPv4 address
+ * 192.168.1.2 is the value 0xC0A80102.
+ */
+#define	TABLE_FIELD_ID_NAT_IP 0x7b
+/* enum: NAT direction: 0=>source, 1=>destination. */
+#define	TABLE_FIELD_ID_NAT_DIR 0x7c
+/* enum: Conntrack mark value, passed to action rule lookup. Note that this is
+ * not related to the "user mark" in the metadata / packet prefix.
+ */
+#define	TABLE_FIELD_ID_CT_MARK 0x7d
+/* enum: Private flags for conntrack, passed to action rule lookup. */
+#define	TABLE_FIELD_ID_CT_PRIV_FLAGS 0x7e
+/* enum: True if the conntrack lookup resulted in a hit. */
+#define	TABLE_FIELD_ID_CT_HIT 0x7f
+/* enum: True to suppress delivery when source and destination m-ports match.
+ */
+#define	TABLE_FIELD_ID_SUPPRESS_SELF_DELIVERY 0x8c
+/* enum: True to perform tunnel decapsulation. */
+#define	TABLE_FIELD_ID_DO_DECAP 0x8d
+/* enum: True to copy outer frame DSCP to inner on decap. */
+#define	TABLE_FIELD_ID_DECAP_DSCP_COPY 0x8e
+/* enum: True to map outer frame ECN to inner on decap, by RFC 6040 rules. */
+#define	TABLE_FIELD_ID_DECAP_ECN_RFC6040 0x8f
+/* enum: True to replace DSCP field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_DSCP 0x90
+/* enum: True to replace ECN field. */
+#define	TABLE_FIELD_ID_DO_REPLACE_ECN 0x91
+/* enum: True to decrement IP Time-To-Live. */
+#define	TABLE_FIELD_ID_DO_DECR_IP_TTL 0x92
+/* enum: True to replace source MAC address. */
+#define	TABLE_FIELD_ID_DO_SRC_MAC 0x93
+/* enum: True to replace destination MAC address. */
+#define	TABLE_FIELD_ID_DO_DST_MAC 0x94
+/* enum: Number of VLAN tags to pop. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_POP 0x95
+/* enum: Number of VLANs tags to push. Valid values are 0, 1, or 2. */
+#define	TABLE_FIELD_ID_DO_VLAN_PUSH 0x96
+/* enum: True to count this packet. */
+#define	TABLE_FIELD_ID_DO_COUNT 0x97
+/* enum: True to perform tunnel encapsulation. */
+#define	TABLE_FIELD_ID_DO_ENCAP 0x98
+/* enum: True to copy inner frame DSCP to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_DSCP_COPY 0x99
+/* enum: True to copy inner frame ECN to outer on encap. */
+#define	TABLE_FIELD_ID_ENCAP_ECN_COPY 0x9a
+/* enum: True to deliver the packet (otherwise it is dropped). */
+#define	TABLE_FIELD_ID_DO_DELIVER 0x9b
+/* enum: True to set the user flag in the metadata. */
+#define	TABLE_FIELD_ID_DO_FLAG 0x9c
+/* enum: True to update the user mark in the metadata. */
+#define	TABLE_FIELD_ID_DO_MARK 0x9d
+/* enum: True to override the capsule virtual channel for network deliveries.
+ */
+#define	TABLE_FIELD_ID_DO_SET_NET_CHAN 0x9e
+/* enum: True to override the reported source m-port for host deliveries. */
+#define	TABLE_FIELD_ID_DO_SET_SRC_MPORT 0x9f
+/* enum: Encap header ID for DO_ENCAP, indexing Encap_Hdr_Part1/2_Table. */
+#define	TABLE_FIELD_ID_ENCAP_HDR_ID 0xaa
+/* enum: New DSCP value for DO_REPLACE_DSCP. */
+#define	TABLE_FIELD_ID_DSCP_VALUE 0xab
+/* enum: If DO_REPLACE_ECN is set, the new value for the ECN field. If
+ * DO_REPLACE_ECN is not set, ECN_CONTROL[0] and ECN_CONTROL[1] are set to
+ * request remapping of ECT0 and ECT1 ECN codepoints respectively to CE.
+ */
+#define	TABLE_FIELD_ID_ECN_CONTROL 0xac
+/* enum: Source MAC ID for DO_SRC_MAC, indexing Replace_Src_MAC_Table. */
+#define	TABLE_FIELD_ID_SRC_MAC_ID 0xad
+/* enum: Destination MAC ID for DO_DST_MAC, indexing Replace_Dst_MAC_Table. */
+#define	TABLE_FIELD_ID_DST_MAC_ID 0xae
+/* enum: Parameter for either DO_SET_NET_CHAN (only bottom 6 bits used in this
+ * case) or DO_SET_SRC_MPORT.
+ */
+#define	TABLE_FIELD_ID_REPORTED_SRC_MPORT_OR_NET_CHAN 0xaf
+/* enum: 64-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK64 0xb4
+/* enum: 32-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK32 0xb5
+/* enum: 16-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK16 0xb6
+/* enum: 8-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK8 0xb7
+/* enum: 4-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK4 0xb8
+/* enum: 2-byte chunk of added encapsulation header. */
+#define	TABLE_FIELD_ID_CHUNK2 0xb9
+/* enum: Added encapsulation header length in words. */
+#define	TABLE_FIELD_ID_HDR_LEN_W 0xba
+/* enum: Static value for layer 2/3 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L23 0xbb
+/* enum: Static value for layer 4 LACP hash of the encapsulation header. */
+#define	TABLE_FIELD_ID_ENC_LACP_HASH_L4 0xbc
+/* enum: True to use the static ENC_LACP_HASH values for the encap header
+ * instead of the calculated values for the inner frame when delivering a newly
+ * encapsulated packet to a LAG m-port.
+ */
+#define	TABLE_FIELD_ID_USE_ENC_LACP_HASHES 0xbd
+/* enum: True to trigger conntrack from first action rule lookup (AR=>CT=>AR
+ * sequence).
+ */
+#define	TABLE_FIELD_ID_DO_CT 0xc8
+/* enum: True to perform NAT using parameters from conntrack lookup response.
+ */
+#define	TABLE_FIELD_ID_DO_NAT 0xc9
+/* enum: True to trigger recirculated action rule lookup (AR=>AR sequence). */
+#define	TABLE_FIELD_ID_DO_RECIRC 0xca
+/* enum: Next action set payload ID for replay. The null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_PAYLOAD 0xcb
+/* enum: Next action set row ID for replay. The null value is all-1-bits. */
+#define	TABLE_FIELD_ID_NEXT_ACTION_SET_ROW 0xcc
+/* enum: Action set payload ID for additional delivery to management CPU. The
+ * null value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_PAYLOAD 0xcd
+/* enum: Action set row ID for additional delivery to management CPU. The null
+ * value is all-1-bits.
+ */
+#define	TABLE_FIELD_ID_MC_ACTION_SET_ROW 0xce
+/* enum: True to include layer 4 in LACP hash on delivery to a LAG m-port. */
+#define	TABLE_FIELD_ID_LACP_INC_L4 0xdc
+/* enum: True to request that LACP is performed by a plugin. */
+#define	TABLE_FIELD_ID_LACP_PLUGIN 0xdd
+/* enum: LACP_Balance_Table base address divided by 64. */
+#define	TABLE_FIELD_ID_BAL_TBL_BASE_DIV64 0xde
+/* enum: Length of balance table region: 0=>64, 1=>128, 2=>256. */
+#define	TABLE_FIELD_ID_BAL_TBL_LEN_ID 0xdf
+/* enum: LACP LAG ID (i.e. the low 3 bits of LACP LAG mport ID), indexing
+ * LACP_LAG_Config_Table. Refer to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_LACP_LAG_ID 0xe0
+/* enum: Address in LACP_Balance_Table. The balance table is partitioned
+ * between LAGs according to the settings in LACP_LAG_Config_Table and then
+ * indexed by the LACP hash, providing the mapping to destination mports. Refer
+ * to SF-123102-TC.
+ */
+#define	TABLE_FIELD_ID_BAL_TBL_ADDR 0xe1
+/* enum: UDP port to match for UDP-based encapsulations; required to be 0 for
+ * other encapsulation types.
+ */
+#define	TABLE_FIELD_ID_UDP_PORT 0xe6
+/* enum: True to perform RSS based on outer fields rather than inner fields. */
+#define	TABLE_FIELD_ID_RSS_ON_OUTER 0xe7
+/* enum: True to perform steering table lookup on outer fields rather than
+ * inner fields.
+ */
+#define	TABLE_FIELD_ID_STEER_ON_OUTER 0xe8
+/* enum: Destination queue ID for host delivery. */
+#define	TABLE_FIELD_ID_DST_QID 0xf0
+/* enum: True to drop this packet. */
+#define	TABLE_FIELD_ID_DROP 0xf1
+/* enum: True to strip outer VLAN tag from this packet. */
+#define	TABLE_FIELD_ID_VLAN_STRIP 0xf2
+/* enum: True to override the user mark field with the supplied USER_MARK, or
+ * false to bitwise-OR the USER_MARK into it.
+ */
+#define	TABLE_FIELD_ID_MARK_OVERRIDE 0xf3
+/* enum: True to override the user flag field with the supplied USER_FLAG, or
+ * false to bitwise-OR the USER_FLAG into it.
+ */
+#define	TABLE_FIELD_ID_FLAG_OVERRIDE 0xf4
+/* enum: RSS context ID, indexing the RSS_Context_Table. */
+#define	TABLE_FIELD_ID_RSS_CTX_ID 0xfa
+/* enum: True to enable RSS. */
+#define	TABLE_FIELD_ID_RSS_EN 0xfb
+/* enum: Toeplitz hash key. */
+#define	TABLE_FIELD_ID_KEY 0xfc
+/* enum: Key mode for IPv4 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V4_KEY_MODE 0xfd
+/* enum: Key mode for IPv6 TCP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_TCP_V6_KEY_MODE 0xfe
+/* enum: Key mode for IPv4 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V4_KEY_MODE 0xff
+/* enum: Key mode for IPv6 UDP packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_UDP_V6_KEY_MODE 0x100
+/* enum: Key mode for other IPv4 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V4_KEY_MODE 0x101
+/* enum: Key mode for other IPv6 packets - see TABLE_RSS_KEY_MODE enum. */
+#define	TABLE_FIELD_ID_OTHER_V6_KEY_MODE 0x102
+/* enum: Spreading mode - 0=>indirection; 1=>even. */
+#define	TABLE_FIELD_ID_SPREAD_MODE 0x103
+/* enum: For indirection spreading mode, the base address of a region within
+ * the Indirection_Table. For even spreading mode, the number of queues to
+ * spread across (only values 1-255 are valid for this mode).
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_BASE 0x104
+/* enum: For indirection spreading mode, identifies the length of a region
+ * within the Indirection_Table, where length = 32 << len_id. Must be set to 0
+ * for even spreading mode.
+ */
+#define	TABLE_FIELD_ID_INDIR_TBL_LEN_ID 0x105
+/* enum: An offset to be applied to the base destination queue ID. */
+#define	TABLE_FIELD_ID_INDIR_OFFSET 0x106
+/* enum: DPU offload engine profile ID to address. */
+#define	TABLE_FIELD_ID_OE_PROFILE 0x3e8
+/* enum: Width of the CRC to calculate - see CRC_VARIANT enum. */
+#define	TABLE_FIELD_ID_CRC_VARIANT 0x3f2
+/* enum: If set, reflect the bits of each input byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFIN 0x3f3
+/* enum: If set, reflect the bits of each output byte, bit 7 is LSB, bit 0 is
+ * MSB. If clear, bit 7 is MSB, bit 0 is LSB.
+ */
+#define	TABLE_FIELD_ID_CRC_REFOUT 0x3f4
+/* enum: If set, invert every bit of the output value. */
+#define	TABLE_FIELD_ID_CRC_INVOUT 0x3f5
+/* enum: The CRC polynomial to use for checksumming, in normal form. See
+ * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Specification for a
+ * description of normal form.
+ */
+#define	TABLE_FIELD_ID_CRC_POLY 0x3f6
+/* enum: Operation for the checksum engine to perform - see DPU_CSUM_OP enum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OP 0x410
+/* enum: Byte offset of checksum relative to region_start (for VALIDATE_*
+ * operations only).
+ */
+#define	TABLE_FIELD_ID_CSUM_OFFSET 0x411
+/* enum: Indicates there is additional data on OPR bus that needs to be
+ * incorporated into the payload checksum.
+ */
+#define	TABLE_FIELD_ID_CSUM_OPR_ADDITIONAL_DATA 0x412
+/* enum: Log2 data size of additional data on OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_DATA_SIZE_LOG2 0x413
+/* enum: 4 byte offset of where to find the additional data on the OPR bus. */
+#define	TABLE_FIELD_ID_CSUM_OPR_4B_OFF 0x414
+/* enum: Operation type for the AES-GCM core - see GCM_OP_CODE enum. */
+#define	TABLE_FIELD_ID_GCM_OP_CODE 0x41a
+/* enum: Key length - AES_KEY_LEN enum. */
+#define	TABLE_FIELD_ID_GCM_KEY_LEN 0x41b
+/* enum: OPR 4 byte offset for ICV or GHASH output (only in BULK_* mode) or
+ * IPSEC descrypt output.
+ */
+#define	TABLE_FIELD_ID_GCM_OPR_4B_OFFSET 0x41c
+/* enum: If OP_CODE is BULK_*, indicates Emit GHASH (Fragment mode). Else,
+ * indicates IPSEC-ESN mode.
+ */
+#define	TABLE_FIELD_ID_GCM_EMIT_GHASH_ISESN 0x41d
+/* enum: Replay Protection Enable. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_PROTECT_EN 0x41e
+/* enum: IPSEC Encrypt ESP trailer NEXT_HEADER byte. */
+#define	TABLE_FIELD_ID_GCM_NEXT_HDR 0x41f
+/* enum: Replay Window Size. */
+#define	TABLE_FIELD_ID_GCM_REPLAY_WIN_SIZE 0x420
 
 /* MCDI_EVENT structuredef: The structure of an MCDI_EVENT on Siena/EF10/EF100
  * platforms
@@ -819,7 +1434,7 @@
 #define	MCDI_EVENT_AOE_FPGA_LOAD_FAILED 0xe
 /* enum: Notify that invalid flash type detected */
 #define	MCDI_EVENT_AOE_INVALID_FPGA_FLASH_TYPE 0xf
-/* enum: Notify that the attempt to run FPGA Controller firmware timedout */
+/* enum: Notify that the attempt to run FPGA Controller firmware timed out */
 #define	MCDI_EVENT_AOE_FC_RUN_TIMEDOUT 0x10
 /* enum: Failure to probe one or more FPGA boot flash chips */
 #define	MCDI_EVENT_AOE_FPGA_BOOT_FLASH_INVALID 0x11
@@ -837,7 +1452,7 @@
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_INFO_WIDTH 8
 /* enum: FC Assert happened, but the register information is not available */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_SEEN 0x0
-/* enum: The register information for FC Assert is ready for readinng by driver
+/* enum: The register information for FC Assert is ready for reading by driver
  */
 #define	MCDI_EVENT_AOE_ERR_FC_ASSERT_DATA_READY 0x1
 #define	MCDI_EVENT_AOE_ERR_CODE_FPGA_HEADER_VERIFY_FAILED_OFST 0
@@ -946,6 +1561,12 @@
 #define	MCDI_EVENT_MODULECHANGE_SEQ_OFST 0
 #define	MCDI_EVENT_MODULECHANGE_SEQ_LBN 30
 #define	MCDI_EVENT_MODULECHANGE_SEQ_WIDTH 2
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_LBN 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_VI_ID_WIDTH 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_OFST 0
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_LBN 16
+#define	MCDI_EVENT_DESC_PROXY_VIRTQ_ID_WIDTH 16
 #define	MCDI_EVENT_DATA_LBN 0
 #define	MCDI_EVENT_DATA_WIDTH 32
 /* Alias for PTP_DATA. */
@@ -1076,6 +1697,18 @@
  * SF-122927-TC for details.
  */
 #define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_DRIVER_ATTACH 0x26
+/* enum: Notification that the mport journal has changed since it was last read
+ * and updates can be read using the MC_CMD_MAE_MPORT_READ_JOURNAL command. The
+ * firmware may moderate the events so that an event is not sent for every
+ * change to the journal.
+ */
+#define	MCDI_EVENT_CODE_MPORT_JOURNAL_CHANGE 0x27
+/* enum: Notification that a source queue is enabled and attached to its proxy
+ * sink queue. SRC field contains the handle of the affected descriptor proxy
+ * function. DATA field contains the relative source queue number and absolute
+ * VI ID.
+ */
+#define	MCDI_EVENT_CODE_DESC_PROXY_FUNC_QUEUE_START 0x28
 /* enum: Artificial event generated by host and posted via MC for test
  * purposes.
  */
@@ -1842,6 +2475,7 @@
 /* Log destination */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_LEN 4
+/* enum property: bitmask */
 /* enum: UART. */
 #define	MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1
 /* enum: Event queue. */
@@ -1888,6 +2522,9 @@
 
 /* MC_CMD_GET_VERSION_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_OUT_LEN 32
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1910,6 +2547,9 @@
 
 /* MC_CMD_GET_VERSION_EXT_OUT msgresponse */
 #define	MC_CMD_GET_VERSION_EXT_OUT_LEN 48
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -1940,6 +2580,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V2_OUT_LEN 304
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2079,6 +2722,9 @@
  * (depending on which components exist on a particular adapter)
  */
 #define	MC_CMD_GET_VERSION_V3_OUT_LEN 328
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2225,6 +2871,9 @@
  * version information
  */
 #define	MC_CMD_GET_VERSION_V4_OUT_LEN 392
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2387,6 +3036,9 @@
  * and board version information
  */
 #define	MC_CMD_GET_VERSION_V5_OUT_LEN 424
+/* This is normally the UTC build time in seconds since epoch or one of the
+ * special values listed
+ */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */
 /*            MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN 4 */
 /*            Enum values, see field(s): */
@@ -2659,7 +3311,9 @@
 #define	MC_CMD_PTP_IN_CMD_LEN 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_OFST 4
 #define	MC_CMD_PTP_IN_PERIPH_ID_LEN 4
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8
 #define	MC_CMD_PTP_IN_ENABLE_QUEUE_LEN 4
 /* PTP timestamping mode. Not used from Huntington onwards. */
@@ -3030,7 +3684,9 @@
 #define	MC_CMD_PTP_ENABLE_PPS 0x0
 /* enum: Disable */
 #define	MC_CMD_PTP_DISABLE_PPS 0x1
-/* Not used. Events are always sent to function relative queue 0. */
+/* Not used, initialize to 0. Events are always sent to function relative queue
+ * 0.
+ */
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_OFST 8
 #define	MC_CMD_PTP_IN_PPS_ENABLE_QUEUE_ID_LEN 4
 
@@ -3392,6 +4048,87 @@
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_OFST 20
 #define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_RESERVED2_LEN 4
 
+/* MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2 msgresponse */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_LEN 40
+/* Time format required/used by for this NIC. Applies to all PTP MCDI
+ * operations that pass times between the host and firmware. If this operation
+ * is not supported (older firmware) a format of seconds and nanoseconds should
+ * be assumed.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_OFST 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_TIME_FORMAT_LEN 4
+/* enum: Times are in seconds and nanoseconds */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_NANOSECONDS 0x0
+/* enum: Major register has units of 16 second per tick, minor 8 ns per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_16SECONDS_8NANOSECONDS 0x1
+/* enum: Major register has units of seconds, minor 2^-27s per tick */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_27FRACTION 0x2
+/* enum: Major register units are seconds, minor units are quarter nanoseconds
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SECONDS_QTR_NANOSECONDS 0x3
+/* Minimum acceptable value for a corrected synchronization timeset. When
+ * comparing host and NIC clock times, the MC returns a set of samples that
+ * contain the host start and end time, the MC time when the host start was
+ * detected and the time the MC waited between reading the time and detecting
+ * the host end. The corrected sync window is the difference between the host
+ * end and start times minus the time that the MC waited for host end.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_OFST 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_SYNC_WINDOW_MIN_LEN 4
+/* Various PTP capabilities */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_CAPABILITIES_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_LBN 0
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_REPORT_SYNC_STATUS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_LBN 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RX_TSTAMP_OOB_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_LBN 2
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_64BIT_SECONDS_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_OFST 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_LBN 3
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FP44_FREQ_ADJ_WIDTH 1
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_OFST 12
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED0_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_OFST 16
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED1_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_OFST 20
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_RESERVED2_LEN 4
+/* Minimum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of -0.1 ns should be assumed, which is
+ * equivalent to a -10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_OFST 24
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_LBN 192
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_OFST 28
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_LBN 224
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MIN_HI_WIDTH 32
+/* Maximum supported value for the FREQ field in
+ * MC_CMD_PTP/MC_CMD_PTP_IN_ADJUST and
+ * MC_CMD_PTP/MC_CMD_PTP_IN_CLOCK_FREQ_ADJUST message requests. If this message
+ * response is not supported a value of 0.1 ns should be assumed, which is
+ * equivalent to a +10% adjustment.
+ */
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LEN 8
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_OFST 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_LBN 256
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_LO_WIDTH 32
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_OFST 36
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LEN 4
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_LBN 288
+#define	MC_CMD_PTP_OUT_GET_ATTRIBUTES_V2_FREQ_ADJ_MAX_HI_WIDTH 32
+
 /* MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS msgresponse */
 #define	MC_CMD_PTP_OUT_GET_TIMESTAMP_CORRECTIONS_LEN 16
 /* Uncorrected error on PTP transmit timestamps in NIC clock format */
@@ -3443,12 +4180,16 @@
 /***********************************/
 /* MC_CMD_CSR_READ32
  * Read 32bit words from the indirect memory map.
+ *
+ * Note - this command originally belonged to INSECURE category. But access is
+ * required to specific registers for customer diagnostics. The command handler
+ * has additional checks to reject insecure calls.
  */
 #define	MC_CMD_CSR_READ32 0xc
 #define	MC_CMD_CSR_READ32_MSGSET 0xc
 #undef	MC_CMD_0xc_PRIVILEGE_CTG
 
-#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_INSECURE
+#define	MC_CMD_0xc_PRIVILEGE_CTG SRIOV_CTG_ADMIN
 
 /* MC_CMD_CSR_READ32_IN msgrequest */
 #define	MC_CMD_CSR_READ32_IN_LEN 12
@@ -4221,6 +4962,7 @@
 /* Flags associated with this function */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_OFST 4
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FUNC_FLAGS_LEN 4
+/* enum property: bitshift */
 /* enum: Labels the lowest-numbered function visible to the OS */
 #define	MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY 0x0
 /* enum: The function can control the link state of the physical port it is
@@ -4454,6 +5196,54 @@
 /* MC_CMD_GET_PHY_CFG_IN msgrequest */
 #define	MC_CMD_GET_PHY_CFG_IN_LEN 0
 
+/* MC_CMD_GET_PHY_CFG_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_CFG_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_CFG_OUT msgresponse */
 #define	MC_CMD_GET_PHY_CFG_OUT_LEN 72
 /* flags */
@@ -4549,6 +5339,9 @@
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_OFST 8
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_LBN 21
 #define	MC_CMD_PHY_CAP_25G_BASER_FEC_REQUESTED_WIDTH 1
+#define	MC_CMD_PHY_CAP_200000FDX_OFST 8
+#define	MC_CMD_PHY_CAP_200000FDX_LBN 22
+#define	MC_CMD_PHY_CAP_200000FDX_WIDTH 1
 /* ?? */
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12
 #define	MC_CMD_GET_PHY_CFG_OUT_CHANNEL_LEN 4
@@ -4582,6 +5375,7 @@
 #define	MC_CMD_MEDIA_DSFP 0x8
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48
 #define	MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_LEN 4
+/* enum property: bitshift */
 /* enum: Native clause 22 */
 #define	MC_CMD_MMD_CLAUSE22 0x0
 #define	MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */
@@ -4847,6 +5641,54 @@
 /* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */
 #define	MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0
 
+/* MC_CMD_GET_LOOPBACK_MODES_IN_V2 msgrequest */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_LEN 8
+/* Target port to request loopback modes for. Uses MAE_LINK_ENDPOINT_SELECTOR
+ * which identifies a real or virtual network port by MAE port and link end.
+ * See the structure definition for more details
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 40
 /* Supported loopbacks. */
@@ -4860,6 +5702,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 #define	MC_CMD_LOOPBACK_NONE 0x0
 /* enum: Data. */
@@ -4949,6 +5792,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4962,6 +5806,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4975,6 +5820,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -4988,6 +5834,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5006,6 +5853,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_LBN 32
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100M_HI_WIDTH 32
+/* enum property: bitshift */
 /* enum: None. */
 /*               MC_CMD_LOOPBACK_NONE 0x0 */
 /* enum: Data. */
@@ -5095,6 +5943,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_LBN 96
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_1G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5108,6 +5957,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_LBN 160
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_10G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5121,6 +5971,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_LBN 224
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported loopbacks. */
@@ -5134,6 +5985,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_LBN 288
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_40G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 25G loopbacks. */
@@ -5147,6 +5999,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_LBN 352
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_25G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 50 loopbacks. */
@@ -5160,6 +6013,7 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_LBN 416
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_50G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 /* Supported 100G loopbacks. */
@@ -5173,6 +6027,214 @@
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LEN 4
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_LBN 480
 #define	MC_CMD_GET_LOOPBACK_MODES_OUT_V2_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+
+/* MC_CMD_GET_LOOPBACK_MODES_OUT_V3 msgresponse: Supported loopback modes for
+ * newer NICs with 200G support
+ */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_LEN 72
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_OFST 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_LBN 0
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_OFST 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_LBN 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100M_HI_WIDTH 32
+/* enum property: bitshift */
+/* enum: None. */
+/*               MC_CMD_LOOPBACK_NONE 0x0 */
+/* enum: Data. */
+/*               MC_CMD_LOOPBACK_DATA 0x1 */
+/* enum: GMAC. */
+/*               MC_CMD_LOOPBACK_GMAC 0x2 */
+/* enum: XGMII. */
+/*               MC_CMD_LOOPBACK_XGMII 0x3 */
+/* enum: XGXS. */
+/*               MC_CMD_LOOPBACK_XGXS 0x4 */
+/* enum: XAUI. */
+/*               MC_CMD_LOOPBACK_XAUI 0x5 */
+/* enum: GMII. */
+/*               MC_CMD_LOOPBACK_GMII 0x6 */
+/* enum: SGMII. */
+/*               MC_CMD_LOOPBACK_SGMII 0x7 */
+/* enum: XGBR. */
+/*               MC_CMD_LOOPBACK_XGBR 0x8 */
+/* enum: XFI. */
+/*               MC_CMD_LOOPBACK_XFI 0x9 */
+/* enum: XAUI Far. */
+/*               MC_CMD_LOOPBACK_XAUI_FAR 0xa */
+/* enum: GMII Far. */
+/*               MC_CMD_LOOPBACK_GMII_FAR 0xb */
+/* enum: SGMII Far. */
+/*               MC_CMD_LOOPBACK_SGMII_FAR 0xc */
+/* enum: XFI Far. */
+/*               MC_CMD_LOOPBACK_XFI_FAR 0xd */
+/* enum: GPhy. */
+/*               MC_CMD_LOOPBACK_GPHY 0xe */
+/* enum: PhyXS. */
+/*               MC_CMD_LOOPBACK_PHYXS 0xf */
+/* enum: PCS. */
+/*               MC_CMD_LOOPBACK_PCS 0x10 */
+/* enum: PMA-PMD. */
+/*               MC_CMD_LOOPBACK_PMAPMD 0x11 */
+/* enum: Cross-Port. */
+/*               MC_CMD_LOOPBACK_XPORT 0x12 */
+/* enum: XGMII-Wireside. */
+/*               MC_CMD_LOOPBACK_XGMII_WS 0x13 */
+/* enum: XAUI Wireside. */
+/*               MC_CMD_LOOPBACK_XAUI_WS 0x14 */
+/* enum: XAUI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 */
+/* enum: XAUI Wireside near. */
+/*               MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 */
+/* enum: GMII Wireside. */
+/*               MC_CMD_LOOPBACK_GMII_WS 0x17 */
+/* enum: XFI Wireside. */
+/*               MC_CMD_LOOPBACK_XFI_WS 0x18 */
+/* enum: XFI Wireside Far. */
+/*               MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 */
+/* enum: PhyXS Wireside. */
+/*               MC_CMD_LOOPBACK_PHYXS_WS 0x1a */
+/* enum: PMA lanes MAC-Serdes. */
+/*               MC_CMD_LOOPBACK_PMA_INT 0x1b */
+/* enum: KR Serdes Parallel (Encoder). */
+/*               MC_CMD_LOOPBACK_SD_NEAR 0x1c */
+/* enum: KR Serdes Serial. */
+/*               MC_CMD_LOOPBACK_SD_FAR 0x1d */
+/* enum: PMA lanes MAC-Serdes Wireside. */
+/*               MC_CMD_LOOPBACK_PMA_INT_WS 0x1e */
+/* enum: KR Serdes Parallel Wireside (Full PCS). */
+/*               MC_CMD_LOOPBACK_SD_FEP2_WS 0x1f */
+/* enum: KR Serdes Parallel Wireside (Sym Aligner to TX). */
+/*               MC_CMD_LOOPBACK_SD_FEP1_5_WS 0x20 */
+/* enum: KR Serdes Parallel Wireside (Deserializer to Serializer). */
+/*               MC_CMD_LOOPBACK_SD_FEP_WS 0x21 */
+/* enum: KR Serdes Serial Wireside. */
+/*               MC_CMD_LOOPBACK_SD_FES_WS 0x22 */
+/* enum: Near side of AOE Siena side port */
+/*               MC_CMD_LOOPBACK_AOE_INT_NEAR 0x23 */
+/* enum: Medford Wireside datapath loopback */
+/*               MC_CMD_LOOPBACK_DATA_WS 0x24 */
+/* enum: Force link up without setting up any physical loopback (snapper use
+ * only)
+ */
+/*               MC_CMD_LOOPBACK_FORCE_EXT_LINK 0x25 */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_OFST 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_LBN 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_OFST 12
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_LBN 96
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_1G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_OFST 16
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_LBN 128
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_OFST 20
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_LBN 160
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_10G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_OFST 24
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_LBN 192
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_OFST 28
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_LBN 224
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_SUGGESTED_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_OFST 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_LBN 256
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_OFST 36
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_LBN 288
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_40G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 25G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_OFST 40
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_LBN 320
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_OFST 44
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_LBN 352
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_25G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 50 loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_OFST 48
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_LBN 384
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_OFST 52
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_LBN 416
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_50G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 100G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_OFST 56
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_LBN 448
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_OFST 60
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_LBN 480
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_100G_HI_WIDTH 32
+/* enum property: bitshift */
+/*            Enum values, see field(s): */
+/*               100M */
+/* Supported 200G loopbacks. */
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LEN 8
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_OFST 64
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_LBN 512
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_LO_WIDTH 32
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_OFST 68
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LEN 4
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_LBN 544
+#define	MC_CMD_GET_LOOPBACK_MODES_OUT_V3_200G_HI_WIDTH 32
+/* enum property: bitshift */
 /*            Enum values, see field(s): */
 /*               100M */
 
@@ -5222,6 +6284,54 @@
 /* MC_CMD_GET_LINK_IN msgrequest */
 #define	MC_CMD_GET_LINK_IN_LEN 0
 
+/* MC_CMD_GET_LINK_IN_V2 msgrequest */
+#define	MC_CMD_GET_LINK_IN_V2_LEN 8
+/* Target port to request link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_LINK_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_LINK_OUT msgresponse */
 #define	MC_CMD_GET_LINK_OUT_LEN 28
 /* Near-side advertised capabilities. Refer to
@@ -5498,6 +6608,95 @@
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_LBN 7
 #define	MC_CMD_SET_LINK_IN_V2_MODULE_SEQ_IGNORE_WIDTH 1
 
+/* MC_CMD_SET_LINK_IN_V3 msgrequest */
+#define	MC_CMD_SET_LINK_IN_V3_LEN 28
+/* Near-side advertised capabilities. Refer to
+ * MC_CMD_GET_PHY_CFG_OUT/SUPPORTED_CAP for bit definitions.
+ */
+#define	MC_CMD_SET_LINK_IN_V3_CAP_OFST 0
+#define	MC_CMD_SET_LINK_IN_V3_CAP_LEN 4
+/* Flags */
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_FLAGS_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_LOWPOWER_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_LBN 1
+#define	MC_CMD_SET_LINK_IN_V3_POWEROFF_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_LBN 2
+#define	MC_CMD_SET_LINK_IN_V3_TXDIS_WIDTH 1
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_OFST 4
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_LBN 3
+#define	MC_CMD_SET_LINK_IN_V3_LINKDOWN_WIDTH 1
+/* Loopback mode. */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_OFST 8
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_MODE_LEN 4
+/*            Enum values, see field(s): */
+/*               MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */
+/* A loopback speed of "0" is supported, and means (choose any available
+ * speed).
+ */
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_OFST 12
+#define	MC_CMD_SET_LINK_IN_V3_LOOPBACK_SPEED_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_LBN 0
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_NUMBER_WIDTH 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_OFST 16
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_LBN 7
+#define	MC_CMD_SET_LINK_IN_V3_MODULE_SEQ_IGNORE_WIDTH 1
+/* Padding */
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_OFST 17
+#define	MC_CMD_SET_LINK_IN_V3_RESERVED_LEN 3
+/* Target port to set link state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_LINK_END_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LEN 8
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_SET_LINK_IN_V3_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_SET_LINK_OUT msgresponse */
 #define	MC_CMD_SET_LINK_OUT_LEN 0
 
@@ -5719,19 +6918,9 @@
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_OFST 28
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_LBN 4
 #define	MC_CMD_SET_MAC_V3_IN_CFG_FCS_WIDTH 1
-/* Identifies the MAC to update by the specifying the end of a logical MAE
- * link. Setting TARGET to MAE_LINK_ENDPOINT_COMPAT is equivalent to using the
- * previous version of the command (MC_CMD_SET_MAC_EXT). Not all possible
- * combinations of MPORT_END and MPORT_SELECTOR in TARGET will work in all
- * circumstances. 1. Some will always work (e.g. a VF can always address its
- * logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC), 2. Some are not
- * meaningful and will always fail with EINVAL (e.g. attempting to address the
- * VNIC end of a link to a physical port), 3. Some are meaningful but require
- * the MCDI client to have the required permission and fail with EPERM
- * otherwise (e.g. trying to set the MAC on a VF the caller cannot administer),
- * and 4. Some could be implementation-specific and fail with ENOTSUP if not
- * available (no examples exist right now). See SF-123581-TC section 4.3 for
- * more details.
+/* Target port to set mac state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
  */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_LEN 8
@@ -5743,6 +6932,7 @@
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_LBN 288
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_OFST 32
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_LEN 4
 #define	MC_CMD_SET_MAC_V3_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 32
@@ -5938,6 +7128,98 @@
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_OFST 16
 #define	MC_CMD_MAC_STATS_IN_PORT_ID_LEN 4
 
+/* MC_CMD_MAC_STATS_V2_IN msgrequest */
+#define	MC_CMD_MAC_STATS_V2_IN_LEN 28
+/* ??? */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_OFST 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_OFST 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_LBN 32
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_ADDR_HI_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CMD_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LBN 0
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_LBN 1
+#define	MC_CMD_MAC_STATS_V2_IN_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_LBN 2
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CHANGE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_LBN 3
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_ENABLE_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_LBN 4
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_CLEAR_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_LBN 5
+#define	MC_CMD_MAC_STATS_V2_IN_PERIODIC_NOEVENT_WIDTH 1
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_OFST 8
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_LBN 16
+#define	MC_CMD_MAC_STATS_V2_IN_PERIOD_MS_WIDTH 16
+/* DMA length. Should be set to MAC_STATS_NUM_STATS * sizeof(uint64_t), as
+ * returned by MC_CMD_GET_CAPABILITIES_V4_OUT. For legacy firmware not
+ * supporting MC_CMD_GET_CAPABILITIES_V4_OUT, DMA_LEN should be set to
+ * MC_CMD_MAC_NSTATS * sizeof(uint64_t)
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_OFST 12
+#define	MC_CMD_MAC_STATS_V2_IN_DMA_LEN_LEN 4
+/* port id so vadapter stats can be provided */
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_OFST 16
+#define	MC_CMD_MAC_STATS_V2_IN_PORT_ID_LEN 4
+/* Target port to request statistics for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_OFST 23
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 180
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 176
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 22
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_LINK_END_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LEN 8
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_OFST 20
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_LBN 160
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_OFST 24
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_LBN 192
+#define	MC_CMD_MAC_STATS_V2_IN_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_MAC_STATS_OUT_DMA msgresponse */
 #define	MC_CMD_MAC_STATS_OUT_DMA_LEN 0
 
@@ -5954,6 +7236,7 @@
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS
+/* enum property: index */
 #define	MC_CMD_MAC_GENERATION_START 0x0 /* enum */
 #define	MC_CMD_MAC_DMABUF_START 0x1 /* enum */
 #define	MC_CMD_MAC_TX_PKTS 0x1 /* enum */
@@ -6116,6 +7399,7 @@
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V2_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V2
+/* enum property: index */
 /* enum: Start of FEC stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_FEC_DMABUF_START 0x61
 /* enum: Number of uncorrected FEC codewords on link (RS-FEC only for Medford2)
@@ -6155,6 +7439,7 @@
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V3_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V3
+/* enum property: index */
 /* enum: Start of CTPIO stats buffer space, Medford2 and up */
 #define	MC_CMD_MAC_CTPIO_DMABUF_START 0x68
 /* enum: Number of CTPIO fallbacks because a DMA packet was in progress on the
@@ -6235,6 +7520,7 @@
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_LBN 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_HI_WIDTH 32
 #define	MC_CMD_MAC_STATS_V4_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS_V4
+/* enum property: index */
 /* enum: Start of V4 stats buffer space */
 #define	MC_CMD_MAC_V4_DMABUF_START 0x79
 /* enum: RXDP counter: Number of packets truncated because scattering was
@@ -6522,6 +7808,7 @@
 #define	MC_CMD_WOL_FILTER_RESET_IN_LEN 4
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0
 #define	MC_CMD_WOL_FILTER_RESET_IN_MASK_LEN 4
+/* enum property: bitmask */
 #define	MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */
 #define	MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */
 
@@ -6566,6 +7853,7 @@
 /* Bit mask of supported types. */
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0
 #define	MC_CMD_NVRAM_TYPES_OUT_TYPES_LEN 4
+/* enum property: bitshift */
 /* enum: Disabled callisto. */
 #define	MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0
 /* enum: MC firmware. */
@@ -7613,6 +8901,54 @@
 /* MC_CMD_GET_PHY_STATE_IN msgrequest */
 #define	MC_CMD_GET_PHY_STATE_IN_LEN 0
 
+/* MC_CMD_GET_PHY_STATE_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_LEN 8
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details.
+ */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 20
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 16
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_OFST 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_LBN 0
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_OFST 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_LBN 32
+#define	MC_CMD_GET_PHY_STATE_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_STATE_OUT msgresponse */
 #define	MC_CMD_GET_PHY_STATE_OUT_LEN 4
 #define	MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0
@@ -7884,6 +9220,62 @@
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_LBN 16
 #define	MC_CMD_GET_PHY_MEDIA_INFO_IN_DSFP_BANK_WIDTH 16
 
+/* MC_CMD_GET_PHY_MEDIA_INFO_IN_V2 msgrequest */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_LEN 12
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_PAGE_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_LBN 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_PAGE_WIDTH 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_OFST 0
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_LBN 16
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_DSFP_BANK_WIDTH 16
+/* Target port to request PHY state for. Uses MAE_LINK_ENDPOINT_SELECTOR which
+ * identifies a real or virtual network port by MAE port and link end. See the
+ * structure definition for more details
+ */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_HI_WIDTH 32
+/* See structuredef: MAE_LINK_ENDPOINT_SELECTOR */
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FLAT_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_OFST 7
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_TYPE_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_MPORT_ID_LEN 3
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_PPORT_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_LBN 52
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_INTF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_LBN 48
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_MH_PF_ID_WIDTH 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_OFST 6
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_PF_ID_LEN 1
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_MPORT_SELECTOR_FUNC_VF_ID_LEN 2
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_LINK_END_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LEN 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_OFST 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_LBN 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_LO_WIDTH 32
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_OFST 8
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LEN 4
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_LBN 64
+#define	MC_CMD_GET_PHY_MEDIA_INFO_IN_V2_TARGET_FLAT_HI_WIDTH 32
+
 /* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
 #define	MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
@@ -9069,27 +10461,22 @@
  * and a generation count for this version of the sensor table. On systems
  * advertising the DYNAMIC_SENSORS capability bit, this replaces the
  * MC_CMD_READ_SENSORS command. On multi-MC systems this may include sensors
- * added by the NMC.
- *
- * Sensor handles are persistent for the lifetime of the sensor and are used to
- * identify sensors in MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
- * MC_CMD_DYNAMIC_SENSORS_GET_VALUES.
- *
- * The generation count is maintained by the MC, is persistent across reboots
- * and will be incremented each time the sensor table is modified. When the
- * table is modified, a CODE_DYNAMIC_SENSORS_CHANGE event will be generated
- * containing the new generation count. The driver should compare this against
- * the current generation count, and if it is different, call
- * MC_CMD_DYNAMIC_SENSORS_LIST again to update it's copy of the sensor table.
- *
- * The sensor count is provided to allow a future path to supporting more than
+ * added by the NMC. Sensor handles are persistent for the lifetime of the
+ * sensor and are used to identify sensors in
+ * MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS and
+ * MC_CMD_DYNAMIC_SENSORS_GET_VALUES. The generation count is maintained by the
+ * MC, is persistent across reboots and will be incremented each time the
+ * sensor table is modified. When the table is modified, a
+ * CODE_DYNAMIC_SENSORS_CHANGE event will be generated containing the new
+ * generation count. The driver should compare this against the current
+ * generation count, and if it is different, call MC_CMD_DYNAMIC_SENSORS_LIST
+ * again to update it's copy of the sensor table. The sensor count is provided
+ * to allow a future path to supporting more than
  * MC_CMD_DYNAMIC_SENSORS_GET_READINGS_IN_HANDLES_MAXNUM_MCDI2 sensors, i.e.
  * the maximum number that will fit in a single response. As this is a fairly
  * large number (253) it is not anticipated that this will be needed in the
- * near future, so can currently be ignored.
- *
- * On Riverhead this command is implemented as a a wrapper for `list` in the
- * sensor_query SPHINX service.
+ * near future, so can currently be ignored. On Riverhead this command is
+ * implemented as a wrapper for `list` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_LIST 0x66
 #define	MC_CMD_DYNAMIC_SENSORS_LIST_MSGSET 0x66
@@ -9127,15 +10514,13 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS
  * Get descriptions for a set of sensors, specified as an array of sensor
- * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for
- * `get_descriptions` in the sensor_query SPHINX service.
+ * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. Any handles which do not
+ * correspond to a sensor currently managed by the MC will be dropped from from
+ * the response. This may happen when a sensor table update is in progress, and
+ * effectively means the set of usable sensors is the intersection between the
+ * sets of sensors known to the driver and the MC. On Riverhead this command is
+ * implemented as a wrapper for `get_descriptions` in the sensor_query SPHINX
+ * service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS 0x67
 #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS_MSGSET 0x67
@@ -9173,19 +10558,15 @@
 /***********************************/
 /* MC_CMD_DYNAMIC_SENSORS_GET_READINGS
  * Read the state and value for a set of sensors, specified as an array of
- * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST.
- *
- * In the case of a broken sensor, then the state of the response's
- * MC_CMD_DYNAMIC_SENSORS_VALUE entry will be set to BROKEN, and any value
- * provided should be treated as erroneous.
- *
- * Any handles which do not correspond to a sensor currently managed by the MC
- * will be dropped from from the response. This may happen when a sensor table
- * update is in progress, and effectively means the set of usable sensors is
- * the intersection between the sets of sensors known to the driver and the MC.
- *
- * On Riverhead this command is implemented as a a wrapper for `get_readings`
- * in the sensor_query SPHINX service.
+ * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. In the case of a
+ * broken sensor, then the state of the response's MC_CMD_DYNAMIC_SENSORS_VALUE
+ * entry will be set to BROKEN, and any value provided should be treated as
+ * erroneous. Any handles which do not correspond to a sensor currently managed
+ * by the MC will be dropped from from the response. This may happen when a
+ * sensor table update is in progress, and effectively means the set of usable
+ * sensors is the intersection between the sets of sensors known to the driver
+ * and the MC. On Riverhead this command is implemented as a wrapper for
+ * `get_readings` in the sensor_query SPHINX service.
  */
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS 0x68
 #define	MC_CMD_DYNAMIC_SENSORS_GET_READINGS_MSGSET 0x68
@@ -11629,6 +13010,9 @@
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_LBN 11
 #define	MC_CMD_FILTER_OP_IN_MATCH_FWDEF1_WIDTH 1
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -11833,6 +13217,9 @@
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12118,6 +13505,9 @@
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_LBN 25
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_IFRM_UNKNOWN_UCAST_DST_WIDTH 1
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_OFST 16
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_LBN 29
+#define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_IPV4_MCAST_DST_WIDTH 1
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_OFST 16
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_LBN 30
 #define	MC_CMD_FILTER_OP_V3_IN_MATCH_UNKNOWN_MCAST_DST_WIDTH 1
@@ -12663,6 +14053,7 @@
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_OFST 0
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_LEN 4
 #define	MC_CMD_PARSER_DISP_RW_OUT_PORT_DP_MAPPING_NUM 4
+/* enum property: bitmask */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP0 0x1 /* enum */
 #define	MC_CMD_PARSER_DISP_RW_OUT_DP1 0x2 /* enum */
 
@@ -13511,10 +14902,9 @@
 
 /***********************************/
 /* MC_CMD_GET_CAPABILITIES
- * Get device capabilities.
- *
- * This is supplementary to the MC_CMD_GET_BOARD_CFG command, and intended to
- * reference inherent device capabilities as opposed to current NVRAM config.
+ * Get device capabilities. This is supplementary to the MC_CMD_GET_BOARD_CFG
+ * command, and intended to reference inherent device capabilities as opposed
+ * to current NVRAM config.
  */
 #define	MC_CMD_GET_CAPABILITIES 0xbe
 #define	MC_CMD_GET_CAPABILITIES_MSGSET 0xbe
@@ -16473,6 +17863,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V7_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V7_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 
 /* MC_CMD_GET_CAPABILITIES_V8_OUT msgresponse */
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_LEN 160
@@ -16974,6 +18373,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V8_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V8_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -17489,6 +18897,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V9_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V9_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18039,6 +19456,15 @@
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_OFST 148
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_LBN 12
 #define	MC_CMD_GET_CAPABILITIES_V10_OUT_RSS_STEER_ON_OUTER_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_LBN 13
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_MAE_ACTION_SET_ALLOC_V3_SUPPORTED_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_LBN 14
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_DYNAMIC_MPORT_JOURNAL_WIDTH 1
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_OFST 148
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_LBN 15
+#define	MC_CMD_GET_CAPABILITIES_V10_OUT_CLIENT_CMD_VF_PROXY_WIDTH 1
 /* These bits are reserved for communicating test-specific capabilities to
  * host-side test software. All production drivers should treat this field as
  * opaque.
@@ -18134,6 +19560,13 @@
  * are not defined.
  */
 #define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_TSA 0x1
+/* enum: MCDI command used for platform management. Typically, these commands
+ * are used for low-level operations directed at the platform as a whole (e.g.
+ * MMIO device enumeration) rather than individual functions and use a
+ * dedicated comms channel (e.g. RPmsg/IPI). May be handled by the same or
+ * different CPU as MCDI_MESSAGE_TYPE_MC.
+ */
+#define	MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM 0x2
 
 
 /***********************************/
@@ -22051,8 +23484,8 @@
  * TLV_PORT_MODE_*). A superset of MC_CMD_GET_PORT_MODES_OUT/MODES that
  * contains all modes implemented in firmware for a particular board. Modes
  * listed in MODES are considered production modes and should be exposed in
- * userland tools. Modes listed in in ENGINEERING_MODES, but not in MODES
- * should be considered hidden (not to be exposed in userland tools) and for
+ * userland tools. Modes listed in ENGINEERING_MODES, but not in MODES should
+ * be considered hidden (not to be exposed in userland tools) and for
  * engineering use only. There are no other semantic differences and any mode
  * listed in either MODES or ENGINEERING_MODES can be set on the board.
  */
@@ -26509,6 +27942,7 @@
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MINNUM 0
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM 31
 #define	MC_CMD_FPGA_OP_GET_MAC_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_PACKETS 0x0 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_BYTES 0x1 /* enum */
 #define	MC_CMD_FPGA_MAC_TX_TOTAL_GOOD_PACKETS 0x2 /* enum */
@@ -26617,6 +28051,65 @@
 /* MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT msgresponse */
 #define	MC_CMD_EXTERNAL_MAE_SET_LINK_MODE_OUT_LEN 0
 
+
+/***********************************/
+/* MC_CMD_GET_BUFTBL_STATS
+ * Currently EF10 only. Read usage and limits for Buffer Table
+ */
+#define	MC_CMD_GET_BUFTBL_STATS 0x6a
+#define	MC_CMD_GET_BUFTBL_STATS_MSGSET 0x6a
+#undef	MC_CMD_0x6a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x6a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_GET_BUFTBL_STATS_IN msgrequest */
+#define	MC_CMD_GET_BUFTBL_STATS_IN_LEN 0
+
+/* MC_CMD_GET_BUFTBL_STATS_OUT msgresponse */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_LEN 40
+/* number of buffer table entries per set */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_OFST 0
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_SET_LEN 4
+/* number of buffer table entries per cluster */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_OFST 4
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_ENTRIES_PER_CLUSTER_LEN 4
+/* Maximum size buffer table can grow to, in clusters. On EF10, this can
+ * potentially vary depending on the size of the Descriptor Cache.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_OFST 8
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MAX_CLUSTERS_LEN 4
+/* High water mark for number of buffer table clusters which have been
+ * allocated.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_OFST 12
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HIGH_WATER_CLUSTERS_LEN 4
+/* Number of free buffer table clusters on the free cluster list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_OFST 16
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_CLUSTERS_LEN 4
+/* Number of free buffer table sets on the free set list. */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_OFST 20
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_FREE_SETS_LEN 4
+/* Number of chunks of fully-used clusters allocated to the MC for EVQ, RXQ and
+ * TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_OFST 24
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_FULL_CLUSTERS_LEN 4
+/* Number of chunks in partially-used clusters allocated to the MC for EVQ, RXQ
+ * and TXQs.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_OFST 28
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_MC_PART_CLUSTERS_LEN 4
+/* Number of buffer table sets (chunks) allocated to the host via
+ * MC_CMD_ALLOC_BUFTBL_CHUNK.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_OFST 32
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_BUFTBL_HOST_SETS_LEN 4
+/* Maximum number of VIs per NIC. On EF10 this is the current value as used to
+ * size the Descriptor Cache in hardware.
+ */
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_OFST 36
+#define	MC_CMD_GET_BUFTBL_STATS_OUT_VI_MAX_LEN 4
+
 /* CLIENT_HANDLE structuredef: A client is an abstract entity that can make
  * requests of the device and that can own resources managed by the device.
  * Examples of clients include PCIe functions and dynamic clients. A client
@@ -26684,8 +28177,8 @@
 
 /* SCHED_CREDIT_CHECK_RESULT structuredef */
 #define	SCHED_CREDIT_CHECK_RESULT_LEN 16
-/* The instance of the scheduler. Refer to XN-200389-AW for the location of
- * these schedulers in the hardware.
+/* The instance of the scheduler. Refer to XN-200389-AW (snic/hnic) and
+ * XN-200425-TC (cdx) for the location of these schedulers in the hardware.
  */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_OFST 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LEN 1
@@ -26697,6 +28190,18 @@
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_HOST_D 0x5 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_HUB_REPLAY 0x6 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_DMAC_H2C 0x7 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_B 0x8 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_HUB_NET_REPLAY 0x9 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_ADAPTER_C2H_C 0xa /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A2_H2C_C 0xb /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A3_SOFT_ADAPTOR_C 0xc /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A4_DPU_WRITE_C 0xd /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_JRC_RRU 0xe /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_CDM_SINK 0xf /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PCIE_SINK 0x10 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_UPORT_SINK 0x11 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_PSX_SINK 0x12 /* enum */
+#define	SCHED_CREDIT_CHECK_RESULT_A5_DPU_READ_C 0x13 /* enum */
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_LBN 0
 #define	SCHED_CREDIT_CHECK_RESULT_SCHED_INSTANCE_WIDTH 8
 /* The type of node that this result refers to. */
@@ -26706,6 +28211,10 @@
 #define	SCHED_CREDIT_CHECK_RESULT_DEST 0x0
 /* enum: Source node */
 #define	SCHED_CREDIT_CHECK_RESULT_SOURCE 0x1
+/* enum: Destination node credit type 1 (new to the Keystone schedulers, see
+ * SF-120268-TC)
+ */
+#define	SCHED_CREDIT_CHECK_RESULT_DEST_CREDIT1 0x2
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_LBN 8
 #define	SCHED_CREDIT_CHECK_RESULT_NODE_TYPE_WIDTH 8
 /* Level of node in scheduler hierarchy (level 0 is the bottom of the
@@ -27813,6 +29322,51 @@
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM 14
 #define	MC_CMD_CHECK_SCHEDULER_CREDITS_OUT_RESULTS_MAXNUM_MCDI2 62
 
+
+/***********************************/
+/* MC_CMD_TXQ_STATS
+ * Query per-TXQ statistics.
+ */
+#define	MC_CMD_TXQ_STATS 0x1d5
+#define	MC_CMD_TXQ_STATS_MSGSET 0x1d5
+#undef	MC_CMD_0x1d5_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1d5_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TXQ_STATS_IN msgrequest */
+#define	MC_CMD_TXQ_STATS_IN_LEN 8
+/* Instance of TXQ to retrieve statistics for */
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_OFST 0
+#define	MC_CMD_TXQ_STATS_IN_INSTANCE_LEN 4
+/* Flags for the request */
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_FLAGS_LEN 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_OFST 4
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_LBN 0
+#define	MC_CMD_TXQ_STATS_IN_CLEAR_WIDTH 1
+
+/* MC_CMD_TXQ_STATS_OUT msgresponse */
+#define	MC_CMD_TXQ_STATS_OUT_LENMIN 0
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX 248
+#define	MC_CMD_TXQ_STATS_OUT_LENMAX_MCDI2 1016
+#define	MC_CMD_TXQ_STATS_OUT_LEN(num) (0+8*(num))
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_NUM(len) (((len)-0)/8)
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LEN 8
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_OFST 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_LBN 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_LO_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_OFST 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LEN 4
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_LBN 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_HI_WIDTH 32
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MINNUM 0
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM 31
+#define	MC_CMD_TXQ_STATS_OUT_STATISTICS_MAXNUM_MCDI2 127
+/* enum property: index */
+#define	MC_CMD_TXQ_STATS_CTPIO_MAX_FILL 0x0 /* enum */
+
 /* FUNCTION_PERSONALITY structuredef: The meanings of the personalities are
  * defined in SF-120734-TC with more information in SF-122717-TC.
  */
@@ -28296,6 +29850,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_LBN 32
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_IN_FUNC_VF_OFST 2
@@ -28332,6 +29887,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_CREATE_OUT_FUNC_VF_OFST 6
@@ -28709,6 +30265,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LEN 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_LBN 64
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_OFST 4
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_PF_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_OPEN_OUT_FUNC_VF_OFST 6
@@ -28788,6 +30345,7 @@
 #define	DESC_PROXY_FUNC_MAP_FUNC_HI_WIDTH 32
 #define	DESC_PROXY_FUNC_MAP_FUNC_LBN 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_WIDTH 64
+/* See structuredef: PCIE_FUNCTION */
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_OFST 0
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LEN 2
 #define	DESC_PROXY_FUNC_MAP_FUNC_PF_LBN 0
@@ -28851,6 +30409,27 @@
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM 4
 #define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_MAXNUM_MCDI2 19
+/* See structuredef: DESC_PROXY_FUNC_MAP */
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LEN 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_LBN 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_LO_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_LBN 64
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_HI_WIDTH 32
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_OFST 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_PF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_OFST 6
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_VF_LEN 2
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_OFST 8
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_FUNC_INTF_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_OFST 12
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_PERSONALITY_LEN 4
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_OFST 16
+#define	MC_CMD_DESC_PROXY_FUNC_ENUM_OUT_FUNC_MAP_LABEL_LEN 40
 
 
 /***********************************/
@@ -29015,6 +30594,7 @@
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MINNUM 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM 63
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_MAXNUM_MCDI2 255
+/* See structuredef: QUEUE_ID */
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_OFST 0
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_ABS_VI_LEN 2
 #define	MC_CMD_DESC_PROXY_FUNC_GET_VI_INFO_OUT_VI_MAP_REL_QUEUE_LBN 16
@@ -29082,6 +30662,7 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LEN 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_LBN 64
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_HI_WIDTH 32
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_ADDR_SPC_ID_IN_FUNC_VF_OFST 6
@@ -29162,6 +30743,7 @@
  * backwards compatibility only, callers should use PCIE_INTERFACE_CALLER.
  */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_PCIE_FUNCTION_INTF_NULL 0xffffffff
+/* See structuredef: PCIE_FUNCTION */
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_OFST 4
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_PF_LEN 2
 #define	MC_CMD_GET_CLIENT_HANDLE_IN_FUNC_VF_OFST 6
@@ -29320,6 +30902,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_LBN 1096
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_OFST 138
@@ -29333,10 +30916,12 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_WIDTH 8
+/* More generic alias for ENC_VLAN_FLAGS. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_OFST 138
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_LBN 1104
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_WIDTH 8
+/* Deprecated in favour of ENC_FLAGS_MASK alias. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_HAS_OVLAN_MASK_OFST 139
@@ -29350,6 +30935,7 @@
 #define	MAE_ENC_FIELD_PAIRS_ENC_IP_FRAG_MASK_WIDTH 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_LBN 1112
 #define	MAE_ENC_FIELD_PAIRS_ENC_VLAN_FLAGS_MASK_WIDTH 8
+/* More generic alias for ENC_FLAGS_MASK. */
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_OFST 139
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LEN 1
 #define	MAE_ENC_FIELD_PAIRS_ENC_FLAGS_MASK_LBN 1112
@@ -29503,6 +31089,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_LBN 1152
@@ -29826,6 +31416,10 @@
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_LBN 1144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_WIDTH 8
+/* Due to hardware limitations, firmware may return
+ * MC_CMD_ERR_EINVAL(BAD_IP_TTL) when attempting to match on an IP_TTL value
+ * other than 1.
+ */
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_OFST 144
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LEN 1
 #define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_LBN 1152
@@ -30120,7 +31714,7 @@
 /* MAE_MPORT_SELECTOR structuredef: MPORTS are identified by an opaque unsigned
  * integer value (mport_id) that is guaranteed to be representable within
  * 32-bits or within any NIC interface field that needs store the value
- * (whichever is narrowers). This selector structure provides a stable way to
+ * (whichever is narrower). This selector structure provides a stable way to
  * refer to m-ports.
  */
 #define	MAE_MPORT_SELECTOR_LEN 4
@@ -30195,10 +31789,22 @@
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
 /* MAE_LINK_ENDPOINT_SELECTOR structuredef: Structure that identifies a real or
- * virtual network port by MAE port and link end
+ * virtual network port by MAE port and link end. Intended to be used by
+ * network port MCDI commands. Setting FLAT to MAE_LINK_ENDPOINT_COMPAT is
+ * equivalent to using the previous version of the command. Not all possible
+ * combinations of MPORT_END and MPORT_SELECTOR in MAE_LINK_ENDPOINT_SELECTOR
+ * will work in all circumstances. 1. Some will always work (e.g. a VF can
+ * always address its logical MAC using MPORT_SELECTOR=ASSIGNED,LINK_END=VNIC),
+ * 2. Some are not meaningful and will always fail with EINVAL (e.g. attempting
+ * to address the VNIC end of a link to a physical port), 3. Some are
+ * meaningful but require the MCDI client to have the required permission and
+ * fail with EPERM otherwise (e.g. trying to set the MAC on a VF the caller
+ * cannot administer), and 4. Some could be implementation-specific and fail
+ * with ENOTSUP if not available (no examples exist right now). See
+ * SF-123581-TC section 4.3 for more details.
  */
 #define	MAE_LINK_ENDPOINT_SELECTOR_LEN 8
-/* The MAE MPORT of interest */
+/* Identifier for the MAE MPORT of interest */
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_OFST 0
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LEN 4
 #define	MAE_LINK_ENDPOINT_SELECTOR_MPORT_SELECTOR_LBN 0
@@ -30395,6 +32001,90 @@
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_OFST 56
 #define	MC_CMD_MAE_GET_CAPS_V2_OUT_CT_COUNTERS_LEN 4
 
+/* MC_CMD_MAE_GET_CAPS_V3_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_LEN 64
+/* The number of field IDs that the NIC supports. Any field with a ID greater
+ * than or equal to the value returned in this field must be treated as having
+ * a support level of MAE_FIELD_UNSUPPORTED in all requests.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_LBN 3
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_TYPE_L2GRE_WIDTH 1
+/* Deprecated alias for AR_COUNTERS. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTERS_LEN 4
+/* The total number of AR counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_AR_COUNTERS_LEN 4
+/* The total number of counters lists available to allocate. A value of zero
+ * indicates that counter lists are not supported by the NIC. (But single
+ * counters may still be.)
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_RULES_LEN 4
+/* The number of priorities available for ACTION_RULE filters. It is invalid to
+ * install a MATCH_ACTION filter with a priority number >= ACTION_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_ACTION_PRIOS_LEN 4
+/* The number of priorities available for OUTER_RULE filters. It is invalid to
+ * install an OUTER_RULE filter with a priority number >= OUTER_PRIOS.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OUTER_PRIOS_LEN 4
+/* MAE API major version. Currently 1. If this field is not present in the
+ * response (i.e. response shorter than 384 bits), then its value is zero. If
+ * the value does not match the client's expectations, the client should raise
+ * a fatal error.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_API_VER_LEN 4
+/* Mask of supported counter types. Each bit position corresponds to a value of
+ * the MAE_COUNTER_TYPE enum. If this field is missing (i.e. V1 response),
+ * clients must assume that only AR counters are supported (i.e.
+ * COUNTER_TYPES_SUPPORTED==0x1). See also
+ * MC_CMD_MAE_COUNTERS_STREAM_START/COUNTER_TYPES_MASK.
+ */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_OFST 52
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_COUNTER_TYPES_SUPPORTED_LEN 4
+/* The total number of conntrack counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_OFST 56
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_CT_COUNTERS_LEN 4
+/* The total number of Outer Rule counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_OFST 60
+#define	MC_CMD_MAE_GET_CAPS_V3_OUT_OR_COUNTERS_LEN 4
+
 
 /***********************************/
 /* MC_CMD_MAE_GET_AR_CAPS
@@ -30498,10 +32188,13 @@
 /* Generation count. Packets with generation count >= GENERATION_COUNT will
  * contain valid counter values for counter IDs allocated in this call, unless
  * the counter values are zero and zero squash is enabled. Note that there is
- * an independent GENERATION_COUNT object per counter type.
+ * an independent GENERATION_COUNT object per counter type, and that generation
+ * counts wrap from 0xffffffff to 1.
  */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* enum: Generation counter 0 is reserved and unused. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_INVALID 0x0
 /* The number of counter IDs that the NIC allocated. It is never less than 1;
  * failure to allocate a single counter will cause an error to be returned. It
  * is never greater than REQUESTED_COUNT, but may be less.
@@ -30516,6 +32209,8 @@
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2 253
 /* enum: A counter ID that is guaranteed never to represent a real counter */
 #define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL 0xffffffff
+/*            Other enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 
 
 /***********************************/
@@ -30577,7 +32272,8 @@
  * values will be written for these counters. If values for these counter IDs
  * are present, the counter ID has been reallocated. A counter ID will not be
  * reallocated within a single read cycle as this would merge increments from
- * the 'old' and 'new' counters.
+ * the 'old' and 'new' counters. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
@@ -30696,7 +32392,8 @@
 /* Generation count for AR counters. The final set of AR counter values will be
  * written out in packets with count == GENERATION_COUNT. An empty packet with
  * count > GENERATION_COUNT indicates that no more counter values of this type
- * will be written to this stream.
+ * will be written to this stream. GENERATION_COUNT_INVALID is reserved and
+ * unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
@@ -30712,6 +32409,7 @@
  * final set of counter values will be written out in packets with count ==
  * GENERATION_COUNT. An empty packet with count > GENERATION_COUNT indicates
  * that no more counter values of this type will be written to this stream.
+ * GENERATION_COUNT_INVALID is reserved and unused.
  */
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_OFST 0
 #define	MC_CMD_MAE_COUNTERS_STREAM_STOP_V2_OUT_GENERATION_COUNT_LEN 4
@@ -30960,6 +32658,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE_LEN 2
@@ -30985,19 +32701,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31041,6 +32761,24 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_OFST 0
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_LBN 14
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_LACP_INC_L4_WIDTH 1
 /* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_OFST 4
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_VLAN0_TCI_BE_LEN 2
@@ -31066,19 +32804,23 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_OFST 20
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_DELIVER_LEN 4
 /* Allows an action set to trigger several counter updates. Set to
- * COUNTER_LIST_ID_NULL to request no counter action.
+ * MAE_COUNTER_ID_NULL to request no counter action.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_OFST 24
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 /* If a driver only wished to update one counter within this action set, then
  * it can supply a COUNTER_ID instead of allocating a single-element counter
  * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
- * should be set to COUNTER_ID_NULL if this behaviour is not required. It is
- * not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
  * COUNTER_ID.
  */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_OFST 28
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_OFST 32
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_MARK_VALUE_LEN 4
 /* Set to MAC_ID_NULL to request no source MAC replacement. */
@@ -31131,6 +32873,172 @@
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_LBN 6
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_V2_IN_ECN_ECT_1_TO_CE_WIDTH 1
 
+/* MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN msgrequest: Only supported if
+ * MAE_ACTION_SET_ALLOC_V3_SUPPORTED is advertised in
+ * MC_CMD_GET_CAPABILITIES_V10_OUT.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LEN 53
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_NAT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_LBN 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DECR_IP_TTL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_LBN 13
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_SRC_MPORT_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_LBN 14
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SUPPRESS_SELF_DELIVERY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_LBN 15
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_LBN 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_LBN 17
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_RDP_OUT_HOST_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_LBN 18
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_SET_NET_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_LBN 19
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_PLUGIN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_LBN 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_LACP_INC_L4_WIDTH 1
+/* If VLAN_PUSH >= 1, TCI value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_TCI_BE_LEN 2
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ENCAP_HEADER_ID_LEN 4
+/* An m-port selector identifying the m-port that the modified packet should be
+ * delivered to. Set to MPORT_SELECTOR_NULL to request no delivery of the
+ * packet.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_OFST 20
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DELIVER_LEN 4
+/* Allows an action set to trigger several counter updates. Set to
+ * MAE_COUNTER_ID_NULL to request no counter action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_OFST 24
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_LIST_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+/* If a driver only wished to update one counter within this action set, then
+ * it can supply a COUNTER_ID instead of allocating a single-element counter
+ * list. The ID must have been allocated with COUNTER_TYPE=AR. This field
+ * should be set to MAE_COUNTER_ID_NULL if this behaviour is not required. It
+ * is not valid to supply a non-NULL value for both COUNTER_LIST_ID and
+ * COUNTER_ID.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_OFST 28
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_COUNTER_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_COUNTER_ID */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_OFST 32
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_MARK_VALUE_LEN 4
+/* Set to MAC_ID_NULL to request no source MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DST_MAC_ID_LEN 4
+/* Source m-port ID to be reported for DO_SET_SRC_MPORT action. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_OFST 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_REPORTED_SRC_MPORT_LEN 4
+/* Actions for modifying the Differentiated Services Code-Point (DSCP) bits
+ * within IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_CONTROL_LEN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_DSCP_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_DSCP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_OFST 48
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DSCP_VALUE_WIDTH 6
+/* Actions for modifying the Explicit Congestion Notification (ECN) bits within
+ * IPv4 and IPv6 headers.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_CONTROL_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_ENCAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_ECN_DECAP_COPY_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_DO_REPLACE_ECN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_VALUE_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_LBN 5
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_0_TO_CE_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_OFST 50
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_LBN 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_ECN_ECT_1_TO_CE_WIDTH 1
+/* Actions for overwriting CH_ROUTE subfields. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OVERWRITE_LEN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_C_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_LBN 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_D_PL_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_LBN 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_PL_CHAN_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_OFST 51
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_LBN 3
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_RDP_OUT_HOST_CHAN_WIDTH 1
+/* Override outgoing CH_VC to network port for DO_SET_NET_CHAN action. Cannot
+ * be used in conjunction with DO_SET_SRC_MPORT action.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_OFST 52
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_V3_IN_NET_CHAN_LEN 1
+
 /* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
 #define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
 /* The MSB of the AS_ID is guaranteed to be clear if the ID is not
@@ -31297,6 +33205,7 @@
  */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+/* Deprecated alias for ACTION_CONTROL. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL_LEN 4
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_OFST 8
@@ -31307,15 +33216,26 @@
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_WIDTH 2
 /*             Enum values, see field(s): */
 /*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_LBN 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RECIRC_ID_WIDTH 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_OFST 8
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_LBN 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_DOMAIN_WIDTH 16
-/* Reserved for future use. Must be set to zero. */
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_OFST 12
-#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_RSVD_LEN 4
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ACTION_CONTROL_LEN 4
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_COUNTER_ID_LEN 4
 /* Structure of the format MAE_ENC_FIELD_PAIRS. */
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST 16
 #define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_LEN 1
@@ -31367,6 +33287,59 @@
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM 32
 #define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MAXNUM_MCDI2 32
 
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_UPDATE
+ * Atomically change the response of an Outer Rule.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE 0x17d
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_MSGSET 0x17d
+#undef	MC_CMD_0x17d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x17d_PRIVILEGE_CTG SRIOV_CTG_MAE
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_LEN 16
+/* ID of outer rule to update */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_OR_ID_LEN 4
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* This field controls the actions that are performed when a rule is hit. */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_ACTION_CONTROL_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_LBN 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_LBN 3
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_DO_COUNT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_LBN 4
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_TCP_FLAGS_INHIBIT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_LBN 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_RECIRC_ID_WIDTH 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_LBN 16
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_CT_DOMAIN_WIDTH 16
+/* ID of counter to increment when the rule is hit. Only used if the DO_COUNT
+ * flag is set. The ID must have been allocated with COUNTER_TYPE=OR.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_OFST 12
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_IN_COUNTER_ID_LEN 4
+
+/* MC_CMD_MAE_OUTER_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_UPDATE_OUT_LEN 0
+
 /* MAE_ACTION_RULE_RESPONSE structuredef */
 #define	MAE_ACTION_RULE_RESPONSE_LEN 16
 #define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
@@ -31932,6 +33905,7 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_OFST 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_LBN 0
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MORE_WIDTH 1
+/* The number of MAE_MPORT_DESC structures in MPORT_DESC_DATA. May be zero. */
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_OFST 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT_LEN 4
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC_OFST 8
@@ -31946,4 +33920,407 @@
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM 240
 #define	MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1008
 
+/* TABLE_FIELD_DESCR structuredef: An individual table field descriptor. This
+ * describes the location and properties of one N-bit field within a wider
+ * M-bit key/mask/response value.
+ */
+#define	TABLE_FIELD_DESCR_LEN 8
+/* Identifier for this field. */
+#define	TABLE_FIELD_DESCR_FIELD_ID_OFST 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_LEN 2
+/*            Enum values, see field(s): */
+/*               TABLE_FIELD_ID */
+#define	TABLE_FIELD_DESCR_FIELD_ID_LBN 0
+#define	TABLE_FIELD_DESCR_FIELD_ID_WIDTH 16
+/* Lowest (least significant) bit number of the bits of this field. */
+#define	TABLE_FIELD_DESCR_LBN_OFST 2
+#define	TABLE_FIELD_DESCR_LBN_LEN 2
+#define	TABLE_FIELD_DESCR_LBN_LBN 16
+#define	TABLE_FIELD_DESCR_LBN_WIDTH 16
+/* Width of this field in bits. */
+#define	TABLE_FIELD_DESCR_WIDTH_OFST 4
+#define	TABLE_FIELD_DESCR_WIDTH_LEN 2
+#define	TABLE_FIELD_DESCR_WIDTH_LBN 32
+#define	TABLE_FIELD_DESCR_WIDTH_WIDTH 16
+/* The mask type for this field. (Note that masking is relevant to keys; fields
+ * of responses are always reported with the EXACT type.)
+ */
+#define	TABLE_FIELD_DESCR_MASK_TYPE_OFST 6
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LEN 1
+/* enum: Field must never be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_NEVER 0x0
+/* enum: Exact match: field must always be selected in the mask. */
+#define	TABLE_FIELD_DESCR_MASK_EXACT 0x1
+/* enum: Ternary match: arbitrary mask bits are allowed. */
+#define	TABLE_FIELD_DESCR_MASK_TERNARY 0x2
+/* enum: Whole field match: mask must be all 1 bits, or all 0 bits. */
+#define	TABLE_FIELD_DESCR_MASK_WHOLE_FIELD 0x3
+/* enum: Longest prefix match: mask must be 1 bit(s) followed by 0 bit(s). */
+#define	TABLE_FIELD_DESCR_MASK_LPM 0x4
+#define	TABLE_FIELD_DESCR_MASK_TYPE_LBN 48
+#define	TABLE_FIELD_DESCR_MASK_TYPE_WIDTH 8
+/* A version code that allows field semantics to be extended. All fields
+ * currently use version 0.
+ */
+#define	TABLE_FIELD_DESCR_SCHEME_OFST 7
+#define	TABLE_FIELD_DESCR_SCHEME_LEN 1
+#define	TABLE_FIELD_DESCR_SCHEME_LBN 56
+#define	TABLE_FIELD_DESCR_SCHEME_WIDTH 8
+
+
+/***********************************/
+/* MC_CMD_TABLE_LIST
+ * Return the list of tables which may be accessed via this table API.
+ */
+#define	MC_CMD_TABLE_LIST 0x1c9
+#define	MC_CMD_TABLE_LIST_MSGSET 0x1c9
+#undef	MC_CMD_0x1c9_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1c9_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_LIST_IN msgrequest */
+#define	MC_CMD_TABLE_LIST_IN_LEN 4
+/* Index of the first item to be returned in the TABLE_ID sequence. (Set to 0
+ * for the first call; further calls are only required if the whole sequence
+ * does not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_OFST 0
+#define	MC_CMD_TABLE_LIST_IN_FIRST_TABLE_ID_INDEX_LEN 4
+
+/* MC_CMD_TABLE_LIST_OUT msgresponse */
+#define	MC_CMD_TABLE_LIST_OUT_LENMIN 4
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX 252
+#define	MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_LIST_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(len) (((len)-4)/4)
+/* The total number of tables. */
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_OFST 0
+#define	MC_CMD_TABLE_LIST_OUT_N_TABLES_LEN 4
+/* A sequence of table identifiers. If all N_TABLES items do not fit, further
+ * items can be obtained by repeating the call with a non-zero
+ * FIRST_TABLE_ID_INDEX.
+ */
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_OFST 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_LEN 4
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MINNUM 0
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM 62
+#define	MC_CMD_TABLE_LIST_OUT_TABLE_ID_MAXNUM_MCDI2 254
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+
+
+/***********************************/
+/* MC_CMD_TABLE_DESCRIPTOR
+ * Request the table descriptor for a particular table. This describes
+ * properties of the table and the format of the key and response. May return
+ * EINVAL for unknown table ID.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR 0x1ca
+#define	MC_CMD_TABLE_DESCRIPTOR_MSGSET 0x1ca
+#undef	MC_CMD_0x1ca_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ca_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DESCRIPTOR_IN msgrequest */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_LEN 8
+/* Identifier for this field. */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Index of the first item to be returned in the FIELDS sequence. (Set to 0 for
+ * the first call; further calls are only required if the whole sequence does
+ * not fit within the maximum MCDI message size.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX_LEN 4
+
+/* MC_CMD_TABLE_DESCRIPTOR_OUT msgresponse */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN 28
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX 252
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_LEN(num) (20+8*(num))
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(len) (((len)-20)/8)
+/* Maximum number of entries in this table. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_OFST 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_ENTRIES_LEN 4
+/* The type of table. (This is really just informational; the important
+ * properties of a table that affect programming can be deduced from other
+ * items in the table or field descriptor.)
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_OFST 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_LEN 2
+/* enum: Direct table (essentially just an array). Behaves like a BCAM for
+ * programming purposes, where the fact that the key is actually used as an
+ * array index is really just an implementation detail.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_DIRECT 0x1
+/* enum: BCAM (binary CAM) table: exact match on all key fields." */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM 0x2
+/* enum: TCAM (ternary CAM) table: matches fields with a mask. Each entry may
+ * have its own different mask.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_TCAM 0x3
+/* enum: STCAM (semi-TCAM) table: like a TCAM but entries shared a limited
+ * number of unique masks.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_STCAM 0x4
+/* Width of key (and corresponding mask, for TCAM or STCAM) in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_KEY_WIDTH_LEN 2
+/* Width of response in bits. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_RESP_WIDTH_LEN 2
+/* The total number of fields in the key. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_OFST 10
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS_LEN 2
+/* The total number of fields in the response. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_OFST 12
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS_LEN 2
+/* Number of priorities for STCAM or TCAM; otherwise 0. The priority of a table
+ * entry (relevant when more than one masked entry matches) ranges from
+ * 0=highest to N_PRIORITIES-1=lowest.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_OFST 14
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_N_PRIORITIES_LEN 2
+/* Maximum number of masks for STCAM; otherwise 0. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_OFST 16
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_MAX_MASKS_LEN 2
+/* Flags. */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FLAGS_LEN 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_OFST 18
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_LBN 0
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_ALLOC_MASKS_WIDTH 1
+/* Access scheme version code, allowing the method of accessing table entries
+ * to change semantics in future. A client which does not understand the value
+ * of this field should assume that it cannot program this table. Currently
+ * always set to 0 indicating the original MC_CMD_TABLE_INSERT/UPDATE/DELETE
+ * semantics.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_OFST 19
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_SCHEME_LEN 1
+/* A sequence of TABLE_FIELD_DESCR structures: N_KEY_FIELDS items describing
+ * the key, followed by N_RESP_FIELDS items describing the response. If all
+ * N_KEY_FIELDS+N_RESP_FIELDS items do not fit, further items can be obtained
+ * by repeating the call with a non-zero FIRST_FIELDS_INDEX.
+ */
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LEN 8
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_OFST 20
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_LBN 160
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_LO_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_OFST 24
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LEN 4
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_LBN 192
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_HI_WIDTH 32
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MINNUM 1
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM 29
+#define	MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_MAXNUM_MCDI2 125
+
+
+/***********************************/
+/* MC_CMD_TABLE_INSERT
+ * Insert a new entry into a table. The entry must not currently exist. May
+ * return EINVAL for unknown table ID or other bad request parameters, EEXIST
+ * if the entry already exists, ENOSPC if there is no space or EPERM if the
+ * operation is not permitted. In case of an error, the additional MCDI error
+ * argument field returns the raw error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_INSERT 0x1cd
+#define	MC_CMD_TABLE_INSERT_MSGSET 0x1cd
+#undef	MC_CMD_0x1cd_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cd_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_INSERT_IN msgrequest */
+#define	MC_CMD_TABLE_INSERT_IN_LENMIN 16
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX 252
+#define	MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_INSERT_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_INSERT_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_INSERT_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_INSERT_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_INSERT_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_INSERT_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_INSERT_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_INSERT_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_INSERT_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_INSERT_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_INSERT_OUT msgresponse */
+#define	MC_CMD_TABLE_INSERT_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_UPDATE
+ * Update an existing entry in a table with a new response value. May return
+ * EINVAL for unknown table ID or other bad request parameters, ENOENT if the
+ * entry does not already exist, or EPERM if the operation is not permitted. In
+ * case of an error, the additional MCDI error argument field returns the raw
+ * error code from the underlying CAM driver.
+ */
+#define	MC_CMD_TABLE_UPDATE 0x1ce
+#define	MC_CMD_TABLE_UPDATE_MSGSET 0x1ce
+#undef	MC_CMD_0x1ce_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1ce_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_UPDATE_IN msgrequest */
+#define	MC_CMD_TABLE_UPDATE_IN_LENMIN 16
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX 252
+#define	MC_CMD_TABLE_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_UPDATE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_UPDATE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_UPDATE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_UPDATE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_UPDATE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_UPDATE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_UPDATE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_UPDATE_OUT msgresponse */
+#define	MC_CMD_TABLE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_TABLE_DELETE
+ * Delete an existing entry in a table. May return EINVAL for unknown table ID
+ * or other bad request parameters, ENOENT if the entry does not exist, or
+ * EPERM if the operation is not permitted. In case of an error, the additional
+ * MCDI error argument field returns the raw error code from the underlying CAM
+ * driver.
+ */
+#define	MC_CMD_TABLE_DELETE 0x1cf
+#define	MC_CMD_TABLE_DELETE_MSGSET 0x1cf
+#undef	MC_CMD_0x1cf_PRIVILEGE_CTG
+
+#define	MC_CMD_0x1cf_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_TABLE_DELETE_IN msgrequest */
+#define	MC_CMD_TABLE_DELETE_IN_LENMIN 16
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX 252
+#define	MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_TABLE_DELETE_IN_LEN(num) (12+4*(num))
+#define	MC_CMD_TABLE_DELETE_IN_DATA_NUM(len) (((len)-12)/4)
+/* Table identifier. */
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_OFST 0
+#define	MC_CMD_TABLE_DELETE_IN_TABLE_ID_LEN 4
+/*            Enum values, see field(s): */
+/*               TABLE_ID */
+/* Width in bits of supplied key data (must match table properties). */
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_OFST 4
+#define	MC_CMD_TABLE_DELETE_IN_KEY_WIDTH_LEN 2
+/* Width in bits of supplied mask data (0 for direct/BCAM tables, or for STCAM
+ * when allocated MASK_ID is used instead).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_WIDTH_LEN 2
+/* Width in bits of supplied response data (for INSERT and UPDATE operations
+ * this must match the table properties; for DELETE operations, no response
+ * data is required and this must be 0).
+ */
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_RESP_WIDTH_LEN 2
+/* Mask ID for STCAM table - used instead of mask data if the table descriptor
+ * reports ALLOC_MASKS==1. Otherwise set to 0.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_OFST 6
+#define	MC_CMD_TABLE_DELETE_IN_MASK_ID_LEN 2
+/* Priority for TCAM or STCAM, in range 0..N_PRIORITIES-1, otherwise 0. */
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_OFST 8
+#define	MC_CMD_TABLE_DELETE_IN_PRIORITY_LEN 2
+/* (32-bit alignment padding - set to 0) */
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_OFST 10
+#define	MC_CMD_TABLE_DELETE_IN_RESERVED_LEN 2
+/* Sequence of key, mask (if MASK_WIDTH > 0), and response (if RESP_WIDTH > 0)
+ * data values. Each of these items is logically treated as a single wide N-bit
+ * value, in which the individual fields have been placed within that value per
+ * the LBN and WIDTH information from the table field descriptors. The wide
+ * N-bit value is padded with 0 bits at the MSB end if necessary to make a
+ * multiple of 32 bits. The value is then packed into this command as a
+ * sequence of 32-bit words, bits [31:0] first, then bits [63:32], etc.
+ */
+#define	MC_CMD_TABLE_DELETE_IN_DATA_OFST 12
+#define	MC_CMD_TABLE_DELETE_IN_DATA_LEN 4
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MINNUM 1
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM 60
+#define	MC_CMD_TABLE_DELETE_IN_DATA_MAXNUM_MCDI2 252
+
+/* MC_CMD_TABLE_DELETE_OUT msgresponse */
+#define	MC_CMD_TABLE_DELETE_OUT_LEN 0
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 02/34] common/sfc_efx/base: detect MCDI Table Access API support
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
                     ` (34 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Future patches will add an implementation of MCDI Table
Access API in libefx. This patch adds a way to determine
if this API is supported.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h          | 2 ++
 drivers/common/sfc_efx/base/hunt_nic.c     | 2 ++
 drivers/common/sfc_efx/base/medford2_nic.c | 2 ++
 drivers/common/sfc_efx/base/medford_nic.c  | 2 ++
 drivers/common/sfc_efx/base/rhead_nic.c    | 9 +++++++++
 drivers/common/sfc_efx/base/siena_nic.c    | 2 ++
 6 files changed, 19 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f4fa88f169..520674a602 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1672,6 +1672,8 @@ typedef struct efx_nic_cfg_s {
 	boolean_t		enc_mae_admin;
 	/* NIC support for MAE action set v2 features. */
 	boolean_t		enc_mae_aset_v2_supported;
+	/* NIC support for MCDI Table Access API. */
+	boolean_t		enc_table_api_supported;
 	/* Firmware support for "FLAG" and "MARK" filter actions */
 	boolean_t		enc_filter_action_flag_supported;
 	boolean_t		enc_filter_action_mark_supported;
diff --git a/drivers/common/sfc_efx/base/hunt_nic.c b/drivers/common/sfc_efx/base/hunt_nic.c
index 08ae324482..04595a39c8 100644
--- a/drivers/common/sfc_efx/base/hunt_nic.c
+++ b/drivers/common/sfc_efx/base/hunt_nic.c
@@ -192,6 +192,8 @@ hunt_board_cfg(
 	/* All Huntington devices have a PCIe Gen3, 8 lane connector */
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford2_nic.c b/drivers/common/sfc_efx/base/medford2_nic.c
index 6d19524573..49adabffb2 100644
--- a/drivers/common/sfc_efx/base/medford2_nic.c
+++ b/drivers/common/sfc_efx/base/medford2_nic.c
@@ -152,6 +152,8 @@ medford2_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/medford_nic.c b/drivers/common/sfc_efx/base/medford_nic.c
index b111e3eded..9a460b2b9b 100644
--- a/drivers/common/sfc_efx/base/medford_nic.c
+++ b/drivers/common/sfc_efx/base/medford_nic.c
@@ -150,6 +150,8 @@ medford_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	return (0);
 
 fail4:
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index eda6c1c4f9..a773aea38d 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -176,6 +176,15 @@ rhead_board_cfg(
 	encp->enc_required_pcie_bandwidth_mbps = bandwidth;
 	encp->enc_max_pcie_link_gen = EFX_PCIE_LINK_SPEED_GEN3;
 
+	/*
+	 * FIXME: MCDI table API support depends on an EF100 firmware build
+	 * and an EF100 platform. It should be discovered by using a capability
+	 * flag from MCDI that is not implemented yet.
+	 * Right now we can safely rely on the return code from the libefx
+	 * MCDI Table API.
+	 */
+	encp->enc_table_api_supported = B_TRUE;
+
 	return (0);
 
 fail3:
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 9f14faf271..1f1fb7d2af 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -205,6 +205,8 @@ siena_board_cfg(
 	encp->enc_mae_supported = B_FALSE;
 	encp->enc_mae_admin = B_FALSE;
 
+	encp->enc_table_api_supported = B_FALSE;
+
 	encp->enc_dma_mapping = EFX_NIC_DMA_MAPPING_FLAT;
 
 	return (0);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-19 15:58     ` Ferruh Yigit
  2023-06-07 13:02   ` [PATCH v4 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
                     ` (33 subsequent siblings)
  36 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

New MCDI Table Access API allows management of
the HW tables' content.
This part of API helps to list all supported tables.
In the near future, only the CT table is planned
to be used, so only one identifier for this table
was added to the efx.
New table IDs will be added as needed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 15 ++++
 drivers/common/sfc_efx/base/efx_table.c | 94 +++++++++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build |  1 +
 drivers/common/sfc_efx/version.map      |  2 +
 4 files changed, 112 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_table.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 520674a602..2de08d1230 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5070,6 +5070,21 @@ efx_nic_dma_map(
 	__in		size_t len,
 	__out		efsys_dma_addr_t *nic_addrp);
 
+/* Unique IDs for HW tables */
+typedef enum efx_table_id_e {
+	EFX_TABLE_ID_CONNTRACK = 0x10300,
+} efx_table_id_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
new file mode 100644
index 0000000000..7cfdfea36e
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+	__checkReturn				efx_rc_t
+efx_table_list(
+	__in					efx_nic_t *enp,
+	__in					uint32_t entry_ofst,
+	__out_opt				unsigned int *total_n_tablesp,
+	__out_ecount_opt(n_table_ids)		efx_table_id_t *table_ids,
+	__in					unsigned int n_table_ids,
+	__out_opt				unsigned int *n_table_ids_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_LIST_IN_LEN,
+	    MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table IDs */
+	EFX_STATIC_ASSERT(EFX_TABLE_ID_CONNTRACK == TABLE_ID_CONNTRACK_TABLE);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((n_table_ids != 0) &&
+	   ((table_ids == NULL) || (n_table_ids_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_LIST;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_LIST_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, entry_ofst);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_LIST_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	if (total_n_tablesp != NULL)
+		*total_n_tablesp = MCDI_OUT_DWORD(req, TABLE_LIST_OUT_N_TABLES);
+
+	n_entries = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(req.emr_out_length_used);
+
+	if (table_ids != NULL) {
+		if (n_entries > n_table_ids) {
+			rc = ENOMEM;
+			goto fail5;
+		}
+
+		for (i = 0; i < n_entries; i++) {
+			table_ids[i] = MCDI_OUT_INDEXED_DWORD(req,
+			    TABLE_LIST_OUT_TABLE_ID, i);
+		}
+	}
+
+	if (n_table_ids_writtenp != NULL)
+		*n_table_ids_writtenp = n_entries;
+
+	return (0);
+
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index ff7f33fb44..7fc04aa57b 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -16,6 +16,7 @@ sources = [
         'efx_lic.c',
         'efx_mac.c',
         'efx_mae.c',
+        'efx_table.c',
         'efx_mcdi.c',
         'efx_mon.c',
         'efx_nic.c',
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index aabc354118..5717cc0ed2 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -232,6 +232,8 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_list;
+
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
 	efx_tunnel_config_udp_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 04/34] common/sfc_efx/base: add macro to get indexed QWORD field
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (2 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
                     ` (32 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Extend MCDI macros to manipulate with fields in indexed QWORDs.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
---
 drivers/common/sfc_efx/base/efx_mcdi.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 14a3833567..f13bf43da6 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -504,6 +504,10 @@ efx_mcdi_set_nic_addr_regions(
 	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
 			(_idx)), _field)
 
+#define	MCDI_OUT_INDEXED_QWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_QWORD_FIELD(*(MCDI_OUT2(_emr, efx_qword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_OUT_INDEXED_STRUCT_MEMBER(_emr, _type, _arr_ofst, _idx,	\
 		_member_ofst)						\
 	((_type *)(MCDI_OUT2(_emr, uint8_t, _arr_ofst) +		\
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 05/34] common/sfc_efx/base: add API to get HW table desc
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (3 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
                     ` (31 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Table's descriptor and fields' descriptors can be taken
by table ID using a new API.
In the near future, only the CT table is planned
to be used, so only fields that are required for these
purposes were added to the efx.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       |  67 +++++++
 drivers/common/sfc_efx/base/efx_table.c | 256 ++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |   3 +
 3 files changed, 326 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 2de08d1230..e7988e3657 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5085,6 +5085,73 @@ efx_table_list(
 	__in					unsigned int n_table_ids,
 	__out_opt				unsigned int *n_table_ids_writtenp);
 
+LIBEFX_API
+extern	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void);
+
+LIBEFX_API
+extern	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id);
+
+/* Unique IDs for table fields */
+typedef enum efx_table_field_id_e {
+	EFX_TABLE_FIELD_ID_UNUSED = 0x0,
+	EFX_TABLE_FIELD_ID_COUNTER_ID = 0xa,
+	EFX_TABLE_FIELD_ID_ETHER_TYPE = 0x1c,
+	EFX_TABLE_FIELD_ID_SRC_IP = 0x1d,
+	EFX_TABLE_FIELD_ID_DST_IP = 0x1e,
+	EFX_TABLE_FIELD_ID_IP_PROTO = 0x20,
+	EFX_TABLE_FIELD_ID_SRC_PORT = 0x21,
+	EFX_TABLE_FIELD_ID_DST_PORT = 0x22,
+	EFX_TABLE_FIELD_ID_NAT_PORT = 0x7a,
+	EFX_TABLE_FIELD_ID_NAT_IP = 0x7b,
+	EFX_TABLE_FIELD_ID_NAT_DIR = 0x7c,
+	EFX_TABLE_FIELD_ID_CT_MARK = 0x7d,
+} efx_table_field_id_t;
+
+/* Table fields mask types */
+typedef enum efx_table_field_mask_type_e {
+	EFX_TABLE_FIELD_MASK_NEVER = 0x0,
+	EFX_TABLE_FIELD_MASK_EXACT = 0x1,
+} efx_table_field_mask_type_t;
+
+typedef struct efx_table_field_desc_s {
+	efx_table_field_id_t		field_id;
+	uint16_t			lbn;
+	uint16_t			width;
+	efx_table_field_mask_type_t	mask_type;
+	uint8_t				scheme;
+} efx_table_field_descriptor_t;
+
+/* Types of HW tables */
+typedef enum efx_table_type_e {
+	/* Exact match to all key fields of table entry. */
+	EFX_TABLE_TYPE_BCAM = 0x2,
+} efx_table_type_t;
+
+typedef struct efx_table_descriptor_s {
+	efx_table_type_t	type;
+	uint16_t		key_width;
+	uint16_t		resp_width;
+	/* Number of key's fields to match data */
+	uint16_t		n_key_fields;
+	/* Number of fields in match response */
+	uint16_t		n_resp_fields;
+} efx_table_descriptor_t;
+
+LIBEFX_API
+extern	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 7cfdfea36e..c5657ddff7 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -6,6 +6,11 @@
 #include "efx.h"
 #include "efx_impl.h"
 
+/* List of HW tables that have support in efx */
+static const efx_table_id_t efx_supported_table_ids[] = {
+	EFX_TABLE_ID_CONNTRACK,
+};
+
 	__checkReturn				efx_rc_t
 efx_table_list(
 	__in					efx_nic_t *enp,
@@ -80,6 +85,257 @@ efx_table_list(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn		size_t
+efx_table_supported_num_get(
+	__in			void)
+{
+	return (EFX_ARRAY_SIZE(efx_supported_table_ids));
+}
+
+	__checkReturn		boolean_t
+efx_table_is_supported(
+	__in			efx_table_id_t table_id)
+{
+	size_t i;
+
+	for (i = 0; i < efx_table_supported_num_get(); i++) {
+		if (efx_supported_table_ids[i] == table_id)
+			return (B_TRUE);
+	}
+
+	return (B_FALSE);
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_ct_desc_fields_check(
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+	efx_rc_t rc;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		switch (fields_descsp[i].field_id) {
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+		case EFX_TABLE_FIELD_ID_DST_IP:
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
+				rc = EINVAL;
+				goto fail1;
+			}
+			break;
+		/*
+		 * TODO:
+		 * All fields in the CT table have EXACT mask.
+		 * All the response field descriptors must have the EXACT mask.
+		 * In the current implementation, only the Ethertype, source and
+		 * destination IP address, IP protocol, and source and destination IP
+		 * are used for the lookup by the key.
+		 * FW could use the NEVER mask for the fields in the key that are not
+		 * used for the lookup.
+		 * As an alternative, a new mask could be added for these fields,
+		 * like EXACT_NOT_USED.
+		 */
+		default:
+			if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
+			    (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
+				rc = EINVAL;
+				goto fail2;
+			}
+			break;
+		}
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_table_desc_fields_check(
+	__in				efx_table_id_t table_id,
+	__in_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	efx_rc_t rc;
+
+	switch (table_id) {
+	case EFX_TABLE_ID_CONNTRACK:
+		rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
+		if (rc != 0)
+			goto fail1;
+		break;
+	default:
+		break;
+	}
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static					void
+efx_table_desc_fields_get(
+	__in				const efx_mcdi_req_t *req,
+	__out_ecount(n_fields_descs)	efx_table_field_descriptor_t *fields_descsp,
+	__in				unsigned int n_fields_descs)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields_descs; i++) {
+		fields_descsp[i].field_id = (efx_table_field_id_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
+
+		fields_descsp[i].lbn =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
+
+		fields_descsp[i].width =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
+
+		fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
+
+		fields_descsp[i].scheme =
+		    MCDI_OUT_INDEXED_QWORD_FIELD(*req,
+			TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
+	}
+}
+
+	__checkReturn				efx_rc_t
+efx_table_describe(
+	__in					efx_nic_t *enp,
+	__in					efx_table_id_t table_id,
+	__in					uint32_t field_offset,
+	__out_opt				efx_table_descriptor_t *table_descp,
+	__out_ecount_opt(n_field_descs)		efx_table_field_descriptor_t *fields_descs,
+	__in					unsigned int n_field_descs,
+	__out_opt				unsigned int *n_field_descs_writtenp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_entries;
+	efx_mcdi_req_t req;
+	unsigned int i;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
+	    MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
+
+	/* Ensure EFX and MCDI use same values for table types */
+	EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
+
+	/* Ensure EFX and MCDI use same values for table fields */
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
+	EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (!efx_table_is_supported(table_id)) {
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if ((n_field_descs != 0) &&
+	    ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	if (table_descp != NULL) {
+		table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_TYPE);
+		table_descp->key_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
+		table_descp->resp_width = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
+		table_descp->n_key_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
+		table_descp->n_resp_fields = MCDI_OUT_WORD(
+		    req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
+	}
+
+	n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
+
+	if (fields_descs != NULL) {
+		if (n_entries > n_field_descs) {
+			rc = ENOMEM;
+			goto fail6;
+		}
+
+		efx_table_desc_fields_get(&req, fields_descs, n_entries);
+		rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
+		if (rc != 0)
+			goto fail7;
+	}
+
+	if (n_field_descs_writtenp != NULL)
+		*n_field_descs_writtenp = n_entries;
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 5717cc0ed2..a87cb1bba5 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -232,7 +232,10 @@ INTERNAL {
 	efx_sram_buf_tbl_clear;
 	efx_sram_buf_tbl_set;
 
+	efx_table_describe;
+	efx_table_is_supported;
 	efx_table_list;
+	efx_table_supported_num_get;
 
 	efx_tunnel_config_clear;
 	efx_tunnel_config_udp_add;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 06/34] common/sfc_efx/base: add API to insert data to HW table
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (4 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
                     ` (30 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev
  Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov,
	Viacheslav Galaktionov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to insert data to any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Viacheslav Galaktionov <viacheslav.galaktionov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 16 +++++
 drivers/common/sfc_efx/base/efx_table.c | 79 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 96 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index e7988e3657..90d86c70dd 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5152,6 +5152,22 @@ efx_table_describe(
 	__in					unsigned int n_field_descs,
 	__out_opt				unsigned int *n_field_descs_writtenp);
 
+/* Maximum possible size of data for manipulation of the tables */
+#define EFX_TABLE_ENTRY_LENGTH_MAX	1008
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index c5657ddff7..6ebb92e83b 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -338,6 +338,85 @@ efx_table_describe(
 	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_insert(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t priority,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in				uint16_t resp_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_INSERT_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_INSERT_IN_LENMAX  * sizeof(uint32_t)) ==
+	    EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_INSERT_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_INSERT_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_INSERT_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_PRIORITY, priority);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_WIDTH, mask_width);
+	MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_RESP_WIDTH, resp_width);
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_INSERT_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index a87cb1bba5..2be519e0e1 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
 	efx_table_supported_num_get;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 07/34] common/sfc_efx/base: add API to delete entry from HW table
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (5 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
                     ` (29 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

API allows to delete entry from any supported HW table.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h       | 11 ++++
 drivers/common/sfc_efx/base/efx_table.c | 77 +++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map      |  1 +
 3 files changed, 89 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 90d86c70dd..49f807823e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -5168,6 +5168,17 @@ efx_table_entry_insert(
 	__in_bcount(data_size)		uint8_t *entry_datap,
 	__in				unsigned int data_size);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_table.c b/drivers/common/sfc_efx/base/efx_table.c
index 6ebb92e83b..13a12a116e 100644
--- a/drivers/common/sfc_efx/base/efx_table.c
+++ b/drivers/common/sfc_efx/base/efx_table.c
@@ -419,6 +419,83 @@ efx_table_entry_insert(
 
 fail4:
 	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_table_entry_delete(
+	__in				efx_nic_t *enp,
+	__in				efx_table_id_t table_id,
+	__in				uint16_t mask_id,
+	__in				uint16_t key_width,
+	__in				uint16_t mask_width,
+	__in_bcount(data_size)		uint8_t *entry_datap,
+	__in				unsigned int data_size)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	unsigned int n_dwords;
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2,
+	    MC_CMD_TABLE_DELETE_OUT_LEN);
+
+	/*
+	 * Ensure  MCDI number of 32bit units matches EFX maximum possible
+	 * data in bytes.
+	 */
+	EFX_STATIC_ASSERT((MC_CMD_TABLE_DELETE_IN_LENMAX  * sizeof(uint32_t)) ==
+		EFX_TABLE_ENTRY_LENGTH_MAX);
+
+	if (encp->enc_table_api_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((data_size % sizeof(uint32_t)) != 0) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	n_dwords = data_size / sizeof(uint32_t);
+
+	req.emr_cmd = MC_CMD_TABLE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_TABLE_DELETE_IN_LEN(n_dwords);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_TABLE_DELETE_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, TABLE_DELETE_IN_TABLE_ID, (uint32_t)table_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_ID, mask_id);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_KEY_WIDTH, key_width);
+	MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_WIDTH, mask_width);
+
+
+	memcpy(MCDI_IN2(req, uint8_t, TABLE_DELETE_IN_DATA), entry_datap, data_size);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 2be519e0e1..d083a54a03 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -233,6 +233,7 @@ INTERNAL {
 	efx_sram_buf_tbl_set;
 
 	efx_table_describe;
+	efx_table_entry_delete;
 	efx_table_entry_insert;
 	efx_table_is_supported;
 	efx_table_list;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 08/34] net/sfc: add MCDI wrappers for BCAM tables
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (6 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
                     ` (28 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

A "table" is structure used for lookups, consisting of a set of
entries which can be matched against an N-bit "request", to
return either a "hit" with an M-bit "response", or a "miss" if
there is no match. There are a number of HW tables of various
types that could be used in MAE.

In some types of table the entry may also be associated with an
N-bit "mask", allowing some bits of the request to be treated as
don't-care, and an integer "priority" to determine which entry is
used if more than one matches.

BCAM tables don't support "mask" and "priority", so the
corresponding fields must be zeroed.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_tbls.h | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.h

diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
new file mode 100644
index 0000000000..302f67224c
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBLS_H
+#define _SFC_TBLS_H
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Table types:
+ *   CAM - Content addressable memory
+ *  BCAM - Binary CAM
+ *  TCAM - Ternary CAM
+ * STCAM - Semi-ternary CAM
+ *
+ * Short description:
+ * TCAM:  Each entry has a key, mask, response and priority. An entry matches
+ *        when (key & mask) == (request & mask). In the case of multiple
+ *        matches, the entry with the highest priority wins; Each entry may
+ *        have its own mask, but TCAM table definitions may place constraints
+ *        on the possible masks allowed for each of the individual fields.
+ * STCAM: A limited form of TCAM in which only a limited number of masks and
+ *        associated priorities), up to some maximum fixed by the definition
+ *        of the table, may be in use at any one time.
+ * BCAM:  Each entry has only a key and response, with the whole request
+ *        matched against the key (like a typical hash table or "map").
+ * Direct (sometimes "DCAM", although it's not really content-addressable):
+ *        Essentially just an array, where the key bits are used simply as an
+ *        index.
+ */
+
+/* Priority is used only for TCAM or STCAM, use 0 in case of BCAM */
+#define SFC_TBLS_BCAM_PRIORITY		0
+
+/* Mask ID is used only for STCAM with ALLOC_MASKS flag, use 0 for BCAM */
+#define SFC_TBLS_BCAM_MASK_ID		0
+
+/* Mask is used only for STCAM */
+#define SFC_TBLS_BCAM_MASK_WIDTH	0
+
+static inline int
+sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_insert(enp, table_id, SFC_TBLS_BCAM_PRIORITY,
+				      SFC_TBLS_BCAM_MASK_ID, key_width,
+				      SFC_TBLS_BCAM_MASK_WIDTH, resp_width,
+				      data, data_size);
+}
+
+static inline int
+sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
+			   uint8_t *data, unsigned int data_size)
+{
+	return efx_table_entry_delete(enp, table_id, SFC_TBLS_BCAM_MASK_ID,
+				      key_width, SFC_TBLS_BCAM_MASK_WIDTH,
+				      data, data_size);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_TBLS_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 09/34] net/sfc: add functions to manipulate MCDI table fields
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (7 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 10/34] net/sfc: attach to HW table API Ivan Malov
                     ` (27 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

Implemented functions that help to fill user data for
manipulation with HW tables in the required format.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |   1 +
 drivers/net/sfc/sfc_tbls.c  | 147 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbls.h  | 136 +++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_tbls.c

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c2d8430810..39c7f24764 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -87,6 +87,7 @@ sources = files(
         'sfc_tso.c',
         'sfc_filter.c',
         'sfc_switch.c',
+        'sfc_tbls.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
new file mode 100644
index 0000000000..536cf689ba
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc_tbls.h"
+#include "sfc_debug.h"
+
+#include <rte_ip.h>
+
+/* Number of bits in uint32_t type */
+#define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
+
+static uint32_t
+sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t mask;
+
+	SFC_ASSERT(width <= SFC_TBLS_U32_BITS);
+
+	if (width == SFC_TBLS_U32_BITS)
+		return value;
+
+	mask = RTE_LEN2MASK(width, uint32_t);
+	value &= mask;
+
+	if (lbn != 0) {
+		mask <<= lbn;
+		value <<= lbn;
+	}
+
+	return (in & (~mask)) | value;
+}
+
+void
+sfc_tbls_field_set_u32(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint32_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	if (lbn + width <= SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, lbn, width, value);
+	} else {
+		*data = sfc_tbls_field_update(*data, lbn,
+					      SFC_TBLS_U32_BITS - lbn, value);
+		value >>= SFC_TBLS_U32_BITS - lbn;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+		*data = sfc_tbls_field_update(*data, 0,
+					      width + lbn - SFC_TBLS_U32_BITS,
+					      value);
+	}
+}
+
+void
+sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, uint16_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      uint16_t width, uint8_t value)
+{
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value);
+}
+
+void
+sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		      __rte_unused uint16_t width, const uint32_t *ip)
+{
+	unsigned int i;
+	size_t ipv6_addr_len = RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr);
+
+	/*
+	 * The same 128-bit container is used to store either
+	 * an IPv4 or an IPv6 address, with an IPv4 address
+	 * assumed to have 12 trailing zeroes.
+	 */
+	SFC_ASSERT(width == ipv6_addr_len * CHAR_BIT);
+
+	for (i = 0; i < ipv6_addr_len / sizeof(*ip); i++) {
+		sfc_tbls_field_set_u32(data, data_size, lbn,
+				       SFC_TBLS_U32_BITS, ip[i]);
+		lbn += SFC_TBLS_U32_BITS;
+	}
+}
+
+void
+sfc_tbls_field_set_u64(uint32_t data[], __rte_unused unsigned int data_size,
+		       uint16_t lbn, uint16_t width, uint64_t value)
+{
+	uint32_t data_offset = 0;
+
+	if (lbn >= SFC_TBLS_U32_BITS) {
+		data_offset = lbn / SFC_TBLS_U32_BITS;
+
+		SFC_ASSERT(data_offset < data_size);
+
+		data += data_offset;
+		lbn %= SFC_TBLS_U32_BITS;
+	}
+
+	*data = sfc_tbls_field_update(*data, lbn, SFC_TBLS_U32_BITS - lbn, value);
+	value >>= SFC_TBLS_U32_BITS - lbn;
+	width -= SFC_TBLS_U32_BITS - lbn;
+
+	data_offset++;
+	SFC_ASSERT(data_offset < data_size);
+
+	data++;
+
+	if (width > SFC_TBLS_U32_BITS) {
+		*data = sfc_tbls_field_update(*data, 0, SFC_TBLS_U32_BITS, value);
+		value >>= SFC_TBLS_U32_BITS;
+		width -= SFC_TBLS_U32_BITS;
+
+		data_offset++;
+		SFC_ASSERT(data_offset < data_size);
+
+		data++;
+	}
+
+	*data = sfc_tbls_field_update(*data, 0, width, value);
+}
+
+void
+sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size, uint16_t lbn,
+		       uint16_t width, bool value)
+{
+	SFC_ASSERT(width == 1);
+
+	sfc_tbls_field_set_u32(data, data_size, lbn, width, value ? 1 : 0);
+}
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 302f67224c..74bdfab476 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -63,6 +63,142 @@ sfc_tbls_bcam_entry_delete(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key
 				      data, data_size);
 }
 
+/**
+ * All manipulations with HW tables entries require forming
+ * a key and response.
+ * The key and response fields follow, consecutively, each
+ * packed as follows:
+ *  - the key/response is logically treated as a single wide N-bit value;
+ *  - fields have been placed in these logical values per the "lbn" and "width"
+ *    information from the table field descriptors;
+ *  - the wide N-bit value is padded at the MSB end up to a 32-bit boundary;
+ *  - the values are put into the table op request with bits[31:0] of the wide
+ *    value in the first 32-bit word, bits[63:32] in the second 32-bit word, etc.
+ *
+ * Below is an API that helps to form  MCDI insertion/deletion request.
+ * Workflow:
+ * 1) Allocate an array of EFX_TABLE_ENTRY_LENGTH_MAX bytes.
+ * 2) Read a descriptor of the table that you want to use.
+ * 3) Fill the array using sfc_tbls_field_set_* functions to form a key.
+ *    Each field of the key has LBN and width. This information can be
+ *    found in a field's descriptor.
+ * 4) Use sfc_tbls_next_req_fields() to get a pointer where the response
+ *    must start. It's required as the key and response need to be
+ *    zero-padded at the MSB end to multiples of 32 bits.
+ * 5) Fill the response the same way.
+ * 6) Use sfc_tbls_next_req_fields() to get the end of the data request.
+ *    It will help you to get the real size of the data request.
+ */
+
+/**
+ * Get a pointer to the beginning of the next 32-bit wide fields
+ * that go after a given width.
+ * It should be used to get a pointer to the response's start and the end
+ * of the data for an MCDI request.
+ *
+ * @param data		Pointer to the data to make an offset from
+ * @param width		Width of fields to offset
+ *
+ * @note @p width is expected to be a key's or response's size.
+ *
+ * @return Pointer to the beginning of the next field.
+ */
+static inline uint32_t *
+sfc_tbls_next_req_fields(uint32_t *data, uint16_t width)
+{
+	return data + EFX_DIV_ROUND_UP(width, sizeof(*data) * CHAR_BIT);
+}
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint32_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u32(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint32_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint16_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u16(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint16_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint8_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u8(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, uint8_t value);
+
+/**
+ * Insert IP address into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param ip		IP address to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_ip(uint32_t data[], unsigned int data_size,
+			   uint16_t lbn, uint16_t width, const uint32_t *ip);
+
+/**
+ * Insert value into a field in the data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		uint64_t value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_u64(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, uint64_t value);
+
+/**
+ * Insert value into a field in the @p data buffer starting at
+ * bit offset @p lbn and containing @p width bits.
+ *
+ * @param data		Data buffer
+ * @param data_size	Size of the data buffer
+ * @param lbn		Offset
+ * @param width		Width of @p value in bits
+ * @param value		Bit value to insert
+ *
+ * @note @p width and @p lbn must to be obtained from the field's descriptor.
+ */
+void sfc_tbls_field_set_bit(uint32_t data[], unsigned int data_size,
+			    uint16_t lbn, uint16_t width, bool value);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 10/34] net/sfc: attach to HW table API
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (8 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
                     ` (26 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The patch adds APIs to initialise, manipulate and finalise
HW tables API-specific context in NIC control structure.
The context itself will be used to store HW tables-related info,
like table descriptors and field descriptors.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build          |   4 +-
 drivers/net/sfc/sfc.c                |  18 +-
 drivers/net/sfc/sfc.h                |   2 +
 drivers/net/sfc/sfc_tbl_meta.c       |  71 ++++++++
 drivers/net/sfc/sfc_tbl_meta.h       |  37 ++++
 drivers/net/sfc/sfc_tbl_meta_cache.c | 253 +++++++++++++++++++++++++++
 drivers/net/sfc/sfc_tbl_meta_cache.h |  25 +++
 drivers/net/sfc/sfc_tbls.c           |  60 +++++++
 drivers/net/sfc/sfc_tbls.h           |  81 +++++++++
 9 files changed, 549 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta.h
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.c
 create mode 100644 drivers/net/sfc/sfc_tbl_meta_cache.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 39c7f24764..c9d4264674 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -71,7 +71,7 @@ if not cc.links(atomic_check_code)
     ext_deps += libatomic_dep
 endif
 
-deps += ['common_sfc_efx', 'bus_pci']
+deps += ['common_sfc_efx', 'bus_pci', 'hash']
 sources = files(
         'sfc_ethdev.c',
         'sfc_kvargs.c',
@@ -88,6 +88,8 @@ sources = files(
         'sfc_filter.c',
         'sfc_switch.c',
         'sfc_tbls.c',
+        'sfc_tbl_meta.c',
+        'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 22753e3417..a56521696a 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -491,6 +491,10 @@ sfc_try_start(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_ev_start;
 
+	rc = sfc_tbls_start(sa);
+	if (rc != 0)
+		goto fail_tbls_start;
+
 	rc = sfc_port_start(sa);
 	if (rc != 0)
 		goto fail_port_start;
@@ -526,9 +530,12 @@ sfc_try_start(struct sfc_adapter *sa)
 fail_rx_start:
 	sfc_port_stop(sa);
 
-fail_port_start:
+fail_tbls_start:
 	sfc_ev_stop(sa);
 
+fail_port_start:
+	sfc_tbls_stop(sa);
+
 fail_ev_start:
 	sfc_intr_stop(sa);
 
@@ -626,6 +633,7 @@ sfc_stop(struct sfc_adapter *sa)
 	sfc_tx_stop(sa);
 	sfc_rx_stop(sa);
 	sfc_port_stop(sa);
+	sfc_tbls_stop(sa);
 	sfc_ev_stop(sa);
 	sfc_intr_stop(sa);
 	efx_nic_fini(sa->nic);
@@ -983,6 +991,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_attach;
 
+	rc = sfc_tbls_attach(sa);
+	if (rc != 0)
+		goto fail_tables_attach;
+
 	rc = sfc_mae_switchdev_init(sa);
 	if (rc != 0)
 		goto fail_mae_switchdev_init;
@@ -1025,6 +1037,9 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_mae_switchdev_fini(sa);
 
 fail_mae_switchdev_init:
+	sfc_tbls_detach(sa);
+
+fail_tables_attach:
 	sfc_mae_detach(sa);
 
 fail_mae_attach:
@@ -1088,6 +1103,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
+	sfc_tbls_detach(sa);
 	sfc_mae_detach(sa);
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 730d054aea..6b301aad60 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -31,6 +31,7 @@
 #include "sfc_flow_tunnel.h"
 #include "sfc_sriov.h"
 #include "sfc_mae.h"
+#include "sfc_tbls.h"
 #include "sfc_dp.h"
 #include "sfc_sw_stats.h"
 #include "sfc_repr_proxy.h"
@@ -244,6 +245,7 @@ struct sfc_adapter {
 	struct sfc_ft_ctx		ft_ctx_pool[SFC_FT_MAX_NTUNNELS];
 	struct sfc_filter		filter;
 	struct sfc_mae			mae;
+	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
 	struct sfc_flow_list		flow_list;
diff --git a/drivers/net/sfc/sfc_tbl_meta.c b/drivers/net/sfc/sfc_tbl_meta.c
new file mode 100644
index 0000000000..997082fd74
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_tbl_meta.h"
+#include "sfc_tbl_meta_cache.h"
+
+const struct sfc_tbl_meta *
+sfc_tbl_meta_lookup(struct sfc_adapter *sa, efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta;
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return NULL;
+
+	rc = rte_hash_lookup_data(tables->meta.cache, (const void *)&table_id,
+				  (void **)&meta);
+	if (rc < 0)
+		return NULL;
+
+	SFC_ASSERT(meta != NULL);
+	SFC_ASSERT(meta->table_id == table_id);
+
+	return meta;
+}
+
+int
+sfc_tbl_meta_init(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return 0;
+
+	rc = sfc_tbl_meta_cache_ctor(&meta->cache);
+	if (rc != 0)
+		return rc;
+
+	rc = sfc_tbl_meta_cache_update(meta->cache, sa->nic);
+	if (rc != 0) {
+		sfc_tbl_meta_cache_dtor(&meta->cache);
+		return rc;
+	}
+
+	return 0;
+}
+
+void
+sfc_tbl_meta_fini(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	struct sfc_tbl_meta_cache *meta = &tables->meta;
+
+	if (meta->cache == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(tables->status == SFC_TBLS_STATUS_SUPPORTED);
+
+	sfc_tbl_meta_cache_dtor(&meta->cache);
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta.h b/drivers/net/sfc/sfc_tbl_meta.h
new file mode 100644
index 0000000000..7d39957514
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_H
+#define _SFC_TBL_META_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Metadata about table layout */
+struct sfc_tbl_meta {
+	efx_table_id_t			table_id;
+	efx_table_descriptor_t		descriptor;
+	efx_table_field_descriptor_t	*keys;
+	efx_table_field_descriptor_t	*responses;
+};
+
+struct sfc_tbl_meta_cache {
+	struct rte_hash	*cache;
+};
+
+struct sfc_adapter;
+
+const struct sfc_tbl_meta *sfc_tbl_meta_lookup(struct sfc_adapter *sa,
+					       efx_table_id_t table_id);
+
+int sfc_tbl_meta_init(struct sfc_adapter *sa);
+void sfc_tbl_meta_fini(struct sfc_adapter *sa);
+
+#endif /* _SFC_TBL_META_H */
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.c b/drivers/net/sfc/sfc_tbl_meta_cache.c
new file mode 100644
index 0000000000..bffbc4a158
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.c
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include <rte_malloc.h>
+#include <rte_jhash.h>
+
+#include "sfc_tbl_meta_cache.h"
+#include "sfc_debug.h"
+
+/* The minimal size of the table meta cache */
+#define SFC_TBL_META_CACHE_SIZE_MIN	8
+
+int
+sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache)
+{
+	size_t cache_size = RTE_MAX((unsigned int)SFC_TBL_META_CACHE_SIZE_MIN,
+				    efx_table_supported_num_get());
+	struct rte_hash *cache = NULL;
+	const struct rte_hash_parameters hash_params = {
+		.name       = "meta_hash_table",
+		.hash_func  = rte_jhash,
+		.entries    = cache_size,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(efx_table_id_t),
+	};
+
+	cache = rte_hash_create(&hash_params);
+	if (cache == NULL)
+		return -ENOMEM;
+
+	*ref_cache = cache;
+
+	return 0;
+}
+
+static void
+sfc_tbl_meta_cache_free(struct sfc_tbl_meta *meta)
+{
+	SFC_ASSERT(meta != NULL);
+
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+	rte_free(meta);
+}
+
+void
+sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache)
+{
+	struct rte_hash *cache = *ref_cache;
+	const void *next_key;
+	uint32_t iter = 0;
+	void *next_meta;
+
+	if (cache == NULL)
+		return;
+
+	while (rte_hash_iterate(cache, &next_key, &next_meta, &iter) >= 0)
+		sfc_tbl_meta_cache_free((struct sfc_tbl_meta *)next_meta);
+
+	rte_hash_free(cache);
+
+	*ref_cache = NULL;
+}
+
+/**
+ * Table descriptor contains information about the table's
+ * fields that can be associated with both the key and the response.
+ * Save these fields by separating the key from the response in
+ * appropriate places based on their lengths.
+ */
+static int
+sfc_tbl_meta_desc_fields_copy(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+			      efx_table_field_descriptor_t *fields,
+			      unsigned int total_n_fields)
+{
+	uint16_t n_key_fields = meta->descriptor.n_key_fields;
+	size_t field_size = sizeof(*fields);
+	unsigned int n_field_descs_written;
+	uint32_t field_offset;
+	int rc;
+
+	for (n_field_descs_written = 0, field_offset = 0;
+	     field_offset < total_n_fields;
+	     field_offset += n_field_descs_written) {
+		rc = efx_table_describe(enp, meta->table_id, field_offset, NULL,
+					fields, total_n_fields, &n_field_descs_written);
+		if (rc != 0)
+			return rc;
+
+		if (field_offset + n_field_descs_written > total_n_fields)
+			return -EINVAL;
+
+		if (field_offset < n_key_fields &&
+		    field_offset + n_field_descs_written > n_key_fields) {
+			/*
+			 * Some of the descriptors belong to key,
+			 * the other to response.
+			 */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, (n_key_fields - field_offset) * field_size);
+			rte_memcpy(meta->responses,
+				   RTE_PTR_ADD(fields,
+				   (n_key_fields - field_offset) * field_size),
+				   (field_offset + n_field_descs_written - n_key_fields) *
+				   field_size);
+		} else if (field_offset < n_key_fields) {
+			/* All fields belong to the key */
+			rte_memcpy(RTE_PTR_ADD(meta->keys, field_offset * field_size),
+				   fields, n_field_descs_written * field_size);
+		} else {
+			/* All fields belong to the response */
+			rte_memcpy(RTE_PTR_ADD(meta->responses,
+				   (field_offset - n_key_fields) * field_size),
+				   fields, n_field_descs_written * field_size);
+		}
+	}
+
+	return 0;
+}
+
+static int
+sfc_tbl_meta_desc_read(struct sfc_tbl_meta *meta, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	efx_table_field_descriptor_t *fields;
+	unsigned int total_n_fields;
+	int rc;
+
+	rc = efx_table_describe(enp, table_id, 0, &meta->descriptor, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	total_n_fields = meta->descriptor.n_key_fields + meta->descriptor.n_resp_fields;
+
+	fields = rte_calloc(NULL, total_n_fields, sizeof(*fields), 0);
+	if (fields == NULL)
+		return -ENOMEM;
+
+	meta->table_id = table_id;
+
+	meta->keys = rte_calloc("efx_table_key_field_descs",
+				meta->descriptor.n_key_fields,
+				sizeof(*meta->keys), 0);
+	if (meta->keys == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_keys;
+	}
+
+	meta->responses = rte_calloc("efx_table_response_field_descs",
+				     meta->descriptor.n_resp_fields,
+				     sizeof(*meta->responses), 0);
+	if (meta->responses == NULL) {
+		rc = -ENOMEM;
+		goto fail_alloc_responses;
+	}
+
+	rc = sfc_tbl_meta_desc_fields_copy(meta, enp, fields, total_n_fields);
+	if (rc != 0)
+		goto fail_copy_fields;
+
+	return 0;
+
+fail_copy_fields:
+	rte_free(meta->responses);
+fail_alloc_responses:
+	rte_free(meta->keys);
+fail_alloc_keys:
+	rte_free(fields);
+
+	return rc;
+}
+
+static int
+sfc_tbl_meta_cache_add(struct rte_hash *cache, efx_nic_t *enp,
+		       efx_table_id_t table_id)
+{
+	struct sfc_tbl_meta *meta = NULL;
+	int rc;
+
+	meta = rte_zmalloc("sfc_tbl_meta", sizeof(*meta), 0);
+	if (meta == NULL)
+		return -ENOMEM;
+
+	rc = sfc_tbl_meta_desc_read(meta, enp, table_id);
+	if (rc != 0)
+		goto fail_read_meta;
+
+	rc = rte_hash_add_key_data(cache, &table_id, meta);
+	if (rc != 0)
+		goto fail_add_key;
+
+	return 0;
+
+fail_add_key:
+	rte_free(meta->keys);
+	rte_free(meta->responses);
+fail_read_meta:
+	rte_free(meta);
+
+	return rc;
+}
+
+int
+sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp)
+{
+	efx_table_id_t *table_ids = NULL;
+	unsigned int n_table_ids_written;
+	unsigned int total_n_tables;
+	unsigned int n_table_ids;
+	uint32_t table_index;
+	unsigned int i;
+	int rc = 0;
+
+	rc = efx_table_list(enp, 0, &total_n_tables, NULL, 0, NULL);
+	if (rc != 0)
+		return rc;
+
+	table_ids = rte_calloc(NULL, total_n_tables, sizeof(*table_ids), 0);
+	if (table_ids == NULL)
+		return -ENOMEM;
+
+	n_table_ids = total_n_tables;
+
+	for (table_index = 0, n_table_ids_written = 0;
+	     table_index < total_n_tables;
+	     table_index += n_table_ids_written) {
+		rc = efx_table_list(enp, table_index, NULL,
+				    table_ids, n_table_ids, &n_table_ids_written);
+		if (rc != 0)
+			goto out;
+
+		if (table_index + n_table_ids_written > total_n_tables) {
+			rc = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < n_table_ids_written; i++, table_index++) {
+			if (!efx_table_is_supported(table_ids[i]))
+				continue;
+
+			rc = sfc_tbl_meta_cache_add(cache, enp, table_ids[i]);
+			if (rc != 0)
+				goto out;
+		}
+	}
+
+out:
+	rte_free(table_ids);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_tbl_meta_cache.h b/drivers/net/sfc/sfc_tbl_meta_cache.h
new file mode 100644
index 0000000000..2deff620a4
--- /dev/null
+++ b/drivers/net/sfc/sfc_tbl_meta_cache.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_TBL_META_CACHE_H
+#define _SFC_TBL_META_CACHE_H
+
+#include <rte_hash.h>
+
+#include "efx.h"
+
+#include "sfc_tbl_meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sfc_tbl_meta_cache_ctor(struct rte_hash **ref_cache);
+
+void sfc_tbl_meta_cache_dtor(struct rte_hash **ref_cache);
+
+int sfc_tbl_meta_cache_update(struct rte_hash *cache, efx_nic_t *enp);
+
+#endif /* _SFC_TBLS_DESC_CACHE_H */
diff --git a/drivers/net/sfc/sfc_tbls.c b/drivers/net/sfc/sfc_tbls.c
index 536cf689ba..3108955bc3 100644
--- a/drivers/net/sfc/sfc_tbls.c
+++ b/drivers/net/sfc/sfc_tbls.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2023 Advanced Micro Devices, Inc.
  */
 
+#include "sfc.h"
 #include "sfc_tbls.h"
 #include "sfc_debug.h"
 
@@ -11,6 +12,65 @@
 /* Number of bits in uint32_t type */
 #define SFC_TBLS_U32_BITS (sizeof(uint32_t) * CHAR_BIT)
 
+int
+sfc_tbls_attach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	const struct sfc_mae *mae = &sa->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	if (mae->status != SFC_MAE_STATUS_ADMIN ||
+	    !encp->enc_table_api_supported) {
+		tables->status = SFC_TBLS_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	tables->status = SFC_TBLS_STATUS_SUPPORTED;
+
+	rc = sfc_tbl_meta_init(sa);
+	if (rc != 0)
+		return rc;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_tbls_detach(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+
+	sfc_log_init(sa, "entry");
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		goto done;
+
+	sfc_tbl_meta_fini(sa);
+
+done:
+	sfc_log_init(sa, "done");
+
+	tables->status = SFC_TBLS_STATUS_UNKNOWN;
+}
+
+int
+sfc_tbls_start(struct sfc_adapter *sa)
+{
+	struct sfc_tbls *tables = &sa->hw_tables;
+	int rc;
+
+	if (tables->status == SFC_TBLS_STATUS_UNKNOWN) {
+		rc = sfc_tbls_attach(sa);
+		return rc;
+	}
+
+	return 0;
+}
+
 static uint32_t
 sfc_tbls_field_update(uint32_t in, uint16_t lbn, uint16_t width, uint32_t value)
 {
diff --git a/drivers/net/sfc/sfc_tbls.h b/drivers/net/sfc/sfc_tbls.h
index 74bdfab476..ff619e5141 100644
--- a/drivers/net/sfc/sfc_tbls.h
+++ b/drivers/net/sfc/sfc_tbls.h
@@ -8,6 +8,8 @@
 
 #include "efx.h"
 
+#include "sfc_tbl_meta.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -44,6 +46,85 @@ extern "C" {
 /* Mask is used only for STCAM */
 #define SFC_TBLS_BCAM_MASK_WIDTH	0
 
+/** Options for HW tables support status */
+enum sfc_tbls_status {
+	SFC_TBLS_STATUS_UNKNOWN = 0,
+	SFC_TBLS_STATUS_UNSUPPORTED,
+	SFC_TBLS_STATUS_SUPPORTED,
+};
+
+/**
+ * Entry point to access HW tables
+ *
+ * SFC driver can access hardware (HW) tables.
+ * Interaction with HW tables is done through the MCDI table access API
+ * that is implemented in EFX.
+ *
+ * In order to manipulate data on HW tables it's necessary to
+ * - discover the list of supported tables;
+ * - read a table descriptor to get details of the structure
+ *   of the table;
+ * - get named fields of the table;
+ * - insert/delete/update table entries based on given fields
+ *   and information about the table
+ *
+ * All table layout data should be saved in a cache.
+ * The cache allows to avoid getting the table descriptor each time when you want
+ * to manipulate table entries. It just contains the table
+ * descriptors and all associated data. The cache is based on the RTE hash map and
+ * it uses a table ID as a key.
+ * The sfc_tbl_meta library serves as a wrapper over the cache and allows to user
+ * to get all information about the tables without worrying about the cache.
+ *
+ * +------------------------+
+ * | Cache is uninitialized |<----------------------------------+
+ * +------------------------+					|
+ *	|							|
+ *	| sfc_attach()						|
+ *	| sfc_tbls_attach() -- (fail) -- sfc_tbls_detach()------+
+ *	V					^
+ * +------------------------+			|
+ * |  Cache is initialized  |			+-------+
+ * +------------------------+				|
+ *	| sfc_start()					|
+ *	| sfc_tbls_start() -- (fail) -- sfc_tbls_stop()-+
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | and valid              |				|
+ * +------------------------+				|
+ *	|						|
+ *	| sfc_restart()					|
+ *	V						|
+ * +------------------------+				|
+ * | Cache is initialized   |				|
+ * | but can be invalid     |				|
+ * +------------------------+---------------------------+
+ */
+struct sfc_tbls {
+	struct sfc_tbl_meta_cache	meta;
+	enum sfc_tbls_status		status;
+};
+
+struct sfc_adapter;
+
+static inline bool
+sfc_tbls_id_is_supported(struct sfc_adapter *sa,
+			 efx_table_id_t table_id)
+{
+	return (sfc_tbl_meta_lookup(sa, table_id) == NULL ? false : true);
+}
+
+int sfc_tbls_attach(struct sfc_adapter *sa);
+void sfc_tbls_detach(struct sfc_adapter *sa);
+int sfc_tbls_start(struct sfc_adapter *sa);
+
+static inline void
+sfc_tbls_stop(struct sfc_adapter *sa)
+{
+	sfc_tbls_detach(sa);
+}
+
 static inline int
 sfc_tbls_bcam_entry_insert(efx_nic_t *enp, efx_table_id_t table_id, uint16_t key_width,
 			   uint16_t resp_width, uint8_t *data, unsigned int data_size)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 11/34] net/sfc: add API to manage HW Conntrack table
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (9 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 10/34] net/sfc: attach to HW table API Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
                     ` (25 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Denis Pryazhennikov, Andy Moreton

From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>

The new API allows to manipulate entries in
the HW Conntrack table.
It uses a new Table Access API as a backend.

Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_mae_ct.c | 201 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae_ct.h |  68 ++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae_ct.c
 create mode 100644 drivers/net/sfc/sfc_mae_ct.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index c9d4264674..5adde68517 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -92,6 +92,7 @@ sources = files(
         'sfc_tbl_meta_cache.c',
         'sfc_mae.c',
         'sfc_mae_counter.c',
+        'sfc_mae_ct.c',
         'sfc_flow.c',
         'sfc_flow_rss.c',
         'sfc_flow_tunnel.c',
diff --git a/drivers/net/sfc/sfc_mae_ct.c b/drivers/net/sfc/sfc_mae_ct.c
new file mode 100644
index 0000000000..fd6819c8a5
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#include "sfc.h"
+#include "sfc_mae_ct.h"
+
+/* SF-123102-TC-1A § 10.6.3: Conntrack_Table key */
+static void
+sfc_mae_ct_key_to_mcdi_key(const sfc_mae_conntrack_key_t *key,
+			   const efx_table_field_descriptor_t *fields,
+			   unsigned int n_fields, uint32_t *mcdi_key,
+			   unsigned int key_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_IP_PROTO:
+			sfc_tbls_field_set_u8(mcdi_key, key_size, desc->lbn,
+					      desc->width, key->ip_proto);
+			break;
+		case EFX_TABLE_FIELD_ID_ETHER_TYPE:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->ether_type_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->src_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_PORT:
+			sfc_tbls_field_set_u16(mcdi_key, key_size, desc->lbn,
+					       desc->width, key->dst_port_le);
+			break;
+		case EFX_TABLE_FIELD_ID_SRC_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->src_addr_le);
+			break;
+		case EFX_TABLE_FIELD_ID_DST_IP:
+			sfc_tbls_field_set_ip(mcdi_key, key_size, desc->lbn,
+					      desc->width,
+					      (const uint32_t *)key->dst_addr_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+/* SF-123102-TC-1A § 10.6.4: Conntrack_Table response */
+static void
+sfc_mae_ct_response_to_mcdi_response(const sfc_mae_conntrack_response_t *response,
+				     const efx_table_field_descriptor_t *fields,
+				     unsigned int n_fields, uint32_t *mcdi_resp,
+				     unsigned int resp_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < n_fields; i++) {
+		const efx_table_field_descriptor_t *desc = &fields[i];
+
+		if (desc->mask_type == EFX_TABLE_FIELD_MASK_NEVER)
+			continue;
+
+		/* Fields of responses are always reported with the EXACT type. */
+		SFC_ASSERT(desc->mask_type == EFX_TABLE_FIELD_MASK_EXACT);
+
+		switch (desc->field_id) {
+		case EFX_TABLE_FIELD_ID_CT_MARK:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->ct_mark);
+			break;
+		case EFX_TABLE_FIELD_ID_COUNTER_ID:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->counter_id);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_DIR:
+			sfc_tbls_field_set_u8(mcdi_resp, resp_size, desc->lbn,
+					      desc->width, response->nat.dir_is_dst);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_IP:
+			sfc_tbls_field_set_u32(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.ip_le);
+			break;
+		case EFX_TABLE_FIELD_ID_NAT_PORT:
+			sfc_tbls_field_set_u16(mcdi_resp, resp_size, desc->lbn,
+					       desc->width, response->nat.port_le);
+			break;
+
+		default:
+			break;
+		}
+	}
+}
+
+int
+sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key,
+			 const sfc_mae_conntrack_response_t *response)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int response_size;
+	uint32_t *response_data;
+	unsigned int data_size;
+	unsigned int key_size;
+	uint32_t *start_data;
+	uint16_t resp_width;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+	resp_width = meta->descriptor.resp_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	response_data = sfc_tbls_next_req_fields(key_data, key_width);
+	end_data = sfc_tbls_next_req_fields(response_data, resp_width);
+
+	key_size = RTE_PTR_DIFF(response_data, key_data);
+	response_size = RTE_PTR_DIFF(end_data, response_data);
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields, key_data,
+				   key_size);
+	sfc_mae_ct_response_to_mcdi_response(response, meta->responses,
+					     meta->descriptor.n_resp_fields,
+					     response_data, response_size);
+
+	rc = sfc_tbls_bcam_entry_insert(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, resp_width, data,
+					data_size);
+
+	return rc;
+}
+
+int
+sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			 const sfc_mae_conntrack_key_t *key)
+{
+	const struct sfc_tbls *tables = &sa->hw_tables;
+	uint8_t data[EFX_TABLE_ENTRY_LENGTH_MAX] = {0};
+	const struct sfc_tbl_meta *meta = NULL;
+	unsigned int data_size;
+	uint32_t *start_data;
+	uint16_t key_width;
+	uint32_t *key_data;
+	uint32_t *end_data;
+	int rc = 0;
+
+	if (tables->status != SFC_TBLS_STATUS_SUPPORTED)
+		return -ENOTSUP;
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return -ENOTSUP;
+
+	meta = sfc_mae_conntrack_meta_lookup(sa);
+	if (meta == NULL)
+		return -ENOENT;
+
+	key_width = meta->descriptor.key_width;
+
+	start_data = (uint32_t *)data;
+	key_data = start_data;
+	end_data = sfc_tbls_next_req_fields(key_data, key_width);
+
+	data_size = RTE_PTR_DIFF(end_data, start_data);
+	SFC_ASSERT(data_size <= sizeof(data));
+
+	sfc_mae_ct_key_to_mcdi_key(key, meta->keys,
+				   meta->descriptor.n_key_fields,
+				   key_data, data_size);
+
+	rc = sfc_tbls_bcam_entry_delete(sa->nic, EFX_TABLE_ID_CONNTRACK,
+					key_width, data, data_size);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae_ct.h b/drivers/net/sfc/sfc_mae_ct.h
new file mode 100644
index 0000000000..b5a3181cd3
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae_ct.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ */
+
+#ifndef _SFC_MAE_CONNTRACK_H
+#define _SFC_MAE_CONNTRACK_H
+
+#include <stdbool.h>
+
+#include <rte_ip.h>
+
+#include "efx.h"
+
+#include "sfc_tbls.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sfc_mae_conntrack_key_s {
+	uint8_t		ip_proto;
+	uint16_t	ether_type_le;
+
+	uint16_t	src_port_le;
+	uint16_t	dst_port_le;
+
+	uint8_t		src_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, src_addr)];
+	uint8_t		dst_addr_le[RTE_SIZEOF_FIELD(struct rte_ipv6_hdr, dst_addr)];
+} sfc_mae_conntrack_key_t;
+
+typedef struct sfc_mae_conntrack_nat_s {
+	uint32_t	ip_le;
+	uint16_t	port_le;
+	bool		dir_is_dst;
+} sfc_mae_conntrack_nat_t;
+
+typedef struct sfc_mae_conntrack_response_s {
+	uint32_t		ct_mark;
+	sfc_mae_conntrack_nat_t	nat;
+	uint32_t		counter_id;
+} sfc_mae_conntrack_response_t;
+
+struct sfc_adapter;
+
+static inline bool
+sfc_mae_conntrack_is_supported(struct sfc_adapter *sa)
+{
+	return sfc_tbls_id_is_supported(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+static inline const struct sfc_tbl_meta *
+sfc_mae_conntrack_meta_lookup(struct sfc_adapter *sa)
+{
+	return sfc_tbl_meta_lookup(sa, EFX_TABLE_ID_CONNTRACK);
+}
+
+int sfc_mae_conntrack_insert(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key,
+			     const sfc_mae_conntrack_response_t *response);
+
+int sfc_mae_conntrack_delete(struct sfc_adapter *sa,
+			     const sfc_mae_conntrack_key_t *key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_CONNTRACK_H */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 12/34] net/sfc: make entry pointer optional in MAE resource helpers
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (10 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
                     ` (24 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Keep NULL object check in one place rather than repeat it in
all of the callers. That should make the code easier on eyes.
Future code for additional object types will follow this way.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 78 ++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 26 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e5e9257998..1928d58779 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -402,6 +402,9 @@ sfc_mae_outer_rule_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(rule->refcnt != 0);
 
@@ -429,11 +432,16 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_outer_rule *rule,
 			  efx_mae_match_spec_t *match_spec_action)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(rule->match_spec != NULL);
@@ -480,11 +488,16 @@ static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (rule == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -1057,6 +1070,9 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 {
 	struct sfc_mae *mae = &sa->mae;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(action_set->refcnt != 0);
 
@@ -1092,15 +1108,24 @@ static int
 sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			  struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
-	struct sfc_mae_mac_addr *dst_mac_addr = action_set->dst_mac_addr;
-	struct sfc_mae_mac_addr *src_mac_addr = action_set->src_mac_addr;
-	struct sfc_mae_counter_id *counters = action_set->counters;
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_encap_header *encap_header;
+	struct sfc_mae_mac_addr *dst_mac_addr;
+	struct sfc_mae_mac_addr *src_mac_addr;
+	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return 0;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	encap_header = action_set->encap_header;
+	dst_mac_addr = action_set->dst_mac_addr;
+	src_mac_addr = action_set->src_mac_addr;
+	counters = action_set->counters;
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
 		SFC_ASSERT(action_set->spec != NULL);
@@ -1167,11 +1192,16 @@ static void
 sfc_mae_action_set_disable(struct sfc_adapter *sa,
 			   struct sfc_mae_action_set *action_set)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
+	if (action_set == NULL)
+		return;
+
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	fw_rsrc = &action_set->fw_rsrc;
+
 	if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
@@ -1226,11 +1256,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 
-	if (spec_mae->outer_rule != NULL)
-		sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-
-	if (spec_mae->action_set != NULL)
-		sfc_mae_action_set_del(sa, spec_mae->action_set);
+	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
+	sfc_mae_action_set_del(sa, spec_mae->action_set);
 
 	if (spec_mae->match_spec != NULL)
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
@@ -2575,9 +2602,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
 						  &invalid_rule_id);
 	if (rc != 0) {
-		if (*rulep != NULL)
-			sfc_mae_outer_rule_del(sa, *rulep);
-
+		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
 
 		return rte_flow_error_set(error, rc,
@@ -3979,10 +4004,15 @@ static int
 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 				struct sfc_mae_outer_rule *rule)
 {
-	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
 	struct sfc_mae_outer_rule *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc;
 	struct sfc_mae *mae = &sa->mae;
 
+	if (rule == NULL)
+		return 0;
+
+	fw_rsrc = &rule->fw_rsrc;
+
 	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
 		/* An active rule is reused. It's class is wittingly valid. */
 		return 0;
@@ -4069,11 +4099,9 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (sa->state != SFC_ETHDEV_STARTED)
 		return EAGAIN;
 
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
-		if (rc != 0)
-			return rc;
-	}
+	rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
+	if (rc != 0)
+		return rc;
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
@@ -4139,8 +4167,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4175,8 +4202,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	if (outer_rule != NULL)
-		sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 13/34] net/sfc: turn flow create/destroy methods into lock wrappers
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (11 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
                     ` (23 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is useful to facilitate driver-internal flow rework.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 42 ++++++++++++++++++++++++++++++--------
 drivers/net/sfc/sfc_flow.h |  9 ++++++++
 2 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index fe1f5ba55f..432295ea62 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2610,16 +2610,32 @@ sfc_flow_create(struct rte_eth_dev *dev,
 		struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow *flow;
+
+	sfc_adapter_lock(sa);
+	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	sfc_adapter_unlock(sa);
+
+	return flow;
+}
+
+struct rte_flow *
+sfc_flow_create_locked(struct sfc_adapter *sa,
+		       const struct rte_flow_attr *attr,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow_error *error)
+{
 	struct rte_flow *flow = NULL;
 	int rc;
 
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
 	flow = sfc_flow_zmalloc(error);
 	if (flow == NULL)
 		goto fail_no_mem;
 
-	sfc_adapter_lock(sa);
-
-	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
@@ -2631,8 +2647,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 			goto fail_flow_insert;
 	}
 
-	sfc_adapter_unlock(sa);
-
 	return flow;
 
 fail_flow_insert:
@@ -2640,7 +2654,6 @@ sfc_flow_create(struct rte_eth_dev *dev,
 
 fail_bad_value:
 	sfc_flow_free(sa, flow);
-	sfc_adapter_unlock(sa);
 
 fail_no_mem:
 	return NULL;
@@ -2652,10 +2665,23 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 		 struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	int rc;
+
+	sfc_adapter_lock(sa);
+	rc = sfc_flow_destroy_locked(sa, flow, error);
+	sfc_adapter_unlock(sa);
+
+	return rc;
+}
+
+int
+sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			struct rte_flow_error *error)
+{
 	struct rte_flow *flow_ptr;
 	int rc = EINVAL;
 
-	sfc_adapter_lock(sa);
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
 		if (flow_ptr == flow)
@@ -2675,8 +2701,6 @@ sfc_flow_destroy(struct rte_eth_dev *dev,
 	sfc_flow_free(sa, flow);
 
 fail_bad_value:
-	sfc_adapter_unlock(sa);
-
 	return -rc;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 12875344b5..a3ca09f225 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -195,6 +195,15 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+					const struct rte_flow_attr *attr,
+					const struct rte_flow_item pattern[],
+					const struct rte_flow_action actions[],
+					struct rte_flow_error *error);
+
+int sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
+			    struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 14/34] net/sfc: let driver-internal flows use VF representor action
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (12 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
                     ` (22 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

In the case of VF <--> VF representor pairs, these flows can
only collect VF traffic, so let them use generic flow action
PORT_REPRESENTOR, as part of re-using generic flow mechanism.

Currently, it does not allow to access VF representors since
they have no unique HW logical ports (m-ports). They all sit
on the same (representor proxy) m-port, while demultiplexing
of traffic uses ingress (VF) m-port value in packet metadata.
Traffic from arbitrary sources cannot be identified this way.
But, for VF traffic, it should be right to make an exception.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c            | 25 +++++++++++++++++++------
 drivers/net/sfc/sfc_repr.c           | 20 ++++++++++++++++----
 drivers/net/sfc/sfc_repr_proxy.c     | 15 +++++++++++++++
 drivers/net/sfc/sfc_repr_proxy_api.h |  3 +++
 drivers/net/sfc/sfc_switch.c         |  7 ++-----
 drivers/net/sfc/sfc_switch.h         | 10 ++++++++++
 6 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 1928d58779..89fa75281f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1525,6 +1525,7 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 	const struct rte_flow_item_port_id *spec = NULL;
 	const struct rte_flow_item_port_id *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1556,8 +1557,10 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 					  "The port ID is too large");
 	}
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
-					     spec->id, &mport_sel);
+					     spec->id, type_mask, &mport_sel);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1590,6 +1593,7 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 	const struct rte_flow_item_ethdev *spec = NULL;
 	const struct rte_flow_item_ethdev *mask = NULL;
 	efx_mport_sel_t mport_sel;
+	unsigned int type_mask;
 	int rc;
 
 	if (ctx_mae->match_mport_set) {
@@ -1617,9 +1621,11 @@ sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
 
 	switch (item->type) {
 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
+		type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_switch_get_ethdev_mport(
 				ctx_mae->sa->mae.switch_domain_id,
-				spec->port_id, &mport_sel);
+				spec->port_id, type_mask, &mport_sel);
 		if (rc != 0) {
 			return rte_flow_error_set(error, rc,
 					RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -3529,6 +3535,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 {
 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
+	unsigned int type_mask;
 	efx_mport_sel_t mport;
 	uint16_t port_id;
 	int rc;
@@ -3538,8 +3545,10 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 
 	port_id = (conf->original != 0) ? sas->port_id : conf->id;
 
+	type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     port_id, &mport);
+					     port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			port_id, strerror(rc));
@@ -3558,14 +3567,14 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
 		const struct rte_flow_action_ethdev *conf,
-		efx_mae_actions_t *spec)
+		unsigned int type_mask, efx_mae_actions_t *spec)
 {
 	struct sfc_mae *mae = &sa->mae;
 	efx_mport_sel_t mport;
 	int rc;
 
 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-					     conf->port_id, &mport);
+					     conf->port_id, type_mask, &mport);
 	if (rc != 0) {
 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
 			conf->port_id, strerror(rc));
@@ -3641,6 +3650,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
+	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
@@ -3757,8 +3767,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
 				       bundle->actions_mask);
+
+		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
-				action->conf, spec);
+				action->conf, switch_port_type_mask, spec);
 		break;
 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index d4134ec91b..6c7727d569 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -933,15 +933,26 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 	struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
 	struct sfc_mae_switch_port_request switch_port_request;
 	efx_mport_sel_t ethdev_mport_sel;
+	efx_mport_id_t proxy_mport_id;
 	struct sfc_repr *sr;
 	int ret;
 
 	/*
-	 * Currently there is no mport we can use for representor's
-	 * ethdev. Use an invalid one for now. This way representors
-	 * can be instantiated.
+	 * For each representor, a driver-internal flow has to be installed
+	 * in order to direct traffic coming from the represented entity to
+	 * the "representor proxy". Such internal flows need to find ethdev
+	 * mport by ethdev ID of the representors in question to specify in
+	 * delivery action. So set the representor ethdev's mport to that
+	 * of the "representor proxy" in below switch port request.
 	 */
-	efx_mae_mport_invalid(&ethdev_mport_sel);
+	sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
+
+	ret = efx_mae_mport_by_id(&proxy_mport_id, &ethdev_mport_sel);
+	if (ret != 0) {
+		SFC_GENERIC_LOG(ERR,
+			"%s() failed to get repr proxy mport by ID", __func__);
+		goto fail_get_selector;
+	}
 
 	memset(&switch_port_request, 0, sizeof(switch_port_request));
 	switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
@@ -1033,6 +1044,7 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
 
 fail_create_port:
 fail_mae_assign_switch_port:
+fail_get_selector:
 	SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
 	return ret;
 }
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 4ba7683370..74c3494c35 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -1708,3 +1708,18 @@ sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id, uint16_t repr_id,
 
 	return rc;
 }
+
+void
+sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id, efx_mport_id_t *mport_alias)
+{
+	const struct sfc_repr_proxy *rp;
+	struct sfc_adapter *sa;
+
+	sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
+	sfc_adapter_lock(sa);
+	rp = sfc_repr_proxy_by_adapter(sa);
+
+	memcpy(mport_alias, &rp->mport_alias, sizeof(*mport_alias));
+
+	sfc_adapter_unlock(sa);
+}
diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h b/drivers/net/sfc/sfc_repr_proxy_api.h
index 1d38ab2451..07d79a50cb 100644
--- a/drivers/net/sfc/sfc_repr_proxy_api.h
+++ b/drivers/net/sfc/sfc_repr_proxy_api.h
@@ -46,6 +46,9 @@ int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id);
 int sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id,
 		uint16_t repr_id, const struct rte_ether_addr *mac_addr);
 
+void sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id,
+				    efx_mport_id_t *mport_alias);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 8f1ee97fa8..f80de4e889 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -551,6 +551,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
 int
 sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				uint16_t ethdev_port_id,
+				unsigned int allowed_mae_switch_port_types,
 				efx_mport_sel_t *mport_sel)
 {
 	struct sfc_mae_switch_port *port;
@@ -562,11 +563,7 @@ sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 	if (rc != 0)
 		goto unlock;
 
-	if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) {
-		/*
-		 * The ethdev is a "VF representor". It does not own
-		 * a dedicated m-port suitable for use in flow rules.
-		 */
+	if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
 		rc = ENOTSUP;
 		goto unlock;
 	}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 62aea9b785..6a85ce4dcf 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -102,8 +102,18 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
 			      uint16_t switch_port_id);
 
+/*
+ * For user flows, allowed_mae_switch_port_types can only contain bit
+ * SFC_MAE_SWITCH_PORT_INDEPENDENT, meaning that only those ethdevs
+ * that have their own MAE m-ports can be accessed by a port-based
+ * action. For driver-internal flows, this mask can also contain
+ * bit SFC_MAE_SWITCH_PORT_REPRESENTOR to allow VF traffic to be
+ * sent to the common MAE m-port of all such REPRESENTOR ports
+ * via a port-based action, for default switch interconnection.
+ */
 int sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
 				    uint16_t ethdev_port_id,
+				    unsigned int allowed_mae_switch_port_types,
 				    efx_mport_sel_t *mport_sel);
 
 int sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 15/34] net/sfc: extend generic flow API to allow for internal flows
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (13 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
                     ` (21 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

At the moment, driver-internal flow rules are provisioned by
functions that are separate from the generic flow management
framework. In order to use the latter for such rules, extend
it accordingly. This will be actually used in the next patch.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc.c      |  9 ++++-----
 drivers/net/sfc/sfc_flow.c | 37 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_flow.h |  5 ++++-
 drivers/net/sfc/sfc_mae.c  | 31 +++++++++++++++++++++++++++----
 drivers/net/sfc/sfc_mae.h  |  5 +++--
 5 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index a56521696a..2cfff20f47 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -975,6 +975,8 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_rss_attach;
 
+	sfc_flow_init(sa);
+
 	rc = sfc_flow_rss_attach(sa);
 	if (rc != 0)
 		goto fail_flow_rss_attach;
@@ -1006,8 +1008,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
-	sfc_flow_init(sa);
-
 	rc = sfc_sw_xstats_init(sa);
 	if (rc != 0)
 		goto fail_sw_xstats_init;
@@ -1030,7 +1030,6 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_sw_xstats_close(sa);
 
 fail_sw_xstats_init:
-	sfc_flow_fini(sa);
 	sfc_repr_proxy_detach(sa);
 
 fail_repr_proxy_attach:
@@ -1052,6 +1051,7 @@ sfc_attach(struct sfc_adapter *sa)
 	sfc_flow_rss_detach(sa);
 
 fail_flow_rss_attach:
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 
 fail_rss_attach:
@@ -1099,8 +1099,6 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_sriov_vswitch_destroy(sa);
 
-	sfc_flow_fini(sa);
-
 	sfc_repr_proxy_detach(sa);
 	sfc_mae_switchdev_fini(sa);
 	sfc_tbls_detach(sa);
@@ -1108,6 +1106,7 @@ sfc_detach(struct sfc_adapter *sa)
 	sfc_mae_counter_rxq_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_flow_rss_detach(sa);
+	sfc_flow_fini(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
 	sfc_ev_detach(sa);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 432295ea62..f6d1ae2a5b 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -7,6 +7,8 @@
  * for Solarflare) and Solarflare Communications, Inc.
  */
 
+#include <stdbool.h>
+
 #include <rte_byteorder.h>
 #include <rte_tailq.h>
 #include <rte_common.h>
@@ -2405,7 +2407,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2421,7 +2423,7 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
 	if (rc != 0)
 		goto fail;
 
@@ -2613,14 +2615,14 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow;
 
 	sfc_adapter_lock(sa);
-	flow = sfc_flow_create_locked(sa, attr, pattern, actions, error);
+	flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
 	sfc_adapter_unlock(sa);
 
 	return flow;
 }
 
 struct rte_flow *
-sfc_flow_create_locked(struct sfc_adapter *sa,
+sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item pattern[],
 		       const struct rte_flow_action actions[],
@@ -2635,13 +2637,15 @@ sfc_flow_create_locked(struct sfc_adapter *sa,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	flow->internal = internal;
+
 	rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
 	TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
 
-	if (sa->state == SFC_ETHDEV_STARTED) {
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED) {
 		rc = sfc_flow_insert(sa, flow, error);
 		if (rc != 0)
 			goto fail_flow_insert;
@@ -2694,7 +2698,7 @@ sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
 		goto fail_bad_value;
 	}
 
-	if (sa->state == SFC_ETHDEV_STARTED)
+	if (flow->internal || sa->state == SFC_ETHDEV_STARTED)
 		rc = sfc_flow_remove(sa, flow, error);
 
 	TAILQ_REMOVE(&sa->flow_list, flow, entries);
@@ -2711,10 +2715,14 @@ sfc_flow_flush(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct rte_flow *flow;
 	int ret = 0;
+	void *tmp;
 
 	sfc_adapter_lock(sa);
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		if (sa->state == SFC_ETHDEV_STARTED) {
 			int rc;
 
@@ -2842,10 +2850,14 @@ void
 sfc_flow_fini(struct sfc_adapter *sa)
 {
 	struct rte_flow *flow;
+	void *tmp;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
+	RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
+		if (flow->internal)
+			continue;
+
 		TAILQ_REMOVE(&sa->flow_list, flow, entries);
 		sfc_flow_free(sa, flow);
 	}
@@ -2858,8 +2870,10 @@ sfc_flow_stop(struct sfc_adapter *sa)
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	TAILQ_FOREACH(flow, &sa->flow_list, entries)
-		sfc_flow_remove(sa, flow, NULL);
+	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (!flow->internal)
+			sfc_flow_remove(sa, flow, NULL);
+	}
 
 	/*
 	 * MAE counter service is not stopped on flow rule remove to avoid
@@ -2881,6 +2895,9 @@ sfc_flow_start(struct sfc_adapter *sa)
 	sfc_ft_counters_reset(sa);
 
 	TAILQ_FOREACH(flow, &sa->flow_list, entries) {
+		if (flow->internal)
+			continue;
+
 		rc = sfc_flow_insert(sa, flow, NULL);
 		if (rc != 0)
 			goto fail_bad_flow;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index a3ca09f225..ec5e29f257 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -10,6 +10,8 @@
 #ifndef _SFC_FLOW_H
 #define _SFC_FLOW_H
 
+#include <stdbool.h>
+
 #include <rte_tailq.h>
 #include <rte_flow_driver.h>
 
@@ -101,6 +103,7 @@ struct sfc_flow_spec {
 struct rte_flow {
 	struct sfc_flow_spec spec;	/* flow specification */
 	TAILQ_ENTRY(rte_flow) entries;	/* flow list entries */
+	bool internal;			/* true for internal rules */
 };
 
 TAILQ_HEAD(sfc_flow_list, rte_flow);
@@ -195,7 +198,7 @@ typedef int (sfc_flow_query_cb_t)(struct rte_eth_dev *dev,
 				  void *data,
 				  struct rte_flow_error *error);
 
-struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa,
+struct rte_flow *sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
 					const struct rte_flow_attr *attr,
 					const struct rte_flow_item pattern[],
 					const struct rte_flow_action actions[],
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 89fa75281f..f7bf682c11 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2537,6 +2537,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
+	if (ctx->internal) {
+		/*
+		 * A driver-internal flow may not comprise an outer rule,
+		 * but it must not match on invalid outer rule ID since
+		 * it must catch all missed packets, including those
+		 * that hit an outer rule of another flow entry but
+		 * do not hit a higher-priority action rule later.
+		 * So do not set match on outer rule ID here.
+		 */
+		SFC_ASSERT(ctx->match_spec_outer == NULL);
+		*rulep = NULL;
+		return 0;
+	}
+
 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
 		*rulep = NULL;
 		goto no_or_id;
@@ -2823,9 +2837,10 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
-			   struct sfc_flow_spec_mae *spec,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2833,6 +2848,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
 	ctx_mae.ft_rule_type = spec->ft_rule_type;
+	ctx_mae.internal = flow->internal;
 	ctx_mae.priority = spec->priority;
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
@@ -3642,11 +3658,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct sfc_flow_spec_mae *spec_mae,
+			  const struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
+	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -3770,6 +3787,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 		switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
 
+		if (flow->internal) {
+			switch_port_type_mask |=
+					1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
+		}
+
 		rc = sfc_mae_rule_parse_action_port_representor(sa,
 				action->conf, switch_port_type_mask, spec);
 		break;
@@ -3840,9 +3862,10 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
-			   struct sfc_flow_spec_mae *spec_mae,
+			   struct rte_flow *flow,
 			   struct rte_flow_error *error)
 {
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
@@ -3899,7 +3922,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
+		rc = sfc_mae_rule_parse_action(sa, action, flow,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d2995ded88..307236ea11 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -363,6 +363,7 @@ struct sfc_mae_parse_ctx {
 	size_t				tunnel_def_mask_size;
 	const void			*tunnel_def_mask;
 	bool				match_mport_set;
+	bool				internal;
 	enum sfc_ft_rule_type		ft_rule_type;
 	struct sfc_mae_pattern_data	pattern_data;
 	efx_tunnel_protocol_t		encap_type;
@@ -376,11 +377,11 @@ void sfc_mae_detach(struct sfc_adapter *sa);
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
 int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			       const struct rte_flow_item pattern[],
-			       struct sfc_flow_spec_mae *spec,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       const struct rte_flow_action actions[],
-			       struct sfc_flow_spec_mae *spec_mae,
+			       struct rte_flow *flow,
 			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 16/34] net/sfc: switch driver-internal flows to use generic methods
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (14 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
                     ` (20 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so helps to consolidate flow operation and ensure that
every FW-allocatable resource can be shared by several flows.
That is useful in the light of upcoming support for embedded
conntrack assistance, where several flows will ideally share
everything but unique 5-tuple entries in the conntrack table.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c        | 186 +++++++------------------------
 drivers/net/sfc/sfc_mae.h        |  51 ++-------
 drivers/net/sfc/sfc_repr_proxy.c |  38 ++-----
 drivers/net/sfc/sfc_repr_proxy.h |   2 +-
 4 files changed, 61 insertions(+), 216 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index f7bf682c11..51b2a22357 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -74,137 +74,48 @@ sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 	sfc_mae_counters_fini(&registry->counters);
 }
 
-static int
-sfc_mae_internal_rule_find_empty_slot(struct sfc_adapter *sa,
-				      struct sfc_mae_rule **rule)
-{
-	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_internal_rules *internal_rules = &mae->internal_rules;
-	unsigned int entry;
-	int rc;
-
-	for (entry = 0; entry < SFC_MAE_NB_RULES_MAX; entry++) {
-		if (internal_rules->rules[entry].spec == NULL)
-			break;
-	}
-
-	if (entry == SFC_MAE_NB_RULES_MAX) {
-		rc = ENOSPC;
-		sfc_err(sa, "failed too many rules (%u rules used)", entry);
-		goto fail_too_many_rules;
-	}
-
-	*rule = &internal_rules->rules[entry];
-
-	return 0;
-
-fail_too_many_rules:
-	return rc;
-}
-
-int
-sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-				     const efx_mport_sel_t *mport_match,
-				     const efx_mport_sel_t *mport_deliver,
-				     int prio, struct sfc_mae_rule **rulep)
+struct rte_flow *
+sfc_mae_repr_flow_create(struct sfc_adapter *sa, int prio, uint16_t port_id,
+			 enum rte_flow_action_type dst_type,
+			 enum rte_flow_item_type src_type)
 {
+	const struct rte_flow_item_ethdev item_spec = { .port_id = port_id };
+	const struct rte_flow_action_ethdev action = { .port_id = port_id };
+	const void *item_mask = &rte_flow_item_ethdev_mask;
+	struct rte_flow_attr attr = { .transfer = 1 };
+	const struct rte_flow_action actions[] = {
+		{ .type = dst_type, .conf = &action },
+		{ .type = RTE_FLOW_ACTION_TYPE_END }
+	};
+	const struct rte_flow_item items[] = {
+		{ .type = src_type, .mask = item_mask, .spec = &item_spec },
+		{ .type = RTE_FLOW_ITEM_TYPE_END }
+	};
 	struct sfc_mae *mae = &sa->mae;
-	struct sfc_mae_rule *rule;
-	int rc;
-
-	sfc_log_init(sa, "entry");
+	struct rte_flow_error error;
 
 	if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
-		rc = EINVAL;
 		sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
 			mae->nb_action_rule_prios_max);
-		goto fail_invalid_prio;
+		return NULL;
 	}
 	if (prio < 0)
 		prio = mae->nb_action_rule_prios_max - 1;
 
-	rc = sfc_mae_internal_rule_find_empty_slot(sa, &rule);
-	if (rc != 0)
-		goto fail_find_empty_slot;
-
-	sfc_log_init(sa, "init MAE match spec");
-	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
-				     (uint32_t)prio, &rule->spec);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE match spec");
-		goto fail_match_init;
-	}
-
-	rc = efx_mae_match_spec_mport_set(rule->spec, mport_match, NULL);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get MAE match mport selector");
-		goto fail_mport_set;
-	}
-
-	rc = efx_mae_action_set_spec_init(sa->nic, &rule->actions);
-	if (rc != 0) {
-		sfc_err(sa, "failed to init MAE action set");
-		goto fail_action_init;
-	}
-
-	rc = efx_mae_action_set_populate_deliver(rule->actions,
-						 mport_deliver);
-	if (rc != 0) {
-		sfc_err(sa, "failed to populate deliver action");
-		goto fail_populate_deliver;
-	}
-
-	rc = efx_mae_action_set_alloc(sa->nic, rule->actions,
-				      &rule->action_set);
-	if (rc != 0) {
-		sfc_err(sa, "failed to allocate action set");
-		goto fail_action_set_alloc;
-	}
-
-	rc = efx_mae_action_rule_insert(sa->nic, rule->spec, NULL,
-					&rule->action_set,
-					&rule->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to insert action rule");
-		goto fail_rule_insert;
-	}
-
-	*rulep = rule;
-
-	sfc_log_init(sa, "done");
-
-	return 0;
-
-fail_rule_insert:
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-
-fail_action_set_alloc:
-fail_populate_deliver:
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
+	attr.priority = prio;
 
-fail_action_init:
-fail_mport_set:
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
-
-fail_match_init:
-fail_find_empty_slot:
-fail_invalid_prio:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	return sfc_flow_create_locked(sa, true, &attr, items, actions, &error);
 }
 
 void
-sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule)
+sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow)
 {
-	if (rule == NULL || rule->spec == NULL)
-		return;
-
-	efx_mae_action_rule_remove(sa->nic, &rule->rule_id);
-	efx_mae_action_set_free(sa->nic, &rule->action_set);
-	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
-	efx_mae_match_spec_fini(sa->nic, rule->spec);
+	struct rte_flow_error error;
+	int rc;
 
-	rule->spec = NULL;
+	rc = sfc_flow_destroy_locked(sa, flow, &error);
+	if (rc != 0)
+		sfc_err(sa, "failed to destroy the internal flow");
 }
 
 int
@@ -4311,11 +4222,9 @@ sfc_mae_flow_query(struct rte_eth_dev *dev,
 int
 sfc_mae_switchdev_init(struct sfc_adapter *sa)
 {
-	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 	struct sfc_mae *mae = &sa->mae;
-	efx_mport_sel_t pf;
-	efx_mport_sel_t phy;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
@@ -4330,31 +4239,20 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 		goto fail_no_mae;
 	}
 
-	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
-					    &pf);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PF mport");
-		goto fail_pf_get;
-	}
-
-	rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
-	if (rc != 0) {
-		sfc_err(sa, "failed get PHY mport");
-		goto fail_phy_get;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_pf_to_ext);
-	if (rc != 0) {
+	mae->switchdev_rule_pf_to_ext = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
+					 RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR);
+	if (mae->switchdev_rule_pf_to_ext == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
 		goto fail_pf_add;
 	}
 
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
-			SFC_MAE_RULE_PRIO_LOWEST,
-			&mae->switchdev_rule_ext_to_pf);
-	if (rc != 0) {
+	mae->switchdev_rule_ext_to_pf = sfc_mae_repr_flow_create(sa,
+					 SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
+					 RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+					 RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (mae->switchdev_rule_ext_to_pf == NULL) {
 		sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
 		goto fail_phy_add;
 	}
@@ -4364,11 +4262,9 @@ sfc_mae_switchdev_init(struct sfc_adapter *sa)
 	return 0;
 
 fail_phy_add:
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 
 fail_pf_add:
-fail_phy_get:
-fail_pf_get:
 fail_no_mae:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
@@ -4382,6 +4278,6 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	if (!sa->switchdev)
 		return;
 
-	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
-	sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
+	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 307236ea11..f9434e1ab6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -180,33 +180,6 @@ struct sfc_mae_counter_registry {
 	} polling;
 };
 
-/**
- * MAE rules used to capture traffic generated by VFs and direct it to
- * representors (one for each VF).
- */
-#define SFC_MAE_NB_REPR_RULES_MAX	(64)
-
-/** Rules to forward traffic from PHY port to PF and from PF to PHY port */
-#define SFC_MAE_NB_SWITCHDEV_RULES	(2)
-/** Maximum required internal MAE rules */
-#define SFC_MAE_NB_RULES_MAX		(SFC_MAE_NB_SWITCHDEV_RULES + \
-					 SFC_MAE_NB_REPR_RULES_MAX)
-
-struct sfc_mae_rule {
-	efx_mae_match_spec_t		*spec;
-	efx_mae_actions_t		*actions;
-	efx_mae_aset_id_t		action_set;
-	efx_mae_rule_id_t		rule_id;
-};
-
-struct sfc_mae_internal_rules {
-	/*
-	 * Rules required to sustain switchdev mode or to provide
-	 * port representor functionality.
-	 */
-	struct sfc_mae_rule		rules[SFC_MAE_NB_RULES_MAX];
-};
-
 struct sfc_mae {
 	/** Assigned switch domain identifier */
 	uint16_t			switch_domain_id;
@@ -234,14 +207,12 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter registry */
 	struct sfc_mae_counter_registry	counter_registry;
-	/** Driver-internal flow rules */
-	struct sfc_mae_internal_rules	internal_rules;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
 	 */
-	struct sfc_mae_rule		*switchdev_rule_pf_to_ext;
-	struct sfc_mae_rule		*switchdev_rule_ext_to_pf;
+	struct rte_flow			*switchdev_rule_pf_to_ext;
+	struct rte_flow			*switchdev_rule_ext_to_pf;
 };
 
 struct sfc_adapter;
@@ -396,16 +367,18 @@ sfc_flow_query_cb_t sfc_mae_flow_query;
 
 /**
  * Insert a driver-internal flow rule that matches traffic originating from
- * some m-port selector and redirects it to another one
- * (eg. PF --> PHY, PHY --> PF).
+ * a source port (REPRESENTED_PORT or PORT_REPRESENTOR) and directs it to
+ * its destination counterpart (PORT_REPRESENTOR or REPRESENTED_PORT).
  *
- * If requested priority is negative, use the lowest priority.
+ * If the prio argument is negative, the lowest level will be picked.
  */
-int sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
-					 const efx_mport_sel_t *mport_match,
-					 const efx_mport_sel_t *mport_deliver,
-					 int prio, struct sfc_mae_rule **rulep);
-void sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule);
+struct rte_flow *sfc_mae_repr_flow_create(struct sfc_adapter *sa,
+					  int prio, uint16_t port_id,
+					  enum rte_flow_action_type dst_type,
+					  enum rte_flow_item_type src_type);
+
+void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
+
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 74c3494c35..ff13795c97 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -681,47 +681,25 @@ static int
 sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_repr_proxy *rp = &sa->repr_proxy;
-	efx_mport_sel_t mport_alias_selector;
-	efx_mport_sel_t mport_vf_selector;
-	struct sfc_mae_rule *mae_rule;
-	int rc;
+	int rc = EINVAL;
 
 	sfc_log_init(sa, "entry");
 
-	rc = efx_mae_mport_by_id(&port->egress_mport,
-				 &mport_vf_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get VF mport for repr %u",
-			port->repr_id);
-		goto fail_get_vf;
-	}
-
-	rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
-	if (rc != 0) {
-		sfc_err(sa, "failed to get mport selector for repr %u",
-			port->repr_id);
-		goto fail_get_alias;
-	}
-
-	rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
-						  &mport_alias_selector, -1,
-						  &mae_rule);
-	if (rc != 0) {
+	port->mae_rule = sfc_mae_repr_flow_create(sa,
+				    SFC_MAE_RULE_PRIO_LOWEST, port->rte_port_id,
+				    RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
+				    RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
+	if (port->mae_rule == NULL) {
 		sfc_err(sa, "failed to insert MAE rule for repr %u",
 			port->repr_id);
 		goto fail_rule_add;
 	}
 
-	port->mae_rule = mae_rule;
-
 	sfc_log_init(sa, "done");
 
 	return 0;
 
 fail_rule_add:
-fail_get_alias:
-fail_get_vf:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -730,9 +708,7 @@ static void
 sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
 			       struct sfc_repr_proxy_port *port)
 {
-	struct sfc_mae_rule *mae_rule = port->mae_rule;
-
-	sfc_mae_rule_del(sa, mae_rule);
+	sfc_mae_repr_flow_destroy(sa, port->mae_rule);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_repr_proxy.h b/drivers/net/sfc/sfc_repr_proxy.h
index 260e2cab30..0a4dedc3e1 100644
--- a/drivers/net/sfc/sfc_repr_proxy.h
+++ b/drivers/net/sfc/sfc_repr_proxy.h
@@ -67,7 +67,7 @@ struct sfc_repr_proxy_port {
 	uint32_t				remote_vnic_mcdi_client_handle;
 	struct sfc_repr_proxy_rxq		rxq[SFC_REPR_RXQ_MAX];
 	struct sfc_repr_proxy_txq		txq[SFC_REPR_TXQ_MAX];
-	struct sfc_mae_rule			*mae_rule;
+	struct rte_flow				*mae_rule;
 	bool					enabled;
 	bool					started;
 };
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 17/34] net/sfc: move MAE flow parsing method to MAE-specific source
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (15 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
                     ` (19 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so will facilitate easier code restructure in the next
patches required to rework flow housekeeping and indirection.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 47 +-----------------------------
 drivers/net/sfc/sfc_mae.c  | 58 ++++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  | 14 ++++-----
 3 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f6d1ae2a5b..6dfbbfd022 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2395,53 +2395,8 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  struct rte_flow_error *error)
 {
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
-	struct sfc_flow_spec *spec = &flow->spec;
-	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	int rc;
-
-	/*
-	 * If the flow is meant to be a TUNNEL rule in a FT context,
-	 * preparse its actions and save its properties in spec_mae.
-	 */
-	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
-	if (rc != 0)
-		goto fail;
-
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
-		/*
-		 * By design, this flow should be represented solely by the
-		 * outer rule. But the HW/FW hasn't got support for setting
-		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
-		 * does it support outer rule counters. As a workaround, an
-		 * action rule of lower priority is used to do the job.
-		 *
-		 * So don't skip sfc_mae_rule_parse_actions() below.
-		 */
-	}
-
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
-	if (rc != 0)
-		goto fail;
-
-	if (spec_mae->ft_ctx != NULL) {
-		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
-			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
 
-		++(spec_mae->ft_ctx->refcnt);
-	}
-
-	return 0;
-
-fail:
-	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
-	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
-	spec_mae->ft_ctx = NULL;
-
-	return rc;
+	return sfc_mae_rule_parse(sa, pattern, actions, flow, error);
 }
 
 static int
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 51b2a22357..e2f098ea53 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -2745,7 +2745,7 @@ sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
 
-int
+static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
@@ -3770,7 +3770,7 @@ sfc_mae_process_encap_header(struct sfc_adapter *sa,
 	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
 }
 
-int
+static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
@@ -3933,6 +3933,60 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	return rc;
 }
 
+int
+sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow *flow, struct rte_flow_error *error)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	int rc;
+
+	/*
+	 * If the flow is meant to be a TUNNEL rule in a FT context,
+	 * preparse its actions and save its properties in spec_mae.
+	 */
+	rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
+	if (rc != 0)
+		goto fail;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * By design, this flow should be represented solely by the
+		 * outer rule. But the HW/FW hasn't got support for setting
+		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+		 * does it support outer rule counters. As a workaround, an
+		 * action rule of lower priority is used to do the job.
+		 *
+		 * So don't skip sfc_mae_rule_parse_actions() below.
+		 */
+	}
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	if (rc != 0)
+		goto fail;
+
+	if (spec_mae->ft_ctx != NULL) {
+		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
+			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
+
+		++(spec_mae->ft_ctx->refcnt);
+	}
+
+	return 0;
+
+fail:
+	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
+	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
+	spec_mae->ft_ctx = NULL;
+
+	return rc;
+}
+
 static bool
 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
 			const efx_mae_match_spec_t *left,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index f9434e1ab6..1d937c9b5b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -345,15 +345,13 @@ struct sfc_mae_parse_ctx {
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 void sfc_mae_detach(struct sfc_adapter *sa);
+
+int sfc_mae_rule_parse(struct sfc_adapter *sa,
+		       const struct rte_flow_item pattern[],
+		       const struct rte_flow_action actions[],
+		       struct rte_flow *flow, struct rte_flow_error *error);
+
 sfc_flow_cleanup_cb_t sfc_mae_flow_cleanup;
-int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
-			       const struct rte_flow_item pattern[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
-int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
-			       const struct rte_flow_action actions[],
-			       struct rte_flow *flow,
-			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 sfc_flow_insert_cb_t sfc_mae_flow_insert;
 sfc_flow_remove_cb_t sfc_mae_flow_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 18/34] net/sfc: move MAE counter stream start to action set handler
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (16 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
                     ` (18 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Logically, starting flow counter streaming belongs in action
set enable path. Move it there as a preparation step for the
patch that will make action rules shareable by several flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e2f098ea53..37292f5d7c 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1063,6 +1063,18 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
+		if (action_set->n_counters > 0) {
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_err(sa, "failed to start MAE counters support: %s",
+					rte_strerror(rc));
+				sfc_mae_encap_header_disable(sa, encap_header);
+				sfc_mae_mac_addr_disable(sa, src_mac_addr);
+				sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+				return rc;
+			}
+		}
+
 		rc = sfc_mae_counters_enable(sa, counters,
 					     action_set->n_counters,
 					     action_set->spec);
@@ -4141,15 +4153,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_enable;
 
-	if (action_set->n_counters > 0) {
-		rc = sfc_mae_counter_start(sa);
-		if (rc != 0) {
-			sfc_err(sa, "failed to start MAE counters support: %s",
-				rte_strerror(rc));
-			goto fail_mae_counter_start;
-		}
-	}
-
 	fw_rsrc = &action_set->fw_rsrc;
 
 	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
@@ -4164,7 +4167,6 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	return 0;
 
 fail_action_rule_insert:
-fail_mae_counter_start:
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 19/34] net/sfc: prepare MAE outer rules for action rule indirection
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (17 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
                     ` (17 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Flows provided by match-action engine (MAE) will be reworked
by the next patch to make action rule (AR) entries shareable.
To ensure correct AR specification comparison on attach path,
augment the way outer rules (OR) are handled, namely, how OR
IDs are indicated in a AR specification on parse and disable.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 44 ++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 37292f5d7c..624be53269 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -397,8 +397,10 @@ sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
-			   struct sfc_mae_outer_rule *rule)
+			   struct sfc_mae_outer_rule *rule,
+			   efx_mae_match_spec_t *match_spec_action)
 {
+	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -409,6 +411,18 @@ sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
 
 	fw_rsrc = &rule->fw_rsrc;
 
+	if (match_spec_action == NULL)
+		goto skip_action_rule;
+
+	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
+						  &invalid_rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "cannot restore match on invalid outer rule ID: %s",
+			strerror(rc));
+		return;
+	}
+
+skip_action_rule:
 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
@@ -2457,7 +2471,7 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_outer_rule **rulep,
 			   struct rte_flow_error *error)
 {
-	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
+	efx_mae_rule_id_t or_id = { .id = EFX_MAE_RSRC_ID_INVALID };
 	int rc;
 
 	if (ctx->internal) {
@@ -2504,13 +2518,20 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	/* The spec has now been tracked by the outer rule entry. */
 	ctx->match_spec_outer = NULL;
 
+	or_id.id = (*rulep)->fw_rsrc.rule_id.id;
+
 no_or_id:
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
 	case SFC_FT_RULE_TUNNEL:
-		/* No action rule */
-		return 0;
+		/*
+		 * Workaround. TUNNEL flows are not supposed to involve
+		 * MAE action rules, but, due to the currently limited
+		 * HW/FW implementation, action rules are still needed.
+		 * See sfc_mae_rule_parse_pattern().
+		 */
+		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
 		 * Match on recirculation ID rather than
@@ -2536,14 +2557,13 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 	 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
 	 * in the action rule specification; this ensures correct behaviour.
 	 *
-	 * If, on the other hand, this flow does have an outer rule, its ID
-	 * may be unknown at the moment (not yet allocated), but OR_ID mask
-	 * has to be set to 0xffffffff anyway for correct class comparisons.
-	 * When the outer rule has been allocated, this match field will be
-	 * overridden by sfc_mae_outer_rule_enable() to use the right value.
+	 * If, however, this flow does have an outer rule, OR_ID match must
+	 * be set to the currently known value for that outer rule. It will
+	 * be either 0xffffffff or some valid ID, depending on whether this
+	 * outer rule is currently active (adapter state is STARTED) or not.
 	 */
 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
-						  &invalid_rule_id);
+						  &or_id);
 	if (rc != 0) {
 		sfc_mae_outer_rule_del(sa, *rulep);
 		*rulep = NULL;
@@ -4170,7 +4190,7 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 fail_outer_rule_enable:
 	return rc;
@@ -4205,7 +4225,7 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	sfc_mae_action_set_disable(sa, action_set);
 
 skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule);
+	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
 
 	return 0;
 }
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 20/34] net/sfc: turn MAE flow action rules into shareable resources
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (18 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
                     ` (16 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance. With the new feature, multiple flows that differ
in the 5-tuple match fields but are otherwise identical will
be able to share all FW-allocatable objects except for those
of the conntrack table. That will boost flow engine capacity.

To prepare for that, action rules of the match-action engine
have to be turned into shareable objects, from SW standpoint.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   4 +-
 drivers/net/sfc/sfc_flow.h |  13 +-
 drivers/net/sfc/sfc_mae.c  | 362 +++++++++++++++++++++++++++----------
 drivers/net/sfc/sfc_mae.h  |  13 ++
 4 files changed, 287 insertions(+), 105 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 6dfbbfd022..0abeabfbf2 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1294,9 +1294,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		}
 		spec->type = SFC_FLOW_SPEC_MAE;
 		spec_mae->priority = attr->priority;
-		spec_mae->match_spec = NULL;
-		spec_mae->action_set = NULL;
-		spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+		spec_mae->action_rule = NULL;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index ec5e29f257..10c73d012f 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -75,14 +75,13 @@ struct sfc_flow_spec_mae {
 	struct sfc_ft_ctx		*ft_ctx;
 	/* Desired priority level */
 	unsigned int			priority;
-	/* Outer rule registry entry */
+	/*
+	 * Outer rule registry entry (points to below action_rule->outer_rule
+	 * when action_rule is not NULL; self-sufficient entry otherwise)
+	 */
 	struct sfc_mae_outer_rule	*outer_rule;
-	/* EFX match specification */
-	efx_mae_match_spec_t		*match_spec;
-	/* Action set registry entry */
-	struct sfc_mae_action_set	*action_set;
-	/* Firmware-allocated rule ID */
-	efx_mae_rule_id_t		rule_id;
+	/* Action rule registry entry */
+	struct sfc_mae_action_rule	*action_rule;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 624be53269..addcad2843 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -204,6 +204,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
 	TAILQ_INIT(&mae->action_sets);
+	TAILQ_INIT(&mae->action_rules);
 
 	if (encp->enc_mae_admin)
 		mae->status = SFC_MAE_STATUS_ADMIN;
@@ -1172,6 +1173,200 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 	--(fw_rsrc->refcnt);
 }
 
+struct sfc_mae_action_rule_ctx {
+	struct sfc_mae_outer_rule	*outer_rule;
+	struct sfc_mae_action_set	*action_set;
+	efx_mae_match_spec_t		*match_spec;
+};
+
+static int
+sfc_mae_action_rule_attach(struct sfc_adapter *sa,
+			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule **rulep,
+			   __rte_unused struct rte_flow_error *error)
+{
+	struct sfc_mae_action_rule *rule;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	/*
+	 * It is assumed that the caller of this helper has already properly
+	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
+	 * ctx->outer_rule refers to a currently active outer rule) or
+	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
+	 */
+	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->outer_rule != ctx->outer_rule ||
+		    rule->action_set != ctx->action_set)
+			continue;
+
+		if (efx_mae_match_specs_equal(rule->match_spec,
+					      ctx->match_spec)) {
+			sfc_dbg(sa, "attaching to action_rule=%p", rule);
+			++(rule->refcnt);
+			*rulep = rule;
+			return 0;
+		}
+	}
+
+	/*
+	 * No need to set RTE error, as this
+	 * code should be handled gracefully.
+	 */
+	return -ENOENT;
+}
+
+static int
+sfc_mae_action_rule_add(struct sfc_adapter *sa,
+			const struct sfc_mae_action_rule_ctx *ctx,
+			struct sfc_mae_action_rule **rulep)
+{
+	struct sfc_mae_action_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	rule = rte_zmalloc("sfc_mae_action_rule", sizeof(*rule), 0);
+	if (rule == NULL)
+		return ENOMEM;
+
+	rule->refcnt = 1;
+	rule->outer_rule = ctx->outer_rule;
+	rule->action_set = ctx->action_set;
+	rule->match_spec = ctx->match_spec;
+
+	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);
+
+	*rulep = rule;
+
+	sfc_dbg(sa, "added action_rule=%p", rule);
+
+	return 0;
+}
+
+static void
+sfc_mae_action_rule_del(struct sfc_adapter *sa,
+			struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae *mae = &sa->mae;
+	if (rule == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(rule->refcnt != 0);
+
+	--(rule->refcnt);
+
+	if (rule->refcnt != 0)
+		return;
+
+	if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    rule->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u",
+			rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
+	}
+
+	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
+	sfc_mae_action_set_del(sa, rule->action_set);
+	sfc_mae_outer_rule_del(sa, rule->outer_rule);
+
+	TAILQ_REMOVE(&mae->action_rules, rule, entries);
+	rte_free(rule);
+
+	sfc_dbg(sa, "deleted action_rule=%p", rule);
+}
+
+static int
+sfc_mae_action_rule_enable(struct sfc_adapter *sa,
+			   struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->refcnt != 0)
+		goto success;
+
+	rc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);
+	if (rc != 0)
+		goto fail_outer_rule_enable;
+
+	rc = sfc_mae_action_set_enable(sa, rule->action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, NULL,
+					&rule->action_set->fw_rsrc.aset_id,
+					&fw_rsrc->rule_id);
+	if (rc != 0) {
+		sfc_err(sa, "failed to enable action_rule=%p: %s",
+			rule, strerror(rc));
+		goto fail_action_rule_insert;
+	}
+
+success:
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled action_rule=%p: AR_ID=0x%08x",
+			rule, fw_rsrc->rule_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+
+fail_action_rule_insert:
+	sfc_mae_action_set_disable(sa, rule->action_set);
+
+fail_action_set_enable:
+	sfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);
+
+fail_outer_rule_enable:
+	return rc;
+}
+static void
+sfc_mae_action_rule_disable(struct sfc_adapter *sa,
+			    struct sfc_mae_action_rule *rule)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &rule->fw_rsrc;
+
+	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u",
+			rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled action_rule=%p with AR_ID=0x%08x",
+				rule, fw_rsrc->rule_id.id);
+		} else {
+			sfc_err(sa, "failed to disable action_rule=%p with AR_ID=0x%08x: %s",
+				rule, fw_rsrc->rule_id.id, strerror(rc));
+		}
+
+		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+		sfc_mae_action_set_disable(sa, rule->action_set);
+
+		sfc_mae_outer_rule_disable(sa, rule->outer_rule,
+					   rule->match_spec);
+	}
+
+	--(fw_rsrc->refcnt);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -1191,13 +1386,7 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		--(spec_mae->ft_ctx->refcnt);
 	}
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
-	sfc_mae_action_set_del(sa, spec_mae->action_set);
-
-	if (spec_mae->match_spec != NULL)
-		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
 }
 
 static int
@@ -2781,9 +2970,11 @@ static int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec = &flow->spec.mae;
+	struct sfc_mae_outer_rule **outer_rulep;
 	struct sfc_mae_parse_ctx ctx_mae;
 	unsigned int priority_shift = 0;
 	struct sfc_flow_parse_ctx ctx;
@@ -2796,6 +2987,8 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	ctx_mae.ft_ctx = spec->ft_ctx;
 	ctx_mae.sa = sa;
 
+	outer_rulep = &action_rule_ctx->outer_rule;
+
 	switch (ctx_mae.ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		/*
@@ -2872,7 +3065,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
-	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
+	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
 
@@ -2884,7 +3077,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		goto fail_validate_match_spec_action;
 	}
 
-	spec->match_spec = ctx_mae.match_spec_action;
+	action_rule_ctx->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
@@ -3806,6 +3999,7 @@ static int
 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   const struct rte_flow_action actions[],
 			   struct rte_flow *flow,
+			   struct sfc_mae_action_rule_ctx *action_rule_ctx,
 			   struct rte_flow_error *error)
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
@@ -3927,8 +4121,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		goto fail_check_fate_action;
 	}
 
-	spec_mae->action_set = sfc_mae_action_set_attach(sa, &ctx);
-	if (spec_mae->action_set != NULL) {
+	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
+	if (action_rule_ctx->action_set != NULL) {
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -3936,7 +4130,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx, &spec_mae->action_set);
+	rc = sfc_mae_action_set_add(sa, actions, &ctx,
+				    &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -3972,6 +4167,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule_ctx ctx = {};
 	int rc;
 
 	/*
@@ -3982,7 +4178,7 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	if (rc != 0)
 		goto fail;
 
-	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, error);
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
@@ -3998,10 +4194,30 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 		 */
 	}
 
-	rc = sfc_mae_rule_parse_actions(sa, actions, flow, error);
+	spec_mae->outer_rule = ctx.outer_rule;
+
+	rc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);
 	if (rc != 0)
 		goto fail;
 
+	rc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,
+					error);
+	if (rc == 0) {
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+		sfc_mae_action_set_del(sa, ctx.action_set);
+		sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+	} else if (rc == -ENOENT) {
+		rc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);
+		if (rc != 0) {
+			rc = rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to add the entry");
+			goto fail;
+		}
+	} else {
+		goto fail;
+	}
+
 	if (spec_mae->ft_ctx != NULL) {
 		if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
 			spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
@@ -4012,6 +4228,12 @@ sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
 	return 0;
 
 fail:
+	if (ctx.match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
+
+	sfc_mae_action_set_del(sa, ctx.action_set);
+	sfc_mae_outer_rule_del(sa, ctx.outer_rule);
+
 	/* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
 	spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
 	spec_mae->ft_ctx = NULL;
@@ -4071,30 +4293,27 @@ sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
-				 struct sfc_flow_spec_mae *spec)
+				 struct sfc_mae_action_rule *rule)
 {
-	const struct rte_flow *entry;
+	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
+	const struct sfc_mae_action_rule *entry;
+	struct sfc_mae *mae = &sa->mae;
 
-	if (spec->match_spec == NULL)
+	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* An active rule is reused. Its class is known to be valid. */
 		return 0;
+	}
 
-	TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
-		const struct sfc_flow_spec *entry_spec = &entry->spec;
-		const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
-		const efx_mae_match_spec_t *left = es_mae->match_spec;
-		const efx_mae_match_spec_t *right = spec->match_spec;
+	TAILQ_FOREACH_REVERSE(entry, &mae->action_rules,
+			      sfc_mae_action_rules, entries) {
+		const efx_mae_match_spec_t *left = entry->match_spec;
+		const efx_mae_match_spec_t *right = rule->match_spec;
 
-		switch (entry_spec->type) {
-		case SFC_FLOW_SPEC_FILTER:
-			/* Ignore VNIC-level flows */
-			break;
-		case SFC_FLOW_SPEC_MAE:
-			if (sfc_mae_rules_class_cmp(sa, left, right))
-				return 0;
-			break;
-		default:
-			SFC_ASSERT(false);
-		}
+		if (entry == rule)
+			continue;
+
+		if (sfc_mae_rules_class_cmp(sa, left, right))
+			return 0;
 	}
 
 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
@@ -4124,6 +4343,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	int rc;
 
@@ -4136,7 +4356,7 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
-	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+	return sfc_mae_action_rule_class_verify(sa, action_rule);
 }
 
 int
@@ -4145,55 +4365,22 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_fw_rsrc *fw_rsrc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 	int rc;
 
-	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
-
-	if (outer_rule != NULL) {
-		rc = sfc_mae_outer_rule_enable(sa, outer_rule,
-					       spec_mae->match_spec);
-		if (rc != 0)
-			goto fail_outer_rule_enable;
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
 		spec_mae->ft_ctx->reset_tunnel_hit_counter =
 			spec_mae->ft_ctx->switch_hit_counter;
 	}
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "enabled flow=%p (no AR)", flow);
+	if (action_rule == NULL)
 		return 0;
-	}
-
-	rc = sfc_mae_action_set_enable(sa, action_set);
-	if (rc != 0)
-		goto fail_action_set_enable;
-
-	fw_rsrc = &action_set->fw_rsrc;
 
-	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
-					NULL, &fw_rsrc->aset_id,
-					&spec_mae->rule_id);
+	rc = sfc_mae_action_rule_enable(sa, action_rule);
 	if (rc != 0)
-		goto fail_action_rule_insert;
-
-	sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
+		return rc;
 
 	return 0;
-
-fail_action_rule_insert:
-	sfc_mae_action_set_disable(sa, action_set);
-
-fail_action_set_enable:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
-
-fail_outer_rule_enable:
-	return rc;
 }
 
 int
@@ -4202,30 +4389,12 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
-	struct sfc_mae_action_set *action_set = spec_mae->action_set;
-	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
-	int rc;
+	struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
 
-	if (action_set == NULL) {
-		sfc_dbg(sa, "disabled flow=%p (no AR)", flow);
-		goto skip_action_rule;
-	}
-
-	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
-
-	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
-			flow, spec_mae->rule_id.id, strerror(rc));
-	}
-	sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x",
-		flow, spec_mae->rule_id.id);
-	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
-
-	sfc_mae_action_set_disable(sa, action_set);
+	if (action_rule == NULL)
+		return 0;
 
-skip_action_rule:
-	sfc_mae_outer_rule_disable(sa, outer_rule, spec_mae->match_spec);
+	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
 }
@@ -4237,17 +4406,20 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 		      struct rte_flow_query_count *data,
 		      struct rte_flow_error *error)
 {
-	struct sfc_mae_action_set *action_set = spec->action_set;
+	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
+	struct sfc_mae_action_set *action_set;
 	unsigned int i;
 	int rc;
 
-	if (action_set == NULL || action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
+	action_set = action_rule->action_set;
+
 	for (i = 0; i < action_set->n_counters; i++) {
 		/*
 		 * Get the first available counter of the flow rule if
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1d937c9b5b..cbe190075c 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -97,6 +97,17 @@ struct sfc_mae_action_set {
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 
+/** Action rule registry entry */
+struct sfc_mae_action_rule {
+	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	struct sfc_mae_outer_rule		*outer_rule;
+	struct sfc_mae_action_set		*action_set;
+	efx_mae_match_spec_t			*match_spec;
+	struct sfc_mae_fw_rsrc			fw_rsrc;
+	unsigned int				refcnt;
+};
+TAILQ_HEAD(sfc_mae_action_rules, sfc_mae_action_rule);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -201,6 +212,8 @@ struct sfc_mae {
 	struct sfc_mae_mac_addrs	mac_addrs;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
+	/** Action rule registry */
+	struct sfc_mae_action_rules	action_rules;
 	/** Encap. header bounce buffer */
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 21/34] common/sfc_efx/base: provide an API to clone MAE match specs
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (19 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
                     ` (15 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

The DPDK driver would like to have a means to make a copy of
the action rule match specification before trying to dissect
it to possibly move out the per-connection 5-tuple data from
it to build up an entry in the HW conntrack assistance table.

Making such a copy at the end of parsing should be preferred
over maintaining DPDK-level structures because the resulting
code is easier on eyes and less prone to errors in this case.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 49f807823e..97271f0f00 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4452,6 +4452,13 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_match_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 7732d99992..43dfba518a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1163,6 +1163,32 @@ efx_mae_match_spec_mport_set(
 
 fail2:
 	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_clone(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *orig,
+	__out				efx_mae_match_spec_t **clonep)
+{
+	efx_mae_match_spec_t *clone;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
+	if (clone == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
+
+	*clonep = clone;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d083a54a03..931d556e80 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -124,6 +124,7 @@ INTERNAL {
 	efx_mae_mac_addr_alloc;
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
+	efx_mae_match_spec_clone;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 22/34] common/sfc_efx/base: add API to read back MAE match criteria
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (20 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
                     ` (14 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Later patches of the series provide support for HW conntrack
assistance in the DPDK driver. In order to detect flows that
are subject to such assistance, the driver needs to retrieve
5-tuple match data from an already constructed specification.

A dedicated API to selectively read back match criteria will
make a neat solution to keep the implementation less complex.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  10 ++
 drivers/common/sfc_efx/base/efx_mae.c | 131 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |   1 +
 3 files changed, 142 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 97271f0f00..bc5117653f 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4430,6 +4430,16 @@ efx_mae_match_spec_field_set(
 	__in				size_t mask_size,
 	__in_bcount(mask_size)		const uint8_t *mask);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask);
+
 /* The corresponding mask will be set to B_TRUE. */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 43dfba518a..011f38d298 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1054,6 +1054,137 @@ efx_mae_match_spec_field_set(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_get(
+	__in				const efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__out_bcount_opt(value_size)	uint8_t *value,
+	__in				size_t mask_size,
+	__out_bcount_opt(mask_size)	uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	unsigned int desc_set_nentries;
+	const uint8_t *mvp;
+	efx_rc_t rc;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
+	case EFX_MAE_RULE_ACTION:
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if ((unsigned int)field_id >= desc_set_nentries) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (descp->emmd_mask_size == 0) {
+		/* The ID points to a gap in the array of field descriptors. */
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (value != NULL && value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (mask != NULL && mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail5;
+	}
+
+	if (value == NULL && value_size != 0) {
+		rc = EINVAL;
+		goto fail6;
+	}
+
+	if (mask == NULL && mask_size != 0) {
+		rc = EINVAL;
+		goto fail7;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The MCDI request field is in network (big endian) order.
+		 * The mask/value are also big endian.
+		 */
+		memcpy(value, mvp + descp->emmd_value_offset, value_size);
+		memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The MCDI request field is little endian.
+		 * The mask/value are in host byte order.
+		 */
+		switch (value_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_value_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)value =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(value, mvp + descp->emmd_value_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			memcpy(&dword, mvp + descp->emmd_mask_offset,
+			    sizeof (dword));
+
+			*(uint32_t *)mask =
+			    EFX_DWORD_FIELD(dword, EFX_DWORD_0);
+			break;
+		case 1:
+			memcpy(mask, mvp + descp->emmd_mask_offset, 1);
+			break;
+		case 0:
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+fail7:
+	EFSYS_PROBE(fail7);
+fail6:
+	EFSYS_PROBE(fail6);
 fail5:
 	EFSYS_PROBE(fail5);
 fail4:
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 931d556e80..b1ca8e1215 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (21 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-26 13:07     ` Thomas Monjalon
  2023-06-07 13:02   ` [PATCH v4 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
                     ` (13 subsequent siblings)
  36 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

EF100 match-action engine (MAE) has conntrack assistance
table. A hit in this table can provide a mark value for
the following lookup stage, which is action rule lookup.

Provide support for setting match on conntrack mark.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  7 +++++++
 drivers/common/sfc_efx/base/efx_mae.c | 28 +++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map    |  1 +
 3 files changed, 36 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index bc5117653f..f8c5d7a3bc 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4276,6 +4276,7 @@ typedef enum efx_mae_field_id_e {
 	 * or by using dedicated field-specific helper APIs.
 	 */
 	EFX_MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_CT_MARK,
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
@@ -4462,6 +4463,12 @@ efx_mae_match_spec_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_match_spec_clone(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 011f38d298..b00ed2ec7a 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -474,6 +474,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
 	EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
 	EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
+	EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -549,6 +550,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
 	EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
 
 #undef EFX_MAE_MV_DESC
 };
@@ -910,6 +912,32 @@ efx_mae_match_spec_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_ct_mark_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				uint32_t ct_mark)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	mp = (const uint8_t *)&full_mask;
+	vp = (const uint8_t *)&ct_mark;
+
+	rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
+					  sizeof (ct_mark), vp,
+					  sizeof (full_mask), mp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index b1ca8e1215..d972896210 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -125,6 +125,7 @@ INTERNAL {
 	efx_mae_mac_addr_free;
 	efx_mae_match_spec_bit_set;
 	efx_mae_match_spec_clone;
+	efx_mae_match_spec_ct_mark_set;
 	efx_mae_match_spec_field_get;
 	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (22 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
                     ` (12 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such can be initiated when a packet hits an outer rule.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  9 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 26 ++++++++++++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 37 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f8c5d7a3bc..5e3718050d 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4679,6 +4679,15 @@ efx_mae_outer_rule_recirc_id_set(
 	__in				efx_mae_match_spec_t *spec,
 	__in				uint8_t recirc_id);
 
+/*
+ * Request that packets hitting this rule be submitted
+ * for a lookup in the conntrack assistance table.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec);
+
 LIBEFX_API
 extern	__checkReturn		efx_rc_t
 efx_mae_outer_rule_insert(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 9a5d465fa0..0a6a489d2c 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1761,6 +1761,7 @@ struct efx_mae_match_spec_s {
 		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 	uint8_t				emms_outer_rule_recirc_id;
+	boolean_t			emms_outer_rule_do_ct;
 };
 
 typedef enum efx_mae_action_e {
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index b00ed2ec7a..546c743a02 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -2369,6 +2369,26 @@ efx_mae_outer_rule_recirc_id_set(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_outer_rule_do_ct_set(
+	__in				efx_mae_match_spec_t *spec)
+{
+	efx_rc_t rc;
+
+	if (spec->emms_type != EFX_MAE_RULE_OUTER) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	spec->emms_outer_rule_do_ct = B_TRUE;
+
+	return (0);
+
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
@@ -2389,6 +2409,7 @@ efx_mae_outer_rule_insert(
 	uint32_t encap_type_mcdi;
 	efx_mae_rule_id_t or_id;
 	size_t offset;
+	uint8_t do_ct;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
@@ -2451,6 +2472,11 @@ efx_mae_outer_rule_insert(
 	    MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
 	    spec->emms_outer_rule_recirc_id);
 
+	do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
+
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
+	    MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index d972896210..28a2be0a95 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -143,6 +143,7 @@ INTERNAL {
 	efx_mae_mport_free;
 	efx_mae_mport_id_by_selector;
 	efx_mae_mport_invalid;
+	efx_mae_outer_rule_do_ct_set;
 	efx_mae_outer_rule_insert;
 	efx_mae_outer_rule_recirc_id_set;
 	efx_mae_outer_rule_remove;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 25/34] net/sfc: make use of conntrack assistance for transfer flows
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (23 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
                     ` (11 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

On EF100 hardware, match-action engine (MAE) can be equipped
with an assistance table for connection tracking (CT). In it,
an entry key is a set of exact match fields: an EtherType, a
pair of IP addresses, a L4 protocol ID and a pair of L4 port
numbers. An entry response can provide matching packets with
a mark value and additional data to be plumbed to NAT action.
In addition, an update to mark-and-sweep counter can be done.

This table was designed with larger capacity in mind,
so moving the above match criteria out of an action
rule (AR) specification to a CT entry increases the
likelihood of reusing AR entries and improves the
total flow engine capacity. Make use of that.

NAT and CT counters will be supported later.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h |   4 +
 drivers/net/sfc/sfc_mae.c  | 314 +++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h  |   1 +
 3 files changed, 310 insertions(+), 9 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 10c73d012f..8f706fc589 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -18,6 +18,7 @@
 #include "efx.h"
 
 #include "sfc_flow_rss.h"
+#include "sfc_mae_ct.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -82,6 +83,9 @@ struct sfc_flow_spec_mae {
 	struct sfc_mae_outer_rule	*outer_rule;
 	/* Action rule registry entry */
 	struct sfc_mae_action_rule	*action_rule;
+	/* Conntrack (CT) assistance table entry key and response */
+	sfc_mae_conntrack_response_t	ct_resp;
+	sfc_mae_conntrack_key_t		ct_key;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index addcad2843..d3b4099213 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -18,6 +18,7 @@
 #include "sfc.h"
 #include "sfc_flow_tunnel.h"
 #include "sfc_mae_counter.h"
+#include "sfc_mae_ct.h"
 #include "sfc_log.h"
 #include "sfc_switch.h"
 #include "sfc_service.h"
@@ -1177,18 +1178,23 @@ struct sfc_mae_action_rule_ctx {
 	struct sfc_mae_outer_rule	*outer_rule;
 	struct sfc_mae_action_set	*action_set;
 	efx_mae_match_spec_t		*match_spec;
+	uint32_t			ct_mark;
 };
 
 static int
 sfc_mae_action_rule_attach(struct sfc_adapter *sa,
-			   const struct sfc_mae_action_rule_ctx *ctx,
+			   struct sfc_mae_action_rule_ctx *ctx,
 			   struct sfc_mae_action_rule **rulep,
-			   __rte_unused struct rte_flow_error *error)
+			   struct rte_flow_error *error)
 {
+	uint32_t new_ct_mark = ctx->ct_mark;
 	struct sfc_mae_action_rule *rule;
+	int rc;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	SFC_ASSERT(ctx->ct_mark <= 1);
+
 	/*
 	 * It is assumed that the caller of this helper has already properly
 	 * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
@@ -1196,10 +1202,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 	 * on 0xffffffff / 0xffffffff, so that specs compare correctly.
 	 */
 	TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
+		if (rule->ct_mark == new_ct_mark)
+			++new_ct_mark;
+
 		if (rule->outer_rule != ctx->outer_rule ||
-		    rule->action_set != ctx->action_set)
+		    rule->action_set != ctx->action_set ||
+		    !!rule->ct_mark != !!ctx->ct_mark)
 			continue;
 
+		if (ctx->ct_mark != 0) {
+			rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+							    rule->ct_mark);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark for comparison");
+			}
+		}
+
 		if (efx_mae_match_specs_equal(rule->match_spec,
 					      ctx->match_spec)) {
 			sfc_dbg(sa, "attaching to action_rule=%p", rule);
@@ -1209,6 +1229,24 @@ sfc_mae_action_rule_attach(struct sfc_adapter *sa,
 		}
 	}
 
+	if (ctx->ct_mark != 0) {
+		if (new_ct_mark == UINT32_MAX) {
+			return rte_flow_error_set(error, ERANGE,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to allocate CT mark");
+		}
+
+		rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
+						    new_ct_mark);
+		if (rc != 0) {
+			return rte_flow_error_set(error, EFAULT,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					NULL, "AR: failed to set CT mark");
+		}
+
+		ctx->ct_mark = new_ct_mark;
+	}
+
 	/*
 	 * No need to set RTE error, as this
 	 * code should be handled gracefully.
@@ -1231,6 +1269,17 @@ sfc_mae_action_rule_add(struct sfc_adapter *sa,
 		return ENOMEM;
 
 	rule->refcnt = 1;
+
+	/*
+	 * It is assumed that the caller invoked sfc_mae_action_rule_attach()
+	 * and got (-ENOENT) before getting here. That ensures a unique CT
+	 * mark value or, if no CT is involved at all, simply zero.
+	 *
+	 * It is also assumed that match on the mark (if non-zero)
+	 * is already set in the action rule match specification.
+	 */
+	rule->ct_mark = ctx->ct_mark;
+
 	rule->outer_rule = ctx->outer_rule;
 	rule->action_set = ctx->action_set;
 	rule->match_spec = ctx->match_spec;
@@ -1802,6 +1851,8 @@ struct sfc_mae_field_locator {
 	size_t				size;
 	/* Field offset in the corresponding rte_flow_item_ struct */
 	size_t				ofst;
+
+	uint8_t				ct_key_field;
 };
 
 static void
@@ -2654,6 +2705,216 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 	},
 };
 
+#define SFC_MAE_CT_KEY_ET 0x01 /* EtherType */
+#define SFC_MAE_CT_KEY_DA 0x02 /* IPv4/IPv6 destination address */
+#define SFC_MAE_CT_KEY_SA 0x04 /* IPv4/IPv6 source address */
+#define SFC_MAE_CT_KEY_L4 0x08 /* IPv4/IPv6 L4 protocol ID */
+#define SFC_MAE_CT_KEY_DP 0x10 /* L4 destination port */
+#define SFC_MAE_CT_KEY_SP 0x20 /* L4 source port */
+
+#define SFC_MAE_CT_KEY_FIELD_SIZE_MAX	sizeof(sfc_mae_conntrack_key_t)
+
+static const struct sfc_mae_field_locator flocs_ct[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ether_type_le),
+		offsetof(sfc_mae_conntrack_key_t, ether_type_le),
+		SFC_MAE_CT_KEY_ET,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr) -
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(sfc_mae_conntrack_key_t, dst_addr_le),
+		SFC_MAE_CT_KEY_DA,
+	},
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(sfc_mae_conntrack_key_t, src_addr_le),
+		SFC_MAE_CT_KEY_SA,
+	},
+	{
+		EFX_MAE_FIELD_IP_PROTO,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ip_proto),
+		offsetof(sfc_mae_conntrack_key_t, ip_proto),
+		SFC_MAE_CT_KEY_L4,
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, dst_port_le),
+		offsetof(sfc_mae_conntrack_key_t, dst_port_le),
+		SFC_MAE_CT_KEY_DP,
+	},
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, src_port_le),
+		offsetof(sfc_mae_conntrack_key_t, src_port_le),
+		SFC_MAE_CT_KEY_SP,
+	},
+};
+
+static int
+sfc_mae_rule_process_ct(struct sfc_adapter *sa, struct sfc_mae_parse_ctx *pctx,
+			struct sfc_mae_action_rule_ctx *action_rule_ctx,
+			struct sfc_flow_spec_mae *spec,
+			struct rte_flow_error *error)
+{
+	efx_mae_match_spec_t *match_spec_tmp;
+	uint8_t ct_key_missing_fields =
+		SFC_MAE_CT_KEY_ET | SFC_MAE_CT_KEY_DA | SFC_MAE_CT_KEY_SA |
+		SFC_MAE_CT_KEY_L4 | SFC_MAE_CT_KEY_DP | SFC_MAE_CT_KEY_SP;
+	unsigned int i;
+	int rc;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_TUNNEL) {
+		/*
+		 * TUNNEL rules have no network match fields that belong
+		 * in an action rule match specification, so nothing can
+		 * be possibly utilised for conntrack assistance offload.
+		 */
+		return 0;
+	}
+
+	if (!sfc_mae_conntrack_is_supported(sa))
+		return 0;
+
+	rc = efx_mae_match_spec_clone(sa->nic, pctx->match_spec_action,
+				      &match_spec_tmp);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"AR: failed to clone the match specification");
+	}
+
+	for (i = 0; i < RTE_DIM(flocs_ct); ++i) {
+		const struct sfc_mae_field_locator *fl = &flocs_ct[i];
+		uint8_t mask_full[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask_zero[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t value[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t mask[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
+		uint8_t *ct_key = (uint8_t *)&spec->ct_key;
+		efx_mae_field_id_t fid = fl->field_id;
+		unsigned int j;
+
+		rc = efx_mae_match_spec_field_get(match_spec_tmp, fid,
+						  fl->size, value,
+						  fl->size, mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to extract match field");
+		}
+
+		memset(mask_full, 0xff, fl->size);
+
+		if (memcmp(mask, mask_full, fl->size) != 0)
+			continue;
+
+		memset(mask_zero, 0, fl->size);
+
+		rc = efx_mae_match_spec_field_set(match_spec_tmp, fid,
+						  fl->size, mask_zero,
+						  fl->size, mask_zero);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"AR: failed to erase match field");
+		}
+
+		for (j = 0; j < fl->size; ++j) {
+			uint8_t *byte_dst = ct_key + fl->ofst + fl->size - 1 - j;
+			const uint8_t *byte_src = value + j;
+
+			*byte_dst = *byte_src;
+		}
+
+		ct_key_missing_fields &= ~(fl->ct_key_field);
+	}
+
+	if (ct_key_missing_fields != 0) {
+		efx_mae_match_spec_fini(sa->nic, match_spec_tmp);
+		return 0;
+	}
+
+	efx_mae_match_spec_fini(sa->nic, pctx->match_spec_action);
+	pctx->match_spec_action = match_spec_tmp;
+
+	if (pctx->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		/*
+		 * A SWITCH rule re-uses the corresponding TUNNEL rule's
+		 * outer rule, where conntrack request should have been
+		 * configured already, so skip outer rule processing.
+		 */
+		goto skip_outer_rule;
+	}
+
+	if (pctx->match_spec_outer == NULL) {
+		const struct sfc_mae_pattern_data *pdata = &pctx->pattern_data;
+		const struct sfc_mae_ethertype *et;
+		struct sfc_mae *mae = &sa->mae;
+
+		rc = efx_mae_match_spec_init(sa->nic,
+					     EFX_MAE_RULE_OUTER,
+					     mae->nb_outer_rule_prios_max - 1,
+					     &pctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to initialise the match specification");
+		}
+
+		/* Match on EtherType appears to be compulsory in outer rules */
+
+		et = &pdata->ethertypes[pdata->nb_vlan_tags];
+
+		rc = efx_mae_match_spec_field_set(pctx->match_spec_outer,
+				EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
+				sizeof(et->value), (const uint8_t *)&et->value,
+				sizeof(et->mask), (const uint8_t *)&et->mask);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to set match on EtherType");
+		}
+	}
+
+	rc = efx_mae_outer_rule_do_ct_set(pctx->match_spec_outer);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"OR: failed to request CT lookup");
+	}
+
+skip_outer_rule:
+	/* Initial/dummy CT mark value */
+	action_rule_ctx->ct_mark = 1;
+
+	return 0;
+}
+
+#undef SFC_MAE_CT_KEY_ET
+#undef SFC_MAE_CT_KEY_DA
+#undef SFC_MAE_CT_KEY_SA
+#undef SFC_MAE_CT_KEY_L4
+#undef SFC_MAE_CT_KEY_DP
+#undef SFC_MAE_CT_KEY_SP
+
 static int
 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 			   struct sfc_mae_parse_ctx *ctx,
@@ -2677,13 +2938,11 @@ sfc_mae_rule_process_outer(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
+	if (ctx->match_spec_outer == NULL) {
 		*rulep = NULL;
 		goto no_or_id;
 	}
 
-	SFC_ASSERT(ctx->match_spec_outer != NULL);
-
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -2810,6 +3069,7 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 {
 	const struct rte_flow_item *pattern = ctx->pattern;
 	struct sfc_mae *mae = &sa->mae;
+	bool request_ct = false;
 	uint8_t recirc_id = 0;
 	int rc;
 
@@ -2905,6 +3165,14 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 	switch (ctx->ft_rule_type) {
 	case SFC_FT_RULE_TUNNEL:
 		recirc_id = SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id);
+
+		if (sfc_mae_conntrack_is_supported(sa)) {
+			/*
+			 * Request lookup in conntrack table since SWITCH rules
+			 * are eligible to utilise this type of assistance.
+			 */
+			request_ct = true;
+		}
 		/* FALLTHROUGH */
 	case SFC_FT_RULE_NONE:
 		if (ctx->priority >= mae->nb_outer_rule_prios_max) {
@@ -2938,6 +3206,16 @@ sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 					"OR: failed to initialise RECIRC_ID");
 		}
+
+		if (!request_ct)
+			break;
+
+		rc = efx_mae_outer_rule_do_ct_set(ctx->match_spec_outer);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					"OR: failed to request CT lookup");
+		}
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/* Outermost items -> "ENC" match fields in the action rule. */
@@ -2959,9 +3237,6 @@ static void
 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
 			      struct sfc_mae_parse_ctx *ctx)
 {
-	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
-		return;
-
 	if (ctx->match_spec_outer != NULL)
 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
 }
@@ -3065,6 +3340,11 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_pattern_data;
 
+	rc = sfc_mae_rule_process_ct(sa, &ctx_mae, action_rule_ctx,
+				     spec, error);
+	if (rc != 0)
+		goto fail_process_ct;
+
 	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
 	if (rc != 0)
 		goto fail_process_outer;
@@ -3083,6 +3363,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 fail_validate_match_spec_action:
 fail_process_outer:
+fail_process_ct:
 fail_process_pattern_data:
 fail_parse_pattern:
 	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
@@ -4380,6 +4661,18 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		return rc;
 
+	if (spec_mae->action_rule->ct_mark != 0) {
+		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
+		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+
+		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
+					      &spec_mae->ct_resp);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -4394,6 +4687,9 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule == NULL)
 		return 0;
 
+	if (action_rule->ct_mark != 0)
+		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index cbe190075c..67fa2ca5c9 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -100,6 +100,7 @@ TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
 /** Action rule registry entry */
 struct sfc_mae_action_rule {
 	TAILQ_ENTRY(sfc_mae_action_rule)	entries;
+	uint32_t				ct_mark;
 	struct sfc_mae_outer_rule		*outer_rule;
 	struct sfc_mae_action_set		*action_set;
 	efx_mae_match_spec_t			*match_spec;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 26/34] common/sfc_efx/base: support NAT edits in MAE
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (24 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
                     ` (10 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

NAT goes after IP TTL decrement. It can operate
on the outermost frame only. In the case of
prior decapsulation, that maps to the frame
which was (originally) the inner one. Input
data for the action comes from the response
of the HW conntrack assistance table hit.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      | 13 +++++++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 17 +++++++++++++++++
 drivers/common/sfc_efx/version.map     |  1 +
 4 files changed, 32 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 5e3718050d..a296d34f29 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4560,6 +4560,19 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_decr_ip_ttl(
 	__in				efx_mae_actions_t *spec);
 
+/*
+ * This only requests NAT action. The replacement IP address and
+ * L4 port number, as well as the edit direction (DST/SRC), come
+ * from the response to a hit in the conntrack assistance table.
+ *
+ * The action amends the outermost frame. In the case of prior
+ * decapsulation, that maps to the (originally) inner frame.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 0a6a489d2c..e978ad0de8 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1771,6 +1771,7 @@ typedef enum efx_mae_action_e {
 	EFX_MAE_ACTION_SET_DST_MAC,
 	EFX_MAE_ACTION_SET_SRC_MAC,
 	EFX_MAE_ACTION_DECR_IP_TTL,
+	EFX_MAE_ACTION_NAT,
 	EFX_MAE_ACTION_VLAN_PUSH,
 	EFX_MAE_ACTION_COUNT,
 	EFX_MAE_ACTION_ENCAP,
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 546c743a02..aaea38c933 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1837,6 +1837,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_DECR_IP_TTL] = {
 		.emad_add = efx_mae_action_set_no_op
 	},
+	[EFX_MAE_ACTION_NAT] = {
+		.emad_add = efx_mae_action_set_no_op
+	},
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
@@ -1863,6 +1866,7 @@ static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_SET_DST_MAC) |
 	(1U << EFX_MAE_ACTION_SET_SRC_MAC) |
 	(1U << EFX_MAE_ACTION_DECR_IP_TTL) |
+	(1U << EFX_MAE_ACTION_NAT) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	/*
 	 * HW will conduct action COUNT after
@@ -2038,6 +2042,14 @@ efx_mae_action_set_populate_decr_ip_ttl(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_nat(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_NAT, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_push(
 	__in				efx_mae_actions_t *spec,
@@ -3093,6 +3105,11 @@ efx_mae_action_set_alloc(
 		    MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
 	}
 
+	if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
+	}
+
 	if (spec->ema_n_vlan_tags_to_push > 0) {
 		unsigned int outer_tag_idx;
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 28a2be0a95..1ff760a024 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -104,6 +104,7 @@ INTERNAL {
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_mark_reset;
+	efx_mae_action_set_populate_nat;
 	efx_mae_action_set_populate_set_dst_mac;
 	efx_mae_action_set_populate_set_src_mac;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (25 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-21 16:50     ` Ferruh Yigit
  2023-06-07 13:02   ` [PATCH v4 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
                     ` (9 subsequent siblings)
  36 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

For this offload to work, the innermost pattern items must
provide the full set of exact match criteria, which are as
follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
and TP SRC, where the protocol types can be autodetected.

The offload requires that the IPv4 and the TP actions be
requested simultaneously in the same flow by the caller:
SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.

The offload operates on the outermost frame, which,
if action VXLAN_DECAP was requested, maps to the
inner frame of the original packet. The caller
is responsible to request this offload only
when the target header is an IPv4-based one.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/features/sfc.ini       |  4 ++
 doc/guides/nics/sfc_efx.rst            |  8 +++
 doc/guides/rel_notes/release_23_07.rst | 15 +++++
 drivers/net/sfc/sfc_mae.c              | 77 +++++++++++++++++++++++---
 4 files changed, 96 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index f5ac644278..19d4935ce6 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -75,8 +75,12 @@ port_representor     = Y
 represented_port     = Y
 queue                = Y
 rss                  = Y
+set_ipv4_dst         = Y
+set_ipv4_src         = Y
 set_mac_dst          = Y
 set_mac_src          = Y
+set_tp_dst           = Y
+set_tp_src           = Y
 vf                   = Y
 vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index de0656876b..6e974c3720 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -270,10 +270,18 @@ Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- SET_IPV4_DST
+
+- SET_IPV4_SRC
+
 - SET_MAC_DST
 
 - SET_MAC_SRC
 
+- SET_TP_DST
+
+- SET_TP_SRC
+
 - OF_DEC_NW_TTL
 
 - DEC_TTL
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index a9b1293689..6fae4eb0a7 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -55,6 +55,21 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Updated Solarflare network PMD.**
+
+  Updated the Solarflare ``sfc_efx`` driver with changes including:
+
+  * Added partial support for transfer flow actions SET_IPV4_DST,
+    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
+    It is required that the innermost pattern items provide the
+    full set of exact match criteria: EtherType, IP DST, IP SRC,
+    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
+    must be requested simultaneously in the same flow. These
+    actions operate on the outermost frame, at the point
+    where action VXLAN_DECAP (if any) has done its job.
+    The caller is responsible to request this offload
+    only when the target header is an IPv4-based one.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d3b4099213..c58a2520da 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -9,6 +9,7 @@
 
 #include <stdbool.h>
 
+#include <rte_byteorder.h>
 #include <rte_bitops.h>
 #include <rte_common.h>
 #include <rte_vxlan.h>
@@ -3444,6 +3445,8 @@ sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
+	SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
 };
 
 struct sfc_mae_actions_bundle {
@@ -3464,7 +3467,8 @@ struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      efx_mae_actions_t *spec)
+			      struct sfc_flow_spec_mae *flow_spec,
+			      bool ct, efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
@@ -3475,6 +3479,16 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 		rc = efx_mae_action_set_populate_vlan_push(
 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
+		flow_spec->ct_resp.nat.dir_is_dst = true;
+		/* FALLTHROUGH */
+	case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
+		if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
+		    flow_spec->ct_resp.nat.port_le != 0)
+			rc = efx_mae_action_set_populate_nat(spec);
+		else
+			rc = EINVAL;
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -3491,7 +3505,8 @@ sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
 static int
 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			    struct sfc_mae_actions_bundle *bundle,
-			    efx_mae_actions_t *spec,
+			    struct sfc_flow_spec_mae *flow_spec,
+			    efx_mae_actions_t *spec, bool ct,
 			    struct rte_flow_error *error)
 {
 	enum sfc_mae_actions_bundle_type bundle_type_new;
@@ -3503,6 +3518,14 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -3515,7 +3538,7 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 
 	if (bundle_type_new != bundle->type ||
 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
-		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
 		if (rc != 0)
 			goto fail_submit;
 
@@ -3532,6 +3555,20 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 			"Failed to request the (group of) action(s)");
 }
 
+static void
+sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
+				   uint32_t *nat_addr_le)
+{
+	*nat_addr_le = rte_bswap32(conf->ipv4_addr);
+}
+
+static void
+sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
+				   uint16_t *nat_port_le)
+{
+	*nat_port_le = rte_bswap16(conf->port);
+}
+
 static void
 sfc_mae_rule_parse_action_of_push_vlan(
 			    const struct rte_flow_action_of_push_vlan *conf,
@@ -4056,6 +4093,10 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
 	[RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
+	[RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
@@ -4075,12 +4116,12 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  const struct rte_flow *flow,
+			  struct rte_flow *flow,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
 {
-	const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
+	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4127,6 +4168,24 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_addr(action->conf,
+					&spec_mae->ct_resp.nat.ip_le);
+		break;
+	case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
+	case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
+				       bundle->actions_mask);
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_nat_port(action->conf,
+						&spec_mae->ct_resp.nat.port_le);
+		break;
 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
 				       bundle->actions_mask);
@@ -4285,6 +4344,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	struct sfc_mae_actions_bundle bundle = {0};
+	bool ct = (action_rule_ctx->ct_mark != 0);
 	const struct rte_flow_action *action;
 	struct sfc_mae_aset_ctx ctx = {0};
 	struct sfc_mae *mae = &sa->mae;
@@ -4335,8 +4395,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_actions_bundle_sync(action, &bundle,
-						 ctx.spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+						 ctx.spec, ct, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
@@ -4346,7 +4406,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			goto fail_rule_parse_action;
 	}
 
-	rc = sfc_mae_actions_bundle_sync(action, &bundle, ctx.spec, error);
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
+					 ctx.spec, ct, error);
 	if (rc != 0)
 		goto fail_rule_parse_action;
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 28/34] net/sfc: rename SW structures used by transfer flow counters
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (26 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
                     ` (8 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so facilitates rearrangements of the next patch needed
to make software counter objects shareable across many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 14 +++++++-------
 drivers/net/sfc/sfc_mae.h         | 14 +++++++-------
 drivers/net/sfc/sfc_mae_counter.c | 31 ++++++++++++++++---------------
 drivers/net/sfc/sfc_mae_counter.h | 16 ++++++++--------
 4 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index c58a2520da..2b4c821883 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -151,7 +151,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		if (rc != 0)
 			goto fail_mae_get_limits;
 
-		sfc_log_init(sa, "init MAE counter registry");
+		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
 						   limits.eml_max_n_counters);
 		if (rc != 0) {
@@ -817,7 +817,7 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counters,
+			struct sfc_mae_counter *counters,
 			unsigned int n_counters,
 			efx_mae_actions_t *action_set_spec)
 {
@@ -833,7 +833,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 	SFC_ASSERT(n_counters == 1);
 
-	rc = sfc_mae_counter_enable(sa, &counters[0]);
+	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
 	if (rc != 0) {
 		sfc_err(sa, "failed to enable MAE counter %u: %s",
 			counters[0].mae_id.id, rte_strerror(rc));
@@ -851,7 +851,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 	return 0;
 
 fail_fill_in_id:
-	(void)sfc_mae_counter_disable(sa, &counters[0]);
+	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 
 fail_counter_add:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
@@ -860,7 +860,7 @@ sfc_mae_counters_enable(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter_id *counters,
+			 struct sfc_mae_counter *counters,
 			 unsigned int n_counters)
 {
 	if (n_counters == 0)
@@ -874,7 +874,7 @@ sfc_mae_counters_disable(struct sfc_adapter *sa,
 		return EALREADY;
 	}
 
-	return sfc_mae_counter_disable(sa, &counters[0]);
+	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
 }
 
 struct sfc_mae_aset_ctx {
@@ -1039,7 +1039,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter_id *counters;
+	struct sfc_mae_counter *counters;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 67fa2ca5c9..7337fcf14d 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -68,7 +68,7 @@ struct sfc_mae_encap_header {
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
 /* Counter ID */
-struct sfc_mae_counter_id {
+struct sfc_mae_counter {
 	/* ID of a counter in MAE */
 	efx_counter_t			mae_id;
 	/* ID of a counter in RTE */
@@ -86,7 +86,7 @@ struct sfc_mae_counter_id {
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter_id	*counters;
+	struct sfc_mae_counter		*counters;
 	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
@@ -129,7 +129,7 @@ struct sfc_mae_bounce_eh {
 };
 
 /** Counter collection entry */
-struct sfc_mae_counter {
+struct sfc_mae_counter_record {
 	bool				inuse;
 	uint32_t			generation_count;
 	union sfc_pkts_bytes		value;
@@ -143,9 +143,9 @@ struct sfc_mae_counters_xstats {
 	uint64_t			realloc_update;
 };
 
-struct sfc_mae_counters {
+struct sfc_mae_counter_records {
 	/** An array of all MAE counters */
-	struct sfc_mae_counter		*mae_counters;
+	struct sfc_mae_counter_record	*mae_counters;
 	/** Extra statistics for counters */
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
@@ -162,7 +162,7 @@ enum sfc_mae_counter_polling_mode {
 struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Counters collection */
-	struct sfc_mae_counters		counters;
+	struct sfc_mae_counter_records	counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
@@ -219,7 +219,7 @@ struct sfc_mae {
 	struct sfc_mae_bounce_eh	bounce_eh;
 	/** Flag indicating whether counter-only RxQ is running */
 	bool				counter_rxq_running;
-	/** Counter registry */
+	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 818b4dad4a..8170175991 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -76,12 +76,12 @@ sfc_mae_counter_rxq_required(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_enable(struct sfc_adapter *sa,
-		       struct sfc_mae_counter_id *counterp)
+sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
@@ -147,12 +147,12 @@ sfc_mae_counter_enable(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counter_disable(struct sfc_adapter *sa,
-			struct sfc_mae_counter_id *counter)
+sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counters *counters = &reg->counters;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
@@ -189,12 +189,13 @@ sfc_mae_counter_disable(struct sfc_adapter *sa,
 
 static void
 sfc_mae_counter_increment(struct sfc_adapter *sa,
-			  struct sfc_mae_counters *counters,
+			  struct sfc_mae_counter_records *counters,
 			  uint32_t mae_counter_id,
 			  uint32_t generation_count,
 			  uint64_t pkts, uint64_t bytes)
 {
-	struct sfc_mae_counter *p = &counters->mae_counters[mae_counter_id];
+	struct sfc_mae_counter_record *p =
+		&counters->mae_counters[mae_counter_id];
 	struct sfc_mae_counters_xstats *xstats = &counters->xstats;
 	union sfc_pkts_bytes cnt_val;
 	bool inuse;
@@ -667,7 +668,7 @@ sfc_mae_counter_thread_spawn(struct sfc_adapter *sa,
 }
 
 int
-sfc_mae_counters_init(struct sfc_mae_counters *counters,
+sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 		      uint32_t nb_counters_max)
 {
 	int rc;
@@ -691,7 +692,7 @@ sfc_mae_counters_init(struct sfc_mae_counters *counters,
 }
 
 void
-sfc_mae_counters_fini(struct sfc_mae_counters *counters)
+sfc_mae_counters_fini(struct sfc_mae_counter_records *counters)
 {
 	rte_free(counters->mae_counters);
 	counters->mae_counters = NULL;
@@ -942,13 +943,13 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counters *counters,
-		    const struct sfc_mae_counter_id *counter,
+sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
 	uint64_t non_reset_tunnel_hit_counter;
-	struct sfc_mae_counter *p;
+	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
 	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 28d70f7d69..9c6d8103ac 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -38,15 +38,15 @@ void sfc_mae_counter_rxq_detach(struct sfc_adapter *sa);
 int sfc_mae_counter_rxq_init(struct sfc_adapter *sa);
 void sfc_mae_counter_rxq_fini(struct sfc_adapter *sa);
 
-int sfc_mae_counters_init(struct sfc_mae_counters *counters,
+int sfc_mae_counters_init(struct sfc_mae_counter_records *counters,
 			  uint32_t nb_counters_max);
-void sfc_mae_counters_fini(struct sfc_mae_counters *counters);
-int sfc_mae_counter_enable(struct sfc_adapter *sa,
-			   struct sfc_mae_counter_id *counterp);
-int sfc_mae_counter_disable(struct sfc_adapter *sa,
-			    struct sfc_mae_counter_id *counter);
-int sfc_mae_counter_get(struct sfc_mae_counters *counters,
-			const struct sfc_mae_counter_id *counter,
+void sfc_mae_counters_fini(struct sfc_mae_counter_records *counters);
+int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
+				   struct sfc_mae_counter *counterp);
+int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
+				    struct sfc_mae_counter *counter);
+int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
 int sfc_mae_counter_start(struct sfc_adapter *sa);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 29/34] net/sfc: rework MAE action rule counter representation in SW
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (27 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
                     ` (7 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Such rework is needed to prepare for INDIRECT action support
and in order to align with the latest HW support perspective.

Currently, the driver supports only one counter per flow. It
was once thought that MAE would support multiple counters in
one action set. That was partly envisaged in code and naming.
But HW support for the feature is no longer planned in EF100.

The code also assumes that a counter object cannot be shared.
This assumption is outdated. The driver may support this now
via action of type INDIRECT provided by generic flow library.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 342 +++++++++++++++++-------------
 drivers/net/sfc/sfc_mae.h         |  17 +-
 drivers/net/sfc/sfc_mae_counter.c |  22 +-
 3 files changed, 211 insertions(+), 170 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2b4c821883..4d3778eaba 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -205,6 +205,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->mac_addrs);
 	TAILQ_INIT(&mae->encap_headers);
+	TAILQ_INIT(&mae->counters);
 	TAILQ_INIT(&mae->action_sets);
 	TAILQ_INIT(&mae->action_rules);
 
@@ -816,72 +817,155 @@ sfc_mae_encap_header_disable(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_counters_enable(struct sfc_adapter *sa,
-			struct sfc_mae_counter *counters,
-			unsigned int n_counters,
-			efx_mae_actions_t *action_set_spec)
+sfc_mae_counter_add(struct sfc_adapter *sa,
+		    const struct sfc_mae_counter *counter_tmp,
+		    struct sfc_mae_counter **counterp)
 {
-	int rc;
+	struct sfc_mae_counter *counter;
+	struct sfc_mae *mae = &sa->mae;
 
-	sfc_log_init(sa, "entry");
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	if (n_counters == 0) {
-		sfc_log_init(sa, "no counters - skip");
-		return 0;
+	counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
+	if (counter == NULL)
+		return ENOMEM;
+
+	if (counter_tmp != NULL) {
+		counter->rte_id_valid = counter_tmp->rte_id_valid;
+		counter->rte_id = counter_tmp->rte_id;
 	}
 
-	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
+	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+	counter->refcnt = 1;
 
-	rc = sfc_mae_counter_fw_rsrc_enable(sa, &counters[0]);
-	if (rc != 0) {
-		sfc_err(sa, "failed to enable MAE counter %u: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_counter_add;
-	}
+	TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
+	*counterp = counter;
 
-	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
-						   &counters[0].mae_id);
-	if (rc != 0) {
-		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
-			counters[0].mae_id.id, rte_strerror(rc));
-		goto fail_fill_in_id;
-	}
+	sfc_dbg(sa, "added counter=%p", counter);
 
 	return 0;
+}
+
+static void
+sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae *mae = &sa->mae;
 
-fail_fill_in_id:
-	(void)sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	if (counter == NULL)
+		return;
 
-fail_counter_add:
-	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
-	return rc;
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(counter->refcnt != 0);
+
+	--(counter->refcnt);
+
+	if (counter->refcnt != 0)
+		return;
+
+	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
+	    counter->fw_rsrc.refcnt != 0) {
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
+			counter, counter->fw_rsrc.counter_id.id,
+			counter->fw_rsrc.refcnt);
+	}
+
+	TAILQ_REMOVE(&mae->counters, counter, entries);
+	rte_free(counter);
+
+	sfc_dbg(sa, "deleted counter=%p", counter);
 }
 
 static int
-sfc_mae_counters_disable(struct sfc_adapter *sa,
-			 struct sfc_mae_counter *counters,
-			 unsigned int n_counters)
+sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
+		       efx_mae_actions_t *action_set_spec)
 {
-	if (n_counters == 0)
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
 		return 0;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
-	SFC_ASSERT(n_counters == 1);
 
-	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
-		sfc_err(sa, "failed to disable: already disabled");
-		return EALREADY;
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
+
+		rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
+		if (rc != 0) {
+			sfc_err(sa, "failed to enable counter=%p: %s",
+				counter, rte_strerror(rc));
+			return rc;
+		}
+	}
+
+	if (action_set_spec != NULL) {
+		rc = efx_mae_action_set_fill_in_counter_id(
+					action_set_spec, &fw_rsrc->counter_id);
+		if (rc != 0) {
+			if (fw_rsrc->refcnt == 0) {
+				(void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
+				fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
+			}
+
+			sfc_err(sa, "cannot fill in counter ID: %s",
+				strerror(rc));
+			return rc;
+		}
+	}
+
+	if (fw_rsrc->refcnt == 0) {
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
+			counter, fw_rsrc->counter_id.id);
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static void
+sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc;
+	int rc;
+
+	if (counter == NULL)
+		return;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	fw_rsrc = &counter->fw_rsrc;
+
+	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
+	    fw_rsrc->refcnt == 0) {
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
+			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		return;
+	}
+
+	if (fw_rsrc->refcnt == 1) {
+		uint32_t counter_id = fw_rsrc->counter_id.id;
+
+		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
+		if (rc == 0) {
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
+				counter, counter_id);
+		} else {
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
+				counter, counter_id, strerror(rc));
+		}
+
+		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
 	}
 
-	return sfc_mae_counter_fw_rsrc_disable(sa, &counters[0]);
+	--(fw_rsrc->refcnt);
 }
 
 struct sfc_mae_aset_ctx {
-	uint64_t			*ft_switch_hit_counter;
-	struct sfc_ft_ctx		*counter_ft_ctx;
 	struct sfc_mae_encap_header	*encap_header;
-	unsigned int			n_counters;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_mac_addr		*dst_mac;
 	struct sfc_mae_mac_addr		*src_mac;
 
@@ -897,17 +981,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
-	/*
-	 * Shared counters are not supported, hence, action
-	 * sets with counters are not attachable.
-	 */
-	if (ctx->n_counters != 0)
-		return NULL;
-
 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
 		if (action_set->encap_header == ctx->encap_header &&
 		    action_set->dst_mac_addr == ctx->dst_mac &&
 		    action_set->src_mac_addr == ctx->src_mac &&
+		    action_set->counter == ctx->counter &&
 		    efx_mae_action_set_specs_equal(action_set->spec,
 						   ctx->spec)) {
 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
@@ -921,13 +999,11 @@ sfc_mae_action_set_attach(struct sfc_adapter *sa,
 
 static int
 sfc_mae_action_set_add(struct sfc_adapter *sa,
-		       const struct rte_flow_action actions[],
 		       const struct sfc_mae_aset_ctx *ctx,
 		       struct sfc_mae_action_set **action_setp)
 {
 	struct sfc_mae_action_set *action_set;
 	struct sfc_mae *mae = &sa->mae;
-	unsigned int i;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
@@ -937,49 +1013,12 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 		return ENOMEM;
 	}
 
-	if (ctx->n_counters > 0) {
-		const struct rte_flow_action *action;
-
-		action_set->counters = rte_malloc("sfc_mae_counter_ids",
-			sizeof(action_set->counters[0]) * ctx->n_counters, 0);
-		if (action_set->counters == NULL) {
-			rte_free(action_set);
-			sfc_err(sa, "failed to alloc counters");
-			return ENOMEM;
-		}
-
-		for (i = 0; i < ctx->n_counters; ++i) {
-			action_set->counters[i].rte_id_valid = B_FALSE;
-			action_set->counters[i].mae_id.id =
-				EFX_MAE_RSRC_ID_INVALID;
-
-			action_set->counters[i].ft_ctx = ctx->counter_ft_ctx;
-			action_set->counters[i].ft_switch_hit_counter =
-				ctx->ft_switch_hit_counter;
-		}
-
-		for (action = actions, i = 0;
-		     action->type != RTE_FLOW_ACTION_TYPE_END &&
-		     i < ctx->n_counters; ++action) {
-			const struct rte_flow_action_count *conf;
-
-			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
-				continue;
-
-			conf = action->conf;
-
-			action_set->counters[i].rte_id_valid = B_TRUE;
-			action_set->counters[i].rte_id = conf->id;
-			i++;
-		}
-		action_set->n_counters = ctx->n_counters;
-	}
-
 	action_set->refcnt = 1;
 	action_set->spec = ctx->spec;
 	action_set->encap_header = ctx->encap_header;
 	action_set->dst_mac_addr = ctx->dst_mac;
 	action_set->src_mac_addr = ctx->src_mac;
+	action_set->counter = ctx->counter;
 
 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
@@ -1020,12 +1059,7 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	sfc_mae_encap_header_del(sa, action_set->encap_header);
 	sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
 	sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
-	if (action_set->n_counters > 0) {
-		SFC_ASSERT(action_set->n_counters == 1);
-		SFC_ASSERT(action_set->counters[0].mae_id.id ==
-			   EFX_MAE_RSRC_ID_INVALID);
-		rte_free(action_set->counters);
-	}
+	sfc_mae_counter_del(sa, action_set->counter);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 
@@ -1039,7 +1073,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	struct sfc_mae_encap_header *encap_header;
 	struct sfc_mae_mac_addr *dst_mac_addr;
 	struct sfc_mae_mac_addr *src_mac_addr;
-	struct sfc_mae_counter *counters;
+	struct sfc_mae_counter *counter;
 	struct sfc_mae_fw_rsrc *fw_rsrc;
 	int rc;
 
@@ -1051,8 +1085,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 	encap_header = action_set->encap_header;
 	dst_mac_addr = action_set->dst_mac_addr;
 	src_mac_addr = action_set->src_mac_addr;
-	counters = action_set->counters;
 	fw_rsrc = &action_set->fw_rsrc;
+	counter = action_set->counter;
 
 	if (fw_rsrc->refcnt == 0) {
 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
@@ -1080,7 +1114,7 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			return rc;
 		}
 
-		if (action_set->n_counters > 0) {
+		if (counter != NULL) {
 			rc = sfc_mae_counter_start(sa);
 			if (rc != 0) {
 				sfc_err(sa, "failed to start MAE counters support: %s",
@@ -1092,13 +1126,8 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			}
 		}
 
-		rc = sfc_mae_counters_enable(sa, counters,
-					     action_set->n_counters,
-					     action_set->spec);
+		rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
 		if (rc != 0) {
-			sfc_err(sa, "failed to enable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
@@ -1111,11 +1140,10 @@ sfc_mae_action_set_enable(struct sfc_adapter *sa,
 			sfc_err(sa, "failed to enable action_set=%p: %s",
 				action_set, strerror(rc));
 
-			(void)sfc_mae_counters_disable(sa, counters,
-						       action_set->n_counters);
 			sfc_mae_encap_header_disable(sa, encap_header);
 			sfc_mae_mac_addr_disable(sa, src_mac_addr);
 			sfc_mae_mac_addr_disable(sa, dst_mac_addr);
+			sfc_mae_counter_disable(sa, counter);
 			return rc;
 		}
 
@@ -1160,16 +1188,10 @@ sfc_mae_action_set_disable(struct sfc_adapter *sa,
 		}
 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-		rc = sfc_mae_counters_disable(sa, action_set->counters,
-					      action_set->n_counters);
-		if (rc != 0) {
-			sfc_err(sa, "failed to disable %u MAE counters: %s",
-				action_set->n_counters, rte_strerror(rc));
-		}
-
 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
 		sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
 		sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
+		sfc_mae_counter_disable(sa, action_set->counter);
 	}
 
 	--(fw_rsrc->refcnt);
@@ -3929,10 +3951,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
-				const struct rte_flow_action_count *conf
-					__rte_unused,
+				const struct rte_flow_action_count *conf,
+				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
+	struct sfc_mae_counter counter_tmp = {};
 	int rc;
 
 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
@@ -3947,17 +3970,33 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		goto fail_no_service_core;
 	}
 
-	rc = efx_mae_action_set_populate_count(spec);
-	if (rc != 0) {
-		sfc_err(sa,
-			"failed to populate counters in MAE action set: %s",
-			rte_strerror(rc));
-		goto fail_populate_count;
+	if (*counterp != NULL) {
+		sfc_err(sa, "cannot request more than 1 action COUNT per flow");
+		rc = EINVAL;
+		goto fail_more_than_one;
+	}
+
+	if (spec != NULL) {
+		rc = efx_mae_action_set_populate_count(spec);
+		if (rc != 0) {
+			sfc_err(sa,
+				"failed to populate counters in MAE action set: %s",
+				rte_strerror(rc));
+			goto fail_populate_count;
+		}
+	}
+
+	if (conf != NULL) {
+		counter_tmp.rte_id_valid = true;
+		counter_tmp.rte_id = conf->id;
 	}
 
+	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
+
 	return 0;
 
 fail_populate_count:
+fail_more_than_one:
 fail_no_service_core:
 fail_counter_queue_uninit:
 
@@ -4124,7 +4163,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
+	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
+	efx_mae_actions_t *spec_ptr = spec;
 	unsigned int switch_port_type_mask;
 	bool custom_error = B_FALSE;
 	int rc = 0;
@@ -4212,7 +4253,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
-		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
+		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
@@ -4362,19 +4404,23 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_action_set_spec_init;
 
-	for (action = actions;
-	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
-			++(ctx.n_counters);
-	}
-
 	if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
+		bool have_user_action_count = false;
+
 		/* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
 		rc = efx_mae_action_set_populate_decap(ctx.spec);
 		if (rc != 0)
 			goto fail_enforce_ft_decap;
 
-		if (ctx.n_counters == 0 &&
+		for (action = actions;
+		     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+			if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+				have_user_action_count = true;
+				break;
+			}
+		}
+
+		if (!have_user_action_count &&
 		    sfc_mae_counter_stream_enabled(sa)) {
 			/*
 			 * The user opted not to use action COUNT in this rule,
@@ -4386,7 +4432,9 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			if (rc != 0)
 				goto fail_enforce_ft_count;
 
-			ctx.n_counters = 1;
+			rc = sfc_mae_counter_add(sa, NULL, &ctx.counter);
+			if (rc != 0)
+				goto fail_enforce_ft_count;
 		}
 	}
 
@@ -4416,13 +4464,6 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_process_encap_header;
 
-	if (ctx.n_counters > 1) {
-		rc = ENOTSUP;
-		sfc_err(sa, "too many count actions requested: %u",
-			ctx.n_counters);
-		goto fail_nb_count;
-	}
-
 	switch (spec_mae->ft_rule_type) {
 	case SFC_FT_RULE_NONE:
 		break;
@@ -4432,7 +4473,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_workaround_tunnel_delivery;
 
-		ctx.counter_ft_ctx = spec_mae->ft_ctx;
+		if (ctx.counter != NULL)
+			(ctx.counter)->ft_ctx = spec_mae->ft_ctx;
 		break;
 	case SFC_FT_RULE_SWITCH:
 		/*
@@ -4441,7 +4483,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		ctx.ft_switch_hit_counter =
+		(ctx.counter)->ft_switch_hit_counter =
 			&spec_mae->ft_ctx->switch_hit_counter;
 		break;
 	default:
@@ -4465,6 +4507,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, &ctx);
 	if (action_rule_ctx->action_set != NULL) {
+		sfc_mae_counter_del(sa, ctx.counter);
 		sfc_mae_mac_addr_del(sa, ctx.src_mac);
 		sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 		sfc_mae_encap_header_del(sa, ctx.encap_header);
@@ -4472,8 +4515,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		return 0;
 	}
 
-	rc = sfc_mae_action_set_add(sa, actions, &ctx,
-				    &action_rule_ctx->action_set);
+	rc = sfc_mae_action_set_add(sa, &ctx, &action_rule_ctx->action_set);
 	if (rc != 0)
 		goto fail_action_set_add;
 
@@ -4482,11 +4524,11 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 fail_action_set_add:
 fail_check_fate_action:
 fail_workaround_tunnel_delivery:
-fail_nb_count:
 	sfc_mae_encap_header_del(sa, ctx.encap_header);
 
 fail_process_encap_header:
 fail_rule_parse_action:
+	sfc_mae_counter_del(sa, ctx.counter);
 	sfc_mae_mac_addr_del(sa, ctx.src_mac);
 	sfc_mae_mac_addr_del(sa, ctx.dst_mac);
 	efx_mae_action_set_spec_fini(sa->nic, ctx.spec);
@@ -4766,28 +4808,22 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
 	struct sfc_mae_action_set *action_set;
-	unsigned int i;
+	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->n_counters == 0) {
+	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
 	}
 
 	action_set = action_rule->action_set;
+	counter = action_set->counter;
 
-	for (i = 0; i < action_set->n_counters; i++) {
-		/*
-		 * Get the first available counter of the flow rule if
-		 * counter ID is not specified, provided that this
-		 * counter is not an automatic (implicit) one.
-		 */
-		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
-			continue;
-
+	if (conf == NULL ||
+	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 &action_set->counters[i], data);
+					 counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 7337fcf14d..c73ce0a5e6 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -27,6 +27,7 @@ struct sfc_mae_fw_rsrc {
 	unsigned int			refcnt;
 	RTE_STD_C11
 	union {
+		efx_counter_t		counter_id;
 		efx_mae_aset_id_t	aset_id;
 		efx_mae_rule_id_t	rule_id;
 		efx_mae_mac_id_t	mac_id;
@@ -67,10 +68,11 @@ struct sfc_mae_encap_header {
 
 TAILQ_HEAD(sfc_mae_encap_headers, sfc_mae_encap_header);
 
-/* Counter ID */
+/* Counter object registry entry */
 struct sfc_mae_counter {
-	/* ID of a counter in MAE */
-	efx_counter_t			mae_id;
+	TAILQ_ENTRY(sfc_mae_counter)	entries;
+	unsigned int			refcnt;
+
 	/* ID of a counter in RTE */
 	uint32_t			rte_id;
 	/* RTE counter ID validity status */
@@ -80,18 +82,21 @@ struct sfc_mae_counter {
 	uint64_t			*ft_switch_hit_counter;
 	/* Flow Tunnel (FT) context (for TUNNEL rules; otherwise, NULL) */
 	struct sfc_ft_ctx		*ft_ctx;
+
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
+TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
-	struct sfc_mae_counter		*counters;
-	uint32_t			n_counters;
 	efx_mae_actions_t		*spec;
 	struct sfc_mae_encap_header	*encap_header;
 	struct sfc_mae_mac_addr		*dst_mac_addr;
 	struct sfc_mae_mac_addr		*src_mac_addr;
+	struct sfc_mae_counter		*counter;
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
@@ -221,6 +226,8 @@ struct sfc_mae {
 	bool				counter_rxq_running;
 	/** Counter record registry */
 	struct sfc_mae_counter_registry	counter_registry;
+	/** Counter object registry */
+	struct sfc_mae_counters		counters;
 	/**
 	 * Switchdev default rules. They forward traffic from PHY port
 	 * to PF and vice versa.
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 8170175991..90b89e81c6 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -110,7 +110,7 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 		goto fail_counter_id_range;
 	}
 
-	counterp->mae_id = mae_counter;
+	counterp->fw_rsrc.counter_id.id = mae_counter.id;
 
 	p = &counters->mae_counters[mae_counter.id];
 
@@ -152,29 +152,27 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
 	struct sfc_mae_counter_records *counters = &reg->counters;
+	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
-	if (counter->mae_id.id == EFX_MAE_RSRC_ID_INVALID)
-		return 0;
-
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
+	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
 	 * at the beginning of delete operation. Release ordering is
 	 * paired with acquire ordering on load in counter increment operation.
 	 */
-	p = &counters->mae_counters[counter->mae_id.id];
+	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, &counter->mae_id, NULL);
+	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
 	if (rc != 0)
 		sfc_err(sa, "failed to free MAE counter %u: %s",
-			counter->mae_id.id, rte_strerror(rc));
+			mae_counter->id, rte_strerror(rc));
 
 	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, counter->mae_id.id,
+		 " bytes=%" PRIu64, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -182,7 +180,7 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	 * If there's some error, the resulting resource leakage is bad, but
 	 * nothing sensible can be done in this case.
 	 */
-	counter->mae_id.id = EFX_MAE_RSRC_ID_INVALID;
+	mae_counter->id = EFX_MAE_RSRC_ID_INVALID;
 
 	return rc;
 }
@@ -952,8 +950,8 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
 
-	SFC_ASSERT(counter->mae_id.id < counters->n_mae_counters);
-	p = &counters->mae_counters[counter->mae_id.id];
+	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
+	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
 
 	/*
 	 * Ordering is relaxed since it is the only operation on counter value.
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 30/34] net/sfc: support indirect count action in transfer flows
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (28 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
                     ` (6 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Indirect count action is useful to applications that
need to gather aggregated statistics for many flows.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst            |   2 +
 doc/guides/rel_notes/release_23_07.rst |   3 +
 drivers/net/sfc/sfc.h                  |   1 +
 drivers/net/sfc/sfc_flow.c             | 126 +++++++++++++++++++
 drivers/net/sfc/sfc_flow.h             |  14 +++
 drivers/net/sfc/sfc_mae.c              | 167 ++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h              |  15 +++
 7 files changed, 327 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 6e974c3720..ba82b02093 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -306,6 +306,8 @@ Supported actions (***transfer*** rules):
 
 - COUNT
 
+- INDIRECT
+
 - DROP
 
 Validating flow rules depends on the firmware variant.
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index 6fae4eb0a7..5a77b71d0a 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -70,6 +70,9 @@ New Features
     The caller is responsible to request this offload
     only when the target header is an IPv4-based one.
 
+  * Added support for transfer flow action INDIRECT
+    with subtype COUNT, for aggregated statistics.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 6b301aad60..f84a21009e 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -248,6 +248,7 @@ struct sfc_adapter {
 	struct sfc_tbls			hw_tables;
 	struct sfc_repr_proxy		repr_proxy;
 
+	struct sfc_flow_indir_actions	flow_indir_actions;
 	struct sfc_flow_list		flow_list;
 
 	unsigned int			rxq_max;
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 0abeabfbf2..a35f20770d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static struct rte_flow_action_handle *
+sfc_flow_action_handle_create(struct rte_eth_dev *dev,
+			      const struct rte_flow_indir_action_conf *conf,
+			      const struct rte_flow_action *action,
+			      struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *handle;
+	int ret;
+
+	if (!conf->transfer) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "non-transfer domain does not support indirect actions");
+		return NULL;
+	}
+
+	if (conf->ingress || conf->egress) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "cannot combine ingress/egress with transfer");
+		return NULL;
+	}
+
+	handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0);
+	if (handle == NULL) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "failed to allocate memory");
+		return NULL;
+	}
+
+	sfc_adapter_lock(sa);
+
+	ret = sfc_mae_indir_action_create(sa, action, handle, error);
+	if (ret != 0) {
+		sfc_adapter_unlock(sa);
+		rte_free(handle);
+		return NULL;
+	}
+
+	TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);
+
+	handle->transfer = (bool)conf->transfer;
+
+	sfc_adapter_unlock(sa);
+
+	return handle;
+}
+
+static int
+sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,
+			       struct rte_flow_action_handle *handle,
+			       struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_destroy(sa, handle,
+							  error);
+			if (rc != 0)
+				goto exit;
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);
+		rte_free(entry);
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
+static int
+sfc_flow_action_handle_query(struct rte_eth_dev *dev,
+			     const struct rte_flow_action_handle *handle,
+			     void *data, struct rte_flow_error *error)
+{
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+	struct rte_flow_action_handle *entry;
+	int rc = EINVAL;
+
+	sfc_adapter_lock(sa);
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry != handle)
+			continue;
+
+		if (entry->transfer) {
+			rc = sfc_mae_indir_action_query(sa, handle,
+							data, error);
+		} else {
+			SFC_ASSERT(B_FALSE);
+		}
+
+		goto exit;
+	}
+
+	rc = rte_flow_error_set(error, ENOENT,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"indirect action handle not found");
+
+exit:
+	sfc_adapter_unlock(sa);
+	return rc;
+}
+
 const struct rte_flow_ops sfc_flow_ops = {
 	.validate = sfc_flow_validate,
 	.create = sfc_flow_create,
@@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = {
 	.flush = sfc_flow_flush,
 	.query = sfc_flow_query,
 	.isolate = sfc_flow_isolate,
+	.action_handle_create = sfc_flow_action_handle_create,
+	.action_handle_destroy = sfc_flow_action_handle_destroy,
+	.action_handle_query = sfc_flow_action_handle_query,
 	.tunnel_decap_set = sfc_ft_decap_set,
 	.tunnel_match = sfc_ft_match,
 	.tunnel_action_decap_release = sfc_ft_action_decap_release,
@@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa)
 {
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+	TAILQ_INIT(&sa->flow_indir_actions);
 	TAILQ_INIT(&sa->flow_list);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 8f706fc589..af94d0654a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -88,6 +88,20 @@ struct sfc_flow_spec_mae {
 	sfc_mae_conntrack_key_t		ct_key;
 };
 
+/* PMD-specific definition of the opaque type from rte_flow.h */
+struct rte_flow_action_handle {
+	TAILQ_ENTRY(rte_flow_action_handle)	entries;
+
+	bool					transfer;
+	enum rte_flow_action_type		type;
+
+	union {
+		struct sfc_mae_counter		*counter;
+	};
+};
+
+TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle);
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 4d3778eaba..e79df3b56a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -4003,6 +4003,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa,
+				   const struct rte_flow_action_handle *handle,
+				   enum sfc_ft_rule_type ft_rule_type,
+				   struct sfc_mae_aset_ctx *ctx,
+				   struct rte_flow_error *error)
+{
+	struct rte_flow_action_handle *entry;
+	int rc;
+
+	TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
+		if (entry == handle) {
+			sfc_dbg(sa, "attaching to indirect_action=%p", entry);
+
+			switch (entry->type) {
+			case RTE_FLOW_ACTION_TYPE_COUNT:
+				if (ft_rule_type != SFC_FT_RULE_NONE) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot use indirect count action in tunnel model");
+				}
+
+				if (ctx->counter != NULL) {
+					return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "cannot have multiple actions COUNT in one flow");
+				}
+
+				rc = efx_mae_action_set_populate_count(ctx->spec);
+				if (rc != 0) {
+					return rte_flow_error_set(error, rc,
+					 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					 "failed to add COUNT to MAE action set");
+				}
+
+				ctx->counter = entry->counter;
+				++(ctx->counter->refcnt);
+				break;
+			default:
+				SFC_ASSERT(B_FALSE);
+				break;
+			}
+
+			return 0;
+		}
+	}
+
+	return rte_flow_error_set(error, ENOENT,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				  "indirect action handle not found");
+}
+
 static int
 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
 				const struct rte_flow_action_vf *vf_conf,
@@ -4141,6 +4193,7 @@ static const char * const action_names[] = {
 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
 	[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
 	[RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT",
+	[RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT",
 	[RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
 	[RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
 	[RTE_FLOW_ACTION_TYPE_PF] = "PF",
@@ -4256,6 +4309,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
 						     counterp, spec_ptr);
 		break;
+	case RTE_FLOW_ACTION_TYPE_INDIRECT:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_indirect(sa, action->conf,
+							spec_mae->ft_rule_type,
+							ctx, error);
+		custom_error = B_TRUE;
+		break;
 	case RTE_FLOW_ACTION_TYPE_FLAG:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
 				       bundle->actions_mask);
@@ -4811,7 +4872,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 	struct sfc_mae_counter *counter;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set->counter == NULL) {
+	if (action_rule == NULL || action_rule->action_set == NULL ||
+	    action_rule->action_set->counter == NULL ||
+	    action_rule->action_set->counter->indirect) {
 		return rte_flow_error_set(error, EINVAL,
 			RTE_FLOW_ERROR_TYPE_ACTION, action,
 			"Queried flow rule does not have count actions");
@@ -4922,3 +4985,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa)
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
 	sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
 }
+
+int
+sfc_mae_indir_action_create(struct sfc_adapter *sa,
+			    const struct rte_flow_action *action,
+			    struct rte_flow_action_handle *handle,
+			    struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      &handle->counter, NULL);
+		if (ret == 0)
+			handle->counter->indirect = true;
+		break;
+	default:
+		ret = ENOTSUP;
+	}
+
+	if (ret != 0) {
+		return rte_flow_error_set(error, ret,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"failed to parse indirect action to mae object");
+	}
+
+	handle->type = action->type;
+
+	return 0;
+}
+
+int
+sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+			     const struct rte_flow_action_handle *handle,
+			     struct rte_flow_error *error)
+{
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		if (handle->counter->refcnt != 1)
+			goto fail;
+
+		sfc_mae_counter_del(sa, handle->counter);
+		break;
+	default:
+		SFC_ASSERT(B_FALSE);
+		break;
+	}
+
+	return 0;
+
+fail:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is still in use");
+}
+
+int
+sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			   const struct rte_flow_action_handle *handle,
+			   void *data, struct rte_flow_error *error)
+{
+	int ret;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(handle != NULL);
+
+	switch (handle->type) {
+	case RTE_FLOW_ACTION_TYPE_COUNT:
+		SFC_ASSERT(handle->counter != NULL);
+
+		if (handle->counter->fw_rsrc.refcnt == 0)
+			goto fail_not_in_use;
+
+		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
+					  handle->counter, data);
+		if (ret != 0)
+			goto fail_counter_get;
+
+		break;
+	default:
+		goto fail_unsup;
+	}
+
+	return 0;
+
+fail_not_in_use:
+	return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action is not in use");
+
+fail_counter_get:
+	return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "failed to collect indirect action COUNT data");
+
+fail_unsup:
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "indirect action of this type cannot be queried");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index c73ce0a5e6..e7b7d3a35e 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -84,6 +84,8 @@ struct sfc_mae_counter {
 	struct sfc_ft_ctx		*ft_ctx;
 
 	struct sfc_mae_fw_rsrc		fw_rsrc;
+
+	bool				indirect;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow);
 int sfc_mae_switchdev_init(struct sfc_adapter *sa);
 void sfc_mae_switchdev_fini(struct sfc_adapter *sa);
 
+int sfc_mae_indir_action_create(struct sfc_adapter *sa,
+				const struct rte_flow_action *action,
+				struct rte_flow_action_handle *handle,
+				struct rte_flow_error *error);
+
+int sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
+				 const struct rte_flow_action_handle *handle,
+				 struct rte_flow_error *error);
+
+int sfc_mae_indir_action_query(struct sfc_adapter *sa,
+			       const struct rte_flow_action_handle *handle,
+			       void *data, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (29 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
                     ` (5 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so is required to disambiguate counters of different
types supported by the match-action engine (MAE) on EF100.

Currently, the code only supports action rule counters,
but MAE may also support conntrack assistance counters.
Add type-aware allocate and free MCDI handlers and
extend reporting of counter limits accordingly.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  39 +++++++-
 drivers/common/sfc_efx/base/efx_impl.h |   2 +-
 drivers/common/sfc_efx/base/efx_mae.c  | 120 ++++++++++++++++++++-----
 drivers/common/sfc_efx/version.map     |   2 +
 4 files changed, 140 insertions(+), 23 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index a296d34f29..5a2e05134a 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,7 +4191,10 @@ typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_outer_prios;
 	uint32_t			eml_encap_types_supported;
 	uint32_t			eml_encap_header_size_limit;
-	uint32_t			eml_max_n_counters;
+	union {
+		uint32_t		eml_max_n_counters;
+		uint32_t		eml_max_n_action_counters;
+	};
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4780,6 +4783,14 @@ efx_mae_action_set_fill_in_eh_id(
 	__in				efx_mae_actions_t *spec,
 	__in				const efx_mae_eh_id_t *eh_idp);
 
+/*
+ * Counter types that may be supported by the match-action engine.
+ * Each counter type maintains its own counter ID namespace in FW.
+ */
+typedef enum efx_counter_type_e {
+	EFX_COUNTER_TYPE_ACTION = 0,
+} efx_counter_type_t;
+
 typedef struct efx_counter_s {
 	uint32_t id;
 } efx_counter_t;
@@ -4809,6 +4820,8 @@ efx_mae_action_set_alloc(
 	__out				efx_mae_aset_id_t *aset_idp);
 
 /*
+ * Allocates MAE counter(s) of type EFX_COUNTER_TYPE_ACTION.
+ *
  * Generation count has two purposes:
  *
  * 1) Distinguish between counter packets that belong to freed counter
@@ -4832,6 +4845,20 @@ efx_mae_counters_alloc(
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+/*
+ * Allocates MAE counter(s) of the specified type. Other
+ * than that, behaves like efx_mae_counters_alloc().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_alloc_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_counters_free(
@@ -4841,6 +4868,16 @@ efx_mae_counters_free(
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp);
+
 /* When set, include counters with a value of zero */
 #define	EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE	(1U << 0)
 
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index e978ad0de8..f6b472c160 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -841,7 +841,7 @@ typedef struct efx_mae_s {
 	/** Outer rule match field capabilities. */
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
-	uint32_t			em_max_ncounters;
+	uint32_t			em_max_n_action_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index aaea38c933..4078146741 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -67,8 +67,8 @@ efx_mae_get_capabilities(
 	maep->em_max_nfields =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
 
-	maep->em_max_ncounters =
-	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS);
+	maep->em_max_n_action_counters =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
 	return (0);
 
@@ -374,7 +374,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
-	emlp->eml_max_n_counters = maep->em_max_ncounters;
+	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
 
 	return (0);
 
@@ -3256,55 +3256,70 @@ efx_mae_action_set_fill_in_counter_id(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_alloc(
+efx_mae_counters_alloc_type(
 	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
 	__in				uint32_t n_counters,
 	__out				uint32_t *n_allocatedp,
 	__out_ecount(n_counters)	efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_ALLOC_IN_LEN,
+	    MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	uint32_t n_allocated;
 	efx_mcdi_req_t req;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (n_counters > max_n_counters ||
 	    n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
 	    n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
 		rc = EINVAL;
-		goto fail1;
+		goto fail2;
 	}
 
 	req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
 
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
 	    n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_allocated = MCDI_OUT_DWORD(req,
 	    MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
 	if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	for (i = 0; i < n_allocated; i++) {
@@ -3321,6 +3336,8 @@ efx_mae_counters_alloc(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3334,33 +3351,67 @@ efx_mae_counters_alloc(
 }
 
 	__checkReturn			efx_rc_t
-efx_mae_counters_free(
+efx_mae_counters_alloc(
 	__in				efx_nic_t *enp,
 	__in				uint32_t n_counters,
+	__out				uint32_t *n_allocatedp,
+	__out_ecount(n_counters)	efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
+					 n_counters, n_allocatedp,
+					 countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_counters_free_type(
+	__in				efx_nic_t *enp,
+	__in				efx_counter_type_t type,
+	__in				uint32_t n_counters,
 	__out				uint32_t *n_freedp,
 	__in_ecount(n_counters)		const efx_counter_t *countersp,
 	__out_opt			uint32_t *gen_countp)
 {
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
 	    MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
 	efx_mae_t *maep = enp->en_maep;
+	uint32_t max_n_counters;
 	efx_mcdi_req_t req;
 	uint32_t n_freed;
 	unsigned int i;
 	efx_rc_t rc;
 
-	if (n_counters > maep->em_max_ncounters ||
-	    n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM ||
-	    n_counters >
-	    MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+	switch (type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		max_n_counters = maep->em_max_n_action_counters;
+		break;
+	default:
 		rc = EINVAL;
 		goto fail1;
 	}
 
+	if (n_counters > max_n_counters ||
+	    n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
+	    n_counters >
+	    MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
 	req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters);
+	req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
 
@@ -3371,23 +3422,25 @@ efx_mae_counters_free(
 	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
 			  n_counters);
 
+	MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail2;
+		goto fail3;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
 		rc = EMSGSIZE;
-		goto fail3;
+		goto fail4;
 	}
 
 	n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
 
 	if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
 		rc = EFAULT;
-		goto fail4;
+		goto fail5;
 	}
 
 	if (gen_countp != NULL) {
@@ -3399,6 +3452,8 @@ efx_mae_counters_free(
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -3411,6 +3466,29 @@ efx_mae_counters_free(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_counters_free(
+	__in				efx_nic_t *enp,
+	__in				uint32_t n_counters,
+	__out				uint32_t *n_freedp,
+	__in_ecount(n_counters)		const efx_counter_t *countersp,
+	__out_opt			uint32_t *gen_countp)
+{
+	efx_rc_t rc;
+
+	rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
+					n_counters, n_freedp,
+					countersp, gen_countp);
+	if (rc != 0)
+		goto fail1;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_counters_stream_start(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 1ff760a024..e550b64be6 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -113,7 +113,9 @@ INTERNAL {
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
 	efx_mae_counters_alloc;
+	efx_mae_counters_alloc_type;
 	efx_mae_counters_free;
+	efx_mae_counters_free_type;
 	efx_mae_counters_stream_give_credits;
 	efx_mae_counters_stream_start;
 	efx_mae_counters_stream_stop;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 32/34] net/sfc: indicate MAE counter type in use for transfer flows
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (30 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
                     ` (4 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Doing so assists adding support for additional counter types.

Current implementation is only aware of action rule counters
that are supported by the match-action engine (MAE) on EF100
NICs, but MAE may also support conntrack assistance counters.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c         | 56 ++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |  7 ++-
 drivers/net/sfc/sfc_mae_counter.c | 77 +++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae_counter.h |  2 +-
 4 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index e79df3b56a..7353d04af8 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,15 +65,24 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_counters_max)
+			      uint32_t nb_action_counters_max)
 {
-	return sfc_mae_counters_init(&registry->counters, nb_counters_max);
+	int ret;
+
+	ret = sfc_mae_counters_init(&registry->action_counters,
+				    nb_action_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
+
+	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
-	sfc_mae_counters_fini(&registry->counters);
+	sfc_mae_counters_fini(&registry->action_counters);
 }
 
 struct rte_flow *
@@ -153,10 +162,10 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-						   limits.eml_max_n_counters);
+					limits.eml_max_n_action_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init MAE counters registry for %u entries: %s",
-				limits.eml_max_n_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
+				limits.eml_max_n_action_counters, rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -833,6 +842,9 @@ sfc_mae_counter_add(struct sfc_adapter *sa,
 	if (counter_tmp != NULL) {
 		counter->rte_id_valid = counter_tmp->rte_id_valid;
 		counter->rte_id = counter_tmp->rte_id;
+		counter->type = counter_tmp->type;
+	} else {
+		counter->type = EFX_COUNTER_TYPE_ACTION;
 	}
 
 	counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -864,8 +876,8 @@ sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
 	    counter->fw_rsrc.refcnt != 0) {
-		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%08x, refcnt=%u",
-			counter, counter->fw_rsrc.counter_id.id,
+		sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, counter->fw_rsrc.counter_id.id,
 			counter->fw_rsrc.refcnt);
 	}
 
@@ -916,8 +928,8 @@ sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
 	}
 
 	if (fw_rsrc->refcnt == 0) {
-		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%08x",
-			counter, fw_rsrc->counter_id.id);
+		sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%x-#%u",
+			counter, counter->type, fw_rsrc->counter_id.id);
 	}
 
 	++(fw_rsrc->refcnt);
@@ -940,8 +952,8 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 	if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
 	    fw_rsrc->refcnt == 0) {
-		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%08x, refcnt=%u",
-			counter, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
+		sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%x-#%u, refcnt=%u",
+			counter, counter->type, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
 		return;
 	}
 
@@ -950,11 +962,11 @@ sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
 
 		rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
 		if (rc == 0) {
-			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%08x",
-				counter, counter_id);
+			sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%x-#%u",
+				counter, counter->type, counter_id);
 		} else {
-			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%08x: %s",
-				counter, counter_id, strerror(rc));
+			sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%x-#%u: %s",
+				counter, counter->type, counter_id, strerror(rc));
 		}
 
 		fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -3952,6 +3964,7 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 				const struct rte_flow_action_count *conf,
+				efx_counter_type_t mae_counter_type,
 				struct sfc_mae_counter **counterp,
 				efx_mae_actions_t *spec)
 {
@@ -3991,6 +4004,8 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
 		counter_tmp.rte_id = conf->id;
 	}
 
+	counter_tmp.type = mae_counter_type;
+
 	return sfc_mae_counter_add(sa, &counter_tmp, counterp);
 
 	return 0;
@@ -4215,6 +4230,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 {
 	struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
+	efx_counter_type_t mae_counter_type = EFX_COUNTER_TYPE_ACTION;
 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
 	struct sfc_mae_counter **counterp = &ctx->counter;
 	efx_mae_actions_t *spec = ctx->spec;
@@ -4307,6 +4323,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_count(sa, action->conf,
+						     mae_counter_type,
 						     counterp, spec_ptr);
 		break;
 	case RTE_FLOW_ACTION_TYPE_INDIRECT:
@@ -4885,8 +4902,7 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 
 	if (conf == NULL ||
 	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					 counter, data);
+		rc = sfc_mae_counter_get(sa, counter, data);
 		if (rc != 0) {
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5000,6 +5016,7 @@ sfc_mae_indir_action_create(struct sfc_adapter *sa,
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_COUNT:
 		ret = sfc_mae_rule_parse_action_count(sa, action->conf,
+						      EFX_COUNTER_TYPE_ACTION,
 						      &handle->counter, NULL);
 		if (ret == 0)
 			handle->counter->indirect = true;
@@ -5063,8 +5080,7 @@ sfc_mae_indir_action_query(struct sfc_adapter *sa,
 		if (handle->counter->fw_rsrc.refcnt == 0)
 			goto fail_not_in_use;
 
-		ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
-					  handle->counter, data);
+		ret = sfc_mae_counter_get(sa, handle->counter, data);
 		if (ret != 0)
 			goto fail_counter_get;
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index e7b7d3a35e..3a3a5225fd 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -86,6 +86,7 @@ struct sfc_mae_counter {
 	struct sfc_mae_fw_rsrc		fw_rsrc;
 
 	bool				indirect;
+	efx_counter_type_t		type;
 };
 
 TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter);
@@ -157,6 +158,8 @@ struct sfc_mae_counter_records {
 	struct sfc_mae_counters_xstats	xstats;
 	/** Count of all MAE counters */
 	unsigned int			n_mae_counters;
+	/** Counter type, for logging */
+	efx_counter_type_t		type;
 };
 
 /** Options for MAE counter polling mode */
@@ -168,8 +171,8 @@ enum sfc_mae_counter_polling_mode {
 
 struct sfc_mae_counter_registry {
 	/* Common counter information */
-	/** Counters collection */
-	struct sfc_mae_counter_records	counters;
+	/** Action rule counter record collection */
+	struct sfc_mae_counter_records	action_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 90b89e81c6..47448cba15 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -80,19 +80,28 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 			       struct sfc_mae_counter *counterp)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	efx_counter_t mae_counter;
 	uint32_t generation_count;
 	uint32_t unused;
 	int rc;
 
+	switch (counterp->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		rc = EINVAL;
+		goto fail_counter_type_check;
+	}
+
 	/*
 	 * The actual count of counters allocated is ignored since a failure
 	 * to allocate a single counter is indicated by non-zero return code.
 	 */
-	rc = efx_mae_counters_alloc(sa->nic, 1, &unused, &mae_counter,
-				    &generation_count);
+	rc = efx_mae_counters_alloc_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, &generation_count);
 	if (rc != 0) {
 		sfc_err(sa, "failed to alloc MAE counter: %s",
 			rte_strerror(rc));
@@ -132,16 +141,18 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	 */
 	__atomic_store_n(&p->inuse, true, __ATOMIC_RELEASE);
 
-	sfc_info(sa, "enabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter.id,
+	sfc_info(sa, "enabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counterp->type, mae_counter.id,
 		 p->reset.pkts, p->reset.bytes);
 
 	return 0;
 
 fail_counter_id_range:
-	(void)efx_mae_counters_free(sa->nic, 1, &unused, &mae_counter, NULL);
+	(void)efx_mae_counters_free_type(sa->nic, counterp->type, 1, &unused,
+					 &mae_counter, NULL);
 
 fail_mae_counter_alloc:
+fail_counter_type_check:
 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 	return rc;
 }
@@ -151,12 +162,20 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				struct sfc_mae_counter *counter)
 {
 	struct sfc_mae_counter_registry *reg = &sa->mae.counter_registry;
-	struct sfc_mae_counter_records *counters = &reg->counters;
 	efx_counter_t *mae_counter = &counter->fw_rsrc.counter_id;
+	struct sfc_mae_counter_records *counters;
 	struct sfc_mae_counter_record *p;
 	uint32_t unused;
 	int rc;
 
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &reg->action_counters;
+		break;
+	default:
+		return EINVAL;
+	}
+
 	SFC_ASSERT(mae_counter->id < counters->n_mae_counters);
 	/*
 	 * The flag is set at the very end of add operation and reset
@@ -166,13 +185,14 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	p = &counters->mae_counters[mae_counter->id];
 	__atomic_store_n(&p->inuse, false, __ATOMIC_RELEASE);
 
-	rc = efx_mae_counters_free(sa->nic, 1, &unused, mae_counter, NULL);
+	rc = efx_mae_counters_free_type(sa->nic, counter->type, 1, &unused,
+					mae_counter, NULL);
 	if (rc != 0)
-		sfc_err(sa, "failed to free MAE counter %u: %s",
-			mae_counter->id, rte_strerror(rc));
+		sfc_err(sa, "failed to free MAE counter 0x%x-#%u: %s",
+			counter->type, mae_counter->id, rte_strerror(rc));
 
-	sfc_info(sa, "disabled MAE counter #%u with reset pkts=%" PRIu64
-		 " bytes=%" PRIu64, mae_counter->id,
+	sfc_info(sa, "disabled MAE counter 0x%x-#%u with reset pkts=%" PRIu64
+		 " bytes=%" PRIu64, counter->type, mae_counter->id,
 		 p->reset.pkts, p->reset.bytes);
 
 	/*
@@ -243,8 +263,8 @@ sfc_mae_counter_increment(struct sfc_adapter *sa,
 				 __ATOMIC_RELAXED);
 	}
 
-	sfc_info(sa, "update MAE counter #%u: pkts+%" PRIu64 "=%" PRIu64
-		 ", bytes+%" PRIu64 "=%" PRIu64, mae_counter_id,
+	sfc_info(sa, "update MAE counter 0x%x-#%u: pkts+%" PRIu64 "=%" PRIu64
+		 ", bytes+%" PRIu64 "=%" PRIu64, counters->type, mae_counter_id,
 		 pkts, cnt_val.pkts, bytes, cnt_val.bytes);
 }
 
@@ -253,6 +273,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			     struct sfc_mae_counter_registry *counter_registry,
 			     const struct rte_mbuf *m)
 {
+	struct sfc_mae_counter_records *counters;
 	uint32_t generation_count;
 	const efx_xword_t *hdr;
 	const efx_oword_t *counters_data;
@@ -293,7 +314,12 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	}
 
 	id = EFX_XWORD_FIELD(*hdr, ERF_SC_PACKETISER_HEADER_IDENTIFIER);
-	if (unlikely(id != ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR)) {
+
+	switch (id) {
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
+		counters = &counter_registry->action_counters;
+		break;
+	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
 	}
@@ -367,7 +393,7 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
 		sfc_mae_counter_increment(sa,
-			&counter_registry->counters,
+			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_COUNTER_INDEX),
 			generation_count,
@@ -941,14 +967,25 @@ sfc_mae_counter_start(struct sfc_adapter *sa)
 }
 
 int
-sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+sfc_mae_counter_get(struct sfc_adapter *sa,
 		    const struct sfc_mae_counter *counter,
 		    struct rte_flow_query_count *data)
 {
 	struct sfc_ft_ctx *ft_ctx = counter->ft_ctx;
+	struct sfc_mae_counter_records *counters;
 	uint64_t non_reset_tunnel_hit_counter;
 	struct sfc_mae_counter_record *p;
 	union sfc_pkts_bytes value;
+	bool need_byte_count;
+
+	switch (counter->type) {
+	case EFX_COUNTER_TYPE_ACTION:
+		counters = &sa->mae.counter_registry.action_counters;
+		need_byte_count = true;
+		break;
+	default:
+		return EINVAL;
+	}
 
 	SFC_ASSERT(counter->fw_rsrc.counter_id.id < counters->n_mae_counters);
 	p = &counters->mae_counters[counter->fw_rsrc.counter_id.id];
@@ -968,7 +1005,7 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 		data->hits += ft_ctx->switch_hit_counter;
 		non_reset_tunnel_hit_counter = data->hits;
 		data->hits -= ft_ctx->reset_tunnel_hit_counter;
-	} else {
+	} else if (need_byte_count) {
 		data->bytes_set = 1;
 		data->bytes = value.bytes - p->reset.bytes;
 	}
@@ -979,7 +1016,9 @@ sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
 				non_reset_tunnel_hit_counter;
 		} else {
 			p->reset.pkts = value.pkts;
-			p->reset.bytes = value.bytes;
+
+			if (need_byte_count)
+				p->reset.bytes = value.bytes;
 		}
 	}
 
diff --git a/drivers/net/sfc/sfc_mae_counter.h b/drivers/net/sfc/sfc_mae_counter.h
index 9c6d8103ac..effb037799 100644
--- a/drivers/net/sfc/sfc_mae_counter.h
+++ b/drivers/net/sfc/sfc_mae_counter.h
@@ -45,7 +45,7 @@ int sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 				   struct sfc_mae_counter *counterp);
 int sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 				    struct sfc_mae_counter *counter);
-int sfc_mae_counter_get(struct sfc_mae_counter_records *counters,
+int sfc_mae_counter_get(struct sfc_adapter *sa,
 			const struct sfc_mae_counter *counter,
 			struct rte_flow_query_count *data);
 
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 33/34] common/sfc_efx/base: support conntrack assistance counters
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (31 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-07 13:02   ` [PATCH v4 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
                     ` (3 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

Counters that can be referenced by HW conntrack assistance
table work similar to those of the action rules. However,
their IDs belong to a separate (CT-specific) namespace.

These are 1-bit saturating counters with no byte count.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  2 ++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 35 +++++++++++++++++++++++---
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 5a2e05134a..df4ed82780 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4195,6 +4195,7 @@ typedef struct efx_mae_limits_s {
 		uint32_t		eml_max_n_counters;
 		uint32_t		eml_max_n_action_counters;
 	};
+	uint32_t			eml_max_n_conntrack_counters;
 } efx_mae_limits_t;
 
 LIBEFX_API
@@ -4789,6 +4790,7 @@ efx_mae_action_set_fill_in_eh_id(
  */
 typedef enum efx_counter_type_e {
 	EFX_COUNTER_TYPE_ACTION = 0,
+	EFX_COUNTER_TYPE_CONNTRACK,
 } efx_counter_type_t;
 
 typedef struct efx_counter_s {
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index f6b472c160..a0dde1b1b4 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -842,6 +842,7 @@ typedef struct efx_mae_s {
 	efx_mae_field_cap_t		*em_outer_rule_field_caps;
 	size_t				em_outer_rule_field_caps_size;
 	uint32_t			em_max_n_action_counters;
+	uint32_t			em_max_n_conntrack_counters;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4078146741..6457f39ccf 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -16,7 +16,7 @@ efx_mae_get_capabilities(
 	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload,
 	    MC_CMD_MAE_GET_CAPS_IN_LEN,
-	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	    MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
 	struct efx_mae_s *maep = enp->en_maep;
 	efx_rc_t rc;
 
@@ -24,7 +24,7 @@ efx_mae_get_capabilities(
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
 	req.emr_out_buf = payload;
-	req.emr_out_length = MC_CMD_MAE_GET_CAPS_OUT_LEN;
+	req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
 
 	efx_mcdi_execute(enp, &req);
 
@@ -70,6 +70,13 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_counters =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
 
+	if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
+		maep->em_max_n_conntrack_counters =
+		    MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
+	} else {
+		maep->em_max_n_conntrack_counters = 0;
+	}
+
 	return (0);
 
 fail2:
@@ -375,6 +382,7 @@ efx_mae_get_limits(
 	emlp->eml_encap_header_size_limit =
 	    MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
 	emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
+	emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
 
 	return (0);
 
@@ -3275,11 +3283,15 @@ efx_mae_counters_alloc_type(
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
+	EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
 
 	switch (type) {
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3396,6 +3408,9 @@ efx_mae_counters_free_type(
 	case EFX_COUNTER_TYPE_ACTION:
 		max_n_counters = maep->em_max_n_action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		max_n_counters = maep->em_max_n_conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail1;
@@ -3498,8 +3513,11 @@ efx_mae_counters_stream_start(
 	__out				uint32_t *flags_out)
 {
 	efx_mcdi_req_t req;
-	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN,
+	EFX_MCDI_DECLARE_BUF(payload,
+			     MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
 			     MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	uint32_t counter_types;
 	efx_rc_t rc;
 
 	EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
@@ -3510,7 +3528,7 @@ efx_mae_counters_stream_start(
 
 	req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN;
+	req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
 	req.emr_out_buf = payload;
 	req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
 
@@ -3519,6 +3537,15 @@ efx_mae_counters_stream_start(
 			 packet_size);
 	MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
 
+	counter_types = (1U << MAE_COUNTER_TYPE_AR);
+
+	if (maep->em_max_n_conntrack_counters != 0)
+		counter_types |= (1U << MAE_COUNTER_TYPE_CT);
+
+	MCDI_IN_SET_DWORD(req,
+			  MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
+			  counter_types);
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* [PATCH v4 34/34] net/sfc: use conntrack assistance counters in transfer flows
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (32 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
@ 2023-06-07 13:02   ` Ivan Malov
  2023-06-08 12:33   ` [PATCH v4 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
                     ` (2 subsequent siblings)
  36 siblings, 0 replies; 156+ messages in thread
From: Ivan Malov @ 2023-06-07 13:02 UTC (permalink / raw)
  To: dev; +Cc: Andrew Rybchenko, Ferruh Yigit, Andy Moreton

These are 1-bit saturating counters which can only be useful
to tell whether a given flow rule has offloaded some packets
since the last query. Byte count is never provided for these.

Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.h        |   2 +
 drivers/net/sfc/sfc_mae.c         | 119 ++++++++++++++++++++++--------
 drivers/net/sfc/sfc_mae.h         |   2 +
 drivers/net/sfc/sfc_mae_counter.c |  30 ++++++++
 4 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index af94d0654a..601f93e540 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -86,6 +86,8 @@ struct sfc_flow_spec_mae {
 	/* Conntrack (CT) assistance table entry key and response */
 	sfc_mae_conntrack_response_t	ct_resp;
 	sfc_mae_conntrack_key_t		ct_key;
+	/* Conntrack (CT) assistance counter */
+	struct sfc_mae_counter		*ct_counter;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7353d04af8..ab315853d5 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -65,7 +65,8 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 
 static int
 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
-			      uint32_t nb_action_counters_max)
+			      uint32_t nb_action_counters_max,
+			      uint32_t nb_conntrack_counters_max)
 {
 	int ret;
 
@@ -76,12 +77,20 @@ sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
 
 	registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
 
+	ret = sfc_mae_counters_init(&registry->conntrack_counters,
+				    nb_conntrack_counters_max);
+	if (ret != 0)
+		return ret;
+
+	registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
+
 	return 0;
 }
 
 static void
 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
 {
+	sfc_mae_counters_fini(&registry->conntrack_counters);
 	sfc_mae_counters_fini(&registry->action_counters);
 }
 
@@ -162,10 +171,13 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 		sfc_log_init(sa, "init MAE counter record registry");
 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
-					limits.eml_max_n_action_counters);
+					limits.eml_max_n_action_counters,
+					limits.eml_max_n_conntrack_counters);
 		if (rc != 0) {
-			sfc_err(sa, "failed to init record registry for %u AR counters: %s",
-				limits.eml_max_n_action_counters, rte_strerror(rc));
+			sfc_err(sa, "failed to init record registry for %u AR and %u CT counters: %s",
+				limits.eml_max_n_action_counters,
+				limits.eml_max_n_conntrack_counters,
+				rte_strerror(rc));
 			goto fail_counter_registry_init;
 		}
 	}
@@ -1471,6 +1483,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 	}
 
 	sfc_mae_action_rule_del(sa, spec_mae->action_rule);
+
+	sfc_mae_counter_del(sa, spec_mae->ct_counter);
 }
 
 static int
@@ -4223,7 +4237,7 @@ static const char * const action_names[] = {
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
-			  struct rte_flow *flow,
+			  struct rte_flow *flow, bool ct,
 			  struct sfc_mae_actions_bundle *bundle,
 			  struct sfc_mae_aset_ctx *ctx,
 			  struct rte_flow_error *error)
@@ -4239,6 +4253,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	bool custom_error = B_FALSE;
 	int rc = 0;
 
+	if (ct) {
+		mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
+		counterp = &spec_mae->ct_counter;
+		spec_ptr = NULL;
+	}
+
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
@@ -4526,7 +4546,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		if (rc != 0)
 			goto fail_rule_parse_action;
 
-		rc = sfc_mae_rule_parse_action(sa, action, flow,
+		rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
 					       &bundle, &ctx, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
@@ -4561,8 +4581,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 		 */
 		efx_mae_action_set_populate_mark_reset(ctx.spec);
 
-		(ctx.counter)->ft_switch_hit_counter =
-			&spec_mae->ft_ctx->switch_hit_counter;
+		if (ctx.counter != NULL) {
+			(ctx.counter)->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		} else if (sfc_mae_counter_stream_enabled(sa)) {
+			SFC_ASSERT(ct);
+
+			spec_mae->ct_counter->ft_switch_hit_counter =
+				&spec_mae->ft_ctx->switch_hit_counter;
+		}
 		break;
 	default:
 		SFC_ASSERT(B_FALSE);
@@ -4843,12 +4870,34 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 		return rc;
 
 	if (spec_mae->action_rule->ct_mark != 0) {
+		struct sfc_mae_counter *counter = spec_mae->ct_counter;
+
+		rc = sfc_mae_counter_enable(sa, counter, NULL);
+		if (rc != 0) {
+			sfc_mae_action_rule_disable(sa, action_rule);
+			return rc;
+		}
+
+		if (counter != NULL) {
+			struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
+
+			spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
+
+			rc = sfc_mae_counter_start(sa);
+			if (rc != 0) {
+				sfc_mae_action_rule_disable(sa, action_rule);
+				return rc;
+			}
+		} else {
+			spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
+		}
+
 		spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
-		spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
 
 		rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
 					      &spec_mae->ct_resp);
 		if (rc != 0) {
+			sfc_mae_counter_disable(sa, counter);
 			sfc_mae_action_rule_disable(sa, action_rule);
 			return rc;
 		}
@@ -4871,6 +4920,8 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 	if (action_rule->ct_mark != 0)
 		(void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
 
+	sfc_mae_counter_disable(sa, spec_mae->ct_counter);
+
 	sfc_mae_action_rule_disable(sa, action_rule);
 
 	return 0;
@@ -4885,31 +4936,41 @@ sfc_mae_query_counter(struct sfc_adapter *sa,
 {
 	const struct sfc_mae_action_rule *action_rule = spec->action_rule;
 	const struct rte_flow_action_count *conf = action->conf;
-	struct sfc_mae_action_set *action_set;
-	struct sfc_mae_counter *counter;
+	struct sfc_mae_counter *counters[1 /* action rule counter */ +
+					 1 /* conntrack counter */];
+	unsigned int i;
 	int rc;
 
-	if (action_rule == NULL || action_rule->action_set == NULL ||
-	    action_rule->action_set->counter == NULL ||
-	    action_rule->action_set->counter->indirect) {
-		return rte_flow_error_set(error, EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION, action,
-			"Queried flow rule does not have count actions");
-	}
+	/*
+	 * The check for counter unavailability is done based
+	 * on counter traversal results. See error set below.
+	 */
+	if (action_rule != NULL && action_rule->action_set != NULL &&
+	    action_rule->action_set->counter != NULL &&
+	    !action_rule->action_set->counter->indirect)
+		counters[0] = action_rule->action_set->counter;
+	else
+		counters[0] = NULL;
 
-	action_set = action_rule->action_set;
-	counter = action_set->counter;
+	counters[1] = spec->ct_counter;
 
-	if (conf == NULL ||
-	    (counter->rte_id_valid && conf->id == counter->rte_id)) {
-		rc = sfc_mae_counter_get(sa, counter, data);
-		if (rc != 0) {
-			return rte_flow_error_set(error, EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION, action,
-				"Queried flow rule counter action is invalid");
-		}
+	for (i = 0; i < RTE_DIM(counters); ++i) {
+		struct sfc_mae_counter *counter = counters[i];
 
-		return 0;
+		if (counter == NULL)
+			continue;
+
+		if (conf == NULL ||
+		    (counter->rte_id_valid && conf->id == counter->rte_id)) {
+			rc = sfc_mae_counter_get(sa, counter, data);
+			if (rc != 0) {
+				return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION, action,
+					"Queried flow rule counter action is invalid");
+			}
+
+			return 0;
+		}
 	}
 
 	return rte_flow_error_set(error, ENOENT,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3a3a5225fd..80585c0e93 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -173,6 +173,8 @@ struct sfc_mae_counter_registry {
 	/* Common counter information */
 	/** Action rule counter record collection */
 	struct sfc_mae_counter_records	action_counters;
+	/** Conntrack counter record collection */
+	struct sfc_mae_counter_records	conntrack_counters;
 
 	/* Information used by counter update service */
 	/** Callback to get packets from RxQ */
diff --git a/drivers/net/sfc/sfc_mae_counter.c b/drivers/net/sfc/sfc_mae_counter.c
index 47448cba15..79043ff7d7 100644
--- a/drivers/net/sfc/sfc_mae_counter.c
+++ b/drivers/net/sfc/sfc_mae_counter.c
@@ -91,6 +91,9 @@ sfc_mae_counter_fw_rsrc_enable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		rc = EINVAL;
 		goto fail_counter_type_check;
@@ -172,6 +175,9 @@ sfc_mae_counter_fw_rsrc_disable(struct sfc_adapter *sa,
 	case EFX_COUNTER_TYPE_ACTION:
 		counters = &reg->action_counters;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &reg->conntrack_counters;
+		break;
 	default:
 		return EINVAL;
 	}
@@ -319,6 +325,9 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_AR:
 		counters = &counter_registry->action_counters;
 		break;
+	case ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT:
+		counters = &counter_registry->conntrack_counters;
+		break;
 	default:
 		sfc_err(sa, "unexpected MAE counters source identifier %u", id);
 		return;
@@ -392,6 +401,23 @@ sfc_mae_parse_counter_packet(struct sfc_adapter *sa,
 		byte_count_hi =
 			EFX_OWORD_FIELD32(counters_data[i],
 				ERF_SC_PACKETISER_PAYLOAD_BYTE_COUNT_HI);
+
+		if (id == ERF_SC_PACKETISER_HEADER_IDENTIFIER_CT) {
+			/*
+			 * FIXME:
+			 *
+			 * CT counters are 1-bit saturating counters.
+			 * There is no way to express this in DPDK
+			 * currently, so increment the hit count
+			 * by one to let the application know
+			 * that the flow is still effective.
+			 */
+			packet_count_lo = 1;
+			packet_count_hi = 0;
+			byte_count_lo = 0;
+			byte_count_hi = 0;
+		}
+
 		sfc_mae_counter_increment(sa,
 			counters,
 			EFX_OWORD_FIELD32(counters_data[i],
@@ -983,6 +1009,10 @@ sfc_mae_counter_get(struct sfc_adapter *sa,
 		counters = &sa->mae.counter_registry.action_counters;
 		need_byte_count = true;
 		break;
+	case EFX_COUNTER_TYPE_CONNTRACK:
+		counters = &sa->mae.counter_registry.conntrack_counters;
+		need_byte_count = false;
+		break;
 	default:
 		return EINVAL;
 	}
-- 
2.30.2


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 00/34] net/sfc: support HW conntrack assistance
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (33 preceding siblings ...)
  2023-06-07 13:02   ` [PATCH v4 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
@ 2023-06-08 12:33   ` Andrew Rybchenko
  2023-06-19 15:58     ` Ferruh Yigit
  2023-06-19 15:45   ` Ferruh Yigit
  2023-06-21 16:53   ` Ferruh Yigit
  36 siblings, 1 reply; 156+ messages in thread
From: Andrew Rybchenko @ 2023-06-08 12:33 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Ferruh Yigit

On 6/7/23 16:02, Ivan Malov wrote:
> On EF100 hardware, match-action engine (MAE) can be equipped
> with an assistance table for connection tracking (CT). In it,
> an entry key is a set of exact match fields: an EtherType, a
> pair of IP addresses, a L4 protocol ID and a pair of L4 port
> numbers. An entry response can provide matching packets with
> a mark value and additional data to be plumbed to NAT action.
> In addition, an update to mark-and-sweep counter can be done.
> 
> This table was designed with larger capacity in mind,
> so moving the above match criteria out of an action
> rule (AR) specification to a CT entry increases the
> likelihood of reusing AR entries and improves the
> total flow engine capacity. Make use of that.
> 
> Changes in v2:
> * Found and fixed my own mistake in [15/34]
> * Fixed [16/34] as per 0-day robot report
> * Added missing release notes to [27/34]
> * Added missing release notes to [30/34]
> 
> Changes in v3:
> * Fixed release notes in [27/34]
> * Rebased on dpdk to fix CI
> 
> Changes in v4:
> * Applied review notes in [05/34], [08/34], [09/34] and [10/34].

My ack from the previous version is lost.



^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 00/34] net/sfc: support HW conntrack assistance
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (34 preceding siblings ...)
  2023-06-08 12:33   ` [PATCH v4 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
@ 2023-06-19 15:45   ` Ferruh Yigit
  2023-06-21 16:53   ` Ferruh Yigit
  36 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-19 15:45 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko

On 6/7/2023 2:02 PM, Ivan Malov wrote:
> On EF100 hardware, match-action engine (MAE) can be equipped
> with an assistance table for connection tracking (CT). In it,
> an entry key is a set of exact match fields: an EtherType, a
> pair of IP addresses, a L4 protocol ID and a pair of L4 port
> numbers. An entry response can provide matching packets with
> a mark value and additional data to be plumbed to NAT action.
> In addition, an update to mark-and-sweep counter can be done.
> 
> This table was designed with larger capacity in mind,
> so moving the above match criteria out of an action
> rule (AR) specification to a CT entry increases the
> likelihood of reusing AR entries and improves the
> total flow engine capacity. Make use of that.
> 
> Changes in v2:
> * Found and fixed my own mistake in [15/34]
> * Fixed [16/34] as per 0-day robot report
> * Added missing release notes to [27/34]
> * Added missing release notes to [30/34]
> 
> Changes in v3:
> * Fixed release notes in [27/34]
> * Rebased on dpdk to fix CI
> 
> Changes in v4:
> * Applied review notes in [05/34], [08/34], [09/34] and [10/34].
> 
> Denis Pryazhennikov (11):
>   common/sfc_efx/base: update MCDI headers
>   common/sfc_efx/base: detect MCDI Table Access API support
>   common/sfc_efx/base: add API to list HW tables
>   common/sfc_efx/base: add macro to get indexed QWORD field
>   common/sfc_efx/base: add API to get HW table desc
>   common/sfc_efx/base: add API to insert data to HW table
>   common/sfc_efx/base: add API to delete entry from HW table
>   net/sfc: add MCDI wrappers for BCAM tables
>   net/sfc: add functions to manipulate MCDI table fields
>   net/sfc: attach to HW table API
>   net/sfc: add API to manage HW Conntrack table
> 
> Ivan Malov (23):
>   net/sfc: make entry pointer optional in MAE resource helpers
>   net/sfc: turn flow create/destroy methods into lock wrappers
>   net/sfc: let driver-internal flows use VF representor action
>   net/sfc: extend generic flow API to allow for internal flows
>   net/sfc: switch driver-internal flows to use generic methods
>   net/sfc: move MAE flow parsing method to MAE-specific source
>   net/sfc: move MAE counter stream start to action set handler
>   net/sfc: prepare MAE outer rules for action rule indirection
>   net/sfc: turn MAE flow action rules into shareable resources
>   common/sfc_efx/base: provide an API to clone MAE match specs
>   common/sfc_efx/base: add API to read back MAE match criteria
>   common/sfc_efx/base: match on conntrack mark in action rules
>   common/sfc_efx/base: add API to request MAE conntrack lookup
>   net/sfc: make use of conntrack assistance for transfer flows

Well done Ivan ;)


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-07 13:02   ` [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
@ 2023-06-19 15:58     ` Ferruh Yigit
  2023-06-21 11:09       ` Ivan Malov
  0 siblings, 1 reply; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-19 15:58 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Denis Pryazhennikov, Andy Moreton

On 6/7/2023 2:02 PM, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> New MCDI Table Access API allows management of
> the HW tables' content.
> This part of API helps to list all supported tables.
> In the near future, only the CT table is planned
> to be used, so only one identifier for this table
> was added to the efx.
> New table IDs will be added as needed.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>

This patch adds a function to the base code, but it is disconnected from
the context.
In the future if someone looks this function in git log, there is no
easy way to see why this function added and where/how it is used at time
it is added etc..

So, instead of making commit per function, can you please split commits
based on functionality/logic?

Please combine the commit that new function and commit where new
function is used to single commit, making a commit per feature?


If you are concerned about checkpatch warnings related to the component
(like common/sfc_efx/base), please ignore it for the case when a feature
is distributed into multiple components, and feel free to use most
appropriate component name, I assume it will be driver component
(net/sfc) most of the times.


There is apply errors on CI, which prevents CI checks, can you please
rebase set on top of latest head?


Btw, we call 'API' to end-user facing functions, that user directly
call, for this context better to call it 'function', but after patches
merged probably you won't need it at all.

Thanks,
Ferruh

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 00/34] net/sfc: support HW conntrack assistance
  2023-06-08 12:33   ` [PATCH v4 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
@ 2023-06-19 15:58     ` Ferruh Yigit
  0 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-19 15:58 UTC (permalink / raw)
  To: Andrew Rybchenko, Ivan Malov, dev

On 6/8/2023 1:33 PM, Andrew Rybchenko wrote:
> On 6/7/23 16:02, Ivan Malov wrote:
>> On EF100 hardware, match-action engine (MAE) can be equipped
>> with an assistance table for connection tracking (CT). In it,
>> an entry key is a set of exact match fields: an EtherType, a
>> pair of IP addresses, a L4 protocol ID and a pair of L4 port
>> numbers. An entry response can provide matching packets with
>> a mark value and additional data to be plumbed to NAT action.
>> In addition, an update to mark-and-sweep counter can be done.
>>
>> This table was designed with larger capacity in mind,
>> so moving the above match criteria out of an action
>> rule (AR) specification to a CT entry increases the
>> likelihood of reusing AR entries and improves the
>> total flow engine capacity. Make use of that.
>>
>> Changes in v2:
>> * Found and fixed my own mistake in [15/34]
>> * Fixed [16/34] as per 0-day robot report
>> * Added missing release notes to [27/34]
>> * Added missing release notes to [30/34]
>>
>> Changes in v3:
>> * Fixed release notes in [27/34]
>> * Rebased on dpdk to fix CI
>>
>> Changes in v4:
>> * Applied review notes in [05/34], [08/34], [09/34] and [10/34].
> 
> My ack from the previous version is lost.
> 
> 

Can you please apply Andrew's ack to each commit for next version?


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-19 15:58     ` Ferruh Yigit
@ 2023-06-21 11:09       ` Ivan Malov
  2023-06-21 14:30         ` Ferruh Yigit
  0 siblings, 1 reply; 156+ messages in thread
From: Ivan Malov @ 2023-06-21 11:09 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Andrew Rybchenko, Denis Pryazhennikov, Andy Moreton

Hi Ferruh,

Thank you so much for your review notes. You suggested to squash
some pairs of "common/sfc_base/efx" and "net/sfc" patches, so
that logical changes would be unified. I see your point.

On the other hand, however, doing so would be rather unusual
from our internal process standpoint. Typically, we stick
with the idea that splitting patches into smaller ones is
better, as it is much easier to reason about and debug
smaller changesets rather than bigger ones.

The thing is, the DPDK driver is not the only one based on
the common code ("libefx"), that is, we got used to
keeping things separate, even despite some of them
beging logically connected. I apologise in case
my explanation is still vague.

If the reader comes across a libefx patch in one of the
other libefx-based projects and wants to search for it
in the other projects (DPDK), it is much easier for
them to find what they need provided that the patch
exists in DPDK in the same format, as a separate
change set with (almost) the same commit summary.

In other words, there are pros and cons to squashing
things, well, at least in this particular series,
which is rather big and complicated.

How about we retain the series as it is, in its current state
this time? We hope to adopt the suggested ("bigger logical
patches") next time, in our future work. What do you think?

We would discuss this internally, with our team, and come
up with the new approach for us all to structure future
patch sets, for some other features yet to be supported.

Thank you.

On Mon, 19 Jun 2023, Ferruh Yigit wrote:

> On 6/7/2023 2:02 PM, Ivan Malov wrote:
>> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
>>
>> New MCDI Table Access API allows management of
>> the HW tables' content.
>> This part of API helps to list all supported tables.
>> In the near future, only the CT table is planned
>> to be used, so only one identifier for this table
>> was added to the efx.
>> New table IDs will be added as needed.
>>
>> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>>
>
> This patch adds a function to the base code, but it is disconnected from
> the context.
> In the future if someone looks this function in git log, there is no
> easy way to see why this function added and where/how it is used at time
> it is added etc..
>
> So, instead of making commit per function, can you please split commits
> based on functionality/logic?
>
> Please combine the commit that new function and commit where new
> function is used to single commit, making a commit per feature?
>
>
> If you are concerned about checkpatch warnings related to the component
> (like common/sfc_efx/base), please ignore it for the case when a feature
> is distributed into multiple components, and feel free to use most
> appropriate component name, I assume it will be driver component
> (net/sfc) most of the times.
>
>
> There is apply errors on CI, which prevents CI checks, can you please
> rebase set on top of latest head?
>
>
> Btw, we call 'API' to end-user facing functions, that user directly
> call, for this context better to call it 'function', but after patches
> merged probably you won't need it at all.
>
> Thanks,
> Ferruh
>

^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables
  2023-06-21 11:09       ` Ivan Malov
@ 2023-06-21 14:30         ` Ferruh Yigit
  0 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-21 14:30 UTC (permalink / raw)
  To: Ivan Malov; +Cc: dev, Andrew Rybchenko, Denis Pryazhennikov, Andy Moreton

On 6/21/2023 12:09 PM, Ivan Malov wrote:
> Hi Ferruh,
> 
> Thank you so much for your review notes. You suggested to squash
> some pairs of "common/sfc_base/efx" and "net/sfc" patches, so
> that logical changes would be unified. I see your point.
> 
> On the other hand, however, doing so would be rather unusual
> from our internal process standpoint. Typically, we stick
> with the idea that splitting patches into smaller ones is
> better, as it is much easier to reason about and debug
> smaller changesets rather than bigger ones.
> 
> The thing is, the DPDK driver is not the only one based on
> the common code ("libefx"), that is, we got used to
> keeping things separate, even despite some of them
> beging logically connected. I apologise in case
> my explanation is still vague.
> 
> If the reader comes across a libefx patch in one of the
> other libefx-based projects and wants to search for it
> in the other projects (DPDK), it is much easier for
> them to find what they need provided that the patch
> exists in DPDK in the same format, as a separate
> change set with (almost) the same commit summary.
> 
> In other words, there are pros and cons to squashing
> things, well, at least in this particular series,
> which is rather big and complicated.
> 
> How about we retain the series as it is, in its current state
> this time? We hope to adopt the suggested ("bigger logical
> patches") next time, in our future work. What do you think?
> 
> We would discuss this internally, with our team, and come
> up with the new approach for us all to structure future
> patch sets, for some other features yet to be supported.
> 

Ack, thanks.

Let me continue with this set as it is taking into account that -rc2 is
so close, we can sync more for future patches.

> Thank you.
> 
> On Mon, 19 Jun 2023, Ferruh Yigit wrote:
> 
>> On 6/7/2023 2:02 PM, Ivan Malov wrote:
>>> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
>>>
>>> New MCDI Table Access API allows management of
>>> the HW tables' content.
>>> This part of API helps to list all supported tables.
>>> In the near future, only the CT table is planned
>>> to be used, so only one identifier for this table
>>> was added to the efx.
>>> New table IDs will be added as needed.
>>>
>>> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
>>> Reviewed-by: Andy Moreton <amoreton@xilinx.com>
>>>
>>
>> This patch adds a function to the base code, but it is disconnected from
>> the context.
>> In the future if someone looks this function in git log, there is no
>> easy way to see why this function added and where/how it is used at time
>> it is added etc..
>>
>> So, instead of making commit per function, can you please split commits
>> based on functionality/logic?
>>
>> Please combine the commit that new function and commit where new
>> function is used to single commit, making a commit per feature?
>>
>>
>> If you are concerned about checkpatch warnings related to the component
>> (like common/sfc_efx/base), please ignore it for the case when a feature
>> is distributed into multiple components, and feel free to use most
>> appropriate component name, I assume it will be driver component
>> (net/sfc) most of the times.
>>
>>
>> There is apply errors on CI, which prevents CI checks, can you please
>> rebase set on top of latest head?
>>
>>
>> Btw, we call 'API' to end-user facing functions, that user directly
>> call, for this context better to call it 'function', but after patches
>> merged probably you won't need it at all.
>>
>> Thanks,
>> Ferruh
>>


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend
  2023-06-07 13:02   ` [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
@ 2023-06-21 16:50     ` Ferruh Yigit
  0 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-21 16:50 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Andy Moreton

On 6/7/2023 2:02 PM, Ivan Malov wrote:
> For this offload to work, the innermost pattern items must
> provide the full set of exact match criteria, which are as
> follows: EtherType, IP DST, IP SRC, TP protocol ID, TP DST
> and TP SRC, where the protocol types can be autodetected.
> 
> The offload requires that the IPv4 and the TP actions be
> requested simultaneously in the same flow by the caller:
> SET_IPV4_DST + SET_TP_DST or SET_IPV4_SRC + SET_TP_SRC.
> 
> The offload operates on the outermost frame, which,
> if action VXLAN_DECAP was requested, maps to the
> inner frame of the original packet. The caller
> is responsible to request this offload only
> when the target header is an IPv4-based one.
> 
> Signed-off-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

<...>

> --- a/doc/guides/rel_notes/release_23_07.rst
> +++ b/doc/guides/rel_notes/release_23_07.rst
> @@ -55,6 +55,21 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **Updated Solarflare network PMD.**
> +
> +  Updated the Solarflare ``sfc_efx`` driver with changes including:
> +
> +  * Added partial support for transfer flow actions SET_IPV4_DST,
> +    SET_TP_DST, SET_IPV4_SRC and SET_TP_SRC on SN1000 SmartNICs.
> +    It is required that the innermost pattern items provide the
> +    full set of exact match criteria: EtherType, IP DST, IP SRC,
> +    TP protocol ID, TP DST and TP SRC. The IPv4 and TP actions
> +    must be requested simultaneously in the same flow. These
> +    actions operate on the outermost frame, at the point
> +    where action VXLAN_DECAP (if any) has done its job.
> +    The caller is responsible to request this offload
> +    only when the target header is an IPv4-based one.
> +

Reordered update, moved it under existing Solarflare update and
simplified note as more suitable for release notes.


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers
  2023-06-07 13:02   ` [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
@ 2023-06-21 16:52     ` Ferruh Yigit
  0 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-21 16:52 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko, Denis Pryazhennikov, Andy Moreton

On 6/7/2023 2:02 PM, Ivan Malov wrote:
> From: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> 
> Pickup new FW interface definitions.
> 
> Signed-off-by: Denis Pryazhennikov <denis.pryazhennikov@arknetworks.am>
> Reviewed-by: Ivan Malov <ivan.malov@arknetworks.am>
> Reviewed-by: Andy Moreton <amoreton@xilinx.com>

<...>

> @@ -9127,15 +10514,13 @@
>  /***********************************/
>  /* MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS
>   * Get descriptions for a set of sensors, specified as an array of sensor
> - * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST
> - *
> - * Any handles which do not correspond to a sensor currently managed by the MC
> - * will be dropped from from the response. This may happen when a sensor table
> - * update is in progress, and effectively means the set of usable sensors is
> - * the intersection between the sets of sensors known to the driver and the MC.
> - *
> - * On Riverhead this command is implemented as a a wrapper for
> - * `get_descriptions` in the sensor_query SPHINX service.
> + * handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. Any handles which do not
> + * correspond to a sensor currently managed by the MC will be dropped from from

typo "from from" fixed. This is reported by checkpatch.

> + * the response. This may happen when a sensor table update is in progress, and
> + * effectively means the set of usable sensors is the intersection between the
> + * sets of sensors known to the driver and the MC. On Riverhead this command is
> + * implemented as a wrapper for `get_descriptions` in the sensor_query SPHINX
> + * service.
>   */
>  #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS 0x67
>  #define	MC_CMD_DYNAMIC_SENSORS_GET_DESCRIPTIONS_MSGSET 0x67
> @@ -9173,19 +10558,15 @@
>  /***********************************/
>  /* MC_CMD_DYNAMIC_SENSORS_GET_READINGS
>   * Read the state and value for a set of sensors, specified as an array of
> - * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST.
> - *
> - * In the case of a broken sensor, then the state of the response's
> - * MC_CMD_DYNAMIC_SENSORS_VALUE entry will be set to BROKEN, and any value
> - * provided should be treated as erroneous.
> - *
> - * Any handles which do not correspond to a sensor currently managed by the MC
> - * will be dropped from from the response. This may happen when a sensor table
> - * update is in progress, and effectively means the set of usable sensors is
> - * the intersection between the sets of sensors known to the driver and the MC.
> - *
> - * On Riverhead this command is implemented as a a wrapper for `get_readings`
> - * in the sensor_query SPHINX service.
> + * sensor handles as returned by MC_CMD_DYNAMIC_SENSORS_LIST. In the case of a
> + * broken sensor, then the state of the response's MC_CMD_DYNAMIC_SENSORS_VALUE
> + * entry will be set to BROKEN, and any value provided should be treated as
> + * erroneous. Any handles which do not correspond to a sensor currently managed
> + * by the MC will be dropped from from the response. This may happen when a

ditto, fixed "from from"


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 00/34] net/sfc: support HW conntrack assistance
  2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
                     ` (35 preceding siblings ...)
  2023-06-19 15:45   ` Ferruh Yigit
@ 2023-06-21 16:53   ` Ferruh Yigit
  36 siblings, 0 replies; 156+ messages in thread
From: Ferruh Yigit @ 2023-06-21 16:53 UTC (permalink / raw)
  To: Ivan Malov, dev; +Cc: Andrew Rybchenko

On 6/7/2023 2:02 PM, Ivan Malov wrote:
> On EF100 hardware, match-action engine (MAE) can be equipped
> with an assistance table for connection tracking (CT). In it,
> an entry key is a set of exact match fields: an EtherType, a
> pair of IP addresses, a L4 protocol ID and a pair of L4 port
> numbers. An entry response can provide matching packets with
> a mark value and additional data to be plumbed to NAT action.
> In addition, an update to mark-and-sweep counter can be done.
> 
> This table was designed with larger capacity in mind,
> so moving the above match criteria out of an action
> rule (AR) specification to a CT entry increases the
> likelihood of reusing AR entries and improves the
> total flow engine capacity. Make use of that.
> 
> Changes in v2:
> * Found and fixed my own mistake in [15/34]
> * Fixed [16/34] as per 0-day robot report
> * Added missing release notes to [27/34]
> * Added missing release notes to [30/34]
> 
> Changes in v3:
> * Fixed release notes in [27/34]
> * Rebased on dpdk to fix CI
> 
> Changes in v4:
> * Applied review notes in [05/34], [08/34], [09/34] and [10/34].
> 
> Denis Pryazhennikov (11):
>   common/sfc_efx/base: update MCDI headers
>   common/sfc_efx/base: detect MCDI Table Access API support
>   common/sfc_efx/base: add API to list HW tables
>   common/sfc_efx/base: add macro to get indexed QWORD field
>   common/sfc_efx/base: add API to get HW table desc
>   common/sfc_efx/base: add API to insert data to HW table
>   common/sfc_efx/base: add API to delete entry from HW table
>   net/sfc: add MCDI wrappers for BCAM tables
>   net/sfc: add functions to manipulate MCDI table fields
>   net/sfc: attach to HW table API
>   net/sfc: add API to manage HW Conntrack table
> 
> Ivan Malov (23):
>   net/sfc: make entry pointer optional in MAE resource helpers
>   net/sfc: turn flow create/destroy methods into lock wrappers
>   net/sfc: let driver-internal flows use VF representor action
>   net/sfc: extend generic flow API to allow for internal flows
>   net/sfc: switch driver-internal flows to use generic methods
>   net/sfc: move MAE flow parsing method to MAE-specific source
>   net/sfc: move MAE counter stream start to action set handler
>   net/sfc: prepare MAE outer rules for action rule indirection
>   net/sfc: turn MAE flow action rules into shareable resources
>   common/sfc_efx/base: provide an API to clone MAE match specs
>   common/sfc_efx/base: add API to read back MAE match criteria
>   common/sfc_efx/base: match on conntrack mark in action rules
>   common/sfc_efx/base: add API to request MAE conntrack lookup
>   net/sfc: make use of conntrack assistance for transfer flows
>   common/sfc_efx/base: support NAT edits in MAE
>   net/sfc: add support for IPv4 NAT offload to MAE backend
>   net/sfc: rename SW structures used by transfer flow counters
>   net/sfc: rework MAE action rule counter representation in SW
>   net/sfc: support indirect count action in transfer flows
>   common/sfc_efx/base: rework MAE counter provisioning helpers
>   net/sfc: indicate MAE counter type in use for transfer flows
>   common/sfc_efx/base: support conntrack assistance counters
>   net/sfc: use conntrack assistance counters in transfer flows
>

Series applied to dpdk-next-net/main, thanks.


^ permalink raw reply	[flat|nested] 156+ messages in thread

* Re: [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules
  2023-06-07 13:02   ` [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
@ 2023-06-26 13:07     ` Thomas Monjalon
  0 siblings, 0 replies; 156+ messages in thread
From: Thomas Monjalon @ 2023-06-26 13:07 UTC (permalink / raw)
  To: Ivan Malov
  Cc: dev, Andrew Rybchenko, Ferruh Yigit, Andy Moreton, david.marchand

07/06/2023 15:02, Ivan Malov:
> EF100 match-action engine (MAE) has conntrack assistance
> table. A hit in this table can provide a mark value for
> the following lookup stage, which is action rule lookup.
> 
> Provide support for setting match on conntrack mark.

What happened Ivan? This commit message is not right aligned!
We could accept you drop a space before parentheses if it helps :)




^ permalink raw reply	[flat|nested] 156+ messages in thread

end of thread, other threads:[~2023-06-26 13:07 UTC | newest]

Thread overview: 156+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-01 19:55 [PATCH 00/34] net/sfc: support HW conntrack assistance Ivan Malov
2023-06-01 19:55 ` [PATCH 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
2023-06-01 19:55 ` [PATCH 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
2023-06-01 19:55 ` [PATCH 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
2023-06-01 19:55 ` [PATCH 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
2023-06-01 19:55 ` [PATCH 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
2023-06-01 19:55 ` [PATCH 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
2023-06-01 19:55 ` [PATCH 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
2023-06-01 19:55 ` [PATCH 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
2023-06-01 19:55 ` [PATCH 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
2023-06-01 19:55 ` [PATCH 10/34] net/sfc: attach to HW table API Ivan Malov
2023-06-01 19:55 ` [PATCH 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
2023-06-01 19:55 ` [PATCH 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
2023-06-01 19:55 ` [PATCH 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
2023-06-01 19:55 ` [PATCH 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
2023-06-01 19:55 ` [PATCH 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
2023-06-01 19:55 ` [PATCH 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
2023-06-01 19:55 ` [PATCH 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
2023-06-01 19:55 ` [PATCH 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
2023-06-01 19:55 ` [PATCH 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
2023-06-01 19:55 ` [PATCH 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
2023-06-01 19:55 ` [PATCH 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
2023-06-01 19:55 ` [PATCH 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
2023-06-01 19:55 ` [PATCH 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
2023-06-01 19:55 ` [PATCH 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
2023-06-01 19:55 ` [PATCH 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
2023-06-01 19:55 ` [PATCH 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
2023-06-01 19:55 ` [PATCH 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
2023-06-01 19:55 ` [PATCH 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
2023-06-01 19:55 ` [PATCH 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
2023-06-01 19:55 ` [PATCH 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
2023-06-01 19:55 ` [PATCH 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
2023-06-01 19:55 ` [PATCH 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
2023-06-01 19:55 ` [PATCH 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
2023-06-01 19:55 ` [PATCH 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
2023-06-04  0:00 ` [PATCH v2 00/34] net/sfc: support HW conntrack assistance Ivan Malov
2023-06-04  0:00   ` [PATCH v2 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
2023-06-04  0:00   ` [PATCH v2 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
2023-06-04  0:00   ` [PATCH v2 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
2023-06-04  0:00   ` [PATCH v2 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
2023-06-04  0:00   ` [PATCH v2 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
2023-06-04  0:00   ` [PATCH v2 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
2023-06-04  0:00   ` [PATCH v2 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
2023-06-04  0:00   ` [PATCH v2 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
2023-06-04  0:00   ` [PATCH v2 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
2023-06-04  0:00   ` [PATCH v2 10/34] net/sfc: attach to HW table API Ivan Malov
2023-06-04  0:00   ` [PATCH v2 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
2023-06-04  0:00   ` [PATCH v2 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
2023-06-04  0:00   ` [PATCH v2 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
2023-06-04  0:00   ` [PATCH v2 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
2023-06-04  0:00   ` [PATCH v2 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
2023-06-04  0:00   ` [PATCH v2 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
2023-06-04  0:00   ` [PATCH v2 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
2023-06-04  0:00   ` [PATCH v2 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
2023-06-04  0:00   ` [PATCH v2 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
2023-06-04  0:00   ` [PATCH v2 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
2023-06-04  0:00   ` [PATCH v2 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
2023-06-04  0:00   ` [PATCH v2 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
2023-06-04  0:00   ` [PATCH v2 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
2023-06-04  0:00   ` [PATCH v2 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
2023-06-04  0:00   ` [PATCH v2 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
2023-06-04  0:00   ` [PATCH v2 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
2023-06-04  0:00   ` [PATCH v2 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
2023-06-04  0:00   ` [PATCH v2 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
2023-06-04  0:00   ` [PATCH v2 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
2023-06-04  0:00   ` [PATCH v2 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
2023-06-04  0:00   ` [PATCH v2 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
2023-06-04  0:00   ` [PATCH v2 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
2023-06-04  0:00   ` [PATCH v2 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
2023-06-04  0:00   ` [PATCH v2 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
2023-06-04 23:24 ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Ivan Malov
2023-06-04 23:24   ` [PATCH v3 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
2023-06-04 23:24   ` [PATCH v3 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
2023-06-04 23:24   ` [PATCH v3 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
2023-06-04 23:24   ` [PATCH v3 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
2023-06-04 23:24   ` [PATCH v3 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
2023-06-07 11:47     ` Andrew Rybchenko
2023-06-07 12:06     ` Andrew Rybchenko
2023-06-04 23:24   ` [PATCH v3 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
2023-06-04 23:24   ` [PATCH v3 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
2023-06-04 23:24   ` [PATCH v3 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
2023-06-07 11:53     ` Andrew Rybchenko
2023-06-04 23:24   ` [PATCH v3 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
2023-06-07 12:00     ` Andrew Rybchenko
2023-06-04 23:24   ` [PATCH v3 10/34] net/sfc: attach to HW table API Ivan Malov
2023-06-07 12:08     ` Andrew Rybchenko
2023-06-04 23:25   ` [PATCH v3 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
2023-06-04 23:25   ` [PATCH v3 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
2023-06-04 23:25   ` [PATCH v3 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
2023-06-04 23:25   ` [PATCH v3 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
2023-06-04 23:25   ` [PATCH v3 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
2023-06-04 23:25   ` [PATCH v3 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
2023-06-04 23:25   ` [PATCH v3 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
2023-06-04 23:25   ` [PATCH v3 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
2023-06-04 23:25   ` [PATCH v3 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
2023-06-04 23:25   ` [PATCH v3 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
2023-06-04 23:25   ` [PATCH v3 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
2023-06-04 23:25   ` [PATCH v3 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
2023-06-04 23:25   ` [PATCH v3 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
2023-06-04 23:25   ` [PATCH v3 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
2023-06-04 23:25   ` [PATCH v3 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
2023-06-04 23:25   ` [PATCH v3 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
2023-06-04 23:25   ` [PATCH v3 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
2023-06-04 23:25   ` [PATCH v3 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
2023-06-04 23:25   ` [PATCH v3 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
2023-06-04 23:25   ` [PATCH v3 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
2023-06-04 23:25   ` [PATCH v3 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
2023-06-04 23:25   ` [PATCH v3 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
2023-06-04 23:25   ` [PATCH v3 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
2023-06-04 23:25   ` [PATCH v3 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
2023-06-07 12:19   ` [PATCH v3 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
2023-06-07 13:02 ` [PATCH v4 " Ivan Malov
2023-06-07 13:02   ` [PATCH v4 01/34] common/sfc_efx/base: update MCDI headers Ivan Malov
2023-06-21 16:52     ` Ferruh Yigit
2023-06-07 13:02   ` [PATCH v4 02/34] common/sfc_efx/base: detect MCDI Table Access API support Ivan Malov
2023-06-07 13:02   ` [PATCH v4 03/34] common/sfc_efx/base: add API to list HW tables Ivan Malov
2023-06-19 15:58     ` Ferruh Yigit
2023-06-21 11:09       ` Ivan Malov
2023-06-21 14:30         ` Ferruh Yigit
2023-06-07 13:02   ` [PATCH v4 04/34] common/sfc_efx/base: add macro to get indexed QWORD field Ivan Malov
2023-06-07 13:02   ` [PATCH v4 05/34] common/sfc_efx/base: add API to get HW table desc Ivan Malov
2023-06-07 13:02   ` [PATCH v4 06/34] common/sfc_efx/base: add API to insert data to HW table Ivan Malov
2023-06-07 13:02   ` [PATCH v4 07/34] common/sfc_efx/base: add API to delete entry from " Ivan Malov
2023-06-07 13:02   ` [PATCH v4 08/34] net/sfc: add MCDI wrappers for BCAM tables Ivan Malov
2023-06-07 13:02   ` [PATCH v4 09/34] net/sfc: add functions to manipulate MCDI table fields Ivan Malov
2023-06-07 13:02   ` [PATCH v4 10/34] net/sfc: attach to HW table API Ivan Malov
2023-06-07 13:02   ` [PATCH v4 11/34] net/sfc: add API to manage HW Conntrack table Ivan Malov
2023-06-07 13:02   ` [PATCH v4 12/34] net/sfc: make entry pointer optional in MAE resource helpers Ivan Malov
2023-06-07 13:02   ` [PATCH v4 13/34] net/sfc: turn flow create/destroy methods into lock wrappers Ivan Malov
2023-06-07 13:02   ` [PATCH v4 14/34] net/sfc: let driver-internal flows use VF representor action Ivan Malov
2023-06-07 13:02   ` [PATCH v4 15/34] net/sfc: extend generic flow API to allow for internal flows Ivan Malov
2023-06-07 13:02   ` [PATCH v4 16/34] net/sfc: switch driver-internal flows to use generic methods Ivan Malov
2023-06-07 13:02   ` [PATCH v4 17/34] net/sfc: move MAE flow parsing method to MAE-specific source Ivan Malov
2023-06-07 13:02   ` [PATCH v4 18/34] net/sfc: move MAE counter stream start to action set handler Ivan Malov
2023-06-07 13:02   ` [PATCH v4 19/34] net/sfc: prepare MAE outer rules for action rule indirection Ivan Malov
2023-06-07 13:02   ` [PATCH v4 20/34] net/sfc: turn MAE flow action rules into shareable resources Ivan Malov
2023-06-07 13:02   ` [PATCH v4 21/34] common/sfc_efx/base: provide an API to clone MAE match specs Ivan Malov
2023-06-07 13:02   ` [PATCH v4 22/34] common/sfc_efx/base: add API to read back MAE match criteria Ivan Malov
2023-06-07 13:02   ` [PATCH v4 23/34] common/sfc_efx/base: match on conntrack mark in action rules Ivan Malov
2023-06-26 13:07     ` Thomas Monjalon
2023-06-07 13:02   ` [PATCH v4 24/34] common/sfc_efx/base: add API to request MAE conntrack lookup Ivan Malov
2023-06-07 13:02   ` [PATCH v4 25/34] net/sfc: make use of conntrack assistance for transfer flows Ivan Malov
2023-06-07 13:02   ` [PATCH v4 26/34] common/sfc_efx/base: support NAT edits in MAE Ivan Malov
2023-06-07 13:02   ` [PATCH v4 27/34] net/sfc: add support for IPv4 NAT offload to MAE backend Ivan Malov
2023-06-21 16:50     ` Ferruh Yigit
2023-06-07 13:02   ` [PATCH v4 28/34] net/sfc: rename SW structures used by transfer flow counters Ivan Malov
2023-06-07 13:02   ` [PATCH v4 29/34] net/sfc: rework MAE action rule counter representation in SW Ivan Malov
2023-06-07 13:02   ` [PATCH v4 30/34] net/sfc: support indirect count action in transfer flows Ivan Malov
2023-06-07 13:02   ` [PATCH v4 31/34] common/sfc_efx/base: rework MAE counter provisioning helpers Ivan Malov
2023-06-07 13:02   ` [PATCH v4 32/34] net/sfc: indicate MAE counter type in use for transfer flows Ivan Malov
2023-06-07 13:02   ` [PATCH v4 33/34] common/sfc_efx/base: support conntrack assistance counters Ivan Malov
2023-06-07 13:02   ` [PATCH v4 34/34] net/sfc: use conntrack assistance counters in transfer flows Ivan Malov
2023-06-08 12:33   ` [PATCH v4 00/34] net/sfc: support HW conntrack assistance Andrew Rybchenko
2023-06-19 15:58     ` Ferruh Yigit
2023-06-19 15:45   ` Ferruh Yigit
2023-06-21 16:53   ` Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).