DRV_LOG(DEBUG, "Flow Hit ASO is supported.");
}
#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO */
+#if defined(HAVE_MLX5_DR_CREATE_ACTION_ASO) && \
+ defined(HAVE_MLX5_DR_ACTION_ASO_CT)
+ if (config->hca_attr.ct_offload &&
+ priv->mtr_color_reg == REG_C_3) {
+ err = mlx5_flow_aso_ct_mng_init(sh);
+ if (err) {
+ err = -err;
+ goto error;
+ }
+ DRV_LOG(DEBUG, "CT ASO is supported.");
+ sh->ct_aso_en = 1;
+ }
+#endif /* HAVE_MLX5_DR_CREATE_ACTION_ASO && HAVE_MLX5_DR_ACTION_ASO_CT */
#if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_SAMPLE)
if (config->hca_attr.log_max_ft_sampler_num > 0 &&
config->dv_flow_en) {
}
}
+/*
+ * Initialize the ASO connection tracking structure.
+ *
+ * @param[in] sh
+ * Pointer to mlx5_dev_ctx_shared object.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_flow_aso_ct_mng_init(struct mlx5_dev_ctx_shared *sh)
+{
+ int err;
+
+ if (sh->ct_mng)
+ return 0;
+ sh->ct_mng = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*sh->ct_mng),
+ RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
+ if (!sh->ct_mng) {
+ DRV_LOG(ERR, "ASO CT management allocation failed.");
+ rte_errno = ENOMEM;
+ return -rte_errno;
+ }
+ err = mlx5_aso_queue_init(sh, ASO_OPC_MOD_CONNECTION_TRACKING);
+ if (err) {
+ mlx5_free(sh->ct_mng);
+ /* rte_errno should be extracted from the failure. */
+ rte_errno = EINVAL;
+ return -rte_errno;
+ }
+ rte_spinlock_init(&sh->ct_mng->ct_sl);
+ rte_rwlock_init(&sh->ct_mng->resize_rwl);
+ LIST_INIT(&sh->ct_mng->free_cts);
+ return 0;
+}
+
/**
* Initialize the flow resources' indexed mempool.
*
} ports[MLX5_BOND_MAX_PORTS];
};
+/* Number of connection tracking objects per pool: must be a power of 2. */
+#define MLX5_ASO_CT_ACTIONS_PER_POOL 64
+
+/* ASO Conntrack state. */
+enum mlx5_aso_ct_state {
+ ASO_CONNTRACK_FREE, /* Inactive, in the free list. */
+ ASO_CONNTRACK_WAIT, /* WQE sent in the SQ. */
+ ASO_CONNTRACK_READY, /* CQE received w/o error. */
+ ASO_CONNTRACK_QUERY, /* WQE for query sent. */
+ ASO_CONNTRACK_MAX, /* Guard. */
+};
+
+/* Generic ASO connection tracking structure. */
+struct mlx5_aso_ct_action {
+ LIST_ENTRY(mlx5_aso_ct_action) next; /* Pointer to the next ASO CT. */
+ void *dr_action_orig; /* General action object for original dir. */
+ void *dr_action_rply; /* General action object for reply dir. */
+ uint32_t refcnt; /* Action used count in device flows. */
+ uint16_t offset; /* Offset of ASO CT in DevX objects bulk. */
+ uint16_t peer; /* The only peer port index could also use this CT. */
+ enum mlx5_aso_ct_state state; /* ASO CT state. */
+ bool is_original; /* The direction of the DR action to be used. */
+};
+
+/* ASO connection tracking software pool definition. */
+struct mlx5_aso_ct_pool {
+ uint16_t index; /* Pool index in pools array. */
+ struct mlx5_devx_obj *devx_obj;
+ /* The first devx object in the bulk, used for freeing (not yet). */
+ struct mlx5_aso_ct_action actions[MLX5_ASO_CT_ACTIONS_PER_POOL];
+ /* CT action structures bulk. */
+};
+
+LIST_HEAD(aso_ct_list, mlx5_aso_ct_action);
+
+/* Pools management structure for ASO connection tracking pools. */
+struct mlx5_aso_ct_pools_mng {
+ struct mlx5_aso_ct_pool **pools;
+ uint16_t n; /* Total number of pools. */
+ uint16_t next; /* Number of pools in use, index of next free pool. */
+ rte_spinlock_t ct_sl; /* The ASO CT free list lock. */
+ rte_rwlock_t resize_rwl; /* The ASO CT pool resize lock. */
+ struct aso_ct_list free_cts; /* Free ASO CT objects list. */
+ struct mlx5_aso_sq aso_sq; /* ASO queue objects. */
+};
+
/*
* Shared Infiniband device context for Master/Representors
* which belong to same IB device with multiple IB ports.
uint32_t sq_ts_format:2; /* SQ timestamp formats supported. */
uint32_t qp_ts_format:2; /* QP timestamp formats supported. */
uint32_t meter_aso_en:1; /* Flow Meter ASO is supported. */
+ uint32_t ct_aso_en:1; /* Connection Tracking ASO is supported. */
uint32_t max_port; /* Maximal IB device port index. */
struct mlx5_bond_info bond; /* Bonding information. */
void *ctx; /* Verbs/DV/DevX context. */
rte_spinlock_t geneve_tlv_opt_sl; /* Lock for geneve tlv resource */
struct mlx5_flow_mtr_mng *mtrmng;
/* Meter management structure. */
+ struct mlx5_aso_ct_pools_mng *ct_mng;
+ /* Management data for ASO connection tracking. */
struct mlx5_dev_shared_port port[]; /* per device port data array. */
};
int mlx5_flex_parser_ecpri_alloc(struct rte_eth_dev *dev);
int mlx5_flow_aso_age_mng_init(struct mlx5_dev_ctx_shared *sh);
int mlx5_aso_flow_mtrs_mng_init(struct mlx5_dev_ctx_shared *sh);
+int mlx5_flow_aso_ct_mng_init(struct mlx5_dev_ctx_shared *sh);
/* mlx5_ethdev.c */
}
}
+/*
+ * Initialize Send Queue used for ASO connection tracking.
+ *
+ * @param[in] sq
+ * ASO SQ to initialize.
+ */
+static void
+mlx5_aso_ct_init_sq(struct mlx5_aso_sq *sq)
+{
+ volatile struct mlx5_aso_wqe *restrict wqe;
+ int i;
+ int size = 1 << sq->log_desc_n;
+ uint64_t addr;
+
+ /* All the next fields state should stay constant. */
+ for (i = 0, wqe = &sq->sq_obj.aso_wqes[0]; i < size; ++i, ++wqe) {
+ wqe->general_cseg.sq_ds = rte_cpu_to_be_32((sq->sqn << 8) |
+ (sizeof(*wqe) >> 4));
+ /* One unique MR for the query data. */
+ wqe->aso_cseg.lkey = rte_cpu_to_be_32(sq->mr.lkey);
+ /* Magic number 64 represents the length of a ASO CT obj. */
+ addr = (uint64_t)((uintptr_t)sq->mr.addr + i * 64);
+ wqe->aso_cseg.va_h = rte_cpu_to_be_32((uint32_t)(addr >> 32));
+ wqe->aso_cseg.va_l_r = rte_cpu_to_be_32((uint32_t)addr | 1u);
+ /*
+ * The values of operand_masks are different for modify
+ * and query.
+ * And data_mask may be different for each modification. In
+ * query, it could be zero and ignored.
+ * CQE generation is always needed, in order to decide when
+ * it is available to create the flow or read the data.
+ */
+ wqe->general_cseg.flags = RTE_BE32(MLX5_COMP_ALWAYS <<
+ MLX5_COMP_MODE_OFFSET);
+ }
+}
+
/**
* Create Send Queue used for ASO access.
*
return -1;
mlx5_aso_mtr_init_sq(&sh->mtrmng->pools_mng.sq);
break;
+ case ASO_OPC_MOD_CONNECTION_TRACKING:
+ /* 64B per object for query. */
+ if (mlx5_aso_reg_mr(sh, 64 * sq_desc_n,
+ &sh->ct_mng->aso_sq.mr, 0))
+ return -1;
+ if (mlx5_aso_sq_create(sh->ctx, &sh->ct_mng->aso_sq, 0,
+ sh->tx_uar, sh->pdn, MLX5_ASO_QUEUE_LOG_DESC,
+ sh->sq_ts_format)) {
+ mlx5_aso_dereg_mr(sh, &sh->ct_mng->aso_sq.mr);
+ return -1;
+ }
+ mlx5_aso_ct_init_sq(&sh->ct_mng->aso_sq);
+ break;
default:
DRV_LOG(ERR, "Unknown ASO operation mode");
return -1;