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>
'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',
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;
};
/**
#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"
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;
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;
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;
#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"
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;
#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"
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;
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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 */
#include "efx.h"
#include "sfc.h"
+#include "sfc_flow_tunnel.h"
#include "sfc_mae_counter.h"
#include "sfc_log.h"
#include "sfc_switch.h"
{
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));
#include "sfc.h"
#include "sfc_debug.h"
+#include "sfc_flow_tunnel.h"
#include "sfc_log.h"
#include "sfc_ev.h"
#include "sfc_rx.h"
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,
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;