DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules
@ 2020-10-20  8:47 Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
                   ` (63 more replies)
  0 siblings, 64 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev

Transfer rules for Alveo SN1000 SmartNICs support matching on various
inner and outer packet headers, traffic source items like PORT_ID,
PHY_PORT, PF and VF and actions to route traffic to destination
(PORT_ID, PHY_PORT, PF, VF or DROP), MARK, FLAG and apply VLAN
push/pop transformations.


Andrew Rybchenko (2):
  common/sfc_efx/base: add MAE definitions to MCDI
  doc: advertise flow API transfer rules support in net/sfc

Ivan Malov (60):
  common/sfc_efx/base: indicate support for MAE
  net/sfc: add a stub for attaching to MAE
  common/sfc_efx/base: add MAE init/fini APIs
  drivers: init/fini MAE on attach/detach
  common/sfc_efx/base: add an MAE limit query API
  net/sfc: add the concept of MAE (transfer) rules
  common/sfc_efx/base: add match spec init/fini APIs
  net/sfc: add pattern parsing stub to MAE backend
  common/sfc_efx/base: add a match spec validate API
  net/sfc: validate match spec in MAE backend
  common/sfc_efx/base: add a match specs class comparison API
  net/sfc: add verify method to flow validate path
  common/sfc_efx/base: add action set spec init/fini APIs
  net/sfc: add actions parsing stub to MAE backend
  common/sfc_efx/base: support setting a PPORT in a match spec
  net/sfc: support flow item PHY PORT in MAE backend
  common/sfc_efx/base: add MAE match fields for Ethernet
  net/sfc: support flow item ETH in MAE backend
  common/sfc_efx/base: support adding DELIVER action to a set
  net/sfc: support flow action PHY PORT in MAE backend
  common/sfc_efx/base: add MAE action set provisioning APIs
  common/sfc_efx/base: add MAE action rule provisioning APIs
  net/sfc: implement flow insert/remove in MAE backend
  common/sfc_efx/base: support adding VLAN POP action to a set
  net/sfc: support flow action OF POP VLAN in MAE backend
  common/sfc_efx/base: support adding VLAN PUSH action
  net/sfc: add facilities to handle bundles of actions
  net/sfc: support VLAN PUSH actions in MAE backend
  common/sfc_efx/base: support adding FLAG action to a set
  net/sfc: support flow action FLAG in MAE backend
  common/sfc_efx/base: support adding MARK action to a set
  net/sfc: support flow action MARK in MAE backend
  common/sfc_efx/base: add named constant for invalid VF
  common/sfc_efx/base: add an API to get MPORT of a PF/VF
  net/sfc: support flow items PF and VF in transfer rules
  net/sfc: support flow actions PF and VF in transfer rules
  common/sfc_efx/base: add an API for adding action DROP
  net/sfc: support flow action DROP in transfer rules
  common/sfc_efx/base: refactor version / boot info get helper
  common/sfc_efx/base: add an API for querying board info
  net/sfc: add HW switch ID helpers
  net/sfc: support the concept of RTE switch domains/ports
  net/sfc: support flow action PORT ID in transfer rules
  net/sfc: support flow item PORT ID in transfer rules
  common/sfc_efx/base: add MAE match fields for VLAN
  net/sfc: support flow item VLAN in transfer rules
  common/sfc_efx/base: add MAE match fields for IPv4
  net/sfc: support flow item IPV4 in transfer rules
  common/sfc_efx/base: add MAE match fields for IPv6
  net/sfc: support flow item IPV6 in transfer rules
  common/sfc_efx/base: add MAE match fields for TCP and UDP
  net/sfc: support flow item TCP in transfer rules
  net/sfc: support flow item UDP in transfer rules
  common/sfc_efx/base: indicate MAE support for encapsulation
  common/sfc_efx/base: add MAE encap. match fields
  common/sfc_efx/base: add MAE match field VNET ID for tunnels
  common/sfc_efx/base: add an API to compare match specs
  common/sfc_efx/base: validate and compare outer match specs
  common/sfc_efx/base: support outer rule provisioning
  net/sfc: support encap. flow items in transfer rules

 doc/guides/nics/sfc_efx.rst                   |   59 +-
 doc/guides/rel_notes/release_20_11.rst        |    3 +-
 drivers/common/sfc_efx/base/ef10_nic.c        |   15 +
 drivers/common/sfc_efx/base/efx.h             |  337 ++-
 drivers/common/sfc_efx/base/efx_check.h       |    6 +
 drivers/common/sfc_efx/base/efx_impl.h        |   86 +
 drivers/common/sfc_efx/base/efx_mae.c         | 1906 ++++++++++++++
 drivers/common/sfc_efx/base/efx_mcdi.c        |  194 +-
 drivers/common/sfc_efx/base/efx_mcdi.h        |   34 +
 drivers/common/sfc_efx/base/efx_nic.c         |   46 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h   | 2232 ++++++++++++++++
 drivers/common/sfc_efx/base/meson.build       |    1 +
 drivers/common/sfc_efx/base/siena_nic.c       |    2 +
 drivers/common/sfc_efx/efsys.h                |    2 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |   30 +
 drivers/net/sfc/meson.build                   |    2 +
 drivers/net/sfc/sfc.c                         |   52 +
 drivers/net/sfc/sfc.h                         |   10 +
 drivers/net/sfc/sfc_ethdev.c                  |    7 +
 drivers/net/sfc/sfc_flow.c                    |  124 +-
 drivers/net/sfc/sfc_flow.h                    |   30 +
 drivers/net/sfc/sfc_mae.c                     | 2340 +++++++++++++++++
 drivers/net/sfc/sfc_mae.h                     |  208 ++
 drivers/net/sfc/sfc_switch.c                  |  334 +++
 drivers/net/sfc/sfc_switch.h                  |   53 +
 25 files changed, 8039 insertions(+), 74 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.h
 create mode 100644 drivers/net/sfc/sfc_switch.c
 create mode 100644 drivers/net/sfc/sfc_switch.h

-- 
2.17.1


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

* [dpdk-dev] [PATCH 01/62] common/sfc_efx/base: add MAE definitions to MCDI
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 02/62] common/sfc_efx/base: indicate support for MAE Andrew Rybchenko
                   ` (62 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev

MAE stands for Match-Action-Engine and will be used to
support rte_flow API transfer rules.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2232 +++++++++++++++++++
 1 file changed, 2232 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index f31a25e4ff..7125d053e8 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -410,6 +410,151 @@
 #define	MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff
 #define	MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */
 
+/* MAE_FIELD_SUPPORT_STATUS enum */
+/* enum: The NIC does not support this field. The driver must ensure that any
+ * mask associated with this field in a match rule is zeroed. The NIC may
+ * either reject requests with an invalid mask for such a field, or may assume
+ * that the mask is zero. (This category only exists to describe behaviour for
+ * fields that a newer driver might know about but that older firmware does
+ * not. It is recommended that firmware report MAE_FIELD_FIELD_MATCH_NEVER for
+ * all match fields defined at the time of its compilation. If a driver see a
+ * field support status value that it does not recognise, it must treat that
+ * field as thought the field was reported as MAE_FIELD_SUPPORTED_MATCH_NEVER,
+ * and must never set a non-zero mask value for this field.
+ */
+#define	MAE_FIELD_UNSUPPORTED 0x0
+/* enum: The NIC supports this field, but cannot use it in a match rule. The
+ * driver must ensure that any mask for such a field in a match rule is zeroed.
+ * The NIC will reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_NEVER 0x1
+/* enum: The NIC supports this field, and must use it in all match rules. The
+ * driver must ensure that any mask for such a field is all ones. The NIC will
+ * reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_ALWAYS 0x2
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver must ensure that any mask for such a field is either all zeroes
+ * or all ones. The NIC will reject requests with an invalid mask for such a
+ * field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_OPTIONAL 0x3
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver must ensure that any mask for such a field is either all zeroes
+ * or a consecutive set of ones following by all zeroes (starting from MSB).
+ * The NIC will reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_PREFIX 0x4
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver may provide an arbitrary mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_MASK 0x5
+
+/* MAE_FIELD enum: NB: this enum shares namespace with the support status enum.
+ */
+/* enum: Source mport upon entering the MAE. */
+#define	MAE_FIELD_INGRESS_PORT 0x0
+#define	MAE_FIELD_MARK 0x1 /* enum */
+/* enum: Table ID used in action rule. Initially zero, can be changed in action
+ * rule response.
+ */
+#define	MAE_FIELD_RECIRC_ID 0x2
+#define	MAE_FIELD_IS_IP_FRAG 0x3 /* enum */
+#define	MAE_FIELD_DO_CT 0x4 /* enum */
+#define	MAE_FIELD_CT_HIT 0x5 /* enum */
+/* enum: Undefined unless CT_HIT=1. */
+#define	MAE_FIELD_CT_MARK 0x6
+/* enum: Undefined unless DO_CT=1. */
+#define	MAE_FIELD_CT_DOMAIN 0x7
+/* enum: Undefined unless CT_HIT=1. */
+#define	MAE_FIELD_CT_PRIVATE_FLAGS 0x8
+/* enum: 1 if the packet ingressed the NIC from one of the MACs, else 0. */
+#define	MAE_FIELD_IS_FROM_NETWORK 0x9
+#define	MAE_FIELD_ETHER_TYPE 0x21 /* enum */
+#define	MAE_FIELD_VLAN0_TCI 0x22 /* enum */
+#define	MAE_FIELD_VLAN0_PROTO 0x23 /* enum */
+#define	MAE_FIELD_VLAN1_TCI 0x24 /* enum */
+#define	MAE_FIELD_VLAN1_PROTO 0x25 /* enum */
+/* enum: Inner when encap */
+#define	MAE_FIELD_ETH_SADDR 0x28
+/* enum: Inner when encap */
+#define	MAE_FIELD_ETH_DADDR 0x29
+/* enum: Inner when encap. NB: IPv4 and IPv6 fields are mutually exclusive. */
+#define	MAE_FIELD_SRC_IP4 0x2a
+/* enum: Inner when encap */
+#define	MAE_FIELD_SRC_IP6 0x2b
+/* enum: Inner when encap */
+#define	MAE_FIELD_DST_IP4 0x2c
+/* enum: Inner when encap */
+#define	MAE_FIELD_DST_IP6 0x2d
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_PROTO 0x2e
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_TOS 0x2f
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_TTL 0x30
+/* enum: Inner when encap TODO: how this is defined? The raw flags +
+ * frag_offset from the packet, or some derived value more amenable to ternary
+ * matching? TODO: there was a proposal for driver-allocation fields. The
+ * driver would provide some instruction for how to extract given field values,
+ * and would be given a field id in return. It could then use that field id in
+ * its matches. This feels like it would be extremely hard to implement in
+ * hardware, but I mention it for completeness.
+ */
+#define	MAE_FIELD_IP_FLAGS 0x31
+/* enum: Ports (UDP, TCP) Inner when encap */
+#define	MAE_FIELD_L4_SPORT 0x32
+/* enum: Ports (UDP, TCP) Inner when encap */
+#define	MAE_FIELD_L4_DPORT 0x33
+/* enum: Inner when encap */
+#define	MAE_FIELD_TCP_FLAGS 0x34
+/* enum: The type of encapsulated used for this packet. Value as per
+ * ENCAP_TYPE_*.
+ */
+#define	MAE_FIELD_ENCAP_TYPE 0x3f
+/* enum: The ID of the outer rule that marked this packet as encapsulated.
+ * Useful for implicitly matching on outer fields.
+ */
+#define	MAE_FIELD_OUTER_RULE_ID 0x40
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETHER_TYPE 0x41
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN0_TCI 0x42
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN0_PROTO 0x43
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN1_TCI 0x44
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN1_PROTO 0x45
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETH_SADDR 0x48
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETH_DADDR 0x49
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_SRC_IP4 0x4a
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_SRC_IP6 0x4b
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_DST_IP4 0x4c
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_DST_IP6 0x4d
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_PROTO 0x4e
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_TOS 0x4f
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_TTL 0x50
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_FLAGS 0x51
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_L4_SPORT 0x52
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_L4_DPORT 0x53
+/* enum: VNI (when VXLAN or GENEVE) VSID (when NVGRE) Outer; only present when
+ * encap
+ */
+#define	MAE_FIELD_ENC_VNET_ID 0x54
+
 /* MAE_MCDI_ENCAP_TYPE enum: Encapsulation type. Defines how the payload will
  * be parsed to an inner frame. Other values are reserved. Unknown values
  * should be treated same as NONE.
@@ -25644,6 +25789,900 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_OUT_ADDR_SPC_ID_LO_OFST 0
 #define	MC_CMD_GET_ADDR_SPC_ID_OUT_ADDR_SPC_ID_HI_OFST 4
 
+/* MAE_FIELD_FLAGS structuredef */
+#define	MAE_FIELD_FLAGS_LEN 4
+#define	MAE_FIELD_FLAGS_FLAT_OFST 0
+#define	MAE_FIELD_FLAGS_FLAT_LEN 4
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_OFST 0
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_LBN 0
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_WIDTH 6
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_OFST 0
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_LBN 6
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_WIDTH 1
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_OFST 0
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_LBN 7
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_WIDTH 1
+#define	MAE_FIELD_FLAGS_FLAT_LBN 0
+#define	MAE_FIELD_FLAGS_FLAT_WIDTH 32
+
+/* MAE_ENC_FIELD_PAIRS structuredef: Mask and value pairs for all fields that
+ * it makes sense to use to determine the encapsulation type of a packet. Its
+ * intended use is to keep a common packing of fields across multiple MCDI
+ * commands, keeping things inherently sychronised and allowing code shared. To
+ * use in an MCDI command, the command should end with a variable length byte
+ * array populated with this structure. Do not extend this structure. Instead,
+ * create _Vx versions with the necessary fields appended. That way, the
+ * existing semantics for extending MCDI commands are preserved.
+ */
+#define	MAE_ENC_FIELD_PAIRS_LEN 156
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_OFST 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_LBN 64
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_OFST 10
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_LBN 80
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_OFST 12
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_LBN 96
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_OFST 14
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_LBN 112
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_OFST 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_LBN 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_OFST 18
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LBN 144
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_OFST 20
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_LBN 160
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_OFST 22
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_LBN 176
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_OFST 24
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_LBN 192
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_OFST 26
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LBN 208
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_OFST 28
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_LBN 224
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_OFST 34
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_LBN 272
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_OFST 40
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_LBN 320
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_OFST 46
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_LBN 368
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_OFST 52
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_LBN 416
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_OFST 56
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_LBN 448
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_OFST 60
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_LBN 480
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_OFST 76
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_LBN 608
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_OFST 92
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_LBN 736
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_OFST 96
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_LBN 768
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_OFST 100
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_LBN 800
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_OFST 116
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_LBN 928
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_OFST 132
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_LBN 1056
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_OFST 133
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_LBN 1064
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_OFST 134
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_LBN 1072
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_OFST 135
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_LBN 1080
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_OFST 136
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_LBN 1088
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_OFST 137
+#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
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_OFST 140
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_LBN 1120
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_OFST 144
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_LBN 1152
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_OFST 148
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_LBN 1184
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_OFST 150
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_LBN 1200
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_OFST 152
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_LBN 1216
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_OFST 154
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_LBN 1232
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_WIDTH 16
+
+/* MAE_FIELD_MASK_VALUE_PAIRS structuredef: Mask and value pairs for all fields
+ * currently defined. Same semantics as MAE_ENC_FIELD_PAIRS.
+ */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_LEN 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_OFST 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_LBN 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_OFST 12
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_LBN 96
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_OFST 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_LBN 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_OFST 18
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_LBN 144
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_OFST 20
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_LBN 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_OFST 22
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_LBN 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_OFST 24
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_LBN 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_OFST 26
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_LBN 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_OFST 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_LBN 224
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_OFST 30
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_LBN 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_OFST 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_LBN 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_OFST 34
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_LBN 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_OFST 36
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_LBN 288
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_OFST 42
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_LBN 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_OFST 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_LBN 384
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_OFST 54
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_LBN 432
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_OFST 60
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_LBN 480
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_OFST 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_LBN 512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_OFST 68
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_LBN 544
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_OFST 84
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_LBN 672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_OFST 100
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_LBN 800
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_OFST 104
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_LBN 832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_OFST 108
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_LBN 864
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_OFST 124
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_LBN 992
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_OFST 140
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_LBN 1120
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_OFST 141
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_LBN 1128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_OFST 142
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_LBN 1136
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_OFST 143
+#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
+#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
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_OFST 145
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_LBN 1160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_OFST 148
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_LBN 1184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_OFST 152
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_LBN 1216
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_OFST 156
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_LBN 1248
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_OFST 158
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_LBN 1264
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_OFST 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_LBN 1280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_OFST 162
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_LBN 1296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_OFST 164
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_LBN 1312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_OFST 166
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_LBN 1328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_OFST 168
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_LBN 1344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_OFST 172
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_LBN 1376
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_OFST 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_LBN 1408
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_OFST 180
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_LBN 1440
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_OFST 184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_LBN 1472
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_OFST 188
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_LBN 1504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_OFST 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_LBN 1536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_OFST 194
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_LBN 1552
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_OFST 196
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_LBN 1568
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_OFST 198
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LBN 1584
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_OFST 200
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_LBN 1600
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_OFST 202
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_LBN 1616
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_OFST 204
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_LBN 1632
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_OFST 206
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LBN 1648
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_OFST 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_LBN 1664
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_OFST 214
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_LBN 1712
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_OFST 220
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_LBN 1760
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_OFST 226
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_LBN 1808
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_OFST 232
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_LBN 1856
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_OFST 236
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_LBN 1888
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_OFST 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_LBN 1920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_OFST 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_LBN 2048
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_OFST 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_LBN 2176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_OFST 276
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_LBN 2208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_OFST 280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_LBN 2240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_OFST 296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_LBN 2368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_OFST 312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_LBN 2496
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_OFST 313
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_LBN 2504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_OFST 314
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_LBN 2512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_OFST 315
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_LBN 2520
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_OFST 316
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_LBN 2528
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_OFST 317
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_LBN 2536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_OFST 320
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_LBN 2560
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_OFST 324
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_LBN 2592
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_OFST 328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_LBN 2624
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_OFST 330
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_LBN 2640
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_OFST 332
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_LBN 2656
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_OFST 334
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_LBN 2672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_OFST 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_LBN 2688
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_OFST 340
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_LBN 2720
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_WIDTH 32
+
+/* MAE_FIELD_MASK_VALUE_PAIRS_V2 structuredef */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN 372
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_OFST 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_LBN 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_OFST 12
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_LBN 96
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_OFST 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_LBN 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_OFST 18
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_LBN 144
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_OFST 20
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_LBN 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_OFST 22
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_LBN 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_OFST 24
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_LBN 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_OFST 26
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_LBN 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_OFST 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_LBN 224
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_OFST 30
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_LBN 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_OFST 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_LBN 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_OFST 34
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_LBN 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_OFST 36
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_LBN 288
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_OFST 42
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_LBN 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_OFST 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_LBN 384
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_OFST 54
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_LBN 432
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_OFST 60
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_LBN 480
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_OFST 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_LBN 512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_OFST 68
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_LBN 544
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_OFST 84
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_LBN 672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_OFST 100
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_LBN 800
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_OFST 104
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_LBN 832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_OFST 108
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_LBN 864
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_OFST 124
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_LBN 992
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_OFST 140
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_LBN 1120
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_OFST 141
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_LBN 1128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_OFST 142
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_LBN 1136
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_OFST 143
+#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
+#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
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_OFST 145
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_LBN 1160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_OFST 148
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_LBN 1184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_OFST 152
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_LBN 1216
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_OFST 156
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_LBN 1248
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_OFST 158
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_LBN 1264
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_OFST 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_LBN 1280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_OFST 162
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_LBN 1296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_OFST 164
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_LBN 1312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_OFST 166
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_LBN 1328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_OFST 168
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_LBN 1344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_OFST 172
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_LBN 1376
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_OFST 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_LBN 1408
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_OFST 180
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_LBN 1440
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_OFST 184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_LBN 1472
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_OFST 188
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_LBN 1504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_OFST 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_LBN 1536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_OFST 194
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_LBN 1552
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_OFST 196
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_LBN 1568
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_OFST 198
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_LBN 1584
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_OFST 200
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_LBN 1600
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_OFST 202
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_LBN 1616
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_OFST 204
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_LBN 1632
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_OFST 206
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_LBN 1648
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_OFST 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_LBN 1664
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_OFST 214
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_LBN 1712
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_OFST 220
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_LBN 1760
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_OFST 226
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_LBN 1808
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_OFST 232
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_LBN 1856
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_OFST 236
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_LBN 1888
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_OFST 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_LBN 1920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_OFST 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_LBN 2048
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_OFST 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_LBN 2176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_OFST 276
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_LBN 2208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_OFST 280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_LBN 2240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_OFST 296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_LBN 2368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_OFST 312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_LBN 2496
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_OFST 313
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_LBN 2504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_OFST 314
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_LBN 2512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_OFST 315
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_LBN 2520
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_OFST 316
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_LBN 2528
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_OFST 317
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_LBN 2536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_OFST 320
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_LBN 2560
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_OFST 324
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_LBN 2592
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_OFST 328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_LBN 2624
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_OFST 330
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_LBN 2640
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_OFST 332
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_LBN 2656
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_OFST 334
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_LBN 2672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_OFST 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_LBN 2688
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_OFST 340
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_LBN 2720
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_LBN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_LBN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_LBN 3
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_LBN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_WIDTH 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_LBN 2752
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST 348
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_LBN 2784
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_OFST 352
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_LBN 2816
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_OFST 354
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_LBN 2832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_OFST 356
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_LBN 2848
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_OFST 360
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_LBN 2880
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_OFST 364
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_LBN 2912
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_WIDTH 8
+/* Set to zero. */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_OFST 365
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_LBN 2920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_OFST 366
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_LBN 2928
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_WIDTH 8
+/* Set to zero. */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_OFST 367
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_LBN 2936
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_OFST 368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_LBN 2944
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_WIDTH 8
+/* Set to zero */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_OFST 369
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_LBN 2952
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_OFST 370
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_LBN 2960
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_WIDTH 8
+/* Set to zero */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_OFST 371
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_LBN 2968
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_WIDTH 8
+
 /* 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
@@ -25699,4 +26738,1197 @@
 #define	MAE_MPORT_SELECTOR_FLAT_LBN 0
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
+
+/***********************************/
+/* MC_CMD_MAE_GET_CAPS
+ * Describes capabilities of the MAE (Match-Action Engine)
+ */
+#define	MC_CMD_MAE_GET_CAPS 0x140
+#undef	MC_CMD_0x140_PRIVILEGE_CTG
+
+#define	MC_CMD_0x140_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_OUT_LEN 52
+/* 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_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+/* The total number of counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_OUT_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_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_OUT_API_VER_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_GET_AR_CAPS
+ * Get a level of support for match fields when used in match-action rules
+ */
+#define	MC_CMD_MAE_GET_AR_CAPS 0x141
+#undef	MC_CMD_0x141_PRIVILEGE_CTG
+
+#define	MC_CMD_0x141_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_AR_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_AR_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_AR_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX 252
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_NUM(len) (((len)-4)/4)
+/* Number of fields actually returned in FIELD_FLAGS. */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_COUNT_LEN 4
+/* Array of values indicating the NIC's support for a given field, indexed by
+ * field id. The driver must ensure space for
+ * MC_CMD_MAE_GET_CAPS.MATCH_FIELD_COUNT entries in the array..
+ */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_LEN 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MINNUM 0
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MAXNUM 62
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MAXNUM_MCDI2 254
+
+
+/***********************************/
+/* MC_CMD_MAE_GET_OR_CAPS
+ * Get a level of support for fields used in outer rule keys.
+ */
+#define	MC_CMD_MAE_GET_OR_CAPS 0x142
+#undef	MC_CMD_0x142_PRIVILEGE_CTG
+
+#define	MC_CMD_0x142_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_OR_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_OR_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_OR_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX 252
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_NUM(len) (((len)-4)/4)
+/* Number of fields actually returned in FIELD_FLAGS. */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_COUNT_LEN 4
+/* Same semantics as MC_CMD_MAE_GET_AR_CAPS.MAE_FIELD_FLAGS */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_OFST 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_LEN 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MINNUM 0
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MAXNUM 62
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MAXNUM_MCDI2 254
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTER_ALLOC
+ * Allocate match-action-engine counters, which can be referenced in Action
+ * Rules.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC 0x143
+#undef	MC_CMD_0x143_PRIVILEGE_CTG
+
+#define	MC_CMD_0x143_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_COUNTER_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_LEN 4
+/* The number of counters that the driver would like allocated */
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT_LEN 4
+
+/* MC_CMD_MAE_COUNTER_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN 12
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX 252
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(num) (8+4*(num))
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NUM(len) (((len)-8)/4)
+/* 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.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* 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.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT_OFST 4
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT_LEN 4
+/* An array containing the IDs for the counters allocated. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_OFST 8
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM 61
+#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
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTER_FREE
+ * Free match-action-engine counters
+ */
+#define	MC_CMD_MAE_COUNTER_FREE 0x144
+#undef	MC_CMD_0x144_PRIVILEGE_CTG
+
+#define	MC_CMD_0x144_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_COUNTER_FREE_IN msgrequest */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMIN 8
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMAX 132
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2 132
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_NUM(len) (((len)-4)/4)
+/* The number of counter IDs to be freed. */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT_LEN 4
+/* An array containing the counter IDs to be freed. */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_OFST 4
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM 32
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_COUNTER_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN 12
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX 136
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2 136
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LEN(num) (8+4*(num))
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_NUM(len) (((len)-8)/4)
+/* Generation count. A packet with generation count == GENERATION_COUNT will
+ * contain the final values for these counter IDs, unless the counter values
+ * are zero and zero squash is enabled. Receiving a packet with generation
+ * count > GENERATION_COUNT guarantees that no more 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.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
+/* The number of counter IDs actually freed. It is never less than 1; failure
+ * to free a single counter will cause an error to be returned. It is never
+ * greater than the number that were requested to be freed, but may be less if
+ * counters could not be freed.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT_OFST 4
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT_LEN 4
+/* An array containing the IDs for the counters to that were freed. Note,
+ * failure to free a counter can only occur on incorrect driver behaviour, so
+ * asserting that the expected counters were freed is reasonable. When
+ * debugging, attempting to free a single counter at a time will provide a
+ * reason for the failure to free said counter.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_OFST 8
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MAXNUM 32
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_START
+ * Start streaming counter values, specifying an RxQ to deliver packets to.
+ * Counters allocated to the calling function will be written in a round robin
+ * at a fixed cycle rate, assuming sufficient credits are available. The driver
+ * may cause the counter values to be written at a slower rate by constraining
+ * the availability of credits. Note that if the driver wishes to deliver
+ * packets to a different queue, it must call MAE_COUNTERS_STREAM_STOP to stop
+ * delivering packets to the current queue first.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START 0x151
+
+/* MC_CMD_MAE_COUNTERS_STREAM_START_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN 8
+/* The RxQ to write packets to. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_QID_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_QID_LEN 2
+/* Maximum size in bytes of packets that may be written to the RxQ. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE_OFST 2
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE_LEN 2
+/* Optional flags. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_FLAGS_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_WIDTH 1
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_LBN 1
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_WIDTH 1
+
+/* MC_CMD_MAE_COUNTERS_STREAM_START_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_FLAGS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_FLAGS_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_WIDTH 1
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP
+ * Stop streaming counter values to the specified RxQ.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP 0x152
+
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN 2
+/* The RxQ to stop writing packets to. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_QID_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_QID_LEN 2
+
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN 4
+/* Generation count. The 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 will be written to
+ * this stream.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS
+ * Give a number of credits to the packetiser. Each credit received allows the
+ * MC to write one packet to the RxQ, therefore for each credit the driver must
+ * have written sufficient descriptors for a packet of length
+ * MAE_COUNTERS_PACKETISER_STREAM_START/PACKET_SIZE and rung the doorbell.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS 0x153
+
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN 4
+/* Number of credits to give to the packetiser. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS_LEN 4
+
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC
+ * Allocate encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC 0x148
+#undef	MC_CMD_0x148_PRIVILEGE_CTG
+
+#define	MC_CMD_0x148_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX 252
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(num) (4+1*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_NUM(len) (((len)-4)/1)
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_LEN 1
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MINNUM 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM 248
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2 1016
+
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN 4
+/* enum: An encap metadata ID that is guaranteed never to represent real encap
+ * metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE
+ * Update encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE 0x149
+#undef	MC_CMD_0x149_PRIVILEGE_CTG
+
+#define	MC_CMD_0x149_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMIN 8
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX 252
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(num) (8+1*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_NUM(len) (((len)-8)/1)
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_OFST 8
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_LEN 1
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MINNUM 0
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM 244
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM_MCDI2 1012
+
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_FREE
+ * Free encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE 0x14a
+#undef	MC_CMD_0x14a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MINNUM 1
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MAXNUM 32
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ENCAP_HEADER_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MINNUM 1
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MAXNUM 32
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MAC_ADDR_ALLOC
+ * Allocate MAC address. Hardware implementations have MAC addresses programmed
+ * into an indirection table, and clients should take care not to allocate the
+ * same MAC address twice (but instead reuse its ID).
+ */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC 0x15e
+#undef	MC_CMD_0x15e_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15e_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MAC_ADDR_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN 6
+/* MAC address as bytes in network order. */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_LEN 6
+
+/* MC_CMD_MAE_MAC_ADDR_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN 4
+/* enum: An MAC address ID that is guaranteed never to represent a real MAC
+ * address.
+ */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_MAC_ADDR_FREE
+ * Free MAC address.
+ */
+#define	MC_CMD_MAE_MAC_ADDR_FREE 0x15f
+#undef	MC_CMD_0x15f_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15f_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MAC_ADDR_FREE_IN msgrequest */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MINNUM 1
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MAXNUM 32
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_MAC_ADDR_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MINNUM 1
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MAXNUM 32
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_ALLOC
+ * Allocate an action set, which can be referenced either in response to an
+ * Action Rule, or as part of an Action Set List.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC 0x14d
+#undef	MC_CMD_0x14d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14d_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_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
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_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_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.
+ */
+#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
+/* 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. 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 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
+#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. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID_LEN 4
+
+/* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_AS_ID_LEN 4
+/* enum: An action set ID that is guaranteed never to represent an action set
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_FREE
+ */
+#define	MC_CMD_MAE_ACTION_SET_FREE 0x14e
+#undef	MC_CMD_0x14e_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14e_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_SET_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC
+ * Allocate an action set list (ASL) that can be referenced by an ID. The ASL
+ * ID can be used when inserting an action rule, so that for each packet
+ * matching the rule every action set in the list is applied.
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC 0x14f
+#undef	MC_CMD_0x14f_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14f_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMIN 8
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX 252
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_NUM(len) (((len)-4)/4)
+/* Number of elements in the AS_IDS field. */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_COUNT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_COUNT_LEN 4
+/* The IDs of the action sets in this list. The last element of this list may
+ * be the ID of an already allocated ASL. In this case the action sets from the
+ * already allocated ASL will be applied after the action sets supplied by this
+ * request. This mechanism can be used to reduce resource usage in the case
+ * where one ASL is a sublist of another ASL. The sublist should be allocated
+ * first, then the superlist should be allocated by supplying all required
+ * action set IDs that are not in the sublist followed by the ID of the
+ * sublist. One sublist can be referenced by multiple superlists.
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM 62
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2 254
+
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_LEN 4
+/* enum: An action set list ID that is guaranteed never to represent an action
+ * set list
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE
+ * Free match-action-engine redirect_lists
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE 0x150
+#undef	MC_CMD_0x150_PRIVILEGE_CTG
+
+#define	MC_CMD_0x150_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_INSERT
+ * Inserts an Outer Rule, which controls encapsulation parsing, and may
+ * influence the Lookup Sequence.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT 0x15a
+#undef	MC_CMD_0x15a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15a_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_MAE_OUTER_RULE_INSERT_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMIN 16
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX 252
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(num) (16+1*(num))
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_NUM(len) (((len)-16)/1)
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* Match priority. Lower values have higher priority. Must be less than
+ * MC_CMD_MAE_GET_CAPS_OUT.ENCAP_PRIOS If a packet matches two filters with
+ * equal priority then it is unspecified which takes priority.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+#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
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_LBN 1
+#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_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
+/* 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
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MINNUM 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MAXNUM 236
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MAXNUM_MCDI2 1004
+
+/* MC_CMD_MAE_OUTER_RULE_INSERT_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN 4
+/* enum: An outer match ID that is guaranteed never to represent an outer match
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_REMOVE
+ */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE 0x15b
+#undef	MC_CMD_0x15b_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15b_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_MAE_OUTER_RULE_REMOVE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMIN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMAX 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MINNUM 1
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MAXNUM 32
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_OUTER_RULE_REMOVE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMAX 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MINNUM 1
+#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
+
+/* MAE_ACTION_RULE_RESPONSE structuredef */
+#define	MAE_ACTION_RULE_RESPONSE_LEN 16
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_LBN 0
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_WIDTH 32
+/* Only one of ASL_ID or AS_ID may have a non-NULL value. */
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_OFST 4
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_LBN 32
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_WIDTH 32
+/* Controls lookup flow when this rule is hit. See sub-fields for details. More
+ * info on the lookup sequence can be found in SF-122976-TC. It is an error to
+ * set both DO_CT and DO_RECIRC.
+ */
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_LBN 0
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_WIDTH 1
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_LBN 1
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_WIDTH 1
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_LBN 2
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_LBN 8
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_WIDTH 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_LBN 16
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_WIDTH 16
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_LBN 64
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_WIDTH 32
+/* Counter ID to increment if DO_CT or DO_RECIRC is set. Must be set to
+ * COUNTER_ID_NULL otherwise.
+ */
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_OFST 12
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_LBN 96
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_INSERT
+ * Insert a rule specify that packets matching a filter be processed according
+ * to a previous allocated action. Masks can be set as indicated by
+ * MC_CMD_MAE_GET_MATCH_FIELD_CAPABILITIES.
+ */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT 0x15c
+#undef	MC_CMD_0x15c_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15c_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_INSERT_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMIN 28
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX 252
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LEN(num) (28+1*(num))
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_NUM(len) (((len)-28)/1)
+/* See MC_CMD_MAE_OUTER_RULE_REGISTER_IN/PRIO. */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_PRIO_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_PRIO_LEN 4
+/* Structure of the format MAE_ACTION_RULE_RESPONSE */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST 4
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN 20
+/* Reserved for future use. Must be set to zero. */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RSVD_OFST 24
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RSVD_LEN 4
+/* Structure of the format MAE_FIELD_MASK_VALUE_PAIRS */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST 28
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_LEN 1
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MINNUM 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MAXNUM 224
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MAXNUM_MCDI2 992
+
+/* MC_CMD_MAE_ACTION_RULE_INSERT_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN 4
+/* enum: An action rule ID that is guaranteed never to represent an action rule
+ */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_UPDATE
+ * Atomically change the response of an action rule. Firmware may return
+ * ENOTSUP, in which case the driver should DELETE/INSERT.
+ */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE 0x15d
+#undef	MC_CMD_0x15d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15d_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN 24
+/* ID of action rule to update */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_AR_ID_LEN 4
+/* Structure of the format MAE_ACTION_RULE_RESPONSE */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_RESPONSE_OFST 4
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_RESPONSE_LEN 20
+
+/* MC_CMD_MAE_ACTION_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_DELETE
+ */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE 0x155
+#undef	MC_CMD_0x155_PRIVILEGE_CTG
+
+#define	MC_CMD_0x155_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_DELETE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_RULE_DELETE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_LOOKUP
+ * Return the m-port corresponding to a selector.
+ */
+#define	MC_CMD_MAE_MPORT_LOOKUP 0x160
+#undef	MC_CMD_0x160_PRIVILEGE_CTG
+
+#define	MC_CMD_0x160_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_LOOKUP_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_LEN 4
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR_LEN 4
+
+/* MC_CMD_MAE_MPORT_LOOKUP_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN 4
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_MPORT_ID_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_ALLOC
+ * Allocates a m-port, which can subsequently be used in action rules as a
+ * match or delivery argument.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC 0x163
+#undef	MC_CMD_0x163_PRIVILEGE_CTG
+
+#define	MC_CMD_0x163_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_LEN 20
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_UUID_LEN 16
+
+/* MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN 24
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_UUID_LEN 16
+/* An m-port selector identifying the VNIC to which traffic should be
+ * delivered. This must currently be set to MAE_MPORT_SELECTOR_ASSIGNED (i.e.
+ * the m-port assigned to the calling client).
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT_OFST 20
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_VNIC_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_LEN 20
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_UUID_LEN 16
+
+/* MC_CMD_MAE_MPORT_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_LEN 4
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_MPORT_ID_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN 24
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID_LEN 4
+/* A value that will appear in the packet metadata for any packets delivered
+ * using an alias type m-port. This value is guaranteed unique on the VNIC
+ * being delivered to, and is guaranteed not to exceed the range of values
+ * representable in the relevant metadata field.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LABEL_OFST 20
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LABEL_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_LEN 4
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_MPORT_ID_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_FREE
+ * Free a m-port which was previously allocated by the driver.
+ */
+#define	MC_CMD_MAE_MPORT_FREE 0x164
+#undef	MC_CMD_0x164_PRIVILEGE_CTG
+
+#define	MC_CMD_0x164_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_FREE_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_FREE_IN_LEN 4
+/* MPORT_ID as returned by MC_CMD_MAE_MPORT_ALLOC. */
+#define	MC_CMD_MAE_MPORT_FREE_IN_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_FREE_IN_MPORT_ID_LEN 4
+
+/* MC_CMD_MAE_MPORT_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_FREE_OUT_LEN 0
+
+/* MAE_MPORT_DESC structuredef */
+#define	MAE_MPORT_DESC_LEN 52
+#define	MAE_MPORT_DESC_MPORT_ID_OFST 0
+#define	MAE_MPORT_DESC_MPORT_ID_LEN 4
+#define	MAE_MPORT_DESC_MPORT_ID_LBN 0
+#define	MAE_MPORT_DESC_MPORT_ID_WIDTH 32
+/* Reserved for future purposes, contains information independent of caller */
+#define	MAE_MPORT_DESC_FLAGS_OFST 4
+#define	MAE_MPORT_DESC_FLAGS_LEN 4
+#define	MAE_MPORT_DESC_FLAGS_LBN 32
+#define	MAE_MPORT_DESC_FLAGS_WIDTH 32
+#define	MAE_MPORT_DESC_CALLER_FLAGS_OFST 8
+#define	MAE_MPORT_DESC_CALLER_FLAGS_LEN 4
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_OFST 8
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_LBN 0
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_WIDTH 1
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_OFST 8
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_LBN 1
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_WIDTH 1
+#define	MAE_MPORT_DESC_CAN_DELETE_OFST 8
+#define	MAE_MPORT_DESC_CAN_DELETE_LBN 2
+#define	MAE_MPORT_DESC_CAN_DELETE_WIDTH 1
+#define	MAE_MPORT_DESC_CALLER_FLAGS_LBN 64
+#define	MAE_MPORT_DESC_CALLER_FLAGS_WIDTH 32
+/* Not the ideal name; it's really the type of thing connected to the m-port */
+#define	MAE_MPORT_DESC_MPORT_TYPE_OFST 12
+#define	MAE_MPORT_DESC_MPORT_TYPE_LEN 4
+/* enum: Connected to a MAC... */
+#define	MAE_MPORT_DESC_MPORT_TYPE_NET_PORT 0x0
+/* enum: Adds metadata and delivers to another m-port */
+#define	MAE_MPORT_DESC_MPORT_TYPE_ALIAS 0x1
+/* enum: Connected to a VNIC. */
+#define	MAE_MPORT_DESC_MPORT_TYPE_VNIC 0x2
+#define	MAE_MPORT_DESC_MPORT_TYPE_LBN 96
+#define	MAE_MPORT_DESC_MPORT_TYPE_WIDTH 32
+/* 128-bit value available to drivers for m-port identification. */
+#define	MAE_MPORT_DESC_UUID_OFST 16
+#define	MAE_MPORT_DESC_UUID_LEN 16
+#define	MAE_MPORT_DESC_UUID_LBN 128
+#define	MAE_MPORT_DESC_UUID_WIDTH 128
+/* Big wadge of space reserved for other common properties */
+#define	MAE_MPORT_DESC_RESERVED_OFST 32
+#define	MAE_MPORT_DESC_RESERVED_LEN 8
+#define	MAE_MPORT_DESC_RESERVED_LO_OFST 32
+#define	MAE_MPORT_DESC_RESERVED_HI_OFST 36
+#define	MAE_MPORT_DESC_RESERVED_LBN 256
+#define	MAE_MPORT_DESC_RESERVED_WIDTH 64
+/* Logical port index. Only valid when type NET Port. */
+#define	MAE_MPORT_DESC_NET_PORT_IDX_OFST 40
+#define	MAE_MPORT_DESC_NET_PORT_IDX_LEN 4
+#define	MAE_MPORT_DESC_NET_PORT_IDX_LBN 320
+#define	MAE_MPORT_DESC_NET_PORT_IDX_WIDTH 32
+/* The m-port delivered to */
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_OFST 40
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_LEN 4
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_LBN 320
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_WIDTH 32
+/* The type of thing that owns the VNIC */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_OFST 40
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_LEN 4
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION 0x1 /* enum */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_PLUGIN 0x2 /* enum */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_LBN 320
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_WIDTH 32
+/* The PCIe interface on which the funcion lives. CJK: We need an enumeration
+ * of interfaces that we extend as new interface (types) appear. This belongs
+ * elsewhere and should be referenced from here
+ */
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_OFST 44
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_LEN 4
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_LBN 352
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_WIDTH 32
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_OFST 48
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_LEN 2
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_LBN 384
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_WIDTH 16
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_OFST 50
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_LEN 2
+/* enum: Indicates that the function is a PF */
+#define	MAE_MPORT_DESC_VF_IDX_NULL 0xffff
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_LBN 400
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_WIDTH 16
+/* Reserved. Should be ignored for now. */
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_OFST 44
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_LEN 4
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_LBN 352
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_ENUMERATE
+ */
+#define	MC_CMD_MAE_MPORT_ENUMERATE 0x17c
+
+/* MC_CMD_MAE_MPORT_ENUMERATE_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_IN_LEN 0
+
+/* MC_CMD_MAE_MPORT_ENUMERATE_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMIN 8
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMAX 252
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LEN(num) (8+1*(num))
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_NUM(len) (((len)-8)/1)
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_COUNT_OFST 0
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_COUNT_LEN 4
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_SIZEOF_MPORT_DESC_OFST 4
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_SIZEOF_MPORT_DESC_LEN 4
+/* Any array of MAE_MPORT_DESC structures. The MAE_MPORT_DESC structure may
+ * grow in future version of this command. Drivers should use a stride of
+ * SIZEOF_MPORT_DESC. Fields beyond SIZEOF_MPORT_DESC are not present.
+ */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_OFST 8
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_LEN 1
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MINNUM 0
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MAXNUM 244
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1012
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.17.1


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

* [dpdk-dev] [PATCH 02/62] common/sfc_efx/base: indicate support for MAE
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 03/62] net/sfc: add a stub for attaching to MAE Andrew Rybchenko
                   ` (61 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Riverhead boards maintain support for MAE, a low-level Match-Action Engine.
The feature is documented in SF-122526-TC.

The new field will help client drivers to test
NIC support for MAE status.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_nic.c  | 15 +++++++++++++++
 drivers/common/sfc_efx/base/efx.h       |  2 ++
 drivers/common/sfc_efx/base/efx_check.h |  6 ++++++
 drivers/common/sfc_efx/base/siena_nic.c |  2 ++
 drivers/common/sfc_efx/efsys.h          |  2 ++
 5 files changed, 27 insertions(+)

diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index df7db6a803..68414d9fa9 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1421,8 +1421,23 @@ ef10_get_datapath_caps(
 	else
 		encp->enc_filter_action_mark_max = 0;
 
+#if EFSYS_OPT_MAE
+	/*
+	 * Indicate support for MAE.
+	 * MAE is supported by Riverhead boards starting with R2,
+	 * and it is required that FW is built with MAE support, too.
+	 */
+	if (CAP_FLAGS3(req, MAE_SUPPORTED))
+		encp->enc_mae_supported = B_TRUE;
+	else
+		encp->enc_mae_supported = B_FALSE;
+#else
+	encp->enc_mae_supported = B_FALSE;
+#endif /* EFSYS_OPT_MAE */
+
 #undef CAP_FLAGS1
 #undef CAP_FLAGS2
+#undef CAP_FLAGS3
 
 	return (0);
 
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index bd1ac303b1..9947882d26 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1593,6 +1593,8 @@ typedef struct efx_nic_cfg_s {
 	uint32_t		enc_mac_stats_nstats;
 	boolean_t		enc_fec_counters;
 	boolean_t		enc_hlb_counters;
+	/* NIC support for Match-Action Engine (MAE). */
+	boolean_t		enc_mae_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/efx_check.h b/drivers/common/sfc_efx/base/efx_check.h
index 8f42d87a04..078e5b9811 100644
--- a/drivers/common/sfc_efx/base/efx_check.h
+++ b/drivers/common/sfc_efx/base/efx_check.h
@@ -401,4 +401,10 @@
 # endif
 #endif /* EFSYS_OPT_DESC_PROXY */
 
+#if EFSYS_OPT_MAE
+# if !EFSYS_OPT_RIVERHEAD
+#  error "MAE requires RIVERHEAD"
+# endif
+#endif /* EFSYS_OPT_MAE */
+
 #endif /* _SYS_EFX_CHECK_H */
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 4137c1e245..e2af0ff3dc 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -196,6 +196,8 @@ siena_board_cfg(
 	encp->enc_filter_action_mark_supported = B_FALSE;
 	encp->enc_filter_action_mark_max = 0;
 
+	encp->enc_mae_supported = B_FALSE;
+
 	return (0);
 
 fail2:
diff --git a/drivers/common/sfc_efx/efsys.h b/drivers/common/sfc_efx/efsys.h
index f7d5f8a060..8636e73b68 100644
--- a/drivers/common/sfc_efx/efsys.h
+++ b/drivers/common/sfc_efx/efsys.h
@@ -167,6 +167,8 @@ prefetch_read_once(const volatile void *addr)
 
 #define EFSYS_OPT_DESC_PROXY 0
 
+#define EFSYS_OPT_MAE 0
+
 /* ID */
 
 typedef struct __efsys_identifier_s efsys_identifier_t;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 03/62] net/sfc: add a stub for attaching to MAE
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 02/62] common/sfc_efx/base: indicate support for MAE Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 04/62] common/sfc_efx/base: add MAE init/fini APIs Andrew Rybchenko
                   ` (60 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add a stub for MAE attach / detach path and introduce MAE-specific context.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |  1 +
 drivers/net/sfc/sfc.c       |  8 ++++++
 drivers/net/sfc/sfc.h       |  2 ++
 drivers/net/sfc/sfc_mae.c   | 49 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   | 41 +++++++++++++++++++++++++++++++
 5 files changed, 101 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 589f7863ae..7a893080cb 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -47,6 +47,7 @@ sources = files(
 	'sfc_tx.c',
 	'sfc_tso.c',
 	'sfc_filter.c',
+	'sfc_mae.c',
 	'sfc_flow.c',
 	'sfc_dp.c',
 	'sfc_ef10_rx.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 8fa790da55..3b896490f7 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -857,6 +857,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_filter_attach;
 
+	rc = sfc_mae_attach(sa);
+	if (rc != 0)
+		goto fail_mae_attach;
+
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
@@ -878,6 +882,9 @@ sfc_attach(struct sfc_adapter *sa)
 
 fail_sriov_vswitch_create:
 	sfc_flow_fini(sa);
+	sfc_mae_detach(sa);
+
+fail_mae_attach:
 	sfc_filter_detach(sa);
 
 fail_filter_attach:
@@ -918,6 +925,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_flow_fini(sa);
 
+	sfc_mae_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 047ca64de7..4b5d687108 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -27,6 +27,7 @@
 #include "sfc_log.h"
 #include "sfc_filter.h"
 #include "sfc_sriov.h"
+#include "sfc_mae.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -233,6 +234,7 @@ struct sfc_adapter {
 	struct sfc_intr			intr;
 	struct sfc_port			port;
 	struct sfc_filter		filter;
+	struct sfc_mae			mae;
 
 	struct sfc_flow_list		flow_list;
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
new file mode 100644
index 0000000000..3ce654c19b
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae.c
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#include <stdbool.h>
+
+#include <rte_common.h>
+
+#include "efx.h"
+
+#include "sfc.h"
+#include "sfc_log.h"
+
+int
+sfc_mae_attach(struct sfc_adapter *sa)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_mae *mae = &sa->mae;
+
+	sfc_log_init(sa, "entry");
+
+	if (!encp->enc_mae_supported) {
+		mae->status = SFC_MAE_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	mae->status = SFC_MAE_STATUS_SUPPORTED;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_mae_detach(struct sfc_adapter *sa)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	sfc_log_init(sa, "entry");
+
+	mae->status = SFC_MAE_STATUS_UNKNOWN;
+
+	sfc_log_init(sa, "done");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
new file mode 100644
index 0000000000..d7821e71cc
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#ifndef _SFC_MAE_H
+#define _SFC_MAE_H
+
+#include <stdbool.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Options for MAE support status */
+enum sfc_mae_status {
+	SFC_MAE_STATUS_UNKNOWN = 0,
+	SFC_MAE_STATUS_UNSUPPORTED,
+	SFC_MAE_STATUS_SUPPORTED
+};
+
+struct sfc_mae {
+	/** NIC support for MAE status */
+	enum sfc_mae_status		status;
+};
+
+struct sfc_adapter;
+
+int sfc_mae_attach(struct sfc_adapter *sa);
+void sfc_mae_detach(struct sfc_adapter *sa);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_H */
-- 
2.17.1


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

* [dpdk-dev] [PATCH 04/62] common/sfc_efx/base: add MAE init/fini APIs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (2 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 03/62] net/sfc: add a stub for attaching to MAE Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 05/62] drivers: init/fini MAE on attach/detach Andrew Rybchenko
                   ` (59 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The patch adds APIs for client drivers to initialise / finalise
MAE-specific context in NIC control structure. The context
itself will be used by the follow-up patches to store
supportive data for library-internal consumers.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 14 +++++
 drivers/common/sfc_efx/base/efx_impl.h        | 10 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 57 +++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build       |  1 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |  3 +
 5 files changed, 85 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_mae.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 9947882d26..f109c8e332 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4036,6 +4036,20 @@ efx_proxy_auth_privilege_modify(
 
 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
 
+#if EFSYS_OPT_MAE
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_init(
+	__in				efx_nic_t *enp);
+
+LIBEFX_API
+extern					void
+efx_mae_fini(
+	__in				efx_nic_t *enp);
+
+#endif /* EFSYS_OPT_MAE */
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 196fd4a79c..8e72796acf 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -780,6 +780,13 @@ typedef struct efx_proxy_ops_s {
 
 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
 
+#if EFSYS_OPT_MAE
+
+typedef struct efx_mae_s {
+} efx_mae_t;
+
+#endif /* EFSYS_OPT_MAE */
+
 #define	EFX_DRV_VER_MAX		20
 
 typedef struct efx_drv_cfg_s {
@@ -886,6 +893,9 @@ struct efx_nic_s {
 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
 	const efx_proxy_ops_t	*en_epop;
 #endif	/* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+#if EFSYS_OPT_MAE
+	efx_mae_t		*en_maep;
+#endif	/* EFSYS_OPT_MAE */
 };
 
 #define	EFX_FAMILY_IS_EF10(_enp) \
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
new file mode 100644
index 0000000000..0de9ccb2e0
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019 Xilinx, Inc. All rights reserved.
+ * All rights reserved.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+
+#if EFSYS_OPT_MAE
+
+	__checkReturn			efx_rc_t
+efx_mae_init(
+	__in				efx_nic_t *enp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_t *maep;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep);
+	if (maep == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	enp->en_maep = maep;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_fini(
+	__in				efx_nic_t *enp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_t *maep = enp->en_maep;
+
+	if (encp->enc_mae_supported == B_FALSE)
+		return;
+
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
+	enp->en_maep = NULL;
+}
+
+#endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index e0acbda993..2016346eb5 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -15,6 +15,7 @@ sources = [
 	'efx_intr.c',
 	'efx_lic.c',
 	'efx_mac.c',
+	'efx_mae.c',
 	'efx_mcdi.c',
 	'efx_mon.c',
 	'efx_nic.c',
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index f656d5b644..c76dfe1e45 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,9 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_fini;
+	efx_mae_init;
+
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
 	efx_mcdi_get_timeout;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 05/62] drivers: init/fini MAE on attach/detach
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (3 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 04/62] common/sfc_efx/base: add MAE init/fini APIs Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 06/62] common/sfc_efx/base: add an MAE limit query API Andrew Rybchenko
                   ` (58 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

These actions affect MAE supplementary resources which are libefx-internal.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/efsys.h |  2 +-
 drivers/net/sfc/sfc_mae.c      | 17 +++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/efsys.h b/drivers/common/sfc_efx/efsys.h
index 8636e73b68..bbe9f2ef12 100644
--- a/drivers/common/sfc_efx/efsys.h
+++ b/drivers/common/sfc_efx/efsys.h
@@ -167,7 +167,7 @@ prefetch_read_once(const volatile void *addr)
 
 #define EFSYS_OPT_DESC_PROXY 0
 
-#define EFSYS_OPT_MAE 0
+#define EFSYS_OPT_MAE 1
 
 /* ID */
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 3ce654c19b..2a7ed6377a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -21,6 +21,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	struct sfc_mae *mae = &sa->mae;
+	int rc;
 
 	sfc_log_init(sa, "entry");
 
@@ -29,21 +30,37 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		return 0;
 	}
 
+	sfc_log_init(sa, "init MAE");
+	rc = efx_mae_init(sa->nic);
+	if (rc != 0)
+		goto fail_mae_init;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 
 	sfc_log_init(sa, "done");
 
 	return 0;
+
+fail_mae_init:
+	sfc_log_init(sa, "failed %d", rc);
+
+	return rc;
 }
 
 void
 sfc_mae_detach(struct sfc_adapter *sa)
 {
 	struct sfc_mae *mae = &sa->mae;
+	enum sfc_mae_status status_prev = mae->status;
 
 	sfc_log_init(sa, "entry");
 
 	mae->status = SFC_MAE_STATUS_UNKNOWN;
 
+	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
+		return;
+
+	efx_mae_fini(sa->nic);
+
 	sfc_log_init(sa, "done");
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH 06/62] common/sfc_efx/base: add an MAE limit query API
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (4 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 05/62] drivers: init/fini MAE on attach/detach Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 07/62] net/sfc: add the concept of MAE (transfer) rules Andrew Rybchenko
                   ` (57 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add an API for client drivers to query the engine limits.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 10 +++
 drivers/common/sfc_efx/base/efx_impl.h        |  1 +
 drivers/common/sfc_efx/base/efx_mae.c         | 72 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 84 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f109c8e332..db66be0faf 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4048,6 +4048,16 @@ extern					void
 efx_mae_fini(
 	__in				efx_nic_t *enp);
 
+typedef struct efx_mae_limits_s {
+	uint32_t			eml_max_n_action_prios;
+} efx_mae_limits_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_get_limits(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_limits_t *emlp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 8e72796acf..6e9329c203 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -783,6 +783,7 @@ typedef struct efx_proxy_ops_s {
 #if EFSYS_OPT_MAE
 
 typedef struct efx_mae_s {
+	uint32_t			em_max_n_action_prios;
 } 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 0de9ccb2e0..c93342de15 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -10,6 +10,47 @@
 
 #if EFSYS_OPT_MAE
 
+static	__checkReturn			efx_rc_t
+efx_mae_get_capabilities(
+	__in				efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_GET_CAPS_IN_LEN,
+	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	efx_rc_t rc;
+
+	req.emr_cmd = MC_CMD_MAE_GET_CAPS;
+	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;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	maep->em_max_n_action_prios =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_init(
 	__in				efx_nic_t *enp)
@@ -31,8 +72,16 @@ efx_mae_init(
 
 	enp->en_maep = maep;
 
+	rc = efx_mae_get_capabilities(enp);
+	if (rc != 0)
+		goto fail3;
+
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
+	enp->en_maep = NULL;
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
@@ -54,4 +103,27 @@ efx_mae_fini(
 	enp->en_maep = NULL;
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_get_limits(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_limits_t *emlp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	struct efx_mae_s *maep = enp->en_maep;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index c76dfe1e45..4b500b646a 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -86,6 +86,7 @@ INTERNAL {
 	efx_mac_up;
 
 	efx_mae_fini;
+	efx_mae_get_limits;
 	efx_mae_init;
 
 	efx_mcdi_fini;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 07/62] net/sfc: add the concept of MAE (transfer) rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (5 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 06/62] common/sfc_efx/base: add an MAE limit query API Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 08/62] common/sfc_efx/base: add match spec init/fini APIs Andrew Rybchenko
                   ` (56 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Define the corresponding specification structure and
make the code identify MAE rules by testing transfer
attribute presence. Also, add a priority level check.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  5 +++--
 drivers/net/sfc/sfc_flow.c  | 26 ++++++++++++++++++++------
 drivers/net/sfc/sfc_flow.h  |  9 +++++++++
 drivers/net/sfc/sfc_mae.c   | 11 +++++++++++
 drivers/net/sfc/sfc_mae.h   |  2 ++
 5 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 959b52c1c3..7a5aff79f9 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -144,8 +144,9 @@ Flow API support
 Supported attributes:
 
 - Ingress
+- Transfer
 
-Supported pattern items:
+Supported pattern items (***non-transfer*** rules):
 
 - VOID
 
@@ -173,7 +174,7 @@ Supported pattern items:
 
 - NVGRE (exact match of virtual subnet ID)
 
-Supported actions:
+Supported actions (***non-transfer*** rules):
 
 - VOID
 
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index cb802d7991..86082208d0 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1124,12 +1124,15 @@ static const struct sfc_flow_item sfc_flow_items[] = {
  * Protocol-independent flow API support
  */
 static int
-sfc_flow_parse_attr(const struct rte_flow_attr *attr,
+sfc_flow_parse_attr(struct sfc_adapter *sa,
+		    const struct rte_flow_attr *attr,
 		    struct rte_flow *flow,
 		    struct rte_flow_error *error)
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_filter *spec_filter = &spec->filter;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae *mae = &sa->mae;
 
 	if (attr == NULL) {
 		rte_flow_error_set(error, EINVAL,
@@ -1167,10 +1170,20 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr,
 		spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
 		spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
 	} else {
-		rte_flow_error_set(error, ENOTSUP,
-				   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr,
-				   "Transfer is not supported");
-		return -rte_errno;
+		if (mae->status != SFC_MAE_STATUS_SUPPORTED) {
+			rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
+					   attr, "Transfer is not supported");
+			return -rte_errno;
+		}
+		if (attr->priority > mae->nb_action_rule_prios_max) {
+			rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+					   attr, "Unsupported priority level");
+			return -rte_errno;
+		}
+		spec->type = SFC_FLOW_SPEC_MAE;
+		spec_mae->priority = attr->priority;
 	}
 
 	return 0;
@@ -2403,10 +2416,11 @@ sfc_flow_parse(struct rte_eth_dev *dev,
 	       struct rte_flow *flow,
 	       struct rte_flow_error *error)
 {
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	const struct sfc_flow_ops_by_spec *ops;
 	int rc;
 
-	rc = sfc_flow_parse_attr(attr, flow, error);
+	rc = sfc_flow_parse_attr(sa, attr, flow, error);
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 433c7a31e9..1fbcb878d1 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -38,6 +38,7 @@ struct sfc_flow_rss {
 /* Flow engines supported by the implementation */
 enum sfc_flow_spec_type {
 	SFC_FLOW_SPEC_FILTER = 0,
+	SFC_FLOW_SPEC_MAE,
 
 	SFC_FLOW_SPEC_NTYPES
 };
@@ -58,6 +59,12 @@ struct sfc_flow_spec_filter {
 	struct sfc_flow_rss rss_conf;
 };
 
+/* MAE-specific flow specification */
+struct sfc_flow_spec_mae {
+	/* Desired priority level */
+	unsigned int			priority;
+};
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
@@ -67,6 +74,8 @@ struct sfc_flow_spec {
 	union {
 		/* Filter-based (VNIC level flows) specification */
 		struct sfc_flow_spec_filter filter;
+		/* MAE-based (lower-level HW switch flows) specification */
+		struct sfc_flow_spec_mae mae;
 	};
 };
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2a7ed6377a..487bd61f76 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -21,6 +21,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	struct sfc_mae *mae = &sa->mae;
+	efx_mae_limits_t limits;
 	int rc;
 
 	sfc_log_init(sa, "entry");
@@ -35,12 +36,21 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_init;
 
+	sfc_log_init(sa, "get MAE limits");
+	rc = efx_mae_get_limits(sa->nic, &limits);
+	if (rc != 0)
+		goto fail_mae_get_limits;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
+	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
 
 	sfc_log_init(sa, "done");
 
 	return 0;
 
+fail_mae_get_limits:
+	efx_mae_fini(sa->nic);
+
 fail_mae_init:
 	sfc_log_init(sa, "failed %d", rc);
 
@@ -55,6 +65,7 @@ sfc_mae_detach(struct sfc_adapter *sa)
 
 	sfc_log_init(sa, "entry");
 
+	mae->nb_action_rule_prios_max = 0;
 	mae->status = SFC_MAE_STATUS_UNKNOWN;
 
 	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d7821e71cc..dd9ca07d15 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -28,6 +28,8 @@ enum sfc_mae_status {
 struct sfc_mae {
 	/** NIC support for MAE status */
 	enum sfc_mae_status		status;
+	/** Priority level limit for MAE action rules */
+	unsigned int			nb_action_rule_prios_max;
 };
 
 struct sfc_adapter;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 08/62] common/sfc_efx/base: add match spec init/fini APIs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (6 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 07/62] net/sfc: add the concept of MAE (transfer) rules Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 09/62] net/sfc: add pattern parsing stub to MAE backend Andrew Rybchenko
                   ` (55 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

An MAE rule is a function of match criteria and a priority. The said match
criteria have to be provided using "mask-value pairs" packing format which
on its own should not be exposed to client drivers. The latter have to use
a functional interface of sorts in order to generate a match specification.

Define an EFX match specification and implement initialise / finalise APIs.
The "mask-value pairs" buffer itself is not used in this particular patch,
so the corresponding struct member will be added in the follow-up patch.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 22 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h        |  9 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 46 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  2 +
 4 files changed, 79 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index db66be0faf..40c5968ea9 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4058,6 +4058,28 @@ efx_mae_get_limits(
 	__in				efx_nic_t *enp,
 	__out				efx_mae_limits_t *emlp);
 
+typedef enum efx_mae_rule_type_e {
+	EFX_MAE_RULE_ACTION = 0,
+
+	EFX_MAE_RULE_NTYPES
+} efx_mae_rule_type_t;
+
+typedef struct efx_mae_match_spec_s	efx_mae_match_spec_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_init(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_rule_type_t type,
+	__in				uint32_t prio,
+	__out				efx_mae_match_spec_t **specp);
+
+LIBEFX_API
+extern					void
+efx_mae_match_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *spec);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 6e9329c203..931989f17a 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1675,6 +1675,15 @@ efx_pci_xilinx_cap_tbl_find(
 
 #endif /* EFSYS_OPT_PCI */
 
+#if EFSYS_OPT_MAE
+
+struct efx_mae_match_spec_s {
+	efx_mae_rule_type_t		emms_type;
+	uint32_t			emms_prio;
+};
+
+#endif /* EFSYS_OPT_MAE */
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index c93342de15..b1ebc93714 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -126,4 +126,50 @@ efx_mae_get_limits(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_init(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_rule_type_t type,
+	__in				uint32_t prio,
+	__out				efx_mae_match_spec_t **specp)
+{
+	efx_mae_match_spec_t *spec;
+	efx_rc_t rc;
+
+	switch (type) {
+	case EFX_MAE_RULE_ACTION:
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
+	if (spec == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	spec->emms_type = type;
+	spec->emms_prio = prio;
+
+	*specp = spec;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_match_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *spec)
+{
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 4b500b646a..57a6c96b3e 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -88,6 +88,8 @@ INTERNAL {
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
+	efx_mae_match_spec_fini;
+	efx_mae_match_spec_init;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 09/62] net/sfc: add pattern parsing stub to MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (7 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 08/62] common/sfc_efx/base: add match spec init/fini APIs Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 10/62] common/sfc_efx/base: add a match spec validate API Andrew Rybchenko
                   ` (54 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add pattern parsing stub, define and implement flow cleanup method.
The latter is needed to free any dynamic structures allocated
during flow parsing.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 41 +++++++++++++++++++++++-
 drivers/net/sfc/sfc_flow.h |  8 +++++
 drivers/net/sfc/sfc_mae.c  | 65 ++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  | 10 ++++++
 4 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 86082208d0..634818cdf2 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -27,20 +27,30 @@
 
 struct sfc_flow_ops_by_spec {
 	sfc_flow_parse_cb_t	*parse;
+	sfc_flow_cleanup_cb_t	*cleanup;
 	sfc_flow_insert_cb_t	*insert;
 	sfc_flow_remove_cb_t	*remove;
 };
 
 static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;
+static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_mae;
 static sfc_flow_insert_cb_t sfc_flow_filter_insert;
 static sfc_flow_remove_cb_t sfc_flow_filter_remove;
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 	.parse = sfc_flow_parse_rte_to_filter,
+	.cleanup = NULL,
 	.insert = sfc_flow_filter_insert,
 	.remove = sfc_flow_filter_remove,
 };
 
+static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
+	.parse = sfc_flow_parse_rte_to_mae,
+	.cleanup = sfc_mae_flow_cleanup,
+	.insert = NULL,
+	.remove = NULL,
+};
+
 static const struct sfc_flow_ops_by_spec *
 sfc_flow_get_ops_by_spec(struct rte_flow *flow)
 {
@@ -51,6 +61,9 @@ sfc_flow_get_ops_by_spec(struct rte_flow *flow)
 	case SFC_FLOW_SPEC_FILTER:
 		ops = &sfc_flow_ops_filter;
 		break;
+	case SFC_FLOW_SPEC_MAE:
+		ops = &sfc_flow_ops_mae;
+		break;
 	default:
 		SFC_ASSERT(false);
 		break;
@@ -1184,6 +1197,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;
 	}
 
 	return 0;
@@ -2408,6 +2422,25 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
 	return rc;
 }
 
+static int
+sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
+			  const struct rte_flow_item pattern[],
+			  __rte_unused const struct rte_flow_action actions[],
+			  struct rte_flow *flow,
+			  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;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	if (rc != 0)
+		return rc;
+
+	return 0;
+}
+
 static int
 sfc_flow_parse(struct rte_eth_dev *dev,
 	       const struct rte_flow_attr *attr,
@@ -2451,8 +2484,14 @@ sfc_flow_zmalloc(struct rte_flow_error *error)
 }
 
 static void
-sfc_flow_free(__rte_unused struct sfc_adapter *sa, struct rte_flow *flow)
+sfc_flow_free(struct sfc_adapter *sa, struct rte_flow *flow)
 {
+	const struct sfc_flow_ops_by_spec *ops;
+
+	ops = sfc_flow_get_ops_by_spec(flow);
+	if (ops != NULL && ops->cleanup != NULL)
+		ops->cleanup(sa, flow);
+
 	rte_free(flow);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 1fbcb878d1..03a68d8633 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -63,6 +63,8 @@ struct sfc_flow_spec_filter {
 struct sfc_flow_spec_mae {
 	/* Desired priority level */
 	unsigned int			priority;
+	/* EFX match specification */
+	efx_mae_match_spec_t		*match_spec;
 };
 
 /* Flow specification */
@@ -100,6 +102,7 @@ enum sfc_flow_item_layers {
 /* Flow parse context types */
 enum sfc_flow_parse_ctx_type {
 	SFC_FLOW_PARSE_CTX_FILTER = 0,
+	SFC_FLOW_PARSE_CTX_MAE,
 
 	SFC_FLOW_PARSE_CTX_NTYPES
 };
@@ -112,6 +115,8 @@ struct sfc_flow_parse_ctx {
 	union {
 		/* Context pointer valid for filter-based (VNIC) flows */
 		efx_filter_spec_t *filter;
+		/* Context pointer valid for MAE-based flows */
+		struct sfc_mae_parse_ctx *mae;
 	};
 };
 
@@ -154,6 +159,9 @@ typedef int (sfc_flow_parse_cb_t)(struct rte_eth_dev *dev,
 				  struct rte_flow *flow,
 				  struct rte_flow_error *error);
 
+typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
+				     struct rte_flow *flow);
+
 typedef int (sfc_flow_insert_cb_t)(struct sfc_adapter *sa,
 				   struct rte_flow *flow);
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 487bd61f76..53e141775a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -75,3 +75,68 @@ sfc_mae_detach(struct sfc_adapter *sa)
 
 	sfc_log_init(sa, "done");
 }
+
+void
+sfc_mae_flow_cleanup(struct sfc_adapter *sa,
+		     struct rte_flow *flow)
+{
+	struct sfc_flow_spec *spec;
+	struct sfc_flow_spec_mae *spec_mae;
+
+	if (flow == NULL)
+		return;
+
+	spec = &flow->spec;
+
+	if (spec == NULL)
+		return;
+
+	spec_mae = &spec->mae;
+
+	if (spec_mae->match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+}
+
+static const struct sfc_flow_item sfc_flow_items[] = {
+};
+
+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_error *error)
+{
+	struct sfc_mae_parse_ctx ctx_mae;
+	struct sfc_flow_parse_ctx ctx;
+	int rc;
+
+	memset(&ctx_mae, 0, sizeof(ctx_mae));
+
+	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
+				     spec->priority,
+				     &ctx_mae.match_spec_action);
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Failed to initialise action rule match specification");
+		goto fail_init_match_spec_action;
+	}
+
+	ctx.type = SFC_FLOW_PARSE_CTX_MAE;
+	ctx.mae = &ctx_mae;
+
+	rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
+				    pattern, &ctx, error);
+	if (rc != 0)
+		goto fail_parse_pattern;
+
+	spec->match_spec = ctx_mae.match_spec_action;
+
+	return 0;
+
+fail_parse_pattern:
+	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
+
+fail_init_match_spec_action:
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index dd9ca07d15..536dadd092 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -33,9 +33,19 @@ struct sfc_mae {
 };
 
 struct sfc_adapter;
+struct sfc_flow_spec;
+
+struct sfc_mae_parse_ctx {
+	efx_mae_match_spec_t		*match_spec_action;
+};
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 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_error *error);
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH 10/62] common/sfc_efx/base: add a match spec validate API
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (8 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 09/62] net/sfc: add pattern parsing stub to MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 11/62] net/sfc: validate match spec in MAE backend Andrew Rybchenko
                   ` (53 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE has restrictions on what kind of mask a particular field can have in a
match specification. Add an API for client drivers to check specifications.

The patch defines a field description list, whilst the list itself is
left empty. This is to provide a general idea of how field properties
will be used to validate a match specification. Particular fields
will be added to the list by follow-up patches.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  18 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  17 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 262 ++++++++++++++++++
 drivers/common/sfc_efx/base/efx_mcdi.h        |   4 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |   1 +
 5 files changed, 302 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 40c5968ea9..094fad6367 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4080,6 +4080,24 @@ efx_mae_match_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_match_spec_t *spec);
 
+typedef enum efx_mae_field_id_e {
+	EFX_MAE_FIELD_NIDS
+} efx_mae_field_id_t;
+
+/*
+ * Make sure that match fields known by EFX have proper masks set
+ * in the match specification as per requirements of SF-122526-TC.
+ *
+ * In the case efx_mae_field_id_t lacks named identifiers for any
+ * fields which the FW maintains with support status MATCH_ALWAYS,
+ * the validation result may not be accurate.
+ */
+LIBEFX_API
+extern	__checkReturn			boolean_t
+efx_mae_match_spec_is_valid(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 931989f17a..2b872bb62e 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -782,8 +782,22 @@ typedef struct efx_proxy_ops_s {
 
 #if EFSYS_OPT_MAE
 
+typedef struct efx_mae_field_cap_s {
+	uint32_t			emfc_support;
+	boolean_t			emfc_mask_affects_class;
+	boolean_t			emfc_match_affects_class;
+} efx_mae_field_cap_t;
+
 typedef struct efx_mae_s {
 	uint32_t			em_max_n_action_prios;
+	/*
+	 * The number of MAE field IDs recognised by the FW implementation.
+	 * Any field ID greater than or equal to this value is unsupported.
+	 */
+	uint32_t			em_max_nfields;
+	/** Action rule match field capabilities. */
+	efx_mae_field_cap_t		*em_action_rule_field_caps;
+	size_t				em_action_rule_field_caps_size;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
@@ -1680,6 +1694,9 @@ efx_pci_xilinx_cap_tbl_find(
 struct efx_mae_match_spec_s {
 	efx_mae_rule_type_t		emms_type;
 	uint32_t			emms_prio;
+	union emms_mask_value_pairs {
+		uint8_t			action[MAE_FIELD_MASK_VALUE_PAIRS_LEN];
+	} emms_mask_value_pairs;
 };
 
 #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 b1ebc93714..9e22c3d507 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -42,8 +42,93 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_prios =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
 
+	maep->em_max_nfields =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_mae_get_action_rule_caps(
+	__in				efx_nic_t *enp,
+	__in				unsigned int field_ncaps,
+	__out_ecount(field_ncaps)	efx_mae_field_cap_t *field_caps)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_GET_AR_CAPS_IN_LEN,
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2);
+	unsigned int mcdi_field_ncaps;
+	unsigned int i;
+	efx_rc_t rc;
+
+	if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) >
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
+
+	if (req.emr_out_length_used <
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	if (mcdi_field_ncaps > field_ncaps) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	for (i = 0; i < mcdi_field_ncaps; ++i) {
+		uint32_t match_flag;
+		uint32_t mask_flag;
+
+		field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_SUPPORT_STATUS);
+
+		match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
+
+		field_caps[i].emfc_match_affects_class =
+		    (match_flag != 0) ? B_TRUE : B_FALSE;
+
+		mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
+
+		field_caps[i].emfc_mask_affects_class =
+		    (mask_flag != 0) ? B_TRUE : B_FALSE;
+	}
+
 	return (0);
 
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
@@ -56,6 +141,8 @@ efx_mae_init(
 	__in				efx_nic_t *enp)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_field_cap_t *ar_fcaps;
+	size_t ar_fcaps_size;
 	efx_mae_t *maep;
 	efx_rc_t rc;
 
@@ -76,8 +163,27 @@ efx_mae_init(
 	if (rc != 0)
 		goto fail3;
 
+	ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
+	EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
+	if (ar_fcaps == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	maep->em_action_rule_field_caps_size = ar_fcaps_size;
+	maep->em_action_rule_field_caps = ar_fcaps;
+
+	rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
+	if (rc != 0)
+		goto fail5;
+
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+	EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
+fail4:
+	EFSYS_PROBE(fail4);
 fail3:
 	EFSYS_PROBE(fail3);
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
@@ -99,6 +205,8 @@ efx_mae_fini(
 	if (encp->enc_mae_supported == B_FALSE)
 		return;
 
+	EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
+	    maep->em_action_rule_field_caps);
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
 	enp->en_maep = NULL;
 }
@@ -172,4 +280,158 @@ efx_mae_match_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+/* Named identifiers which are valid indices to efx_mae_field_cap_t */
+typedef enum efx_mae_field_cap_id_e {
+	EFX_MAE_FIELD_CAP_NIDS
+} efx_mae_field_cap_id_t;
+
+typedef enum efx_mae_field_endianness_e {
+	EFX_MAE_FIELD_LE = 0,
+	EFX_MAE_FIELD_BE,
+
+	EFX_MAE_FIELD_ENDIANNESS_NTYPES
+} efx_mae_field_endianness_t;
+
+/*
+ * The following structure is a means to describe an MAE field.
+ * The information in it is meant to be used internally by
+ * APIs for addressing a given field in a mask-value pairs
+ * structure and for validation purposes.
+ */
+typedef struct efx_mae_mv_desc_s {
+	efx_mae_field_cap_id_t		emmd_field_cap_id;
+
+	size_t				emmd_value_size;
+	size_t				emmd_value_offset;
+	size_t				emmd_mask_size;
+	size_t				emmd_mask_offset;
+
+	efx_mae_field_endianness_t	emmd_endianness;
+} efx_mae_mv_desc_t;
+
+/* Indices to this array are provided by efx_mae_field_id_t */
+static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
+};
+
+#define	EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit)		\
+	    ((_mask)[(_bit) / (_mask_page_nbits)] &			\
+		    (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
+
+static inline				boolean_t
+efx_mask_is_prefix(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	boolean_t prev_bit_is_set = B_TRUE;
+	unsigned int i;
+
+	for (i = 0; i < 8 * mask_nbytes; ++i) {
+		boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i);
+
+		if (!prev_bit_is_set && bit_is_set)
+			return B_FALSE;
+
+		prev_bit_is_set = bit_is_set;
+	}
+
+	return B_TRUE;
+}
+
+static inline				boolean_t
+efx_mask_is_all_ones(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	unsigned int i;
+	uint8_t t = ~0;
+
+	for (i = 0; i < mask_nbytes; ++i)
+		t &= maskp[i];
+
+	return (t == (uint8_t)(~0));
+}
+
+static inline				boolean_t
+efx_mask_is_all_zeros(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	unsigned int i;
+	uint8_t t = 0;
+
+	for (i = 0; i < mask_nbytes; ++i)
+		t |= maskp[i];
+
+	return (t == 0);
+}
+
+	__checkReturn			boolean_t
+efx_mae_match_spec_is_valid(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec)
+{
+	efx_mae_t *maep = enp->en_maep;
+	unsigned int field_ncaps = maep->em_max_nfields;
+	const efx_mae_field_cap_t *field_caps;
+	const efx_mae_mv_desc_t *desc_setp;
+	unsigned int desc_set_nentries;
+	boolean_t is_valid = B_TRUE;
+	efx_mae_field_id_t field_id;
+	const uint8_t *mvp;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		field_caps = maep->em_action_rule_field_caps;
+		desc_setp = __efx_mae_action_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		return (B_FALSE);
+	}
+
+	if (field_caps == NULL)
+		return (B_FALSE);
+
+	for (field_id = 0; field_id < desc_set_nentries; ++field_id) {
+		const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
+		efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
+		const uint8_t *m_buf = mvp + descp->emmd_mask_offset;
+		size_t m_size = descp->emmd_mask_size;
+
+		if (m_size == 0)
+			continue; /* Skip array gap */
+
+		if (field_cap_id >= field_ncaps)
+			break;
+
+		switch (field_caps[field_cap_id].emfc_support) {
+		case MAE_FIELD_SUPPORTED_MATCH_MASK:
+			is_valid = B_TRUE;
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_PREFIX:
+			is_valid = efx_mask_is_prefix(m_size, m_buf);
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
+			is_valid = (efx_mask_is_all_ones(m_size, m_buf) ||
+			    efx_mask_is_all_zeros(m_size, m_buf));
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
+			is_valid = efx_mask_is_all_ones(m_size, m_buf);
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_NEVER:
+		case MAE_FIELD_UNSUPPORTED:
+		default:
+			is_valid = efx_mask_is_all_zeros(m_size, m_buf);
+			break;
+		}
+
+		if (is_valid == B_FALSE)
+			break;
+	}
+
+	return (is_valid);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 77a3d636e2..9dd0a23862 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -421,6 +421,10 @@ efx_mcdi_phy_module_get_info(
 	EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),		\
 			MC_CMD_ ## _field)
 
+#define	MCDI_OUT_INDEXED_DWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_EV_FIELD(_eqp, _field)					\
 	EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field)
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 57a6c96b3e..0e6d44b6dc 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_init;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
+	efx_mae_match_spec_is_valid;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 11/62] net/sfc: validate match spec in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (9 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 10/62] common/sfc_efx/base: add a match spec validate API Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 12/62] common/sfc_efx/base: add a match specs class comparison API Andrew Rybchenko
                   ` (52 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Validate the match specification resulting from pattern
parsing within MAE backend in RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 53e141775a..7e4397762b 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -130,10 +130,18 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_parse_pattern;
 
+	if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
+		rc = rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					"Inconsistent pattern");
+		goto fail_validate_match_spec_action;
+	}
+
 	spec->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
+fail_validate_match_spec_action:
 fail_parse_pattern:
 	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
 
-- 
2.17.1


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

* [dpdk-dev] [PATCH 12/62] common/sfc_efx/base: add a match specs class comparison API
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (10 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 11/62] net/sfc: validate match spec in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 13/62] net/sfc: add verify method to flow validate path Andrew Rybchenko
                   ` (51 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

From MAE standpoint, a flow rule belongs to some class. Field capabilities
advertised by the FW provide a hint on whether changing a particular match
field value or its mask will affect the class of the rule. A client driver
can make use of the concept of a class by comparing a rule being validated
with already inserted ones so that if an existing rule with the same class
is encountered, it will become possible to skip making an explicit request
to the FW because the class of an already inserted rule is wittingly valid.

Implement an API for client drivers to carry out the said class comparison.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 13 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 96 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 3 files changed, 110 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 094fad6367..c91f7948a0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4098,6 +4098,19 @@ efx_mae_match_spec_is_valid(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_match_spec_t *spec);
 
+/*
+ * Conduct a comparison to check whether two match specifications
+ * of equal rule type (action / outer) and priority would map to
+ * the very same rule class from the firmware's standpoint.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_specs_class_cmp(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right,
+	__out				boolean_t *have_same_classp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 9e22c3d507..a126cba37f 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -434,4 +434,100 @@ efx_mae_match_spec_is_valid(
 	return (is_valid);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_match_specs_class_cmp(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right,
+	__out				boolean_t *have_same_classp)
+{
+	efx_mae_t *maep = enp->en_maep;
+	unsigned int field_ncaps = maep->em_max_nfields;
+	const efx_mae_field_cap_t *field_caps;
+	const efx_mae_mv_desc_t *desc_setp;
+	unsigned int desc_set_nentries;
+	boolean_t have_same_class = B_TRUE;
+	efx_mae_field_id_t field_id;
+	const uint8_t *mvpl;
+	const uint8_t *mvpr;
+	efx_rc_t rc;
+
+	switch (left->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		field_caps = maep->em_action_rule_field_caps;
+		desc_setp = __efx_mae_action_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		mvpl = left->emms_mask_value_pairs.action;
+		mvpr = right->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (field_caps == NULL) {
+		rc = EAGAIN;
+		goto fail2;
+	}
+
+	if (left->emms_type != right->emms_type ||
+	    left->emms_prio != right->emms_prio) {
+		/*
+		 * Rules of different types can never map to the same class.
+		 *
+		 * The FW can support some set of match criteria for one
+		 * priority and not support the very same set for
+		 * another priority. Thus, two rules which have
+		 * different priorities can never map to
+		 * the same class.
+		 */
+		*have_same_classp = B_FALSE;
+		return (0);
+	}
+
+	for (field_id = 0; field_id < desc_set_nentries; ++field_id) {
+		const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
+		efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
+
+		if (descp->emmd_mask_size == 0)
+			continue; /* Skip array gap */
+
+		if (field_cap_id >= field_ncaps)
+			break;
+
+		if (field_caps[field_cap_id].emfc_mask_affects_class) {
+			const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset;
+			const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset;
+			size_t mask_size = descp->emmd_mask_size;
+
+			if (memcmp(lmaskp, rmaskp, mask_size) != 0) {
+				have_same_class = B_FALSE;
+				break;
+			}
+		}
+
+		if (field_caps[field_cap_id].emfc_match_affects_class) {
+			const uint8_t *lvalp = mvpl + descp->emmd_value_offset;
+			const uint8_t *rvalp = mvpr + descp->emmd_value_offset;
+			size_t value_size = descp->emmd_value_size;
+
+			if (memcmp(lvalp, rvalp, value_size) != 0) {
+				have_same_class = B_FALSE;
+				break;
+			}
+		}
+	}
+
+	*have_same_classp = have_same_class;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 0e6d44b6dc..aeb6f4d134 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,6 +91,7 @@ INTERNAL {
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
 	efx_mae_match_spec_is_valid;
+	efx_mae_match_specs_class_cmp;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 13/62] net/sfc: add verify method to flow validate path
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (11 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 12/62] common/sfc_efx/base: add a match specs class comparison API Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 14/62] common/sfc_efx/base: add action set spec init/fini APIs Andrew Rybchenko
                   ` (50 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The new method is needed to make sure that a flow being
validated will have a chance to be accepted by the FW.
MAE-specific implementation of the method should
compare the class of a rule being validated with
the corresponding classes of active rules, and,
if no matches found, make a request to the FW.
Support for the latter will be added in future.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 40 ++++++++++++++++++++
 drivers/net/sfc/sfc_flow.h |  3 ++
 drivers/net/sfc/sfc_mae.c  | 75 ++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  1 +
 4 files changed, 119 insertions(+)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 634818cdf2..f69dd6ac5d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -27,6 +27,7 @@
 
 struct sfc_flow_ops_by_spec {
 	sfc_flow_parse_cb_t	*parse;
+	sfc_flow_verify_cb_t	*verify;
 	sfc_flow_cleanup_cb_t	*cleanup;
 	sfc_flow_insert_cb_t	*insert;
 	sfc_flow_remove_cb_t	*remove;
@@ -39,6 +40,7 @@ static sfc_flow_remove_cb_t sfc_flow_filter_remove;
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 	.parse = sfc_flow_parse_rte_to_filter,
+	.verify = NULL,
 	.cleanup = NULL,
 	.insert = sfc_flow_filter_insert,
 	.remove = sfc_flow_filter_remove,
@@ -46,6 +48,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
 	.parse = sfc_flow_parse_rte_to_mae,
+	.verify = sfc_mae_flow_verify,
 	.cleanup = sfc_mae_flow_cleanup,
 	.insert = NULL,
 	.remove = NULL,
@@ -2543,6 +2546,41 @@ sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow,
 	return rc;
 }
 
+static int
+sfc_flow_verify(struct sfc_adapter *sa, struct rte_flow *flow,
+		struct rte_flow_error *error)
+{
+	const struct sfc_flow_ops_by_spec *ops;
+	int rc = 0;
+
+	ops = sfc_flow_get_ops_by_spec(flow);
+	if (ops == NULL) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "No backend to handle this flow");
+		return -rte_errno;
+	}
+
+	if (ops->verify != NULL) {
+		/*
+		 * Use locking since verify method may need to
+		 * access the list of already created rules.
+		 */
+		sfc_adapter_lock(sa);
+		rc = ops->verify(sa, flow);
+		sfc_adapter_unlock(sa);
+	}
+
+	if (rc != 0) {
+		rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Failed to verify flow validity with FW");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
 static int
 sfc_flow_validate(struct rte_eth_dev *dev,
 		  const struct rte_flow_attr *attr,
@@ -2559,6 +2597,8 @@ sfc_flow_validate(struct rte_eth_dev *dev,
 		return -rte_errno;
 
 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	if (rc == 0)
+		rc = sfc_flow_verify(sa, flow, error);
 
 	sfc_flow_free(sa, flow);
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 03a68d8633..164e9f9a9a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -159,6 +159,9 @@ typedef int (sfc_flow_parse_cb_t)(struct rte_eth_dev *dev,
 				  struct rte_flow *flow,
 				  struct rte_flow_error *error);
 
+typedef int (sfc_flow_verify_cb_t)(struct sfc_adapter *sa,
+				   struct rte_flow *flow);
+
 typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
 				     struct rte_flow *flow);
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7e4397762b..42200c3f7e 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -148,3 +148,78 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 fail_init_match_spec_action:
 	return rc;
 }
+
+static bool
+sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
+			const efx_mae_match_spec_t *left,
+			const efx_mae_match_spec_t *right)
+{
+	bool have_same_class;
+	int rc;
+
+	rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
+					   &have_same_class);
+
+	return (rc == 0) ? have_same_class : false;
+}
+
+static int
+sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
+				 struct sfc_flow_spec_mae *spec)
+{
+	const struct rte_flow *entry;
+
+	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;
+
+		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);
+		}
+	}
+
+	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
+		 "support for inner frame pattern items is not guaranteed; "
+		 "other than that, the items are valid from SW standpoint");
+	return 0;
+}
+
+/**
+ * Confirm that a given flow can be accepted by the FW.
+ *
+ * @param sa
+ *   Software adapter context
+ * @param flow
+ *   Flow to be verified
+ * @return
+ *   Zero on success and non-zero in the case of error.
+ *   A special value of EAGAIN indicates that the adapter is
+ *   not in started state. This state is compulsory because
+ *   it only makes sense to compare the rule class of the flow
+ *   being validated with classes of the active rules.
+ *   Such classes are wittingly supported by the FW.
+ */
+int
+sfc_mae_flow_verify(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (sa->state != SFC_ADAPTER_STARTED)
+		return EAGAIN;
+
+	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 536dadd092..4c5bc4c6ce 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -46,6 +46,7 @@ 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_error *error);
+sfc_flow_verify_cb_t sfc_mae_flow_verify;
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH 14/62] common/sfc_efx/base: add action set spec init/fini APIs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (12 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 13/62] net/sfc: add verify method to flow validate path Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-27  8:56   ` Ali Alnubani
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 15/62] net/sfc: add actions parsing stub to MAE backend Andrew Rybchenko
                   ` (49 subsequent siblings)
  63 siblings, 1 reply; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The engine is only able to carry out chosen actions on matching packets in
a strict order. No MCDI exists to identify supported actions and the order.
Still, the definition of the latter is available from the FW documentation.

The general idea is to define an action specification structure and supply
a client driver with APIs for adding actions individually, order-dependent.
A client driver is supposed to invoke an API on every action passed by the
application, and if an out-of-order action follows, the API will reject it.

Add an action set specification stub and supply initialise / finalise APIs.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 20 ++++++++++
 drivers/common/sfc_efx/base/efx_impl.h        |  3 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 39 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  3 ++
 4 files changed, 65 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index c91f7948a0..cd0b22d43a 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4098,6 +4098,26 @@ efx_mae_match_spec_is_valid(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_match_spec_t *spec);
 
+typedef struct efx_mae_actions_s efx_mae_actions_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_init(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_actions_t **specp);
+
+LIBEFX_API
+extern					void
+efx_mae_action_set_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_actions_t *spec);
+
+LIBEFX_API
+extern	__checkReturn			boolean_t
+efx_mae_action_set_specs_equal(
+	__in				const efx_mae_actions_t *left,
+	__in				const efx_mae_actions_t *right);
+
 /*
  * Conduct a comparison to check whether two match specifications
  * of equal rule type (action / outer) and priority would map to
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 2b872bb62e..86ef8e1b92 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1699,6 +1699,9 @@ struct efx_mae_match_spec_s {
 	} emms_mask_value_pairs;
 };
 
+typedef struct efx_mae_actions_s {
+} efx_mae_actions_t;
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index a126cba37f..81c586dfe8 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -434,6 +434,45 @@ efx_mae_match_spec_is_valid(
 	return (is_valid);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_init(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_actions_t **specp)
+{
+	efx_mae_actions_t *spec;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
+	if (spec == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	*specp = spec;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_action_set_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_actions_t *spec)
+{
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
+}
+
+	__checkReturn			boolean_t
+efx_mae_action_set_specs_equal(
+	__in				const efx_mae_actions_t *left,
+	__in				const efx_mae_actions_t *right)
+{
+	return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_match_specs_class_cmp(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index aeb6f4d134..8a4d2b2fff 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,9 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_spec_fini;
+	efx_mae_action_set_spec_init;
+	efx_mae_action_set_specs_equal;
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 15/62] net/sfc: add actions parsing stub to MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (13 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 14/62] common/sfc_efx/base: add action set spec init/fini APIs Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 16/62] common/sfc_efx/base: support setting a PPORT in a match spec Andrew Rybchenko
                   ` (48 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

If parsing a flow results in an action set specification
identical to an already existing one, duplication will
be avoided by reusing the list entry of the latter.
Using an attach helper and a reference counter
is meant to serve the said purpose.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   8 ++-
 drivers/net/sfc/sfc_flow.h |   2 +
 drivers/net/sfc/sfc_mae.c  | 133 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  15 +++++
 4 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f69dd6ac5d..f4d53bf770 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1201,6 +1201,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;
 	}
 
 	return 0;
@@ -2428,7 +2429,7 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
 static int
 sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  const struct rte_flow_item pattern[],
-			  __rte_unused const struct rte_flow_action actions[],
+			  const struct rte_flow_action actions[],
 			  struct rte_flow *flow,
 			  struct rte_flow_error *error)
 {
@@ -2441,6 +2442,11 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		return rc;
 
+	rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set,
+					error);
+	if (rc != 0)
+		return rc;
+
 	return 0;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 164e9f9a9a..7d15f47e60 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -65,6 +65,8 @@ struct sfc_flow_spec_mae {
 	unsigned int			priority;
 	/* EFX match specification */
 	efx_mae_match_spec_t		*match_spec;
+	/* Action set registry entry */
+	struct sfc_mae_action_set	*action_set;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 42200c3f7e..de2c6b26e4 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -43,6 +43,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
+	TAILQ_INIT(&mae->action_sets);
 
 	sfc_log_init(sa, "done");
 
@@ -76,6 +77,68 @@ sfc_mae_detach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "done");
 }
 
+static struct sfc_mae_action_set *
+sfc_mae_action_set_attach(struct sfc_adapter *sa,
+			  const efx_mae_actions_t *spec)
+{
+	struct sfc_mae_action_set *action_set;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
+		if (efx_mae_action_set_specs_equal(action_set->spec, spec)) {
+			++(action_set->refcnt);
+			return action_set;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+sfc_mae_action_set_add(struct sfc_adapter *sa,
+		       efx_mae_actions_t *spec,
+		       struct sfc_mae_action_set **action_setp)
+{
+	struct sfc_mae_action_set *action_set;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
+	if (action_set == NULL)
+		return ENOMEM;
+
+	action_set->refcnt = 1;
+	action_set->spec = spec;
+
+	TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
+
+	*action_setp = action_set;
+
+	return 0;
+}
+
+static void
+sfc_mae_action_set_del(struct sfc_adapter *sa,
+		       struct sfc_mae_action_set *action_set)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(action_set->refcnt != 0);
+
+	--(action_set->refcnt);
+
+	if (action_set->refcnt != 0)
+		return;
+
+	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
+	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
+	rte_free(action_set);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -93,6 +156,9 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	spec_mae = &spec->mae;
 
+	if (spec_mae->action_set != NULL)
+		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);
 }
@@ -149,6 +215,73 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action(const struct rte_flow_action *action,
+			  __rte_unused efx_mae_actions_t *spec,
+			  struct rte_flow_error *error)
+{
+	switch (action->type) {
+	default:
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+				"Unsupported action");
+	}
+
+	return 0;
+}
+
+int
+sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
+			   const struct rte_flow_action actions[],
+			   struct sfc_mae_action_set **action_setp,
+			   struct rte_flow_error *error)
+{
+	const struct rte_flow_action *action;
+	efx_mae_actions_t *spec;
+	int rc;
+
+	if (actions == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
+				"NULL actions");
+	}
+
+	rc = efx_mae_action_set_spec_init(sa->nic, &spec);
+	if (rc != 0)
+		goto fail_action_set_spec_init;
+
+	for (action = actions;
+	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+		rc = sfc_mae_rule_parse_action(action, spec, error);
+		if (rc != 0)
+			goto fail_rule_parse_action;
+	}
+
+	*action_setp = sfc_mae_action_set_attach(sa, spec);
+	if (*action_setp != NULL) {
+		efx_mae_action_set_spec_fini(sa->nic, spec);
+		return 0;
+	}
+
+	rc = sfc_mae_action_set_add(sa, spec, action_setp);
+	if (rc != 0)
+		goto fail_action_set_add;
+
+	return 0;
+
+fail_action_set_add:
+fail_rule_parse_action:
+	efx_mae_action_set_spec_fini(sa->nic, spec);
+
+fail_action_set_spec_init:
+	if (rc > 0) {
+		rc = rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			NULL, "Failed to process the action");
+	}
+	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 4c5bc4c6ce..5727962a0b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -18,6 +18,15 @@
 extern "C" {
 #endif
 
+/** Action set registry entry */
+struct sfc_mae_action_set {
+	TAILQ_ENTRY(sfc_mae_action_set)	entries;
+	unsigned int			refcnt;
+	efx_mae_actions_t		*spec;
+};
+
+TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -30,6 +39,8 @@ struct sfc_mae {
 	enum sfc_mae_status		status;
 	/** Priority level limit for MAE action rules */
 	unsigned int			nb_action_rule_prios_max;
+	/** Action set registry */
+	struct sfc_mae_action_sets	action_sets;
 };
 
 struct sfc_adapter;
@@ -46,6 +57,10 @@ 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_error *error);
+int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
+			       const struct rte_flow_action actions[],
+			       struct sfc_mae_action_set **action_setp,
+			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 
 #ifdef __cplusplus
-- 
2.17.1


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

* [dpdk-dev] [PATCH 16/62] common/sfc_efx/base: support setting a PPORT in a match spec
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (14 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 15/62] net/sfc: add actions parsing stub to MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 17/62] net/sfc: support flow item PHY PORT in MAE backend Andrew Rybchenko
                   ` (47 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add an API for setting mask-value pairs in a match specification structure
and add support for MAE field INGRESS_PORT of type PPORT.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  48 +++++
 drivers/common/sfc_efx/base/efx_mae.c         | 170 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   3 +
 3 files changed, 221 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cd0b22d43a..4fb3b02aa8 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4081,9 +4081,57 @@ efx_mae_match_spec_fini(
 	__in				efx_mae_match_spec_t *spec);
 
 typedef enum efx_mae_field_id_e {
+	EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR = 0,
+
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
+/* MPORT selector. Used to refer to MPORTs in match/action rules. */
+typedef struct efx_mport_sel_s {
+	uint32_t sel;
+} efx_mport_sel_t;
+
+/*
+ * Get MPORT selector of a physical port.
+ *
+ * The resulting MPORT selector is opaque to the caller and can be
+ * passed as an argument to efx_mae_match_spec_mport_set().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_mport_by_phy_port(
+	__in				uint32_t phy_port,
+	__out				efx_mport_sel_t *mportp);
+
+/*
+ * Fields which have BE postfix in their named constants are expected
+ * to be passed by callers in big-endian byte order. They will appear
+ * in the MCDI buffer, which is a part of the match specification, in
+ * the very same byte order, that is, no conversion will be performed.
+ *
+ * Fields which don't have BE postfix in their named constants are in
+ * host byte order. MCDI expects them to be little-endian, so the API
+ * will take care to carry out conversion to little-endian byte order.
+ * At the moment, the only field in host byte order is MPORT selector.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__in_bcount(value_size)		const uint8_t *value,
+	__in				size_t mask_size,
+	__in_bcount(mask_size)		const uint8_t *mask);
+
+/* If the mask argument is NULL, the API will use full mask by default. */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_mport_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mport_sel_t *valuep,
+	__in_opt			const efx_mport_sel_t *maskp);
+
 /*
  * Make sure that match fields known by EFX have proper masks set
  * in the match specification as per requirements of SF-122526-TC.
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 81c586dfe8..4e6ae2227d 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -282,6 +282,8 @@ efx_mae_match_spec_fini(
 
 /* Named identifiers which are valid indices to efx_mae_field_cap_t */
 typedef enum efx_mae_field_cap_id_e {
+	EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
+
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
 
@@ -311,8 +313,176 @@ typedef struct efx_mae_mv_desc_s {
 
 /* Indices to this array are provided by efx_mae_field_id_t */
 static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
+#define	EFX_MAE_MV_DESC(_name, _endianness)				\
+	[EFX_MAE_FIELD_##_name] =					\
+	{								\
+		EFX_MAE_FIELD_ID_##_name,				\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_LEN,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_OFST,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_LEN,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_OFST,		\
+		_endianness						\
+	}
+
+	EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
+
+#undef EFX_MAE_MV_DESC
 };
 
+	__checkReturn			efx_rc_t
+efx_mae_mport_by_phy_port(
+	__in				uint32_t phy_port,
+	__out				efx_mport_sel_t *mportp)
+{
+	efx_dword_t dword;
+	efx_rc_t rc;
+
+	if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	EFX_POPULATE_DWORD_2(dword,
+	    MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
+	    MAE_MPORT_SELECTOR_PPORT_ID, phy_port);
+
+	memset(mportp, 0, sizeof (*mportp));
+	mportp->sel = dword.ed_u32[0];
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__in_bcount(value_size)		const uint8_t *value,
+	__in				size_t mask_size,
+	__in_bcount(mask_size)		const uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	uint8_t *mvp;
+	efx_rc_t rc;
+
+	if (field_id >= EFX_MAE_FIELD_NIDS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if (value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The mask/value are in network (big endian) order.
+		 * The MCDI request field is also big endian.
+		 */
+		memcpy(mvp + descp->emmd_value_offset, value, value_size);
+		memcpy(mvp + descp->emmd_mask_offset, mask, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The mask/value are in host byte order.
+		 * The MCDI request field is little endian.
+		 */
+		switch (value_size) {
+		case 4:
+			EFX_POPULATE_DWORD_1(dword,
+			    EFX_DWORD_0, *(const uint32_t *)value);
+
+			memcpy(mvp + descp->emmd_value_offset,
+			    &dword, sizeof (dword));
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			EFX_POPULATE_DWORD_1(dword,
+			    EFX_DWORD_0, *(const uint32_t *)mask);
+
+			memcpy(mvp + descp->emmd_mask_offset,
+			    &dword, sizeof (dword));
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+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_mport_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mport_sel_t *valuep,
+	__in_opt			const efx_mport_sel_t *maskp)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	if (valuep == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	vp = (const uint8_t *)&valuep->sel;
+	if (maskp != NULL)
+		mp = (const uint8_t *)&maskp->sel;
+	else
+		mp = (const uint8_t *)&full_mask;
+
+	rc = efx_mae_match_spec_field_set(spec,
+	    EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR,
+	    sizeof (valuep->sel), vp, sizeof (maskp->sel), mp);
+	if (rc != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #define	EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit)		\
 	    ((_mask)[(_bit) / (_mask_page_nbits)] &			\
 		    (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 8a4d2b2fff..86ed437e8d 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,10 +91,13 @@ INTERNAL {
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
+	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
 	efx_mae_match_spec_is_valid;
+	efx_mae_match_spec_mport_set;
 	efx_mae_match_specs_class_cmp;
+	efx_mae_mport_by_phy_port;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 17/62] net/sfc: support flow item PHY PORT in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (15 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 16/62] common/sfc_efx/base: support setting a PPORT in a match spec Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 18/62] common/sfc_efx/base: add MAE match fields for Ethernet Andrew Rybchenko
                   ` (46 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  4 +++
 drivers/net/sfc/sfc_mae.c   | 69 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |  1 +
 3 files changed, 74 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 7a5aff79f9..b12e93180e 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -188,6 +188,10 @@ Supported actions (***non-transfer*** rules):
 
 - MARK (supported only with ef10_essb Rx datapath)
 
+Supported pattern items (***transfer*** rules):
+
+- PHY_PORT (cannot repeat; conflicts with other traffic source items)
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index de2c6b26e4..87d2e15d29 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -163,7 +163,76 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
 }
 
+static int
+sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
+				 struct sfc_flow_parse_ctx *ctx,
+				 struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const struct rte_flow_item_phy_port supp_mask = {
+		.index = 0xffffffff,
+	};
+	const void *def_mask = &rte_flow_item_phy_port_mask;
+	const struct rte_flow_item_phy_port *spec = NULL;
+	const struct rte_flow_item_phy_port *mask = NULL;
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(struct rte_flow_item_phy_port), error);
+	if (rc != 0)
+		return rc;
+
+	if (mask->index != supp_mask.index) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad mask in the PHY_PORT pattern item");
+	}
+
+	/* If "spec" is not set, could be any physical port */
+	if (spec == NULL)
+		return 0;
+
+	rc = efx_mae_mport_by_phy_port(spec->index, &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PHY_PORT index");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PHY_PORT");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
+	{
+		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_phy_port,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 5727962a0b..1ef582e82b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -48,6 +48,7 @@ struct sfc_flow_spec;
 
 struct sfc_mae_parse_ctx {
 	efx_mae_match_spec_t		*match_spec_action;
+	bool				match_mport_set;
 };
 
 int sfc_mae_attach(struct sfc_adapter *sa);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 18/62] common/sfc_efx/base: add MAE match fields for Ethernet
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (16 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 17/62] net/sfc: support flow item PHY PORT in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 19/62] net/sfc: support flow item ETH in MAE backend Andrew Rybchenko
                   ` (45 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 3 +++
 drivers/common/sfc_efx/base/efx_mae.c | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 4fb3b02aa8..8d88834c30 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4082,6 +4082,9 @@ efx_mae_match_spec_fini(
 
 typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR = 0,
+	EFX_MAE_FIELD_ETHER_TYPE_BE,
+	EFX_MAE_FIELD_ETH_SADDR_BE,
+	EFX_MAE_FIELD_ETH_DADDR_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4e6ae2227d..01b2e311a5 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -283,6 +283,9 @@ efx_mae_match_spec_fini(
 /* Named identifiers which are valid indices to efx_mae_field_cap_t */
 typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
+	EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
+	EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
+	EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -325,6 +328,9 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	}
 
 	EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 19/62] net/sfc: support flow item ETH in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (17 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 18/62] common/sfc_efx/base: add MAE match fields for Ethernet Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 20/62] common/sfc_efx/base: support adding DELIVER action to a set Andrew Rybchenko
                   ` (44 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   2 +
 drivers/net/sfc/sfc_mae.c   | 106 ++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index b12e93180e..65d52d5551 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -192,6 +192,8 @@ Supported pattern items (***transfer*** rules):
 
 - PHY_PORT (cannot repeat; conflicts with other traffic source items)
 
+- ETH
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 87d2e15d29..95f8cffc27 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -221,6 +221,105 @@ sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 	return 0;
 }
 
+struct sfc_mae_field_locator {
+	efx_mae_field_id_t		field_id;
+	size_t				size;
+	/* Field offset in the corresponding rte_flow_item_ struct */
+	size_t				ofst;
+};
+
+static void
+sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
+			     unsigned int nb_field_locators, void *mask_ptr,
+			     size_t mask_size)
+{
+	unsigned int i;
+
+	memset(mask_ptr, 0, mask_size);
+
+	for (i = 0; i < nb_field_locators; ++i) {
+		const struct sfc_mae_field_locator *fl = &field_locators[i];
+
+		SFC_ASSERT(fl->ofst + fl->size <= mask_size);
+		memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size);
+	}
+}
+
+static int
+sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
+		   unsigned int nb_field_locators, const uint8_t *spec,
+		   const uint8_t *mask, efx_mae_match_spec_t *efx_spec,
+		   struct rte_flow_error *error)
+{
+	unsigned int i;
+	int rc = 0;
+
+	for (i = 0; i < nb_field_locators; ++i) {
+		const struct sfc_mae_field_locator *fl = &field_locators[i];
+
+		rc = efx_mae_match_spec_field_set(efx_spec, fl->field_id,
+						  fl->size, spec + fl->ofst,
+						  fl->size, mask + fl->ofst);
+		if (rc != 0)
+			break;
+	}
+
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
+				NULL, "Failed to process item fields");
+	}
+
+	return rc;
+}
+
+static const struct sfc_mae_field_locator flocs_eth[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type),
+		offsetof(struct rte_flow_item_eth, type),
+	},
+	{
+		EFX_MAE_FIELD_ETH_DADDR_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst),
+		offsetof(struct rte_flow_item_eth, dst),
+	},
+	{
+		EFX_MAE_FIELD_ETH_SADDR_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src),
+		offsetof(struct rte_flow_item_eth, src),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
+			    struct sfc_flow_parse_ctx *ctx,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct rte_flow_item_eth supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_eth_mask,
+				 sizeof(struct rte_flow_item_eth), error);
+	if (rc != 0)
+		return rc;
+
+	/* If "spec" is not set, could be any Ethernet */
+	if (spec == NULL)
+		return 0;
+
+	return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
@@ -233,6 +332,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_phy_port,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_ETH,
+		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
+		.layer = SFC_FLOW_ITEM_L2,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_eth,
+	},
 };
 
 int
-- 
2.17.1


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

* [dpdk-dev] [PATCH 20/62] common/sfc_efx/base: support adding DELIVER action to a set
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (18 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 19/62] net/sfc: support flow item ETH in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 21/62] net/sfc: support flow action PHY PORT in MAE backend Andrew Rybchenko
                   ` (43 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Introduce a mechanism for adding actions to an action set and
add support for DELIVER action.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  11 +-
 drivers/common/sfc_efx/base/efx_impl.h        |  11 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 141 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   1 +
 4 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 8d88834c30..6f63a6ecd0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4094,11 +4094,14 @@ typedef struct efx_mport_sel_s {
 	uint32_t sel;
 } efx_mport_sel_t;
 
+#define	EFX_MPORT_NULL			(0U)
+
 /*
  * Get MPORT selector of a physical port.
  *
  * The resulting MPORT selector is opaque to the caller and can be
- * passed as an argument to efx_mae_match_spec_mport_set().
+ * passed as an argument to efx_mae_match_spec_mport_set()
+ * and efx_mae_action_set_populate_deliver().
  */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
@@ -4163,6 +4166,12 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mport_sel_t *mportp);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 86ef8e1b92..927324c85c 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1699,7 +1699,18 @@ struct efx_mae_match_spec_s {
 	} emms_mask_value_pairs;
 };
 
+typedef enum efx_mae_action_e {
+	/* DELIVER is always the last action. */
+	EFX_MAE_ACTION_DELIVER,
+
+	EFX_MAE_NACTIONS
+} efx_mae_action_t;
+
 typedef struct efx_mae_actions_s {
+	/* Bitmap of actions in spec, indexed by action type */
+	uint32_t			emass_actions;
+
+	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_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 01b2e311a5..47611c4397 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -641,6 +641,147 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	if (arg_size != sizeof (spec->emass_deliver_mport)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	memcpy(&spec->emass_deliver_mport, arg, arg_size);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+typedef struct efx_mae_action_desc_s {
+	/* Action specific handler */
+	efx_rc_t	(*emad_add)(efx_mae_actions_t *,
+				    size_t, const uint8_t *);
+} efx_mae_action_desc_t;
+
+static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_DELIVER] = {
+		.emad_add = efx_mae_action_set_add_deliver
+	}
+};
+
+static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_DELIVER);
+
+static const uint32_t efx_mae_action_repeat_map = 0;
+
+/*
+ * Add an action to an action set.
+ *
+ * This has to be invoked in the desired action order.
+ * An out-of-order action request will be turned down.
+ */
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_populate(
+	__in				efx_mae_actions_t *spec,
+	__in				efx_mae_action_t type,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	uint32_t action_mask;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
+	    (sizeof (efx_mae_action_ordered_map) * 8));
+	EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
+	    (sizeof (efx_mae_action_repeat_map) * 8));
+
+	EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
+
+	if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	action_mask = (1U << type);
+
+	if ((spec->emass_actions & action_mask) != 0) {
+		/* The action set already contains this action. */
+		if ((efx_mae_action_repeat_map & action_mask) == 0) {
+			/* Cannot add another non-repeatable action. */
+			rc = ENOTSUP;
+			goto fail2;
+		}
+	}
+
+	if ((efx_mae_action_ordered_map & action_mask) != 0) {
+		uint32_t later_actions_mask =
+			efx_mae_action_ordered_map &
+			~(action_mask | (action_mask - 1));
+
+		if ((spec->emass_actions & later_actions_mask) != 0) {
+			/* Cannot add an action after later ordered actions. */
+			rc = ENOTSUP;
+			goto fail3;
+		}
+	}
+
+	if (efx_mae_actions[type].emad_add != NULL) {
+		rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
+		if (rc != 0)
+			goto fail4;
+	}
+
+	spec->emass_actions |= action_mask;
+
+	return (0);
+
+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_action_set_populate_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mport_sel_t *mportp)
+{
+	const uint8_t *arg;
+	efx_rc_t rc;
+
+	if (mportp == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	arg = (const uint8_t *)&mportp->sel;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
 	__in				const efx_mae_actions_t *left,
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 86ed437e8d..d2a5d58ae8 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,7 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 21/62] net/sfc: support flow action PHY PORT in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (19 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 20/62] common/sfc_efx/base: support adding DELIVER action to a set Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 22/62] common/sfc_efx/base: add MAE action set provisioning APIs Andrew Rybchenko
                   ` (42 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action DELIVER with
MPORT of a given physical port.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  4 ++++
 drivers/net/sfc/sfc_mae.c   | 40 +++++++++++++++++++++++++++++++++----
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 65d52d5551..e367ddd6e6 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -194,6 +194,10 @@ Supported pattern items (***transfer*** rules):
 
 - ETH
 
+Supported actions (***transfer*** rules):
+
+- PHY_PORT
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 95f8cffc27..057eef537b 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -391,18 +391,50 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_rule_parse_action(const struct rte_flow_action *action,
-			  __rte_unused efx_mae_actions_t *spec,
+sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
+				   const struct rte_flow_action_phy_port *conf,
+				   efx_mae_actions_t *spec)
+{
+	efx_mport_sel_t mport;
+	uint32_t phy_port;
+	int rc;
+
+	if (conf->original != 0)
+		phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port;
+	else
+		phy_port = conf->index;
+
+	rc = efx_mae_mport_by_phy_port(phy_port, &mport);
+	if (rc != 0)
+		return rc;
+
+	return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
+static int
+sfc_mae_rule_parse_action(struct sfc_adapter *sa,
+			  const struct rte_flow_action *action,
+			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
+	int rc;
+
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
+		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
+		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 				"Unsupported action");
 	}
 
-	return 0;
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
+				NULL, "Failed to request the action");
+	}
+
+	return rc;
 }
 
 int
@@ -427,7 +459,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_rule_parse_action(action, spec, error);
+		rc = sfc_mae_rule_parse_action(sa, action, spec, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 	}
-- 
2.17.1


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

* [dpdk-dev] [PATCH 22/62] common/sfc_efx/base: add MAE action set provisioning APIs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (20 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 21/62] net/sfc: support flow action PHY PORT in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 23/62] common/sfc_efx/base: add MAE action rule " Andrew Rybchenko
                   ` (41 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The patch adds APIs for action set allocation / release.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  20 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 128 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   2 +
 3 files changed, 150 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 6f63a6ecd0..3053da75f8 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,6 +4191,26 @@ efx_mae_match_specs_class_cmp(
 	__in				const efx_mae_match_spec_t *right,
 	__out				boolean_t *have_same_classp);
 
+#define	EFX_MAE_RSRC_ID_INVALID	UINT32_MAX
+
+/* Action set ID */
+typedef struct efx_mae_aset_id_s {
+	uint32_t id;
+} efx_mae_aset_id_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_alloc(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_actions_t *spec,
+	__out				efx_mae_aset_id_t *aset_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_aset_id_t *aset_idp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 47611c4397..2626710216 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -886,4 +886,132 @@ efx_mae_match_specs_class_cmp(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_alloc(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_actions_t *spec,
+	__out				efx_mae_aset_id_t *aset_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN,
+	    MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
+	efx_mae_aset_id_t aset_id;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN;
+
+	/*
+	 * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the
+	 * corresponding resource types are supported by the implementation.
+	 * Use proper resource ID assignments instead.
+	 */
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
+
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
+	    MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
+	    MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
+	if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail4;
+	}
+
+	aset_idp->id = aset_id.id;
+
+	return (0);
+
+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_action_set_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_aset_id_t *aset_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1),
+	    MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) !=
+	    aset_idp->id) {
+		/* Firmware failed to free the action set. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index d2a5d58ae8..643b3bab52 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,8 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_alloc;
+	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 23/62] common/sfc_efx/base: add MAE action rule provisioning APIs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (21 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 22/62] common/sfc_efx/base: add MAE action set provisioning APIs Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 24/62] net/sfc: implement flow insert/remove in MAE backend Andrew Rybchenko
                   ` (40 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add APIs for action rule insert / remove operations.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  29 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 150 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   2 +
 3 files changed, 181 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 3053da75f8..d37850eda6 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4193,6 +4193,11 @@ efx_mae_match_specs_class_cmp(
 
 #define	EFX_MAE_RSRC_ID_INVALID	UINT32_MAX
 
+/* Rule ID */
+typedef struct efx_mae_rule_id_s {
+	uint32_t id;
+} efx_mae_rule_id_t;
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
@@ -4211,6 +4216,30 @@ efx_mae_action_set_free(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_aset_id_t *aset_idp);
 
+/* Action set list ID */
+typedef struct efx_mae_aset_list_id_s {
+	uint32_t id;
+} efx_mae_aset_list_id_t;
+
+/*
+ * Either action set list ID or action set ID must be passed to this API,
+ * but not both.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_rule_insert(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec,
+	__in				const efx_mae_aset_list_id_t *asl_idp,
+	__in				const efx_mae_aset_id_t *as_idp,
+	__out				efx_mae_rule_id_t *ar_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_rule_remove(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_rule_id_t *ar_idp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 2626710216..1715cdc4fb 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1005,6 +1005,156 @@ efx_mae_action_set_free(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_action_rule_insert(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec,
+	__in				const efx_mae_aset_list_id_t *asl_idp,
+	__in				const efx_mae_aset_id_t *as_idp,
+	__out				efx_mae_rule_id_t *ar_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
+	efx_oword_t *rule_response;
+	efx_mae_rule_id_t ar_id;
+	size_t offset;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(sizeof (ar_idp->id) ==
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN);
+
+	EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (spec->emms_type != EFX_MAE_RULE_ACTION ||
+	    (asl_idp != NULL && as_idp != NULL) ||
+	    (asl_idp == NULL && as_idp == NULL)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN;
+
+	EFX_STATIC_ASSERT(sizeof (*rule_response) <=
+	    MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN);
+	offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST;
+	rule_response = (efx_oword_t *)(payload + offset);
+	EFX_POPULATE_OWORD_3(*rule_response,
+	    MAE_ACTION_RULE_RESPONSE_ASL_ID,
+	    (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID,
+	    MAE_ACTION_RULE_RESPONSE_AS_ID,
+	    (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID,
+	    MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio);
+
+	/*
+	 * Mask-value pairs have been stored in the byte order needed for the
+	 * MCDI request and are thus safe to be copied directly to the buffer.
+	 */
+	EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
+	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+	offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
+	memcpy(payload + offset, spec->emms_mask_value_pairs.action,
+	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
+	if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail5;
+	}
+
+	ar_idp->id = ar_id.id;
+
+	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_action_rule_remove(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_rule_id_t *ar_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1),
+	    MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) !=
+	    ar_idp->id) {
+		/* Firmware failed to delete the action rule. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 643b3bab52..0e0d058c8f 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,8 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_rule_insert;
+	efx_mae_action_rule_remove;
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 24/62] net/sfc: implement flow insert/remove in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (22 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 23/62] common/sfc_efx/base: add MAE action rule " Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 25/62] common/sfc_efx/base: support adding VLAN POP action to a set Andrew Rybchenko
                   ` (39 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Exercise action set allocation / release and action rule
insertion / removal in order to let flow API callers
actually get created flows functioning.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   5 +-
 drivers/net/sfc/sfc_flow.h |   2 +
 drivers/net/sfc/sfc_mae.c  | 108 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  12 +++++
 4 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f4d53bf770..3af95ac8ee 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -50,8 +50,8 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
 	.parse = sfc_flow_parse_rte_to_mae,
 	.verify = sfc_mae_flow_verify,
 	.cleanup = sfc_mae_flow_cleanup,
-	.insert = NULL,
-	.remove = NULL,
+	.insert = sfc_mae_flow_insert,
+	.remove = sfc_mae_flow_remove,
 };
 
 static const struct sfc_flow_ops_by_spec *
@@ -1202,6 +1202,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		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;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 7d15f47e60..d3bdbd5f75 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -67,6 +67,8 @@ struct sfc_flow_spec_mae {
 	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;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 057eef537b..ea15ccaedb 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -113,6 +113,8 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 	action_set->refcnt = 1;
 	action_set->spec = spec;
 
+	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+
 	TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
 
 	*action_setp = action_set;
@@ -134,11 +136,62 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	if (action_set->refcnt != 0)
 		return;
 
+	SFC_ASSERT(action_set->fw_rsrc.aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set->fw_rsrc.refcnt == 0);
+
 	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 }
 
+static int
+sfc_mae_action_set_enable(struct sfc_adapter *sa,
+			  struct sfc_mae_action_set *action_set)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+		SFC_ASSERT(action_set->spec != NULL);
+
+		rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
+					      &fw_rsrc->aset_id);
+		if (rc != 0)
+			return rc;
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static int
+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;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(fw_rsrc->aset_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
+		if (rc != 0)
+			return rc;
+
+		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+	}
+
+	--(fw_rsrc->refcnt);
+
+	return 0;
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -156,6 +209,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	spec_mae = &spec->mae;
 
+	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+
 	if (spec_mae->action_set != NULL)
 		sfc_mae_action_set_del(sa, spec_mae->action_set);
 
@@ -563,3 +618,56 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
+
+int
+sfc_mae_flow_insert(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	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_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set != NULL);
+
+	rc = sfc_mae_action_set_enable(sa, action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
+					NULL, &fw_rsrc->aset_id,
+					&spec_mae->rule_id);
+	if (rc != 0)
+		goto fail_action_rule_insert;
+
+	return 0;
+
+fail_action_rule_insert:
+	(void)sfc_mae_action_set_disable(sa, action_set);
+
+fail_action_set_enable:
+	return rc;
+}
+
+int
+sfc_mae_flow_remove(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	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;
+	int rc;
+
+	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set != NULL);
+
+	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
+	if (rc != 0)
+		return rc;
+
+	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	return sfc_mae_action_set_disable(sa, action_set);
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1ef582e82b..d9f0ee3cbc 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -18,11 +18,21 @@
 extern "C" {
 #endif
 
+/** FW-allocatable resource context */
+struct sfc_mae_fw_rsrc {
+	unsigned int			refcnt;
+	RTE_STD_C11
+	union {
+		efx_mae_aset_id_t	aset_id;
+	};
+};
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
 	efx_mae_actions_t		*spec;
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
@@ -63,6 +73,8 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       struct sfc_mae_action_set **action_setp,
 			       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;
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH 25/62] common/sfc_efx/base: support adding VLAN POP action to a set
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (23 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 24/62] net/sfc: implement flow insert/remove in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 26/62] net/sfc: support flow action OF POP VLAN in MAE backend Andrew Rybchenko
                   ` (38 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE supports stripping two tags, so this action can
be requested once or twice.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  5 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  7 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 54 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index d37850eda6..17bfc6fdfd 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4166,6 +4166,11 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_pop(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 927324c85c..abd7f78cc2 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1700,16 +1700,23 @@ struct efx_mae_match_spec_s {
 };
 
 typedef enum efx_mae_action_e {
+	/* These actions are strictly ordered. */
+	EFX_MAE_ACTION_VLAN_POP,
+
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
 
 	EFX_MAE_NACTIONS
 } efx_mae_action_t;
 
+/* MAE VLAN_POP action can handle 1 or 2 tags. */
+#define	EFX_MAE_VLAN_POP_MAX_NTAGS	(2)
+
 typedef struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			emass_actions;
 
+	unsigned int			emass_n_vlan_tags_to_pop;
 	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_t;
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 1715cdc4fb..0465ddf923 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -641,6 +641,42 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_vlan_pop(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (spec->emass_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) {
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	++spec->emass_n_vlan_tags_to_pop;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -677,15 +713,20 @@ typedef struct efx_mae_action_desc_s {
 } efx_mae_action_desc_t;
 
 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_VLAN_POP] = {
+		.emad_add = efx_mae_action_set_add_vlan_pop
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
 };
 
 static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
-static const uint32_t efx_mae_action_repeat_map = 0;
+static const uint32_t efx_mae_action_repeat_map =
+	(1U << EFX_MAE_ACTION_VLAN_POP);
 
 /*
  * Add an action to an action set.
@@ -759,6 +800,14 @@ efx_mae_action_set_spec_populate(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_pop(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_VLAN_POP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -923,6 +972,9 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
 
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->emass_n_vlan_tags_to_pop);
+
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 0e0d058c8f..41c14c6451 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
+	efx_mae_action_set_populate_vlan_pop;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 26/62] net/sfc: support flow action OF POP VLAN in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (24 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 25/62] common/sfc_efx/base: support adding VLAN POP action to a set Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 27/62] common/sfc_efx/base: support adding VLAN PUSH action Andrew Rybchenko
                   ` (37 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

This action is supported only for rules which have transfer attribute,
and can be requested once or twice per a rule.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst | 2 ++
 drivers/net/sfc/sfc_mae.c   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e367ddd6e6..ed9fc9d845 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -196,6 +196,8 @@ Supported pattern items (***transfer*** rules):
 
 Supported actions (***transfer*** rules):
 
+- OF_POP_VLAN
+
 - PHY_PORT
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index ea15ccaedb..a86a22ad8f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -475,6 +475,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	int rc;
 
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+		rc = efx_mae_action_set_populate_vlan_pop(spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
 		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
 		break;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 27/62] common/sfc_efx/base: support adding VLAN PUSH action
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (25 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 26/62] net/sfc: support flow action OF POP VLAN in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 28/62] net/sfc: add facilities to handle bundles of actions Andrew Rybchenko
                   ` (36 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE supports pushing two tags, so this action can
be requested once or twice.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  7 ++
 drivers/common/sfc_efx/base/efx_impl.h        | 12 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 86 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 17bfc6fdfd..193ffff14c 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4171,6 +4171,13 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				uint16_t tpid_be,
+	__in				uint16_t tci_be);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index abd7f78cc2..cefbcac93e 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1702,6 +1702,7 @@ struct efx_mae_match_spec_s {
 typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
 	EFX_MAE_ACTION_VLAN_POP,
+	EFX_MAE_ACTION_VLAN_PUSH,
 
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
@@ -1712,11 +1713,22 @@ typedef enum efx_mae_action_e {
 /* MAE VLAN_POP action can handle 1 or 2 tags. */
 #define	EFX_MAE_VLAN_POP_MAX_NTAGS	(2)
 
+/* MAE VLAN_PUSH action can handle 1 or 2 tags. */
+#define	EFX_MAE_VLAN_PUSH_MAX_NTAGS	(2)
+
+typedef struct efx_mae_action_vlan_push_s {
+	uint16_t			emavp_tpid_be;
+	uint16_t			emavp_tci_be;
+} efx_mae_action_vlan_push_t;
+
 typedef struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			emass_actions;
 
 	unsigned int			emass_n_vlan_tags_to_pop;
+	unsigned int			emass_n_vlan_tags_to_push;
+	efx_mae_action_vlan_push_t	emass_vlan_push_descs[
+	    EFX_MAE_VLAN_PUSH_MAX_NTAGS];
 	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_t;
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 0465ddf923..b631487645 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -677,6 +677,44 @@ efx_mae_action_set_add_vlan_pop(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	unsigned int n_tags = spec->emass_n_vlan_tags_to_push;
+	efx_rc_t rc;
+
+	if (arg_size != sizeof (*spec->emass_vlan_push_descs)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	memcpy(&spec->emass_vlan_push_descs[n_tags], arg, arg_size);
+	++(spec->emass_n_vlan_tags_to_push);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -716,6 +754,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_VLAN_POP] = {
 		.emad_add = efx_mae_action_set_add_vlan_pop
 	},
+	[EFX_MAE_ACTION_VLAN_PUSH] = {
+		.emad_add = efx_mae_action_set_add_vlan_push
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
@@ -723,10 +764,12 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 
 static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
+	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
 static const uint32_t efx_mae_action_repeat_map =
-	(1U << EFX_MAE_ACTION_VLAN_POP);
+	(1U << EFX_MAE_ACTION_VLAN_POP) |
+	(1U << EFX_MAE_ACTION_VLAN_PUSH);
 
 /*
  * Add an action to an action set.
@@ -808,6 +851,22 @@ efx_mae_action_set_populate_vlan_pop(
 	    EFX_MAE_ACTION_VLAN_POP, 0, NULL));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				uint16_t tpid_be,
+	__in				uint16_t tci_be)
+{
+	efx_mae_action_vlan_push_t action;
+	const uint8_t *arg = (const uint8_t *)&action;
+
+	action.emavp_tpid_be = tpid_be;
+	action.emavp_tci_be = tci_be;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -975,6 +1034,31 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->emass_n_vlan_tags_to_pop);
 
+	if (spec->emass_n_vlan_tags_to_push > 0) {
+		unsigned int outer_tag_idx;
+
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH,
+		    spec->emass_n_vlan_tags_to_push);
+
+		if (spec->emass_n_vlan_tags_to_push ==
+		    EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
+			MCDI_IN_SET_WORD(req,
+			    MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
+			    spec->emass_vlan_push_descs[0].emavp_tpid_be);
+			MCDI_IN_SET_WORD(req,
+			    MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
+			    spec->emass_vlan_push_descs[0].emavp_tci_be);
+		}
+
+		outer_tag_idx = spec->emass_n_vlan_tags_to_push - 1;
+
+		MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
+		    spec->emass_vlan_push_descs[outer_tag_idx].emavp_tpid_be);
+		MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
+		    spec->emass_vlan_push_descs[outer_tag_idx].emavp_tci_be);
+	}
+
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 41c14c6451..be11b6ad3c 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,6 +91,7 @@ INTERNAL {
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_vlan_pop;
+	efx_mae_action_set_populate_vlan_push;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 28/62] net/sfc: add facilities to handle bundles of actions
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (26 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 27/62] common/sfc_efx/base: support adding VLAN PUSH action Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 29/62] net/sfc: support VLAN PUSH actions in MAE backend Andrew Rybchenko
                   ` (35 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

There are MAE actions which do not have uniform counterparts
in terms of RTE flow. However, there are bundles of RTE flow
actions which can be considered as such counterparts.

Implement facilities to handle related RTE flow actions as
parts of a whole. These facilities will be used by a later
patch to add support for VLAN PUSH actions bundle.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   4 --
 drivers/net/sfc/sfc_flow.h |   4 ++
 drivers/net/sfc/sfc_mae.c  | 112 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 3af95ac8ee..6ccefef477 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1679,9 +1679,6 @@ sfc_flow_parse_actions(struct sfc_adapter *sa,
 		return -rte_errno;
 	}
 
-#define SFC_BUILD_SET_OVERFLOW(_action, _set) \
-	RTE_BUILD_BUG_ON(_action >= sizeof(_set) * CHAR_BIT)
-
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
 		switch (actions->type) {
 		case RTE_FLOW_ACTION_TYPE_VOID:
@@ -1777,7 +1774,6 @@ sfc_flow_parse_actions(struct sfc_adapter *sa,
 
 		actions_set |= (1UL << actions->type);
 	}
-#undef SFC_BUILD_SET_OVERFLOW
 
 	/* When fate is unknown, drop traffic. */
 	if ((actions_set & fate_actions_mask) == 0) {
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index d3bdbd5f75..e991ae132c 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -26,6 +26,10 @@ extern "C" {
  */
 #define SF_FLOW_SPEC_NB_FILTERS_MAX 8
 
+/* Used to guard action masks */
+#define SFC_BUILD_SET_OVERFLOW(_action, _set) \
+	RTE_BUILD_BUG_ON((_action) >= sizeof(_set) * CHAR_BIT)
+
 /* RSS configuration storage */
 struct sfc_flow_rss {
 	unsigned int	rxq_hw_index_min;
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index a86a22ad8f..5fbf627f0a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -445,6 +445,99 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	return rc;
 }
 
+/*
+ * An action supported by MAE may correspond to a bundle of RTE flow actions,
+ * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP.
+ * That is, related RTE flow actions need to be tracked as parts of a whole
+ * so that they can be combined into a single action and submitted to MAE
+ * representation of a given rule's action set.
+ *
+ * Each RTE flow action provided by an application gets classified as
+ * one belonging to some bundle type. If an action is not supposed to
+ * belong to any bundle, or if this action is END, it is described as
+ * one belonging to a dummy bundle of type EMPTY.
+ *
+ * A currently tracked bundle will be submitted if a repeating
+ * action or an action of different bundle type follows.
+ */
+
+enum sfc_mae_actions_bundle_type {
+	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
+};
+
+struct sfc_mae_actions_bundle {
+	enum sfc_mae_actions_bundle_type	type;
+
+	/* Indicates actions already tracked by the current bundle */
+	uint64_t				actions_mask;
+};
+
+/*
+ * Combine configuration of RTE flow actions tracked by the bundle into a
+ * single action and submit the result to MAE action set specification.
+ * Do nothing in the case of dummy action bundle.
+ */
+static int
+sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
+			      __rte_unused efx_mae_actions_t *spec)
+{
+	int rc = 0;
+
+	switch (bundle->type) {
+	case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
+		break;
+	default:
+		SFC_ASSERT(B_FALSE);
+		break;
+	}
+
+	return rc;
+}
+
+/*
+ * Given the type of the next RTE flow action in the line, decide
+ * whether a new bundle is about to start, and, if this is the case,
+ * submit and reset the current 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 rte_flow_error *error)
+{
+	enum sfc_mae_actions_bundle_type bundle_type_new;
+	int rc;
+
+	switch (action->type) {
+	default:
+		/*
+		 * Self-sufficient actions, including END, are handled in this
+		 * case. No checks for unsupported actions are needed here
+		 * because parsing doesn't occur at this point.
+		 */
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY;
+		break;
+	}
+
+	if (bundle_type_new != bundle->type ||
+	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
+		rc = sfc_mae_actions_bundle_submit(bundle, spec);
+		if (rc != 0)
+			goto fail_submit;
+
+		memset(bundle, 0, sizeof(*bundle));
+	}
+
+	bundle->type = bundle_type_new;
+
+	return 0;
+
+fail_submit:
+	return rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+			"Failed to request the (group of) action(s)");
+}
+
 static int
 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
 				   const struct rte_flow_action_phy_port *conf,
@@ -469,6 +562,7 @@ sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
+			  struct sfc_mae_actions_bundle *bundle,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
@@ -476,9 +570,13 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
+				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_vlan_pop(spec);
 		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
+				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
 		break;
 	default:
@@ -490,6 +588,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	if (rc != 0) {
 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
 				NULL, "Failed to request the action");
+	} else {
+		bundle->actions_mask |= (1ULL << action->type);
 	}
 
 	return rc;
@@ -501,6 +601,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			   struct sfc_mae_action_set **action_setp,
 			   struct rte_flow_error *error)
 {
+	struct sfc_mae_actions_bundle bundle = {0};
 	const struct rte_flow_action *action;
 	efx_mae_actions_t *spec;
 	int rc;
@@ -517,11 +618,20 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_rule_parse_action(sa, action, spec, error);
+		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
+		if (rc != 0)
+			goto fail_rule_parse_action;
+
+		rc = sfc_mae_rule_parse_action(sa, action, &bundle, spec,
+					       error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 	}
 
+	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
+	if (rc != 0)
+		goto fail_rule_parse_action;
+
 	*action_setp = sfc_mae_action_set_attach(sa, spec);
 	if (*action_setp != NULL) {
 		efx_mae_action_set_spec_fini(sa->nic, spec);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 29/62] net/sfc: support VLAN PUSH actions in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (27 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 28/62] net/sfc: add facilities to handle bundles of actions Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 30/62] common/sfc_efx/base: support adding FLAG action to a set Andrew Rybchenko
                   ` (34 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

A group of actions (OF_PUSH_VLAN, OF_VLAN_SET_VID and
OF_VLAN_SET_PCP) maps to MAE action VLAN_PUSH.

This action group is supported only for rules which have transfer
attribute, and can be requested once or twice per a rule.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  6 ++++
 drivers/net/sfc/sfc_mae.c   | 61 +++++++++++++++++++++++++++++++++++--
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index ed9fc9d845..b0caa4edf9 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -198,6 +198,12 @@ Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
 
+- OF_PUSH_VLAN
+
+- OF_VLAN_SET_VID
+
+- OF_VLAN_SET_PCP
+
 - PHY_PORT
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 5fbf627f0a..98808ac3f0 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -463,6 +463,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 
 enum sfc_mae_actions_bundle_type {
 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
+	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
 };
 
 struct sfc_mae_actions_bundle {
@@ -470,6 +471,10 @@ struct sfc_mae_actions_bundle {
 
 	/* Indicates actions already tracked by the current bundle */
 	uint64_t				actions_mask;
+
+	/* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */
+	rte_be16_t				vlan_push_tpid;
+	rte_be16_t				vlan_push_tci;
 };
 
 /*
@@ -479,13 +484,17 @@ struct sfc_mae_actions_bundle {
  */
 static int
 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
-			      __rte_unused efx_mae_actions_t *spec)
+			      efx_mae_actions_t *spec)
 {
 	int rc = 0;
 
 	switch (bundle->type) {
 	case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
 		break;
+	case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH:
+		rc = efx_mae_action_set_populate_vlan_push(
+			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
+		break;
 	default:
 		SFC_ASSERT(B_FALSE);
 		break;
@@ -509,6 +518,11 @@ sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
 	int rc;
 
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
+		break;
 	default:
 		/*
 		 * Self-sufficient actions, including END, are handled in this
@@ -538,6 +552,34 @@ 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_of_push_vlan(
+			    const struct rte_flow_action_of_push_vlan *conf,
+			    struct sfc_mae_actions_bundle *bundle)
+{
+	bundle->vlan_push_tpid = conf->ethertype;
+}
+
+static void
+sfc_mae_rule_parse_action_of_set_vlan_vid(
+			    const struct rte_flow_action_of_set_vlan_vid *conf,
+			    struct sfc_mae_actions_bundle *bundle)
+{
+	bundle->vlan_push_tci |= (conf->vlan_vid &
+				  rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t)));
+}
+
+static void
+sfc_mae_rule_parse_action_of_set_vlan_pcp(
+			    const struct rte_flow_action_of_set_vlan_pcp *conf,
+			    struct sfc_mae_actions_bundle *bundle)
+{
+	uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp &
+					   RTE_LEN2MASK(3, uint8_t)) << 13;
+
+	bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
+}
+
 static int
 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
 				   const struct rte_flow_action_phy_port *conf,
@@ -566,7 +608,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
-	int rc;
+	int rc = 0;
 
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
@@ -574,6 +616,21 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_vlan_pop(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle);
+		break;
+	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle);
+		break;
+	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
+				       bundle->actions_mask);
+		sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
+		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
 				       bundle->actions_mask);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 30/62] common/sfc_efx/base: support adding FLAG action to a set
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (28 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 29/62] net/sfc: support VLAN PUSH actions in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 31/62] net/sfc: support flow action FLAG in MAE backend Andrew Rybchenko
                   ` (33 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

This action can be added at any point before DELIVER.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  5 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  8 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 62 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 193ffff14c..e03da22c3b 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4178,6 +4178,11 @@ efx_mae_action_set_populate_vlan_push(
 	__in				uint16_t tpid_be,
 	__in				uint16_t tci_be);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_flag(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index cefbcac93e..bffd4c6ce8 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1704,6 +1704,14 @@ typedef enum efx_mae_action_e {
 	EFX_MAE_ACTION_VLAN_POP,
 	EFX_MAE_ACTION_VLAN_PUSH,
 
+	/*
+	 * These actions are not strictly ordered and can
+	 * be passed by a client in any order (before DELIVER).
+	 * However, these enumerants must be kept compactly
+	 * in the end of the enumeration (before DELIVER).
+	 */
+	EFX_MAE_ACTION_FLAG,
+
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index b631487645..93fd02f6d2 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -715,6 +715,37 @@ efx_mae_action_set_add_vlan_push(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_flag(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	_NOTE(ARGUNUSED(spec))
+
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	/* This action does not have any arguments, so do nothing here. */
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -757,6 +788,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_VLAN_PUSH] = {
 		.emad_add = efx_mae_action_set_add_vlan_push
 	},
+	[EFX_MAE_ACTION_FLAG] = {
+		.emad_add = efx_mae_action_set_add_flag
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
@@ -765,8 +799,17 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
+	(1U << EFX_MAE_ACTION_FLAG) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
+/*
+ * These actions must not be added after DELIVER, but
+ * they can have any place among the rest of
+ * strictly ordered actions.
+ */
+static const uint32_t efx_mae_action_nonstrict_map =
+	(1U << EFX_MAE_ACTION_FLAG);
+
 static const uint32_t efx_mae_action_repeat_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH);
@@ -793,6 +836,7 @@ efx_mae_action_set_spec_populate(
 	    (sizeof (efx_mae_action_repeat_map) * 8));
 
 	EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
+	EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_DELIVER);
 
 	if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
 		rc = EINVAL;
@@ -811,9 +855,10 @@ efx_mae_action_set_spec_populate(
 	}
 
 	if ((efx_mae_action_ordered_map & action_mask) != 0) {
+		uint32_t strict_ordered_map =
+		    efx_mae_action_ordered_map & ~efx_mae_action_nonstrict_map;
 		uint32_t later_actions_mask =
-			efx_mae_action_ordered_map &
-			~(action_mask | (action_mask - 1));
+		    strict_ordered_map & ~(action_mask | (action_mask - 1));
 
 		if ((spec->emass_actions & later_actions_mask) != 0) {
 			/* Cannot add an action after later ordered actions. */
@@ -867,6 +912,14 @@ efx_mae_action_set_populate_vlan_push(
 	    EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_flag(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_FLAG, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -1059,6 +1112,11 @@ efx_mae_action_set_alloc(
 		    spec->emass_vlan_push_descs[outer_tag_idx].emavp_tci_be);
 	}
 
+	if ((spec->emass_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
+	}
+
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index be11b6ad3c..f57f4a3a8f 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
+	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_vlan_pop;
 	efx_mae_action_set_populate_vlan_push;
 	efx_mae_action_set_spec_fini;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 31/62] net/sfc: support flow action FLAG in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (29 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 30/62] common/sfc_efx/base: support adding FLAG action to a set Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 32/62] common/sfc_efx/base: support adding MARK action to a set Andrew Rybchenko
                   ` (32 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action FLAG.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst | 2 ++
 drivers/net/sfc/sfc_mae.c   | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index b0caa4edf9..2ddfd0c957 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -204,6 +204,8 @@ Supported actions (***transfer*** rules):
 
 - OF_VLAN_SET_PCP
 
+- FLAG
+
 - PHY_PORT
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 98808ac3f0..af961ceffe 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -631,6 +631,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
 		break;
+	case RTE_FLOW_ACTION_TYPE_FLAG:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
+				       bundle->actions_mask);
+		rc = efx_mae_action_set_populate_flag(spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
 				       bundle->actions_mask);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 32/62] common/sfc_efx/base: support adding MARK action to a set
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (30 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 31/62] net/sfc: support flow action FLAG in MAE backend Andrew Rybchenko
@ 2020-10-20  8:47 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 33/62] net/sfc: support flow action MARK in MAE backend Andrew Rybchenko
                   ` (31 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:47 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

This action can be added at any point before DELIVER.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  6 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  2 +
 drivers/common/sfc_efx/base/efx_mae.c         | 58 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index e03da22c3b..1d2987653b 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4183,6 +4183,12 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_flag(
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_mark(
+	__in				efx_mae_actions_t *spec,
+	__in				uint32_t mark_value);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index bffd4c6ce8..db68cc7b24 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1711,6 +1711,7 @@ typedef enum efx_mae_action_e {
 	 * in the end of the enumeration (before DELIVER).
 	 */
 	EFX_MAE_ACTION_FLAG,
+	EFX_MAE_ACTION_MARK,
 
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
@@ -1737,6 +1738,7 @@ typedef struct efx_mae_actions_s {
 	unsigned int			emass_n_vlan_tags_to_push;
 	efx_mae_action_vlan_push_t	emass_vlan_push_descs[
 	    EFX_MAE_VLAN_PUSH_MAX_NTAGS];
+	uint32_t			emass_mark_value;
 	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_t;
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 93fd02f6d2..880336a7d9 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -746,6 +746,35 @@ efx_mae_action_set_add_flag(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_mark(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	if (arg_size != sizeof (spec->emass_mark_value)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	memcpy(&spec->emass_mark_value, arg, arg_size);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -791,6 +820,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_FLAG] = {
 		.emad_add = efx_mae_action_set_add_flag
 	},
+	[EFX_MAE_ACTION_MARK] = {
+		.emad_add = efx_mae_action_set_add_mark
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
@@ -800,6 +832,7 @@ static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	(1U << EFX_MAE_ACTION_FLAG) |
+	(1U << EFX_MAE_ACTION_MARK) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
 /*
@@ -808,7 +841,8 @@ static const uint32_t efx_mae_action_ordered_map =
  * strictly ordered actions.
  */
 static const uint32_t efx_mae_action_nonstrict_map =
-	(1U << EFX_MAE_ACTION_FLAG);
+	(1U << EFX_MAE_ACTION_FLAG) |
+	(1U << EFX_MAE_ACTION_MARK);
 
 static const uint32_t efx_mae_action_repeat_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
@@ -836,7 +870,8 @@ efx_mae_action_set_spec_populate(
 	    (sizeof (efx_mae_action_repeat_map) * 8));
 
 	EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
-	EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_DELIVER);
+	EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_MARK);
+	EFX_STATIC_ASSERT(EFX_MAE_ACTION_MARK + 1 == EFX_MAE_ACTION_DELIVER);
 
 	if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
 		rc = EINVAL;
@@ -920,6 +955,17 @@ efx_mae_action_set_populate_flag(
 	    EFX_MAE_ACTION_FLAG, 0, NULL));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_mark(
+	__in				efx_mae_actions_t *spec,
+	__in				uint32_t mark_value)
+{
+	const uint8_t *arg = (const uint8_t *)&mark_value;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_MARK, sizeof (mark_value), arg));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -1117,6 +1163,14 @@ efx_mae_action_set_alloc(
 		    MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
 	}
 
+	if ((spec->emass_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) {
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_MARK, 1);
+
+		MCDI_IN_SET_DWORD(req,
+		    MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->emass_mark_value);
+	}
+
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index f57f4a3a8f..6ed412ee39 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,6 +91,7 @@ INTERNAL {
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_populate_flag;
+	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_vlan_pop;
 	efx_mae_action_set_populate_vlan_push;
 	efx_mae_action_set_spec_fini;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 33/62] net/sfc: support flow action MARK in MAE backend
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (31 preceding siblings ...)
  2020-10-20  8:47 ` [dpdk-dev] [PATCH 32/62] common/sfc_efx/base: support adding MARK action to a set Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 34/62] common/sfc_efx/base: add named constant for invalid VF Andrew Rybchenko
                   ` (30 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action MARK.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  2 ++
 drivers/net/sfc/sfc_mae.c   | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 2ddfd0c957..ff0d094068 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -206,6 +206,8 @@ Supported actions (***transfer*** rules):
 
 - FLAG
 
+- MARK
+
 - PHY_PORT
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index af961ceffe..1e7a368303 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -580,6 +580,13 @@ sfc_mae_rule_parse_action_of_set_vlan_pcp(
 	bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
 }
 
+static int
+sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf,
+			       efx_mae_actions_t *spec)
+{
+	return efx_mae_action_set_populate_mark(spec, conf->id);
+}
+
 static int
 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
 				   const struct rte_flow_action_phy_port *conf,
@@ -636,6 +643,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = efx_mae_action_set_populate_flag(spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_MARK:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_mark(action->conf, spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
 				       bundle->actions_mask);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 34/62] common/sfc_efx/base: add named constant for invalid VF
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (32 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 33/62] net/sfc: support flow action MARK in MAE backend Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 35/62] common/sfc_efx/base: add an API to get MPORT of a PF/VF Andrew Rybchenko
                   ` (29 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

This makes existing code clearer. Also, it will be used by a later patch.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 1d2987653b..eefd79dd06 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1603,11 +1603,13 @@ typedef struct efx_nic_cfg_s {
 	uint32_t		enc_assigned_port;
 } efx_nic_cfg_t;
 
+#define	EFX_PCI_VF_INVALID 0xffff
+
 #define	EFX_VPORT_PCI_FUNCTION_IS_PF(configp) \
-	((configp)->evc_function == 0xffff)
+	((configp)->evc_function == EFX_PCI_VF_INVALID)
 
-#define	EFX_PCI_FUNCTION_IS_PF(_encp)	((_encp)->enc_vf == 0xffff)
-#define	EFX_PCI_FUNCTION_IS_VF(_encp)	((_encp)->enc_vf != 0xffff)
+#define	EFX_PCI_FUNCTION_IS_PF(_encp)	((_encp)->enc_vf == EFX_PCI_VF_INVALID)
+#define	EFX_PCI_FUNCTION_IS_VF(_encp)	((_encp)->enc_vf != EFX_PCI_VF_INVALID)
 
 #define	EFX_PCI_FUNCTION(_encp)	\
 	(EFX_PCI_FUNCTION_IS_PF(_encp) ? (_encp)->enc_pf : (_encp)->enc_vf)
@@ -3871,7 +3873,7 @@ typedef enum efx_vport_type_e {
 #define		EFX_VPORT_ID_INVALID	0
 
 typedef struct efx_vport_config_s {
-	/* Either VF index or 0xffff for PF */
+	/* Either VF index or EFX_PCI_VF_INVALID for PF */
 	uint16_t	evc_function;
 	/* VLAN ID of the associated function */
 	uint16_t	evc_vid;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 35/62] common/sfc_efx/base: add an API to get MPORT of a PF/VF
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (33 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 34/62] common/sfc_efx/base: add named constant for invalid VF Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 36/62] net/sfc: support flow items PF and VF in transfer rules Andrew Rybchenko
                   ` (28 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

PCIe functions have static MPORTs which can be utilised by
MAE rules as delivery destinations for matching traffic.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 14 +++++++
 drivers/common/sfc_efx/base/efx_mae.c         | 39 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 3 files changed, 54 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index eefd79dd06..96ea93f75a 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4111,6 +4111,20 @@ efx_mae_mport_by_phy_port(
 	__in				uint32_t phy_port,
 	__out				efx_mport_sel_t *mportp);
 
+/*
+ * Get MPORT selector of a PCIe function.
+ *
+ * The resulting MPORT selector is opaque to the caller and can be
+ * passed as an argument to efx_mae_match_spec_mport_set()
+ * and efx_mae_action_set_populate_deliver().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_mport_by_pcie_function(
+	__in				uint32_t pf,
+	__in				uint32_t vf,
+	__out				efx_mport_sel_t *mportp);
+
 /*
  * Fields which have BE postfix in their named constants are expected
  * to be passed by callers in big-endian byte order. They will appear
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 880336a7d9..ee51f19e5e 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -357,6 +357,45 @@ efx_mae_mport_by_phy_port(
 
 	return (0);
 
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_mport_by_pcie_function(
+	__in				uint32_t pf,
+	__in				uint32_t vf,
+	__out				efx_mport_sel_t *mportp)
+{
+	efx_dword_t dword;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(EFX_PCI_VF_INVALID ==
+	    MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL);
+
+	if (pf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_PF_ID)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (vf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_VF_ID)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	EFX_POPULATE_DWORD_3(dword,
+	    MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_FUNC,
+	    MAE_MPORT_SELECTOR_FUNC_PF_ID, pf,
+	    MAE_MPORT_SELECTOR_FUNC_VF_ID, vf);
+
+	memset(mportp, 0, sizeof (*mportp));
+	mportp->sel = dword.ed_u32[0];
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
 fail1:
 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
 	return (rc);
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 6ed412ee39..cb92955a64 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -106,6 +106,7 @@ INTERNAL {
 	efx_mae_match_spec_is_valid;
 	efx_mae_match_spec_mport_set;
 	efx_mae_match_specs_class_cmp;
+	efx_mae_mport_by_pcie_function;
 	efx_mae_mport_by_phy_port;
 
 	efx_mcdi_fini;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 36/62] net/sfc: support flow items PF and VF in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (34 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 35/62] common/sfc_efx/base: add an API to get MPORT of a PF/VF Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 37/62] net/sfc: support flow actions " Andrew Rybchenko
                   ` (27 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for these flow items to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   4 ++
 drivers/net/sfc/sfc_mae.c   | 126 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |   1 +
 3 files changed, 131 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index ff0d094068..b0f19d51b4 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -192,6 +192,10 @@ Supported pattern items (***transfer*** rules):
 
 - PHY_PORT (cannot repeat; conflicts with other traffic source items)
 
+- PF (cannot repeat; conflicts with other traffic source items)
+
+- VF (cannot repeat; conflicts with other traffic source items)
+
 - ETH
 
 Supported actions (***transfer*** rules):
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 1e7a368303..7d1a3b5999 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -276,6 +276,109 @@ sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 	return 0;
 }
 
+static int
+sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
+			   struct sfc_flow_parse_ctx *ctx,
+			   struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
+					    &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PF ID");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PF");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
+static int
+sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
+			   struct sfc_flow_parse_ctx *ctx,
+			   struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+	const struct rte_flow_item_vf supp_mask = {
+		.id = 0xffffffff,
+	};
+	const void *def_mask = &rte_flow_item_vf_mask;
+	const struct rte_flow_item_vf *spec = NULL;
+	const struct rte_flow_item_vf *mask = NULL;
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(struct rte_flow_item_vf), error);
+	if (rc != 0)
+		return rc;
+
+	if (mask->id != supp_mask.id) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad mask in the VF pattern item");
+	}
+
+	/*
+	 * If "spec" is not set, the item requests any VF related to the
+	 * PF of the current DPDK port (but not the PF itself).
+	 * Reject this match criterion as unsupported.
+	 */
+	if (spec == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad spec in the VF pattern item");
+	}
+
+	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PF + VF IDs");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PF + VF");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
 struct sfc_mae_field_locator {
 	efx_mae_field_id_t		field_id;
 	size_t				size;
@@ -387,6 +490,28 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_phy_port,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_PF,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_pf,
+	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_VF,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_vf,
+	},
 	{
 		.type = RTE_FLOW_ITEM_TYPE_ETH,
 		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
@@ -407,6 +532,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	int rc;
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
+	ctx_mae.sa = sa;
 
 	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
 				     spec->priority,
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d9f0ee3cbc..3c34d08f88 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -57,6 +57,7 @@ struct sfc_adapter;
 struct sfc_flow_spec;
 
 struct sfc_mae_parse_ctx {
+	struct sfc_adapter		*sa;
 	efx_mae_match_spec_t		*match_spec_action;
 	bool				match_mport_set;
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 37/62] net/sfc: support flow actions PF and VF in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (35 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 36/62] net/sfc: support flow items PF and VF in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 38/62] common/sfc_efx/base: add an API for adding action DROP Andrew Rybchenko
                   ` (26 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action DELIVER with MPORT of the PF/VF.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  4 ++++
 drivers/net/sfc/sfc_mae.c   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index b0f19d51b4..2ec95460c5 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -214,6 +214,10 @@ Supported actions (***transfer*** rules):
 
 - PHY_PORT
 
+- PF
+
+- VF
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7d1a3b5999..ff21351152 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -734,6 +734,30 @@ sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
 	return efx_mae_action_set_populate_deliver(spec, &mport);
 }
 
+static int
+sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
+				const struct rte_flow_action_vf *vf_conf,
+				efx_mae_actions_t *spec)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	efx_mport_sel_t mport;
+	uint32_t vf;
+	int rc;
+
+	if (vf_conf == NULL)
+		vf = EFX_PCI_VF_INVALID;
+	else if (vf_conf->original != 0)
+		vf = encp->enc_vf;
+	else
+		vf = vf_conf->id;
+
+	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport);
+	if (rc != 0)
+		return rc;
+
+	return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
@@ -779,6 +803,16 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_PF:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
+		break;
+	case RTE_FLOW_ACTION_TYPE_VF:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
+		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-- 
2.17.1


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

* [dpdk-dev] [PATCH 38/62] common/sfc_efx/base: add an API for adding action DROP
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (36 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 37/62] net/sfc: support flow actions " Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 39/62] net/sfc: support flow action DROP in transfer rules Andrew Rybchenko
                   ` (25 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Client drivers may need to request that matching traffic be dropped.
Add a dedicated API to support this. The API relies on action
DELIVER with properly constructed NULL MPORT argument.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  5 +++++
 drivers/common/sfc_efx/base/efx_mae.c         | 19 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 96ea93f75a..4a4dc8ba4d 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4211,6 +4211,11 @@ efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
 	__in				const efx_mport_sel_t *mportp);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_drop(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index ee51f19e5e..0cfa3f6c06 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1028,6 +1028,25 @@ efx_mae_action_set_populate_deliver(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_drop(
+	__in				efx_mae_actions_t *spec)
+{
+	efx_mport_sel_t mport;
+	const uint8_t *arg;
+	efx_dword_t dword;
+
+	EFX_POPULATE_DWORD_1(dword,
+	    MAE_MPORT_SELECTOR_FLAT, MAE_MPORT_SELECTOR_NULL);
+
+	mport.sel = dword.ed_u32[0];
+
+	arg = (const uint8_t *)&mport.sel;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_DELIVER, sizeof (mport.sel), arg));
+}
+
 	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
 	__in				const efx_mae_actions_t *left,
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index cb92955a64..7cc692db3f 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
+	efx_mae_action_set_populate_drop;
 	efx_mae_action_set_populate_flag;
 	efx_mae_action_set_populate_mark;
 	efx_mae_action_set_populate_vlan_pop;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 39/62] net/sfc: support flow action DROP in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (37 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 38/62] common/sfc_efx/base: add an API for adding action DROP Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 40/62] common/sfc_efx/base: refactor version / boot info get helper Andrew Rybchenko
                   ` (24 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Effectively, the resulting action will be of type DELIVER, and
destination MPORT will be a properly constructed NULL value.
This will achieve the requested behaviour (no delivery).

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst | 2 ++
 drivers/net/sfc/sfc_mae.c   | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 2ec95460c5..ba73391d5f 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -218,6 +218,8 @@ Supported actions (***transfer*** rules):
 
 - VF
 
+- DROP
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index ff21351152..a5800ae722 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -813,6 +813,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_DROP:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
+				       bundle->actions_mask);
+		rc = efx_mae_action_set_populate_drop(spec);
+		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-- 
2.17.1


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

* [dpdk-dev] [PATCH 40/62] common/sfc_efx/base: refactor version / boot info get helper
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (38 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 39/62] net/sfc: support flow action DROP in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 41/62] common/sfc_efx/base: add an API for querying board info Andrew Rybchenko
                   ` (23 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Refactor MCDI helper for version information and boot status
retrieval; it should comprise two dedicated helper functions.

A later patch will extend and reuse version retrieval helper.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/common/sfc_efx/base/efx_mcdi.c | 156 ++++++++++++++++---------
 drivers/common/sfc_efx/base/efx_mcdi.h |  12 ++
 2 files changed, 116 insertions(+), 52 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c
index ede052a26a..edd069c969 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.c
+++ b/drivers/common/sfc_efx/base/efx_mcdi.c
@@ -962,31 +962,32 @@ efx_mcdi_ev_death(
 }
 
 	__checkReturn		efx_rc_t
-efx_mcdi_version(
+efx_mcdi_get_version(
 	__in			efx_nic_t *enp,
-	__out_ecount_opt(4)	uint16_t versionp[4],
-	__out_opt		uint32_t *buildp,
-	__out_opt		efx_mcdi_boot_t *statusp)
+	__out			efx_mcdi_version_t *verp)
 {
-	efx_mcdi_req_t req;
 	EFX_MCDI_DECLARE_BUF(payload,
-		MAX(MC_CMD_GET_VERSION_IN_LEN, MC_CMD_GET_BOOT_STATUS_IN_LEN),
-		MAX(MC_CMD_GET_VERSION_OUT_LEN,
-			MC_CMD_GET_BOOT_STATUS_OUT_LEN));
-	efx_word_t *ver_words;
-	uint16_t version[4];
-	uint32_t build;
-	efx_mcdi_boot_t status;
+	    MC_CMD_GET_VERSION_IN_LEN,
+	    MC_CMD_GET_VERSION_OUT_LEN);
+	size_t min_resp_len_required;
+	efx_mcdi_req_t req;
 	efx_rc_t rc;
 
+	EFX_STATIC_ASSERT(sizeof (verp->emv_version) ==
+	    MC_CMD_GET_VERSION_OUT_VERSION_LEN);
+	EFX_STATIC_ASSERT(sizeof (verp->emv_firmware) ==
+	    MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN);
+
 	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
 
 	req.emr_cmd = MC_CMD_GET_VERSION;
 	req.emr_in_buf = payload;
-	req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN;
 	req.emr_out_buf = payload;
+	req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN;
 	req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN;
 
+	min_resp_len_required = MC_CMD_GET_VERSION_V0_OUT_LEN;
+
 	efx_mcdi_execute(enp, &req);
 
 	if (req.emr_rc != 0) {
@@ -994,34 +995,56 @@ efx_mcdi_version(
 		goto fail1;
 	}
 
-	/* bootrom support */
-	if (req.emr_out_length_used == MC_CMD_GET_VERSION_V0_OUT_LEN) {
-		version[0] = version[1] = version[2] = version[3] = 0;
-		build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
-
-		goto version;
-	}
-
-	if (req.emr_out_length_used < MC_CMD_GET_VERSION_OUT_LEN) {
+	if (req.emr_out_length_used < min_resp_len_required) {
 		rc = EMSGSIZE;
 		goto fail2;
 	}
 
-	ver_words = MCDI_OUT2(req, efx_word_t, GET_VERSION_OUT_VERSION);
-	version[0] = EFX_WORD_FIELD(ver_words[0], EFX_WORD_0);
-	version[1] = EFX_WORD_FIELD(ver_words[1], EFX_WORD_0);
-	version[2] = EFX_WORD_FIELD(ver_words[2], EFX_WORD_0);
-	version[3] = EFX_WORD_FIELD(ver_words[3], EFX_WORD_0);
-	build = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
+	memset(verp, 0, sizeof (*verp));
 
-version:
-	/* The bootrom doesn't understand BOOT_STATUS */
-	if (MC_FW_VERSION_IS_BOOTLOADER(build)) {
-		status = EFX_MCDI_BOOT_ROM;
-		goto out;
+	if (req.emr_out_length_used > min_resp_len_required) {
+		efx_word_t *ver_words;
+
+		if (req.emr_out_length_used < MC_CMD_GET_VERSION_OUT_LEN) {
+			rc = EMSGSIZE;
+			goto fail3;
+		}
+
+		ver_words = MCDI_OUT2(req, efx_word_t, GET_VERSION_OUT_VERSION);
+
+		verp->emv_version[0] = EFX_WORD_FIELD(ver_words[0], EFX_WORD_0);
+		verp->emv_version[1] = EFX_WORD_FIELD(ver_words[1], EFX_WORD_0);
+		verp->emv_version[2] = EFX_WORD_FIELD(ver_words[2], EFX_WORD_0);
+		verp->emv_version[3] = EFX_WORD_FIELD(ver_words[3], EFX_WORD_0);
 	}
 
-	(void) memset(payload, 0, sizeof (payload));
+	verp->emv_firmware = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+static	__checkReturn		efx_rc_t
+efx_mcdi_get_boot_status(
+	__in			efx_nic_t *enp,
+	__out			efx_mcdi_boot_t *statusp)
+{
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_GET_BOOT_STATUS_IN_LEN,
+	    MC_CMD_GET_BOOT_STATUS_OUT_LEN);
+	efx_mcdi_req_t req;
+	efx_rc_t rc;
+
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
 	req.emr_cmd = MC_CMD_GET_BOOT_STATUS;
 	req.emr_in_buf = payload;
 	req.emr_in_length = MC_CMD_GET_BOOT_STATUS_IN_LEN;
@@ -1030,44 +1053,73 @@ efx_mcdi_version(
 
 	efx_mcdi_execute_quiet(enp, &req);
 
-	if (req.emr_rc == EACCES) {
-		/* Unprivileged functions cannot access BOOT_STATUS */
-		status = EFX_MCDI_BOOT_PRIMARY;
-		version[0] = version[1] = version[2] = version[3] = 0;
-		build = 0;
-		goto out;
-	}
-
 	if (req.emr_rc != 0) {
 		rc = req.emr_rc;
-		goto fail3;
+		goto fail1;
 	}
 
 	if (req.emr_out_length_used < MC_CMD_GET_BOOT_STATUS_OUT_LEN) {
 		rc = EMSGSIZE;
-		goto fail4;
+		goto fail2;
 	}
 
 	if (MCDI_OUT_DWORD_FIELD(req, GET_BOOT_STATUS_OUT_FLAGS,
 	    GET_BOOT_STATUS_OUT_FLAGS_PRIMARY))
-		status = EFX_MCDI_BOOT_PRIMARY;
+		*statusp = EFX_MCDI_BOOT_PRIMARY;
 	else
-		status = EFX_MCDI_BOOT_SECONDARY;
+		*statusp = EFX_MCDI_BOOT_SECONDARY;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+	__checkReturn		efx_rc_t
+efx_mcdi_version(
+	__in			efx_nic_t *enp,
+	__out_ecount_opt(4)	uint16_t versionp[4],
+	__out_opt		uint32_t *buildp,
+	__out_opt		efx_mcdi_boot_t *statusp)
+{
+	efx_mcdi_version_t ver;
+	efx_mcdi_boot_t status;
+	efx_rc_t rc;
+
+	rc = efx_mcdi_get_version(enp, &ver);
+	if (rc != 0)
+		goto fail1;
+
+	/* The bootrom doesn't understand BOOT_STATUS */
+	if (MC_FW_VERSION_IS_BOOTLOADER(ver.emv_firmware)) {
+		status = EFX_MCDI_BOOT_ROM;
+		goto out;
+	}
+
+	rc = efx_mcdi_get_boot_status(enp, &status);
+	if (rc == EACCES) {
+		/* Unprivileged functions cannot access BOOT_STATUS */
+		status = EFX_MCDI_BOOT_PRIMARY;
+		memset(ver.emv_version, 0, sizeof (ver.emv_version));
+		ver.emv_firmware = 0;
+	} else if (rc != 0) {
+		goto fail2;
+	}
 
 out:
 	if (versionp != NULL)
-		memcpy(versionp, version, sizeof (version));
+		memcpy(versionp, ver.emv_version, sizeof (ver.emv_version));
 	if (buildp != NULL)
-		*buildp = build;
+		*buildp = ver.emv_firmware;
 	if (statusp != NULL)
 		*statusp = status;
 
 	return (0);
 
-fail4:
-	EFSYS_PROBE(fail4);
-fail3:
-	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 9dd0a23862..8b50b8a949 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -118,6 +118,18 @@ efx_mcdi_raise_exception(
 	__in_opt	efx_mcdi_req_t *emrp,
 	__in		int rc);
 
+typedef struct efx_mcdi_version_s {
+	/* Basic version information */
+	uint16_t		emv_version[4];
+	uint32_t		emv_firmware;
+} efx_mcdi_version_t;
+
+LIBEFX_INTERNAL
+extern	__checkReturn	efx_rc_t
+efx_mcdi_get_version(
+	__in		efx_nic_t *enp,
+	__out		efx_mcdi_version_t *verp);
+
 typedef enum efx_mcdi_boot_e {
 	EFX_MCDI_BOOT_PRIMARY,
 	EFX_MCDI_BOOT_SECONDARY,
-- 
2.17.1


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

* [dpdk-dev] [PATCH 41/62] common/sfc_efx/base: add an API for querying board info
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (39 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 40/62] common/sfc_efx/base: refactor version / boot info get helper Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 42/62] net/sfc: add HW switch ID helpers Andrew Rybchenko
                   ` (22 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Riverhead boards can provide extended version information.
Implement facilities necessary to obtain it.
Add an API for querying board information.

A client driver may use this to discover which of its instances
relate to which physical boards, based on board serial number
persistence for a given physical board.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/common/sfc_efx/base/efx.h             | 16 +++++++
 drivers/common/sfc_efx/base/efx_mcdi.c        | 48 ++++++++++++++++---
 drivers/common/sfc_efx/base/efx_mcdi.h        | 18 +++++++
 drivers/common/sfc_efx/base/efx_nic.c         | 46 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 5 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 4a4dc8ba4d..75edb59a49 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1647,6 +1647,22 @@ efx_nic_get_fw_version(
 	__in			efx_nic_t *enp,
 	__out			efx_nic_fw_info_t *enfip);
 
+#define	EFX_NIC_BOARD_INFO_SERIAL_LEN	(64)
+#define	EFX_NIC_BOARD_INFO_NAME_LEN	(16)
+
+typedef struct efx_nic_board_info_s {
+	/* The following two fields are NUL-terminated ASCII strings. */
+	char			enbi_serial[EFX_NIC_BOARD_INFO_SERIAL_LEN];
+	char			enbi_name[EFX_NIC_BOARD_INFO_NAME_LEN];
+	uint32_t		enbi_revision;
+} efx_nic_board_info_t;
+
+LIBEFX_API
+extern	__checkReturn	efx_rc_t
+efx_nic_get_board_info(
+	__in		efx_nic_t *enp,
+	__out		efx_nic_board_info_t *board_infop);
+
 /* Driver resource limits (minimum required/maximum usable). */
 typedef struct efx_drv_limits_s {
 	uint32_t	edl_min_evq_count;
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c
index edd069c969..8c984d8cad 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.c
+++ b/drivers/common/sfc_efx/base/efx_mcdi.c
@@ -964,11 +964,13 @@ efx_mcdi_ev_death(
 	__checkReturn		efx_rc_t
 efx_mcdi_get_version(
 	__in			efx_nic_t *enp,
+	__in			uint32_t flags_req,
 	__out			efx_mcdi_version_t *verp)
 {
+	efx_nic_board_info_t *board_infop = &verp->emv_board_info;
 	EFX_MCDI_DECLARE_BUF(payload,
-	    MC_CMD_GET_VERSION_IN_LEN,
-	    MC_CMD_GET_VERSION_OUT_LEN);
+	    MC_CMD_GET_VERSION_EXT_IN_LEN,
+	    MC_CMD_GET_VERSION_V2_OUT_LEN);
 	size_t min_resp_len_required;
 	efx_mcdi_req_t req;
 	efx_rc_t rc;
@@ -978,15 +980,35 @@ efx_mcdi_get_version(
 	EFX_STATIC_ASSERT(sizeof (verp->emv_firmware) ==
 	    MC_CMD_GET_VERSION_OUT_FIRMWARE_LEN);
 
+	EFX_STATIC_ASSERT(EFX_MCDI_VERSION_BOARD_INFO ==
+	    (1U << MC_CMD_GET_VERSION_V2_OUT_BOARD_EXT_INFO_PRESENT_LBN));
+
+	EFX_STATIC_ASSERT(sizeof (board_infop->enbi_serial) ==
+	    MC_CMD_GET_VERSION_V2_OUT_BOARD_SERIAL_LEN);
+	EFX_STATIC_ASSERT(sizeof (board_infop->enbi_name) ==
+	    MC_CMD_GET_VERSION_V2_OUT_BOARD_NAME_LEN);
+	EFX_STATIC_ASSERT(sizeof (board_infop->enbi_revision) ==
+	    MC_CMD_GET_VERSION_V2_OUT_BOARD_REVISION_LEN);
+
 	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
 
 	req.emr_cmd = MC_CMD_GET_VERSION;
 	req.emr_in_buf = payload;
 	req.emr_out_buf = payload;
-	req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN;
-	req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN;
 
-	min_resp_len_required = MC_CMD_GET_VERSION_V0_OUT_LEN;
+	if (flags_req != 0) {
+		/* Request basic + extended version information. */
+		req.emr_in_length = MC_CMD_GET_VERSION_EXT_IN_LEN;
+		req.emr_out_length = MC_CMD_GET_VERSION_V2_OUT_LEN;
+
+		min_resp_len_required = MC_CMD_GET_VERSION_V2_OUT_LEN;
+	} else {
+		/* Request only basic version information. */
+		req.emr_in_length = MC_CMD_GET_VERSION_IN_LEN;
+		req.emr_out_length = MC_CMD_GET_VERSION_OUT_LEN;
+
+		min_resp_len_required = MC_CMD_GET_VERSION_V0_OUT_LEN;
+	}
 
 	efx_mcdi_execute(enp, &req);
 
@@ -1020,6 +1042,20 @@ efx_mcdi_get_version(
 
 	verp->emv_firmware = MCDI_OUT_DWORD(req, GET_VERSION_OUT_FIRMWARE);
 
+	verp->emv_flags = MCDI_OUT_DWORD(req, GET_VERSION_V2_OUT_FLAGS);
+	verp->emv_flags &= flags_req;
+
+	if ((verp->emv_flags & EFX_MCDI_VERSION_BOARD_INFO) != 0) {
+		memcpy(board_infop->enbi_serial,
+		    MCDI_OUT2(req, char, GET_VERSION_V2_OUT_BOARD_SERIAL),
+		    sizeof (board_infop->enbi_serial));
+		memcpy(board_infop->enbi_name,
+		    MCDI_OUT2(req, char, GET_VERSION_V2_OUT_BOARD_NAME),
+		    sizeof (board_infop->enbi_name));
+		board_infop->enbi_revision =
+		    MCDI_OUT_DWORD(req, GET_VERSION_V2_OUT_BOARD_REVISION);
+	}
+
 	return (0);
 
 fail3:
@@ -1090,7 +1126,7 @@ efx_mcdi_version(
 	efx_mcdi_boot_t status;
 	efx_rc_t rc;
 
-	rc = efx_mcdi_get_version(enp, &ver);
+	rc = efx_mcdi_get_version(enp, 0, &ver);
 	if (rc != 0)
 		goto fail1;
 
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 8b50b8a949..0b39a6f7f6 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -118,16 +118,34 @@ efx_mcdi_raise_exception(
 	__in_opt	efx_mcdi_req_t *emrp,
 	__in		int rc);
 
+/*
+ * Flags that name portions of extended version information
+ *
+ * The values match their MCDI counterparts.
+ */
+#define	EFX_MCDI_VERSION_BOARD_INFO	(1U << 4)
+
 typedef struct efx_mcdi_version_s {
 	/* Basic version information */
 	uint16_t		emv_version[4];
 	uint32_t		emv_firmware;
+
+	/*
+	 * Extended version information
+	 *
+	 * Valid portions of obtained information are indicated by flags.
+	 */
+	uint32_t		emv_flags;
+
+	/* Information valid if emv_flags has EFX_MCDI_VERSION_BOARD_INFO set */
+	efx_nic_board_info_t	emv_board_info;
 } efx_mcdi_version_t;
 
 LIBEFX_INTERNAL
 extern	__checkReturn	efx_rc_t
 efx_mcdi_get_version(
 	__in		efx_nic_t *enp,
+	__in		uint32_t flags_req,
 	__out		efx_mcdi_version_t *verp);
 
 typedef enum efx_mcdi_boot_e {
diff --git a/drivers/common/sfc_efx/base/efx_nic.c b/drivers/common/sfc_efx/base/efx_nic.c
index a78c4c3737..7c28fb1744 100644
--- a/drivers/common/sfc_efx/base/efx_nic.c
+++ b/drivers/common/sfc_efx/base/efx_nic.c
@@ -791,6 +791,52 @@ efx_nic_get_fw_version(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+	__checkReturn	efx_rc_t
+efx_nic_get_board_info(
+	__in		efx_nic_t *enp,
+	__out		efx_nic_board_info_t *board_infop)
+{
+	efx_mcdi_version_t ver;
+	efx_rc_t rc;
+
+	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
+	EFSYS_ASSERT3U(enp->en_features, &, EFX_FEATURE_MCDI);
+
+	rc = efx_mcdi_get_version(enp, EFX_MCDI_VERSION_BOARD_INFO, &ver);
+	if (rc == EMSGSIZE) {
+		/*
+		 * Typically, EMSGSIZE is returned by above call in the
+		 * case when the NIC does not provide extra information.
+		 */
+		rc = ENOTSUP;
+		goto fail1;
+	} else if (rc != 0) {
+		goto fail2;
+	}
+
+	if ((ver.emv_flags & EFX_MCDI_VERSION_BOARD_INFO) == 0) {
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	memcpy(board_infop, &ver.emv_board_info, sizeof (*board_infop));
+
+	/* MCDI should provide NUL-terminated strings, but stay vigilant. */
+	board_infop->enbi_serial[sizeof (board_infop->enbi_serial) - 1] = '\0';
+	board_infop->enbi_name[sizeof (board_infop->enbi_name) - 1] = '\0';
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 7cc692db3f..37056abd60 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -131,6 +131,7 @@ INTERNAL {
 	efx_nic_destroy;
 	efx_nic_fini;
 	efx_nic_get_bar_region;
+	efx_nic_get_board_info;
 	efx_nic_get_fw_subvariant;
 	efx_nic_get_fw_version;
 	efx_nic_get_vi_pool;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 42/62] net/sfc: add HW switch ID helpers
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (40 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 41/62] common/sfc_efx/base: add an API for querying board info Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 43/62] net/sfc: support the concept of RTE switch domains/ports Andrew Rybchenko
                   ` (21 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The driver will need a means to figure out relationship between
RTE ethdev instances and underlying HW switch entities. For now,
use board serial number string as a unique HW switch identifier.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc.c | 44 +++++++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc.h |  8 ++++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 3b896490f7..a4fe495788 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -1259,3 +1259,47 @@ sfc_register_logtype(const struct rte_pci_addr *pci_addr,
 
 	return ret;
 }
+
+struct sfc_hw_switch_id {
+	char	board_sn[RTE_SIZEOF_FIELD(efx_nic_board_info_t, enbi_serial)];
+};
+
+int
+sfc_hw_switch_id_init(struct sfc_adapter *sa,
+		      struct sfc_hw_switch_id **idp)
+{
+	efx_nic_board_info_t board_info;
+	struct sfc_hw_switch_id *id;
+	int rc;
+
+	if (idp == NULL)
+		return EINVAL;
+
+	id = rte_zmalloc("sfc_hw_switch_id", sizeof(*id), 0);
+	if (id == NULL)
+		return ENOMEM;
+
+	rc = efx_nic_get_board_info(sa->nic, &board_info);
+	if (rc != 0)
+		return rc;
+
+	memcpy(id->board_sn, board_info.enbi_serial, sizeof(id->board_sn));
+
+	*idp = id;
+
+	return 0;
+}
+
+void
+sfc_hw_switch_id_fini(__rte_unused struct sfc_adapter *sa,
+		      struct sfc_hw_switch_id *id)
+{
+	rte_free(id);
+}
+
+bool
+sfc_hw_switch_ids_equal(const struct sfc_hw_switch_id *left,
+			const struct sfc_hw_switch_id *right)
+{
+	return strcmp(left->board_sn, right->board_sn) == 0;
+}
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 4b5d687108..ed059e142f 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -403,6 +403,14 @@ int sfc_port_reset_mac_stats(struct sfc_adapter *sa);
 int sfc_set_rx_mode(struct sfc_adapter *sa);
 int sfc_set_rx_mode_unchecked(struct sfc_adapter *sa);
 
+struct sfc_hw_switch_id;
+
+int sfc_hw_switch_id_init(struct sfc_adapter *sa,
+			  struct sfc_hw_switch_id **idp);
+void sfc_hw_switch_id_fini(struct sfc_adapter *sa,
+			   struct sfc_hw_switch_id *idp);
+bool sfc_hw_switch_ids_equal(const struct sfc_hw_switch_id *left,
+			     const struct sfc_hw_switch_id *right);
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH 43/62] net/sfc: support the concept of RTE switch domains/ports
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (41 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 42/62] net/sfc: add HW switch ID helpers Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 44/62] net/sfc: support flow action PORT ID in transfer rules Andrew Rybchenko
                   ` (20 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

A later patch will add support for RTE flow action PORT_ID
to MAE backend. The driver has to ensure that such actions
refer to RTE ethdev instances deployed on top of the same
physical device. Also, the driver needs a means to find
sibling RTE ethdev instances when parsing such actions.

In order to solve these problems, add a switch infrastructure
which allocates switch domains based on persistence of device
serial number string across switch ports included in a domain.
Explain mapping between RTE switch port IDs and MAE endpoints.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build  |   1 +
 drivers/net/sfc/sfc_ethdev.c |   7 +
 drivers/net/sfc/sfc_mae.c    |  35 +++++
 drivers/net/sfc/sfc_mae.h    |   6 +
 drivers/net/sfc/sfc_switch.c | 276 +++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_switch.h |  47 ++++++
 6 files changed, 372 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_switch.c
 create mode 100644 drivers/net/sfc/sfc_switch.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 7a893080cb..42b184c29e 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -47,6 +47,7 @@ sources = files(
 	'sfc_tx.c',
 	'sfc_tso.c',
 	'sfc_filter.c',
+	'sfc_switch.c',
 	'sfc_mae.c',
 	'sfc_flow.c',
 	'sfc_dp.c',
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index c0672083ec..107dd0f470 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -93,6 +93,7 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct sfc_rss *rss = &sas->rss;
+	struct sfc_mae *mae = &sa->mae;
 	uint64_t txq_offloads_def = 0;
 
 	sfc_log_init(sa, "entry");
@@ -187,6 +188,12 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
 			     RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
 
+	if (mae->status == SFC_MAE_STATUS_SUPPORTED) {
+		dev_info->switch_info.name = dev->device->driver->name;
+		dev_info->switch_info.domain_id = mae->switch_domain_id;
+		dev_info->switch_info.port_id = mae->switch_port_id;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index a5800ae722..64cd6b0e9b 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -15,11 +15,24 @@
 
 #include "sfc.h"
 #include "sfc_log.h"
+#include "sfc_switch.h"
+
+static int
+sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
+			    efx_mport_sel_t *mportp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+
+	return efx_mae_mport_by_pcie_function(encp->enc_pf, encp->enc_vf,
+					      mportp);
+}
 
 int
 sfc_mae_attach(struct sfc_adapter *sa)
 {
+	struct sfc_mae_switch_port_request switch_port_request = {0};
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	efx_mport_sel_t entity_mport;
 	struct sfc_mae *mae = &sa->mae;
 	efx_mae_limits_t limits;
 	int rc;
@@ -41,6 +54,25 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_get_limits;
 
+	sfc_log_init(sa, "assign entity MPORT");
+	rc = sfc_mae_assign_entity_mport(sa, &entity_mport);
+	if (rc != 0)
+		goto fail_mae_assign_entity_mport;
+
+	sfc_log_init(sa, "assign RTE switch domain");
+	rc = sfc_mae_assign_switch_domain(sa, &mae->switch_domain_id);
+	if (rc != 0)
+		goto fail_mae_assign_switch_domain;
+
+	sfc_log_init(sa, "assign RTE switch port");
+	switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
+	switch_port_request.entity_mportp = &entity_mport;
+	rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
+					&switch_port_request,
+					&mae->switch_port_id);
+	if (rc != 0)
+		goto fail_mae_assign_switch_port;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
 	TAILQ_INIT(&mae->action_sets);
@@ -49,6 +81,9 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 	return 0;
 
+fail_mae_assign_switch_port:
+fail_mae_assign_switch_domain:
+fail_mae_assign_entity_mport:
 fail_mae_get_limits:
 	efx_mae_fini(sa->nic);
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 3c34d08f88..f92e62dcbe 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -12,6 +12,8 @@
 
 #include <stdbool.h>
 
+#include <rte_spinlock.h>
+
 #include "efx.h"
 
 #ifdef __cplusplus
@@ -45,6 +47,10 @@ enum sfc_mae_status {
 };
 
 struct sfc_mae {
+	/** Assigned switch domain identifier */
+	uint16_t			switch_domain_id;
+	/** Assigned switch port identifier */
+	uint16_t			switch_port_id;
 	/** NIC support for MAE status */
 	enum sfc_mae_status		status;
 	/** Priority level limit for MAE action rules */
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
new file mode 100644
index 0000000000..395fc40263
--- /dev/null
+++ b/drivers/net/sfc/sfc_switch.c
@@ -0,0 +1,276 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#include <stdbool.h>
+
+#include <rte_common.h>
+#include <rte_spinlock.h>
+
+#include "efx.h"
+
+#include "sfc.h"
+#include "sfc_log.h"
+#include "sfc_switch.h"
+
+/**
+ * Switch port registry entry.
+ *
+ * Drivers aware of RTE switch domains also have to maintain RTE switch
+ * port IDs for RTE ethdev instances they operate. These IDs are supposed
+ * to stand for physical interconnect entities, in example, PCIe functions.
+ *
+ * In terms of MAE, a physical interconnect entity can be referred to using
+ * an MPORT selector, that is, a 32-bit value. RTE switch port IDs, in turn,
+ * are 16-bit values, so indirect mapping has to be maintained:
+ *
+ * +--------------------+          +---------------------------------------+
+ * | RTE switch port ID |  ------  |         MAE switch port entry         |
+ * +--------------------+          |         ---------------------         |
+ *                                 |                                       |
+ *                                 | Entity (PCIe function) MPORT selector |
+ *                                 |                   +                   |
+ *                                 |  Port type (independent/representor)  |
+ *                                 +---------------------------------------+
+ *
+ * This mapping comprises a port type to ensure that RTE switch port ID
+ * of a represented entity and that of its representor are different in
+ * the case when the entity gets plugged into DPDK and not into a guest.
+ */
+struct sfc_mae_switch_port {
+	TAILQ_ENTRY(sfc_mae_switch_port)	switch_domain_ports;
+
+	/** Entity (PCIe function) MPORT selector */
+	efx_mport_sel_t				entity_mport;
+	/** Port type (independent/representor) */
+	enum sfc_mae_switch_port_type		type;
+	/** RTE switch port ID */
+	uint16_t				id;
+};
+
+TAILQ_HEAD(sfc_mae_switch_ports, sfc_mae_switch_port);
+
+/**
+ * Switch domain registry entry.
+ *
+ * Even if an RTE ethdev instance gets unplugged, the corresponding
+ * entry in the switch port registry will not be removed because the
+ * entity (PCIe function) MPORT is static and cannot change. If this
+ * RTE ethdev gets plugged back, the entry will be reused, and
+ * RTE switch port ID will be the same.
+ */
+struct sfc_mae_switch_domain {
+	TAILQ_ENTRY(sfc_mae_switch_domain)	entries;
+
+	/** HW switch ID */
+	struct sfc_hw_switch_id			*hw_switch_id;
+	/** The number of ports in the switch port registry */
+	unsigned int				nb_ports;
+	/** Switch port registry */
+	struct sfc_mae_switch_ports		ports;
+	/** RTE switch domain ID allocated for a group of devices */
+	uint16_t				id;
+};
+
+TAILQ_HEAD(sfc_mae_switch_domains, sfc_mae_switch_domain);
+
+/**
+ * MAE representation of RTE switch infrastructure.
+ *
+ * It is possible that an RTE flow API client tries to insert a rule
+ * referencing an RTE ethdev deployed on top of a different physical
+ * device (it may belong to the same vendor or not). This particular
+ * driver/engine cannot support this and has to turn down such rules.
+ *
+ * Technically, it's HW switch identifier which, if queried for each
+ * RTE ethdev instance, indicates relationship between the instances.
+ * In the meantime, RTE flow API clients also need to somehow figure
+ * out relationship between RTE ethdev instances in advance.
+ *
+ * The concept of RTE switch domains resolves this issue. The driver
+ * maintains a static list of switch domains which is easy to browse,
+ * and each RTE ethdev fills RTE switch parameters in device
+ * information structure which is made available to clients.
+ *
+ * Even if all RTE ethdev instances belonging to a switch domain get
+ * unplugged, the corresponding entry in the switch domain registry
+ * will not be removed because the corresponding HW switch exists
+ * regardless of its ports being plugged to DPDK or kept aside.
+ * If a port gets plugged back to DPDK, the corresponding
+ * RTE ethdev will indicate the same RTE switch domain ID.
+ */
+struct sfc_mae_switch {
+	/** A lock to protect the whole structure */
+	rte_spinlock_t			lock;
+	/** Switch domain registry */
+	struct sfc_mae_switch_domains	domains;
+};
+
+static struct sfc_mae_switch sfc_mae_switch = {
+	.lock = RTE_SPINLOCK_INITIALIZER,
+	.domains = TAILQ_HEAD_INITIALIZER(sfc_mae_switch.domains),
+};
+
+
+/* This function expects to be called only when the lock is held */
+static struct sfc_mae_switch_domain *
+sfc_mae_find_switch_domain_by_id(uint16_t switch_domain_id)
+{
+	struct sfc_mae_switch_domain *domain;
+
+	SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+	TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) {
+		if (domain->id == switch_domain_id)
+			return domain;
+	}
+
+	return NULL;
+}
+
+/* This function expects to be called only when the lock is held */
+static struct sfc_mae_switch_domain *
+sfc_mae_find_switch_domain_by_hw_switch_id(const struct sfc_hw_switch_id *id)
+{
+	struct sfc_mae_switch_domain *domain;
+
+	SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+	TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) {
+		if (sfc_hw_switch_ids_equal(domain->hw_switch_id, id))
+			return domain;
+	}
+
+	return NULL;
+}
+
+int
+sfc_mae_assign_switch_domain(struct sfc_adapter *sa,
+			     uint16_t *switch_domain_id)
+{
+	struct sfc_hw_switch_id *hw_switch_id;
+	struct sfc_mae_switch_domain *domain;
+	int rc;
+
+	rte_spinlock_lock(&sfc_mae_switch.lock);
+
+	rc = sfc_hw_switch_id_init(sa, &hw_switch_id);
+	if (rc != 0)
+		goto fail_hw_switch_id_init;
+
+	domain = sfc_mae_find_switch_domain_by_hw_switch_id(hw_switch_id);
+	if (domain != NULL) {
+		sfc_hw_switch_id_fini(sa, hw_switch_id);
+		goto done;
+	}
+
+	domain = rte_zmalloc("sfc_mae_switch_domain", sizeof(*domain), 0);
+	if (domain == NULL) {
+		rc = ENOMEM;
+		goto fail_mem_alloc;
+	}
+
+	/*
+	 * This code belongs to driver init path, that is, negation is
+	 * done at the end of the path by sfc_eth_dev_init(). RTE APIs
+	 * negate error codes, so drop negation here.
+	 */
+	rc = -rte_eth_switch_domain_alloc(&domain->id);
+	if (rc != 0)
+		goto fail_domain_alloc;
+
+	domain->hw_switch_id = hw_switch_id;
+
+	TAILQ_INIT(&domain->ports);
+
+	TAILQ_INSERT_TAIL(&sfc_mae_switch.domains, domain, entries);
+
+done:
+	*switch_domain_id = domain->id;
+
+	rte_spinlock_unlock(&sfc_mae_switch.lock);
+
+	return 0;
+
+fail_domain_alloc:
+	rte_free(domain);
+
+fail_mem_alloc:
+	sfc_hw_switch_id_fini(sa, hw_switch_id);
+	rte_spinlock_unlock(&sfc_mae_switch.lock);
+
+fail_hw_switch_id_init:
+	return rc;
+}
+
+/* This function expects to be called only when the lock is held */
+static struct sfc_mae_switch_port *
+sfc_mae_find_switch_port_by_entity(const struct sfc_mae_switch_domain *domain,
+				   const efx_mport_sel_t *entity_mportp,
+				   enum sfc_mae_switch_port_type type)
+{
+	struct sfc_mae_switch_port *port;
+
+	SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+	TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
+		if (port->entity_mport.sel == entity_mportp->sel &&
+		    port->type == type)
+			return port;
+	}
+
+	return NULL;
+}
+
+int
+sfc_mae_assign_switch_port(uint16_t switch_domain_id,
+			   const struct sfc_mae_switch_port_request *req,
+			   uint16_t *switch_port_id)
+{
+	struct sfc_mae_switch_domain *domain;
+	struct sfc_mae_switch_port *port;
+	int rc;
+
+	rte_spinlock_lock(&sfc_mae_switch.lock);
+
+	domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
+	if (domain == NULL) {
+		rc = EINVAL;
+		goto fail_find_switch_domain_by_id;
+	}
+
+	port = sfc_mae_find_switch_port_by_entity(domain, req->entity_mportp,
+						  req->type);
+	if (port != NULL)
+		goto done;
+
+	port = rte_zmalloc("sfc_mae_switch_port", sizeof(*port), 0);
+	if (port == NULL) {
+		rc = ENOMEM;
+		goto fail_mem_alloc;
+	}
+
+	port->entity_mport.sel = req->entity_mportp->sel;
+	port->type = req->type;
+
+	port->id = (domain->nb_ports++);
+
+	TAILQ_INSERT_TAIL(&domain->ports, port, switch_domain_ports);
+
+done:
+	*switch_port_id = port->id;
+
+	rte_spinlock_unlock(&sfc_mae_switch.lock);
+
+	return 0;
+
+fail_mem_alloc:
+fail_find_switch_domain_by_id:
+	rte_spinlock_unlock(&sfc_mae_switch.lock);
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
new file mode 100644
index 0000000000..9845ac8801
--- /dev/null
+++ b/drivers/net/sfc/sfc_switch.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#ifndef _SFC_SWITCH_H
+#define _SFC_SWITCH_H
+
+#include <stdint.h>
+
+#include "efx.h"
+
+#include "sfc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Options for MAE switch port type */
+enum sfc_mae_switch_port_type {
+	/**
+	 * The switch port is operated by a self-sufficient RTE ethdev
+	 * and thus refers to its underlying PCIe function
+	 */
+	SFC_MAE_SWITCH_PORT_INDEPENDENT = 0,
+};
+
+struct sfc_mae_switch_port_request {
+	enum sfc_mae_switch_port_type		type;
+	const efx_mport_sel_t			*entity_mportp;
+};
+
+int sfc_mae_assign_switch_domain(struct sfc_adapter *sa,
+				 uint16_t *switch_domain_id);
+
+int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
+			       const struct sfc_mae_switch_port_request *req,
+			       uint16_t *switch_port_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_SWITCH_H */
-- 
2.17.1


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

* [dpdk-dev] [PATCH 44/62] net/sfc: support flow action PORT ID in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (42 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 43/62] net/sfc: support the concept of RTE switch domains/ports Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 45/62] net/sfc: support flow item " Andrew Rybchenko
                   ` (19 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action DELIVER with MPORT
of the PCIe function associated with a given DPDK port ID.
The DPDK port must not relate to a different physical device.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst  |  2 ++
 drivers/net/sfc/sfc_mae.c    | 33 ++++++++++++++++++++
 drivers/net/sfc/sfc_switch.c | 58 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_switch.h |  6 ++++
 4 files changed, 99 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index ba73391d5f..7b8c1c8527 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -218,6 +218,8 @@ Supported actions (***transfer*** rules):
 
 - VF
 
+- PORT_ID
+
 - DROP
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 64cd6b0e9b..f309efa2cf 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -30,6 +30,7 @@ sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
 int
 sfc_mae_attach(struct sfc_adapter *sa)
 {
+	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 	struct sfc_mae_switch_port_request switch_port_request = {0};
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	efx_mport_sel_t entity_mport;
@@ -67,6 +68,12 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "assign RTE switch port");
 	switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
 	switch_port_request.entity_mportp = &entity_mport;
+	/*
+	 * As of now, the driver does not support representors, so
+	 * RTE ethdev MPORT simply matches that of the entity.
+	 */
+	switch_port_request.ethdev_mportp = &entity_mport;
+	switch_port_request.ethdev_port_id = sas->port_id;
 	rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
 					&switch_port_request,
 					&mae->switch_port_id);
@@ -793,6 +800,27 @@ sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
 	return efx_mae_action_set_populate_deliver(spec, &mport);
 }
 
+static int
+sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
+				  const struct rte_flow_action_port_id *conf,
+				  efx_mae_actions_t *spec)
+{
+	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+	struct sfc_mae *mae = &sa->mae;
+	efx_mport_sel_t mport;
+	uint16_t port_id;
+	int rc;
+
+	port_id = (conf->original != 0) ? sas->port_id : conf->id;
+
+	rc = sfc_mae_switch_port_by_ethdev(mae->switch_domain_id,
+					   port_id, &mport);
+	if (rc != 0)
+		return rc;
+
+	return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
 static int
 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 			  const struct rte_flow_action *action,
@@ -848,6 +876,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 				       bundle->actions_mask);
 		rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
 		break;
+	case RTE_FLOW_ACTION_TYPE_PORT_ID:
+		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID,
+				       bundle->actions_mask);
+		rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_DROP:
 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
 				       bundle->actions_mask);
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 395fc40263..bdea2a2446 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -41,10 +41,22 @@
  * This mapping comprises a port type to ensure that RTE switch port ID
  * of a represented entity and that of its representor are different in
  * the case when the entity gets plugged into DPDK and not into a guest.
+ *
+ * Entry data also comprises RTE ethdev's own MPORT. This value
+ * coincides with the entity MPORT in the case of independent ports.
+ * In the case of representors, this ID is not a selector and refers
+ * to an allocatable object (that is, it's likely to change on RTE
+ * ethdev replug). Flow API backend must use this value rather
+ * than entity_mport to support flow rule action PORT_ID.
  */
 struct sfc_mae_switch_port {
 	TAILQ_ENTRY(sfc_mae_switch_port)	switch_domain_ports;
 
+	/** RTE ethdev MPORT */
+	efx_mport_sel_t				ethdev_mport;
+	/** RTE ethdev port ID */
+	uint16_t				ethdev_port_id;
+
 	/** Entity (PCIe function) MPORT selector */
 	efx_mport_sel_t				entity_mport;
 	/** Port type (independent/representor) */
@@ -263,6 +275,9 @@ sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 	TAILQ_INSERT_TAIL(&domain->ports, port, switch_domain_ports);
 
 done:
+	port->ethdev_mport = *req->ethdev_mportp;
+	port->ethdev_port_id = req->ethdev_port_id;
+
 	*switch_port_id = port->id;
 
 	rte_spinlock_unlock(&sfc_mae_switch.lock);
@@ -274,3 +289,46 @@ sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 	rte_spinlock_unlock(&sfc_mae_switch.lock);
 	return rc;
 }
+
+/* This function expects to be called only when the lock is held */
+static int
+sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
+				   uint16_t ethdev_port_id,
+				   efx_mport_sel_t *mport_sel)
+{
+	struct sfc_mae_switch_domain *domain;
+	struct sfc_mae_switch_port *port;
+
+	SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+	if (ethdev_port_id == RTE_MAX_ETHPORTS)
+		return EINVAL;
+
+	domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
+	if (domain == NULL)
+		return EINVAL;
+
+	TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
+		if (port->ethdev_port_id == ethdev_port_id) {
+			*mport_sel = port->ethdev_mport;
+			return 0;
+		}
+	}
+
+	return ENOENT;
+}
+
+int
+sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id,
+			      uint16_t ethdev_port_id,
+			      efx_mport_sel_t *mport_sel)
+{
+	int rc;
+
+	rte_spinlock_lock(&sfc_mae_switch.lock);
+	rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id,
+						ethdev_port_id, mport_sel);
+	rte_spinlock_unlock(&sfc_mae_switch.lock);
+
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 9845ac8801..96ece95654 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -32,6 +32,8 @@ enum sfc_mae_switch_port_type {
 struct sfc_mae_switch_port_request {
 	enum sfc_mae_switch_port_type		type;
 	const efx_mport_sel_t			*entity_mportp;
+	const efx_mport_sel_t			*ethdev_mportp;
+	uint16_t				ethdev_port_id;
 };
 
 int sfc_mae_assign_switch_domain(struct sfc_adapter *sa,
@@ -41,6 +43,10 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 			       const struct sfc_mae_switch_port_request *req,
 			       uint16_t *switch_port_id);
 
+int sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id,
+				  uint16_t ethdev_port_id,
+				  efx_mport_sel_t *mport_sel);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.17.1


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

* [dpdk-dev] [PATCH 45/62] net/sfc: support flow item PORT ID in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (43 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 44/62] net/sfc: support flow action PORT ID in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 46/62] common/sfc_efx/base: add MAE match fields for VLAN Andrew Rybchenko
                   ` (18 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

The DPDK port must not relate to a different physical device.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  2 +
 drivers/net/sfc/sfc_mae.c   | 76 +++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 7b8c1c8527..e1cacf55ff 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -190,6 +190,8 @@ Supported actions (***non-transfer*** rules):
 
 Supported pattern items (***transfer*** rules):
 
+- PORT_ID (cannot repeat; conflicts with other traffic source items)
+
 - PHY_PORT (cannot repeat; conflicts with other traffic source items)
 
 - PF (cannot repeat; conflicts with other traffic source items)
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index f309efa2cf..14e6d33c55 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -260,6 +260,71 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
 }
 
+static int
+sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
+				struct sfc_flow_parse_ctx *ctx,
+				struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const struct rte_flow_item_port_id supp_mask = {
+		.id = 0xffffffff,
+	};
+	const void *def_mask = &rte_flow_item_port_id_mask;
+	const struct rte_flow_item_port_id *spec = NULL;
+	const struct rte_flow_item_port_id *mask = NULL;
+	efx_mport_sel_t mport_sel;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(struct rte_flow_item_port_id), error);
+	if (rc != 0)
+		return rc;
+
+	if (mask->id != supp_mask.id) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad mask in the PORT_ID pattern item");
+	}
+
+	/* If "spec" is not set, could be any port ID */
+	if (spec == NULL)
+		return 0;
+
+	if (spec->id > UINT16_MAX) {
+		return rte_flow_error_set(error, EOVERFLOW,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "The port ID is too large");
+	}
+
+	rc = sfc_mae_switch_port_by_ethdev(ctx_mae->sa->mae.switch_domain_id,
+					   spec->id, &mport_sel);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't find RTE ethdev by the port ID");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_sel, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the port ID");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
 static int
 sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 				 struct sfc_flow_parse_ctx *ctx,
@@ -521,6 +586,17 @@ sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
 }
 
 static const struct sfc_flow_item sfc_flow_items[] = {
+	{
+		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_port_id,
+	},
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
 		/*
-- 
2.17.1


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

* [dpdk-dev] [PATCH 46/62] common/sfc_efx/base: add MAE match fields for VLAN
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (44 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 45/62] net/sfc: support flow item " Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 47/62] net/sfc: support flow item VLAN in transfer rules Andrew Rybchenko
                   ` (17 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 4 ++++
 drivers/common/sfc_efx/base/efx_mae.c | 8 ++++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 75edb59a49..30bd411843 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4103,6 +4103,10 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_ETHER_TYPE_BE,
 	EFX_MAE_FIELD_ETH_SADDR_BE,
 	EFX_MAE_FIELD_ETH_DADDR_BE,
+	EFX_MAE_FIELD_VLAN0_TCI_BE,
+	EFX_MAE_FIELD_VLAN0_PROTO_BE,
+	EFX_MAE_FIELD_VLAN1_TCI_BE,
+	EFX_MAE_FIELD_VLAN1_PROTO_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 0cfa3f6c06..334b46630c 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -286,6 +286,10 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
 	EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
 	EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
+	EFX_MAE_FIELD_ID_VLAN0_TCI_BE = MAE_FIELD_VLAN0_TCI,
+	EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO,
+	EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI,
+	EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -331,6 +335,10 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 47/62] net/sfc: support flow item VLAN in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (45 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 46/62] common/sfc_efx/base: add MAE match fields for VLAN Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 48/62] common/sfc_efx/base: add MAE match fields for IPv4 Andrew Rybchenko
                   ` (16 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

In a pattern, a L2 item preceding an item VLAN must have
correct "type" ("inner_type") set depending on the total
number of VLAN tags (double-tagging is supported):

"pattern eth type is X / vlan / end",
X = 0x8100, or 0x88a8, or 0x9100, or 0x9200, or 0x9300

"pattern eth type is X / vlan inner_type is 0x8100 / vlan / end"
X = 0x88a8, or 0x9100, or 0x9200, or 0x9300

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   2 +
 drivers/net/sfc/sfc_mae.c   | 265 +++++++++++++++++++++++++++++++++++-
 drivers/net/sfc/sfc_mae.h   |  47 +++++++
 3 files changed, 311 insertions(+), 3 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e1cacf55ff..adee0cd670 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -200,6 +200,8 @@ Supported pattern items (***transfer*** rules):
 
 - ETH
 
+- VLAN (double-tagging is supported)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 14e6d33c55..cc22fee6fe 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -260,6 +260,122 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
 }
 
+static int
+sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
+{
+	efx_mae_match_spec_t *efx_spec = ctx->match_spec_action;
+	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
+	const efx_mae_field_id_t field_ids[] = {
+		EFX_MAE_FIELD_VLAN0_PROTO_BE,
+		EFX_MAE_FIELD_VLAN1_PROTO_BE,
+	};
+	const struct sfc_mae_ethertype *et;
+	unsigned int i;
+	int rc;
+
+	/*
+	 * In accordance with RTE flow API convention, the innermost L2
+	 * item's "type" ("inner_type") is a L3 EtherType. If there is
+	 * no L3 item, it's 0x0000/0x0000.
+	 */
+	et = &pdata->ethertypes[pdata->nb_vlan_tags];
+	rc = efx_mae_match_spec_field_set(efx_spec, EFX_MAE_FIELD_ETHER_TYPE_BE,
+					  sizeof(et->value),
+					  (const uint8_t *)&et->value,
+					  sizeof(et->mask),
+					  (const uint8_t *)&et->mask);
+	if (rc != 0)
+		return rc;
+
+	/*
+	 * sfc_mae_rule_parse_item_vlan() has already made sure
+	 * that pdata->nb_vlan_tags does not exceed this figure.
+	 */
+	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
+
+	for (i = 0; i < pdata->nb_vlan_tags; ++i) {
+		et = &pdata->ethertypes[i];
+
+		rc = efx_mae_match_spec_field_set(efx_spec, field_ids[i],
+						  sizeof(et->value),
+						  (const uint8_t *)&et->value,
+						  sizeof(et->mask),
+						  (const uint8_t *)&et->mask);
+		if (rc != 0)
+			return rc;
+	}
+
+	return 0;
+}
+
+static int
+sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
+				  struct rte_flow_error *error)
+{
+	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
+	struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
+	const rte_be16_t supported_tpids[] = {
+		/* VLAN standard TPID (always the first element) */
+		RTE_BE16(RTE_ETHER_TYPE_VLAN),
+
+		/* Double-tagging TPIDs */
+		RTE_BE16(RTE_ETHER_TYPE_QINQ),
+		RTE_BE16(RTE_ETHER_TYPE_QINQ1),
+		RTE_BE16(RTE_ETHER_TYPE_QINQ2),
+		RTE_BE16(RTE_ETHER_TYPE_QINQ3),
+	};
+	unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
+	unsigned int ethertype_idx;
+	int rc;
+
+	/*
+	 * sfc_mae_rule_parse_item_vlan() has already made sure
+	 * that pdata->nb_vlan_tags does not exceed this figure.
+	 */
+	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
+
+	for (ethertype_idx = 0;
+	     ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) {
+		unsigned int tpid_idx;
+
+		/* Exact match is supported only. */
+		if (ethertypes[ethertype_idx].mask != RTE_BE16(0xffff)) {
+			rc = EINVAL;
+			goto fail;
+		}
+
+		for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1;
+		     tpid_idx < nb_supported_tpids; ++tpid_idx) {
+			if (ethertypes[ethertype_idx].value ==
+			    supported_tpids[tpid_idx])
+				break;
+		}
+
+		if (tpid_idx == nb_supported_tpids) {
+			rc = EINVAL;
+			goto fail;
+		}
+
+		nb_supported_tpids = 1;
+	}
+
+	/*
+	 * Now, when the number of VLAN tags is known, set fields
+	 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first
+	 * one is either a valid L3 EtherType (or 0x0000/0x0000),
+	 * and the last two are valid TPIDs (or 0x0000/0x0000).
+	 */
+	rc = sfc_mae_set_ethertypes(ctx);
+	if (rc != 0)
+		goto fail;
+
+	return 0;
+
+fail:
+	return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+				  "Failed to process pattern data");
+}
+
 static int
 sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 				struct sfc_flow_parse_ctx *ctx,
@@ -486,6 +602,16 @@ sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
 	return 0;
 }
 
+/*
+ * Having this field ID in a field locator means that this
+ * locator cannot be used to actually set the field at the
+ * time when the corresponding item gets encountered. Such
+ * fields get stashed in the parsing context instead. This
+ * is required to resolve dependencies between the stashed
+ * fields. See sfc_mae_rule_process_pattern_data().
+ */
+#define SFC_MAE_FIELD_HANDLING_DEFERRED	EFX_MAE_FIELD_NIDS
+
 struct sfc_mae_field_locator {
 	efx_mae_field_id_t		field_id;
 	size_t				size;
@@ -522,6 +648,9 @@ sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
 	for (i = 0; i < nb_field_locators; ++i) {
 		const struct sfc_mae_field_locator *fl = &field_locators[i];
 
+		if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED)
+			continue;
+
 		rc = efx_mae_match_spec_field_set(efx_spec, fl->field_id,
 						  fl->size, spec + fl->ofst,
 						  fl->size, mask + fl->ofst);
@@ -539,7 +668,11 @@ sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
 
 static const struct sfc_mae_field_locator flocs_eth[] = {
 	{
-		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
 		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type),
 		offsetof(struct rte_flow_item_eth, type),
 	},
@@ -577,14 +710,128 @@ sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
 	if (rc != 0)
 		return rc;
 
-	/* If "spec" is not set, could be any Ethernet */
-	if (spec == NULL)
+	if (spec != NULL) {
+		struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+		struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
+		const struct rte_flow_item_eth *item_spec;
+		const struct rte_flow_item_eth *item_mask;
+
+		item_spec = (const struct rte_flow_item_eth *)spec;
+		item_mask = (const struct rte_flow_item_eth *)mask;
+
+		ethertypes[0].value = item_spec->type;
+		ethertypes[0].mask = item_mask->type;
+	} else {
+		/*
+		 * The specification is empty. This is wrong in the case
+		 * when there are more network patterns in line. Other
+		 * than that, any Ethernet can match. All of that is
+		 * checked at the end of parsing.
+		 */
 		return 0;
+	}
 
 	return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
 				  ctx_mae->match_spec_action, error);
 }
 
+static const struct sfc_mae_field_locator flocs_vlan[] = {
+	/* Outermost tag */
+	{
+		EFX_MAE_FIELD_VLAN0_TCI_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
+		offsetof(struct rte_flow_item_vlan, tci),
+	},
+	{
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
+		offsetof(struct rte_flow_item_vlan, inner_type),
+	},
+
+	/* Innermost tag */
+	{
+		EFX_MAE_FIELD_VLAN1_TCI_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
+		offsetof(struct rte_flow_item_vlan, tci),
+	},
+	{
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
+		offsetof(struct rte_flow_item_vlan, inner_type),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
+			     struct sfc_flow_parse_ctx *ctx,
+			     struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	const struct sfc_mae_field_locator *flocs;
+	struct rte_flow_item_vlan supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	unsigned int nb_flocs;
+	int rc;
+
+	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
+
+	if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't match that many VLAN tags");
+	}
+
+	nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS;
+	flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs;
+
+	/* If parsing fails, this can remain incremented. */
+	++pdata->nb_vlan_tags;
+
+	sfc_mae_item_build_supp_mask(flocs, nb_flocs,
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_vlan_mask,
+				 sizeof(struct rte_flow_item_vlan), error);
+	if (rc != 0)
+		return rc;
+
+	if (spec != NULL) {
+		struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
+		const struct rte_flow_item_vlan *item_spec;
+		const struct rte_flow_item_vlan *item_mask;
+
+		item_spec = (const struct rte_flow_item_vlan *)spec;
+		item_mask = (const struct rte_flow_item_vlan *)mask;
+
+		ethertypes[pdata->nb_vlan_tags].value = item_spec->inner_type;
+		ethertypes[pdata->nb_vlan_tags].mask = item_mask->inner_type;
+	} else {
+		/*
+		 * The specification is empty. This is wrong in the case
+		 * when there are more network patterns in line. Other
+		 * than that, any Ethernet can match. All of that is
+		 * checked at the end of parsing.
+		 */
+		return 0;
+	}
+
+	return sfc_mae_parse_item(flocs, nb_flocs, spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -637,6 +884,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_eth,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_VLAN,
+		.prev_layer = SFC_FLOW_ITEM_L2,
+		.layer = SFC_FLOW_ITEM_L2,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_vlan,
+	},
 };
 
 int
@@ -670,6 +924,10 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_parse_pattern;
 
+	rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error);
+	if (rc != 0)
+		goto fail_process_pattern_data;
+
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
 		rc = rte_flow_error_set(error, ENOTSUP,
 					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -682,6 +940,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	return 0;
 
 fail_validate_match_spec_action:
+fail_process_pattern_data:
 fail_parse_pattern:
 	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
 
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index f92e62dcbe..e4e8ab67a5 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -62,10 +62,57 @@ struct sfc_mae {
 struct sfc_adapter;
 struct sfc_flow_spec;
 
+/** This implementation supports double-tagging */
+#define SFC_MAE_MATCH_VLAN_MAX_NTAGS	(2)
+
+/** It is possible to keep track of one item ETH and two items VLAN */
+#define SFC_MAE_L2_MAX_NITEMS		(SFC_MAE_MATCH_VLAN_MAX_NTAGS + 1)
+
+/** Auxiliary entry format to keep track of L2 "type" ("inner_type") */
+struct sfc_mae_ethertype {
+	rte_be16_t	value;
+	rte_be16_t	mask;
+};
+
+struct sfc_mae_pattern_data {
+	/**
+	 * Keeps track of "type" ("inner_type") mask and value for each
+	 * parsed L2 item in a pattern. These values/masks get filled
+	 * in MAE match specification at the end of parsing. Also, this
+	 * information is used to conduct consistency checks:
+	 *
+	 * - If an item ETH is followed by a single item VLAN,
+	 *   the former must have "type" set to one of supported
+	 *   TPID values (0x8100, 0x88a8, 0x9100, 0x9200, 0x9300).
+	 *
+	 * - If an item ETH is followed by two items VLAN, the
+	 *   item ETH must have "type" set to one of supported TPID
+	 *   values (0x88a8, 0x9100, 0x9200, 0x9300), and the outermost
+	 *   VLAN item must have "inner_type" set to TPID value 0x8100.
+	 *
+	 * In turn, mapping between RTE convention (above requirements) and
+	 * MAE fields is non-trivial. The following scheme indicates
+	 * which item EtherTypes go to which MAE fields in the case
+	 * of single tag:
+	 *
+	 * ETH	(0x8100)	--> VLAN0_PROTO_BE
+	 * VLAN	(L3 EtherType)	--> ETHER_TYPE_BE
+	 *
+	 * Similarly, in the case of double tagging:
+	 *
+	 * ETH	(0x88a8)	--> VLAN0_PROTO_BE
+	 * VLAN	(0x8100)	--> VLAN1_PROTO_BE
+	 * VLAN	(L3 EtherType)	--> ETHER_TYPE_BE
+	 */
+	struct sfc_mae_ethertype	ethertypes[SFC_MAE_L2_MAX_NITEMS];
+	unsigned int			nb_vlan_tags;
+};
+
 struct sfc_mae_parse_ctx {
 	struct sfc_adapter		*sa;
 	efx_mae_match_spec_t		*match_spec_action;
 	bool				match_mport_set;
+	struct sfc_mae_pattern_data	pattern_data;
 };
 
 int sfc_mae_attach(struct sfc_adapter *sa);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 48/62] common/sfc_efx/base: add MAE match fields for IPv4
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (46 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 47/62] net/sfc: support flow item VLAN in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 49/62] net/sfc: support flow item IPV4 in transfer rules Andrew Rybchenko
                   ` (15 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     |  5 +++++
 drivers/common/sfc_efx/base/efx_mae.c | 10 ++++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 30bd411843..ed15e5e0d5 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4107,6 +4107,11 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_VLAN0_PROTO_BE,
 	EFX_MAE_FIELD_VLAN1_TCI_BE,
 	EFX_MAE_FIELD_VLAN1_PROTO_BE,
+	EFX_MAE_FIELD_SRC_IP4_BE,
+	EFX_MAE_FIELD_DST_IP4_BE,
+	EFX_MAE_FIELD_IP_PROTO,
+	EFX_MAE_FIELD_IP_TOS,
+	EFX_MAE_FIELD_IP_TTL,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 334b46630c..5843a52569 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -290,6 +290,11 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO,
 	EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI,
 	EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO,
+	EFX_MAE_FIELD_ID_SRC_IP4_BE = MAE_FIELD_SRC_IP4,
+	EFX_MAE_FIELD_ID_DST_IP4_BE = MAE_FIELD_DST_IP4,
+	EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO,
+	EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS,
+	EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -339,6 +344,11 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(SRC_IP4_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(DST_IP4_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 49/62] net/sfc: support flow item IPV4 in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (47 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 48/62] common/sfc_efx/base: add MAE match fields for IPv4 Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 50/62] common/sfc_efx/base: add MAE match fields for IPv6 Andrew Rybchenko
                   ` (14 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   3 +
 drivers/net/sfc/sfc_mae.c   | 121 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |  20 ++++++
 3 files changed, 144 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index adee0cd670..e687e1cac3 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -202,6 +202,9 @@ Supported pattern items (***transfer*** rules):
 
 - VLAN (double-tagging is supported)
 
+- IPV4 (source/destination addresses, IP transport protocol,
+  type of service, time to live)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index cc22fee6fe..d7c1cd784f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -312,6 +312,7 @@ static int
 sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 				  struct rte_flow_error *error)
 {
+	efx_mae_match_spec_t *efx_spec = ctx->match_spec_action;
 	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
 	struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
 	const rte_be16_t supported_tpids[] = {
@@ -326,8 +327,19 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 	};
 	unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
 	unsigned int ethertype_idx;
+	const uint8_t *valuep;
+	const uint8_t *maskp;
 	int rc;
 
+	if (pdata->innermost_ethertype_restriction.mask != 0 &&
+	    pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
+		/*
+		 * If a single item VLAN is followed by a L3 item, value
+		 * of "type" in item ETH can't be a double-tagging TPID.
+		 */
+		nb_supported_tpids = 1;
+	}
+
 	/*
 	 * sfc_mae_rule_parse_item_vlan() has already made sure
 	 * that pdata->nb_vlan_tags does not exceed this figure.
@@ -359,6 +371,21 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 		nb_supported_tpids = 1;
 	}
 
+	if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) {
+		struct sfc_mae_ethertype *et = &ethertypes[ethertype_idx];
+
+		if (et->mask == 0) {
+			et->mask = RTE_BE16(0xffff);
+			et->value =
+			    pdata->innermost_ethertype_restriction.value;
+		} else if (et->mask != RTE_BE16(0xffff) ||
+			   et->value !=
+			   pdata->innermost_ethertype_restriction.value) {
+			rc = EINVAL;
+			goto fail;
+		}
+	}
+
 	/*
 	 * Now, when the number of VLAN tags is known, set fields
 	 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first
@@ -369,6 +396,16 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 	if (rc != 0)
 		goto fail;
 
+	valuep = (const uint8_t *)&pdata->l3_next_proto_value;
+	maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
+	rc = efx_mae_match_spec_field_set(efx_spec, EFX_MAE_FIELD_IP_PROTO,
+					  sizeof(pdata->l3_next_proto_value),
+					  valuep,
+					  sizeof(pdata->l3_next_proto_mask),
+					  maskp);
+	if (rc != 0)
+		goto fail;
+
 	return 0;
 
 fail:
@@ -832,6 +869,83 @@ sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
 				  ctx_mae->match_spec_action, error);
 }
 
+static const struct sfc_mae_field_locator flocs_ipv4[] = {
+	{
+		EFX_MAE_FIELD_SRC_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
+		offsetof(struct rte_flow_item_ipv4, hdr.src_addr),
+	},
+	{
+		EFX_MAE_FIELD_DST_IP4_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
+		offsetof(struct rte_flow_item_ipv4, hdr.dst_addr),
+	},
+	{
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id),
+		offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id),
+	},
+	{
+		EFX_MAE_FIELD_IP_TOS,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4,
+				 hdr.type_of_service),
+		offsetof(struct rte_flow_item_ipv4, hdr.type_of_service),
+	},
+	{
+		EFX_MAE_FIELD_IP_TTL,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live),
+		offsetof(struct rte_flow_item_ipv4, hdr.time_to_live),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
+			     struct sfc_flow_parse_ctx *ctx,
+			     struct rte_flow_error *error)
+{
+	rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4);
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	struct rte_flow_item_ipv4 supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4),
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_ipv4_mask,
+				 sizeof(struct rte_flow_item_ipv4), error);
+	if (rc != 0)
+		return rc;
+
+	pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be;
+	pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
+
+	if (spec != NULL) {
+		const struct rte_flow_item_ipv4 *item_spec;
+		const struct rte_flow_item_ipv4 *item_mask;
+
+		item_spec = (const struct rte_flow_item_ipv4 *)spec;
+		item_mask = (const struct rte_flow_item_ipv4 *)mask;
+
+		pdata->l3_next_proto_value = item_spec->hdr.next_proto_id;
+		pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id;
+	} else {
+		return 0;
+	}
+
+	return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -891,6 +1005,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_vlan,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_IPV4,
+		.prev_layer = SFC_FLOW_ITEM_L2,
+		.layer = SFC_FLOW_ITEM_L3,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_ipv4,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index e4e8ab67a5..56be8bf917 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -90,6 +90,10 @@ struct sfc_mae_pattern_data {
 	 *   values (0x88a8, 0x9100, 0x9200, 0x9300), and the outermost
 	 *   VLAN item must have "inner_type" set to TPID value 0x8100.
 	 *
+	 * - If a L2 item is followed by a L3 one, the former must
+	 *   indicate "type" ("inner_type") which corresponds to
+	 *   the protocol used in the L3 item, or 0x0000/0x0000.
+	 *
 	 * In turn, mapping between RTE convention (above requirements) and
 	 * MAE fields is non-trivial. The following scheme indicates
 	 * which item EtherTypes go to which MAE fields in the case
@@ -106,6 +110,22 @@ struct sfc_mae_pattern_data {
 	 */
 	struct sfc_mae_ethertype	ethertypes[SFC_MAE_L2_MAX_NITEMS];
 	unsigned int			nb_vlan_tags;
+
+	/**
+	 * L3 requirement for the innermost L2 item's "type" ("inner_type").
+	 * This contains one of:
+	 * - 0x0800/0xffff: IPV4
+	 * - 0x0000/0x0000: no L3 item
+	 */
+	struct sfc_mae_ethertype	innermost_ethertype_restriction;
+
+	/**
+	 * The following two fields keep track of L3 "proto" mask and value.
+	 * The corresponding fields get filled in MAE match specification
+	 * at the end of parsing.
+	 */
+	uint8_t				l3_next_proto_value;
+	uint8_t				l3_next_proto_mask;
 };
 
 struct sfc_mae_parse_ctx {
-- 
2.17.1


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

* [dpdk-dev] [PATCH 50/62] common/sfc_efx/base: add MAE match fields for IPv6
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (48 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 49/62] net/sfc: support flow item IPV4 in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 51/62] net/sfc: support flow item IPV6 in transfer rules Andrew Rybchenko
                   ` (13 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 2 ++
 drivers/common/sfc_efx/base/efx_mae.c | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index ed15e5e0d5..16927eb910 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4112,6 +4112,8 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_IP_PROTO,
 	EFX_MAE_FIELD_IP_TOS,
 	EFX_MAE_FIELD_IP_TTL,
+	EFX_MAE_FIELD_SRC_IP6_BE,
+	EFX_MAE_FIELD_DST_IP6_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 5843a52569..c015b4c471 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -295,6 +295,8 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO,
 	EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS,
 	EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
+	EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6,
+	EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -349,6 +351,8 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 51/62] net/sfc: support flow item IPV6 in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (49 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 50/62] common/sfc_efx/base: add MAE match fields for IPv6 Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 52/62] common/sfc_efx/base: add MAE match fields for TCP and UDP Andrew Rybchenko
                   ` (12 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   3 +
 drivers/net/sfc/sfc_mae.c   | 106 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |   1 +
 3 files changed, 110 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e687e1cac3..8209990d23 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -205,6 +205,9 @@ Supported pattern items (***transfer*** rules):
 - IPV4 (source/destination addresses, IP transport protocol,
   type of service, time to live)
 
+- IPV6 (source/destination addresses, IP transport protocol,
+  traffic class, hop limit)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index d7c1cd784f..2b0121c0ac 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -946,6 +946,105 @@ sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
 				  ctx_mae->match_spec_action, error);
 }
 
+static const struct sfc_mae_field_locator flocs_ipv6[] = {
+	{
+		EFX_MAE_FIELD_SRC_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
+		offsetof(struct rte_flow_item_ipv6, hdr.src_addr),
+	},
+	{
+		EFX_MAE_FIELD_DST_IP6_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
+		offsetof(struct rte_flow_item_ipv6, hdr.dst_addr),
+	},
+	{
+		/*
+		 * This locator is used only for building supported fields mask.
+		 * The field is handled by sfc_mae_rule_process_pattern_data().
+		 */
+		SFC_MAE_FIELD_HANDLING_DEFERRED,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto),
+		offsetof(struct rte_flow_item_ipv6, hdr.proto),
+	},
+	{
+		EFX_MAE_FIELD_IP_TTL,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits),
+		offsetof(struct rte_flow_item_ipv6, hdr.hop_limits),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
+			     struct sfc_flow_parse_ctx *ctx,
+			     struct rte_flow_error *error)
+{
+	rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	struct rte_flow_item_ipv6 supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	rte_be32_t vtc_flow_be;
+	uint32_t vtc_flow;
+	uint8_t tc_value;
+	uint8_t tc_mask;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6),
+				     &supp_mask, sizeof(supp_mask));
+
+	vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK);
+	memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_ipv6_mask,
+				 sizeof(struct rte_flow_item_ipv6), error);
+	if (rc != 0)
+		return rc;
+
+	pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be;
+	pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
+
+	if (spec != NULL) {
+		const struct rte_flow_item_ipv6 *item_spec;
+		const struct rte_flow_item_ipv6 *item_mask;
+
+		item_spec = (const struct rte_flow_item_ipv6 *)spec;
+		item_mask = (const struct rte_flow_item_ipv6 *)mask;
+
+		pdata->l3_next_proto_value = item_spec->hdr.proto;
+		pdata->l3_next_proto_mask = item_mask->hdr.proto;
+	} else {
+		return 0;
+	}
+
+	rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
+				ctx_mae->match_spec_action, error);
+	if (rc != 0)
+		return rc;
+
+	memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be));
+	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
+	tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+
+	memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be));
+	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
+	tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+
+	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec_action,
+					  EFX_MAE_FIELD_IP_TOS,
+					  sizeof(tc_value), &tc_value,
+					  sizeof(tc_mask), &tc_mask);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
+				NULL, "Failed to process item fields");
+	}
+
+	return 0;
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -1012,6 +1111,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_ipv4,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_IPV6,
+		.prev_layer = SFC_FLOW_ITEM_L2,
+		.layer = SFC_FLOW_ITEM_L3,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_ipv6,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 56be8bf917..993a377861 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -115,6 +115,7 @@ struct sfc_mae_pattern_data {
 	 * L3 requirement for the innermost L2 item's "type" ("inner_type").
 	 * This contains one of:
 	 * - 0x0800/0xffff: IPV4
+	 * - 0x86dd/0xffff: IPV6
 	 * - 0x0000/0x0000: no L3 item
 	 */
 	struct sfc_mae_ethertype	innermost_ethertype_restriction;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 52/62] common/sfc_efx/base: add MAE match fields for TCP and UDP
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (50 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 51/62] net/sfc: support flow item IPV6 in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 53/62] net/sfc: support flow item TCP in transfer rules Andrew Rybchenko
                   ` (11 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 3 +++
 drivers/common/sfc_efx/base/efx_mae.c | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 16927eb910..b84a43336a 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4114,6 +4114,9 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_IP_TTL,
 	EFX_MAE_FIELD_SRC_IP6_BE,
 	EFX_MAE_FIELD_DST_IP6_BE,
+	EFX_MAE_FIELD_L4_SPORT_BE,
+	EFX_MAE_FIELD_L4_DPORT_BE,
+	EFX_MAE_FIELD_TCP_FLAGS_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index c015b4c471..7958504963 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -297,6 +297,9 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
 	EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6,
 	EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6,
+	EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT,
+	EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT,
+	EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -353,6 +356,9 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 53/62] net/sfc: support flow item TCP in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (51 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 52/62] common/sfc_efx/base: add MAE match fields for TCP and UDP Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 54/62] net/sfc: support flow item UDP " Andrew Rybchenko
                   ` (10 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  2 +
 drivers/net/sfc/sfc_mae.c   | 77 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   | 15 +++++++-
 3 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 8209990d23..661af43a20 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -208,6 +208,8 @@ Supported pattern items (***transfer*** rules):
 - IPV6 (source/destination addresses, IP transport protocol,
   traffic class, hop limit)
 
+- TCP (source/destination ports, TCP header length + TCP flags)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2b0121c0ac..59c53a96f3 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -396,6 +396,19 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 	if (rc != 0)
 		goto fail;
 
+	if (pdata->l3_next_proto_restriction_mask == 0xff) {
+		if (pdata->l3_next_proto_mask == 0) {
+			pdata->l3_next_proto_mask = 0xff;
+			pdata->l3_next_proto_value =
+			    pdata->l3_next_proto_restriction_value;
+		} else if (pdata->l3_next_proto_mask != 0xff ||
+			   pdata->l3_next_proto_value !=
+			   pdata->l3_next_proto_restriction_value) {
+			rc = EINVAL;
+			goto fail;
+		}
+	}
+
 	valuep = (const uint8_t *)&pdata->l3_next_proto_value;
 	maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
 	rc = efx_mae_match_spec_field_set(efx_spec, EFX_MAE_FIELD_IP_PROTO,
@@ -1045,6 +1058,63 @@ sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
 	return 0;
 }
 
+static const struct sfc_mae_field_locator flocs_tcp[] = {
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port),
+		offsetof(struct rte_flow_item_tcp, hdr.src_port),
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port),
+		offsetof(struct rte_flow_item_tcp, hdr.dst_port),
+	},
+	{
+		EFX_MAE_FIELD_TCP_FLAGS_BE,
+		/*
+		 * The values have been picked intentionally since the
+		 * target MAE field is oversize (16 bit). This mapping
+		 * relies on the fact that the MAE field is big-endian.
+		 */
+		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) +
+		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags),
+		offsetof(struct rte_flow_item_tcp, hdr.data_off),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
+			    struct sfc_flow_parse_ctx *ctx,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	struct rte_flow_item_tcp supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp),
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_tcp_mask,
+				 sizeof(struct rte_flow_item_tcp), error);
+	if (rc != 0)
+		return rc;
+
+	pdata->l3_next_proto_restriction_value = IPPROTO_TCP;
+	pdata->l3_next_proto_restriction_mask = 0xff;
+
+	if (spec == NULL)
+		return 0;
+
+	return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -1118,6 +1188,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_ipv6,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_TCP,
+		.prev_layer = SFC_FLOW_ITEM_L3,
+		.layer = SFC_FLOW_ITEM_L4,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_tcp,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 993a377861..71046f2308 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -123,10 +123,23 @@ struct sfc_mae_pattern_data {
 	/**
 	 * The following two fields keep track of L3 "proto" mask and value.
 	 * The corresponding fields get filled in MAE match specification
-	 * at the end of parsing.
+	 * at the end of parsing. Also, the information is used by a
+	 * post-check to enforce consistency requirements:
+	 *
+	 * - If a L3 item is followed by an item TCP, the former has
+	 *   its "proto" set to either 0x06/0xff or 0x00/0x00.
 	 */
 	uint8_t				l3_next_proto_value;
 	uint8_t				l3_next_proto_mask;
+
+	/*
+	 * L4 requirement for L3 item's "proto".
+	 * This contains one of:
+	 * - 0x06/0xff: TCP
+	 * - 0x00/0x00: no L4 item
+	 */
+	uint8_t				l3_next_proto_restriction_value;
+	uint8_t				l3_next_proto_restriction_mask;
 };
 
 struct sfc_mae_parse_ctx {
-- 
2.17.1


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

* [dpdk-dev] [PATCH 54/62] net/sfc: support flow item UDP in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (52 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 53/62] net/sfc: support flow item TCP in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 55/62] common/sfc_efx/base: indicate MAE support for encapsulation Andrew Rybchenko
                   ` (9 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  2 ++
 drivers/net/sfc/sfc_mae.c   | 53 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |  4 +++
 3 files changed, 59 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 661af43a20..e8f8fa987b 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -210,6 +210,8 @@ Supported pattern items (***transfer*** rules):
 
 - TCP (source/destination ports, TCP header length + TCP flags)
 
+- UDP (source/destination ports)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 59c53a96f3..3dd233c6dc 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1115,6 +1115,52 @@ sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
 				  ctx_mae->match_spec_action, error);
 }
 
+static const struct sfc_mae_field_locator flocs_udp[] = {
+	{
+		EFX_MAE_FIELD_L4_SPORT_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port),
+		offsetof(struct rte_flow_item_udp, hdr.src_port),
+	},
+	{
+		EFX_MAE_FIELD_L4_DPORT_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port),
+		offsetof(struct rte_flow_item_udp, hdr.dst_port),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item,
+			    struct sfc_flow_parse_ctx *ctx,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
+	struct rte_flow_item_udp supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp),
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_udp_mask,
+				 sizeof(struct rte_flow_item_udp), error);
+	if (rc != 0)
+		return rc;
+
+	pdata->l3_next_proto_restriction_value = IPPROTO_UDP;
+	pdata->l3_next_proto_restriction_mask = 0xff;
+
+	if (spec == NULL)
+		return 0;
+
+	return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
@@ -1195,6 +1241,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_tcp,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_UDP,
+		.prev_layer = SFC_FLOW_ITEM_L3,
+		.layer = SFC_FLOW_ITEM_L4,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_udp,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 71046f2308..8d9b4039f3 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -128,6 +128,9 @@ struct sfc_mae_pattern_data {
 	 *
 	 * - If a L3 item is followed by an item TCP, the former has
 	 *   its "proto" set to either 0x06/0xff or 0x00/0x00.
+	 *
+	 * - If a L3 item is followed by an item UDP, the former has
+	 *   its "proto" set to either 0x11/0xff or 0x00/0x00.
 	 */
 	uint8_t				l3_next_proto_value;
 	uint8_t				l3_next_proto_mask;
@@ -136,6 +139,7 @@ struct sfc_mae_pattern_data {
 	 * L4 requirement for L3 item's "proto".
 	 * This contains one of:
 	 * - 0x06/0xff: TCP
+	 * - 0x11/0xff: UDP
 	 * - 0x00/0x00: no L4 item
 	 */
 	uint8_t				l3_next_proto_restriction_value;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 55/62] common/sfc_efx/base: indicate MAE support for encapsulation
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (53 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 54/62] net/sfc: support flow item UDP " Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 56/62] common/sfc_efx/base: add MAE encap. match fields Andrew Rybchenko
                   ` (8 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE provides support for encapsulation. One needs to insert
a so-called outer rule, which can match outer packet fields,
to require that matching packets be parsed as tunnel frames
of a given type (VXLAN, Geneve, NVGRE). Then it is possible
to chain this rule with an action rule in order to match on
inner fields and carry out some actions on matching packets.

Report to clients what encapsulation types are supported by
MAE. Indicate the number of priority levels for outer rules.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      |  2 ++
 drivers/common/sfc_efx/base/efx_impl.h |  2 ++
 drivers/common/sfc_efx/base/efx_mae.c  | 22 ++++++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index b84a43336a..dea1fe3979 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4068,6 +4068,8 @@ efx_mae_fini(
 
 typedef struct efx_mae_limits_s {
 	uint32_t			eml_max_n_action_prios;
+	uint32_t			eml_max_n_outer_prios;
+	uint32_t			eml_encap_types_supported;
 } efx_mae_limits_t;
 
 LIBEFX_API
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index db68cc7b24..900a8c9c6a 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -798,6 +798,8 @@ typedef struct efx_mae_s {
 	/** Action rule match field capabilities. */
 	efx_mae_field_cap_t		*em_action_rule_field_caps;
 	size_t				em_action_rule_field_caps_size;
+	uint32_t			em_max_n_outer_prios;
+	uint32_t			em_encap_types_supported;
 } 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 7958504963..4e51c7b69b 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -39,9 +39,29 @@ efx_mae_get_capabilities(
 		goto fail2;
 	}
 
+	maep->em_max_n_outer_prios =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_OUTER_PRIOS);
+
 	maep->em_max_n_action_prios =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
 
+	maep->em_encap_types_supported = 0;
+
+	if (MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN) == 1) {
+		maep->em_encap_types_supported |=
+		    (1U << EFX_TUNNEL_PROTOCOL_VXLAN);
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE) == 1) {
+		maep->em_encap_types_supported |=
+		    (1U << EFX_TUNNEL_PROTOCOL_GENEVE);
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE) == 1) {
+		maep->em_encap_types_supported |=
+		    (1U << EFX_TUNNEL_PROTOCOL_NVGRE);
+	}
+
 	maep->em_max_nfields =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
 
@@ -225,7 +245,9 @@ efx_mae_get_limits(
 		goto fail1;
 	}
 
+	emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
 	emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
+	emlp->eml_encap_types_supported = maep->em_encap_types_supported;
 
 	return (0);
 
-- 
2.17.1


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

* [dpdk-dev] [PATCH 56/62] common/sfc_efx/base: add MAE encap. match fields
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (54 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 55/62] common/sfc_efx/base: indicate MAE support for encapsulation Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 57/62] common/sfc_efx/base: add MAE match field VNET ID for tunnels Andrew Rybchenko
                   ` (7 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

These fields are meant to comprise a so-called outer
match specification; provide necessary definitions.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h      | 17 ++++++++
 drivers/common/sfc_efx/base/efx_impl.h |  1 +
 drivers/common/sfc_efx/base/efx_mae.c  | 56 ++++++++++++++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index dea1fe3979..29ef20facc 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4080,6 +4080,7 @@ efx_mae_get_limits(
 
 typedef enum efx_mae_rule_type_e {
 	EFX_MAE_RULE_ACTION = 0,
+	EFX_MAE_RULE_OUTER,
 
 	EFX_MAE_RULE_NTYPES
 } efx_mae_rule_type_t;
@@ -4119,6 +4120,22 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_L4_SPORT_BE,
 	EFX_MAE_FIELD_L4_DPORT_BE,
 	EFX_MAE_FIELD_TCP_FLAGS_BE,
+	EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
+	EFX_MAE_FIELD_ENC_ETH_SADDR_BE,
+	EFX_MAE_FIELD_ENC_ETH_DADDR_BE,
+	EFX_MAE_FIELD_ENC_VLAN0_TCI_BE,
+	EFX_MAE_FIELD_ENC_VLAN0_PROTO_BE,
+	EFX_MAE_FIELD_ENC_VLAN1_TCI_BE,
+	EFX_MAE_FIELD_ENC_VLAN1_PROTO_BE,
+	EFX_MAE_FIELD_ENC_SRC_IP4_BE,
+	EFX_MAE_FIELD_ENC_DST_IP4_BE,
+	EFX_MAE_FIELD_ENC_IP_PROTO,
+	EFX_MAE_FIELD_ENC_IP_TOS,
+	EFX_MAE_FIELD_ENC_IP_TTL,
+	EFX_MAE_FIELD_ENC_SRC_IP6_BE,
+	EFX_MAE_FIELD_ENC_DST_IP6_BE,
+	EFX_MAE_FIELD_ENC_L4_SPORT_BE,
+	EFX_MAE_FIELD_ENC_L4_DPORT_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 900a8c9c6a..6a8b8d65f1 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1698,6 +1698,7 @@ struct efx_mae_match_spec_s {
 	uint32_t			emms_prio;
 	union emms_mask_value_pairs {
 		uint8_t			action[MAE_FIELD_MASK_VALUE_PAIRS_LEN];
+		uint8_t			outer[MAE_ENC_FIELD_PAIRS_LEN];
 	} emms_mask_value_pairs;
 };
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4e51c7b69b..13ccd79f31 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -267,6 +267,8 @@ efx_mae_match_spec_init(
 	efx_rc_t rc;
 
 	switch (type) {
+	case EFX_MAE_RULE_OUTER:
+		break;
 	case EFX_MAE_RULE_ACTION:
 		break;
 	default:
@@ -322,6 +324,22 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT,
 	EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT,
 	EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS,
+	EFX_MAE_FIELD_ID_ENC_ETHER_TYPE_BE = MAE_FIELD_ENC_ETHER_TYPE,
+	EFX_MAE_FIELD_ID_ENC_ETH_SADDR_BE = MAE_FIELD_ENC_ETH_SADDR,
+	EFX_MAE_FIELD_ID_ENC_ETH_DADDR_BE = MAE_FIELD_ENC_ETH_DADDR,
+	EFX_MAE_FIELD_ID_ENC_VLAN0_TCI_BE = MAE_FIELD_ENC_VLAN0_TCI,
+	EFX_MAE_FIELD_ID_ENC_VLAN0_PROTO_BE = MAE_FIELD_ENC_VLAN0_PROTO,
+	EFX_MAE_FIELD_ID_ENC_VLAN1_TCI_BE = MAE_FIELD_ENC_VLAN1_TCI,
+	EFX_MAE_FIELD_ID_ENC_VLAN1_PROTO_BE = MAE_FIELD_ENC_VLAN1_PROTO,
+	EFX_MAE_FIELD_ID_ENC_SRC_IP4_BE = MAE_FIELD_ENC_SRC_IP4,
+	EFX_MAE_FIELD_ID_ENC_DST_IP4_BE = MAE_FIELD_ENC_DST_IP4,
+	EFX_MAE_FIELD_ID_ENC_IP_PROTO = MAE_FIELD_ENC_IP_PROTO,
+	EFX_MAE_FIELD_ID_ENC_IP_TOS = MAE_FIELD_ENC_IP_TOS,
+	EFX_MAE_FIELD_ID_ENC_IP_TTL = MAE_FIELD_ENC_IP_TTL,
+	EFX_MAE_FIELD_ID_ENC_SRC_IP6_BE = MAE_FIELD_ENC_SRC_IP6,
+	EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6,
+	EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
+	EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -382,6 +400,40 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
 
+#undef EFX_MAE_MV_DESC
+};
+
+/* Indices to this array are provided by efx_mae_field_id_t */
+static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = {
+#define	EFX_MAE_MV_DESC(_name, _endianness)				\
+	[EFX_MAE_FIELD_##_name] =					\
+	{								\
+		EFX_MAE_FIELD_ID_##_name,				\
+		MAE_ENC_FIELD_PAIRS_##_name##_LEN,			\
+		MAE_ENC_FIELD_PAIRS_##_name##_OFST,			\
+		MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN,			\
+		MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST,		\
+		_endianness						\
+	}
+
+	EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(ENC_ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_ETH_SADDR_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_ETH_DADDR_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_SRC_IP4_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_DST_IP4_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_IP_PROTO, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_IP_TOS, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_IP_TTL, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_SRC_IP6_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_DST_IP6_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_L4_SPORT_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_L4_DPORT_BE, EFX_MAE_FIELD_BE),
+
 #undef EFX_MAE_MV_DESC
 };
 
@@ -470,6 +522,10 @@ efx_mae_match_spec_field_set(
 	}
 
 	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
 	case EFX_MAE_RULE_ACTION:
 		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
 		mvp = spec->emms_mask_value_pairs.action;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 57/62] common/sfc_efx/base: add MAE match field VNET ID for tunnels
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (55 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 56/62] common/sfc_efx/base: add MAE encap. match fields Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 58/62] common/sfc_efx/base: add an API to compare match specs Andrew Rybchenko
                   ` (6 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for this field and
provide necessary mappings for it to be inserted
directly into mask-value pairs buffer.

VNET_ID can be used to serve the following match fields:
rte_flow_item_vxlan.vni, rte_flow_item_geneve.vni,
rte_flow_item_nvgre.tni

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 1 +
 drivers/common/sfc_efx/base/efx_mae.c | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 29ef20facc..901d653262 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4136,6 +4136,7 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_ENC_DST_IP6_BE,
 	EFX_MAE_FIELD_ENC_L4_SPORT_BE,
 	EFX_MAE_FIELD_ENC_L4_DPORT_BE,
+	EFX_MAE_FIELD_ENC_VNET_ID_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 13ccd79f31..dfb8b2e743 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -340,6 +340,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6,
 	EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
 	EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
+	EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -399,6 +400,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH 58/62] common/sfc_efx/base: add an API to compare match specs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (56 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 57/62] common/sfc_efx/base: add MAE match field VNET ID for tunnels Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 59/62] common/sfc_efx/base: validate and compare outer " Andrew Rybchenko
                   ` (5 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Match specification format and its size are not exposed to clients.
Provide an API to compare two match specifications.

A client would typically use this API to compare a match specification
of an outer rule being validated with match specifications of already
active outer rules (to make sure that rule class is supported).

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h                     | 6 ++++++
 drivers/common/sfc_efx/base/efx_mae.c                 | 8 ++++++++
 drivers/common/sfc_efx/rte_common_sfc_efx_version.map | 1 +
 3 files changed, 15 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 901d653262..c6472eaf76 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4204,6 +4204,12 @@ efx_mae_match_spec_mport_set(
 	__in				const efx_mport_sel_t *valuep,
 	__in_opt			const efx_mport_sel_t *maskp);
 
+LIBEFX_API
+extern	__checkReturn			boolean_t
+efx_mae_match_specs_equal(
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right);
+
 /*
  * Make sure that match fields known by EFX have proper masks set
  * in the match specification as per requirements of SF-122526-TC.
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index dfb8b2e743..935cec5e18 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -636,6 +636,14 @@ efx_mae_match_spec_mport_set(
 	return (rc);
 }
 
+	__checkReturn			boolean_t
+efx_mae_match_specs_equal(
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right)
+{
+	return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
+}
+
 #define	EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit)		\
 	    ((_mask)[(_bit) / (_mask_page_nbits)] &			\
 		    (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 37056abd60..07b3b6371b 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -107,6 +107,7 @@ INTERNAL {
 	efx_mae_match_spec_is_valid;
 	efx_mae_match_spec_mport_set;
 	efx_mae_match_specs_class_cmp;
+	efx_mae_match_specs_equal;
 	efx_mae_mport_by_pcie_function;
 	efx_mae_mport_by_phy_port;
 
-- 
2.17.1


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

* [dpdk-dev] [PATCH 59/62] common/sfc_efx/base: validate and compare outer match specs
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (57 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 58/62] common/sfc_efx/base: add an API to compare match specs Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 60/62] common/sfc_efx/base: support outer rule provisioning Andrew Rybchenko
                   ` (4 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Let the client validate an outer match specification.
Let the client comprare classes of two outer match specifications.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_impl.h |   3 +
 drivers/common/sfc_efx/base/efx_mae.c  | 126 ++++++++++++++++++++++++-
 2 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 6a8b8d65f1..d8423d49fe 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -800,6 +800,9 @@ typedef struct efx_mae_s {
 	size_t				em_action_rule_field_caps_size;
 	uint32_t			em_max_n_outer_prios;
 	uint32_t			em_encap_types_supported;
+	/** Outer rule match field capabilities. */
+	efx_mae_field_cap_t		*em_outer_rule_field_caps;
+	size_t				em_outer_rule_field_caps_size;
 } 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 935cec5e18..45a796fdad 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -74,6 +74,88 @@ efx_mae_get_capabilities(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_get_outer_rule_caps(
+	__in				efx_nic_t *enp,
+	__in				unsigned int field_ncaps,
+	__out_ecount(field_ncaps)	efx_mae_field_cap_t *field_caps)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_GET_OR_CAPS_IN_LEN,
+	    MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2);
+	unsigned int mcdi_field_ncaps;
+	unsigned int i;
+	efx_rc_t rc;
+
+	if (MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps) >
+	    MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_GET_OR_CAPS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_GET_OR_CAPS_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
+
+	if (req.emr_out_length_used <
+	    MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	if (mcdi_field_ncaps > field_ncaps) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	for (i = 0; i < mcdi_field_ncaps; ++i) {
+		uint32_t match_flag;
+		uint32_t mask_flag;
+
+		field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_SUPPORT_STATUS);
+
+		match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
+
+		field_caps[i].emfc_match_affects_class =
+		    (match_flag != 0) ? B_TRUE : B_FALSE;
+
+		mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
+
+		field_caps[i].emfc_mask_affects_class =
+		    (mask_flag != 0) ? B_TRUE : B_FALSE;
+	}
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_get_action_rule_caps(
 	__in				efx_nic_t *enp,
@@ -161,6 +243,8 @@ efx_mae_init(
 	__in				efx_nic_t *enp)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_field_cap_t *or_fcaps;
+	size_t or_fcaps_size;
 	efx_mae_field_cap_t *ar_fcaps;
 	size_t ar_fcaps_size;
 	efx_mae_t *maep;
@@ -183,11 +267,25 @@ efx_mae_init(
 	if (rc != 0)
 		goto fail3;
 
+	or_fcaps_size = maep->em_max_nfields * sizeof (*or_fcaps);
+	EFSYS_KMEM_ALLOC(enp->en_esip, or_fcaps_size, or_fcaps);
+	if (or_fcaps == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	maep->em_outer_rule_field_caps_size = or_fcaps_size;
+	maep->em_outer_rule_field_caps = or_fcaps;
+
+	rc = efx_mae_get_outer_rule_caps(enp, maep->em_max_nfields, or_fcaps);
+	if (rc != 0)
+		goto fail5;
+
 	ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
 	EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
 	if (ar_fcaps == NULL) {
 		rc = ENOMEM;
-		goto fail4;
+		goto fail6;
 	}
 
 	maep->em_action_rule_field_caps_size = ar_fcaps_size;
@@ -195,13 +293,18 @@ efx_mae_init(
 
 	rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
 	if (rc != 0)
-		goto fail5;
+		goto fail7;
 
 	return (0);
 
-fail5:
+fail7:
 	EFSYS_PROBE(fail5);
 	EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
+fail6:
+	EFSYS_PROBE(fail4);
+fail5:
+	EFSYS_PROBE(fail5);
+	EFSYS_KMEM_FREE(enp->en_esip, or_fcaps_size, or_fcaps);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:
@@ -227,6 +330,8 @@ efx_mae_fini(
 
 	EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
 	    maep->em_action_rule_field_caps);
+	EFSYS_KMEM_FREE(enp->en_esip, maep->em_outer_rule_field_caps_size,
+	    maep->em_outer_rule_field_caps);
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
 	enp->en_maep = NULL;
 }
@@ -711,6 +816,13 @@ efx_mae_match_spec_is_valid(
 	const uint8_t *mvp;
 
 	switch (spec->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		field_caps = maep->em_outer_rule_field_caps;
+		desc_setp = __efx_mae_outer_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		mvp = spec->emms_mask_value_pairs.outer;
+		break;
 	case EFX_MAE_RULE_ACTION:
 		field_caps = maep->em_action_rule_field_caps;
 		desc_setp = __efx_mae_action_rule_mv_desc_set;
@@ -1190,6 +1302,14 @@ efx_mae_match_specs_class_cmp(
 	efx_rc_t rc;
 
 	switch (left->emms_type) {
+	case EFX_MAE_RULE_OUTER:
+		field_caps = maep->em_outer_rule_field_caps;
+		desc_setp = __efx_mae_outer_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
+		mvpl = left->emms_mask_value_pairs.outer;
+		mvpr = right->emms_mask_value_pairs.outer;
+		break;
 	case EFX_MAE_RULE_ACTION:
 		field_caps = maep->em_action_rule_field_caps;
 		desc_setp = __efx_mae_action_rule_mv_desc_set;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 60/62] common/sfc_efx/base: support outer rule provisioning
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (58 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 59/62] common/sfc_efx/base: validate and compare outer " Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 61/62] net/sfc: support encap. flow items in transfer rules Andrew Rybchenko
                   ` (3 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Let the client insert / remove outer rules.
Let the client refer to an inserted outer rule in a match
specification of type ACTION.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  21 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 197 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   3 +
 3 files changed, 221 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index c6472eaf76..3b40e28b4e 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4137,6 +4137,7 @@ typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_ENC_L4_SPORT_BE,
 	EFX_MAE_FIELD_ENC_L4_DPORT_BE,
 	EFX_MAE_FIELD_ENC_VNET_ID_BE,
+	EFX_MAE_FIELD_OUTER_RULE_ID,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
@@ -4298,6 +4299,26 @@ typedef struct efx_mae_rule_id_s {
 	uint32_t id;
 } efx_mae_rule_id_t;
 
+LIBEFX_API
+extern	__checkReturn		efx_rc_t
+efx_mae_outer_rule_insert(
+	__in			efx_nic_t *enp,
+	__in			const efx_mae_match_spec_t *spec,
+	__in			efx_tunnel_protocol_t encap_type,
+	__out			efx_mae_rule_id_t *or_idp);
+
+LIBEFX_API
+extern	__checkReturn		efx_rc_t
+efx_mae_outer_rule_remove(
+	__in			efx_nic_t *enp,
+	__in			const efx_mae_rule_id_t *or_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_outer_rule_id_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mae_rule_id_t *or_idp);
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 45a796fdad..fbf56b14ce 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -446,6 +446,7 @@ typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
 	EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
 	EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
+	EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -506,6 +507,7 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
 	EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
 
 #undef EFX_MAE_MV_DESC
 };
@@ -1380,6 +1382,201 @@ efx_mae_match_specs_class_cmp(
 
 	return (0);
 
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn		efx_rc_t
+efx_mae_outer_rule_insert(
+	__in			efx_nic_t *enp,
+	__in			const efx_mae_match_spec_t *spec,
+	__in			efx_tunnel_protocol_t encap_type,
+	__out			efx_mae_rule_id_t *or_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
+	uint32_t encap_type_mcdi;
+	efx_mae_rule_id_t or_id;
+	size_t offset;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
+	    MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN);
+
+	EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+	    MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL);
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (spec->emms_type != EFX_MAE_RULE_OUTER) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	switch (encap_type) {
+	case EFX_TUNNEL_PROTOCOL_NONE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_VXLAN:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
+		break;
+	case EFX_TUNNEL_PROTOCOL_GENEVE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
+		break;
+	case EFX_TUNNEL_PROTOCOL_NVGRE:
+		encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_OUTER_RULE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req,
+	    MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, encap_type_mcdi);
+
+	MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_INSERT_IN_PRIO, spec->emms_prio);
+
+	/*
+	 * Mask-value pairs have been stored in the byte order needed for the
+	 * MCDI request and are thus safe to be copied directly to the buffer.
+	 * The library cares about byte order in efx_mae_match_spec_field_set().
+	 */
+	EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.outer) >=
+	    MAE_ENC_FIELD_PAIRS_LEN);
+	offset = MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST;
+	memcpy(payload + offset, spec->emms_mask_value_pairs.outer,
+	    MAE_ENC_FIELD_PAIRS_LEN);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail4;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail5;
+	}
+
+	or_id.id = MCDI_OUT_DWORD(req, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
+	if (or_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail6;
+	}
+
+	or_idp->id = or_id.id;
+
+	return (0);
+
+fail6:
+	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_mae_outer_rule_remove(
+	__in			efx_nic_t *enp,
+	__in			const efx_mae_rule_id_t *or_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1),
+	    MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_OUTER_RULE_REMOVE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_REMOVE_IN_OR_ID, or_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) !=
+	    or_idp->id) {
+		/* Firmware failed to remove the outer rule. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
+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_outer_rule_id_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mae_rule_id_t *or_idp)
+{
+	uint32_t full_mask = UINT32_MAX;
+	efx_rc_t rc;
+
+	if (spec->emms_type != EFX_MAE_RULE_ACTION) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (or_idp == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_OUTER_RULE_ID,
+	    sizeof (or_idp->id), (const uint8_t *)&or_idp->id,
+	    sizeof (full_mask), (const uint8_t *)&full_mask);
+	if (rc != 0)
+		goto fail3;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 07b3b6371b..403feeaf11 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -106,10 +106,13 @@ INTERNAL {
 	efx_mae_match_spec_init;
 	efx_mae_match_spec_is_valid;
 	efx_mae_match_spec_mport_set;
+	efx_mae_match_spec_outer_rule_id_set;
 	efx_mae_match_specs_class_cmp;
 	efx_mae_match_specs_equal;
 	efx_mae_mport_by_pcie_function;
 	efx_mae_mport_by_phy_port;
+	efx_mae_outer_rule_insert;
+	efx_mae_outer_rule_remove;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH 61/62] net/sfc: support encap. flow items in transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (59 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 60/62] common/sfc_efx/base: support outer rule provisioning Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 62/62] doc: advertise flow API transfer rules support in net/sfc Andrew Rybchenko
                   ` (2 subsequent siblings)
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev, Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for flow items VXLAN, Geneve and NVGRE to
MAE-specific RTE flow implementation.

Having support for these items implies the ability to insert
so-called outer MAE rules and refer to them in MAE action rules.
The patch takes care of all necessary facilities to do that.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   6 +
 drivers/net/sfc/sfc_flow.c  |  18 +-
 drivers/net/sfc/sfc_flow.h  |   2 +
 drivers/net/sfc/sfc_mae.c   | 603 ++++++++++++++++++++++++++++++++++--
 drivers/net/sfc/sfc_mae.h   |  34 ++
 5 files changed, 630 insertions(+), 33 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e8f8fa987b..461120448c 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -212,6 +212,12 @@ Supported pattern items (***transfer*** rules):
 
 - UDP (source/destination ports)
 
+- VXLAN (exact match of VXLAN network identifier)
+
+- GENEVE (exact match of virtual network identifier)
+
+- NVGRE (exact match of virtual subnet ID)
+
 Supported actions (***transfer*** rules):
 
 - OF_POP_VLAN
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 6ccefef477..4321045d1a 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1288,7 +1288,8 @@ sfc_flow_parse_pattern(const struct sfc_flow_item *flow_items,
 			break;
 
 		default:
-			if (is_ifrm) {
+			if (parse_ctx->type == SFC_FLOW_PARSE_CTX_FILTER &&
+			    is_ifrm) {
 				rte_flow_error_set(error, EINVAL,
 					RTE_FLOW_ERROR_TYPE_ITEM,
 					pattern,
@@ -2565,13 +2566,8 @@ sfc_flow_verify(struct sfc_adapter *sa, struct rte_flow *flow,
 	}
 
 	if (ops->verify != NULL) {
-		/*
-		 * Use locking since verify method may need to
-		 * access the list of already created rules.
-		 */
-		sfc_adapter_lock(sa);
+		SFC_ASSERT(sfc_adapter_is_locked(sa));
 		rc = ops->verify(sa, flow);
-		sfc_adapter_unlock(sa);
 	}
 
 	if (rc != 0) {
@@ -2599,12 +2595,16 @@ sfc_flow_validate(struct rte_eth_dev *dev,
 	if (flow == NULL)
 		return -rte_errno;
 
+	sfc_adapter_lock(sa);
+
 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
 	if (rc == 0)
 		rc = sfc_flow_verify(sa, flow, error);
 
 	sfc_flow_free(sa, flow);
 
+	sfc_adapter_unlock(sa);
+
 	return rc;
 }
 
@@ -2623,12 +2623,12 @@ sfc_flow_create(struct rte_eth_dev *dev,
 	if (flow == NULL)
 		goto fail_no_mem;
 
+	sfc_adapter_lock(sa);
+
 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
 	if (rc != 0)
 		goto fail_bad_value;
 
-	sfc_adapter_lock(sa);
-
 	TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
 
 	if (sa->state == SFC_ADAPTER_STARTED) {
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index e991ae132c..09105953ff 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -67,6 +67,8 @@ struct sfc_flow_spec_filter {
 struct sfc_flow_spec_mae {
 	/* Desired priority level */
 	unsigned int			priority;
+	/* Outer rule registry entry */
+	struct sfc_mae_outer_rule	*outer_rule;
 	/* EFX match specification */
 	efx_mae_match_spec_t		*match_spec;
 	/* Action set registry entry */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 3dd233c6dc..c78a376a88 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -81,7 +81,10 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		goto fail_mae_assign_switch_port;
 
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
+	mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
+	mae->encap_types_supported = limits.eml_encap_types_supported;
+	TAILQ_INIT(&mae->outer_rules);
 	TAILQ_INIT(&mae->action_sets);
 
 	sfc_log_init(sa, "done");
@@ -119,6 +122,138 @@ sfc_mae_detach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "done");
 }
 
+static struct sfc_mae_outer_rule *
+sfc_mae_outer_rule_attach(struct sfc_adapter *sa,
+			  const efx_mae_match_spec_t *match_spec,
+			  efx_tunnel_protocol_t encap_type)
+{
+	struct sfc_mae_outer_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	TAILQ_FOREACH(rule, &mae->outer_rules, entries) {
+		if (efx_mae_match_specs_equal(rule->match_spec, match_spec) &&
+		    rule->encap_type == encap_type) {
+			++(rule->refcnt);
+			return rule;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+sfc_mae_outer_rule_add(struct sfc_adapter *sa,
+		       efx_mae_match_spec_t *match_spec,
+		       efx_tunnel_protocol_t encap_type,
+		       struct sfc_mae_outer_rule **rulep)
+{
+	struct sfc_mae_outer_rule *rule;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	rule = rte_zmalloc("sfc_mae_outer_rule", sizeof(*rule), 0);
+	if (rule == NULL)
+		return ENOMEM;
+
+	rule->refcnt = 1;
+	rule->match_spec = match_spec;
+	rule->encap_type = encap_type;
+
+	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	TAILQ_INSERT_TAIL(&mae->outer_rules, rule, entries);
+
+	*rulep = rule;
+
+	return 0;
+}
+
+static void
+sfc_mae_outer_rule_del(struct sfc_adapter *sa,
+		       struct sfc_mae_outer_rule *rule)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(rule->refcnt != 0);
+
+	--(rule->refcnt);
+
+	if (rule->refcnt != 0)
+		return;
+
+	SFC_ASSERT(rule->fw_rsrc.rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(rule->fw_rsrc.refcnt == 0);
+
+	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
+
+	TAILQ_REMOVE(&mae->outer_rules, rule, entries);
+	rte_free(rule);
+}
+
+static int
+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;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+		SFC_ASSERT(rule->match_spec != NULL);
+
+		rc = efx_mae_outer_rule_insert(sa->nic, rule->match_spec,
+					       rule->encap_type,
+					       &fw_rsrc->rule_id);
+		if (rc != 0)
+			return rc;
+	}
+
+	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
+						  &fw_rsrc->rule_id);
+	if (rc != 0) {
+		if (fw_rsrc->refcnt == 0) {
+			(void)efx_mae_outer_rule_remove(sa->nic,
+							&fw_rsrc->rule_id);
+		}
+		return rc;
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static int
+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;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_outer_rule_remove(sa->nic, &fw_rsrc->rule_id);
+		if (rc != 0)
+			return rc;
+
+		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+	}
+
+	--(fw_rsrc->refcnt);
+
+	return 0;
+}
+
 static struct sfc_mae_action_set *
 sfc_mae_action_set_attach(struct sfc_adapter *sa,
 			  const efx_mae_actions_t *spec)
@@ -253,6 +388,9 @@ 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);
 
@@ -263,8 +401,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 static int
 sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
 {
-	efx_mae_match_spec_t *efx_spec = ctx->match_spec_action;
 	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
+	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
 	const efx_mae_field_id_t field_ids[] = {
 		EFX_MAE_FIELD_VLAN0_PROTO_BE,
 		EFX_MAE_FIELD_VLAN1_PROTO_BE,
@@ -279,7 +417,8 @@ sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
 	 * no L3 item, it's 0x0000/0x0000.
 	 */
 	et = &pdata->ethertypes[pdata->nb_vlan_tags];
-	rc = efx_mae_match_spec_field_set(efx_spec, EFX_MAE_FIELD_ETHER_TYPE_BE,
+	rc = efx_mae_match_spec_field_set(ctx->match_spec,
+					  fremap[EFX_MAE_FIELD_ETHER_TYPE_BE],
 					  sizeof(et->value),
 					  (const uint8_t *)&et->value,
 					  sizeof(et->mask),
@@ -296,7 +435,8 @@ sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
 	for (i = 0; i < pdata->nb_vlan_tags; ++i) {
 		et = &pdata->ethertypes[i];
 
-		rc = efx_mae_match_spec_field_set(efx_spec, field_ids[i],
+		rc = efx_mae_match_spec_field_set(ctx->match_spec,
+						  fremap[field_ids[i]],
 						  sizeof(et->value),
 						  (const uint8_t *)&et->value,
 						  sizeof(et->mask),
@@ -312,7 +452,7 @@ static int
 sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 				  struct rte_flow_error *error)
 {
-	efx_mae_match_spec_t *efx_spec = ctx->match_spec_action;
+	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
 	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
 	struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
 	const rte_be16_t supported_tpids[] = {
@@ -411,7 +551,8 @@ sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
 
 	valuep = (const uint8_t *)&pdata->l3_next_proto_value;
 	maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
-	rc = efx_mae_match_spec_field_set(efx_spec, EFX_MAE_FIELD_IP_PROTO,
+	rc = efx_mae_match_spec_field_set(ctx->match_spec,
+					  fremap[EFX_MAE_FIELD_IP_PROTO],
 					  sizeof(pdata->l3_next_proto_value),
 					  valuep,
 					  sizeof(pdata->l3_next_proto_mask),
@@ -478,7 +619,7 @@ sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
 				"Can't find RTE ethdev by the port ID");
 	}
 
-	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
 					  &mport_sel, NULL);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
@@ -536,8 +677,7 @@ sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 				"Failed to convert the PHY_PORT index");
 	}
 
-	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
-					  &mport_v, NULL);
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -573,8 +713,7 @@ sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
 				"Failed to convert the PF ID");
 	}
 
-	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
-					  &mport_v, NULL);
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -639,8 +778,7 @@ sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
 				"Failed to convert the PF + VF IDs");
 	}
 
-	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
-					  &mport_v, NULL);
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
 	if (rc != 0) {
 		return rte_flow_error_set(error, rc,
 				RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -689,9 +827,10 @@ sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
 static int
 sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
 		   unsigned int nb_field_locators, const uint8_t *spec,
-		   const uint8_t *mask, efx_mae_match_spec_t *efx_spec,
+		   const uint8_t *mask, struct sfc_mae_parse_ctx *ctx,
 		   struct rte_flow_error *error)
 {
+	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
 	unsigned int i;
 	int rc = 0;
 
@@ -701,7 +840,8 @@ sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
 		if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED)
 			continue;
 
-		rc = efx_mae_match_spec_field_set(efx_spec, fl->field_id,
+		rc = efx_mae_match_spec_field_set(ctx->match_spec,
+						  fremap[fl->field_id],
 						  fl->size, spec + fl->ofst,
 						  fl->size, mask + fl->ofst);
 		if (rc != 0)
@@ -782,7 +922,7 @@ sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
 	}
 
 	return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
-				  ctx_mae->match_spec_action, error);
+				  ctx_mae, error);
 }
 
 static const struct sfc_mae_field_locator flocs_vlan[] = {
@@ -878,8 +1018,7 @@ sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
 		return 0;
 	}
 
-	return sfc_mae_parse_item(flocs, nb_flocs, spec, mask,
-				  ctx_mae->match_spec_action, error);
+	return sfc_mae_parse_item(flocs, nb_flocs, spec, mask, ctx_mae, error);
 }
 
 static const struct sfc_mae_field_locator flocs_ipv4[] = {
@@ -956,7 +1095,7 @@ sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
 	}
 
 	return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask,
-				  ctx_mae->match_spec_action, error);
+				  ctx_mae, error);
 }
 
 static const struct sfc_mae_field_locator flocs_ipv6[] = {
@@ -993,6 +1132,7 @@ sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
 {
 	rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap;
 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
 	struct rte_flow_item_ipv6 supp_mask;
 	const uint8_t *spec = NULL;
@@ -1034,7 +1174,7 @@ sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
 	}
 
 	rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
-				ctx_mae->match_spec_action, error);
+				ctx_mae, error);
 	if (rc != 0)
 		return rc;
 
@@ -1046,8 +1186,8 @@ sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
 	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
 	tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
 
-	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec_action,
-					  EFX_MAE_FIELD_IP_TOS,
+	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
+					  fremap[EFX_MAE_FIELD_IP_TOS],
 					  sizeof(tc_value), &tc_value,
 					  sizeof(tc_mask), &tc_mask);
 	if (rc != 0) {
@@ -1094,6 +1234,16 @@ sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
 	const uint8_t *mask = NULL;
 	int rc;
 
+	/*
+	 * When encountered among outermost items, item TCP is invalid.
+	 * Check which match specification is being constructed now.
+	 */
+	if (ctx_mae->match_spec != ctx_mae->match_spec_action) {
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "TCP in outer frame is invalid");
+	}
+
 	sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp),
 				     &supp_mask, sizeof(supp_mask));
 
@@ -1112,7 +1262,7 @@ sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
 		return 0;
 
 	return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask,
-				  ctx_mae->match_spec_action, error);
+				  ctx_mae, error);
 }
 
 static const struct sfc_mae_field_locator flocs_udp[] = {
@@ -1158,7 +1308,157 @@ sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item,
 		return 0;
 
 	return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask,
-				  ctx_mae->match_spec_action, error);
+				  ctx_mae, error);
+}
+
+static const struct sfc_mae_field_locator flocs_tunnel[] = {
+	{
+		/*
+		 * The size and offset values are relevant
+		 * for Geneve and NVGRE, too.
+		 */
+		.size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, vni),
+		.ofst = offsetof(struct rte_flow_item_vxlan, vni),
+	},
+};
+
+/*
+ * An auxiliary registry which allows using non-encap. field IDs
+ * directly when building a match specification of type ACTION.
+ *
+ * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel().
+ */
+static const efx_mae_field_id_t field_ids_no_remap[] = {
+#define FIELD_ID_NO_REMAP(_field) \
+	[EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field
+
+	FIELD_ID_NO_REMAP(ETHER_TYPE_BE),
+	FIELD_ID_NO_REMAP(ETH_SADDR_BE),
+	FIELD_ID_NO_REMAP(ETH_DADDR_BE),
+	FIELD_ID_NO_REMAP(VLAN0_TCI_BE),
+	FIELD_ID_NO_REMAP(VLAN0_PROTO_BE),
+	FIELD_ID_NO_REMAP(VLAN1_TCI_BE),
+	FIELD_ID_NO_REMAP(VLAN1_PROTO_BE),
+	FIELD_ID_NO_REMAP(SRC_IP4_BE),
+	FIELD_ID_NO_REMAP(DST_IP4_BE),
+	FIELD_ID_NO_REMAP(IP_PROTO),
+	FIELD_ID_NO_REMAP(IP_TOS),
+	FIELD_ID_NO_REMAP(IP_TTL),
+	FIELD_ID_NO_REMAP(SRC_IP6_BE),
+	FIELD_ID_NO_REMAP(DST_IP6_BE),
+	FIELD_ID_NO_REMAP(L4_SPORT_BE),
+	FIELD_ID_NO_REMAP(L4_DPORT_BE),
+	FIELD_ID_NO_REMAP(TCP_FLAGS_BE),
+
+#undef FIELD_ID_NO_REMAP
+};
+
+/*
+ * An auxiliary registry which allows using "ENC" field IDs
+ * when building a match specification of type OUTER.
+ *
+ * See sfc_mae_rule_encap_parse_init().
+ */
+static const efx_mae_field_id_t field_ids_remap_to_encap[] = {
+#define FIELD_ID_REMAP_TO_ENCAP(_field) \
+	[EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field
+
+	FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE),
+	FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE),
+	FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE),
+	FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE),
+	FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE),
+	FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE),
+	FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE),
+	FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE),
+	FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE),
+	FIELD_ID_REMAP_TO_ENCAP(IP_PROTO),
+	FIELD_ID_REMAP_TO_ENCAP(IP_TOS),
+	FIELD_ID_REMAP_TO_ENCAP(IP_TTL),
+	FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE),
+	FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE),
+	FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE),
+	FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE),
+
+#undef FIELD_ID_REMAP_TO_ENCAP
+};
+
+static int
+sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item,
+			       struct sfc_flow_parse_ctx *ctx,
+			       struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	uint8_t vnet_id_v[sizeof(uint32_t)] = {0};
+	uint8_t vnet_id_m[sizeof(uint32_t)] = {0};
+	const struct rte_flow_item_vxlan *vxp;
+	uint8_t supp_mask[sizeof(uint64_t)];
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	const void *def_mask;
+	int rc;
+
+	/*
+	 * We're about to start processing inner frame items.
+	 * Process pattern data that has been deferred so far
+	 * and reset pattern data storage.
+	 */
+	rc = sfc_mae_rule_process_pattern_data(ctx_mae, error);
+	if (rc != 0)
+		return rc;
+
+	memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data));
+
+	sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel),
+				     &supp_mask, sizeof(supp_mask));
+
+	/*
+	 * This tunnel item was preliminarily detected by
+	 * sfc_mae_rule_encap_parse_init(). Default mask
+	 * was also picked by that helper. Use it here.
+	 */
+	def_mask = ctx_mae->tunnel_def_mask;
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(def_mask), error);
+	if (rc != 0)
+		return rc;
+
+	/*
+	 * This item and later ones comprise a
+	 * match specification of type ACTION.
+	 */
+	ctx_mae->match_spec = ctx_mae->match_spec_action;
+
+	/* This item and later ones use non-encap. EFX MAE field IDs. */
+	ctx_mae->field_ids_remap = field_ids_no_remap;
+
+	if (spec == NULL)
+		return 0;
+
+	/*
+	 * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one.
+	 * Copy 24-bit VNI, which is BE, at offset 1 in it.
+	 * The extra byte is 0 both in the mask and in the value.
+	 */
+	vxp = (const struct rte_flow_item_vxlan *)spec;
+	memcpy(vnet_id_v + 1, &vxp->vni, sizeof(vxp->vni));
+
+	vxp = (const struct rte_flow_item_vxlan *)mask;
+	memcpy(vnet_id_m + 1, &vxp->vni, sizeof(vxp->vni));
+
+	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
+					  EFX_MAE_FIELD_ENC_VNET_ID_BE,
+					  sizeof(vnet_id_v), vnet_id_v,
+					  sizeof(vnet_id_m), vnet_id_m);
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
+					item, "Failed to set VXLAN VNI");
+	}
+
+	return rc;
 }
 
 static const struct sfc_flow_item sfc_flow_items[] = {
@@ -1248,8 +1548,178 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_udp,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_VXLAN,
+		.prev_layer = SFC_FLOW_ITEM_L4,
+		.layer = SFC_FLOW_ITEM_START_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_tunnel,
+	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_GENEVE,
+		.prev_layer = SFC_FLOW_ITEM_L4,
+		.layer = SFC_FLOW_ITEM_START_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_tunnel,
+	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_NVGRE,
+		.prev_layer = SFC_FLOW_ITEM_L3,
+		.layer = SFC_FLOW_ITEM_START_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_tunnel,
+	},
 };
 
+static int
+sfc_mae_rule_process_outer(struct sfc_adapter *sa,
+			   struct sfc_mae_parse_ctx *ctx,
+			   struct sfc_mae_outer_rule **rulep,
+			   struct rte_flow_error *error)
+{
+	struct sfc_mae_outer_rule *rule;
+	int rc;
+
+	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
+		*rulep = NULL;
+		return 0;
+	}
+
+	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,
+					  "Inconsistent pattern (outer)");
+	}
+
+	*rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer,
+					   ctx->encap_type);
+	if (*rulep != NULL) {
+		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
+	} else {
+		rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer,
+					    ctx->encap_type, rulep);
+		if (rc != 0) {
+			return rte_flow_error_set(error, rc,
+					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					"Failed to process the pattern");
+		}
+	}
+
+	/*
+	 * Depending on whether we reuse an existing outer rule or create a
+	 * new one (see above), outer rule ID is either a valid value or
+	 * EFX_MAE_RSRC_ID_INVALID. Set it in the action rule match
+	 * specification (and the full mask, too) in order to have correct
+	 * class comparisons of the new rule with existing ones.
+	 * Also, action rule match specification will be validated shortly,
+	 * and having the full mask set for outer rule ID indicates that we
+	 * will use this field, and support for this field has to be checked.
+	 */
+	rule = *rulep;
+	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
+						  &rule->fw_rsrc.rule_id);
+	if (rc != 0) {
+		sfc_mae_outer_rule_del(sa, *rulep);
+		*rulep = NULL;
+
+		return rte_flow_error_set(error, rc,
+					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					  "Failed to process the pattern");
+	}
+
+	return 0;
+}
+
+static int
+sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
+			      const struct rte_flow_item pattern[],
+			      struct sfc_mae_parse_ctx *ctx,
+			      struct rte_flow_error *error)
+{
+	struct sfc_mae *mae = &sa->mae;
+	int rc;
+
+	if (pattern == NULL) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
+				   "NULL pattern");
+		return -rte_errno;
+	}
+
+	for (;;) {
+		switch (pattern->type) {
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
+			ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask;
+			RTE_BUILD_BUG_ON(sizeof(ctx->tunnel_def_mask) !=
+					 sizeof(rte_flow_item_vxlan_mask));
+			break;
+		case RTE_FLOW_ITEM_TYPE_GENEVE:
+			ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
+			ctx->tunnel_def_mask = &rte_flow_item_geneve_mask;
+			RTE_BUILD_BUG_ON(sizeof(ctx->tunnel_def_mask) !=
+					 sizeof(rte_flow_item_geneve_mask));
+			break;
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+			ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
+			ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask;
+			RTE_BUILD_BUG_ON(sizeof(ctx->tunnel_def_mask) !=
+					 sizeof(rte_flow_item_nvgre_mask));
+			break;
+		case RTE_FLOW_ITEM_TYPE_END:
+			break;
+		default:
+			++pattern;
+			continue;
+		};
+
+		break;
+	}
+
+	if (pattern->type == RTE_FLOW_ITEM_TYPE_END)
+		return 0;
+
+	if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) {
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
+					  pattern, "Unsupported tunnel item");
+	}
+
+	if (ctx->priority >= mae->nb_outer_rule_prios_max) {
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+					  NULL, "Unsupported priority level");
+	}
+
+	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_OUTER, ctx->priority,
+				     &ctx->match_spec_outer);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_ITEM, pattern,
+			"Failed to initialise outer rule match specification");
+	}
+
+	/* Outermost items comprise a match specification of type OUTER. */
+	ctx->match_spec = ctx->match_spec_outer;
+
+	/* Outermost items use "ENC" EFX MAE field IDs. */
+	ctx->field_ids_remap = field_ids_remap_to_encap;
+
+	return 0;
+}
+
+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;
+
+	efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
+}
+
 int
 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 			   const struct rte_flow_item pattern[],
@@ -1261,6 +1731,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	int rc;
 
 	memset(&ctx_mae, 0, sizeof(ctx_mae));
+	ctx_mae.priority = spec->priority;
 	ctx_mae.sa = sa;
 
 	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
@@ -1273,9 +1744,24 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 		goto fail_init_match_spec_action;
 	}
 
+	/*
+	 * As a preliminary setting, assume that there is no encapsulation
+	 * in the pattern. That is, pattern items are about to comprise a
+	 * match specification of type ACTION and use non-encap. field IDs.
+	 *
+	 * sfc_mae_rule_encap_parse_init() below may override this.
+	 */
+	ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE;
+	ctx_mae.match_spec = ctx_mae.match_spec_action;
+	ctx_mae.field_ids_remap = field_ids_no_remap;
+
 	ctx.type = SFC_FLOW_PARSE_CTX_MAE;
 	ctx.mae = &ctx_mae;
 
+	rc = sfc_mae_rule_encap_parse_init(sa, pattern, &ctx_mae, error);
+	if (rc != 0)
+		goto fail_encap_parse_init;
+
 	rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
 				    pattern, &ctx, error);
 	if (rc != 0)
@@ -1285,6 +1771,10 @@ 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);
+	if (rc != 0)
+		goto fail_process_outer;
+
 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
 		rc = rte_flow_error_set(error, ENOTSUP,
 					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
@@ -1297,8 +1787,12 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	return 0;
 
 fail_validate_match_spec_action:
+fail_process_outer:
 fail_process_pattern_data:
 fail_parse_pattern:
+	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
+
+fail_encap_parse_init:
 	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
 
 fail_init_match_spec_action:
@@ -1670,6 +2164,37 @@ sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
 	return (rc == 0) ? have_same_class : false;
 }
 
+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 *mae = &sa->mae;
+
+	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
+		/* An active rule is reused. It's class is wittingly valid. */
+		return 0;
+	}
+
+	TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules,
+			      sfc_mae_outer_rules, entries) {
+		const efx_mae_match_spec_t *left = entry->match_spec;
+		const efx_mae_match_spec_t *right = rule->match_spec;
+
+		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 "
+		 "support for outer frame pattern items is not guaranteed; "
+		 "other than that, the items are valid from SW standpoint");
+	return 0;
+}
+
 static int
 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
 				 struct sfc_flow_spec_mae *spec)
@@ -1722,12 +2247,20 @@ 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_outer_rule *outer_rule = spec_mae->outer_rule;
+	int rc;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	if (sa->state != SFC_ADAPTER_STARTED)
 		return EAGAIN;
 
+	if (outer_rule != NULL) {
+		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);
 }
 
@@ -1737,6 +2270,7 @@ 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 = &action_set->fw_rsrc;
 	int rc;
@@ -1744,6 +2278,13 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
 	SFC_ASSERT(action_set != NULL);
 
+	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;
+	}
+
 	rc = sfc_mae_action_set_enable(sa, action_set);
 	if (rc != 0)
 		goto fail_action_set_enable;
@@ -1760,6 +2301,10 @@ sfc_mae_flow_insert(struct sfc_adapter *sa,
 	(void)sfc_mae_action_set_disable(sa, action_set);
 
 fail_action_set_enable:
+	if (outer_rule != NULL)
+		(void)sfc_mae_outer_rule_disable(sa, outer_rule);
+
+fail_outer_rule_enable:
 	return rc;
 }
 
@@ -1770,6 +2315,7 @@ 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;
 
 	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
@@ -1781,5 +2327,14 @@ sfc_mae_flow_remove(struct sfc_adapter *sa,
 
 	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
 
-	return sfc_mae_action_set_disable(sa, action_set);
+	rc = sfc_mae_action_set_disable(sa, action_set);
+	if (rc != 0) {
+		sfc_err(sa, "failed to disable the action set (rc = %d)", rc);
+		/* Despite the error, proceed with outer rule removal. */
+	}
+
+	if (outer_rule != NULL)
+		return sfc_mae_outer_rule_disable(sa, outer_rule);
+
+	return 0;
 }
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 8d9b4039f3..53ddead979 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -26,9 +26,21 @@ struct sfc_mae_fw_rsrc {
 	RTE_STD_C11
 	union {
 		efx_mae_aset_id_t	aset_id;
+		efx_mae_rule_id_t	rule_id;
 	};
 };
 
+/** Outer rule registry entry */
+struct sfc_mae_outer_rule {
+	TAILQ_ENTRY(sfc_mae_outer_rule)	entries;
+	unsigned int			refcnt;
+	efx_mae_match_spec_t		*match_spec;
+	efx_tunnel_protocol_t		encap_type;
+	struct sfc_mae_fw_rsrc		fw_rsrc;
+};
+
+TAILQ_HEAD(sfc_mae_outer_rules, sfc_mae_outer_rule);
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
@@ -53,8 +65,14 @@ struct sfc_mae {
 	uint16_t			switch_port_id;
 	/** NIC support for MAE status */
 	enum sfc_mae_status		status;
+	/** Priority level limit for MAE outer rules */
+	unsigned int			nb_outer_rule_prios_max;
 	/** Priority level limit for MAE action rules */
 	unsigned int			nb_action_rule_prios_max;
+	/** Encapsulation support status */
+	uint32_t			encap_types_supported;
+	/** Outer rule registry */
+	struct sfc_mae_outer_rules	outer_rules;
 	/** Action set registry */
 	struct sfc_mae_action_sets	action_sets;
 };
@@ -149,8 +167,24 @@ struct sfc_mae_pattern_data {
 struct sfc_mae_parse_ctx {
 	struct sfc_adapter		*sa;
 	efx_mae_match_spec_t		*match_spec_action;
+	efx_mae_match_spec_t		*match_spec_outer;
+	/*
+	 * This points to either of the above two specifications depending
+	 * on which part of the pattern is being parsed (outer / inner).
+	 */
+	efx_mae_match_spec_t		*match_spec;
+	/*
+	 * This points to either "field_ids_remap_to_encap"
+	 * or "field_ids_no_remap" (see sfc_mae.c) depending on
+	 * which part of the pattern is being parsed.
+	 */
+	const efx_mae_field_id_t	*field_ids_remap;
+	/* This points to a tunnel-specific default mask. */
+	const void			*tunnel_def_mask;
 	bool				match_mport_set;
 	struct sfc_mae_pattern_data	pattern_data;
+	efx_tunnel_protocol_t		encap_type;
+	unsigned int			priority;
 };
 
 int sfc_mae_attach(struct sfc_adapter *sa);
-- 
2.17.1


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

* [dpdk-dev] [PATCH 62/62] doc: advertise flow API transfer rules support in net/sfc
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (60 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 61/62] net/sfc: support encap. flow items in transfer rules Andrew Rybchenko
@ 2020-10-20  8:48 ` Andrew Rybchenko
  2020-10-20  8:55 ` [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:48 UTC (permalink / raw)
  To: y; +Cc: dev

Transfer rules support matching on various inner and outer packet
headers, traffic source items like PORT_ID, PHY_PORT, PF and VF and
actions to route traffic to destination (PORT_ID, PHY_PORT, PF, VF or
DROP), MARK, FLAG and apply VLAN push/pop transformations.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 doc/guides/rel_notes/release_20_11.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 278d8dd0d4..b91524ee59 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -165,7 +165,8 @@ New Features
   Updated the Solarflare ``sfc_efx`` driver with changes including:
 
   * Added SR-IOV PF support
-  * Added Alveo SN1000 SmartNICs (EF100 architecture) support
+  * Added Alveo SN1000 SmartNICs (EF100 architecture) support including
+    flow API transfer rules for switch HW offload
 
 * **Updated Virtio driver.**
 
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (61 preceding siblings ...)
  2020-10-20  8:48 ` [dpdk-dev] [PATCH 62/62] doc: advertise flow API transfer rules support in net/sfc Andrew Rybchenko
@ 2020-10-20  8:55 ` Andrew Rybchenko
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
  63 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  8:55 UTC (permalink / raw)
  To: dev

On 10/20/20 11:47 AM, Andrew Rybchenko wrote:
> Transfer rules for Alveo SN1000 SmartNICs support matching on various
> inner and outer packet headers, traffic source items like PORT_ID,
> PHY_PORT, PF and VF and actions to route traffic to destination
> (PORT_ID, PHY_PORT, PF, VF or DROP), MARK, FLAG and apply VLAN
> push/pop transformations.

I'm sorry, no enough coffee this morning and weird To in the
patch series. Will send v2 with correct destination.


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

* [dpdk-dev] [PATCH v2 00/62] net/sfc: support flow API transfer rules
  2020-10-20  8:47 [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
                   ` (62 preceding siblings ...)
  2020-10-20  8:55 ` [dpdk-dev] [PATCH 00/62] net/sfc: support flow API transfer rules Andrew Rybchenko
@ 2020-10-20  9:12 ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
                     ` (62 more replies)
  63 siblings, 63 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev

Transfer rules for Alveo SN1000 SmartNICs support matching on various
inner and outer packet headers, traffic source items like PORT_ID,
PHY_PORT, PF and VF and actions to route traffic to destination
(PORT_ID, PHY_PORT, PF, VF or DROP), MARK, FLAG and apply VLAN
push/pop transformations.


Andrew Rybchenko (2):
  common/sfc_efx/base: add MAE definitions to MCDI
  doc: advertise flow API transfer rules support in net/sfc

Ivan Malov (60):
  common/sfc_efx/base: indicate support for MAE
  net/sfc: add a stub for attaching to MAE
  common/sfc_efx/base: add MAE init/fini APIs
  drivers: init/fini MAE on attach/detach
  common/sfc_efx/base: add an MAE limit query API
  net/sfc: add the concept of MAE (transfer) rules
  common/sfc_efx/base: add match spec init/fini APIs
  net/sfc: add pattern parsing stub to MAE backend
  common/sfc_efx/base: add a match spec validate API
  net/sfc: validate match spec in MAE backend
  common/sfc_efx/base: add a match specs class comparison API
  net/sfc: add verify method to flow validate path
  common/sfc_efx/base: add action set spec init/fini APIs
  net/sfc: add actions parsing stub to MAE backend
  common/sfc_efx/base: support setting a PPORT in a match spec
  net/sfc: support flow item PHY PORT in MAE backend
  common/sfc_efx/base: add MAE match fields for Ethernet
  net/sfc: support flow item ETH in MAE backend
  common/sfc_efx/base: support adding DELIVER action to a set
  net/sfc: support flow action PHY PORT in MAE backend
  common/sfc_efx/base: add MAE action set provisioning APIs
  common/sfc_efx/base: add MAE action rule provisioning APIs
  net/sfc: implement flow insert/remove in MAE backend
  common/sfc_efx/base: support adding VLAN POP action to a set
  net/sfc: support flow action OF POP VLAN in MAE backend
  common/sfc_efx/base: support adding VLAN PUSH action
  net/sfc: add facilities to handle bundles of actions
  net/sfc: support VLAN PUSH actions in MAE backend
  common/sfc_efx/base: support adding FLAG action to a set
  net/sfc: support flow action FLAG in MAE backend
  common/sfc_efx/base: support adding MARK action to a set
  net/sfc: support flow action MARK in MAE backend
  common/sfc_efx/base: add named constant for invalid VF
  common/sfc_efx/base: add an API to get MPORT of a PF/VF
  net/sfc: support flow items PF and VF in transfer rules
  net/sfc: support flow actions PF and VF in transfer rules
  common/sfc_efx/base: add an API for adding action DROP
  net/sfc: support flow action DROP in transfer rules
  common/sfc_efx/base: refactor version / boot info get helper
  common/sfc_efx/base: add an API for querying board info
  net/sfc: add HW switch ID helpers
  net/sfc: support the concept of RTE switch domains/ports
  net/sfc: support flow action PORT ID in transfer rules
  net/sfc: support flow item PORT ID in transfer rules
  common/sfc_efx/base: add MAE match fields for VLAN
  net/sfc: support flow item VLAN in transfer rules
  common/sfc_efx/base: add MAE match fields for IPv4
  net/sfc: support flow item IPV4 in transfer rules
  common/sfc_efx/base: add MAE match fields for IPv6
  net/sfc: support flow item IPV6 in transfer rules
  common/sfc_efx/base: add MAE match fields for TCP and UDP
  net/sfc: support flow item TCP in transfer rules
  net/sfc: support flow item UDP in transfer rules
  common/sfc_efx/base: indicate MAE support for encapsulation
  common/sfc_efx/base: add MAE encap. match fields
  common/sfc_efx/base: add MAE match field VNET ID for tunnels
  common/sfc_efx/base: add an API to compare match specs
  common/sfc_efx/base: validate and compare outer match specs
  common/sfc_efx/base: support outer rule provisioning
  net/sfc: support encap. flow items in transfer rules

 doc/guides/nics/sfc_efx.rst                   |   59 +-
 doc/guides/rel_notes/release_20_11.rst        |    3 +-
 drivers/common/sfc_efx/base/ef10_nic.c        |   15 +
 drivers/common/sfc_efx/base/efx.h             |  337 ++-
 drivers/common/sfc_efx/base/efx_check.h       |    6 +
 drivers/common/sfc_efx/base/efx_impl.h        |   86 +
 drivers/common/sfc_efx/base/efx_mae.c         | 1906 ++++++++++++++
 drivers/common/sfc_efx/base/efx_mcdi.c        |  194 +-
 drivers/common/sfc_efx/base/efx_mcdi.h        |   34 +
 drivers/common/sfc_efx/base/efx_nic.c         |   46 +
 drivers/common/sfc_efx/base/efx_regs_mcdi.h   | 2232 ++++++++++++++++
 drivers/common/sfc_efx/base/meson.build       |    1 +
 drivers/common/sfc_efx/base/siena_nic.c       |    2 +
 drivers/common/sfc_efx/efsys.h                |    2 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |   30 +
 drivers/net/sfc/meson.build                   |    2 +
 drivers/net/sfc/sfc.c                         |   52 +
 drivers/net/sfc/sfc.h                         |   10 +
 drivers/net/sfc/sfc_ethdev.c                  |    7 +
 drivers/net/sfc/sfc_flow.c                    |  124 +-
 drivers/net/sfc/sfc_flow.h                    |   30 +
 drivers/net/sfc/sfc_mae.c                     | 2340 +++++++++++++++++
 drivers/net/sfc/sfc_mae.h                     |  208 ++
 drivers/net/sfc/sfc_switch.c                  |  334 +++
 drivers/net/sfc/sfc_switch.h                  |   53 +
 25 files changed, 8039 insertions(+), 74 deletions(-)
 create mode 100644 drivers/common/sfc_efx/base/efx_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.h
 create mode 100644 drivers/net/sfc/sfc_switch.c
 create mode 100644 drivers/net/sfc/sfc_switch.h

-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 01/62] common/sfc_efx/base: add MAE definitions to MCDI
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 02/62] common/sfc_efx/base: indicate support for MAE Andrew Rybchenko
                     ` (61 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev

MAE stands for Match-Action-Engine and will be used to
support rte_flow API transfer rules.

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/common/sfc_efx/base/efx_regs_mcdi.h | 2232 +++++++++++++++++++
 1 file changed, 2232 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx_regs_mcdi.h b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
index f31a25e4ff..7125d053e8 100644
--- a/drivers/common/sfc_efx/base/efx_regs_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_regs_mcdi.h
@@ -410,6 +410,151 @@
 #define	MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff
 #define	MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */
 
+/* MAE_FIELD_SUPPORT_STATUS enum */
+/* enum: The NIC does not support this field. The driver must ensure that any
+ * mask associated with this field in a match rule is zeroed. The NIC may
+ * either reject requests with an invalid mask for such a field, or may assume
+ * that the mask is zero. (This category only exists to describe behaviour for
+ * fields that a newer driver might know about but that older firmware does
+ * not. It is recommended that firmware report MAE_FIELD_FIELD_MATCH_NEVER for
+ * all match fields defined at the time of its compilation. If a driver see a
+ * field support status value that it does not recognise, it must treat that
+ * field as thought the field was reported as MAE_FIELD_SUPPORTED_MATCH_NEVER,
+ * and must never set a non-zero mask value for this field.
+ */
+#define	MAE_FIELD_UNSUPPORTED 0x0
+/* enum: The NIC supports this field, but cannot use it in a match rule. The
+ * driver must ensure that any mask for such a field in a match rule is zeroed.
+ * The NIC will reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_NEVER 0x1
+/* enum: The NIC supports this field, and must use it in all match rules. The
+ * driver must ensure that any mask for such a field is all ones. The NIC will
+ * reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_ALWAYS 0x2
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver must ensure that any mask for such a field is either all zeroes
+ * or all ones. The NIC will reject requests with an invalid mask for such a
+ * field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_OPTIONAL 0x3
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver must ensure that any mask for such a field is either all zeroes
+ * or a consecutive set of ones following by all zeroes (starting from MSB).
+ * The NIC will reject requests with an invalid mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_PREFIX 0x4
+/* enum: The NIC supports this field, and may optionally use it in match rules.
+ * The driver may provide an arbitrary mask for such a field.
+ */
+#define	MAE_FIELD_SUPPORTED_MATCH_MASK 0x5
+
+/* MAE_FIELD enum: NB: this enum shares namespace with the support status enum.
+ */
+/* enum: Source mport upon entering the MAE. */
+#define	MAE_FIELD_INGRESS_PORT 0x0
+#define	MAE_FIELD_MARK 0x1 /* enum */
+/* enum: Table ID used in action rule. Initially zero, can be changed in action
+ * rule response.
+ */
+#define	MAE_FIELD_RECIRC_ID 0x2
+#define	MAE_FIELD_IS_IP_FRAG 0x3 /* enum */
+#define	MAE_FIELD_DO_CT 0x4 /* enum */
+#define	MAE_FIELD_CT_HIT 0x5 /* enum */
+/* enum: Undefined unless CT_HIT=1. */
+#define	MAE_FIELD_CT_MARK 0x6
+/* enum: Undefined unless DO_CT=1. */
+#define	MAE_FIELD_CT_DOMAIN 0x7
+/* enum: Undefined unless CT_HIT=1. */
+#define	MAE_FIELD_CT_PRIVATE_FLAGS 0x8
+/* enum: 1 if the packet ingressed the NIC from one of the MACs, else 0. */
+#define	MAE_FIELD_IS_FROM_NETWORK 0x9
+#define	MAE_FIELD_ETHER_TYPE 0x21 /* enum */
+#define	MAE_FIELD_VLAN0_TCI 0x22 /* enum */
+#define	MAE_FIELD_VLAN0_PROTO 0x23 /* enum */
+#define	MAE_FIELD_VLAN1_TCI 0x24 /* enum */
+#define	MAE_FIELD_VLAN1_PROTO 0x25 /* enum */
+/* enum: Inner when encap */
+#define	MAE_FIELD_ETH_SADDR 0x28
+/* enum: Inner when encap */
+#define	MAE_FIELD_ETH_DADDR 0x29
+/* enum: Inner when encap. NB: IPv4 and IPv6 fields are mutually exclusive. */
+#define	MAE_FIELD_SRC_IP4 0x2a
+/* enum: Inner when encap */
+#define	MAE_FIELD_SRC_IP6 0x2b
+/* enum: Inner when encap */
+#define	MAE_FIELD_DST_IP4 0x2c
+/* enum: Inner when encap */
+#define	MAE_FIELD_DST_IP6 0x2d
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_PROTO 0x2e
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_TOS 0x2f
+/* enum: Inner when encap */
+#define	MAE_FIELD_IP_TTL 0x30
+/* enum: Inner when encap TODO: how this is defined? The raw flags +
+ * frag_offset from the packet, or some derived value more amenable to ternary
+ * matching? TODO: there was a proposal for driver-allocation fields. The
+ * driver would provide some instruction for how to extract given field values,
+ * and would be given a field id in return. It could then use that field id in
+ * its matches. This feels like it would be extremely hard to implement in
+ * hardware, but I mention it for completeness.
+ */
+#define	MAE_FIELD_IP_FLAGS 0x31
+/* enum: Ports (UDP, TCP) Inner when encap */
+#define	MAE_FIELD_L4_SPORT 0x32
+/* enum: Ports (UDP, TCP) Inner when encap */
+#define	MAE_FIELD_L4_DPORT 0x33
+/* enum: Inner when encap */
+#define	MAE_FIELD_TCP_FLAGS 0x34
+/* enum: The type of encapsulated used for this packet. Value as per
+ * ENCAP_TYPE_*.
+ */
+#define	MAE_FIELD_ENCAP_TYPE 0x3f
+/* enum: The ID of the outer rule that marked this packet as encapsulated.
+ * Useful for implicitly matching on outer fields.
+ */
+#define	MAE_FIELD_OUTER_RULE_ID 0x40
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETHER_TYPE 0x41
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN0_TCI 0x42
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN0_PROTO 0x43
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN1_TCI 0x44
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_VLAN1_PROTO 0x45
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETH_SADDR 0x48
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_ETH_DADDR 0x49
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_SRC_IP4 0x4a
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_SRC_IP6 0x4b
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_DST_IP4 0x4c
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_DST_IP6 0x4d
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_PROTO 0x4e
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_TOS 0x4f
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_TTL 0x50
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_IP_FLAGS 0x51
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_L4_SPORT 0x52
+/* enum: Outer; only present when encap */
+#define	MAE_FIELD_ENC_L4_DPORT 0x53
+/* enum: VNI (when VXLAN or GENEVE) VSID (when NVGRE) Outer; only present when
+ * encap
+ */
+#define	MAE_FIELD_ENC_VNET_ID 0x54
+
 /* MAE_MCDI_ENCAP_TYPE enum: Encapsulation type. Defines how the payload will
  * be parsed to an inner frame. Other values are reserved. Unknown values
  * should be treated same as NONE.
@@ -25644,6 +25789,900 @@
 #define	MC_CMD_GET_ADDR_SPC_ID_OUT_ADDR_SPC_ID_LO_OFST 0
 #define	MC_CMD_GET_ADDR_SPC_ID_OUT_ADDR_SPC_ID_HI_OFST 4
 
+/* MAE_FIELD_FLAGS structuredef */
+#define	MAE_FIELD_FLAGS_LEN 4
+#define	MAE_FIELD_FLAGS_FLAT_OFST 0
+#define	MAE_FIELD_FLAGS_FLAT_LEN 4
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_OFST 0
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_LBN 0
+#define	MAE_FIELD_FLAGS_SUPPORT_STATUS_WIDTH 6
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_OFST 0
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_LBN 6
+#define	MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS_WIDTH 1
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_OFST 0
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_LBN 7
+#define	MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS_WIDTH 1
+#define	MAE_FIELD_FLAGS_FLAT_LBN 0
+#define	MAE_FIELD_FLAGS_FLAT_WIDTH 32
+
+/* MAE_ENC_FIELD_PAIRS structuredef: Mask and value pairs for all fields that
+ * it makes sense to use to determine the encapsulation type of a packet. Its
+ * intended use is to keep a common packing of fields across multiple MCDI
+ * commands, keeping things inherently sychronised and allowing code shared. To
+ * use in an MCDI command, the command should end with a variable length byte
+ * array populated with this structure. Do not extend this structure. Instead,
+ * create _Vx versions with the necessary fields appended. That way, the
+ * existing semantics for extending MCDI commands are preserved.
+ */
+#define	MAE_ENC_FIELD_PAIRS_LEN 156
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_ENC_FIELD_PAIRS_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_OFST 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_LBN 64
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_OFST 10
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_LBN 80
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_OFST 12
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_LBN 96
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_OFST 14
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_LBN 112
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_OFST 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_LBN 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_OFST 18
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LBN 144
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_OFST 20
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_LBN 160
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_OFST 22
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_LBN 176
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_OFST 24
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_LBN 192
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_OFST 26
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LBN 208
+#define	MAE_ENC_FIELD_PAIRS_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_OFST 28
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_LBN 224
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_OFST 34
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_LBN 272
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_OFST 40
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_LBN 320
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_OFST 46
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_LBN 368
+#define	MAE_ENC_FIELD_PAIRS_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_OFST 52
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_LBN 416
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_OFST 56
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_LBN 448
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_OFST 60
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_LBN 480
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_OFST 76
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_LBN 608
+#define	MAE_ENC_FIELD_PAIRS_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_OFST 92
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_LBN 736
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_OFST 96
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_LBN 768
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_OFST 100
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_LBN 800
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_OFST 116
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_LBN 928
+#define	MAE_ENC_FIELD_PAIRS_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_OFST 132
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_LBN 1056
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_OFST 133
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_LBN 1064
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_OFST 134
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_LBN 1072
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_OFST 135
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_LBN 1080
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_OFST 136
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_LEN 1
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_LBN 1088
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_WIDTH 8
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_TTL_MASK_OFST 137
+#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
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_OFST 140
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_LBN 1120
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_OFST 144
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_LBN 1152
+#define	MAE_ENC_FIELD_PAIRS_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_OFST 148
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_LBN 1184
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_OFST 150
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_LBN 1200
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_OFST 152
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_LBN 1216
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_OFST 154
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_LBN 1232
+#define	MAE_ENC_FIELD_PAIRS_ENC_L4_DPORT_BE_MASK_WIDTH 16
+
+/* MAE_FIELD_MASK_VALUE_PAIRS structuredef: Mask and value pairs for all fields
+ * currently defined. Same semantics as MAE_ENC_FIELD_PAIRS.
+ */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_LEN 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_OFST 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_LBN 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_OFST 12
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_LBN 96
+#define	MAE_FIELD_MASK_VALUE_PAIRS_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_OFST 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_LBN 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_OFST 18
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_LBN 144
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_OFST 20
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_LBN 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_OFST 22
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_LBN 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_OFST 24
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_LBN 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_OFST 26
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_LBN 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_OFST 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_LBN 224
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_OFST 30
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_LBN 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_OFST 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_LBN 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_OFST 34
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_LBN 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_OFST 36
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_LBN 288
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_OFST 42
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_LBN 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_OFST 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_LBN 384
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_OFST 54
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_LBN 432
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_OFST 60
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_LBN 480
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_OFST 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_LBN 512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_OFST 68
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_LBN 544
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_OFST 84
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_LBN 672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_OFST 100
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_LBN 800
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_OFST 104
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_LBN 832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_OFST 108
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_LBN 864
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_OFST 124
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_LBN 992
+#define	MAE_FIELD_MASK_VALUE_PAIRS_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_OFST 140
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_LBN 1120
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_OFST 141
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_LBN 1128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_OFST 142
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_LBN 1136
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TOS_MASK_OFST 143
+#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
+#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
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_OFST 145
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_LBN 1160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_OFST 148
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_LBN 1184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_OFST 152
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_LBN 1216
+#define	MAE_FIELD_MASK_VALUE_PAIRS_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_OFST 156
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_LBN 1248
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_OFST 158
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_LBN 1264
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_OFST 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_LBN 1280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_OFST 162
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_LBN 1296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_OFST 164
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_LBN 1312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_OFST 166
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_LBN 1328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_TCP_FLAGS_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_OFST 168
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_LBN 1344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_OFST 172
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_LBN 1376
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENCAP_TYPE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_OFST 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_LBN 1408
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_OFST 180
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_LBN 1440
+#define	MAE_FIELD_MASK_VALUE_PAIRS_OUTER_RULE_ID_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_OFST 184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_LBN 1472
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_OFST 188
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_LBN 1504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_OFST 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_LBN 1536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_OFST 194
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_LBN 1552
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_OFST 196
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_LBN 1568
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_OFST 198
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_LBN 1584
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_OFST 200
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_LBN 1600
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_OFST 202
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_LBN 1616
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_OFST 204
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_LBN 1632
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_OFST 206
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_LBN 1648
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_OFST 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_LBN 1664
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_OFST 214
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_LBN 1712
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_OFST 220
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_LBN 1760
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_OFST 226
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_LBN 1808
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_OFST 232
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_LBN 1856
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_OFST 236
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_LBN 1888
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_OFST 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_LBN 1920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_OFST 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_LBN 2048
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_OFST 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_LBN 2176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_OFST 276
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_LBN 2208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_OFST 280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_LBN 2240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_OFST 296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_LBN 2368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_OFST 312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_LBN 2496
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_OFST 313
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_LBN 2504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_OFST 314
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_LBN 2512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_OFST 315
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_LBN 2520
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_OFST 316
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_LBN 2528
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_OFST 317
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_LBN 2536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_OFST 320
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_LBN 2560
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_OFST 324
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_LBN 2592
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_OFST 328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_LBN 2624
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_OFST 330
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_LBN 2640
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_OFST 332
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_LBN 2656
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_OFST 334
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_LBN 2672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_OFST 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_LBN 2688
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_OFST 340
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_LBN 2720
+#define	MAE_FIELD_MASK_VALUE_PAIRS_ENC_VNET_ID_BE_MASK_WIDTH 32
+
+/* MAE_FIELD_MASK_VALUE_PAIRS_V2 structuredef */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN 372
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_OFST 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_OFST 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_LBN 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_INGRESS_MPORT_SELECTOR_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_OFST 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_LBN 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_OFST 12
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_LBN 96
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_OFST 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_LBN 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_OFST 18
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_LBN 144
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_OFST 20
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_LBN 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_OFST 22
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_LBN 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_OFST 24
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_LBN 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_OFST 26
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_LBN 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_OFST 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_LBN 224
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_OFST 30
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_LBN 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_OFST 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_LBN 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_OFST 34
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_LBN 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_OFST 36
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_LBN 288
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_OFST 42
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_LBN 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_OFST 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_LBN 384
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_OFST 54
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_LBN 432
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_OFST 60
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_LBN 480
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_OFST 64
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_LBN 512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_OFST 68
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_LBN 544
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_OFST 84
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_LBN 672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_OFST 100
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_LBN 800
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_OFST 104
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_LBN 832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_OFST 108
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_LBN 864
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_OFST 124
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_LBN 992
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_OFST 140
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_LBN 1120
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_OFST 141
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_LBN 1128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_OFST 142
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_LBN 1136
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TOS_MASK_OFST 143
+#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
+#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
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_OFST 145
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_LBN 1160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_OFST 148
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_LBN 1184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_OFST 152
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_LBN 1216
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_OFST 156
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_LBN 1248
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_OFST 158
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_LBN 1264
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_OFST 160
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_LBN 1280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_OFST 162
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_LBN 1296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_OFST 164
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_LBN 1312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_OFST 166
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_LBN 1328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_TCP_FLAGS_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_OFST 168
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_LBN 1344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_OFST 172
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_LBN 1376
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENCAP_TYPE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_OFST 176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_LBN 1408
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_OFST 180
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_LBN 1440
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_OUTER_RULE_ID_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_OFST 184
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_LBN 1472
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_OFST 188
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_LBN 1504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETHER_TYPE_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_OFST 192
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_LBN 1536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_OFST 194
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_LBN 1552
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_OFST 196
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_LBN 1568
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_OFST 198
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_LBN 1584
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN0_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_OFST 200
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_LBN 1600
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_OFST 202
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_LBN 1616
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_TCI_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_OFST 204
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_LBN 1632
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_OFST 206
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_LBN 1648
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VLAN1_PROTO_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_OFST 208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_LBN 1664
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_OFST 214
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_LBN 1712
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_SADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_OFST 220
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_LBN 1760
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_OFST 226
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_LEN 6
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_LBN 1808
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_ETH_DADDR_BE_MASK_WIDTH 48
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_OFST 232
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_LBN 1856
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_OFST 236
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_LBN 1888
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_OFST 240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_LBN 1920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_OFST 256
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_LBN 2048
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_SRC_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_OFST 272
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_LBN 2176
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_OFST 276
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_LBN 2208
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP4_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_OFST 280
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_LBN 2240
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_OFST 296
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_LEN 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_LBN 2368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_DST_IP6_BE_MASK_WIDTH 128
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_OFST 312
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_LBN 2496
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_OFST 313
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_LBN 2504
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_PROTO_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_OFST 314
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_LBN 2512
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_OFST 315
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_LBN 2520
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TOS_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_OFST 316
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_LBN 2528
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_OFST 317
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_LBN 2536
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_TTL_MASK_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_OFST 320
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_LBN 2560
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_OFST 324
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_LBN 2592
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_IP_FLAGS_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_OFST 328
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_LBN 2624
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_OFST 330
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_LBN 2640
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_SPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_OFST 332
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_LBN 2656
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_OFST 334
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_LBN 2672
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_L4_DPORT_BE_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_OFST 336
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_LBN 2688
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_OFST 340
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_LBN 2720
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_ENC_VNET_ID_BE_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_LBN 0
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_IP_FRAG_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_LBN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_DO_CT_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_LBN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_HIT_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_LBN 3
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_IS_FROM_NETWORK_WIDTH 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_OFST 344
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_LBN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD_WIDTH 28
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_LBN 2752
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST 348
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_LBN 2784
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_OFST 352
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_LBN 2816
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_OFST 354
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_LEN 2
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_LBN 2832
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_DOMAIN_MASK_WIDTH 16
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_OFST 356
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_LBN 2848
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_OFST 360
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_LEN 4
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_LBN 2880
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_MARK_MASK_WIDTH 32
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_OFST 364
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_LBN 2912
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_WIDTH 8
+/* Set to zero. */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_OFST 365
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_LBN 2920
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD2_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_OFST 366
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_LBN 2928
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_CT_PRIVATE_FLAGS_MASK_WIDTH 8
+/* Set to zero. */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_OFST 367
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_LBN 2936
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD3_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_OFST 368
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_LBN 2944
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_WIDTH 8
+/* Set to zero */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_OFST 369
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_LBN 2952
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD4_WIDTH 8
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_OFST 370
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_LBN 2960
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK_WIDTH 8
+/* Set to zero */
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_OFST 371
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_LEN 1
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_LBN 2968
+#define	MAE_FIELD_MASK_VALUE_PAIRS_V2_RSVD5_WIDTH 8
+
 /* 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
@@ -25699,4 +26738,1197 @@
 #define	MAE_MPORT_SELECTOR_FLAT_LBN 0
 #define	MAE_MPORT_SELECTOR_FLAT_WIDTH 32
 
+
+/***********************************/
+/* MC_CMD_MAE_GET_CAPS
+ * Describes capabilities of the MAE (Match-Action Engine)
+ */
+#define	MC_CMD_MAE_GET_CAPS 0x140
+#undef	MC_CMD_0x140_PRIVILEGE_CTG
+
+#define	MC_CMD_0x140_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_CAPS_OUT_LEN 52
+/* 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_OUT_MATCH_FIELD_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED_LEN 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_LBN 0
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_LBN 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE_WIDTH 1
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_OFST 4
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_LBN 2
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE_WIDTH 1
+/* The total number of counters available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_COUNTERS_OFST 8
+#define	MC_CMD_MAE_GET_CAPS_OUT_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_OUT_COUNTER_LISTS_OFST 12
+#define	MC_CMD_MAE_GET_CAPS_OUT_COUNTER_LISTS_LEN 4
+/* The total number of encap header structures available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_HEADER_LIMIT_OFST 16
+#define	MC_CMD_MAE_GET_CAPS_OUT_ENCAP_HEADER_LIMIT_LEN 4
+/* Reserved. Should be zero. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_RSVD_OFST 20
+#define	MC_CMD_MAE_GET_CAPS_OUT_RSVD_LEN 4
+/* The total number of action sets available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SETS_OFST 24
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SETS_LEN 4
+/* The total number of action set lists available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SET_LISTS_OFST 28
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_SET_LISTS_LEN 4
+/* The total number of outer rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_OUTER_RULES_OFST 32
+#define	MC_CMD_MAE_GET_CAPS_OUT_OUTER_RULES_LEN 4
+/* The total number of action rules available to allocate. */
+#define	MC_CMD_MAE_GET_CAPS_OUT_ACTION_RULES_OFST 36
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_ACTION_PRIOS_OFST 40
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_OUTER_PRIOS_OFST 44
+#define	MC_CMD_MAE_GET_CAPS_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_OUT_API_VER_OFST 48
+#define	MC_CMD_MAE_GET_CAPS_OUT_API_VER_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_GET_AR_CAPS
+ * Get a level of support for match fields when used in match-action rules
+ */
+#define	MC_CMD_MAE_GET_AR_CAPS 0x141
+#undef	MC_CMD_0x141_PRIVILEGE_CTG
+
+#define	MC_CMD_0x141_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_AR_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_AR_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_AR_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX 252
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_NUM(len) (((len)-4)/4)
+/* Number of fields actually returned in FIELD_FLAGS. */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_COUNT_LEN 4
+/* Array of values indicating the NIC's support for a given field, indexed by
+ * field id. The driver must ensure space for
+ * MC_CMD_MAE_GET_CAPS.MATCH_FIELD_COUNT entries in the array..
+ */
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_OFST 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_LEN 4
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MINNUM 0
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MAXNUM 62
+#define	MC_CMD_MAE_GET_AR_CAPS_OUT_FIELD_FLAGS_MAXNUM_MCDI2 254
+
+
+/***********************************/
+/* MC_CMD_MAE_GET_OR_CAPS
+ * Get a level of support for fields used in outer rule keys.
+ */
+#define	MC_CMD_MAE_GET_OR_CAPS 0x142
+#undef	MC_CMD_0x142_PRIVILEGE_CTG
+
+#define	MC_CMD_0x142_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_GET_OR_CAPS_IN msgrequest */
+#define	MC_CMD_MAE_GET_OR_CAPS_IN_LEN 0
+
+/* MC_CMD_MAE_GET_OR_CAPS_OUT msgresponse */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX 252
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_NUM(len) (((len)-4)/4)
+/* Number of fields actually returned in FIELD_FLAGS. */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_COUNT_OFST 0
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_COUNT_LEN 4
+/* Same semantics as MC_CMD_MAE_GET_AR_CAPS.MAE_FIELD_FLAGS */
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_OFST 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_LEN 4
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MINNUM 0
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MAXNUM 62
+#define	MC_CMD_MAE_GET_OR_CAPS_OUT_FIELD_FLAGS_MAXNUM_MCDI2 254
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTER_ALLOC
+ * Allocate match-action-engine counters, which can be referenced in Action
+ * Rules.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC 0x143
+#undef	MC_CMD_0x143_PRIVILEGE_CTG
+
+#define	MC_CMD_0x143_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_COUNTER_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_LEN 4
+/* The number of counters that the driver would like allocated */
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT_LEN 4
+
+/* MC_CMD_MAE_COUNTER_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN 12
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX 252
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(num) (8+4*(num))
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NUM(len) (((len)-8)/4)
+/* 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.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT_LEN 4
+/* 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.
+ */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT_OFST 4
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT_LEN 4
+/* An array containing the IDs for the counters allocated. */
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_OFST 8
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM 61
+#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
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTER_FREE
+ * Free match-action-engine counters
+ */
+#define	MC_CMD_MAE_COUNTER_FREE 0x144
+#undef	MC_CMD_0x144_PRIVILEGE_CTG
+
+#define	MC_CMD_0x144_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_COUNTER_FREE_IN msgrequest */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMIN 8
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMAX 132
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2 132
+#define	MC_CMD_MAE_COUNTER_FREE_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_NUM(len) (((len)-4)/4)
+/* The number of counter IDs to be freed. */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT_LEN 4
+/* An array containing the counter IDs to be freed. */
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_OFST 4
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM 32
+#define	MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_COUNTER_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN 12
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX 136
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2 136
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_LEN(num) (8+4*(num))
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_NUM(len) (((len)-8)/4)
+/* Generation count. A packet with generation count == GENERATION_COUNT will
+ * contain the final values for these counter IDs, unless the counter values
+ * are zero and zero squash is enabled. Receiving a packet with generation
+ * count > GENERATION_COUNT guarantees that no more 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.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_GENERATION_COUNT_LEN 4
+/* The number of counter IDs actually freed. It is never less than 1; failure
+ * to free a single counter will cause an error to be returned. It is never
+ * greater than the number that were requested to be freed, but may be less if
+ * counters could not be freed.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT_OFST 4
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT_LEN 4
+/* An array containing the IDs for the counters to that were freed. Note,
+ * failure to free a counter can only occur on incorrect driver behaviour, so
+ * asserting that the expected counters were freed is reasonable. When
+ * debugging, attempting to free a single counter at a time will provide a
+ * reason for the failure to free said counter.
+ */
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_OFST 8
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_LEN 4
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM 1
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MAXNUM 32
+#define	MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_START
+ * Start streaming counter values, specifying an RxQ to deliver packets to.
+ * Counters allocated to the calling function will be written in a round robin
+ * at a fixed cycle rate, assuming sufficient credits are available. The driver
+ * may cause the counter values to be written at a slower rate by constraining
+ * the availability of credits. Note that if the driver wishes to deliver
+ * packets to a different queue, it must call MAE_COUNTERS_STREAM_STOP to stop
+ * delivering packets to the current queue first.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START 0x151
+
+/* MC_CMD_MAE_COUNTERS_STREAM_START_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN 8
+/* The RxQ to write packets to. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_QID_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_QID_LEN 2
+/* Maximum size in bytes of packets that may be written to the RxQ. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE_OFST 2
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE_LEN 2
+/* Optional flags. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_FLAGS_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_WIDTH 1
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_OFST 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_LBN 1
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_IN_COUNTER_STALL_EN_WIDTH 1
+
+/* MC_CMD_MAE_COUNTERS_STREAM_START_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_FLAGS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_FLAGS_LEN 4
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_WIDTH 1
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP
+ * Stop streaming counter values to the specified RxQ.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP 0x152
+
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN 2
+/* The RxQ to stop writing packets to. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_QID_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_QID_LEN 2
+
+/* MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN 4
+/* Generation count. The 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 will be written to
+ * this stream.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS
+ * Give a number of credits to the packetiser. Each credit received allows the
+ * MC to write one packet to the RxQ, therefore for each credit the driver must
+ * have written sufficient descriptors for a packet of length
+ * MAE_COUNTERS_PACKETISER_STREAM_START/PACKET_SIZE and rung the doorbell.
+ */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS 0x153
+
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN msgrequest */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN 4
+/* Number of credits to give to the packetiser. */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS_OFST 0
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS_LEN 4
+
+/* MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT msgresponse */
+#define	MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC
+ * Allocate encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC 0x148
+#undef	MC_CMD_0x148_PRIVILEGE_CTG
+
+#define	MC_CMD_0x148_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX 252
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(num) (4+1*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_NUM(len) (((len)-4)/1)
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_LEN 1
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MINNUM 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM 248
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2 1016
+
+/* MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN 4
+/* enum: An encap metadata ID that is guaranteed never to represent real encap
+ * metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE
+ * Update encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE 0x149
+#undef	MC_CMD_0x149_PRIVILEGE_CTG
+
+#define	MC_CMD_0x149_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMIN 8
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX 252
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(num) (8+1*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_NUM(len) (((len)-8)/1)
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE_OFST 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_OFST 8
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_LEN 1
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MINNUM 0
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM 244
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM_MCDI2 1012
+
+/* MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ENCAP_HEADER_FREE
+ * Free encap action metadata
+ */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE 0x14a
+#undef	MC_CMD_0x14a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14a_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ENCAP_HEADER_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MINNUM 1
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MAXNUM 32
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_IN_EH_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ENCAP_HEADER_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_OFST 0
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_LEN 4
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MINNUM 1
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MAXNUM 32
+#define	MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MAC_ADDR_ALLOC
+ * Allocate MAC address. Hardware implementations have MAC addresses programmed
+ * into an indirection table, and clients should take care not to allocate the
+ * same MAC address twice (but instead reuse its ID).
+ */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC 0x15e
+#undef	MC_CMD_0x15e_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15e_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MAC_ADDR_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN 6
+/* MAC address as bytes in network order. */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_LEN 6
+
+/* MC_CMD_MAE_MAC_ADDR_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN 4
+/* enum: An MAC address ID that is guaranteed never to represent a real MAC
+ * address.
+ */
+#define	MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_MAC_ADDR_FREE
+ * Free MAC address.
+ */
+#define	MC_CMD_MAE_MAC_ADDR_FREE 0x15f
+#undef	MC_CMD_0x15f_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15f_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MAC_ADDR_FREE_IN msgrequest */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MINNUM 1
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MAXNUM 32
+#define	MC_CMD_MAE_MAC_ADDR_FREE_IN_MAC_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_MAC_ADDR_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_OFST 0
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_LEN 4
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MINNUM 1
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MAXNUM 32
+#define	MC_CMD_MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_ALLOC
+ * Allocate an action set, which can be referenced either in response to an
+ * Action Rule, or as part of an Action Set List.
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC 0x14d
+#undef	MC_CMD_0x14d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14d_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN 44
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAGS_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAGS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_LBN 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_LBN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN_POP_WIDTH 2
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_LBN 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DECAP_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_LBN 9
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_MARK_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_LBN 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_FLAG_WIDTH 1
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_LBN 11
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DO_NAT_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
+/* If VLAN_PUSH >= 1, TPID value to be inserted as outermost VLAN. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE_OFST 6
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TCI value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE_OFST 8
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE_LEN 2
+/* If VLAN_PUSH == 2, inner TPID value to be inserted. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE_OFST 10
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE_LEN 2
+/* Reserved. Ignored by firmware. Should be set to zero or 0xffffffff. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_RSVD_OFST 12
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_RSVD_LEN 4
+/* Set to ENCAP_HEADER_ID_NULL to request no encap action */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID_OFST 16
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_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_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.
+ */
+#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
+/* 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. 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 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
+#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. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID_OFST 36
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID_LEN 4
+/* Set to MAC_ID_NULL to request no destination MAC replacement. */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID_OFST 40
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID_LEN 4
+
+/* MC_CMD_MAE_ACTION_SET_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_AS_ID_LEN 4
+/* enum: An action set ID that is guaranteed never to represent an action set
+ */
+#define	MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_FREE
+ */
+#define	MC_CMD_MAE_ACTION_SET_FREE 0x14e
+#undef	MC_CMD_0x14e_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14e_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_FREE_IN_AS_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_SET_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_FREE_OUT_FREED_AS_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC
+ * Allocate an action set list (ASL) that can be referenced by an ID. The ASL
+ * ID can be used when inserting an action rule, so that for each packet
+ * matching the rule every action set in the list is applied.
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC 0x14f
+#undef	MC_CMD_0x14f_PRIVILEGE_CTG
+
+#define	MC_CMD_0x14f_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMIN 8
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX 252
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(num) (4+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_NUM(len) (((len)-4)/4)
+/* Number of elements in the AS_IDS field. */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_COUNT_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_COUNT_LEN 4
+/* The IDs of the action sets in this list. The last element of this list may
+ * be the ID of an already allocated ASL. In this case the action sets from the
+ * already allocated ASL will be applied after the action sets supplied by this
+ * request. This mechanism can be used to reduce resource usage in the case
+ * where one ASL is a sublist of another ASL. The sublist should be allocated
+ * first, then the superlist should be allocated by supplying all required
+ * action set IDs that are not in the sublist followed by the ID of the
+ * sublist. One sublist can be referenced by multiple superlists.
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_OFST 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM 62
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2 254
+
+/* MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_LEN 4
+/* enum: An action set list ID that is guaranteed never to represent an action
+ * set list
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE
+ * Free match-action-engine redirect_lists
+ */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE 0x150
+#undef	MC_CMD_0x150_PRIVILEGE_CTG
+
+#define	MC_CMD_0x150_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_ASL_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_INSERT
+ * Inserts an Outer Rule, which controls encapsulation parsing, and may
+ * influence the Lookup Sequence.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT 0x15a
+#undef	MC_CMD_0x15a_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15a_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_MAE_OUTER_RULE_INSERT_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMIN 16
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX 252
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_LEN(num) (16+1*(num))
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_NUM(len) (((len)-16)/1)
+/* Packets matching the rule will be parsed with this encapsulation. */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE_LEN 4
+/*            Enum values, see field(s): */
+/*               MAE_MCDI_ENCAP_TYPE */
+/* Match priority. Lower values have higher priority. Must be less than
+ * MC_CMD_MAE_GET_CAPS_OUT.ENCAP_PRIOS If a packet matches two filters with
+ * equal priority then it is unspecified which takes priority.
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_OFST 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_PRIO_LEN 4
+#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
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_LBN 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_DO_CT_WIDTH 1
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_OFST 8
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_CT_VNI_MODE_LBN 1
+#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_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
+/* 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
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MINNUM 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MAXNUM 236
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_MAXNUM_MCDI2 1004
+
+/* MC_CMD_MAE_OUTER_RULE_INSERT_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN 4
+/* enum: An outer match ID that is guaranteed never to represent an outer match
+ */
+#define	MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_OUTER_RULE_REMOVE
+ */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE 0x15b
+#undef	MC_CMD_0x15b_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15b_PRIVILEGE_CTG SRIOV_CTG_ADMIN
+
+/* MC_CMD_MAE_OUTER_RULE_REMOVE_IN msgrequest */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMIN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMAX 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MINNUM 1
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MAXNUM 32
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_IN_OR_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_OUTER_RULE_REMOVE_OUT msgresponse */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMAX 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_OFST 0
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_LEN 4
+#define	MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID_MINNUM 1
+#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
+
+/* MAE_ACTION_RULE_RESPONSE structuredef */
+#define	MAE_ACTION_RULE_RESPONSE_LEN 16
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_OFST 0
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_LBN 0
+#define	MAE_ACTION_RULE_RESPONSE_ASL_ID_WIDTH 32
+/* Only one of ASL_ID or AS_ID may have a non-NULL value. */
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_OFST 4
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_LBN 32
+#define	MAE_ACTION_RULE_RESPONSE_AS_ID_WIDTH 32
+/* Controls lookup flow when this rule is hit. See sub-fields for details. More
+ * info on the lookup sequence can be found in SF-122976-TC. It is an error to
+ * set both DO_CT and DO_RECIRC.
+ */
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_LBN 0
+#define	MAE_ACTION_RULE_RESPONSE_DO_CT_WIDTH 1
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_LBN 1
+#define	MAE_ACTION_RULE_RESPONSE_DO_RECIRC_WIDTH 1
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_LBN 2
+#define	MAE_ACTION_RULE_RESPONSE_CT_VNI_MODE_WIDTH 2
+/*             Enum values, see field(s): */
+/*                MAE_CT_VNI_MODE */
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_LBN 8
+#define	MAE_ACTION_RULE_RESPONSE_RECIRC_ID_WIDTH 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_OFST 8
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_LBN 16
+#define	MAE_ACTION_RULE_RESPONSE_CT_DOMAIN_WIDTH 16
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_LBN 64
+#define	MAE_ACTION_RULE_RESPONSE_LOOKUP_CONTROL_WIDTH 32
+/* Counter ID to increment if DO_CT or DO_RECIRC is set. Must be set to
+ * COUNTER_ID_NULL otherwise.
+ */
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_OFST 12
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_LEN 4
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_LBN 96
+#define	MAE_ACTION_RULE_RESPONSE_COUNTER_ID_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_INSERT
+ * Insert a rule specify that packets matching a filter be processed according
+ * to a previous allocated action. Masks can be set as indicated by
+ * MC_CMD_MAE_GET_MATCH_FIELD_CAPABILITIES.
+ */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT 0x15c
+#undef	MC_CMD_0x15c_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15c_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_INSERT_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMIN 28
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX 252
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_LEN(num) (28+1*(num))
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_NUM(len) (((len)-28)/1)
+/* See MC_CMD_MAE_OUTER_RULE_REGISTER_IN/PRIO. */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_PRIO_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_PRIO_LEN 4
+/* Structure of the format MAE_ACTION_RULE_RESPONSE */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST 4
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN 20
+/* Reserved for future use. Must be set to zero. */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RSVD_OFST 24
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_RSVD_LEN 4
+/* Structure of the format MAE_FIELD_MASK_VALUE_PAIRS */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST 28
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_LEN 1
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MINNUM 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MAXNUM 224
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_MAXNUM_MCDI2 992
+
+/* MC_CMD_MAE_ACTION_RULE_INSERT_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN 4
+/* enum: An action rule ID that is guaranteed never to represent an action rule
+ */
+#define	MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL 0xffffffff
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_UPDATE
+ * Atomically change the response of an action rule. Firmware may return
+ * ENOTSUP, in which case the driver should DELETE/INSERT.
+ */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE 0x15d
+#undef	MC_CMD_0x15d_PRIVILEGE_CTG
+
+#define	MC_CMD_0x15d_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_UPDATE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN 24
+/* ID of action rule to update */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_AR_ID_LEN 4
+/* Structure of the format MAE_ACTION_RULE_RESPONSE */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_RESPONSE_OFST 4
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_IN_RESPONSE_LEN 20
+
+/* MC_CMD_MAE_ACTION_RULE_UPDATE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN 0
+
+
+/***********************************/
+/* MC_CMD_MAE_ACTION_RULE_DELETE
+ */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE 0x155
+#undef	MC_CMD_0x155_PRIVILEGE_CTG
+
+#define	MC_CMD_0x155_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_ACTION_RULE_DELETE_IN msgrequest */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMIN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMAX 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_IN_AR_ID_MAXNUM_MCDI2 32
+
+/* MC_CMD_MAE_ACTION_RULE_DELETE_OUT msgresponse */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMAX 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMAX_MCDI2 128
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(num) (0+4*(num))
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_NUM(len) (((len)-0)/4)
+/* Same semantics as MC_CMD_MAE_COUNTER_FREE */
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_OFST 0
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_LEN 4
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MINNUM 1
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MAXNUM 32
+#define	MC_CMD_MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID_MAXNUM_MCDI2 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_LOOKUP
+ * Return the m-port corresponding to a selector.
+ */
+#define	MC_CMD_MAE_MPORT_LOOKUP 0x160
+#undef	MC_CMD_0x160_PRIVILEGE_CTG
+
+#define	MC_CMD_0x160_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_LOOKUP_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_LEN 4
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR_OFST 0
+#define	MC_CMD_MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR_LEN 4
+
+/* MC_CMD_MAE_MPORT_LOOKUP_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN 4
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_LOOKUP_OUT_MPORT_ID_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_ALLOC
+ * Allocates a m-port, which can subsequently be used in action rules as a
+ * match or delivery argument.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC 0x163
+#undef	MC_CMD_0x163_PRIVILEGE_CTG
+
+#define	MC_CMD_0x163_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_ALLOC_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_LEN 20
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_IN_UUID_LEN 16
+
+/* MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN 24
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_UUID_LEN 16
+/* An m-port selector identifying the VNIC to which traffic should be
+ * delivered. This must currently be set to MAE_MPORT_SELECTOR_ASSIGNED (i.e.
+ * the m-port assigned to the calling client).
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT_OFST 20
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_VNIC_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_LEN 20
+/* The type of m-port to allocate. Firmware may return ENOTSUP for certain
+ * types.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_TYPE_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_TYPE_LEN 4
+/* enum: Traffic can be sent to this type of m-port using an override
+ * descriptor. Traffic received on this type of m-port will go to the VNIC on a
+ * nominated m-port, and will be delivered with metadata identifying the alias
+ * m-port.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_MPORT_TYPE_ALIAS 0x1
+/* enum: This type of m-port has a VNIC attached. Queues can be created on this
+ * VNIC by specifying the created m-port as an m-port selector at queue
+ * creation time.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_MPORT_TYPE_VNIC 0x2
+/* 128-bit value for use by the driver. */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_UUID_OFST 4
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_IN_UUID_LEN 16
+
+/* MC_CMD_MAE_MPORT_ALLOC_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_LEN 4
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_OUT_MPORT_ID_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN 24
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID_LEN 4
+/* A value that will appear in the packet metadata for any packets delivered
+ * using an alias type m-port. This value is guaranteed unique on the VNIC
+ * being delivered to, and is guaranteed not to exceed the range of values
+ * representable in the relevant metadata field.
+ */
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LABEL_OFST 20
+#define	MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LABEL_LEN 4
+
+/* MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT msgrequest */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_LEN 4
+/* ID of newly-allocated m-port. */
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_ALLOC_VNIC_OUT_MPORT_ID_LEN 4
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_FREE
+ * Free a m-port which was previously allocated by the driver.
+ */
+#define	MC_CMD_MAE_MPORT_FREE 0x164
+#undef	MC_CMD_0x164_PRIVILEGE_CTG
+
+#define	MC_CMD_0x164_PRIVILEGE_CTG SRIOV_CTG_GENERAL
+
+/* MC_CMD_MAE_MPORT_FREE_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_FREE_IN_LEN 4
+/* MPORT_ID as returned by MC_CMD_MAE_MPORT_ALLOC. */
+#define	MC_CMD_MAE_MPORT_FREE_IN_MPORT_ID_OFST 0
+#define	MC_CMD_MAE_MPORT_FREE_IN_MPORT_ID_LEN 4
+
+/* MC_CMD_MAE_MPORT_FREE_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_FREE_OUT_LEN 0
+
+/* MAE_MPORT_DESC structuredef */
+#define	MAE_MPORT_DESC_LEN 52
+#define	MAE_MPORT_DESC_MPORT_ID_OFST 0
+#define	MAE_MPORT_DESC_MPORT_ID_LEN 4
+#define	MAE_MPORT_DESC_MPORT_ID_LBN 0
+#define	MAE_MPORT_DESC_MPORT_ID_WIDTH 32
+/* Reserved for future purposes, contains information independent of caller */
+#define	MAE_MPORT_DESC_FLAGS_OFST 4
+#define	MAE_MPORT_DESC_FLAGS_LEN 4
+#define	MAE_MPORT_DESC_FLAGS_LBN 32
+#define	MAE_MPORT_DESC_FLAGS_WIDTH 32
+#define	MAE_MPORT_DESC_CALLER_FLAGS_OFST 8
+#define	MAE_MPORT_DESC_CALLER_FLAGS_LEN 4
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_OFST 8
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_LBN 0
+#define	MAE_MPORT_DESC_CAN_RECEIVE_ON_WIDTH 1
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_OFST 8
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_LBN 1
+#define	MAE_MPORT_DESC_CAN_DELIVER_TO_WIDTH 1
+#define	MAE_MPORT_DESC_CAN_DELETE_OFST 8
+#define	MAE_MPORT_DESC_CAN_DELETE_LBN 2
+#define	MAE_MPORT_DESC_CAN_DELETE_WIDTH 1
+#define	MAE_MPORT_DESC_CALLER_FLAGS_LBN 64
+#define	MAE_MPORT_DESC_CALLER_FLAGS_WIDTH 32
+/* Not the ideal name; it's really the type of thing connected to the m-port */
+#define	MAE_MPORT_DESC_MPORT_TYPE_OFST 12
+#define	MAE_MPORT_DESC_MPORT_TYPE_LEN 4
+/* enum: Connected to a MAC... */
+#define	MAE_MPORT_DESC_MPORT_TYPE_NET_PORT 0x0
+/* enum: Adds metadata and delivers to another m-port */
+#define	MAE_MPORT_DESC_MPORT_TYPE_ALIAS 0x1
+/* enum: Connected to a VNIC. */
+#define	MAE_MPORT_DESC_MPORT_TYPE_VNIC 0x2
+#define	MAE_MPORT_DESC_MPORT_TYPE_LBN 96
+#define	MAE_MPORT_DESC_MPORT_TYPE_WIDTH 32
+/* 128-bit value available to drivers for m-port identification. */
+#define	MAE_MPORT_DESC_UUID_OFST 16
+#define	MAE_MPORT_DESC_UUID_LEN 16
+#define	MAE_MPORT_DESC_UUID_LBN 128
+#define	MAE_MPORT_DESC_UUID_WIDTH 128
+/* Big wadge of space reserved for other common properties */
+#define	MAE_MPORT_DESC_RESERVED_OFST 32
+#define	MAE_MPORT_DESC_RESERVED_LEN 8
+#define	MAE_MPORT_DESC_RESERVED_LO_OFST 32
+#define	MAE_MPORT_DESC_RESERVED_HI_OFST 36
+#define	MAE_MPORT_DESC_RESERVED_LBN 256
+#define	MAE_MPORT_DESC_RESERVED_WIDTH 64
+/* Logical port index. Only valid when type NET Port. */
+#define	MAE_MPORT_DESC_NET_PORT_IDX_OFST 40
+#define	MAE_MPORT_DESC_NET_PORT_IDX_LEN 4
+#define	MAE_MPORT_DESC_NET_PORT_IDX_LBN 320
+#define	MAE_MPORT_DESC_NET_PORT_IDX_WIDTH 32
+/* The m-port delivered to */
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_OFST 40
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_LEN 4
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_LBN 320
+#define	MAE_MPORT_DESC_ALIAS_DELIVER_MPORT_ID_WIDTH 32
+/* The type of thing that owns the VNIC */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_OFST 40
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_LEN 4
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_FUNCTION 0x1 /* enum */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_PLUGIN 0x2 /* enum */
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_LBN 320
+#define	MAE_MPORT_DESC_VNIC_CLIENT_TYPE_WIDTH 32
+/* The PCIe interface on which the funcion lives. CJK: We need an enumeration
+ * of interfaces that we extend as new interface (types) appear. This belongs
+ * elsewhere and should be referenced from here
+ */
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_OFST 44
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_LEN 4
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_LBN 352
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_INTERFACE_WIDTH 32
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_OFST 48
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_LEN 2
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_LBN 384
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_PF_IDX_WIDTH 16
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_OFST 50
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_LEN 2
+/* enum: Indicates that the function is a PF */
+#define	MAE_MPORT_DESC_VF_IDX_NULL 0xffff
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_LBN 400
+#define	MAE_MPORT_DESC_VNIC_FUNCTION_VF_IDX_WIDTH 16
+/* Reserved. Should be ignored for now. */
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_OFST 44
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_LEN 4
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_LBN 352
+#define	MAE_MPORT_DESC_VNIC_PLUGIN_TBD_WIDTH 32
+
+
+/***********************************/
+/* MC_CMD_MAE_MPORT_ENUMERATE
+ */
+#define	MC_CMD_MAE_MPORT_ENUMERATE 0x17c
+
+/* MC_CMD_MAE_MPORT_ENUMERATE_IN msgrequest */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_IN_LEN 0
+
+/* MC_CMD_MAE_MPORT_ENUMERATE_OUT msgresponse */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMIN 8
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMAX 252
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LENMAX_MCDI2 1020
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_LEN(num) (8+1*(num))
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_NUM(len) (((len)-8)/1)
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_COUNT_OFST 0
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_COUNT_LEN 4
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_SIZEOF_MPORT_DESC_OFST 4
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_SIZEOF_MPORT_DESC_LEN 4
+/* Any array of MAE_MPORT_DESC structures. The MAE_MPORT_DESC structure may
+ * grow in future version of this command. Drivers should use a stride of
+ * SIZEOF_MPORT_DESC. Fields beyond SIZEOF_MPORT_DESC are not present.
+ */
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_OFST 8
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_LEN 1
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MINNUM 0
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MAXNUM 244
+#define	MC_CMD_MAE_MPORT_ENUMERATE_OUT_MPORT_DESC_DATA_MAXNUM_MCDI2 1012
+
 #endif /* _SIENA_MC_DRIVER_PCOL_H */
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 02/62] common/sfc_efx/base: indicate support for MAE
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 03/62] net/sfc: add a stub for attaching to MAE Andrew Rybchenko
                     ` (60 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Riverhead boards maintain support for MAE, a low-level Match-Action Engine.
The feature is documented in SF-122526-TC.

The new field will help client drivers to test
NIC support for MAE status.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/ef10_nic.c  | 15 +++++++++++++++
 drivers/common/sfc_efx/base/efx.h       |  2 ++
 drivers/common/sfc_efx/base/efx_check.h |  6 ++++++
 drivers/common/sfc_efx/base/siena_nic.c |  2 ++
 drivers/common/sfc_efx/efsys.h          |  2 ++
 5 files changed, 27 insertions(+)

diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c
index df7db6a803..68414d9fa9 100644
--- a/drivers/common/sfc_efx/base/ef10_nic.c
+++ b/drivers/common/sfc_efx/base/ef10_nic.c
@@ -1421,8 +1421,23 @@ ef10_get_datapath_caps(
 	else
 		encp->enc_filter_action_mark_max = 0;
 
+#if EFSYS_OPT_MAE
+	/*
+	 * Indicate support for MAE.
+	 * MAE is supported by Riverhead boards starting with R2,
+	 * and it is required that FW is built with MAE support, too.
+	 */
+	if (CAP_FLAGS3(req, MAE_SUPPORTED))
+		encp->enc_mae_supported = B_TRUE;
+	else
+		encp->enc_mae_supported = B_FALSE;
+#else
+	encp->enc_mae_supported = B_FALSE;
+#endif /* EFSYS_OPT_MAE */
+
 #undef CAP_FLAGS1
 #undef CAP_FLAGS2
+#undef CAP_FLAGS3
 
 	return (0);
 
diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index bd1ac303b1..9947882d26 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -1593,6 +1593,8 @@ typedef struct efx_nic_cfg_s {
 	uint32_t		enc_mac_stats_nstats;
 	boolean_t		enc_fec_counters;
 	boolean_t		enc_hlb_counters;
+	/* NIC support for Match-Action Engine (MAE). */
+	boolean_t		enc_mae_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/efx_check.h b/drivers/common/sfc_efx/base/efx_check.h
index 8f42d87a04..078e5b9811 100644
--- a/drivers/common/sfc_efx/base/efx_check.h
+++ b/drivers/common/sfc_efx/base/efx_check.h
@@ -401,4 +401,10 @@
 # endif
 #endif /* EFSYS_OPT_DESC_PROXY */
 
+#if EFSYS_OPT_MAE
+# if !EFSYS_OPT_RIVERHEAD
+#  error "MAE requires RIVERHEAD"
+# endif
+#endif /* EFSYS_OPT_MAE */
+
 #endif /* _SYS_EFX_CHECK_H */
diff --git a/drivers/common/sfc_efx/base/siena_nic.c b/drivers/common/sfc_efx/base/siena_nic.c
index 4137c1e245..e2af0ff3dc 100644
--- a/drivers/common/sfc_efx/base/siena_nic.c
+++ b/drivers/common/sfc_efx/base/siena_nic.c
@@ -196,6 +196,8 @@ siena_board_cfg(
 	encp->enc_filter_action_mark_supported = B_FALSE;
 	encp->enc_filter_action_mark_max = 0;
 
+	encp->enc_mae_supported = B_FALSE;
+
 	return (0);
 
 fail2:
diff --git a/drivers/common/sfc_efx/efsys.h b/drivers/common/sfc_efx/efsys.h
index f7d5f8a060..8636e73b68 100644
--- a/drivers/common/sfc_efx/efsys.h
+++ b/drivers/common/sfc_efx/efsys.h
@@ -167,6 +167,8 @@ prefetch_read_once(const volatile void *addr)
 
 #define EFSYS_OPT_DESC_PROXY 0
 
+#define EFSYS_OPT_MAE 0
+
 /* ID */
 
 typedef struct __efsys_identifier_s efsys_identifier_t;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 03/62] net/sfc: add a stub for attaching to MAE
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 01/62] common/sfc_efx/base: add MAE definitions to MCDI Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 02/62] common/sfc_efx/base: indicate support for MAE Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 04/62] common/sfc_efx/base: add MAE init/fini APIs Andrew Rybchenko
                     ` (59 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add a stub for MAE attach / detach path and introduce MAE-specific context.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/meson.build |  1 +
 drivers/net/sfc/sfc.c       |  8 ++++++
 drivers/net/sfc/sfc.h       |  2 ++
 drivers/net/sfc/sfc_mae.c   | 49 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   | 41 +++++++++++++++++++++++++++++++
 5 files changed, 101 insertions(+)
 create mode 100644 drivers/net/sfc/sfc_mae.c
 create mode 100644 drivers/net/sfc/sfc_mae.h

diff --git a/drivers/net/sfc/meson.build b/drivers/net/sfc/meson.build
index 589f7863ae..7a893080cb 100644
--- a/drivers/net/sfc/meson.build
+++ b/drivers/net/sfc/meson.build
@@ -47,6 +47,7 @@ sources = files(
 	'sfc_tx.c',
 	'sfc_tso.c',
 	'sfc_filter.c',
+	'sfc_mae.c',
 	'sfc_flow.c',
 	'sfc_dp.c',
 	'sfc_ef10_rx.c',
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 8fa790da55..3b896490f7 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -857,6 +857,10 @@ sfc_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_filter_attach;
 
+	rc = sfc_mae_attach(sa);
+	if (rc != 0)
+		goto fail_mae_attach;
+
 	sfc_log_init(sa, "fini nic");
 	efx_nic_fini(enp);
 
@@ -878,6 +882,9 @@ sfc_attach(struct sfc_adapter *sa)
 
 fail_sriov_vswitch_create:
 	sfc_flow_fini(sa);
+	sfc_mae_detach(sa);
+
+fail_mae_attach:
 	sfc_filter_detach(sa);
 
 fail_filter_attach:
@@ -918,6 +925,7 @@ sfc_detach(struct sfc_adapter *sa)
 
 	sfc_flow_fini(sa);
 
+	sfc_mae_detach(sa);
 	sfc_filter_detach(sa);
 	sfc_rss_detach(sa);
 	sfc_port_detach(sa);
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 047ca64de7..4b5d687108 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -27,6 +27,7 @@
 #include "sfc_log.h"
 #include "sfc_filter.h"
 #include "sfc_sriov.h"
+#include "sfc_mae.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -233,6 +234,7 @@ struct sfc_adapter {
 	struct sfc_intr			intr;
 	struct sfc_port			port;
 	struct sfc_filter		filter;
+	struct sfc_mae			mae;
 
 	struct sfc_flow_list		flow_list;
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
new file mode 100644
index 0000000000..3ce654c19b
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae.c
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#include <stdbool.h>
+
+#include <rte_common.h>
+
+#include "efx.h"
+
+#include "sfc.h"
+#include "sfc_log.h"
+
+int
+sfc_mae_attach(struct sfc_adapter *sa)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+	struct sfc_mae *mae = &sa->mae;
+
+	sfc_log_init(sa, "entry");
+
+	if (!encp->enc_mae_supported) {
+		mae->status = SFC_MAE_STATUS_UNSUPPORTED;
+		return 0;
+	}
+
+	mae->status = SFC_MAE_STATUS_SUPPORTED;
+
+	sfc_log_init(sa, "done");
+
+	return 0;
+}
+
+void
+sfc_mae_detach(struct sfc_adapter *sa)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	sfc_log_init(sa, "entry");
+
+	mae->status = SFC_MAE_STATUS_UNKNOWN;
+
+	sfc_log_init(sa, "done");
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
new file mode 100644
index 0000000000..d7821e71cc
--- /dev/null
+++ b/drivers/net/sfc/sfc_mae.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019 Solarflare Communications Inc.
+ *
+ * This software was jointly developed between OKTET Labs (under contract
+ * for Solarflare) and Solarflare Communications, Inc.
+ */
+
+#ifndef _SFC_MAE_H
+#define _SFC_MAE_H
+
+#include <stdbool.h>
+
+#include "efx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Options for MAE support status */
+enum sfc_mae_status {
+	SFC_MAE_STATUS_UNKNOWN = 0,
+	SFC_MAE_STATUS_UNSUPPORTED,
+	SFC_MAE_STATUS_SUPPORTED
+};
+
+struct sfc_mae {
+	/** NIC support for MAE status */
+	enum sfc_mae_status		status;
+};
+
+struct sfc_adapter;
+
+int sfc_mae_attach(struct sfc_adapter *sa);
+void sfc_mae_detach(struct sfc_adapter *sa);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_MAE_H */
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 04/62] common/sfc_efx/base: add MAE init/fini APIs
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (2 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 03/62] net/sfc: add a stub for attaching to MAE Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 05/62] drivers: init/fini MAE on attach/detach Andrew Rybchenko
                     ` (58 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The patch adds APIs for client drivers to initialise / finalise
MAE-specific context in NIC control structure. The context
itself will be used by the follow-up patches to store
supportive data for library-internal consumers.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 14 +++++
 drivers/common/sfc_efx/base/efx_impl.h        | 10 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 57 +++++++++++++++++++
 drivers/common/sfc_efx/base/meson.build       |  1 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |  3 +
 5 files changed, 85 insertions(+)
 create mode 100644 drivers/common/sfc_efx/base/efx_mae.c

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 9947882d26..f109c8e332 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4036,6 +4036,20 @@ efx_proxy_auth_privilege_modify(
 
 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
 
+#if EFSYS_OPT_MAE
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_init(
+	__in				efx_nic_t *enp);
+
+LIBEFX_API
+extern					void
+efx_mae_fini(
+	__in				efx_nic_t *enp);
+
+#endif /* EFSYS_OPT_MAE */
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 196fd4a79c..8e72796acf 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -780,6 +780,13 @@ typedef struct efx_proxy_ops_s {
 
 #endif /* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
 
+#if EFSYS_OPT_MAE
+
+typedef struct efx_mae_s {
+} efx_mae_t;
+
+#endif /* EFSYS_OPT_MAE */
+
 #define	EFX_DRV_VER_MAX		20
 
 typedef struct efx_drv_cfg_s {
@@ -886,6 +893,9 @@ struct efx_nic_s {
 #if EFSYS_OPT_MCDI_PROXY_AUTH_SERVER
 	const efx_proxy_ops_t	*en_epop;
 #endif	/* EFSYS_OPT_MCDI_PROXY_AUTH_SERVER */
+#if EFSYS_OPT_MAE
+	efx_mae_t		*en_maep;
+#endif	/* EFSYS_OPT_MAE */
 };
 
 #define	EFX_FAMILY_IS_EF10(_enp) \
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
new file mode 100644
index 0000000000..0de9ccb2e0
--- /dev/null
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2019 Xilinx, Inc. All rights reserved.
+ * All rights reserved.
+ */
+
+#include "efx.h"
+#include "efx_impl.h"
+
+
+#if EFSYS_OPT_MAE
+
+	__checkReturn			efx_rc_t
+efx_mae_init(
+	__in				efx_nic_t *enp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_t *maep;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep);
+	if (maep == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	enp->en_maep = maep;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_fini(
+	__in				efx_nic_t *enp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_t *maep = enp->en_maep;
+
+	if (encp->enc_mae_supported == B_FALSE)
+		return;
+
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
+	enp->en_maep = NULL;
+}
+
+#endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/meson.build b/drivers/common/sfc_efx/base/meson.build
index e0acbda993..2016346eb5 100644
--- a/drivers/common/sfc_efx/base/meson.build
+++ b/drivers/common/sfc_efx/base/meson.build
@@ -15,6 +15,7 @@ sources = [
 	'efx_intr.c',
 	'efx_lic.c',
 	'efx_mac.c',
+	'efx_mae.c',
 	'efx_mcdi.c',
 	'efx_mon.c',
 	'efx_nic.c',
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index f656d5b644..c76dfe1e45 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,9 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_fini;
+	efx_mae_init;
+
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
 	efx_mcdi_get_timeout;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 05/62] drivers: init/fini MAE on attach/detach
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (3 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 04/62] common/sfc_efx/base: add MAE init/fini APIs Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 06/62] common/sfc_efx/base: add an MAE limit query API Andrew Rybchenko
                     ` (57 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

These actions affect MAE supplementary resources which are libefx-internal.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/efsys.h |  2 +-
 drivers/net/sfc/sfc_mae.c      | 17 +++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/efsys.h b/drivers/common/sfc_efx/efsys.h
index 8636e73b68..bbe9f2ef12 100644
--- a/drivers/common/sfc_efx/efsys.h
+++ b/drivers/common/sfc_efx/efsys.h
@@ -167,7 +167,7 @@ prefetch_read_once(const volatile void *addr)
 
 #define EFSYS_OPT_DESC_PROXY 0
 
-#define EFSYS_OPT_MAE 0
+#define EFSYS_OPT_MAE 1
 
 /* ID */
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 3ce654c19b..2a7ed6377a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -21,6 +21,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	struct sfc_mae *mae = &sa->mae;
+	int rc;
 
 	sfc_log_init(sa, "entry");
 
@@ -29,21 +30,37 @@ sfc_mae_attach(struct sfc_adapter *sa)
 		return 0;
 	}
 
+	sfc_log_init(sa, "init MAE");
+	rc = efx_mae_init(sa->nic);
+	if (rc != 0)
+		goto fail_mae_init;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 
 	sfc_log_init(sa, "done");
 
 	return 0;
+
+fail_mae_init:
+	sfc_log_init(sa, "failed %d", rc);
+
+	return rc;
 }
 
 void
 sfc_mae_detach(struct sfc_adapter *sa)
 {
 	struct sfc_mae *mae = &sa->mae;
+	enum sfc_mae_status status_prev = mae->status;
 
 	sfc_log_init(sa, "entry");
 
 	mae->status = SFC_MAE_STATUS_UNKNOWN;
 
+	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
+		return;
+
+	efx_mae_fini(sa->nic);
+
 	sfc_log_init(sa, "done");
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 06/62] common/sfc_efx/base: add an MAE limit query API
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (4 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 05/62] drivers: init/fini MAE on attach/detach Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 07/62] net/sfc: add the concept of MAE (transfer) rules Andrew Rybchenko
                     ` (56 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add an API for client drivers to query the engine limits.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 10 +++
 drivers/common/sfc_efx/base/efx_impl.h        |  1 +
 drivers/common/sfc_efx/base/efx_mae.c         | 72 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 84 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index f109c8e332..db66be0faf 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4048,6 +4048,16 @@ extern					void
 efx_mae_fini(
 	__in				efx_nic_t *enp);
 
+typedef struct efx_mae_limits_s {
+	uint32_t			eml_max_n_action_prios;
+} efx_mae_limits_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_get_limits(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_limits_t *emlp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 8e72796acf..6e9329c203 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -783,6 +783,7 @@ typedef struct efx_proxy_ops_s {
 #if EFSYS_OPT_MAE
 
 typedef struct efx_mae_s {
+	uint32_t			em_max_n_action_prios;
 } 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 0de9ccb2e0..c93342de15 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -10,6 +10,47 @@
 
 #if EFSYS_OPT_MAE
 
+static	__checkReturn			efx_rc_t
+efx_mae_get_capabilities(
+	__in				efx_nic_t *enp)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_GET_CAPS_IN_LEN,
+	    MC_CMD_MAE_GET_CAPS_OUT_LEN);
+	struct efx_mae_s *maep = enp->en_maep;
+	efx_rc_t rc;
+
+	req.emr_cmd = MC_CMD_MAE_GET_CAPS;
+	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;
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail1;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail2;
+	}
+
+	maep->em_max_n_action_prios =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_init(
 	__in				efx_nic_t *enp)
@@ -31,8 +72,16 @@ efx_mae_init(
 
 	enp->en_maep = maep;
 
+	rc = efx_mae_get_capabilities(enp);
+	if (rc != 0)
+		goto fail3;
+
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
+	enp->en_maep = NULL;
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
@@ -54,4 +103,27 @@ efx_mae_fini(
 	enp->en_maep = NULL;
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_get_limits(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_limits_t *emlp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	struct efx_mae_s *maep = enp->en_maep;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index c76dfe1e45..4b500b646a 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -86,6 +86,7 @@ INTERNAL {
 	efx_mac_up;
 
 	efx_mae_fini;
+	efx_mae_get_limits;
 	efx_mae_init;
 
 	efx_mcdi_fini;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 07/62] net/sfc: add the concept of MAE (transfer) rules
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (5 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 06/62] common/sfc_efx/base: add an MAE limit query API Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 08/62] common/sfc_efx/base: add match spec init/fini APIs Andrew Rybchenko
                     ` (55 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Define the corresponding specification structure and
make the code identify MAE rules by testing transfer
attribute presence. Also, add a priority level check.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  5 +++--
 drivers/net/sfc/sfc_flow.c  | 26 ++++++++++++++++++++------
 drivers/net/sfc/sfc_flow.h  |  9 +++++++++
 drivers/net/sfc/sfc_mae.c   | 11 +++++++++++
 drivers/net/sfc/sfc_mae.h   |  2 ++
 5 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 959b52c1c3..7a5aff79f9 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -144,8 +144,9 @@ Flow API support
 Supported attributes:
 
 - Ingress
+- Transfer
 
-Supported pattern items:
+Supported pattern items (***non-transfer*** rules):
 
 - VOID
 
@@ -173,7 +174,7 @@ Supported pattern items:
 
 - NVGRE (exact match of virtual subnet ID)
 
-Supported actions:
+Supported actions (***non-transfer*** rules):
 
 - VOID
 
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index cb802d7991..86082208d0 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1124,12 +1124,15 @@ static const struct sfc_flow_item sfc_flow_items[] = {
  * Protocol-independent flow API support
  */
 static int
-sfc_flow_parse_attr(const struct rte_flow_attr *attr,
+sfc_flow_parse_attr(struct sfc_adapter *sa,
+		    const struct rte_flow_attr *attr,
 		    struct rte_flow *flow,
 		    struct rte_flow_error *error)
 {
 	struct sfc_flow_spec *spec = &flow->spec;
 	struct sfc_flow_spec_filter *spec_filter = &spec->filter;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+	struct sfc_mae *mae = &sa->mae;
 
 	if (attr == NULL) {
 		rte_flow_error_set(error, EINVAL,
@@ -1167,10 +1170,20 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr,
 		spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
 		spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
 	} else {
-		rte_flow_error_set(error, ENOTSUP,
-				   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr,
-				   "Transfer is not supported");
-		return -rte_errno;
+		if (mae->status != SFC_MAE_STATUS_SUPPORTED) {
+			rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
+					   attr, "Transfer is not supported");
+			return -rte_errno;
+		}
+		if (attr->priority > mae->nb_action_rule_prios_max) {
+			rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
+					   attr, "Unsupported priority level");
+			return -rte_errno;
+		}
+		spec->type = SFC_FLOW_SPEC_MAE;
+		spec_mae->priority = attr->priority;
 	}
 
 	return 0;
@@ -2403,10 +2416,11 @@ sfc_flow_parse(struct rte_eth_dev *dev,
 	       struct rte_flow *flow,
 	       struct rte_flow_error *error)
 {
+	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	const struct sfc_flow_ops_by_spec *ops;
 	int rc;
 
-	rc = sfc_flow_parse_attr(attr, flow, error);
+	rc = sfc_flow_parse_attr(sa, attr, flow, error);
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 433c7a31e9..1fbcb878d1 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -38,6 +38,7 @@ struct sfc_flow_rss {
 /* Flow engines supported by the implementation */
 enum sfc_flow_spec_type {
 	SFC_FLOW_SPEC_FILTER = 0,
+	SFC_FLOW_SPEC_MAE,
 
 	SFC_FLOW_SPEC_NTYPES
 };
@@ -58,6 +59,12 @@ struct sfc_flow_spec_filter {
 	struct sfc_flow_rss rss_conf;
 };
 
+/* MAE-specific flow specification */
+struct sfc_flow_spec_mae {
+	/* Desired priority level */
+	unsigned int			priority;
+};
+
 /* Flow specification */
 struct sfc_flow_spec {
 	/* Flow specification type (engine-based) */
@@ -67,6 +74,8 @@ struct sfc_flow_spec {
 	union {
 		/* Filter-based (VNIC level flows) specification */
 		struct sfc_flow_spec_filter filter;
+		/* MAE-based (lower-level HW switch flows) specification */
+		struct sfc_flow_spec_mae mae;
 	};
 };
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 2a7ed6377a..487bd61f76 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -21,6 +21,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
 	struct sfc_mae *mae = &sa->mae;
+	efx_mae_limits_t limits;
 	int rc;
 
 	sfc_log_init(sa, "entry");
@@ -35,12 +36,21 @@ sfc_mae_attach(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mae_init;
 
+	sfc_log_init(sa, "get MAE limits");
+	rc = efx_mae_get_limits(sa->nic, &limits);
+	if (rc != 0)
+		goto fail_mae_get_limits;
+
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
+	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
 
 	sfc_log_init(sa, "done");
 
 	return 0;
 
+fail_mae_get_limits:
+	efx_mae_fini(sa->nic);
+
 fail_mae_init:
 	sfc_log_init(sa, "failed %d", rc);
 
@@ -55,6 +65,7 @@ sfc_mae_detach(struct sfc_adapter *sa)
 
 	sfc_log_init(sa, "entry");
 
+	mae->nb_action_rule_prios_max = 0;
 	mae->status = SFC_MAE_STATUS_UNKNOWN;
 
 	if (status_prev != SFC_MAE_STATUS_SUPPORTED)
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index d7821e71cc..dd9ca07d15 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -28,6 +28,8 @@ enum sfc_mae_status {
 struct sfc_mae {
 	/** NIC support for MAE status */
 	enum sfc_mae_status		status;
+	/** Priority level limit for MAE action rules */
+	unsigned int			nb_action_rule_prios_max;
 };
 
 struct sfc_adapter;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 08/62] common/sfc_efx/base: add match spec init/fini APIs
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (6 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 07/62] net/sfc: add the concept of MAE (transfer) rules Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 09/62] net/sfc: add pattern parsing stub to MAE backend Andrew Rybchenko
                     ` (54 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

An MAE rule is a function of match criteria and a priority. The said match
criteria have to be provided using "mask-value pairs" packing format which
on its own should not be exposed to client drivers. The latter have to use
a functional interface of sorts in order to generate a match specification.

Define an EFX match specification and implement initialise / finalise APIs.
The "mask-value pairs" buffer itself is not used in this particular patch,
so the corresponding struct member will be added in the follow-up patch.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 22 +++++++++
 drivers/common/sfc_efx/base/efx_impl.h        |  9 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 46 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  2 +
 4 files changed, 79 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index db66be0faf..40c5968ea9 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4058,6 +4058,28 @@ efx_mae_get_limits(
 	__in				efx_nic_t *enp,
 	__out				efx_mae_limits_t *emlp);
 
+typedef enum efx_mae_rule_type_e {
+	EFX_MAE_RULE_ACTION = 0,
+
+	EFX_MAE_RULE_NTYPES
+} efx_mae_rule_type_t;
+
+typedef struct efx_mae_match_spec_s	efx_mae_match_spec_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_init(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_rule_type_t type,
+	__in				uint32_t prio,
+	__out				efx_mae_match_spec_t **specp);
+
+LIBEFX_API
+extern					void
+efx_mae_match_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *spec);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 6e9329c203..931989f17a 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1675,6 +1675,15 @@ efx_pci_xilinx_cap_tbl_find(
 
 #endif /* EFSYS_OPT_PCI */
 
+#if EFSYS_OPT_MAE
+
+struct efx_mae_match_spec_s {
+	efx_mae_rule_type_t		emms_type;
+	uint32_t			emms_prio;
+};
+
+#endif /* EFSYS_OPT_MAE */
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index c93342de15..b1ebc93714 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -126,4 +126,50 @@ efx_mae_get_limits(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_init(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_rule_type_t type,
+	__in				uint32_t prio,
+	__out				efx_mae_match_spec_t **specp)
+{
+	efx_mae_match_spec_t *spec;
+	efx_rc_t rc;
+
+	switch (type) {
+	case EFX_MAE_RULE_ACTION:
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
+	if (spec == NULL) {
+		rc = ENOMEM;
+		goto fail2;
+	}
+
+	spec->emms_type = type;
+	spec->emms_prio = prio;
+
+	*specp = spec;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_match_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_match_spec_t *spec)
+{
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 4b500b646a..57a6c96b3e 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -88,6 +88,8 @@ INTERNAL {
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
+	efx_mae_match_spec_fini;
+	efx_mae_match_spec_init;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 09/62] net/sfc: add pattern parsing stub to MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (7 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 08/62] common/sfc_efx/base: add match spec init/fini APIs Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 10/62] common/sfc_efx/base: add a match spec validate API Andrew Rybchenko
                     ` (53 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add pattern parsing stub, define and implement flow cleanup method.
The latter is needed to free any dynamic structures allocated
during flow parsing.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 41 +++++++++++++++++++++++-
 drivers/net/sfc/sfc_flow.h |  8 +++++
 drivers/net/sfc/sfc_mae.c  | 65 ++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  | 10 ++++++
 4 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 86082208d0..634818cdf2 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -27,20 +27,30 @@
 
 struct sfc_flow_ops_by_spec {
 	sfc_flow_parse_cb_t	*parse;
+	sfc_flow_cleanup_cb_t	*cleanup;
 	sfc_flow_insert_cb_t	*insert;
 	sfc_flow_remove_cb_t	*remove;
 };
 
 static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;
+static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_mae;
 static sfc_flow_insert_cb_t sfc_flow_filter_insert;
 static sfc_flow_remove_cb_t sfc_flow_filter_remove;
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 	.parse = sfc_flow_parse_rte_to_filter,
+	.cleanup = NULL,
 	.insert = sfc_flow_filter_insert,
 	.remove = sfc_flow_filter_remove,
 };
 
+static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
+	.parse = sfc_flow_parse_rte_to_mae,
+	.cleanup = sfc_mae_flow_cleanup,
+	.insert = NULL,
+	.remove = NULL,
+};
+
 static const struct sfc_flow_ops_by_spec *
 sfc_flow_get_ops_by_spec(struct rte_flow *flow)
 {
@@ -51,6 +61,9 @@ sfc_flow_get_ops_by_spec(struct rte_flow *flow)
 	case SFC_FLOW_SPEC_FILTER:
 		ops = &sfc_flow_ops_filter;
 		break;
+	case SFC_FLOW_SPEC_MAE:
+		ops = &sfc_flow_ops_mae;
+		break;
 	default:
 		SFC_ASSERT(false);
 		break;
@@ -1184,6 +1197,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;
 	}
 
 	return 0;
@@ -2408,6 +2422,25 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
 	return rc;
 }
 
+static int
+sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
+			  const struct rte_flow_item pattern[],
+			  __rte_unused const struct rte_flow_action actions[],
+			  struct rte_flow *flow,
+			  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;
+
+	rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
+	if (rc != 0)
+		return rc;
+
+	return 0;
+}
+
 static int
 sfc_flow_parse(struct rte_eth_dev *dev,
 	       const struct rte_flow_attr *attr,
@@ -2451,8 +2484,14 @@ sfc_flow_zmalloc(struct rte_flow_error *error)
 }
 
 static void
-sfc_flow_free(__rte_unused struct sfc_adapter *sa, struct rte_flow *flow)
+sfc_flow_free(struct sfc_adapter *sa, struct rte_flow *flow)
 {
+	const struct sfc_flow_ops_by_spec *ops;
+
+	ops = sfc_flow_get_ops_by_spec(flow);
+	if (ops != NULL && ops->cleanup != NULL)
+		ops->cleanup(sa, flow);
+
 	rte_free(flow);
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 1fbcb878d1..03a68d8633 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -63,6 +63,8 @@ struct sfc_flow_spec_filter {
 struct sfc_flow_spec_mae {
 	/* Desired priority level */
 	unsigned int			priority;
+	/* EFX match specification */
+	efx_mae_match_spec_t		*match_spec;
 };
 
 /* Flow specification */
@@ -100,6 +102,7 @@ enum sfc_flow_item_layers {
 /* Flow parse context types */
 enum sfc_flow_parse_ctx_type {
 	SFC_FLOW_PARSE_CTX_FILTER = 0,
+	SFC_FLOW_PARSE_CTX_MAE,
 
 	SFC_FLOW_PARSE_CTX_NTYPES
 };
@@ -112,6 +115,8 @@ struct sfc_flow_parse_ctx {
 	union {
 		/* Context pointer valid for filter-based (VNIC) flows */
 		efx_filter_spec_t *filter;
+		/* Context pointer valid for MAE-based flows */
+		struct sfc_mae_parse_ctx *mae;
 	};
 };
 
@@ -154,6 +159,9 @@ typedef int (sfc_flow_parse_cb_t)(struct rte_eth_dev *dev,
 				  struct rte_flow *flow,
 				  struct rte_flow_error *error);
 
+typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
+				     struct rte_flow *flow);
+
 typedef int (sfc_flow_insert_cb_t)(struct sfc_adapter *sa,
 				   struct rte_flow *flow);
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 487bd61f76..53e141775a 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -75,3 +75,68 @@ sfc_mae_detach(struct sfc_adapter *sa)
 
 	sfc_log_init(sa, "done");
 }
+
+void
+sfc_mae_flow_cleanup(struct sfc_adapter *sa,
+		     struct rte_flow *flow)
+{
+	struct sfc_flow_spec *spec;
+	struct sfc_flow_spec_mae *spec_mae;
+
+	if (flow == NULL)
+		return;
+
+	spec = &flow->spec;
+
+	if (spec == NULL)
+		return;
+
+	spec_mae = &spec->mae;
+
+	if (spec_mae->match_spec != NULL)
+		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
+}
+
+static const struct sfc_flow_item sfc_flow_items[] = {
+};
+
+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_error *error)
+{
+	struct sfc_mae_parse_ctx ctx_mae;
+	struct sfc_flow_parse_ctx ctx;
+	int rc;
+
+	memset(&ctx_mae, 0, sizeof(ctx_mae));
+
+	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
+				     spec->priority,
+				     &ctx_mae.match_spec_action);
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Failed to initialise action rule match specification");
+		goto fail_init_match_spec_action;
+	}
+
+	ctx.type = SFC_FLOW_PARSE_CTX_MAE;
+	ctx.mae = &ctx_mae;
+
+	rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
+				    pattern, &ctx, error);
+	if (rc != 0)
+		goto fail_parse_pattern;
+
+	spec->match_spec = ctx_mae.match_spec_action;
+
+	return 0;
+
+fail_parse_pattern:
+	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
+
+fail_init_match_spec_action:
+	return rc;
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index dd9ca07d15..536dadd092 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -33,9 +33,19 @@ struct sfc_mae {
 };
 
 struct sfc_adapter;
+struct sfc_flow_spec;
+
+struct sfc_mae_parse_ctx {
+	efx_mae_match_spec_t		*match_spec_action;
+};
 
 int sfc_mae_attach(struct sfc_adapter *sa);
 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_error *error);
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 10/62] common/sfc_efx/base: add a match spec validate API
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (8 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 09/62] net/sfc: add pattern parsing stub to MAE backend Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 11/62] net/sfc: validate match spec in MAE backend Andrew Rybchenko
                     ` (52 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE has restrictions on what kind of mask a particular field can have in a
match specification. Add an API for client drivers to check specifications.

The patch defines a field description list, whilst the list itself is
left empty. This is to provide a general idea of how field properties
will be used to validate a match specification. Particular fields
will be added to the list by follow-up patches.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  18 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  17 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 262 ++++++++++++++++++
 drivers/common/sfc_efx/base/efx_mcdi.h        |   4 +
 .../sfc_efx/rte_common_sfc_efx_version.map    |   1 +
 5 files changed, 302 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 40c5968ea9..094fad6367 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4080,6 +4080,24 @@ efx_mae_match_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_match_spec_t *spec);
 
+typedef enum efx_mae_field_id_e {
+	EFX_MAE_FIELD_NIDS
+} efx_mae_field_id_t;
+
+/*
+ * Make sure that match fields known by EFX have proper masks set
+ * in the match specification as per requirements of SF-122526-TC.
+ *
+ * In the case efx_mae_field_id_t lacks named identifiers for any
+ * fields which the FW maintains with support status MATCH_ALWAYS,
+ * the validation result may not be accurate.
+ */
+LIBEFX_API
+extern	__checkReturn			boolean_t
+efx_mae_match_spec_is_valid(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 931989f17a..2b872bb62e 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -782,8 +782,22 @@ typedef struct efx_proxy_ops_s {
 
 #if EFSYS_OPT_MAE
 
+typedef struct efx_mae_field_cap_s {
+	uint32_t			emfc_support;
+	boolean_t			emfc_mask_affects_class;
+	boolean_t			emfc_match_affects_class;
+} efx_mae_field_cap_t;
+
 typedef struct efx_mae_s {
 	uint32_t			em_max_n_action_prios;
+	/*
+	 * The number of MAE field IDs recognised by the FW implementation.
+	 * Any field ID greater than or equal to this value is unsupported.
+	 */
+	uint32_t			em_max_nfields;
+	/** Action rule match field capabilities. */
+	efx_mae_field_cap_t		*em_action_rule_field_caps;
+	size_t				em_action_rule_field_caps_size;
 } efx_mae_t;
 
 #endif /* EFSYS_OPT_MAE */
@@ -1680,6 +1694,9 @@ efx_pci_xilinx_cap_tbl_find(
 struct efx_mae_match_spec_s {
 	efx_mae_rule_type_t		emms_type;
 	uint32_t			emms_prio;
+	union emms_mask_value_pairs {
+		uint8_t			action[MAE_FIELD_MASK_VALUE_PAIRS_LEN];
+	} emms_mask_value_pairs;
 };
 
 #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 b1ebc93714..9e22c3d507 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -42,8 +42,93 @@ efx_mae_get_capabilities(
 	maep->em_max_n_action_prios =
 	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
 
+	maep->em_max_nfields =
+	    MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+static	__checkReturn			efx_rc_t
+efx_mae_get_action_rule_caps(
+	__in				efx_nic_t *enp,
+	__in				unsigned int field_ncaps,
+	__out_ecount(field_ncaps)	efx_mae_field_cap_t *field_caps)
+{
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_GET_AR_CAPS_IN_LEN,
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2);
+	unsigned int mcdi_field_ncaps;
+	unsigned int i;
+	efx_rc_t rc;
+
+	if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) >
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
+
+	if (req.emr_out_length_used <
+	    MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	if (mcdi_field_ncaps > field_ncaps) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	for (i = 0; i < mcdi_field_ncaps; ++i) {
+		uint32_t match_flag;
+		uint32_t mask_flag;
+
+		field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_SUPPORT_STATUS);
+
+		match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
+
+		field_caps[i].emfc_match_affects_class =
+		    (match_flag != 0) ? B_TRUE : B_FALSE;
+
+		mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
+		    MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
+		    MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
+
+		field_caps[i].emfc_mask_affects_class =
+		    (mask_flag != 0) ? B_TRUE : B_FALSE;
+	}
+
 	return (0);
 
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
@@ -56,6 +141,8 @@ efx_mae_init(
 	__in				efx_nic_t *enp)
 {
 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mae_field_cap_t *ar_fcaps;
+	size_t ar_fcaps_size;
 	efx_mae_t *maep;
 	efx_rc_t rc;
 
@@ -76,8 +163,27 @@ efx_mae_init(
 	if (rc != 0)
 		goto fail3;
 
+	ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
+	EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
+	if (ar_fcaps == NULL) {
+		rc = ENOMEM;
+		goto fail4;
+	}
+
+	maep->em_action_rule_field_caps_size = ar_fcaps_size;
+	maep->em_action_rule_field_caps = ar_fcaps;
+
+	rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
+	if (rc != 0)
+		goto fail5;
+
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
+	EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
+fail4:
+	EFSYS_PROBE(fail4);
 fail3:
 	EFSYS_PROBE(fail3);
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
@@ -99,6 +205,8 @@ efx_mae_fini(
 	if (encp->enc_mae_supported == B_FALSE)
 		return;
 
+	EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
+	    maep->em_action_rule_field_caps);
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
 	enp->en_maep = NULL;
 }
@@ -172,4 +280,158 @@ efx_mae_match_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+/* Named identifiers which are valid indices to efx_mae_field_cap_t */
+typedef enum efx_mae_field_cap_id_e {
+	EFX_MAE_FIELD_CAP_NIDS
+} efx_mae_field_cap_id_t;
+
+typedef enum efx_mae_field_endianness_e {
+	EFX_MAE_FIELD_LE = 0,
+	EFX_MAE_FIELD_BE,
+
+	EFX_MAE_FIELD_ENDIANNESS_NTYPES
+} efx_mae_field_endianness_t;
+
+/*
+ * The following structure is a means to describe an MAE field.
+ * The information in it is meant to be used internally by
+ * APIs for addressing a given field in a mask-value pairs
+ * structure and for validation purposes.
+ */
+typedef struct efx_mae_mv_desc_s {
+	efx_mae_field_cap_id_t		emmd_field_cap_id;
+
+	size_t				emmd_value_size;
+	size_t				emmd_value_offset;
+	size_t				emmd_mask_size;
+	size_t				emmd_mask_offset;
+
+	efx_mae_field_endianness_t	emmd_endianness;
+} efx_mae_mv_desc_t;
+
+/* Indices to this array are provided by efx_mae_field_id_t */
+static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
+};
+
+#define	EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit)		\
+	    ((_mask)[(_bit) / (_mask_page_nbits)] &			\
+		    (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
+
+static inline				boolean_t
+efx_mask_is_prefix(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	boolean_t prev_bit_is_set = B_TRUE;
+	unsigned int i;
+
+	for (i = 0; i < 8 * mask_nbytes; ++i) {
+		boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i);
+
+		if (!prev_bit_is_set && bit_is_set)
+			return B_FALSE;
+
+		prev_bit_is_set = bit_is_set;
+	}
+
+	return B_TRUE;
+}
+
+static inline				boolean_t
+efx_mask_is_all_ones(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	unsigned int i;
+	uint8_t t = ~0;
+
+	for (i = 0; i < mask_nbytes; ++i)
+		t &= maskp[i];
+
+	return (t == (uint8_t)(~0));
+}
+
+static inline				boolean_t
+efx_mask_is_all_zeros(
+	__in				size_t mask_nbytes,
+	__in_bcount(mask_nbytes)	const uint8_t *maskp)
+{
+	unsigned int i;
+	uint8_t t = 0;
+
+	for (i = 0; i < mask_nbytes; ++i)
+		t |= maskp[i];
+
+	return (t == 0);
+}
+
+	__checkReturn			boolean_t
+efx_mae_match_spec_is_valid(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec)
+{
+	efx_mae_t *maep = enp->en_maep;
+	unsigned int field_ncaps = maep->em_max_nfields;
+	const efx_mae_field_cap_t *field_caps;
+	const efx_mae_mv_desc_t *desc_setp;
+	unsigned int desc_set_nentries;
+	boolean_t is_valid = B_TRUE;
+	efx_mae_field_id_t field_id;
+	const uint8_t *mvp;
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		field_caps = maep->em_action_rule_field_caps;
+		desc_setp = __efx_mae_action_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		return (B_FALSE);
+	}
+
+	if (field_caps == NULL)
+		return (B_FALSE);
+
+	for (field_id = 0; field_id < desc_set_nentries; ++field_id) {
+		const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
+		efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
+		const uint8_t *m_buf = mvp + descp->emmd_mask_offset;
+		size_t m_size = descp->emmd_mask_size;
+
+		if (m_size == 0)
+			continue; /* Skip array gap */
+
+		if (field_cap_id >= field_ncaps)
+			break;
+
+		switch (field_caps[field_cap_id].emfc_support) {
+		case MAE_FIELD_SUPPORTED_MATCH_MASK:
+			is_valid = B_TRUE;
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_PREFIX:
+			is_valid = efx_mask_is_prefix(m_size, m_buf);
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
+			is_valid = (efx_mask_is_all_ones(m_size, m_buf) ||
+			    efx_mask_is_all_zeros(m_size, m_buf));
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
+			is_valid = efx_mask_is_all_ones(m_size, m_buf);
+			break;
+		case MAE_FIELD_SUPPORTED_MATCH_NEVER:
+		case MAE_FIELD_UNSUPPORTED:
+		default:
+			is_valid = efx_mask_is_all_zeros(m_size, m_buf);
+			break;
+		}
+
+		if (is_valid == B_FALSE)
+			break;
+	}
+
+	return (is_valid);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/base/efx_mcdi.h b/drivers/common/sfc_efx/base/efx_mcdi.h
index 77a3d636e2..9dd0a23862 100644
--- a/drivers/common/sfc_efx/base/efx_mcdi.h
+++ b/drivers/common/sfc_efx/base/efx_mcdi.h
@@ -421,6 +421,10 @@ efx_mcdi_phy_module_get_info(
 	EFX_DWORD_FIELD(*MCDI_OUT2(_emr, efx_dword_t, _ofst),		\
 			MC_CMD_ ## _field)
 
+#define	MCDI_OUT_INDEXED_DWORD_FIELD(_emr, _ofst, _idx, _field)		\
+	EFX_DWORD_FIELD(*(MCDI_OUT2(_emr, efx_dword_t, _ofst) +		\
+			(_idx)), _field)
+
 #define	MCDI_EV_FIELD(_eqp, _field)					\
 	EFX_QWORD_FIELD(*_eqp, MCDI_EVENT_ ## _field)
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 57a6c96b3e..0e6d44b6dc 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_init;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
+	efx_mae_match_spec_is_valid;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 11/62] net/sfc: validate match spec in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (9 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 10/62] common/sfc_efx/base: add a match spec validate API Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 12/62] common/sfc_efx/base: add a match specs class comparison API Andrew Rybchenko
                     ` (51 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Validate the match specification resulting from pattern
parsing within MAE backend in RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 53e141775a..7e4397762b 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -130,10 +130,18 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_parse_pattern;
 
+	if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
+		rc = rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+					"Inconsistent pattern");
+		goto fail_validate_match_spec_action;
+	}
+
 	spec->match_spec = ctx_mae.match_spec_action;
 
 	return 0;
 
+fail_validate_match_spec_action:
 fail_parse_pattern:
 	efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
 
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 12/62] common/sfc_efx/base: add a match specs class comparison API
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (10 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 11/62] net/sfc: validate match spec in MAE backend Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 13/62] net/sfc: add verify method to flow validate path Andrew Rybchenko
                     ` (50 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

From MAE standpoint, a flow rule belongs to some class. Field capabilities
advertised by the FW provide a hint on whether changing a particular match
field value or its mask will affect the class of the rule. A client driver
can make use of the concept of a class by comparing a rule being validated
with already inserted ones so that if an existing rule with the same class
is encountered, it will become possible to skip making an explicit request
to the FW because the class of an already inserted rule is wittingly valid.

Implement an API for client drivers to carry out the said class comparison.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 13 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 96 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 3 files changed, 110 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 094fad6367..c91f7948a0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4098,6 +4098,19 @@ efx_mae_match_spec_is_valid(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_match_spec_t *spec);
 
+/*
+ * Conduct a comparison to check whether two match specifications
+ * of equal rule type (action / outer) and priority would map to
+ * the very same rule class from the firmware's standpoint.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_specs_class_cmp(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right,
+	__out				boolean_t *have_same_classp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 9e22c3d507..a126cba37f 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -434,4 +434,100 @@ efx_mae_match_spec_is_valid(
 	return (is_valid);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_match_specs_class_cmp(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *left,
+	__in				const efx_mae_match_spec_t *right,
+	__out				boolean_t *have_same_classp)
+{
+	efx_mae_t *maep = enp->en_maep;
+	unsigned int field_ncaps = maep->em_max_nfields;
+	const efx_mae_field_cap_t *field_caps;
+	const efx_mae_mv_desc_t *desc_setp;
+	unsigned int desc_set_nentries;
+	boolean_t have_same_class = B_TRUE;
+	efx_mae_field_id_t field_id;
+	const uint8_t *mvpl;
+	const uint8_t *mvpr;
+	efx_rc_t rc;
+
+	switch (left->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		field_caps = maep->em_action_rule_field_caps;
+		desc_setp = __efx_mae_action_rule_mv_desc_set;
+		desc_set_nentries =
+		    EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
+		mvpl = left->emms_mask_value_pairs.action;
+		mvpr = right->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (field_caps == NULL) {
+		rc = EAGAIN;
+		goto fail2;
+	}
+
+	if (left->emms_type != right->emms_type ||
+	    left->emms_prio != right->emms_prio) {
+		/*
+		 * Rules of different types can never map to the same class.
+		 *
+		 * The FW can support some set of match criteria for one
+		 * priority and not support the very same set for
+		 * another priority. Thus, two rules which have
+		 * different priorities can never map to
+		 * the same class.
+		 */
+		*have_same_classp = B_FALSE;
+		return (0);
+	}
+
+	for (field_id = 0; field_id < desc_set_nentries; ++field_id) {
+		const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
+		efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
+
+		if (descp->emmd_mask_size == 0)
+			continue; /* Skip array gap */
+
+		if (field_cap_id >= field_ncaps)
+			break;
+
+		if (field_caps[field_cap_id].emfc_mask_affects_class) {
+			const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset;
+			const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset;
+			size_t mask_size = descp->emmd_mask_size;
+
+			if (memcmp(lmaskp, rmaskp, mask_size) != 0) {
+				have_same_class = B_FALSE;
+				break;
+			}
+		}
+
+		if (field_caps[field_cap_id].emfc_match_affects_class) {
+			const uint8_t *lvalp = mvpl + descp->emmd_value_offset;
+			const uint8_t *rvalp = mvpr + descp->emmd_value_offset;
+			size_t value_size = descp->emmd_value_size;
+
+			if (memcmp(lvalp, rvalp, value_size) != 0) {
+				have_same_class = B_FALSE;
+				break;
+			}
+		}
+	}
+
+	*have_same_classp = have_same_class;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 0e6d44b6dc..aeb6f4d134 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,6 +91,7 @@ INTERNAL {
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
 	efx_mae_match_spec_is_valid;
+	efx_mae_match_specs_class_cmp;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 13/62] net/sfc: add verify method to flow validate path
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (11 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 12/62] common/sfc_efx/base: add a match specs class comparison API Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 14/62] common/sfc_efx/base: add action set spec init/fini APIs Andrew Rybchenko
                     ` (49 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The new method is needed to make sure that a flow being
validated will have a chance to be accepted by the FW.
MAE-specific implementation of the method should
compare the class of a rule being validated with
the corresponding classes of active rules, and,
if no matches found, make a request to the FW.
Support for the latter will be added in future.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c | 40 ++++++++++++++++++++
 drivers/net/sfc/sfc_flow.h |  3 ++
 drivers/net/sfc/sfc_mae.c  | 75 ++++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  1 +
 4 files changed, 119 insertions(+)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 634818cdf2..f69dd6ac5d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -27,6 +27,7 @@
 
 struct sfc_flow_ops_by_spec {
 	sfc_flow_parse_cb_t	*parse;
+	sfc_flow_verify_cb_t	*verify;
 	sfc_flow_cleanup_cb_t	*cleanup;
 	sfc_flow_insert_cb_t	*insert;
 	sfc_flow_remove_cb_t	*remove;
@@ -39,6 +40,7 @@ static sfc_flow_remove_cb_t sfc_flow_filter_remove;
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 	.parse = sfc_flow_parse_rte_to_filter,
+	.verify = NULL,
 	.cleanup = NULL,
 	.insert = sfc_flow_filter_insert,
 	.remove = sfc_flow_filter_remove,
@@ -46,6 +48,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
 
 static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
 	.parse = sfc_flow_parse_rte_to_mae,
+	.verify = sfc_mae_flow_verify,
 	.cleanup = sfc_mae_flow_cleanup,
 	.insert = NULL,
 	.remove = NULL,
@@ -2543,6 +2546,41 @@ sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow,
 	return rc;
 }
 
+static int
+sfc_flow_verify(struct sfc_adapter *sa, struct rte_flow *flow,
+		struct rte_flow_error *error)
+{
+	const struct sfc_flow_ops_by_spec *ops;
+	int rc = 0;
+
+	ops = sfc_flow_get_ops_by_spec(flow);
+	if (ops == NULL) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "No backend to handle this flow");
+		return -rte_errno;
+	}
+
+	if (ops->verify != NULL) {
+		/*
+		 * Use locking since verify method may need to
+		 * access the list of already created rules.
+		 */
+		sfc_adapter_lock(sa);
+		rc = ops->verify(sa, flow);
+		sfc_adapter_unlock(sa);
+	}
+
+	if (rc != 0) {
+		rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Failed to verify flow validity with FW");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
 static int
 sfc_flow_validate(struct rte_eth_dev *dev,
 		  const struct rte_flow_attr *attr,
@@ -2559,6 +2597,8 @@ sfc_flow_validate(struct rte_eth_dev *dev,
 		return -rte_errno;
 
 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+	if (rc == 0)
+		rc = sfc_flow_verify(sa, flow, error);
 
 	sfc_flow_free(sa, flow);
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 03a68d8633..164e9f9a9a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -159,6 +159,9 @@ typedef int (sfc_flow_parse_cb_t)(struct rte_eth_dev *dev,
 				  struct rte_flow *flow,
 				  struct rte_flow_error *error);
 
+typedef int (sfc_flow_verify_cb_t)(struct sfc_adapter *sa,
+				   struct rte_flow *flow);
+
 typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
 				     struct rte_flow *flow);
 
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7e4397762b..42200c3f7e 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -148,3 +148,78 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 fail_init_match_spec_action:
 	return rc;
 }
+
+static bool
+sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
+			const efx_mae_match_spec_t *left,
+			const efx_mae_match_spec_t *right)
+{
+	bool have_same_class;
+	int rc;
+
+	rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
+					   &have_same_class);
+
+	return (rc == 0) ? have_same_class : false;
+}
+
+static int
+sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
+				 struct sfc_flow_spec_mae *spec)
+{
+	const struct rte_flow *entry;
+
+	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;
+
+		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);
+		}
+	}
+
+	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
+		 "support for inner frame pattern items is not guaranteed; "
+		 "other than that, the items are valid from SW standpoint");
+	return 0;
+}
+
+/**
+ * Confirm that a given flow can be accepted by the FW.
+ *
+ * @param sa
+ *   Software adapter context
+ * @param flow
+ *   Flow to be verified
+ * @return
+ *   Zero on success and non-zero in the case of error.
+ *   A special value of EAGAIN indicates that the adapter is
+ *   not in started state. This state is compulsory because
+ *   it only makes sense to compare the rule class of the flow
+ *   being validated with classes of the active rules.
+ *   Such classes are wittingly supported by the FW.
+ */
+int
+sfc_mae_flow_verify(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	struct sfc_flow_spec *spec = &flow->spec;
+	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (sa->state != SFC_ADAPTER_STARTED)
+		return EAGAIN;
+
+	return sfc_mae_action_rule_class_verify(sa, spec_mae);
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 536dadd092..4c5bc4c6ce 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -46,6 +46,7 @@ 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_error *error);
+sfc_flow_verify_cb_t sfc_mae_flow_verify;
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 14/62] common/sfc_efx/base: add action set spec init/fini APIs
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (12 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 13/62] net/sfc: add verify method to flow validate path Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-27  9:13     ` Ali Alnubani
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 15/62] net/sfc: add actions parsing stub to MAE backend Andrew Rybchenko
                     ` (48 subsequent siblings)
  62 siblings, 1 reply; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The engine is only able to carry out chosen actions on matching packets in
a strict order. No MCDI exists to identify supported actions and the order.
Still, the definition of the latter is available from the FW documentation.

The general idea is to define an action specification structure and supply
a client driver with APIs for adding actions individually, order-dependent.
A client driver is supposed to invoke an API on every action passed by the
application, and if an out-of-order action follows, the API will reject it.

Add an action set specification stub and supply initialise / finalise APIs.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             | 20 ++++++++++
 drivers/common/sfc_efx/base/efx_impl.h        |  3 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 39 +++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |  3 ++
 4 files changed, 65 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index c91f7948a0..cd0b22d43a 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4098,6 +4098,26 @@ efx_mae_match_spec_is_valid(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_match_spec_t *spec);
 
+typedef struct efx_mae_actions_s efx_mae_actions_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_init(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_actions_t **specp);
+
+LIBEFX_API
+extern					void
+efx_mae_action_set_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_actions_t *spec);
+
+LIBEFX_API
+extern	__checkReturn			boolean_t
+efx_mae_action_set_specs_equal(
+	__in				const efx_mae_actions_t *left,
+	__in				const efx_mae_actions_t *right);
+
 /*
  * Conduct a comparison to check whether two match specifications
  * of equal rule type (action / outer) and priority would map to
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 2b872bb62e..86ef8e1b92 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1699,6 +1699,9 @@ struct efx_mae_match_spec_s {
 	} emms_mask_value_pairs;
 };
 
+typedef struct efx_mae_actions_s {
+} efx_mae_actions_t;
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index a126cba37f..81c586dfe8 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -434,6 +434,45 @@ efx_mae_match_spec_is_valid(
 	return (is_valid);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_init(
+	__in				efx_nic_t *enp,
+	__out				efx_mae_actions_t **specp)
+{
+	efx_mae_actions_t *spec;
+	efx_rc_t rc;
+
+	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
+	if (spec == NULL) {
+		rc = ENOMEM;
+		goto fail1;
+	}
+
+	*specp = spec;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+					void
+efx_mae_action_set_spec_fini(
+	__in				efx_nic_t *enp,
+	__in				efx_mae_actions_t *spec)
+{
+	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
+}
+
+	__checkReturn			boolean_t
+efx_mae_action_set_specs_equal(
+	__in				const efx_mae_actions_t *left,
+	__in				const efx_mae_actions_t *right)
+{
+	return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_match_specs_class_cmp(
 	__in				efx_nic_t *enp,
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index aeb6f4d134..8a4d2b2fff 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,9 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_spec_fini;
+	efx_mae_action_set_spec_init;
+	efx_mae_action_set_specs_equal;
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 15/62] net/sfc: add actions parsing stub to MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (13 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 14/62] common/sfc_efx/base: add action set spec init/fini APIs Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 16/62] common/sfc_efx/base: support setting a PPORT in a match spec Andrew Rybchenko
                     ` (47 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

If parsing a flow results in an action set specification
identical to an already existing one, duplication will
be avoided by reusing the list entry of the latter.
Using an attach helper and a reference counter
is meant to serve the said purpose.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   8 ++-
 drivers/net/sfc/sfc_flow.h |   2 +
 drivers/net/sfc/sfc_mae.c  | 133 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  15 +++++
 4 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f69dd6ac5d..f4d53bf770 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1201,6 +1201,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;
 	}
 
 	return 0;
@@ -2428,7 +2429,7 @@ sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
 static int
 sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 			  const struct rte_flow_item pattern[],
-			  __rte_unused const struct rte_flow_action actions[],
+			  const struct rte_flow_action actions[],
 			  struct rte_flow *flow,
 			  struct rte_flow_error *error)
 {
@@ -2441,6 +2442,11 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
 	if (rc != 0)
 		return rc;
 
+	rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set,
+					error);
+	if (rc != 0)
+		return rc;
+
 	return 0;
 }
 
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 164e9f9a9a..7d15f47e60 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -65,6 +65,8 @@ struct sfc_flow_spec_mae {
 	unsigned int			priority;
 	/* EFX match specification */
 	efx_mae_match_spec_t		*match_spec;
+	/* Action set registry entry */
+	struct sfc_mae_action_set	*action_set;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 42200c3f7e..de2c6b26e4 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -43,6 +43,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
 
 	mae->status = SFC_MAE_STATUS_SUPPORTED;
 	mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
+	TAILQ_INIT(&mae->action_sets);
 
 	sfc_log_init(sa, "done");
 
@@ -76,6 +77,68 @@ sfc_mae_detach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "done");
 }
 
+static struct sfc_mae_action_set *
+sfc_mae_action_set_attach(struct sfc_adapter *sa,
+			  const efx_mae_actions_t *spec)
+{
+	struct sfc_mae_action_set *action_set;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
+		if (efx_mae_action_set_specs_equal(action_set->spec, spec)) {
+			++(action_set->refcnt);
+			return action_set;
+		}
+	}
+
+	return NULL;
+}
+
+static int
+sfc_mae_action_set_add(struct sfc_adapter *sa,
+		       efx_mae_actions_t *spec,
+		       struct sfc_mae_action_set **action_setp)
+{
+	struct sfc_mae_action_set *action_set;
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
+	if (action_set == NULL)
+		return ENOMEM;
+
+	action_set->refcnt = 1;
+	action_set->spec = spec;
+
+	TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
+
+	*action_setp = action_set;
+
+	return 0;
+}
+
+static void
+sfc_mae_action_set_del(struct sfc_adapter *sa,
+		       struct sfc_mae_action_set *action_set)
+{
+	struct sfc_mae *mae = &sa->mae;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(action_set->refcnt != 0);
+
+	--(action_set->refcnt);
+
+	if (action_set->refcnt != 0)
+		return;
+
+	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
+	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
+	rte_free(action_set);
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -93,6 +156,9 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	spec_mae = &spec->mae;
 
+	if (spec_mae->action_set != NULL)
+		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);
 }
@@ -149,6 +215,73 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 	return rc;
 }
 
+static int
+sfc_mae_rule_parse_action(const struct rte_flow_action *action,
+			  __rte_unused efx_mae_actions_t *spec,
+			  struct rte_flow_error *error)
+{
+	switch (action->type) {
+	default:
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+				"Unsupported action");
+	}
+
+	return 0;
+}
+
+int
+sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
+			   const struct rte_flow_action actions[],
+			   struct sfc_mae_action_set **action_setp,
+			   struct rte_flow_error *error)
+{
+	const struct rte_flow_action *action;
+	efx_mae_actions_t *spec;
+	int rc;
+
+	if (actions == NULL) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
+				"NULL actions");
+	}
+
+	rc = efx_mae_action_set_spec_init(sa->nic, &spec);
+	if (rc != 0)
+		goto fail_action_set_spec_init;
+
+	for (action = actions;
+	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
+		rc = sfc_mae_rule_parse_action(action, spec, error);
+		if (rc != 0)
+			goto fail_rule_parse_action;
+	}
+
+	*action_setp = sfc_mae_action_set_attach(sa, spec);
+	if (*action_setp != NULL) {
+		efx_mae_action_set_spec_fini(sa->nic, spec);
+		return 0;
+	}
+
+	rc = sfc_mae_action_set_add(sa, spec, action_setp);
+	if (rc != 0)
+		goto fail_action_set_add;
+
+	return 0;
+
+fail_action_set_add:
+fail_rule_parse_action:
+	efx_mae_action_set_spec_fini(sa->nic, spec);
+
+fail_action_set_spec_init:
+	if (rc > 0) {
+		rc = rte_flow_error_set(error, rc,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			NULL, "Failed to process the action");
+	}
+	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 4c5bc4c6ce..5727962a0b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -18,6 +18,15 @@
 extern "C" {
 #endif
 
+/** Action set registry entry */
+struct sfc_mae_action_set {
+	TAILQ_ENTRY(sfc_mae_action_set)	entries;
+	unsigned int			refcnt;
+	efx_mae_actions_t		*spec;
+};
+
+TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
+
 /** Options for MAE support status */
 enum sfc_mae_status {
 	SFC_MAE_STATUS_UNKNOWN = 0,
@@ -30,6 +39,8 @@ struct sfc_mae {
 	enum sfc_mae_status		status;
 	/** Priority level limit for MAE action rules */
 	unsigned int			nb_action_rule_prios_max;
+	/** Action set registry */
+	struct sfc_mae_action_sets	action_sets;
 };
 
 struct sfc_adapter;
@@ -46,6 +57,10 @@ 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_error *error);
+int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
+			       const struct rte_flow_action actions[],
+			       struct sfc_mae_action_set **action_setp,
+			       struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
 
 #ifdef __cplusplus
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 16/62] common/sfc_efx/base: support setting a PPORT in a match spec
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (14 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 15/62] net/sfc: add actions parsing stub to MAE backend Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 17/62] net/sfc: support flow item PHY PORT in MAE backend Andrew Rybchenko
                     ` (46 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add an API for setting mask-value pairs in a match specification structure
and add support for MAE field INGRESS_PORT of type PPORT.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  48 +++++
 drivers/common/sfc_efx/base/efx_mae.c         | 170 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   3 +
 3 files changed, 221 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index cd0b22d43a..4fb3b02aa8 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4081,9 +4081,57 @@ efx_mae_match_spec_fini(
 	__in				efx_mae_match_spec_t *spec);
 
 typedef enum efx_mae_field_id_e {
+	EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR = 0,
+
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
 
+/* MPORT selector. Used to refer to MPORTs in match/action rules. */
+typedef struct efx_mport_sel_s {
+	uint32_t sel;
+} efx_mport_sel_t;
+
+/*
+ * Get MPORT selector of a physical port.
+ *
+ * The resulting MPORT selector is opaque to the caller and can be
+ * passed as an argument to efx_mae_match_spec_mport_set().
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_mport_by_phy_port(
+	__in				uint32_t phy_port,
+	__out				efx_mport_sel_t *mportp);
+
+/*
+ * Fields which have BE postfix in their named constants are expected
+ * to be passed by callers in big-endian byte order. They will appear
+ * in the MCDI buffer, which is a part of the match specification, in
+ * the very same byte order, that is, no conversion will be performed.
+ *
+ * Fields which don't have BE postfix in their named constants are in
+ * host byte order. MCDI expects them to be little-endian, so the API
+ * will take care to carry out conversion to little-endian byte order.
+ * At the moment, the only field in host byte order is MPORT selector.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__in_bcount(value_size)		const uint8_t *value,
+	__in				size_t mask_size,
+	__in_bcount(mask_size)		const uint8_t *mask);
+
+/* If the mask argument is NULL, the API will use full mask by default. */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_match_spec_mport_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mport_sel_t *valuep,
+	__in_opt			const efx_mport_sel_t *maskp);
+
 /*
  * Make sure that match fields known by EFX have proper masks set
  * in the match specification as per requirements of SF-122526-TC.
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 81c586dfe8..4e6ae2227d 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -282,6 +282,8 @@ efx_mae_match_spec_fini(
 
 /* Named identifiers which are valid indices to efx_mae_field_cap_t */
 typedef enum efx_mae_field_cap_id_e {
+	EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
+
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
 
@@ -311,8 +313,176 @@ typedef struct efx_mae_mv_desc_s {
 
 /* Indices to this array are provided by efx_mae_field_id_t */
 static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
+#define	EFX_MAE_MV_DESC(_name, _endianness)				\
+	[EFX_MAE_FIELD_##_name] =					\
+	{								\
+		EFX_MAE_FIELD_ID_##_name,				\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_LEN,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_OFST,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_LEN,		\
+		MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_OFST,		\
+		_endianness						\
+	}
+
+	EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
+
+#undef EFX_MAE_MV_DESC
 };
 
+	__checkReturn			efx_rc_t
+efx_mae_mport_by_phy_port(
+	__in				uint32_t phy_port,
+	__out				efx_mport_sel_t *mportp)
+{
+	efx_dword_t dword;
+	efx_rc_t rc;
+
+	if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	EFX_POPULATE_DWORD_2(dword,
+	    MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
+	    MAE_MPORT_SELECTOR_PPORT_ID, phy_port);
+
+	memset(mportp, 0, sizeof (*mportp));
+	mportp->sel = dword.ed_u32[0];
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_match_spec_field_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				efx_mae_field_id_t field_id,
+	__in				size_t value_size,
+	__in_bcount(value_size)		const uint8_t *value,
+	__in				size_t mask_size,
+	__in_bcount(mask_size)		const uint8_t *mask)
+{
+	const efx_mae_mv_desc_t *descp;
+	uint8_t *mvp;
+	efx_rc_t rc;
+
+	if (field_id >= EFX_MAE_FIELD_NIDS) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	switch (spec->emms_type) {
+	case EFX_MAE_RULE_ACTION:
+		descp = &__efx_mae_action_rule_mv_desc_set[field_id];
+		mvp = spec->emms_mask_value_pairs.action;
+		break;
+	default:
+		rc = ENOTSUP;
+		goto fail2;
+	}
+
+	if (value_size != descp->emmd_value_size) {
+		rc = EINVAL;
+		goto fail3;
+	}
+
+	if (mask_size != descp->emmd_mask_size) {
+		rc = EINVAL;
+		goto fail4;
+	}
+
+	if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
+		/*
+		 * The mask/value are in network (big endian) order.
+		 * The MCDI request field is also big endian.
+		 */
+		memcpy(mvp + descp->emmd_value_offset, value, value_size);
+		memcpy(mvp + descp->emmd_mask_offset, mask, mask_size);
+	} else {
+		efx_dword_t dword;
+
+		/*
+		 * The mask/value are in host byte order.
+		 * The MCDI request field is little endian.
+		 */
+		switch (value_size) {
+		case 4:
+			EFX_POPULATE_DWORD_1(dword,
+			    EFX_DWORD_0, *(const uint32_t *)value);
+
+			memcpy(mvp + descp->emmd_value_offset,
+			    &dword, sizeof (dword));
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+
+		switch (mask_size) {
+		case 4:
+			EFX_POPULATE_DWORD_1(dword,
+			    EFX_DWORD_0, *(const uint32_t *)mask);
+
+			memcpy(mvp + descp->emmd_mask_offset,
+			    &dword, sizeof (dword));
+			break;
+		default:
+			EFSYS_ASSERT(B_FALSE);
+		}
+	}
+
+	return (0);
+
+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_mport_set(
+	__in				efx_mae_match_spec_t *spec,
+	__in				const efx_mport_sel_t *valuep,
+	__in_opt			const efx_mport_sel_t *maskp)
+{
+	uint32_t full_mask = UINT32_MAX;
+	const uint8_t *vp;
+	const uint8_t *mp;
+	efx_rc_t rc;
+
+	if (valuep == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	vp = (const uint8_t *)&valuep->sel;
+	if (maskp != NULL)
+		mp = (const uint8_t *)&maskp->sel;
+	else
+		mp = (const uint8_t *)&full_mask;
+
+	rc = efx_mae_match_spec_field_set(spec,
+	    EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR,
+	    sizeof (valuep->sel), vp, sizeof (maskp->sel), mp);
+	if (rc != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #define	EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit)		\
 	    ((_mask)[(_bit) / (_mask_page_nbits)] &			\
 		    (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 8a4d2b2fff..86ed437e8d 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -91,10 +91,13 @@ INTERNAL {
 	efx_mae_fini;
 	efx_mae_get_limits;
 	efx_mae_init;
+	efx_mae_match_spec_field_set;
 	efx_mae_match_spec_fini;
 	efx_mae_match_spec_init;
 	efx_mae_match_spec_is_valid;
+	efx_mae_match_spec_mport_set;
 	efx_mae_match_specs_class_cmp;
+	efx_mae_mport_by_phy_port;
 
 	efx_mcdi_fini;
 	efx_mcdi_get_proxy_handle;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 17/62] net/sfc: support flow item PHY PORT in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (15 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 16/62] common/sfc_efx/base: support setting a PPORT in a match spec Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 18/62] common/sfc_efx/base: add MAE match fields for Ethernet Andrew Rybchenko
                     ` (45 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  4 +++
 drivers/net/sfc/sfc_mae.c   | 69 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h   |  1 +
 3 files changed, 74 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 7a5aff79f9..b12e93180e 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -188,6 +188,10 @@ Supported actions (***non-transfer*** rules):
 
 - MARK (supported only with ef10_essb Rx datapath)
 
+Supported pattern items (***transfer*** rules):
+
+- PHY_PORT (cannot repeat; conflicts with other traffic source items)
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index de2c6b26e4..87d2e15d29 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -163,7 +163,76 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
 }
 
+static int
+sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
+				 struct sfc_flow_parse_ctx *ctx,
+				 struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	const struct rte_flow_item_phy_port supp_mask = {
+		.index = 0xffffffff,
+	};
+	const void *def_mask = &rte_flow_item_phy_port_mask;
+	const struct rte_flow_item_phy_port *spec = NULL;
+	const struct rte_flow_item_phy_port *mask = NULL;
+	efx_mport_sel_t mport_v;
+	int rc;
+
+	if (ctx_mae->match_mport_set) {
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Can't handle multiple traffic source items");
+	}
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask, def_mask,
+				 sizeof(struct rte_flow_item_phy_port), error);
+	if (rc != 0)
+		return rc;
+
+	if (mask->index != supp_mask.index) {
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Bad mask in the PHY_PORT pattern item");
+	}
+
+	/* If "spec" is not set, could be any physical port */
+	if (spec == NULL)
+		return 0;
+
+	rc = efx_mae_mport_by_phy_port(spec->index, &mport_v);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to convert the PHY_PORT index");
+	}
+
+	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+					  &mport_v, NULL);
+	if (rc != 0) {
+		return rte_flow_error_set(error, rc,
+				RTE_FLOW_ERROR_TYPE_ITEM, item,
+				"Failed to set MPORT for the PHY_PORT");
+	}
+
+	ctx_mae->match_mport_set = B_TRUE;
+
+	return 0;
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
+	{
+		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
+		/*
+		 * In terms of RTE flow, this item is a META one,
+		 * and its position in the pattern is don't care.
+		 */
+		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.layer = SFC_FLOW_ITEM_ANY_LAYER,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_phy_port,
+	},
 };
 
 int
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 5727962a0b..1ef582e82b 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -48,6 +48,7 @@ struct sfc_flow_spec;
 
 struct sfc_mae_parse_ctx {
 	efx_mae_match_spec_t		*match_spec_action;
+	bool				match_mport_set;
 };
 
 int sfc_mae_attach(struct sfc_adapter *sa);
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 18/62] common/sfc_efx/base: add MAE match fields for Ethernet
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (16 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 17/62] net/sfc: support flow item PHY PORT in MAE backend Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 19/62] net/sfc: support flow item ETH in MAE backend Andrew Rybchenko
                     ` (44 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add MCDI-compatible enumeration for these fields and
provide necessary mappings for them to be inserted
directly into mask-value pairs buffer.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h     | 3 +++
 drivers/common/sfc_efx/base/efx_mae.c | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 4fb3b02aa8..8d88834c30 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4082,6 +4082,9 @@ efx_mae_match_spec_fini(
 
 typedef enum efx_mae_field_id_e {
 	EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR = 0,
+	EFX_MAE_FIELD_ETHER_TYPE_BE,
+	EFX_MAE_FIELD_ETH_SADDR_BE,
+	EFX_MAE_FIELD_ETH_DADDR_BE,
 
 	EFX_MAE_FIELD_NIDS
 } efx_mae_field_id_t;
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 4e6ae2227d..01b2e311a5 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -283,6 +283,9 @@ efx_mae_match_spec_fini(
 /* Named identifiers which are valid indices to efx_mae_field_cap_t */
 typedef enum efx_mae_field_cap_id_e {
 	EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
+	EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
+	EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
+	EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
 
 	EFX_MAE_FIELD_CAP_NIDS
 } efx_mae_field_cap_id_t;
@@ -325,6 +328,9 @@ static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
 	}
 
 	EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
+	EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
+	EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
 
 #undef EFX_MAE_MV_DESC
 };
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 19/62] net/sfc: support flow item ETH in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (17 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 18/62] common/sfc_efx/base: add MAE match fields for Ethernet Andrew Rybchenko
@ 2020-10-20  9:12   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 20/62] common/sfc_efx/base: support adding DELIVER action to a set Andrew Rybchenko
                     ` (43 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:12 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add support for this flow item to MAE-specific RTE flow implementation.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |   2 +
 drivers/net/sfc/sfc_mae.c   | 106 ++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index b12e93180e..65d52d5551 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -192,6 +192,8 @@ Supported pattern items (***transfer*** rules):
 
 - PHY_PORT (cannot repeat; conflicts with other traffic source items)
 
+- ETH
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 87d2e15d29..95f8cffc27 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -221,6 +221,105 @@ sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
 	return 0;
 }
 
+struct sfc_mae_field_locator {
+	efx_mae_field_id_t		field_id;
+	size_t				size;
+	/* Field offset in the corresponding rte_flow_item_ struct */
+	size_t				ofst;
+};
+
+static void
+sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
+			     unsigned int nb_field_locators, void *mask_ptr,
+			     size_t mask_size)
+{
+	unsigned int i;
+
+	memset(mask_ptr, 0, mask_size);
+
+	for (i = 0; i < nb_field_locators; ++i) {
+		const struct sfc_mae_field_locator *fl = &field_locators[i];
+
+		SFC_ASSERT(fl->ofst + fl->size <= mask_size);
+		memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size);
+	}
+}
+
+static int
+sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
+		   unsigned int nb_field_locators, const uint8_t *spec,
+		   const uint8_t *mask, efx_mae_match_spec_t *efx_spec,
+		   struct rte_flow_error *error)
+{
+	unsigned int i;
+	int rc = 0;
+
+	for (i = 0; i < nb_field_locators; ++i) {
+		const struct sfc_mae_field_locator *fl = &field_locators[i];
+
+		rc = efx_mae_match_spec_field_set(efx_spec, fl->field_id,
+						  fl->size, spec + fl->ofst,
+						  fl->size, mask + fl->ofst);
+		if (rc != 0)
+			break;
+	}
+
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
+				NULL, "Failed to process item fields");
+	}
+
+	return rc;
+}
+
+static const struct sfc_mae_field_locator flocs_eth[] = {
+	{
+		EFX_MAE_FIELD_ETHER_TYPE_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type),
+		offsetof(struct rte_flow_item_eth, type),
+	},
+	{
+		EFX_MAE_FIELD_ETH_DADDR_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst),
+		offsetof(struct rte_flow_item_eth, dst),
+	},
+	{
+		EFX_MAE_FIELD_ETH_SADDR_BE,
+		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src),
+		offsetof(struct rte_flow_item_eth, src),
+	},
+};
+
+static int
+sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
+			    struct sfc_flow_parse_ctx *ctx,
+			    struct rte_flow_error *error)
+{
+	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+	struct rte_flow_item_eth supp_mask;
+	const uint8_t *spec = NULL;
+	const uint8_t *mask = NULL;
+	int rc;
+
+	sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
+				     &supp_mask, sizeof(supp_mask));
+
+	rc = sfc_flow_parse_init(item,
+				 (const void **)&spec, (const void **)&mask,
+				 (const void *)&supp_mask,
+				 &rte_flow_item_eth_mask,
+				 sizeof(struct rte_flow_item_eth), error);
+	if (rc != 0)
+		return rc;
+
+	/* If "spec" is not set, could be any Ethernet */
+	if (spec == NULL)
+		return 0;
+
+	return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
+				  ctx_mae->match_spec_action, error);
+}
+
 static const struct sfc_flow_item sfc_flow_items[] = {
 	{
 		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
@@ -233,6 +332,13 @@ static const struct sfc_flow_item sfc_flow_items[] = {
 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
 		.parse = sfc_mae_rule_parse_item_phy_port,
 	},
+	{
+		.type = RTE_FLOW_ITEM_TYPE_ETH,
+		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
+		.layer = SFC_FLOW_ITEM_L2,
+		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+		.parse = sfc_mae_rule_parse_item_eth,
+	},
 };
 
 int
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 20/62] common/sfc_efx/base: support adding DELIVER action to a set
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (18 preceding siblings ...)
  2020-10-20  9:12   ` [dpdk-dev] [PATCH v2 19/62] net/sfc: support flow item ETH in MAE backend Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 21/62] net/sfc: support flow action PHY PORT in MAE backend Andrew Rybchenko
                     ` (42 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Introduce a mechanism for adding actions to an action set and
add support for DELIVER action.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  11 +-
 drivers/common/sfc_efx/base/efx_impl.h        |  11 ++
 drivers/common/sfc_efx/base/efx_mae.c         | 141 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   1 +
 4 files changed, 163 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 8d88834c30..6f63a6ecd0 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4094,11 +4094,14 @@ typedef struct efx_mport_sel_s {
 	uint32_t sel;
 } efx_mport_sel_t;
 
+#define	EFX_MPORT_NULL			(0U)
+
 /*
  * Get MPORT selector of a physical port.
  *
  * The resulting MPORT selector is opaque to the caller and can be
- * passed as an argument to efx_mae_match_spec_mport_set().
+ * passed as an argument to efx_mae_match_spec_mport_set()
+ * and efx_mae_action_set_populate_deliver().
  */
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
@@ -4163,6 +4166,12 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mport_sel_t *mportp);
+
 LIBEFX_API
 extern	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 86ef8e1b92..927324c85c 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1699,7 +1699,18 @@ struct efx_mae_match_spec_s {
 	} emms_mask_value_pairs;
 };
 
+typedef enum efx_mae_action_e {
+	/* DELIVER is always the last action. */
+	EFX_MAE_ACTION_DELIVER,
+
+	EFX_MAE_NACTIONS
+} efx_mae_action_t;
+
 typedef struct efx_mae_actions_s {
+	/* Bitmap of actions in spec, indexed by action type */
+	uint32_t			emass_actions;
+
+	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_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 01b2e311a5..47611c4397 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -641,6 +641,147 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	if (arg_size != sizeof (spec->emass_deliver_mport)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	memcpy(&spec->emass_deliver_mport, arg, arg_size);
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+typedef struct efx_mae_action_desc_s {
+	/* Action specific handler */
+	efx_rc_t	(*emad_add)(efx_mae_actions_t *,
+				    size_t, const uint8_t *);
+} efx_mae_action_desc_t;
+
+static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_DELIVER] = {
+		.emad_add = efx_mae_action_set_add_deliver
+	}
+};
+
+static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_DELIVER);
+
+static const uint32_t efx_mae_action_repeat_map = 0;
+
+/*
+ * Add an action to an action set.
+ *
+ * This has to be invoked in the desired action order.
+ * An out-of-order action request will be turned down.
+ */
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_spec_populate(
+	__in				efx_mae_actions_t *spec,
+	__in				efx_mae_action_t type,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	uint32_t action_mask;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
+	    (sizeof (efx_mae_action_ordered_map) * 8));
+	EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
+	    (sizeof (efx_mae_action_repeat_map) * 8));
+
+	EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
+
+	if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	action_mask = (1U << type);
+
+	if ((spec->emass_actions & action_mask) != 0) {
+		/* The action set already contains this action. */
+		if ((efx_mae_action_repeat_map & action_mask) == 0) {
+			/* Cannot add another non-repeatable action. */
+			rc = ENOTSUP;
+			goto fail2;
+		}
+	}
+
+	if ((efx_mae_action_ordered_map & action_mask) != 0) {
+		uint32_t later_actions_mask =
+			efx_mae_action_ordered_map &
+			~(action_mask | (action_mask - 1));
+
+		if ((spec->emass_actions & later_actions_mask) != 0) {
+			/* Cannot add an action after later ordered actions. */
+			rc = ENOTSUP;
+			goto fail3;
+		}
+	}
+
+	if (efx_mae_actions[type].emad_add != NULL) {
+		rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
+		if (rc != 0)
+			goto fail4;
+	}
+
+	spec->emass_actions |= action_mask;
+
+	return (0);
+
+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_action_set_populate_deliver(
+	__in				efx_mae_actions_t *spec,
+	__in				const efx_mport_sel_t *mportp)
+{
+	const uint8_t *arg;
+	efx_rc_t rc;
+
+	if (mportp == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	arg = (const uint8_t *)&mportp->sel;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 	__checkReturn			boolean_t
 efx_mae_action_set_specs_equal(
 	__in				const efx_mae_actions_t *left,
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 86ed437e8d..d2a5d58ae8 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,7 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 21/62] net/sfc: support flow action PHY PORT in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (19 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 20/62] common/sfc_efx/base: support adding DELIVER action to a set Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 22/62] common/sfc_efx/base: add MAE action set provisioning APIs Andrew Rybchenko
                     ` (41 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The action handler will use MAE action DELIVER with
MPORT of a given physical port.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst |  4 ++++
 drivers/net/sfc/sfc_mae.c   | 40 +++++++++++++++++++++++++++++++++----
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 65d52d5551..e367ddd6e6 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -194,6 +194,10 @@ Supported pattern items (***transfer*** rules):
 
 - ETH
 
+Supported actions (***transfer*** rules):
+
+- PHY_PORT
+
 Validating flow rules depends on the firmware variant.
 
 The :ref:`flow_isolated_mode` is supported.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 95f8cffc27..057eef537b 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -391,18 +391,50 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
 }
 
 static int
-sfc_mae_rule_parse_action(const struct rte_flow_action *action,
-			  __rte_unused efx_mae_actions_t *spec,
+sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
+				   const struct rte_flow_action_phy_port *conf,
+				   efx_mae_actions_t *spec)
+{
+	efx_mport_sel_t mport;
+	uint32_t phy_port;
+	int rc;
+
+	if (conf->original != 0)
+		phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port;
+	else
+		phy_port = conf->index;
+
+	rc = efx_mae_mport_by_phy_port(phy_port, &mport);
+	if (rc != 0)
+		return rc;
+
+	return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
+static int
+sfc_mae_rule_parse_action(struct sfc_adapter *sa,
+			  const struct rte_flow_action *action,
+			  efx_mae_actions_t *spec,
 			  struct rte_flow_error *error)
 {
+	int rc;
+
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
+		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
+		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 				"Unsupported action");
 	}
 
-	return 0;
+	if (rc != 0) {
+		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
+				NULL, "Failed to request the action");
+	}
+
+	return rc;
 }
 
 int
@@ -427,7 +459,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 
 	for (action = actions;
 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
-		rc = sfc_mae_rule_parse_action(action, spec, error);
+		rc = sfc_mae_rule_parse_action(sa, action, spec, error);
 		if (rc != 0)
 			goto fail_rule_parse_action;
 	}
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 22/62] common/sfc_efx/base: add MAE action set provisioning APIs
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (20 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 21/62] net/sfc: support flow action PHY PORT in MAE backend Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 23/62] common/sfc_efx/base: add MAE action rule " Andrew Rybchenko
                     ` (40 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

The patch adds APIs for action set allocation / release.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  20 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 128 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   2 +
 3 files changed, 150 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 6f63a6ecd0..3053da75f8 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4191,6 +4191,26 @@ efx_mae_match_specs_class_cmp(
 	__in				const efx_mae_match_spec_t *right,
 	__out				boolean_t *have_same_classp);
 
+#define	EFX_MAE_RSRC_ID_INVALID	UINT32_MAX
+
+/* Action set ID */
+typedef struct efx_mae_aset_id_s {
+	uint32_t id;
+} efx_mae_aset_id_t;
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_alloc(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_actions_t *spec,
+	__out				efx_mae_aset_id_t *aset_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_aset_id_t *aset_idp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 47611c4397..2626710216 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -886,4 +886,132 @@ efx_mae_match_specs_class_cmp(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_alloc(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_actions_t *spec,
+	__out				efx_mae_aset_id_t *aset_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN,
+	    MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
+	efx_mae_aset_id_t aset_id;
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN;
+
+	/*
+	 * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the
+	 * corresponding resource types are supported by the implementation.
+	 * Use proper resource ID assignments instead.
+	 */
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
+
+	MCDI_IN_SET_DWORD(req,
+	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
+	    MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
+	    MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail3;
+	}
+
+	aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
+	if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail4;
+	}
+
+	aset_idp->id = aset_id.id;
+
+	return (0);
+
+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_action_set_free(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_aset_id_t *aset_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1),
+	    MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) !=
+	    aset_idp->id) {
+		/* Firmware failed to free the action set. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_MAE */
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index d2a5d58ae8..643b3bab52 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,8 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_set_alloc;
+	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 23/62] common/sfc_efx/base: add MAE action rule provisioning APIs
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (21 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 22/62] common/sfc_efx/base: add MAE action set provisioning APIs Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 24/62] net/sfc: implement flow insert/remove in MAE backend Andrew Rybchenko
                     ` (39 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Add APIs for action rule insert / remove operations.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  29 ++++
 drivers/common/sfc_efx/base/efx_mae.c         | 150 ++++++++++++++++++
 .../sfc_efx/rte_common_sfc_efx_version.map    |   2 +
 3 files changed, 181 insertions(+)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 3053da75f8..d37850eda6 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4193,6 +4193,11 @@ efx_mae_match_specs_class_cmp(
 
 #define	EFX_MAE_RSRC_ID_INVALID	UINT32_MAX
 
+/* Rule ID */
+typedef struct efx_mae_rule_id_s {
+	uint32_t id;
+} efx_mae_rule_id_t;
+
 /* Action set ID */
 typedef struct efx_mae_aset_id_s {
 	uint32_t id;
@@ -4211,6 +4216,30 @@ efx_mae_action_set_free(
 	__in				efx_nic_t *enp,
 	__in				const efx_mae_aset_id_t *aset_idp);
 
+/* Action set list ID */
+typedef struct efx_mae_aset_list_id_s {
+	uint32_t id;
+} efx_mae_aset_list_id_t;
+
+/*
+ * Either action set list ID or action set ID must be passed to this API,
+ * but not both.
+ */
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_rule_insert(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec,
+	__in				const efx_mae_aset_list_id_t *asl_idp,
+	__in				const efx_mae_aset_id_t *as_idp,
+	__out				efx_mae_rule_id_t *ar_idp);
+
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_rule_remove(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_rule_id_t *ar_idp);
+
 #endif /* EFSYS_OPT_MAE */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 2626710216..1715cdc4fb 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -1005,6 +1005,156 @@ efx_mae_action_set_free(
 
 	return (0);
 
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
+	__checkReturn			efx_rc_t
+efx_mae_action_rule_insert(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_match_spec_t *spec,
+	__in				const efx_mae_aset_list_id_t *asl_idp,
+	__in				const efx_mae_aset_id_t *as_idp,
+	__out				efx_mae_rule_id_t *ar_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2,
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
+	efx_oword_t *rule_response;
+	efx_mae_rule_id_t ar_id;
+	size_t offset;
+	efx_rc_t rc;
+
+	EFX_STATIC_ASSERT(sizeof (ar_idp->id) ==
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN);
+
+	EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+	    MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	if (spec->emms_type != EFX_MAE_RULE_ACTION ||
+	    (asl_idp != NULL && as_idp != NULL) ||
+	    (asl_idp == NULL && as_idp == NULL)) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2;
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN;
+
+	EFX_STATIC_ASSERT(sizeof (*rule_response) <=
+	    MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN);
+	offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST;
+	rule_response = (efx_oword_t *)(payload + offset);
+	EFX_POPULATE_OWORD_3(*rule_response,
+	    MAE_ACTION_RULE_RESPONSE_ASL_ID,
+	    (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID,
+	    MAE_ACTION_RULE_RESPONSE_AS_ID,
+	    (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID,
+	    MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio);
+
+	/*
+	 * Mask-value pairs have been stored in the byte order needed for the
+	 * MCDI request and are thus safe to be copied directly to the buffer.
+	 */
+	EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
+	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+	offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
+	memcpy(payload + offset, spec->emms_mask_value_pairs.action,
+	    MAE_FIELD_MASK_VALUE_PAIRS_LEN);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
+	if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) {
+		rc = ENOENT;
+		goto fail5;
+	}
+
+	ar_idp->id = ar_id.id;
+
+	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_action_rule_remove(
+	__in				efx_nic_t *enp,
+	__in				const efx_mae_rule_id_t *ar_idp)
+{
+	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+	efx_mcdi_req_t req;
+	EFX_MCDI_DECLARE_BUF(payload,
+	    MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1),
+	    MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
+	efx_rc_t rc;
+
+	if (encp->enc_mae_supported == B_FALSE) {
+		rc = ENOTSUP;
+		goto fail1;
+	}
+
+	req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1);
+
+	MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id);
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail2;
+	}
+
+	if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) !=
+	    ar_idp->id) {
+		/* Firmware failed to delete the action rule. */
+		rc = EAGAIN;
+		goto fail3;
+	}
+
+	return (0);
+
 fail3:
 	EFSYS_PROBE(fail3);
 fail2:
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 643b3bab52..0e0d058c8f 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -85,6 +85,8 @@ INTERNAL {
 	efx_mac_stats_upload;
 	efx_mac_up;
 
+	efx_mae_action_rule_insert;
+	efx_mae_action_rule_remove;
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 24/62] net/sfc: implement flow insert/remove in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (22 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 23/62] common/sfc_efx/base: add MAE action rule " Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 25/62] common/sfc_efx/base: support adding VLAN POP action to a set Andrew Rybchenko
                     ` (38 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

Exercise action set allocation / release and action rule
insertion / removal in order to let flow API callers
actually get created flows functioning.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/net/sfc/sfc_flow.c |   5 +-
 drivers/net/sfc/sfc_flow.h |   2 +
 drivers/net/sfc/sfc_mae.c  | 108 +++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_mae.h  |  12 +++++
 4 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f4d53bf770..3af95ac8ee 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -50,8 +50,8 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
 	.parse = sfc_flow_parse_rte_to_mae,
 	.verify = sfc_mae_flow_verify,
 	.cleanup = sfc_mae_flow_cleanup,
-	.insert = NULL,
-	.remove = NULL,
+	.insert = sfc_mae_flow_insert,
+	.remove = sfc_mae_flow_remove,
 };
 
 static const struct sfc_flow_ops_by_spec *
@@ -1202,6 +1202,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
 		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;
 	}
 
 	return 0;
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 7d15f47e60..d3bdbd5f75 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -67,6 +67,8 @@ struct sfc_flow_spec_mae {
 	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;
 };
 
 /* Flow specification */
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 057eef537b..ea15ccaedb 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -113,6 +113,8 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
 	action_set->refcnt = 1;
 	action_set->spec = spec;
 
+	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+
 	TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
 
 	*action_setp = action_set;
@@ -134,11 +136,62 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
 	if (action_set->refcnt != 0)
 		return;
 
+	SFC_ASSERT(action_set->fw_rsrc.aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set->fw_rsrc.refcnt == 0);
+
 	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
 	rte_free(action_set);
 }
 
+static int
+sfc_mae_action_set_enable(struct sfc_adapter *sa,
+			  struct sfc_mae_action_set *action_set)
+{
+	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	if (fw_rsrc->refcnt == 0) {
+		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+		SFC_ASSERT(action_set->spec != NULL);
+
+		rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
+					      &fw_rsrc->aset_id);
+		if (rc != 0)
+			return rc;
+	}
+
+	++(fw_rsrc->refcnt);
+
+	return 0;
+}
+
+static int
+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;
+	int rc;
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+	SFC_ASSERT(fw_rsrc->aset_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+	if (fw_rsrc->refcnt == 1) {
+		rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
+		if (rc != 0)
+			return rc;
+
+		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+	}
+
+	--(fw_rsrc->refcnt);
+
+	return 0;
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
@@ -156,6 +209,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
 	spec_mae = &spec->mae;
 
+	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+
 	if (spec_mae->action_set != NULL)
 		sfc_mae_action_set_del(sa, spec_mae->action_set);
 
@@ -563,3 +618,56 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 
 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
+
+int
+sfc_mae_flow_insert(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	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_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+	int rc;
+
+	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set != NULL);
+
+	rc = sfc_mae_action_set_enable(sa, action_set);
+	if (rc != 0)
+		goto fail_action_set_enable;
+
+	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
+					NULL, &fw_rsrc->aset_id,
+					&spec_mae->rule_id);
+	if (rc != 0)
+		goto fail_action_rule_insert;
+
+	return 0;
+
+fail_action_rule_insert:
+	(void)sfc_mae_action_set_disable(sa, action_set);
+
+fail_action_set_enable:
+	return rc;
+}
+
+int
+sfc_mae_flow_remove(struct sfc_adapter *sa,
+		    struct rte_flow *flow)
+{
+	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;
+	int rc;
+
+	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
+	SFC_ASSERT(action_set != NULL);
+
+	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
+	if (rc != 0)
+		return rc;
+
+	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+	return sfc_mae_action_set_disable(sa, action_set);
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 1ef582e82b..d9f0ee3cbc 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -18,11 +18,21 @@
 extern "C" {
 #endif
 
+/** FW-allocatable resource context */
+struct sfc_mae_fw_rsrc {
+	unsigned int			refcnt;
+	RTE_STD_C11
+	union {
+		efx_mae_aset_id_t	aset_id;
+	};
+};
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
 	TAILQ_ENTRY(sfc_mae_action_set)	entries;
 	unsigned int			refcnt;
 	efx_mae_actions_t		*spec;
+	struct sfc_mae_fw_rsrc		fw_rsrc;
 };
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
@@ -63,6 +73,8 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
 			       struct sfc_mae_action_set **action_setp,
 			       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;
 
 #ifdef __cplusplus
 }
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 25/62] common/sfc_efx/base: support adding VLAN POP action to a set
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (23 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 24/62] net/sfc: implement flow insert/remove in MAE backend Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 26/62] net/sfc: support flow action OF POP VLAN in MAE backend Andrew Rybchenko
                     ` (37 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE supports stripping two tags, so this action can
be requested once or twice.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  5 ++
 drivers/common/sfc_efx/base/efx_impl.h        |  7 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 54 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index d37850eda6..17bfc6fdfd 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4166,6 +4166,11 @@ efx_mae_action_set_spec_fini(
 	__in				efx_nic_t *enp,
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_pop(
+	__in				efx_mae_actions_t *spec);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 927324c85c..abd7f78cc2 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1700,16 +1700,23 @@ struct efx_mae_match_spec_s {
 };
 
 typedef enum efx_mae_action_e {
+	/* These actions are strictly ordered. */
+	EFX_MAE_ACTION_VLAN_POP,
+
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
 
 	EFX_MAE_NACTIONS
 } efx_mae_action_t;
 
+/* MAE VLAN_POP action can handle 1 or 2 tags. */
+#define	EFX_MAE_VLAN_POP_MAX_NTAGS	(2)
+
 typedef struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			emass_actions;
 
+	unsigned int			emass_n_vlan_tags_to_pop;
 	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_t;
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 1715cdc4fb..0465ddf923 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -641,6 +641,42 @@ efx_mae_action_set_spec_fini(
 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_vlan_pop(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	efx_rc_t rc;
+
+	if (arg_size != 0) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg != NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (spec->emass_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) {
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	++spec->emass_n_vlan_tags_to_pop;
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -677,15 +713,20 @@ typedef struct efx_mae_action_desc_s {
 } efx_mae_action_desc_t;
 
 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
+	[EFX_MAE_ACTION_VLAN_POP] = {
+		.emad_add = efx_mae_action_set_add_vlan_pop
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
 };
 
 static const uint32_t efx_mae_action_ordered_map =
+	(1U << EFX_MAE_ACTION_VLAN_POP) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
-static const uint32_t efx_mae_action_repeat_map = 0;
+static const uint32_t efx_mae_action_repeat_map =
+	(1U << EFX_MAE_ACTION_VLAN_POP);
 
 /*
  * Add an action to an action set.
@@ -759,6 +800,14 @@ efx_mae_action_set_spec_populate(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_pop(
+	__in				efx_mae_actions_t *spec)
+{
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_VLAN_POP, 0, NULL));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -923,6 +972,9 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, EFX_MAE_RSRC_ID_INVALID);
 
+	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->emass_n_vlan_tags_to_pop);
+
 	MCDI_IN_SET_DWORD(req,
 	    MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->emass_deliver_mport.sel);
 
diff --git a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
index 0e0d058c8f..41c14c6451 100644
--- a/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
+++ b/drivers/common/sfc_efx/rte_common_sfc_efx_version.map
@@ -90,6 +90,7 @@ INTERNAL {
 	efx_mae_action_set_alloc;
 	efx_mae_action_set_free;
 	efx_mae_action_set_populate_deliver;
+	efx_mae_action_set_populate_vlan_pop;
 	efx_mae_action_set_spec_fini;
 	efx_mae_action_set_spec_init;
 	efx_mae_action_set_specs_equal;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 26/62] net/sfc: support flow action OF POP VLAN in MAE backend
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (24 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 25/62] common/sfc_efx/base: support adding VLAN POP action to a set Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 27/62] common/sfc_efx/base: support adding VLAN PUSH action Andrew Rybchenko
                     ` (36 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

This action is supported only for rules which have transfer attribute,
and can be requested once or twice per a rule.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 doc/guides/nics/sfc_efx.rst | 2 ++
 drivers/net/sfc/sfc_mae.c   | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index e367ddd6e6..ed9fc9d845 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -196,6 +196,8 @@ Supported pattern items (***transfer*** rules):
 
 Supported actions (***transfer*** rules):
 
+- OF_POP_VLAN
+
 - PHY_PORT
 
 Validating flow rules depends on the firmware variant.
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index ea15ccaedb..a86a22ad8f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -475,6 +475,9 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
 	int rc;
 
 	switch (action->type) {
+	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+		rc = efx_mae_action_set_populate_vlan_pop(spec);
+		break;
 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
 		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
 		break;
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 27/62] common/sfc_efx/base: support adding VLAN PUSH action
  2020-10-20  9:12 ` [dpdk-dev] [PATCH v2 " Andrew Rybchenko
                     ` (25 preceding siblings ...)
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 26/62] net/sfc: support flow action OF POP VLAN in MAE backend Andrew Rybchenko
@ 2020-10-20  9:13   ` Andrew Rybchenko
  2020-10-20  9:13   ` [dpdk-dev] [PATCH v2 28/62] net/sfc: add facilities to handle bundles of actions Andrew Rybchenko
                     ` (35 subsequent siblings)
  62 siblings, 0 replies; 133+ messages in thread
From: Andrew Rybchenko @ 2020-10-20  9:13 UTC (permalink / raw)
  To: dev; +Cc: Ivan Malov

From: Ivan Malov <ivan.malov@oktetlabs.ru>

MAE supports pushing two tags, so this action can
be requested once or twice.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx.h             |  7 ++
 drivers/common/sfc_efx/base/efx_impl.h        | 12 +++
 drivers/common/sfc_efx/base/efx_mae.c         | 86 ++++++++++++++++++-
 .../sfc_efx/rte_common_sfc_efx_version.map    |  1 +
 4 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h
index 17bfc6fdfd..193ffff14c 100644
--- a/drivers/common/sfc_efx/base/efx.h
+++ b/drivers/common/sfc_efx/base/efx.h
@@ -4171,6 +4171,13 @@ extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_vlan_pop(
 	__in				efx_mae_actions_t *spec);
 
+LIBEFX_API
+extern	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				uint16_t tpid_be,
+	__in				uint16_t tci_be);
+
 LIBEFX_API
 extern	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index abd7f78cc2..cefbcac93e 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1702,6 +1702,7 @@ struct efx_mae_match_spec_s {
 typedef enum efx_mae_action_e {
 	/* These actions are strictly ordered. */
 	EFX_MAE_ACTION_VLAN_POP,
+	EFX_MAE_ACTION_VLAN_PUSH,
 
 	/* DELIVER is always the last action. */
 	EFX_MAE_ACTION_DELIVER,
@@ -1712,11 +1713,22 @@ typedef enum efx_mae_action_e {
 /* MAE VLAN_POP action can handle 1 or 2 tags. */
 #define	EFX_MAE_VLAN_POP_MAX_NTAGS	(2)
 
+/* MAE VLAN_PUSH action can handle 1 or 2 tags. */
+#define	EFX_MAE_VLAN_PUSH_MAX_NTAGS	(2)
+
+typedef struct efx_mae_action_vlan_push_s {
+	uint16_t			emavp_tpid_be;
+	uint16_t			emavp_tci_be;
+} efx_mae_action_vlan_push_t;
+
 typedef struct efx_mae_actions_s {
 	/* Bitmap of actions in spec, indexed by action type */
 	uint32_t			emass_actions;
 
 	unsigned int			emass_n_vlan_tags_to_pop;
+	unsigned int			emass_n_vlan_tags_to_push;
+	efx_mae_action_vlan_push_t	emass_vlan_push_descs[
+	    EFX_MAE_VLAN_PUSH_MAX_NTAGS];
 	efx_mport_sel_t			emass_deliver_mport;
 } efx_mae_actions_t;
 
diff --git a/drivers/common/sfc_efx/base/efx_mae.c b/drivers/common/sfc_efx/base/efx_mae.c
index 0465ddf923..b631487645 100644
--- a/drivers/common/sfc_efx/base/efx_mae.c
+++ b/drivers/common/sfc_efx/base/efx_mae.c
@@ -677,6 +677,44 @@ efx_mae_action_set_add_vlan_pop(
 	return (rc);
 }
 
+static	__checkReturn			efx_rc_t
+efx_mae_action_set_add_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				size_t arg_size,
+	__in_bcount(arg_size)		const uint8_t *arg)
+{
+	unsigned int n_tags = spec->emass_n_vlan_tags_to_push;
+	efx_rc_t rc;
+
+	if (arg_size != sizeof (*spec->emass_vlan_push_descs)) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	if (arg == NULL) {
+		rc = EINVAL;
+		goto fail2;
+	}
+
+	if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
+		rc = ENOTSUP;
+		goto fail3;
+	}
+
+	memcpy(&spec->emass_vlan_push_descs[n_tags], arg, arg_size);
+	++(spec->emass_n_vlan_tags_to_push);
+
+	return (0);
+
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+	return (rc);
+}
+
 static	__checkReturn			efx_rc_t
 efx_mae_action_set_add_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -716,6 +754,9 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 	[EFX_MAE_ACTION_VLAN_POP] = {
 		.emad_add = efx_mae_action_set_add_vlan_pop
 	},
+	[EFX_MAE_ACTION_VLAN_PUSH] = {
+		.emad_add = efx_mae_action_set_add_vlan_push
+	},
 	[EFX_MAE_ACTION_DELIVER] = {
 		.emad_add = efx_mae_action_set_add_deliver
 	}
@@ -723,10 +764,12 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
 
 static const uint32_t efx_mae_action_ordered_map =
 	(1U << EFX_MAE_ACTION_VLAN_POP) |
+	(1U << EFX_MAE_ACTION_VLAN_PUSH) |
 	(1U << EFX_MAE_ACTION_DELIVER);
 
 static const uint32_t efx_mae_action_repeat_map =
-	(1U << EFX_MAE_ACTION_VLAN_POP);
+	(1U << EFX_MAE_ACTION_VLAN_POP) |
+	(1U << EFX_MAE_ACTION_VLAN_PUSH);
 
 /*
  * Add an action to an action set.
@@ -808,6 +851,22 @@ efx_mae_action_set_populate_vlan_pop(
 	    EFX_MAE_ACTION_VLAN_POP, 0, NULL));
 }
 
+	__checkReturn			efx_rc_t
+efx_mae_action_set_populate_vlan_push(
+	__in				efx_mae_actions_t *spec,
+	__in				uint16_t tpid_be,
+	__in				uint16_t tci_be)
+{
+	efx_mae_action_vlan_push_t action;
+	const uint8_t *arg = (const uint8_t *)&action;
+
+	action.emavp_tpid_be = tpid_be;
+	action.emavp_tci_be = tci_be;
+
+	return (efx_mae_action_set_spec_populate(spec,
+	    EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
+}
+
 	__checkReturn			efx_rc_t
 efx_mae_action_set_populate_deliver(
 	__in				efx_mae_actions_t *spec,
@@ -975,6 +1034,31 @@ efx_mae_action_set_alloc(
 	MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
 	    MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->emass_n_vlan_tags_to_pop);
 
+	if (spec->emass_n_vlan_tags_to_push > 0) {
+		unsigned int outer_tag_idx;
+
+		MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
+		    MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH,
+		    spec->emass_n_vlan_tags_to_push);
+
+		if (spec->emass_n_vlan_tags_to_push ==
+		    EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
+			MCDI_IN_SET_WORD(req,
+			    MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
+			    spec->emass_vlan_push_descs[0].emavp_tpid_be);
+			MCDI_IN_SET_WORD(req,
+			    MAE