summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:27:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:27:49 +0000
commitace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch)
treeb2d64bc10158fdd5497876388cd68142ca374ed3 /drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
parentInitial commit. (diff)
downloadlinux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz
linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
new file mode 100644
index 0000000000..d5d33c3b3a
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+#include "fs_core.h"
+#include "eswitch.h"
+#include "en_accel/ipsec.h"
+#include "esw/ipsec_fs.h"
+#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
+#include "en/tc_priv.h"
+#endif
+
+enum {
+ MLX5_ESW_IPSEC_RX_POL_FT_LEVEL,
+ MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL,
+ MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL,
+};
+
+enum {
+ MLX5_ESW_IPSEC_TX_POL_FT_LEVEL,
+ MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL,
+ MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL,
+};
+
+void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ struct mlx5e_ipsec_rx_create_attr *attr)
+{
+ attr->prio = FDB_CRYPTO_INGRESS;
+ attr->pol_level = MLX5_ESW_IPSEC_RX_POL_FT_LEVEL;
+ attr->sa_level = MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL;
+ attr->status_level = MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL;
+ attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB;
+}
+
+int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec,
+ struct mlx5_flow_destination *dest)
+{
+ dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+ dest->ft = mlx5_chains_get_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0);
+
+ return 0;
+}
+
+int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry,
+ struct mlx5_flow_act *flow_act)
+{
+ u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
+ struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+ struct mlx5_core_dev *mdev = ipsec->mdev;
+ struct mlx5_modify_hdr *modify_hdr;
+ u32 mapped_id;
+ int err;
+
+ err = xa_alloc_bh(&ipsec->rx_esw->ipsec_obj_id_map, &mapped_id,
+ xa_mk_value(sa_entry->ipsec_obj_id),
+ XA_LIMIT(1, ESW_IPSEC_RX_MAPPED_ID_MASK), 0);
+ if (err)
+ return err;
+
+ /* reuse tunnel bits for ipsec,
+ * tun_id is always 0 and tun_opts is mapped to ipsec_obj_id.
+ */
+ MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
+ MLX5_SET(set_action_in, action, field,
+ MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
+ MLX5_SET(set_action_in, action, offset, ESW_ZONE_ID_BITS);
+ MLX5_SET(set_action_in, action, length,
+ ESW_TUN_ID_BITS + ESW_TUN_OPTS_BITS);
+ MLX5_SET(set_action_in, action, data, mapped_id);
+
+ modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_FDB,
+ 1, action);
+ if (IS_ERR(modify_hdr)) {
+ err = PTR_ERR(modify_hdr);
+ goto err_header_alloc;
+ }
+
+ sa_entry->rx_mapped_id = mapped_id;
+ flow_act->modify_hdr = modify_hdr;
+ flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
+
+ return 0;
+
+err_header_alloc:
+ xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, mapped_id);
+ return err;
+}
+
+void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry)
+{
+ struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+
+ if (sa_entry->rx_mapped_id)
+ xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map,
+ sa_entry->rx_mapped_id);
+}
+
+int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id,
+ u32 *ipsec_obj_id)
+{
+ struct mlx5e_ipsec *ipsec = priv->ipsec;
+ void *val;
+
+ val = xa_load(&ipsec->rx_esw->ipsec_obj_id_map, id);
+ if (!val)
+ return -ENOENT;
+
+ *ipsec_obj_id = xa_to_value(val);
+
+ return 0;
+}
+
+void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec,
+ struct mlx5e_ipsec_tx_create_attr *attr)
+{
+ attr->prio = FDB_CRYPTO_EGRESS;
+ attr->pol_level = MLX5_ESW_IPSEC_TX_POL_FT_LEVEL;
+ attr->sa_level = MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL;
+ attr->cnt_level = MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL;
+ attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB;
+}
+
+#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
+static int mlx5_esw_ipsec_modify_flow_dests(struct mlx5_eswitch *esw,
+ struct mlx5e_tc_flow *flow)
+{
+ struct mlx5_esw_flow_attr *esw_attr;
+ struct mlx5_flow_attr *attr;
+ int err;
+
+ attr = flow->attr;
+ esw_attr = attr->esw_attr;
+ if (esw_attr->out_count - esw_attr->split_count > 1)
+ return 0;
+
+ err = mlx5_eswitch_restore_ipsec_rule(esw, flow->rule[0], esw_attr,
+ esw_attr->out_count - 1);
+
+ return err;
+}
+#endif
+
+void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev)
+{
+#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
+ struct mlx5_eswitch *esw = mdev->priv.eswitch;
+ struct mlx5_eswitch_rep *rep;
+ struct mlx5e_rep_priv *rpriv;
+ struct rhashtable_iter iter;
+ struct mlx5e_tc_flow *flow;
+ unsigned long i;
+ int err;
+
+ xa_for_each(&esw->offloads.vport_reps, i, rep) {
+ rpriv = rep->rep_data[REP_ETH].priv;
+ if (!rpriv || !rpriv->netdev || !atomic_read(&rpriv->tc_ht.nelems))
+ continue;
+
+ rhashtable_walk_enter(&rpriv->tc_ht, &iter);
+ rhashtable_walk_start(&iter);
+ while ((flow = rhashtable_walk_next(&iter)) != NULL) {
+ if (IS_ERR(flow))
+ continue;
+
+ err = mlx5_esw_ipsec_modify_flow_dests(esw, flow);
+ if (err)
+ mlx5_core_warn_once(mdev,
+ "Failed to modify flow dests for IPsec");
+ }
+ rhashtable_walk_stop(&iter);
+ rhashtable_walk_exit(&iter);
+ }
+#endif
+}