File Index
Files and directories
Sign in
FILE

ipsec_fs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
  3
  4#include "fs_core.h"
  5#include "eswitch.h"
  6#include "en_accel/ipsec.h"
  7#include "esw/ipsec_fs.h"
  8#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
  9#include "en/tc_priv.h"
 10#endif
 11
 12enum {
 13	MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL,
 14	MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL,
 15	MLX5_ESW_IPSEC_RX_POL_FT_LEVEL,
 16};
 17
 18enum {
 19	MLX5_ESW_IPSEC_TX_POL_FT_LEVEL,
 20	MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL,
 21	MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL,
 22};
 23
 24void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
 25				       struct mlx5e_ipsec_rx_create_attr *attr)
 26{
 27	attr->prio = FDB_CRYPTO_INGRESS;
 28	attr->pol_level = MLX5_ESW_IPSEC_RX_POL_FT_LEVEL;
 29	attr->sa_level = MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL;
 30	attr->status_level = MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL;
 31	attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB;
 32}
 33
 34int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec,
 35					   struct mlx5_flow_destination *dest)
 36{
 37	dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 38	dest->ft = mlx5_chains_get_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0);
 39
 40	return 0;
 41}
 42
 43int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry,
 44					  struct mlx5_flow_act *flow_act)
 45{
 46	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
 47	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 48	struct mlx5_core_dev *mdev = ipsec->mdev;
 49	struct mlx5_modify_hdr *modify_hdr;
 50	u32 mapped_id;
 51	int err;
 52
 53	err = xa_alloc_bh(&ipsec->ipsec_obj_id_map, &mapped_id,
 54			  xa_mk_value(sa_entry->ipsec_obj_id),
 55			  XA_LIMIT(1, ESW_IPSEC_RX_MAPPED_ID_MASK), 0);
 56	if (err)
 57		return err;
 58
 59	/* reuse tunnel bits for ipsec,
 60	 * tun_id is always 0 and tun_opts is mapped to ipsec_obj_id.
 61	 */
 62	MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
 63	MLX5_SET(set_action_in, action, field,
 64		 MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
 65	MLX5_SET(set_action_in, action, offset, ESW_ZONE_ID_BITS);
 66	MLX5_SET(set_action_in, action, length,
 67		 ESW_TUN_ID_BITS + ESW_TUN_OPTS_BITS);
 68	MLX5_SET(set_action_in, action, data, mapped_id);
 69
 70	modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_FDB,
 71					      1, action);
 72	if (IS_ERR(modify_hdr)) {
 73		err = PTR_ERR(modify_hdr);
 74		goto err_header_alloc;
 75	}
 76
 77	sa_entry->rx_mapped_id = mapped_id;
 78	flow_act->modify_hdr = modify_hdr;
 79	flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
 80
 81	return 0;
 82
 83err_header_alloc:
 84	xa_erase_bh(&ipsec->ipsec_obj_id_map, mapped_id);
 85	return err;
 86}
 87
 88void mlx5_esw_ipsec_rx_rule_add_match_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
 89					  struct mlx5_flow_spec *spec)
 90{
 91	MLX5_SET(fte_match_param, spec->match_criteria,
 92		 misc_parameters_2.metadata_reg_c_1,
 93		 ESW_IPSEC_RX_MAPPED_ID_MATCH_MASK);
 94	MLX5_SET(fte_match_param, spec->match_value,
 95		 misc_parameters_2.metadata_reg_c_1,
 96		 sa_entry->rx_mapped_id << ESW_ZONE_ID_BITS);
 97
 98	spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
 99}
100
101void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry)
102{
103	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
104
105	if (sa_entry->rx_mapped_id)
106		xa_erase_bh(&ipsec->ipsec_obj_id_map,
107			    sa_entry->rx_mapped_id);
108}
109
110int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id,
111					  u32 *ipsec_obj_id)
112{
113	struct mlx5e_ipsec *ipsec = priv->ipsec;
114	void *val;
115
116	val = xa_load(&ipsec->ipsec_obj_id_map, id);
117	if (!val)
118		return -ENOENT;
119
120	*ipsec_obj_id = xa_to_value(val);
121
122	return 0;
123}
124
125void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec,
126				       struct mlx5e_ipsec_tx_create_attr *attr)
127{
128	attr->prio = FDB_CRYPTO_EGRESS;
129	attr->pol_level = MLX5_ESW_IPSEC_TX_POL_FT_LEVEL;
130	attr->sa_level = MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL;
131	attr->cnt_level = MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL;
132	attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB;
133}
134
135#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
136static int mlx5_esw_ipsec_modify_flow_dests(struct mlx5_eswitch *esw,
137					    struct mlx5e_tc_flow *flow)
138{
139	struct mlx5_esw_flow_attr *esw_attr;
140	struct mlx5_flow_attr *attr;
141	int err;
142
143	attr = flow->attr;
144	esw_attr = attr->esw_attr;
145	if (esw_attr->out_count - esw_attr->split_count > 1)
146		return 0;
147
148	err = mlx5_eswitch_restore_ipsec_rule(esw, flow->rule[0], esw_attr,
149					      esw_attr->out_count - 1);
150
151	return err;
152}
153#endif
154
155void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev)
156{
157#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
158	struct mlx5_eswitch *esw = mdev->priv.eswitch;
159	struct mlx5_eswitch_rep *rep;
160	struct mlx5e_rep_priv *rpriv;
161	struct rhashtable_iter iter;
162	struct mlx5e_tc_flow *flow;
163	unsigned long i;
164	int err;
165
166	mlx5_esw_for_each_rep(esw, i, rep) {
167		if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
168			continue;
169
170		rpriv = rep->rep_data[REP_ETH].priv;
171		rhashtable_walk_enter(&rpriv->tc_ht, &iter);
172		rhashtable_walk_start(&iter);
173		while ((flow = rhashtable_walk_next(&iter)) != NULL) {
174			if (IS_ERR(flow))
175				continue;
176
177			err = mlx5_esw_ipsec_modify_flow_dests(esw, flow);
178			if (err)
179				mlx5_core_warn_once(mdev,
180						    "Failed to modify flow dests for IPsec");
181		}
182		rhashtable_walk_stop(&iter);
183		rhashtable_walk_exit(&iter);
184	}
185#endif
186}
~/ Read-only file preview.