xref: /dpdk/drivers/net/sfc/sfc_flow_tunnel.c (revision f55fe01f88a6802f27df96d78a489306370406a4)
153a80512SIvan Malov /* SPDX-License-Identifier: BSD-3-Clause
253a80512SIvan Malov  *
353a80512SIvan Malov  * Copyright(c) 2021 Xilinx, Inc.
453a80512SIvan Malov  */
553a80512SIvan Malov 
653a80512SIvan Malov #include <stdbool.h>
753a80512SIvan Malov #include <stdint.h>
853a80512SIvan Malov 
97e5b4798SIvan Malov #include <rte_flow.h>
107e5b4798SIvan Malov 
1153a80512SIvan Malov #include "sfc.h"
127e5b4798SIvan Malov #include "sfc_dp.h"
1393de39f5SIvan Malov #include "sfc_flow.h"
1453a80512SIvan Malov #include "sfc_dp_rx.h"
1553a80512SIvan Malov #include "sfc_flow_tunnel.h"
1653a80512SIvan Malov #include "sfc_mae.h"
1753a80512SIvan Malov 
1853a80512SIvan Malov bool
sfc_ft_is_supported(struct sfc_adapter * sa)19*f55fe01fSIvan Malov sfc_ft_is_supported(struct sfc_adapter *sa)
2053a80512SIvan Malov {
2153a80512SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
2253a80512SIvan Malov 
2353a80512SIvan Malov 	return ((sa->priv.dp_rx->features & SFC_DP_RX_FEAT_FLOW_MARK) != 0 &&
24de32ec32SIvan Malov 		sa->mae.status == SFC_MAE_STATUS_ADMIN);
2553a80512SIvan Malov }
2653a80512SIvan Malov 
2753a80512SIvan Malov bool
sfc_ft_is_active(struct sfc_adapter * sa)28*f55fe01fSIvan Malov sfc_ft_is_active(struct sfc_adapter *sa)
2953a80512SIvan Malov {
3053a80512SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
3153a80512SIvan Malov 
3253a80512SIvan Malov 	return ((sa->negotiated_rx_metadata &
3353a80512SIvan Malov 		 RTE_ETH_RX_METADATA_TUNNEL_ID) != 0);
3453a80512SIvan Malov }
3593de39f5SIvan Malov 
36*f55fe01fSIvan Malov struct sfc_ft_ctx *
sfc_ft_ctx_pick(struct sfc_adapter * sa,uint32_t flow_mark)37*f55fe01fSIvan Malov sfc_ft_ctx_pick(struct sfc_adapter *sa, uint32_t flow_mark)
3893de39f5SIvan Malov {
39*f55fe01fSIvan Malov 	uint8_t ft_ctx_mark = SFC_FT_FLOW_MARK_TO_CTX_MARK(flow_mark);
4093de39f5SIvan Malov 
4193de39f5SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
4293de39f5SIvan Malov 
43*f55fe01fSIvan Malov 	if (ft_ctx_mark != SFC_FT_CTX_MARK_INVALID) {
44*f55fe01fSIvan Malov 		sfc_ft_ctx_id_t ft_ctx_id = SFC_FT_CTX_MARK_TO_CTX_ID(ft_ctx_mark);
45*f55fe01fSIvan Malov 		struct sfc_ft_ctx *ft_ctx = &sa->ft_ctx_pool[ft_ctx_id];
4693de39f5SIvan Malov 
47*f55fe01fSIvan Malov 		ft_ctx->id = ft_ctx_id;
4893de39f5SIvan Malov 
49*f55fe01fSIvan Malov 		return ft_ctx;
5093de39f5SIvan Malov 	}
5193de39f5SIvan Malov 
5293de39f5SIvan Malov 	return NULL;
5393de39f5SIvan Malov }
5493de39f5SIvan Malov 
5593de39f5SIvan Malov int
sfc_ft_tunnel_rule_detect(struct sfc_adapter * sa,const struct rte_flow_action * actions,struct sfc_flow_spec_mae * spec,struct rte_flow_error * error)56*f55fe01fSIvan Malov sfc_ft_tunnel_rule_detect(struct sfc_adapter *sa,
5793de39f5SIvan Malov 			  const struct rte_flow_action *actions,
5893de39f5SIvan Malov 			  struct sfc_flow_spec_mae *spec,
5993de39f5SIvan Malov 			  struct rte_flow_error *error)
6093de39f5SIvan Malov {
6193de39f5SIvan Malov 	const struct rte_flow_action_mark *action_mark = NULL;
6293de39f5SIvan Malov 	const struct rte_flow_action_jump *action_jump = NULL;
63*f55fe01fSIvan Malov 	struct sfc_ft_ctx *ft_ctx;
64*f55fe01fSIvan Malov 	uint32_t flow_mark = 0;
6593de39f5SIvan Malov 	int rc = 0;
6693de39f5SIvan Malov 
6793de39f5SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
6893de39f5SIvan Malov 
69*f55fe01fSIvan Malov 	if (!sfc_ft_is_active(sa)) {
7093de39f5SIvan Malov 		/* Tunnel-related actions (if any) will be turned down later. */
7193de39f5SIvan Malov 		return 0;
7293de39f5SIvan Malov 	}
7393de39f5SIvan Malov 
7493de39f5SIvan Malov 	if (actions == NULL) {
7593de39f5SIvan Malov 		rte_flow_error_set(error, EINVAL,
7693de39f5SIvan Malov 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
7793de39f5SIvan Malov 				   "NULL actions");
7893de39f5SIvan Malov 		return -rte_errno;
7993de39f5SIvan Malov 	}
8093de39f5SIvan Malov 
8193de39f5SIvan Malov 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
8293de39f5SIvan Malov 		if (actions->type == RTE_FLOW_ACTION_TYPE_VOID)
8393de39f5SIvan Malov 			continue;
8493de39f5SIvan Malov 
8593de39f5SIvan Malov 		if (actions->conf == NULL) {
8693de39f5SIvan Malov 			rc = EINVAL;
8793de39f5SIvan Malov 			continue;
8893de39f5SIvan Malov 		}
8993de39f5SIvan Malov 
9093de39f5SIvan Malov 		switch (actions->type) {
919df2d8f5SIvan Malov 		case RTE_FLOW_ACTION_TYPE_COUNT:
929df2d8f5SIvan Malov 			break;
9393de39f5SIvan Malov 		case RTE_FLOW_ACTION_TYPE_MARK:
9493de39f5SIvan Malov 			if (action_mark == NULL) {
9593de39f5SIvan Malov 				action_mark = actions->conf;
96*f55fe01fSIvan Malov 				flow_mark = action_mark->id;
9793de39f5SIvan Malov 			} else {
9893de39f5SIvan Malov 				rc = EINVAL;
9993de39f5SIvan Malov 			}
10093de39f5SIvan Malov 			break;
10193de39f5SIvan Malov 		case RTE_FLOW_ACTION_TYPE_JUMP:
10293de39f5SIvan Malov 			if (action_jump == NULL) {
10393de39f5SIvan Malov 				action_jump = actions->conf;
10493de39f5SIvan Malov 				if (action_jump->group != 0)
10593de39f5SIvan Malov 					rc = EINVAL;
10693de39f5SIvan Malov 			} else {
10793de39f5SIvan Malov 				rc = EINVAL;
10893de39f5SIvan Malov 			}
10993de39f5SIvan Malov 			break;
11093de39f5SIvan Malov 		default:
11193de39f5SIvan Malov 			rc = ENOTSUP;
11293de39f5SIvan Malov 			break;
11393de39f5SIvan Malov 		}
11493de39f5SIvan Malov 	}
11593de39f5SIvan Malov 
116*f55fe01fSIvan Malov 	ft_ctx = sfc_ft_ctx_pick(sa, flow_mark);
117*f55fe01fSIvan Malov 	if (ft_ctx != NULL && action_jump != 0) {
118*f55fe01fSIvan Malov 		sfc_dbg(sa, "FT: TUNNEL: detected");
11993de39f5SIvan Malov 
12093de39f5SIvan Malov 		if (rc != 0) {
12193de39f5SIvan Malov 			/* The loop above might have spotted wrong actions. */
122*f55fe01fSIvan Malov 			sfc_err(sa, "FT: TUNNEL: invalid actions: %s",
12393de39f5SIvan Malov 				strerror(rc));
12493de39f5SIvan Malov 			goto fail;
12593de39f5SIvan Malov 		}
12693de39f5SIvan Malov 
127*f55fe01fSIvan Malov 		if (ft_ctx->refcnt == 0) {
128*f55fe01fSIvan Malov 			sfc_err(sa, "FT: TUNNEL: inactive context (ID=%u)",
129*f55fe01fSIvan Malov 				ft_ctx->id);
13093de39f5SIvan Malov 			rc = ENOENT;
13193de39f5SIvan Malov 			goto fail;
13293de39f5SIvan Malov 		}
13393de39f5SIvan Malov 
134*f55fe01fSIvan Malov 		if (ft_ctx->tunnel_rule_is_set) {
135*f55fe01fSIvan Malov 			sfc_err(sa, "FT: TUNNEL: already setup context (ID=%u)",
136*f55fe01fSIvan Malov 				ft_ctx->id);
13793de39f5SIvan Malov 			rc = EEXIST;
13893de39f5SIvan Malov 			goto fail;
13993de39f5SIvan Malov 		}
14093de39f5SIvan Malov 
141*f55fe01fSIvan Malov 		spec->ft_rule_type = SFC_FT_RULE_TUNNEL;
142*f55fe01fSIvan Malov 		spec->ft_ctx = ft_ctx;
14393de39f5SIvan Malov 	}
14493de39f5SIvan Malov 
14593de39f5SIvan Malov 	return 0;
14693de39f5SIvan Malov 
14793de39f5SIvan Malov fail:
14893de39f5SIvan Malov 	return rte_flow_error_set(error, rc,
14993de39f5SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
150*f55fe01fSIvan Malov 				  "FT: TUNNEL: preparsing failed");
15193de39f5SIvan Malov }
1527e5b4798SIvan Malov 
1537e5b4798SIvan Malov static int
sfc_ft_ctx_attach(struct sfc_adapter * sa,const struct rte_flow_tunnel * tunnel,struct sfc_ft_ctx ** ft_ctxp)154*f55fe01fSIvan Malov sfc_ft_ctx_attach(struct sfc_adapter *sa, const struct rte_flow_tunnel *tunnel,
155*f55fe01fSIvan Malov 		  struct sfc_ft_ctx **ft_ctxp)
1567e5b4798SIvan Malov {
157*f55fe01fSIvan Malov 	sfc_ft_ctx_id_t ft_ctx_id;
158*f55fe01fSIvan Malov 	struct sfc_ft_ctx *ft_ctx;
159*f55fe01fSIvan Malov 	const char *ft_ctx_status;
160*f55fe01fSIvan Malov 	int ft_ctx_id_free = -1;
1617e5b4798SIvan Malov 	int rc;
1627e5b4798SIvan Malov 
1637e5b4798SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1647e5b4798SIvan Malov 
165*f55fe01fSIvan Malov 	rc = sfc_dp_ft_ctx_id_register();
1667e5b4798SIvan Malov 	if (rc != 0)
1677e5b4798SIvan Malov 		return rc;
1687e5b4798SIvan Malov 
1697e5b4798SIvan Malov 	if (tunnel->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
170*f55fe01fSIvan Malov 		sfc_err(sa, "FT: unsupported tunnel (encapsulation) type");
1717e5b4798SIvan Malov 		return ENOTSUP;
1727e5b4798SIvan Malov 	}
1737e5b4798SIvan Malov 
174*f55fe01fSIvan Malov 	for (ft_ctx_id = 0; ft_ctx_id < SFC_FT_MAX_NTUNNELS; ++ft_ctx_id) {
175*f55fe01fSIvan Malov 		ft_ctx = &sa->ft_ctx_pool[ft_ctx_id];
1767e5b4798SIvan Malov 
177*f55fe01fSIvan Malov 		if (ft_ctx->refcnt == 0) {
178*f55fe01fSIvan Malov 			if (ft_ctx_id_free == -1)
179*f55fe01fSIvan Malov 				ft_ctx_id_free = ft_ctx_id;
1807e5b4798SIvan Malov 
1817e5b4798SIvan Malov 			continue;
1827e5b4798SIvan Malov 		}
1837e5b4798SIvan Malov 
184*f55fe01fSIvan Malov 		if (memcmp(tunnel, &ft_ctx->tunnel, sizeof(*tunnel)) == 0) {
185*f55fe01fSIvan Malov 			ft_ctx_status = "existing";
1867e5b4798SIvan Malov 			goto attach;
1877e5b4798SIvan Malov 		}
1887e5b4798SIvan Malov 	}
1897e5b4798SIvan Malov 
190*f55fe01fSIvan Malov 	if (ft_ctx_id_free == -1) {
191*f55fe01fSIvan Malov 		sfc_err(sa, "FT: no free slot for the new context");
1927e5b4798SIvan Malov 		return ENOBUFS;
1937e5b4798SIvan Malov 	}
1947e5b4798SIvan Malov 
195*f55fe01fSIvan Malov 	ft_ctx_id = ft_ctx_id_free;
196*f55fe01fSIvan Malov 	ft_ctx = &sa->ft_ctx_pool[ft_ctx_id];
1977e5b4798SIvan Malov 
198*f55fe01fSIvan Malov 	memcpy(&ft_ctx->tunnel, tunnel, sizeof(*tunnel));
1997e5b4798SIvan Malov 
200*f55fe01fSIvan Malov 	ft_ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
2017e5b4798SIvan Malov 
202*f55fe01fSIvan Malov 	ft_ctx->action_mark.id = SFC_FT_CTX_ID_TO_FLOW_MARK(ft_ctx_id);
203*f55fe01fSIvan Malov 	ft_ctx->action.type = RTE_FLOW_ACTION_TYPE_MARK;
204*f55fe01fSIvan Malov 	ft_ctx->action.conf = &ft_ctx->action_mark;
2057e5b4798SIvan Malov 
206*f55fe01fSIvan Malov 	ft_ctx->item_mark_v.id = ft_ctx->action_mark.id;
207*f55fe01fSIvan Malov 	ft_ctx->item.type = RTE_FLOW_ITEM_TYPE_MARK;
208*f55fe01fSIvan Malov 	ft_ctx->item.spec = &ft_ctx->item_mark_v;
209*f55fe01fSIvan Malov 	ft_ctx->item.mask = &ft_ctx->item_mark_m;
210*f55fe01fSIvan Malov 	ft_ctx->item_mark_m.id = UINT32_MAX;
2117e5b4798SIvan Malov 
212*f55fe01fSIvan Malov 	ft_ctx->tunnel_rule_is_set = B_FALSE;
2137e5b4798SIvan Malov 
214*f55fe01fSIvan Malov 	ft_ctx->refcnt = 0;
2157e5b4798SIvan Malov 
216*f55fe01fSIvan Malov 	ft_ctx_status = "newly added";
2177e5b4798SIvan Malov 
2187e5b4798SIvan Malov attach:
219*f55fe01fSIvan Malov 	sfc_dbg(sa, "FT: attaching to %s context (ID=%u)",
220*f55fe01fSIvan Malov 		ft_ctx_status, ft_ctx_id);
2217e5b4798SIvan Malov 
222*f55fe01fSIvan Malov 	++(ft_ctx->refcnt);
223*f55fe01fSIvan Malov 	*ft_ctxp = ft_ctx;
2247e5b4798SIvan Malov 
2257e5b4798SIvan Malov 	return 0;
2267e5b4798SIvan Malov }
2277e5b4798SIvan Malov 
2287e5b4798SIvan Malov static int
sfc_ft_ctx_detach(struct sfc_adapter * sa,uint32_t flow_mark)229*f55fe01fSIvan Malov sfc_ft_ctx_detach(struct sfc_adapter *sa, uint32_t flow_mark)
2307e5b4798SIvan Malov {
231*f55fe01fSIvan Malov 	struct sfc_ft_ctx *ft_ctx;
2327e5b4798SIvan Malov 
2337e5b4798SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
2347e5b4798SIvan Malov 
235*f55fe01fSIvan Malov 	ft_ctx = sfc_ft_ctx_pick(sa, flow_mark);
236*f55fe01fSIvan Malov 	if (ft_ctx == NULL) {
237*f55fe01fSIvan Malov 		sfc_err(sa, "FT: invalid context");
2387e5b4798SIvan Malov 		return EINVAL;
2397e5b4798SIvan Malov 	}
2407e5b4798SIvan Malov 
241*f55fe01fSIvan Malov 	if (ft_ctx->refcnt == 0) {
242*f55fe01fSIvan Malov 		sfc_err(sa, "FT: inactive context (ID=%u)", ft_ctx->id);
2437e5b4798SIvan Malov 		return ENOENT;
2447e5b4798SIvan Malov 	}
2457e5b4798SIvan Malov 
246*f55fe01fSIvan Malov 	--(ft_ctx->refcnt);
2477e5b4798SIvan Malov 
2487e5b4798SIvan Malov 	return 0;
2497e5b4798SIvan Malov }
2507e5b4798SIvan Malov 
2517e5b4798SIvan Malov int
sfc_ft_decap_set(struct rte_eth_dev * dev,struct rte_flow_tunnel * tunnel,struct rte_flow_action ** pmd_actions,uint32_t * num_of_actions,struct rte_flow_error * err)252*f55fe01fSIvan Malov sfc_ft_decap_set(struct rte_eth_dev *dev, struct rte_flow_tunnel *tunnel,
253*f55fe01fSIvan Malov 		 struct rte_flow_action **pmd_actions, uint32_t *num_of_actions,
2547e5b4798SIvan Malov 		 struct rte_flow_error *err)
2557e5b4798SIvan Malov {
2567e5b4798SIvan Malov 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
257*f55fe01fSIvan Malov 	struct sfc_ft_ctx *ft_ctx;
2587e5b4798SIvan Malov 	int rc;
2597e5b4798SIvan Malov 
2607e5b4798SIvan Malov 	sfc_adapter_lock(sa);
2617e5b4798SIvan Malov 
262*f55fe01fSIvan Malov 	if (!sfc_ft_is_active(sa)) {
2637e5b4798SIvan Malov 		rc = ENOTSUP;
2647e5b4798SIvan Malov 		goto fail;
2657e5b4798SIvan Malov 	}
2667e5b4798SIvan Malov 
267*f55fe01fSIvan Malov 	rc = sfc_ft_ctx_attach(sa, tunnel, &ft_ctx);
2687e5b4798SIvan Malov 	if (rc != 0)
2697e5b4798SIvan Malov 		goto fail;
2707e5b4798SIvan Malov 
271*f55fe01fSIvan Malov 	*pmd_actions = &ft_ctx->action;
2727e5b4798SIvan Malov 	*num_of_actions = 1;
2737e5b4798SIvan Malov 
2747e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
2757e5b4798SIvan Malov 
2767e5b4798SIvan Malov 	return 0;
2777e5b4798SIvan Malov 
2787e5b4798SIvan Malov fail:
2797e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
2807e5b4798SIvan Malov 
2817e5b4798SIvan Malov 	return rte_flow_error_set(err, rc,
2827e5b4798SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
283*f55fe01fSIvan Malov 				  "FT: decap_set failed");
2847e5b4798SIvan Malov }
2857e5b4798SIvan Malov 
2867e5b4798SIvan Malov int
sfc_ft_match(struct rte_eth_dev * dev,struct rte_flow_tunnel * tunnel,struct rte_flow_item ** pmd_items,uint32_t * num_of_items,struct rte_flow_error * err)287*f55fe01fSIvan Malov sfc_ft_match(struct rte_eth_dev *dev, struct rte_flow_tunnel *tunnel,
288*f55fe01fSIvan Malov 	     struct rte_flow_item **pmd_items, uint32_t *num_of_items,
2897e5b4798SIvan Malov 	     struct rte_flow_error *err)
2907e5b4798SIvan Malov {
2917e5b4798SIvan Malov 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
292*f55fe01fSIvan Malov 	struct sfc_ft_ctx *ft_ctx;
2937e5b4798SIvan Malov 	int rc;
2947e5b4798SIvan Malov 
2957e5b4798SIvan Malov 	sfc_adapter_lock(sa);
2967e5b4798SIvan Malov 
297*f55fe01fSIvan Malov 	if (!sfc_ft_is_active(sa)) {
2987e5b4798SIvan Malov 		rc = ENOTSUP;
2997e5b4798SIvan Malov 		goto fail;
3007e5b4798SIvan Malov 	}
3017e5b4798SIvan Malov 
302*f55fe01fSIvan Malov 	rc = sfc_ft_ctx_attach(sa, tunnel, &ft_ctx);
3037e5b4798SIvan Malov 	if (rc != 0)
3047e5b4798SIvan Malov 		goto fail;
3057e5b4798SIvan Malov 
306*f55fe01fSIvan Malov 	*pmd_items = &ft_ctx->item;
3077e5b4798SIvan Malov 	*num_of_items = 1;
3087e5b4798SIvan Malov 
3097e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3107e5b4798SIvan Malov 
3117e5b4798SIvan Malov 	return 0;
3127e5b4798SIvan Malov 
3137e5b4798SIvan Malov fail:
3147e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3157e5b4798SIvan Malov 
3167e5b4798SIvan Malov 	return rte_flow_error_set(err, rc,
3177e5b4798SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
318*f55fe01fSIvan Malov 				  "FT: tunnel_match failed");
3197e5b4798SIvan Malov }
3207e5b4798SIvan Malov 
3217e5b4798SIvan Malov int
sfc_ft_item_release(struct rte_eth_dev * dev,struct rte_flow_item * pmd_items,uint32_t num_items,struct rte_flow_error * err)322*f55fe01fSIvan Malov sfc_ft_item_release(struct rte_eth_dev *dev, struct rte_flow_item *pmd_items,
323*f55fe01fSIvan Malov 		    uint32_t num_items, struct rte_flow_error *err)
3247e5b4798SIvan Malov {
3257e5b4798SIvan Malov 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
3267e5b4798SIvan Malov 	const struct rte_flow_item_mark *item_mark;
3277e5b4798SIvan Malov 	struct rte_flow_item *item = pmd_items;
3287e5b4798SIvan Malov 	int rc;
3297e5b4798SIvan Malov 
3307e5b4798SIvan Malov 	sfc_adapter_lock(sa);
3317e5b4798SIvan Malov 
332*f55fe01fSIvan Malov 	if (!sfc_ft_is_active(sa)) {
3337e5b4798SIvan Malov 		rc = ENOTSUP;
3347e5b4798SIvan Malov 		goto fail;
3357e5b4798SIvan Malov 	}
3367e5b4798SIvan Malov 
3377e5b4798SIvan Malov 	if (num_items != 1 || item == NULL || item->spec == NULL ||
3387e5b4798SIvan Malov 	    item->type != RTE_FLOW_ITEM_TYPE_MARK) {
339*f55fe01fSIvan Malov 		sfc_err(sa, "FT: item_release: wrong input");
3407e5b4798SIvan Malov 		rc = EINVAL;
3417e5b4798SIvan Malov 		goto fail;
3427e5b4798SIvan Malov 	}
3437e5b4798SIvan Malov 
3447e5b4798SIvan Malov 	item_mark = item->spec;
3457e5b4798SIvan Malov 
346*f55fe01fSIvan Malov 	rc = sfc_ft_ctx_detach(sa, item_mark->id);
3477e5b4798SIvan Malov 	if (rc != 0)
3487e5b4798SIvan Malov 		goto fail;
3497e5b4798SIvan Malov 
3507e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3517e5b4798SIvan Malov 
3527e5b4798SIvan Malov 	return 0;
3537e5b4798SIvan Malov 
3547e5b4798SIvan Malov fail:
3557e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3567e5b4798SIvan Malov 
3577e5b4798SIvan Malov 	return rte_flow_error_set(err, rc,
3587e5b4798SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
359*f55fe01fSIvan Malov 				  "FT: item_release failed");
3607e5b4798SIvan Malov }
3617e5b4798SIvan Malov 
3627e5b4798SIvan Malov int
sfc_ft_action_decap_release(struct rte_eth_dev * dev,struct rte_flow_action * pmd_actions,uint32_t num_actions,struct rte_flow_error * err)363*f55fe01fSIvan Malov sfc_ft_action_decap_release(struct rte_eth_dev *dev,
3647e5b4798SIvan Malov 			    struct rte_flow_action *pmd_actions,
365*f55fe01fSIvan Malov 			    uint32_t num_actions, struct rte_flow_error *err)
3667e5b4798SIvan Malov {
3677e5b4798SIvan Malov 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
3687e5b4798SIvan Malov 	const struct rte_flow_action_mark *action_mark;
3697e5b4798SIvan Malov 	struct rte_flow_action *action = pmd_actions;
3707e5b4798SIvan Malov 	int rc;
3717e5b4798SIvan Malov 
3727e5b4798SIvan Malov 	sfc_adapter_lock(sa);
3737e5b4798SIvan Malov 
374*f55fe01fSIvan Malov 	if (!sfc_ft_is_active(sa)) {
3757e5b4798SIvan Malov 		rc = ENOTSUP;
3767e5b4798SIvan Malov 		goto fail;
3777e5b4798SIvan Malov 	}
3787e5b4798SIvan Malov 
3797e5b4798SIvan Malov 	if (num_actions != 1 || action == NULL || action->conf == NULL ||
3807e5b4798SIvan Malov 	    action->type != RTE_FLOW_ACTION_TYPE_MARK) {
381*f55fe01fSIvan Malov 		sfc_err(sa, "FT: action_decap_release: wrong input");
3827e5b4798SIvan Malov 		rc = EINVAL;
3837e5b4798SIvan Malov 		goto fail;
3847e5b4798SIvan Malov 	}
3857e5b4798SIvan Malov 
3867e5b4798SIvan Malov 	action_mark = action->conf;
3877e5b4798SIvan Malov 
388*f55fe01fSIvan Malov 	rc = sfc_ft_ctx_detach(sa, action_mark->id);
3897e5b4798SIvan Malov 	if (rc != 0)
3907e5b4798SIvan Malov 		goto fail;
3917e5b4798SIvan Malov 
3927e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3937e5b4798SIvan Malov 
3947e5b4798SIvan Malov 	return 0;
3957e5b4798SIvan Malov 
3967e5b4798SIvan Malov fail:
3977e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
3987e5b4798SIvan Malov 
3997e5b4798SIvan Malov 	return rte_flow_error_set(err, rc,
4007e5b4798SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
401*f55fe01fSIvan Malov 				  "FT: item_release failed");
4027e5b4798SIvan Malov }
4037e5b4798SIvan Malov 
4047e5b4798SIvan Malov int
sfc_ft_get_restore_info(struct rte_eth_dev * dev,struct rte_mbuf * m,struct rte_flow_restore_info * info,struct rte_flow_error * err)405*f55fe01fSIvan Malov sfc_ft_get_restore_info(struct rte_eth_dev *dev, struct rte_mbuf *m,
4067e5b4798SIvan Malov 			struct rte_flow_restore_info *info,
4077e5b4798SIvan Malov 			struct rte_flow_error *err)
4087e5b4798SIvan Malov {
4097e5b4798SIvan Malov 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
410*f55fe01fSIvan Malov 	const struct sfc_ft_ctx *ft_ctx;
411*f55fe01fSIvan Malov 	sfc_ft_ctx_id_t ft_ctx_id;
4127e5b4798SIvan Malov 	int rc;
4137e5b4798SIvan Malov 
4147e5b4798SIvan Malov 	sfc_adapter_lock(sa);
4157e5b4798SIvan Malov 
416*f55fe01fSIvan Malov 	if ((m->ol_flags & sfc_dp_ft_ctx_id_valid) == 0) {
417*f55fe01fSIvan Malov 		sfc_dbg(sa, "FT: get_restore_info: no FT context mark in the packet");
4187e5b4798SIvan Malov 		rc = EINVAL;
4197e5b4798SIvan Malov 		goto fail;
4207e5b4798SIvan Malov 	}
4217e5b4798SIvan Malov 
422*f55fe01fSIvan Malov 	ft_ctx_id = *RTE_MBUF_DYNFIELD(m, sfc_dp_ft_ctx_id_offset,
423*f55fe01fSIvan Malov 				    sfc_ft_ctx_id_t *);
424*f55fe01fSIvan Malov 	ft_ctx = &sa->ft_ctx_pool[ft_ctx_id];
4257e5b4798SIvan Malov 
426*f55fe01fSIvan Malov 	if (ft_ctx->refcnt == 0) {
427*f55fe01fSIvan Malov 		sfc_dbg(sa, "FT: get_restore_info: inactive context (ID=%u)",
428*f55fe01fSIvan Malov 			ft_ctx_id);
4297e5b4798SIvan Malov 		rc = ENOENT;
4307e5b4798SIvan Malov 		goto fail;
4317e5b4798SIvan Malov 	}
4327e5b4798SIvan Malov 
433*f55fe01fSIvan Malov 	memcpy(&info->tunnel, &ft_ctx->tunnel, sizeof(info->tunnel));
4347e5b4798SIvan Malov 
4357e5b4798SIvan Malov 	/*
436*f55fe01fSIvan Malov 	 * The packet still has encapsulation header; TUNNEL rules never
4377e5b4798SIvan Malov 	 * strip it. Therefore, set RTE_FLOW_RESTORE_INFO_ENCAPSULATED.
4387e5b4798SIvan Malov 	 */
4397e5b4798SIvan Malov 	info->flags = RTE_FLOW_RESTORE_INFO_ENCAPSULATED |
4407e5b4798SIvan Malov 		      RTE_FLOW_RESTORE_INFO_GROUP_ID |
4417e5b4798SIvan Malov 		      RTE_FLOW_RESTORE_INFO_TUNNEL;
4427e5b4798SIvan Malov 
4437e5b4798SIvan Malov 	info->group_id = 0;
4447e5b4798SIvan Malov 
4457e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
4467e5b4798SIvan Malov 
4477e5b4798SIvan Malov 	return 0;
4487e5b4798SIvan Malov 
4497e5b4798SIvan Malov fail:
4507e5b4798SIvan Malov 	sfc_adapter_unlock(sa);
4517e5b4798SIvan Malov 
4527e5b4798SIvan Malov 	return rte_flow_error_set(err, rc,
4537e5b4798SIvan Malov 				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
454*f55fe01fSIvan Malov 				  "FT: get_restore_info failed");
4557e5b4798SIvan Malov }
4569df2d8f5SIvan Malov 
4579df2d8f5SIvan Malov void
sfc_ft_counters_reset(struct sfc_adapter * sa)458*f55fe01fSIvan Malov sfc_ft_counters_reset(struct sfc_adapter *sa)
4599df2d8f5SIvan Malov {
4609df2d8f5SIvan Malov 	unsigned int i;
4619df2d8f5SIvan Malov 
4629df2d8f5SIvan Malov 	SFC_ASSERT(sfc_adapter_is_locked(sa));
4639df2d8f5SIvan Malov 	SFC_ASSERT(sa->state != SFC_ETHDEV_STARTED);
4649df2d8f5SIvan Malov 
465*f55fe01fSIvan Malov 	for (i = 0; i < RTE_DIM(sa->ft_ctx_pool); ++i) {
466*f55fe01fSIvan Malov 		struct sfc_ft_ctx *ft_ctx = &sa->ft_ctx_pool[i];
4679df2d8f5SIvan Malov 
468*f55fe01fSIvan Malov 		ft_ctx->reset_tunnel_hit_counter = 0;
469*f55fe01fSIvan Malov 		ft_ctx->switch_hit_counter = 0;
4709df2d8f5SIvan Malov 	}
4719df2d8f5SIvan Malov }
472