git: 080f68d0ab0c - main - mlx5_core: Add steering support for IPsec with IPv6
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Jan 2025 00:53:55 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=080f68d0ab0c87950ecd9b393a156b1e4d12c825
commit 080f68d0ab0c87950ecd9b393a156b1e4d12c825
Author: Ariel Ehrenberg <aehrenberg@nvidia.com>
AuthorDate: 2024-12-04 09:32:54 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-01-07 00:53:37 +0000
mlx5_core: Add steering support for IPsec with IPv6
ipv6 flow tables were not connected to previous FS tables.
Created an additional table to serve as IPsec RX root.
This table has 2 rules for redirecting the received packets
to ipv4/ipv6 based on the IP family in the packet header.
Sponsored by: NVidia networking
---
sys/dev/mlx5/mlx5_accel/ipsec.h | 2 +
sys/dev/mlx5/mlx5_accel/mlx5_ipsec_fs.c | 157 +++++++++++++++++++++++++++---
sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c | 4 +-
3 files changed, 149 insertions(+), 14 deletions(-)
diff --git a/sys/dev/mlx5/mlx5_accel/ipsec.h b/sys/dev/mlx5/mlx5_accel/ipsec.h
index 95742c4099f1..361b9f72d873 100644
--- a/sys/dev/mlx5/mlx5_accel/ipsec.h
+++ b/sys/dev/mlx5/mlx5_accel/ipsec.h
@@ -43,6 +43,7 @@ struct mlx5e_priv;
struct mlx5e_tx_wqe;
struct mlx5e_ipsec_tx;
struct mlx5e_ipsec_rx;
+struct mlx5e_ipsec_rx_ip_type;
struct aes_gcm_keymat {
u64 seq_iv;
@@ -128,6 +129,7 @@ struct mlx5e_ipsec {
struct mlx5e_ipsec_tx *tx;
struct mlx5e_ipsec_rx *rx_ipv4;
struct mlx5e_ipsec_rx *rx_ipv6;
+ struct mlx5e_ipsec_rx_ip_type *rx_ip_type;
struct mlx5e_ipsec_aso *aso;
u32 pdn;
u32 mkey;
diff --git a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_fs.c b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_fs.c
index f7950bf61269..fb9ca94278db 100644
--- a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_fs.c
+++ b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec_fs.c
@@ -138,6 +138,14 @@ struct mlx5e_ipsec_rx_roce {
struct mlx5_flow_namespace *ns_rdma;
};
+struct mlx5e_ipsec_rx_ip_type {
+ struct mlx5_flow_table *ft;
+ struct mlx5_flow_namespace *ns;
+ struct mlx5_flow_handle *ipv4_rule;
+ struct mlx5_flow_handle *ipv6_rule;
+ struct mlx5e_ipsec_miss miss;
+};
+
struct mlx5e_ipsec_rx {
struct mlx5e_ipsec_ft ft;
struct mlx5e_ipsec_miss pol;
@@ -497,6 +505,16 @@ static void setup_fte_addr6(struct mlx5_flow_spec *spec, __be32 *saddr,
outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 0xff, 16);
}
+static void
+setup_fte_ip_version(struct mlx5_flow_spec *spec, u8 family)
+{
+ spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+
+ MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_version);
+ MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version,
+ family == AF_INET ? 4 : 6);
+}
+
static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
{
struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule;
@@ -1598,9 +1616,18 @@ static void ipsec_fs_rx_roce_table_destroy(struct mlx5e_ipsec_rx_roce *rx_roce)
mlx5_destroy_flow_table(rx_roce->ft);
}
+static void
+ipsec_fs_rx_ip_type_catchall_rule_destroy(struct mlx5e_ipsec_rx_ip_type* rx_ip_type)
+{
+ mlx5_del_flow_rules(&rx_ip_type->ipv4_rule);
+ mlx5_del_flow_rules(&rx_ip_type->ipv6_rule);
+ mlx5_del_flow_rules(&rx_ip_type->miss.rule);
+ mlx5_destroy_flow_group(rx_ip_type->miss.group);
+ rx_ip_type->miss.group = NULL;
+}
+
static void ipsec_fs_rx_table_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_rx *rx)
{
- mutex_lock(&rx->ft.mutex);
if (rx->chains) {
ipsec_chains_destroy(rx->chains);
} else {
@@ -1610,7 +1637,6 @@ static void ipsec_fs_rx_table_destroy(struct mlx5_core_dev *mdev, struct mlx5e_i
mlx5_destroy_flow_table(rx->ft.sa);
mlx5_destroy_flow_table(rx->ft.status);
ipsec_fs_rx_roce_table_destroy(&rx->roce);
- mutex_unlock(&rx->ft.mutex);
}
static void ipsec_roce_setup_udp_dport(struct mlx5_flow_spec *spec, u16 dport)
@@ -1831,6 +1857,90 @@ out:
return err;
}
+static int
+ipsec_fs_rx_ip_type_catchall_rules_create(struct mlx5e_priv *priv,
+ struct mlx5_flow_destination *defdst)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct mlx5e_ipsec *ipsec = priv->ipsec;
+ struct mlx5_flow_destination dst = {};
+ struct mlx5_flow_act flow_act = {};
+ struct mlx5_flow_handle *rule;
+ struct mlx5_flow_spec *spec;
+ int err = 0;
+
+ spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec) {
+ return -ENOMEM;
+ }
+ dst.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+
+ /* Set rule for ipv4 packets */
+ dst.ft = ipsec->rx_ipv4->ft.pol;
+ setup_fte_ip_version(spec, AF_INET);
+ rule = mlx5_add_flow_rules(ipsec->rx_ip_type->ft, spec, &flow_act, &dst, 1);
+ if (IS_ERR(rule)) {
+ err = PTR_ERR(rule);
+ mlx5_core_err(mdev, "Failed to add ipv4 rule to ip_type table err=%d\n",
+ err);
+ goto out;
+ }
+ ipsec->rx_ip_type->ipv4_rule = rule;
+
+ /* Set rule for ipv6 packets */
+ dst.ft = ipsec->rx_ipv6->ft.pol;
+ setup_fte_ip_version(spec, AF_INET6);
+ rule = mlx5_add_flow_rules(ipsec->rx_ip_type->ft, spec, &flow_act, &dst, 1);
+ if (IS_ERR(rule)) {
+ err = PTR_ERR(rule);
+ mlx5_core_err(mdev, "Failed to add ipv6 rule to ip_type table err=%d\n",
+ err);
+ goto fail_add_ipv6_rule;
+ }
+ ipsec->rx_ip_type->ipv6_rule = rule;
+
+ /* set miss rule */
+ err = ipsec_miss_create(mdev, ipsec->rx_ip_type->ft, &ipsec->rx_ip_type->miss, defdst);
+ if (err) {
+ mlx5_core_err(mdev, "Failed to add miss rule to ip_type table err=%d\n",
+ err);
+ goto fail_miss_rule;
+ }
+
+ goto out;
+
+fail_miss_rule:
+ mlx5_del_flow_rules(&ipsec->rx_ip_type->ipv6_rule);
+fail_add_ipv6_rule:
+ mlx5_del_flow_rules(&ipsec->rx_ip_type->ipv4_rule);
+out:
+ kvfree(spec);
+ return err;
+}
+
+static int
+ipsec_fs_rx_ip_type_table_create(struct mlx5e_priv *priv,
+ int level)
+{
+ struct mlx5e_ipsec *ipsec = priv->ipsec;
+ struct mlx5_flow_table *ft;
+ int err = 0;
+
+ /* Create rx ip type table */
+ ft = ipsec_rx_ft_create(ipsec->rx_ip_type->ns, level, 0, 1);
+ if (IS_ERR(ft)) {
+ err = PTR_ERR(ft);
+ goto out;
+ }
+ ipsec->rx_ip_type->ft = ft;
+
+ priv->fts.ipsec_ft = priv->ipsec->rx_ip_type->ft;
+
+out:
+ return err;
+}
+
static int ipsec_fs_rx_table_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_rx *rx,
int rx_init_level, int rdma_init_level)
{
@@ -1996,6 +2106,7 @@ void mlx5e_accel_ipsec_fs_rx_catchall_rules_destroy(struct mlx5e_priv *priv)
if (!priv->ipsec)
return;
+ ipsec_fs_rx_ip_type_catchall_rule_destroy(priv->ipsec->rx_ip_type);
ipsec_fs_rx_catchall_rules_destroy(priv->mdev, priv->ipsec->rx_ipv4);
ipsec_fs_rx_catchall_rules_destroy(priv->mdev, priv->ipsec->rx_ipv6);
}
@@ -2019,6 +2130,13 @@ int mlx5e_accel_ipsec_fs_rx_catchall_rules(struct mlx5e_priv *priv)
err = ipsec_fs_rx_catchall_rules(priv, ipsec->rx_ipv4, &dest);
if (err)
ipsec_fs_rx_catchall_rules_destroy(priv->mdev, priv->ipsec->rx_ipv6);
+
+ err = ipsec_fs_rx_ip_type_catchall_rules_create(priv, &dest);
+ if (err) {
+ ipsec_fs_rx_catchall_rules_destroy(priv->mdev, priv->ipsec->rx_ipv6);
+ ipsec_fs_rx_catchall_rules_destroy(priv->mdev, priv->ipsec->rx_ipv4);
+ }
+
out:
return err;
}
@@ -2032,6 +2150,7 @@ void mlx5e_accel_ipsec_fs_rx_tables_destroy(struct mlx5e_priv *priv)
if (!ipsec)
return;
+ mlx5_destroy_flow_table(ipsec->rx_ip_type->ft);
ipsec_fs_rx_table_destroy(mdev, ipsec->rx_ipv6);
ipsec_fs_rx_table_destroy(mdev, ipsec->rx_ipv4);
}
@@ -2045,18 +2164,24 @@ int mlx5e_accel_ipsec_fs_rx_tables_create(struct mlx5e_priv *priv)
if (!ipsec)
return 0;
- err = ipsec_fs_rx_table_create(ipsec->mdev, ipsec->rx_ipv4, 0, 0);
+ err = ipsec_fs_rx_ip_type_table_create(priv, 0);
if (err)
- goto out;
+ return err;
- err = ipsec_fs_rx_table_create(ipsec->mdev, ipsec->rx_ipv6, 4, 1);
- if (err) {
- ipsec_fs_rx_table_destroy(priv->mdev, ipsec->rx_ipv4);
- goto out;
- }
+ err = ipsec_fs_rx_table_create(ipsec->mdev, ipsec->rx_ipv4, 1, 0);
+ if (err)
+ goto err_ipv4_table;
- priv->fts.ipsec_ft = priv->ipsec->rx_ipv4->ft.pol;
-out:
+ err = ipsec_fs_rx_table_create(ipsec->mdev, ipsec->rx_ipv6, 5, 1);
+ if (err)
+ goto err_ipv6_table;
+
+ return 0;
+
+err_ipv6_table:
+ ipsec_fs_rx_table_destroy(priv->mdev, ipsec->rx_ipv4);
+err_ipv4_table:
+ mlx5_destroy_flow_table(ipsec->rx_ip_type->ft);
return err;
}
@@ -2067,6 +2192,7 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec)
mutex_destroy(&ipsec->rx_ipv4->ft.mutex);
mutex_destroy(&ipsec->tx->ft.mutex);
ipsec_fs_destroy_counters(ipsec);
+ kfree(ipsec->rx_ip_type);
kfree(ipsec->rx_ipv6);
kfree(ipsec->rx_ipv4);
kfree(ipsec->tx);
@@ -2089,9 +2215,13 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec)
if (!ipsec->tx)
return -ENOMEM;
+ ipsec->rx_ip_type = kzalloc(sizeof(*ipsec->rx_ip_type), GFP_KERNEL);
+ if (!ipsec->rx_ip_type)
+ goto err_tx;
+
ipsec->rx_ipv4 = kzalloc(sizeof(*ipsec->rx_ipv4), GFP_KERNEL);
if (!ipsec->rx_ipv4)
- goto err_tx;
+ goto err_ip_type;
ipsec->rx_ipv6 = kzalloc(sizeof(*ipsec->rx_ipv6), GFP_KERNEL);
if (!ipsec->rx_ipv6)
@@ -2103,6 +2233,7 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec)
ipsec->tx->ns = tns;
mutex_init(&ipsec->tx->ft.mutex);
+ ipsec->rx_ip_type->ns = rns;
ipsec->rx_ipv4->ns = rns;
ipsec->rx_ipv6->ns = rns;
mutex_init(&ipsec->rx_ipv4->ft.mutex);
@@ -2116,6 +2247,8 @@ err_rx_ipv6:
kfree(ipsec->rx_ipv6);
err_rx_ipv4:
kfree(ipsec->rx_ipv4);
+err_ip_type:
+ kfree(ipsec->rx_ip_type);
err_tx:
kfree(ipsec->tx);
return err;
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
index f8be5b9e881c..6e24395b5577 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
@@ -1626,7 +1626,7 @@ mlx5e_create_vlan_flow_table(struct mlx5e_priv *priv)
ft->num_groups = 0;
ft_attr.max_fte = MLX5E_VLAN_TABLE_SIZE;
- ft_attr.level = (priv->ipsec) ? 8 : 0;
+ ft_attr.level = (priv->ipsec) ? 9 : 0;
ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
if (IS_ERR(ft->t)) {
@@ -2014,7 +2014,7 @@ mlx5e_create_vxlan_flow_table(struct mlx5e_priv *priv)
ft->num_groups = 0;
ft_attr.max_fte = MLX5E_VXLAN_TABLE_SIZE;
- ft_attr.level = (priv->ipsec) ? 9 : 1;
+ ft_attr.level = (priv->ipsec) ? 10 : 1;
ft->t = mlx5_create_flow_table(priv->fts.ns, &ft_attr);
if (IS_ERR(ft->t)) {