net/sfc: fence off 8 bits in Rx mark for tunnel offload
authorIvan Malov <ivan.malov@oktetlabs.ru>
Wed, 13 Oct 2021 13:15:04 +0000 (16:15 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 13 Oct 2021 14:39:11 +0000 (16:39 +0200)
Later patches add support for tunnel offload on Riverhead (EF100).
A board can host at most 254 tunnels. Partially offloaded (missed)
tunnel packets are identified by virtue of 8 high bits in Rx mark.

Add basic definitions of the upcoming tunnel offload support and
take care of the dedicated bits in Rx mark across the driver.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
drivers/net/sfc/meson.build
drivers/net/sfc/sfc_dp_rx.h
drivers/net/sfc/sfc_ef100_rx.c
drivers/net/sfc/sfc_ethdev.c
drivers/net/sfc/sfc_flow.c
drivers/net/sfc/sfc_flow_tunnel.c [new file with mode: 0644]
drivers/net/sfc/sfc_flow_tunnel.h [new file with mode: 0644]
drivers/net/sfc/sfc_mae.c
drivers/net/sfc/sfc_rx.c

index 98365e9..3308733 100644 (file)
@@ -90,6 +90,7 @@ sources = files(
         'sfc_mae.c',
         'sfc_mae_counter.c',
         'sfc_flow.c',
+        'sfc_flow_tunnel.c',
         'sfc_dp.c',
         'sfc_ef10_rx.c',
         'sfc_ef10_essb_rx.c',
index d037aca..099f026 100644 (file)
@@ -92,6 +92,9 @@ struct sfc_dp_rx_qcreate_info {
        efsys_dma_addr_t        fcw_offset;
        /** VI window size shift */
        unsigned int            vi_window_shift;
+
+       /** Mask to extract user bits from Rx prefix mark field */
+       uint32_t                user_mark_mask;
 };
 
 /**
index d6308dc..2b88de1 100644 (file)
@@ -20,7 +20,9 @@
 #include "efx_regs_ef100.h"
 #include "efx.h"
 
+#include "sfc.h"
 #include "sfc_debug.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_tweak.h"
 #include "sfc_dp_rx.h"
 #include "sfc_kvargs.h"
@@ -75,6 +77,7 @@ struct sfc_ef100_rxq {
        uint64_t                        rearm_data;
        uint16_t                        buf_size;
        uint16_t                        prefix_size;
+       uint32_t                        user_mark_mask;
 
        unsigned int                    evq_hw_index;
        volatile void                   *evq_prime;
@@ -423,10 +426,13 @@ sfc_ef100_rx_prefix_to_offloads(const struct sfc_ef100_rxq *rxq,
 
        if (rxq->flags & SFC_EF100_RXQ_USER_MARK) {
                uint32_t user_mark;
+               uint32_t mark;
 
                /* EFX_XWORD_FIELD converts little-endian to CPU */
-               user_mark = EFX_XWORD_FIELD(rx_prefix[0],
-                                           ESF_GZ_RX_PREFIX_USER_MARK);
+               mark = EFX_XWORD_FIELD(rx_prefix[0],
+                                      ESF_GZ_RX_PREFIX_USER_MARK);
+
+               user_mark = mark & rxq->user_mark_mask;
                if (user_mark != SFC_EF100_USER_MARK_INVALID) {
                        ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
                        m->hash.fdir.hi = user_mark;
@@ -760,6 +766,10 @@ sfc_ef100_rx_qcreate(uint16_t port_id, uint16_t queue_id,
        rxq->max_fill_level = info->max_fill_level;
        rxq->refill_threshold = info->refill_threshold;
        rxq->prefix_size = info->prefix_size;
+
+       SFC_ASSERT(info->user_mark_mask != 0);
+       rxq->user_mark_mask = info->user_mark_mask;
+
        rxq->buf_size = info->buf_size;
        rxq->refill_mb_pool = info->refill_mb_pool;
        rxq->rxq_hw_ring = info->rxq_hw_ring;
index c0d9810..e127b18 100644 (file)
@@ -26,6 +26,7 @@
 #include "sfc_rx.h"
 #include "sfc_tx.h"
 #include "sfc_flow.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_dp.h"
 #include "sfc_dp_rx.h"
 #include "sfc_repr.h"
@@ -2332,6 +2333,9 @@ sfc_rx_metadata_negotiate(struct rte_eth_dev *dev, uint64_t *features)
        if ((sa->priv.dp_rx->features & SFC_DP_RX_FEAT_FLOW_MARK) != 0)
                supported |= RTE_ETH_RX_METADATA_USER_MARK;
 
+       if (sfc_flow_tunnel_is_supported(sa))
+               supported |= RTE_ETH_RX_METADATA_TUNNEL_ID;
+
        sa->negotiated_rx_metadata = supported & *features;
        *features = sa->negotiated_rx_metadata;
 
index 9e6d810..2510724 100644 (file)
@@ -22,6 +22,7 @@
 #include "sfc_rx.h"
 #include "sfc_filter.h"
 #include "sfc_flow.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_log.h"
 #include "sfc_dp_rx.h"
 #include "sfc_mae_counter.h"
@@ -1740,8 +1741,13 @@ sfc_flow_parse_mark(struct sfc_adapter *sa,
        struct sfc_flow_spec *spec = &flow->spec;
        struct sfc_flow_spec_filter *spec_filter = &spec->filter;
        const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+       uint32_t mark_max;
 
-       if (mark == NULL || mark->id > encp->enc_filter_action_mark_max)
+       mark_max = encp->enc_filter_action_mark_max;
+       if (sfc_flow_tunnel_is_active(sa))
+               mark_max = RTE_MIN(mark_max, SFC_FT_USER_MARK_MASK);
+
+       if (mark == NULL || mark->id > mark_max)
                return EINVAL;
 
        spec_filter->template.efs_flags |= EFX_FILTER_FLAG_ACTION_MARK;
diff --git a/drivers/net/sfc/sfc_flow_tunnel.c b/drivers/net/sfc/sfc_flow_tunnel.c
new file mode 100644 (file)
index 0000000..2a0cf29
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2021 Xilinx, Inc.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "sfc.h"
+#include "sfc_dp_rx.h"
+#include "sfc_flow_tunnel.h"
+#include "sfc_mae.h"
+
+bool
+sfc_flow_tunnel_is_supported(struct sfc_adapter *sa)
+{
+       SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+       return ((sa->priv.dp_rx->features & SFC_DP_RX_FEAT_FLOW_MARK) != 0 &&
+               sa->mae.status == SFC_MAE_STATUS_SUPPORTED);
+}
+
+bool
+sfc_flow_tunnel_is_active(struct sfc_adapter *sa)
+{
+       SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+       return ((sa->negotiated_rx_metadata &
+                RTE_ETH_RX_METADATA_TUNNEL_ID) != 0);
+}
diff --git a/drivers/net/sfc/sfc_flow_tunnel.h b/drivers/net/sfc/sfc_flow_tunnel.h
new file mode 100644 (file)
index 0000000..fec891f
--- /dev/null
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright(c) 2021 Xilinx, Inc.
+ */
+
+#ifndef _SFC_FLOW_TUNNEL_H
+#define _SFC_FLOW_TUNNEL_H
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Flow Tunnel (FT) SW entry ID */
+typedef uint8_t sfc_ft_id_t;
+
+#define SFC_FT_TUNNEL_MARK_BITS \
+       (sizeof(sfc_ft_id_t) * CHAR_BIT)
+
+#define SFC_FT_USER_MARK_BITS \
+       (sizeof(uint32_t) * CHAR_BIT - SFC_FT_TUNNEL_MARK_BITS)
+
+#define SFC_FT_USER_MARK_MASK \
+       RTE_LEN2MASK(SFC_FT_USER_MARK_BITS, uint32_t)
+
+struct sfc_adapter;
+
+bool sfc_flow_tunnel_is_supported(struct sfc_adapter *sa);
+
+bool sfc_flow_tunnel_is_active(struct sfc_adapter *sa);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SFC_FLOW_TUNNEL_H */
index 571673a..9c1e6f1 100644 (file)
@@ -16,6 +16,7 @@
 #include "efx.h"
 
 #include "sfc.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_mae_counter.h"
 #include "sfc_log.h"
 #include "sfc_switch.h"
@@ -2923,6 +2924,11 @@ sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
 {
        int rc;
 
+       if (conf->id > SFC_FT_USER_MARK_MASK) {
+               sfc_err(sa, "the mark value is too large");
+               return EINVAL;
+       }
+
        rc = efx_mae_action_set_populate_mark(spec, conf->id);
        if (rc != 0)
                sfc_err(sa, "failed to request action MARK: %s", strerror(rc));
index 5e120f5..2c779c4 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "sfc.h"
 #include "sfc_debug.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_log.h"
 #include "sfc_ev.h"
 #include "sfc_rx.h"
@@ -1181,7 +1182,8 @@ sfc_rx_qinit(struct sfc_adapter *sa, sfc_sw_index_t sw_index,
        if ((sa->negotiated_rx_metadata & RTE_ETH_RX_METADATA_USER_FLAG) != 0)
                rxq_info->type_flags |= EFX_RXQ_FLAG_USER_FLAG;
 
-       if ((sa->negotiated_rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0)
+       if ((sa->negotiated_rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0 ||
+           sfc_flow_tunnel_is_active(sa))
                rxq_info->type_flags |= EFX_RXQ_FLAG_USER_MARK;
 
        rc = sfc_ev_qinit(sa, SFC_EVQ_TYPE_RX, sw_index,
@@ -1231,6 +1233,12 @@ sfc_rx_qinit(struct sfc_adapter *sa, sfc_sw_index_t sw_index,
        info.buf_size = buf_size;
        info.batch_max = encp->enc_rx_batch_max;
        info.prefix_size = encp->enc_rx_prefix_size;
+
+       if (sfc_flow_tunnel_is_active(sa))
+               info.user_mark_mask = SFC_FT_USER_MARK_MASK;
+       else
+               info.user_mark_mask = UINT32_MAX;
+
        info.flags = rxq_info->rxq_flags;
        info.rxq_entries = rxq_info->entries;
        info.rxq_hw_ring = rxq->mem.esm_base;