net/mlx5e: Move MACsec flow steering operations to be used as core library
authorPatrisious Haddad <phaddad@nvidia.com>
Tue, 29 Nov 2022 12:50:22 +0000 (14:50 +0200)
committerLeon Romanovsky <leon@kernel.org>
Sun, 20 Aug 2023 09:35:23 +0000 (12:35 +0300)
Move MACsec flow steering operations(macsec_fs) from core/en_accel to
core/lib, this mandates moving MACsec statistics structure from the
general MACsec code header(en_accel/macsec.h) to macsec_fs header to
remove macsec_fs.h dependency over en_accel/macsec.h.

This to lay the ground for RoCE MACsec by moving all the data
that will need to be accessed by both ethernet MACsec and
RoCE MACsec to be shared at core.

Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c [deleted file]
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h [deleted file]
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h [new file with mode: 0644]

index bb1d7b039a7e5b1d736a5c7b3b13d9801c749228..f3b284db1b5bddf53518236c9078990704ac4305 100644 (file)
@@ -139,7 +139,7 @@ config MLX5_CORE_IPOIB
        help
          MLX5 IPoIB offloads & acceleration support.
 
-config MLX5_EN_MACSEC
+config MLX5_MACSEC
        bool "Connect-X support for MACSec offload"
        depends on MLX5_CORE_EN
        depends on MACSEC
index 35f00700a4d6cacfe7593ed799c7c06888cbe250..ade063b57cd506c352b00069d1efa088000d191f 100644 (file)
@@ -94,7 +94,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib
 #
 mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o
 
-mlx5_core-$(CONFIG_MLX5_EN_MACSEC) += en_accel/macsec.o en_accel/macsec_fs.o \
+mlx5_core-$(CONFIG_MLX5_MACSEC) += en_accel/macsec.o lib/macsec_fs.o \
                                      en_accel/macsec_stats.o
 
 mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \
index b1807bfb815f1a43f6c5858d1a3aea5120ecb35b..b82217de9e9f1b6490a8a1e41c203fcad7d42257 100644 (file)
@@ -917,7 +917,7 @@ struct mlx5e_priv {
 
        const struct mlx5e_profile *profile;
        void                      *ppriv;
-#ifdef CONFIG_MLX5_EN_MACSEC
+#ifdef CONFIG_MLX5_MACSEC
        struct mlx5e_macsec       *macsec;
 #endif
 #ifdef CONFIG_MLX5_EN_IPSEC
index bac4717548c67e9e6ac900929de542e1b19b6bdf..caa34b9c161e5188a9ac1607a01e8c390d95d568 100644 (file)
@@ -138,7 +138,7 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
        }
 #endif
 
-#ifdef CONFIG_MLX5_EN_MACSEC
+#ifdef CONFIG_MLX5_MACSEC
        if (unlikely(mlx5e_macsec_skb_is_offload(skb))) {
                struct mlx5e_priv *priv = netdev_priv(dev);
 
@@ -173,7 +173,7 @@ static inline void mlx5e_accel_tx_eseg(struct mlx5e_priv *priv,
                mlx5e_ipsec_tx_build_eseg(priv, skb, eseg);
 #endif
 
-#ifdef CONFIG_MLX5_EN_MACSEC
+#ifdef CONFIG_MLX5_MACSEC
        if (unlikely(mlx5e_macsec_skb_is_offload(skb)))
                mlx5e_macsec_tx_build_eseg(priv->macsec, skb, eseg);
 #endif
index 592b165530ffa376031f19fa54736b345f9fc612..b26044efdec6a1fdc595606cb1d4cd6c1ab48974 100644 (file)
@@ -10,7 +10,6 @@
 #include "lib/aso.h"
 #include "lib/crypto.h"
 #include "en_accel/macsec.h"
-#include "en_accel/macsec_fs.h"
 
 #define MLX5_MACSEC_EPN_SCOPE_MID 0x80000000L
 #define MLX5E_MACSEC_ASO_CTX_SZ MLX5_ST_SZ_BYTES(macsec_aso)
index 347380a2cd9c7fca2b903eec872f8c1978b512fb..1f9c4a2723b2febc9ad60a88f417a84c68c574db 100644 (file)
@@ -4,32 +4,16 @@
 #ifndef __MLX5_EN_ACCEL_MACSEC_H__
 #define __MLX5_EN_ACCEL_MACSEC_H__
 
-#ifdef CONFIG_MLX5_EN_MACSEC
+#ifdef CONFIG_MLX5_MACSEC
 
 #include <linux/mlx5/driver.h>
 #include <net/macsec.h>
 #include <net/dst_metadata.h>
-
-/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */
-#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */
-#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX
-#define MLX5_MACSEC_METADATA_MARKER(metadata)  ((((metadata) >> 30) & 0x3)  == 0x1)
-#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata)  ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK)
+#include "lib/macsec_fs.h"
 
 struct mlx5e_priv;
 struct mlx5e_macsec;
 
-struct mlx5e_macsec_stats {
-       u64 macsec_rx_pkts;
-       u64 macsec_rx_bytes;
-       u64 macsec_rx_pkts_drop;
-       u64 macsec_rx_bytes_drop;
-       u64 macsec_tx_pkts;
-       u64 macsec_tx_bytes;
-       u64 macsec_tx_pkts_drop;
-       u64 macsec_tx_bytes_drop;
-};
-
 void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv);
 int mlx5e_macsec_init(struct mlx5e_priv *priv);
 void mlx5e_macsec_cleanup(struct mlx5e_priv *priv);
@@ -68,6 +52,6 @@ static inline void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
                                                      struct mlx5_cqe64 *cqe)
 {}
 static inline bool mlx5e_is_macsec_device(const struct mlx5_core_dev *mdev) { return false; }
-#endif  /* CONFIG_MLX5_EN_MACSEC */
+#endif  /* CONFIG_MLX5_MACSEC */
 
 #endif /* __MLX5_ACCEL_EN_MACSEC_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
deleted file mode 100644 (file)
index 7fc901a..0000000
+++ /dev/null
@@ -1,1393 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
-/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
-
-#include <net/macsec.h>
-#include <linux/netdevice.h>
-#include <linux/mlx5/qp.h>
-#include <linux/if_vlan.h>
-#include "fs_core.h"
-#include "en/fs.h"
-#include "en_accel/macsec_fs.h"
-#include "mlx5_core.h"
-
-/* MACsec TX flow steering */
-#define CRYPTO_NUM_MAXSEC_FTE BIT(15)
-#define CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE 1
-
-#define TX_CRYPTO_TABLE_LEVEL 0
-#define TX_CRYPTO_TABLE_NUM_GROUPS 3
-#define TX_CRYPTO_TABLE_MKE_GROUP_SIZE 1
-#define TX_CRYPTO_TABLE_SA_GROUP_SIZE \
-       (CRYPTO_NUM_MAXSEC_FTE - (TX_CRYPTO_TABLE_MKE_GROUP_SIZE + \
-                                 CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE))
-#define TX_CHECK_TABLE_LEVEL 1
-#define TX_CHECK_TABLE_NUM_FTE 2
-#define RX_CRYPTO_TABLE_LEVEL 0
-#define RX_CHECK_TABLE_LEVEL 1
-#define RX_CHECK_TABLE_NUM_FTE 3
-#define RX_CRYPTO_TABLE_NUM_GROUPS 3
-#define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \
-       ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2)
-#define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \
-       (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE)
-#define RX_NUM_OF_RULES_PER_SA 2
-
-#define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */
-#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23
-#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8
-#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET 0x5
-#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT (0x1 << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET)
-#define MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI 0x8
-#define MLX5_SECTAG_HEADER_SIZE_WITH_SCI (MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI + MACSEC_SCI_LEN)
-
-/* MACsec RX flow steering */
-#define MLX5_ETH_WQE_FT_META_MACSEC_MASK 0x3E
-
-struct mlx5_sectag_header {
-       __be16 ethertype;
-       u8 tci_an;
-       u8 sl;
-       u32 pn;
-       u8 sci[MACSEC_SCI_LEN]; /* optional */
-}  __packed;
-
-struct mlx5e_macsec_tx_rule {
-       struct mlx5_flow_handle *rule;
-       struct mlx5_pkt_reformat *pkt_reformat;
-       u32 fs_id;
-};
-
-struct mlx5e_macsec_tables {
-       struct mlx5e_flow_table ft_crypto;
-       struct mlx5_flow_handle *crypto_miss_rule;
-
-       struct mlx5_flow_table *ft_check;
-       struct mlx5_flow_group  *ft_check_group;
-       struct mlx5_fc *check_miss_rule_counter;
-       struct mlx5_flow_handle *check_miss_rule;
-       struct mlx5_fc *check_rule_counter;
-
-       u32 refcnt;
-};
-
-struct mlx5e_macsec_tx {
-       struct mlx5_flow_handle *crypto_mke_rule;
-       struct mlx5_flow_handle *check_rule;
-
-       struct ida tx_halloc;
-
-       struct mlx5e_macsec_tables tables;
-};
-
-struct mlx5e_macsec_rx_rule {
-       struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA];
-       struct mlx5_modify_hdr *meta_modhdr;
-};
-
-struct mlx5e_macsec_rx {
-       struct mlx5_flow_handle *check_rule[2];
-       struct mlx5_pkt_reformat *check_rule_pkt_reformat[2];
-
-       struct mlx5e_macsec_tables tables;
-};
-
-union mlx5e_macsec_rule {
-       struct mlx5e_macsec_tx_rule tx_rule;
-       struct mlx5e_macsec_rx_rule rx_rule;
-};
-
-struct mlx5e_macsec_fs {
-       struct mlx5_core_dev *mdev;
-       struct net_device *netdev;
-       struct mlx5e_macsec_tx *tx_fs;
-       struct mlx5e_macsec_rx *rx_fs;
-};
-
-static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       struct mlx5e_macsec_tables *tx_tables;
-
-       tx_tables = &tx_fs->tables;
-
-       /* Tx check table */
-       if (tx_fs->check_rule) {
-               mlx5_del_flow_rules(tx_fs->check_rule);
-               tx_fs->check_rule = NULL;
-       }
-
-       if (tx_tables->check_miss_rule) {
-               mlx5_del_flow_rules(tx_tables->check_miss_rule);
-               tx_tables->check_miss_rule = NULL;
-       }
-
-       if (tx_tables->ft_check_group) {
-               mlx5_destroy_flow_group(tx_tables->ft_check_group);
-               tx_tables->ft_check_group = NULL;
-       }
-
-       if (tx_tables->ft_check) {
-               mlx5_destroy_flow_table(tx_tables->ft_check);
-               tx_tables->ft_check = NULL;
-       }
-
-       /* Tx crypto table */
-       if (tx_fs->crypto_mke_rule) {
-               mlx5_del_flow_rules(tx_fs->crypto_mke_rule);
-               tx_fs->crypto_mke_rule = NULL;
-       }
-
-       if (tx_tables->crypto_miss_rule) {
-               mlx5_del_flow_rules(tx_tables->crypto_miss_rule);
-               tx_tables->crypto_miss_rule = NULL;
-       }
-
-       mlx5e_destroy_flow_table(&tx_tables->ft_crypto);
-}
-
-static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
-{
-       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
-       int ix = 0;
-       u32 *in;
-       int err;
-       u8 *mc;
-
-       ft->g = kcalloc(TX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
-       if (!ft->g)
-               return -ENOMEM;
-       in = kvzalloc(inlen, GFP_KERNEL);
-
-       if (!in) {
-               kfree(ft->g);
-               return -ENOMEM;
-       }
-
-       mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
-
-       /* Flow Group for MKE match */
-       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
-       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
-
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += TX_CRYPTO_TABLE_MKE_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       /* Flow Group for SA rules */
-       memset(in, 0, inlen);
-       memset(mc, 0, mclen);
-       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2);
-       MLX5_SET(fte_match_param, mc, misc_parameters_2.metadata_reg_a,
-                MLX5_ETH_WQE_FT_META_MACSEC_MASK);
-
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += TX_CRYPTO_TABLE_SA_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       /* Flow Group for l2 traps */
-       memset(in, 0, inlen);
-       memset(mc, 0, mclen);
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       kvfree(in);
-       return 0;
-
-err:
-       err = PTR_ERR(ft->g[ft->num_groups]);
-       ft->g[ft->num_groups] = NULL;
-       kvfree(in);
-
-       return err;
-}
-
-static struct mlx5_flow_table
-       *macsec_fs_auto_group_table_create(struct mlx5_flow_namespace *ns, int flags,
-                                          int level, int max_fte)
-{
-       struct mlx5_flow_table_attr ft_attr = {};
-       struct mlx5_flow_table *fdb = NULL;
-
-       /* reserve entry for the match all miss group and rule */
-       ft_attr.autogroup.num_reserved_entries = 1;
-       ft_attr.autogroup.max_num_groups = 1;
-       ft_attr.prio = 0;
-       ft_attr.flags = flags;
-       ft_attr.level = level;
-       ft_attr.max_fte = max_fte;
-
-       fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
-
-       return fdb;
-}
-
-static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs)
-{
-       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       struct net_device *netdev = macsec_fs->netdev;
-       struct mlx5_flow_table_attr ft_attr = {};
-       struct mlx5_flow_destination dest = {};
-       struct mlx5e_macsec_tables *tx_tables;
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5e_flow_table *ft_crypto;
-       struct mlx5_flow_table *flow_table;
-       struct mlx5_flow_group *flow_group;
-       struct mlx5_flow_namespace *ns;
-       struct mlx5_flow_handle *rule;
-       struct mlx5_flow_spec *spec;
-       u32 *flow_group_in;
-       int err;
-
-       ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
-       if (!ns)
-               return -ENOMEM;
-
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return -ENOMEM;
-
-       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
-       if (!flow_group_in) {
-               err = -ENOMEM;
-               goto out_spec;
-       }
-
-       tx_tables = &tx_fs->tables;
-       ft_crypto = &tx_tables->ft_crypto;
-
-       /* Tx crypto table  */
-       ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
-       ft_attr.level = TX_CRYPTO_TABLE_LEVEL;
-       ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
-
-       flow_table = mlx5_create_flow_table(ns, &ft_attr);
-       if (IS_ERR(flow_table)) {
-               err = PTR_ERR(flow_table);
-               netdev_err(netdev, "Failed to create MACsec Tx crypto table err(%d)\n", err);
-               goto out_flow_group;
-       }
-       ft_crypto->t = flow_table;
-
-       /* Tx crypto table groups */
-       err = macsec_fs_tx_create_crypto_table_groups(ft_crypto);
-       if (err) {
-               netdev_err(netdev,
-                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
-                          err);
-               goto err;
-       }
-
-       /* Tx crypto table MKE rule - MKE packets shouldn't be offloaded */
-       spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
-
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
-       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_PAE);
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
-
-       rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to add MACsec TX MKE rule, err=%d\n", err);
-               goto err;
-       }
-       tx_fs->crypto_mke_rule = rule;
-
-       /* Tx crypto table Default miss rule */
-       memset(&flow_act, 0, sizeof(flow_act));
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
-       rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to add MACsec Tx table default miss rule %d\n", err);
-               goto err;
-       }
-       tx_tables->crypto_miss_rule = rule;
-
-       /* Tx check table */
-       flow_table = macsec_fs_auto_group_table_create(ns, 0, TX_CHECK_TABLE_LEVEL,
-                                                      TX_CHECK_TABLE_NUM_FTE);
-       if (IS_ERR(flow_table)) {
-               err = PTR_ERR(flow_table);
-               netdev_err(netdev, "fail to create MACsec TX check table, err(%d)\n", err);
-               goto err;
-       }
-       tx_tables->ft_check = flow_table;
-
-       /* Tx check table Default miss group/rule */
-       memset(flow_group_in, 0, inlen);
-       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
-       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
-       flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in);
-       if (IS_ERR(flow_group)) {
-               err = PTR_ERR(flow_group);
-               netdev_err(netdev,
-                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
-                          err);
-               goto err;
-       }
-       tx_tables->ft_check_group = flow_group;
-
-       /* Tx check table default drop rule */
-       memset(&dest, 0, sizeof(struct mlx5_flow_destination));
-       memset(&flow_act, 0, sizeof(flow_act));
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-       dest.counter_id = mlx5_fc_id(tx_tables->check_miss_rule_counter);
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       rule = mlx5_add_flow_rules(tx_tables->ft_check,  NULL, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err);
-               goto err;
-       }
-       tx_tables->check_miss_rule = rule;
-
-       /* Tx check table rule */
-       memset(spec, 0, sizeof(struct mlx5_flow_spec));
-       memset(&dest, 0, sizeof(struct mlx5_flow_destination));
-       memset(&flow_act, 0, sizeof(flow_act));
-
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
-       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
-
-       flow_act.flags = FLOW_ACT_NO_APPEND;
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-       dest.counter_id = mlx5_fc_id(tx_tables->check_rule_counter);
-       rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to add MACsec check rule, err=%d\n", err);
-               goto err;
-       }
-       tx_fs->check_rule = rule;
-
-       goto out_flow_group;
-
-err:
-       macsec_fs_tx_destroy(macsec_fs);
-out_flow_group:
-       kvfree(flow_group_in);
-out_spec:
-       kvfree(spec);
-       return err;
-}
-
-static int macsec_fs_tx_ft_get(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       struct mlx5e_macsec_tables *tx_tables;
-       int err = 0;
-
-       tx_tables = &tx_fs->tables;
-       if (tx_tables->refcnt)
-               goto out;
-
-       err = macsec_fs_tx_create(macsec_fs);
-       if (err)
-               return err;
-
-out:
-       tx_tables->refcnt++;
-       return err;
-}
-
-static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
-
-       if (--tx_tables->refcnt)
-               return;
-
-       macsec_fs_tx_destroy(macsec_fs);
-}
-
-static int macsec_fs_tx_setup_fte(struct mlx5e_macsec_fs *macsec_fs,
-                                 struct mlx5_flow_spec *spec,
-                                 struct mlx5_flow_act *flow_act,
-                                 u32 macsec_obj_id,
-                                 u32 *fs_id)
-{
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       int err = 0;
-       u32 id;
-
-       err = ida_alloc_range(&tx_fs->tx_halloc, 1,
-                             MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES,
-                             GFP_KERNEL);
-       if (err < 0)
-               return err;
-
-       id = err;
-       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
-
-       /* Metadata match */
-       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a,
-                MLX5_ETH_WQE_FT_META_MACSEC_MASK);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a,
-                MLX5_ETH_WQE_FT_META_MACSEC | id << 2);
-
-       *fs_id = id;
-       flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
-       flow_act->crypto.obj_id = macsec_obj_id;
-
-       mlx5_core_dbg(macsec_fs->mdev, "Tx fte: macsec obj_id %u, fs_id %u\n", macsec_obj_id, id);
-       return 0;
-}
-
-static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx,
-                                             char *reformatbf,
-                                             size_t *reformat_size)
-{
-       const struct macsec_secy *secy = ctx->secy;
-       bool sci_present = macsec_send_sci(secy);
-       struct mlx5_sectag_header sectag = {};
-       const struct macsec_tx_sc *tx_sc;
-
-       tx_sc = &secy->tx_sc;
-       sectag.ethertype = htons(ETH_P_MACSEC);
-
-       if (sci_present) {
-               sectag.tci_an |= MACSEC_TCI_SC;
-               memcpy(&sectag.sci, &secy->sci,
-                      sizeof(sectag.sci));
-       } else {
-               if (tx_sc->end_station)
-                       sectag.tci_an |= MACSEC_TCI_ES;
-               if (tx_sc->scb)
-                       sectag.tci_an |= MACSEC_TCI_SCB;
-       }
-
-       /* With GCM, C/E clear for !encrypt, both set for encrypt */
-       if (tx_sc->encrypt)
-               sectag.tci_an |= MACSEC_TCI_CONFID;
-       else if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
-               sectag.tci_an |= MACSEC_TCI_C;
-
-       sectag.tci_an |= tx_sc->encoding_sa;
-
-       *reformat_size = MLX5_MACSEC_TAG_LEN + (sci_present ? MACSEC_SCI_LEN : 0);
-
-       memcpy(reformatbf, &sectag, *reformat_size);
-}
-
-static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs,
-                                 struct mlx5e_macsec_tx_rule *tx_rule)
-{
-       if (tx_rule->rule) {
-               mlx5_del_flow_rules(tx_rule->rule);
-               tx_rule->rule = NULL;
-       }
-
-       if (tx_rule->pkt_reformat) {
-               mlx5_packet_reformat_dealloc(macsec_fs->mdev, tx_rule->pkt_reformat);
-               tx_rule->pkt_reformat = NULL;
-       }
-
-       if (tx_rule->fs_id) {
-               ida_free(&macsec_fs->tx_fs->tx_halloc, tx_rule->fs_id);
-               tx_rule->fs_id = 0;
-       }
-
-       kfree(tx_rule);
-
-       macsec_fs_tx_ft_put(macsec_fs);
-}
-
-#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1
-
-static union mlx5e_macsec_rule *
-macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
-                     const struct macsec_context *macsec_ctx,
-                     struct mlx5_macsec_rule_attrs *attrs,
-                     u32 *sa_fs_id)
-{
-       char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN];
-       struct mlx5_pkt_reformat_params reformat_params = {};
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       struct net_device *netdev = macsec_fs->netdev;
-       union mlx5e_macsec_rule *macsec_rule = NULL;
-       struct mlx5_flow_destination dest = {};
-       struct mlx5e_macsec_tables *tx_tables;
-       struct mlx5e_macsec_tx_rule *tx_rule;
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5_flow_handle *rule;
-       struct mlx5_flow_spec *spec;
-       size_t reformat_size;
-       int err = 0;
-       u32 fs_id;
-
-       tx_tables = &tx_fs->tables;
-
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return NULL;
-
-       err = macsec_fs_tx_ft_get(macsec_fs);
-       if (err)
-               goto out_spec;
-
-       macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
-       if (!macsec_rule) {
-               macsec_fs_tx_ft_put(macsec_fs);
-               goto out_spec;
-       }
-
-       tx_rule = &macsec_rule->tx_rule;
-
-       /* Tx crypto table crypto rule */
-       macsec_fs_tx_create_sectag_header(macsec_ctx, reformatbf, &reformat_size);
-
-       reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC;
-       reformat_params.size = reformat_size;
-       reformat_params.data = reformatbf;
-
-       if (is_vlan_dev(macsec_ctx->netdev))
-               reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES;
-
-       flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev,
-                                                          &reformat_params,
-                                                          MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
-       if (IS_ERR(flow_act.pkt_reformat)) {
-               err = PTR_ERR(flow_act.pkt_reformat);
-               netdev_err(netdev, "Failed to allocate MACsec Tx reformat context err=%d\n",  err);
-               goto err;
-       }
-       tx_rule->pkt_reformat = flow_act.pkt_reformat;
-
-       err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id);
-       if (err) {
-               netdev_err(netdev,
-                          "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n",
-                          err);
-               goto err;
-       }
-
-       tx_rule->fs_id = fs_id;
-       *sa_fs_id = fs_id;
-
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
-                         MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
-                         MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
-       dest.ft = tx_tables->ft_check;
-       rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to add MACsec TX crypto rule, err=%d\n", err);
-               goto err;
-       }
-       tx_rule->rule = rule;
-
-       goto out_spec;
-
-err:
-       macsec_fs_tx_del_rule(macsec_fs, tx_rule);
-       macsec_rule = NULL;
-out_spec:
-       kvfree(spec);
-
-       return macsec_rule;
-}
-
-static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
-       struct mlx5_core_dev *mdev = macsec_fs->mdev;
-       struct mlx5e_macsec_tables *tx_tables;
-
-       if (!tx_fs)
-               return;
-
-       tx_tables = &tx_fs->tables;
-       if (tx_tables->refcnt) {
-               netdev_err(macsec_fs->netdev,
-                          "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n",
-                          tx_tables->refcnt);
-               return;
-       }
-
-       ida_destroy(&tx_fs->tx_halloc);
-
-       if (tx_tables->check_miss_rule_counter) {
-               mlx5_fc_destroy(mdev, tx_tables->check_miss_rule_counter);
-               tx_tables->check_miss_rule_counter = NULL;
-       }
-
-       if (tx_tables->check_rule_counter) {
-               mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
-               tx_tables->check_rule_counter = NULL;
-       }
-
-       kfree(tx_fs);
-       macsec_fs->tx_fs = NULL;
-}
-
-static int macsec_fs_tx_init(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct net_device *netdev = macsec_fs->netdev;
-       struct mlx5_core_dev *mdev = macsec_fs->mdev;
-       struct mlx5e_macsec_tables *tx_tables;
-       struct mlx5e_macsec_tx *tx_fs;
-       struct mlx5_fc *flow_counter;
-       int err;
-
-       tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL);
-       if (!tx_fs)
-               return -ENOMEM;
-
-       tx_tables = &tx_fs->tables;
-
-       flow_counter = mlx5_fc_create(mdev, false);
-       if (IS_ERR(flow_counter)) {
-               err = PTR_ERR(flow_counter);
-               netdev_err(netdev,
-                          "Failed to create MACsec Tx encrypt flow counter, err(%d)\n",
-                          err);
-               goto err_encrypt_counter;
-       }
-       tx_tables->check_rule_counter = flow_counter;
-
-       flow_counter = mlx5_fc_create(mdev, false);
-       if (IS_ERR(flow_counter)) {
-               err = PTR_ERR(flow_counter);
-               netdev_err(netdev,
-                          "Failed to create MACsec Tx drop flow counter, err(%d)\n",
-                          err);
-               goto err_drop_counter;
-       }
-       tx_tables->check_miss_rule_counter = flow_counter;
-
-       ida_init(&tx_fs->tx_halloc);
-
-       macsec_fs->tx_fs = tx_fs;
-
-       return 0;
-
-err_drop_counter:
-       mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
-       tx_tables->check_rule_counter = NULL;
-
-err_encrypt_counter:
-       kfree(tx_fs);
-       macsec_fs->tx_fs = NULL;
-
-       return err;
-}
-
-static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
-       struct mlx5e_macsec_tables *rx_tables;
-       int i;
-
-       /* Rx check table */
-       for (i = 1; i >= 0; --i) {
-               if (rx_fs->check_rule[i]) {
-                       mlx5_del_flow_rules(rx_fs->check_rule[i]);
-                       rx_fs->check_rule[i] = NULL;
-               }
-
-               if (rx_fs->check_rule_pkt_reformat[i]) {
-                       mlx5_packet_reformat_dealloc(macsec_fs->mdev,
-                                                    rx_fs->check_rule_pkt_reformat[i]);
-                       rx_fs->check_rule_pkt_reformat[i] = NULL;
-               }
-       }
-
-       rx_tables = &rx_fs->tables;
-
-       if (rx_tables->check_miss_rule) {
-               mlx5_del_flow_rules(rx_tables->check_miss_rule);
-               rx_tables->check_miss_rule = NULL;
-       }
-
-       if (rx_tables->ft_check_group) {
-               mlx5_destroy_flow_group(rx_tables->ft_check_group);
-               rx_tables->ft_check_group = NULL;
-       }
-
-       if (rx_tables->ft_check) {
-               mlx5_destroy_flow_table(rx_tables->ft_check);
-               rx_tables->ft_check = NULL;
-       }
-
-       /* Rx crypto table */
-       if (rx_tables->crypto_miss_rule) {
-               mlx5_del_flow_rules(rx_tables->crypto_miss_rule);
-               rx_tables->crypto_miss_rule = NULL;
-       }
-
-       mlx5e_destroy_flow_table(&rx_tables->ft_crypto);
-}
-
-static int macsec_fs_rx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
-{
-       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
-       int ix = 0;
-       u32 *in;
-       int err;
-       u8 *mc;
-
-       ft->g = kcalloc(RX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
-       if (!ft->g)
-               return -ENOMEM;
-
-       in = kvzalloc(inlen, GFP_KERNEL);
-       if (!in) {
-               kfree(ft->g);
-               return -ENOMEM;
-       }
-
-       mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
-
-       /* Flow group for SA rule with SCI */
-       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
-                                               MLX5_MATCH_MISC_PARAMETERS_5);
-       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
-
-       MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
-                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK <<
-                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-       MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_2);
-       MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_3);
-
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       /* Flow group for SA rule without SCI */
-       memset(in, 0, inlen);
-       memset(mc, 0, mclen);
-       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
-                                               MLX5_MATCH_MISC_PARAMETERS_5);
-       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_47_16);
-       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_15_0);
-       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
-
-       MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
-                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       /* Flow Group for l2 traps */
-       memset(in, 0, inlen);
-       memset(mc, 0, mclen);
-       MLX5_SET_CFG(in, start_flow_index, ix);
-       ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
-       MLX5_SET_CFG(in, end_flow_index, ix - 1);
-       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
-       if (IS_ERR(ft->g[ft->num_groups]))
-               goto err;
-       ft->num_groups++;
-
-       kvfree(in);
-       return 0;
-
-err:
-       err = PTR_ERR(ft->g[ft->num_groups]);
-       ft->g[ft->num_groups] = NULL;
-       kvfree(in);
-
-       return err;
-}
-
-static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_fs,
-                                               struct mlx5_flow_destination *dest,
-                                               struct mlx5_flow_act *flow_act,
-                                               struct mlx5_flow_spec *spec,
-                                               int reformat_param_size)
-{
-       int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1;
-       u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI];
-       struct mlx5_pkt_reformat_params reformat_params = {};
-       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
-       struct net_device *netdev = macsec_fs->netdev;
-       struct mlx5e_macsec_tables *rx_tables;
-       struct mlx5_flow_handle *rule;
-       int err = 0;
-
-       rx_tables = &rx_fs->tables;
-
-       /* Rx check table decap 16B rule */
-       memset(dest, 0, sizeof(*dest));
-       memset(flow_act, 0, sizeof(*flow_act));
-       memset(spec, 0, sizeof(*spec));
-
-       reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC;
-       reformat_params.size = reformat_param_size;
-       reformat_params.data = mlx5_reformat_buf;
-       flow_act->pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev,
-                                                           &reformat_params,
-                                                           MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
-       if (IS_ERR(flow_act->pkt_reformat)) {
-               err = PTR_ERR(flow_act->pkt_reformat);
-               netdev_err(netdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err);
-               return err;
-       }
-       rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat;
-
-       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
-       /* MACsec syndrome match */
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.macsec_syndrome);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.macsec_syndrome, 0);
-       /* ASO return reg syndrome match */
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
-
-       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
-       /* Sectag TCI SC present bit*/
-       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
-                MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-
-       if (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI)
-               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
-                        MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT <<
-                        MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-
-       flow_act->flags = FLOW_ACT_NO_APPEND;
-       flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO |
-                          MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
-                          MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-       dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter);
-       rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to add MACsec Rx check rule, err=%d\n", err);
-               return err;
-       }
-
-       rx_fs->check_rule[rule_index] = rule;
-
-       return 0;
-}
-
-static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs)
-{
-       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
-       struct net_device *netdev = macsec_fs->netdev;
-       struct mlx5_flow_table_attr ft_attr = {};
-       struct mlx5_flow_destination dest = {};
-       struct mlx5e_macsec_tables *rx_tables;
-       struct mlx5e_flow_table *ft_crypto;
-       struct mlx5_flow_table *flow_table;
-       struct mlx5_flow_group *flow_group;
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5_flow_namespace *ns;
-       struct mlx5_flow_handle *rule;
-       struct mlx5_flow_spec *spec;
-       u32 *flow_group_in;
-       int err;
-
-       ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
-       if (!ns)
-               return -ENOMEM;
-
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return -ENOMEM;
-
-       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
-       if (!flow_group_in) {
-               err = -ENOMEM;
-               goto free_spec;
-       }
-
-       rx_tables = &rx_fs->tables;
-       ft_crypto = &rx_tables->ft_crypto;
-
-       /* Rx crypto table */
-       ft_attr.level = RX_CRYPTO_TABLE_LEVEL;
-       ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
-
-       flow_table = mlx5_create_flow_table(ns, &ft_attr);
-       if (IS_ERR(flow_table)) {
-               err = PTR_ERR(flow_table);
-               netdev_err(netdev, "Failed to create MACsec Rx crypto table err(%d)\n", err);
-               goto out_flow_group;
-       }
-       ft_crypto->t = flow_table;
-
-       /* Rx crypto table groups */
-       err = macsec_fs_rx_create_crypto_table_groups(ft_crypto);
-       if (err) {
-               netdev_err(netdev,
-                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
-                          err);
-               goto err;
-       }
-
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
-       rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev,
-                          "Failed to add MACsec Rx crypto table default miss rule %d\n",
-                          err);
-               goto err;
-       }
-       rx_tables->crypto_miss_rule = rule;
-
-       /* Rx check table */
-       flow_table = macsec_fs_auto_group_table_create(ns,
-                                                      MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT,
-                                                      RX_CHECK_TABLE_LEVEL,
-                                                      RX_CHECK_TABLE_NUM_FTE);
-       if (IS_ERR(flow_table)) {
-               err = PTR_ERR(flow_table);
-               netdev_err(netdev, "fail to create MACsec RX check table, err(%d)\n", err);
-               goto err;
-       }
-       rx_tables->ft_check = flow_table;
-
-       /* Rx check table Default miss group/rule */
-       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
-       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
-       flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in);
-       if (IS_ERR(flow_group)) {
-               err = PTR_ERR(flow_group);
-               netdev_err(netdev,
-                          "Failed to create default flow group for MACsec Rx check table err(%d)\n",
-                          err);
-               goto err;
-       }
-       rx_tables->ft_check_group = flow_group;
-
-       /* Rx check table default drop rule */
-       memset(&flow_act, 0, sizeof(flow_act));
-
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-       dest.counter_id = mlx5_fc_id(rx_tables->check_miss_rule_counter);
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
-       rule = mlx5_add_flow_rules(rx_tables->ft_check,  NULL, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err);
-               goto err;
-       }
-       rx_tables->check_miss_rule = rule;
-
-       /* Rx check table decap rules */
-       err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
-                                                  MLX5_SECTAG_HEADER_SIZE_WITH_SCI);
-       if (err)
-               goto err;
-
-       err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
-                                                  MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI);
-       if (err)
-               goto err;
-
-       goto out_flow_group;
-
-err:
-       macsec_fs_rx_destroy(macsec_fs);
-out_flow_group:
-       kvfree(flow_group_in);
-free_spec:
-       kvfree(spec);
-       return err;
-}
-
-static int macsec_fs_rx_ft_get(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
-       int err = 0;
-
-       if (rx_tables->refcnt)
-               goto out;
-
-       err = macsec_fs_rx_create(macsec_fs);
-       if (err)
-               return err;
-
-out:
-       rx_tables->refcnt++;
-       return err;
-}
-
-static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
-
-       if (--rx_tables->refcnt)
-               return;
-
-       macsec_fs_rx_destroy(macsec_fs);
-}
-
-static void macsec_fs_rx_del_rule(struct mlx5e_macsec_fs *macsec_fs,
-                                 struct mlx5e_macsec_rx_rule *rx_rule)
-{
-       int i;
-
-       for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) {
-               if (rx_rule->rule[i]) {
-                       mlx5_del_flow_rules(rx_rule->rule[i]);
-                       rx_rule->rule[i] = NULL;
-               }
-       }
-
-       if (rx_rule->meta_modhdr) {
-               mlx5_modify_header_dealloc(macsec_fs->mdev, rx_rule->meta_modhdr);
-               rx_rule->meta_modhdr = NULL;
-       }
-
-       kfree(rx_rule);
-
-       macsec_fs_rx_ft_put(macsec_fs);
-}
-
-static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec,
-                                  struct mlx5_flow_act *flow_act,
-                                  struct mlx5_macsec_rule_attrs *attrs,
-                                  bool sci_present)
-{
-       u8 tci_an = (sci_present << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) | attrs->assoc_num;
-       struct mlx5_flow_act_crypto_params *crypto_params = &flow_act->crypto;
-       __be32 *sci_p = (__be32 *)(&attrs->sci);
-
-       spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
-
-       /* MACsec ethertype */
-       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
-       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_MACSEC);
-
-       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
-
-       /* Sectag AN + TCI SC present bit*/
-       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
-                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
-                tci_an << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
-
-       if (sci_present) {
-               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
-                                misc_parameters_5.macsec_tag_2);
-               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_2,
-                        be32_to_cpu(sci_p[0]));
-
-               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
-                                misc_parameters_5.macsec_tag_3);
-               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_3,
-                        be32_to_cpu(sci_p[1]));
-       } else {
-               /* When SCI isn't present in the Sectag, need to match the source */
-               /* MAC address only if the SCI contains the default MACsec PORT   */
-               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
-               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
-               memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers.smac_47_16),
-                      sci_p, ETH_ALEN);
-       }
-
-       crypto_params->type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
-       crypto_params->obj_id = attrs->macsec_obj_id;
-}
-
-static union mlx5e_macsec_rule *
-macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
-                     struct mlx5_macsec_rule_attrs *attrs,
-                     u32 fs_id)
-{
-       u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
-       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
-       struct net_device *netdev = macsec_fs->netdev;
-       union mlx5e_macsec_rule *macsec_rule = NULL;
-       struct mlx5_modify_hdr *modify_hdr = NULL;
-       struct mlx5_flow_destination dest = {};
-       struct mlx5e_macsec_tables *rx_tables;
-       struct mlx5e_macsec_rx_rule *rx_rule;
-       struct mlx5_flow_act flow_act = {};
-       struct mlx5e_flow_table *ft_crypto;
-       struct mlx5_flow_handle *rule;
-       struct mlx5_flow_spec *spec;
-       int err = 0;
-
-       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec)
-               return NULL;
-
-       err = macsec_fs_rx_ft_get(macsec_fs);
-       if (err)
-               goto out_spec;
-
-       macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
-       if (!macsec_rule) {
-               macsec_fs_rx_ft_put(macsec_fs);
-               goto out_spec;
-       }
-
-       rx_rule = &macsec_rule->rx_rule;
-       rx_tables = &rx_fs->tables;
-       ft_crypto = &rx_tables->ft_crypto;
-
-       /* Set bit[31 - 30] macsec marker - 0x01 */
-       /* Set bit[15-0] fs 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_B);
-       MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30));
-       MLX5_SET(set_action_in, action, offset, 0);
-       MLX5_SET(set_action_in, action, length, 32);
-
-       modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC,
-                                             1, action);
-       if (IS_ERR(modify_hdr)) {
-               err = PTR_ERR(modify_hdr);
-               netdev_err(netdev, "fail to alloc MACsec set modify_header_id err=%d\n", err);
-               modify_hdr = NULL;
-               goto err;
-       }
-       rx_rule->meta_modhdr = modify_hdr;
-
-       /* Rx crypto table with SCI rule */
-       macsec_fs_rx_setup_fte(spec, &flow_act, attrs, true);
-
-       flow_act.modify_hdr = modify_hdr;
-       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
-                         MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
-                         MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
-
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
-       dest.ft = rx_tables->ft_check;
-       rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
-       if (IS_ERR(rule)) {
-               err = PTR_ERR(rule);
-               netdev_err(netdev,
-                          "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n",
-                          err);
-               goto err;
-       }
-       rx_rule->rule[0] = rule;
-
-       /* Rx crypto table without SCI rule */
-       if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) {
-               memset(spec, 0, sizeof(struct mlx5_flow_spec));
-               memset(&dest, 0, sizeof(struct mlx5_flow_destination));
-               memset(&flow_act, 0, sizeof(flow_act));
-
-               macsec_fs_rx_setup_fte(spec, &flow_act, attrs, false);
-
-               flow_act.modify_hdr = modify_hdr;
-               flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
-                                 MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
-                                 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
-
-               dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
-               dest.ft = rx_tables->ft_check;
-               rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
-               if (IS_ERR(rule)) {
-                       err = PTR_ERR(rule);
-                       netdev_err(netdev,
-                                  "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n",
-                                  err);
-                       goto err;
-               }
-               rx_rule->rule[1] = rule;
-       }
-
-       kvfree(spec);
-       return macsec_rule;
-
-err:
-       macsec_fs_rx_del_rule(macsec_fs, rx_rule);
-       macsec_rule = NULL;
-out_spec:
-       kvfree(spec);
-       return macsec_rule;
-}
-
-static int macsec_fs_rx_init(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct net_device *netdev = macsec_fs->netdev;
-       struct mlx5_core_dev *mdev = macsec_fs->mdev;
-       struct mlx5e_macsec_tables *rx_tables;
-       struct mlx5e_macsec_rx *rx_fs;
-       struct mlx5_fc *flow_counter;
-       int err;
-
-       rx_fs = kzalloc(sizeof(*rx_fs), GFP_KERNEL);
-       if (!rx_fs)
-               return -ENOMEM;
-
-       flow_counter = mlx5_fc_create(mdev, false);
-       if (IS_ERR(flow_counter)) {
-               err = PTR_ERR(flow_counter);
-               netdev_err(netdev,
-                          "Failed to create MACsec Rx encrypt flow counter, err(%d)\n",
-                          err);
-               goto err_encrypt_counter;
-       }
-
-       rx_tables = &rx_fs->tables;
-       rx_tables->check_rule_counter = flow_counter;
-
-       flow_counter = mlx5_fc_create(mdev, false);
-       if (IS_ERR(flow_counter)) {
-               err = PTR_ERR(flow_counter);
-               netdev_err(netdev,
-                          "Failed to create MACsec Rx drop flow counter, err(%d)\n",
-                          err);
-               goto err_drop_counter;
-       }
-       rx_tables->check_miss_rule_counter = flow_counter;
-
-       macsec_fs->rx_fs = rx_fs;
-
-       return 0;
-
-err_drop_counter:
-       mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
-       rx_tables->check_rule_counter = NULL;
-
-err_encrypt_counter:
-       kfree(rx_fs);
-       macsec_fs->rx_fs = NULL;
-
-       return err;
-}
-
-static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs)
-{
-       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
-       struct mlx5_core_dev *mdev = macsec_fs->mdev;
-       struct mlx5e_macsec_tables *rx_tables;
-
-       if (!rx_fs)
-               return;
-
-       rx_tables = &rx_fs->tables;
-
-       if (rx_tables->refcnt) {
-               netdev_err(macsec_fs->netdev,
-                          "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n",
-                          rx_tables->refcnt);
-               return;
-       }
-
-       if (rx_tables->check_miss_rule_counter) {
-               mlx5_fc_destroy(mdev, rx_tables->check_miss_rule_counter);
-               rx_tables->check_miss_rule_counter = NULL;
-       }
-
-       if (rx_tables->check_rule_counter) {
-               mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
-               rx_tables->check_rule_counter = NULL;
-       }
-
-       kfree(rx_fs);
-       macsec_fs->rx_fs = NULL;
-}
-
-void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats)
-{
-       struct mlx5e_macsec_stats *stats = (struct mlx5e_macsec_stats *)macsec_stats;
-       struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
-       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
-       struct mlx5_core_dev *mdev = macsec_fs->mdev;
-
-       if (tx_tables->check_rule_counter)
-               mlx5_fc_query(mdev, tx_tables->check_rule_counter,
-                             &stats->macsec_tx_pkts, &stats->macsec_tx_bytes);
-
-       if (tx_tables->check_miss_rule_counter)
-               mlx5_fc_query(mdev, tx_tables->check_miss_rule_counter,
-                             &stats->macsec_tx_pkts_drop, &stats->macsec_tx_bytes_drop);
-
-       if (rx_tables->check_rule_counter)
-               mlx5_fc_query(mdev, rx_tables->check_rule_counter,
-                             &stats->macsec_rx_pkts, &stats->macsec_rx_bytes);
-
-       if (rx_tables->check_miss_rule_counter)
-               mlx5_fc_query(mdev, rx_tables->check_miss_rule_counter,
-                             &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop);
-}
-
-union mlx5e_macsec_rule *
-mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs,
-                        const struct macsec_context *macsec_ctx,
-                        struct mlx5_macsec_rule_attrs *attrs,
-                        u32 *sa_fs_id)
-{
-       return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
-               macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) :
-               macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id);
-}
-
-void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs,
-                             union mlx5e_macsec_rule *macsec_rule,
-                             int action)
-{
-       (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
-               macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) :
-               macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule);
-}
-
-void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs)
-{
-       macsec_fs_rx_cleanup(macsec_fs);
-       macsec_fs_tx_cleanup(macsec_fs);
-       kfree(macsec_fs);
-}
-
-struct mlx5e_macsec_fs *
-mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev,
-                    struct net_device *netdev)
-{
-       struct mlx5e_macsec_fs *macsec_fs;
-       int err;
-
-       macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL);
-       if (!macsec_fs)
-               return NULL;
-
-       macsec_fs->mdev = mdev;
-       macsec_fs->netdev = netdev;
-
-       err = macsec_fs_tx_init(macsec_fs);
-       if (err) {
-               netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
-               goto err;
-       }
-
-       err = macsec_fs_rx_init(macsec_fs);
-       if (err) {
-               netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
-               goto tx_cleanup;
-       }
-
-       return macsec_fs;
-
-tx_cleanup:
-       macsec_fs_tx_cleanup(macsec_fs);
-err:
-       kfree(macsec_fs);
-       return NULL;
-}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.h
deleted file mode 100644 (file)
index b429648..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
-/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
-
-#ifndef __MLX5_MACSEC_STEERING_H__
-#define __MLX5_MACSEC_STEERING_H__
-
-#ifdef CONFIG_MLX5_EN_MACSEC
-
-#include "en_accel/macsec.h"
-
-#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16
-
-struct mlx5e_macsec_fs;
-union mlx5e_macsec_rule;
-
-struct mlx5_macsec_rule_attrs {
-       sci_t sci;
-       u32 macsec_obj_id;
-       u8 assoc_num;
-       int action;
-};
-
-enum mlx5_macsec_action {
-       MLX5_ACCEL_MACSEC_ACTION_ENCRYPT,
-       MLX5_ACCEL_MACSEC_ACTION_DECRYPT,
-};
-
-void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs);
-
-struct mlx5e_macsec_fs *
-mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev);
-
-union mlx5e_macsec_rule *
-mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs,
-                        const struct macsec_context *ctx,
-                        struct mlx5_macsec_rule_attrs *attrs,
-                        u32 *sa_fs_id);
-
-void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs,
-                             union mlx5e_macsec_rule *macsec_rule,
-                             int action);
-
-void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats);
-
-#endif
-
-#endif /* __MLX5_MACSEC_STEERING_H__ */
index 4d77055abd4be3659672663e97c6b4269435119c..8d7a5a81516294565d7652c726dd3f3bcb708c31 100644 (file)
@@ -2490,7 +2490,7 @@ mlx5e_stats_grp_t mlx5e_nic_stats_grps[] = {
        &MLX5E_STATS_GRP(per_port_buff_congest),
        &MLX5E_STATS_GRP(ptp),
        &MLX5E_STATS_GRP(qos),
-#ifdef CONFIG_MLX5_EN_MACSEC
+#ifdef CONFIG_MLX5_MACSEC
        &MLX5E_STATS_GRP(macsec_hw),
 #endif
 };
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c
new file mode 100644 (file)
index 0000000..3d816ee
--- /dev/null
@@ -0,0 +1,1393 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <net/macsec.h>
+#include <linux/netdevice.h>
+#include <linux/mlx5/qp.h>
+#include <linux/if_vlan.h>
+#include "fs_core.h"
+#include "en/fs.h"
+#include "lib/macsec_fs.h"
+#include "mlx5_core.h"
+
+/* MACsec TX flow steering */
+#define CRYPTO_NUM_MAXSEC_FTE BIT(15)
+#define CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE 1
+
+#define TX_CRYPTO_TABLE_LEVEL 0
+#define TX_CRYPTO_TABLE_NUM_GROUPS 3
+#define TX_CRYPTO_TABLE_MKE_GROUP_SIZE 1
+#define TX_CRYPTO_TABLE_SA_GROUP_SIZE \
+       (CRYPTO_NUM_MAXSEC_FTE - (TX_CRYPTO_TABLE_MKE_GROUP_SIZE + \
+                                 CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE))
+#define TX_CHECK_TABLE_LEVEL 1
+#define TX_CHECK_TABLE_NUM_FTE 2
+#define RX_CRYPTO_TABLE_LEVEL 0
+#define RX_CHECK_TABLE_LEVEL 1
+#define RX_CHECK_TABLE_NUM_FTE 3
+#define RX_CRYPTO_TABLE_NUM_GROUPS 3
+#define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \
+       ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2)
+#define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \
+       (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE)
+#define RX_NUM_OF_RULES_PER_SA 2
+
+#define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */
+#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23
+#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8
+#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET 0x5
+#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT (0x1 << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET)
+#define MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI 0x8
+#define MLX5_SECTAG_HEADER_SIZE_WITH_SCI (MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI + MACSEC_SCI_LEN)
+
+/* MACsec RX flow steering */
+#define MLX5_ETH_WQE_FT_META_MACSEC_MASK 0x3E
+
+struct mlx5_sectag_header {
+       __be16 ethertype;
+       u8 tci_an;
+       u8 sl;
+       u32 pn;
+       u8 sci[MACSEC_SCI_LEN]; /* optional */
+}  __packed;
+
+struct mlx5e_macsec_tx_rule {
+       struct mlx5_flow_handle *rule;
+       struct mlx5_pkt_reformat *pkt_reformat;
+       u32 fs_id;
+};
+
+struct mlx5e_macsec_tables {
+       struct mlx5e_flow_table ft_crypto;
+       struct mlx5_flow_handle *crypto_miss_rule;
+
+       struct mlx5_flow_table *ft_check;
+       struct mlx5_flow_group  *ft_check_group;
+       struct mlx5_fc *check_miss_rule_counter;
+       struct mlx5_flow_handle *check_miss_rule;
+       struct mlx5_fc *check_rule_counter;
+
+       u32 refcnt;
+};
+
+struct mlx5e_macsec_tx {
+       struct mlx5_flow_handle *crypto_mke_rule;
+       struct mlx5_flow_handle *check_rule;
+
+       struct ida tx_halloc;
+
+       struct mlx5e_macsec_tables tables;
+};
+
+struct mlx5e_macsec_rx_rule {
+       struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA];
+       struct mlx5_modify_hdr *meta_modhdr;
+};
+
+struct mlx5e_macsec_rx {
+       struct mlx5_flow_handle *check_rule[2];
+       struct mlx5_pkt_reformat *check_rule_pkt_reformat[2];
+
+       struct mlx5e_macsec_tables tables;
+};
+
+union mlx5e_macsec_rule {
+       struct mlx5e_macsec_tx_rule tx_rule;
+       struct mlx5e_macsec_rx_rule rx_rule;
+};
+
+struct mlx5e_macsec_fs {
+       struct mlx5_core_dev *mdev;
+       struct net_device *netdev;
+       struct mlx5e_macsec_tx *tx_fs;
+       struct mlx5e_macsec_rx *rx_fs;
+};
+
+static void macsec_fs_tx_destroy(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       struct mlx5e_macsec_tables *tx_tables;
+
+       tx_tables = &tx_fs->tables;
+
+       /* Tx check table */
+       if (tx_fs->check_rule) {
+               mlx5_del_flow_rules(tx_fs->check_rule);
+               tx_fs->check_rule = NULL;
+       }
+
+       if (tx_tables->check_miss_rule) {
+               mlx5_del_flow_rules(tx_tables->check_miss_rule);
+               tx_tables->check_miss_rule = NULL;
+       }
+
+       if (tx_tables->ft_check_group) {
+               mlx5_destroy_flow_group(tx_tables->ft_check_group);
+               tx_tables->ft_check_group = NULL;
+       }
+
+       if (tx_tables->ft_check) {
+               mlx5_destroy_flow_table(tx_tables->ft_check);
+               tx_tables->ft_check = NULL;
+       }
+
+       /* Tx crypto table */
+       if (tx_fs->crypto_mke_rule) {
+               mlx5_del_flow_rules(tx_fs->crypto_mke_rule);
+               tx_fs->crypto_mke_rule = NULL;
+       }
+
+       if (tx_tables->crypto_miss_rule) {
+               mlx5_del_flow_rules(tx_tables->crypto_miss_rule);
+               tx_tables->crypto_miss_rule = NULL;
+       }
+
+       mlx5e_destroy_flow_table(&tx_tables->ft_crypto);
+}
+
+static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
+       int ix = 0;
+       u32 *in;
+       int err;
+       u8 *mc;
+
+       ft->g = kcalloc(TX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
+       if (!ft->g)
+               return -ENOMEM;
+       in = kvzalloc(inlen, GFP_KERNEL);
+
+       if (!in) {
+               kfree(ft->g);
+               return -ENOMEM;
+       }
+
+       mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
+
+       /* Flow Group for MKE match */
+       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
+       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
+
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += TX_CRYPTO_TABLE_MKE_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       /* Flow Group for SA rules */
+       memset(in, 0, inlen);
+       memset(mc, 0, mclen);
+       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2);
+       MLX5_SET(fte_match_param, mc, misc_parameters_2.metadata_reg_a,
+                MLX5_ETH_WQE_FT_META_MACSEC_MASK);
+
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += TX_CRYPTO_TABLE_SA_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       /* Flow Group for l2 traps */
+       memset(in, 0, inlen);
+       memset(mc, 0, mclen);
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       kvfree(in);
+       return 0;
+
+err:
+       err = PTR_ERR(ft->g[ft->num_groups]);
+       ft->g[ft->num_groups] = NULL;
+       kvfree(in);
+
+       return err;
+}
+
+static struct mlx5_flow_table
+       *macsec_fs_auto_group_table_create(struct mlx5_flow_namespace *ns, int flags,
+                                          int level, int max_fte)
+{
+       struct mlx5_flow_table_attr ft_attr = {};
+       struct mlx5_flow_table *fdb = NULL;
+
+       /* reserve entry for the match all miss group and rule */
+       ft_attr.autogroup.num_reserved_entries = 1;
+       ft_attr.autogroup.max_num_groups = 1;
+       ft_attr.prio = 0;
+       ft_attr.flags = flags;
+       ft_attr.level = level;
+       ft_attr.max_fte = max_fte;
+
+       fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
+
+       return fdb;
+}
+
+static int macsec_fs_tx_create(struct mlx5e_macsec_fs *macsec_fs)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       struct net_device *netdev = macsec_fs->netdev;
+       struct mlx5_flow_table_attr ft_attr = {};
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_macsec_tables *tx_tables;
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5e_flow_table *ft_crypto;
+       struct mlx5_flow_table *flow_table;
+       struct mlx5_flow_group *flow_group;
+       struct mlx5_flow_namespace *ns;
+       struct mlx5_flow_handle *rule;
+       struct mlx5_flow_spec *spec;
+       u32 *flow_group_in;
+       int err;
+
+       ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
+       if (!ns)
+               return -ENOMEM;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+
+       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
+       if (!flow_group_in) {
+               err = -ENOMEM;
+               goto out_spec;
+       }
+
+       tx_tables = &tx_fs->tables;
+       ft_crypto = &tx_tables->ft_crypto;
+
+       /* Tx crypto table  */
+       ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
+       ft_attr.level = TX_CRYPTO_TABLE_LEVEL;
+       ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
+
+       flow_table = mlx5_create_flow_table(ns, &ft_attr);
+       if (IS_ERR(flow_table)) {
+               err = PTR_ERR(flow_table);
+               netdev_err(netdev, "Failed to create MACsec Tx crypto table err(%d)\n", err);
+               goto out_flow_group;
+       }
+       ft_crypto->t = flow_table;
+
+       /* Tx crypto table groups */
+       err = macsec_fs_tx_create_crypto_table_groups(ft_crypto);
+       if (err) {
+               netdev_err(netdev,
+                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
+                          err);
+               goto err;
+       }
+
+       /* Tx crypto table MKE rule - MKE packets shouldn't be offloaded */
+       spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_PAE);
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
+
+       rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to add MACsec TX MKE rule, err=%d\n", err);
+               goto err;
+       }
+       tx_fs->crypto_mke_rule = rule;
+
+       /* Tx crypto table Default miss rule */
+       memset(&flow_act, 0, sizeof(flow_act));
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
+       rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to add MACsec Tx table default miss rule %d\n", err);
+               goto err;
+       }
+       tx_tables->crypto_miss_rule = rule;
+
+       /* Tx check table */
+       flow_table = macsec_fs_auto_group_table_create(ns, 0, TX_CHECK_TABLE_LEVEL,
+                                                      TX_CHECK_TABLE_NUM_FTE);
+       if (IS_ERR(flow_table)) {
+               err = PTR_ERR(flow_table);
+               netdev_err(netdev, "fail to create MACsec TX check table, err(%d)\n", err);
+               goto err;
+       }
+       tx_tables->ft_check = flow_table;
+
+       /* Tx check table Default miss group/rule */
+       memset(flow_group_in, 0, inlen);
+       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
+       flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in);
+       if (IS_ERR(flow_group)) {
+               err = PTR_ERR(flow_group);
+               netdev_err(netdev,
+                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
+                          err);
+               goto err;
+       }
+       tx_tables->ft_check_group = flow_group;
+
+       /* Tx check table default drop rule */
+       memset(&dest, 0, sizeof(struct mlx5_flow_destination));
+       memset(&flow_act, 0, sizeof(flow_act));
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(tx_tables->check_miss_rule_counter);
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       rule = mlx5_add_flow_rules(tx_tables->ft_check,  NULL, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err);
+               goto err;
+       }
+       tx_tables->check_miss_rule = rule;
+
+       /* Tx check table rule */
+       memset(spec, 0, sizeof(struct mlx5_flow_spec));
+       memset(&dest, 0, sizeof(struct mlx5_flow_destination));
+       memset(&flow_act, 0, sizeof(flow_act));
+
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
+
+       flow_act.flags = FLOW_ACT_NO_APPEND;
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(tx_tables->check_rule_counter);
+       rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to add MACsec check rule, err=%d\n", err);
+               goto err;
+       }
+       tx_fs->check_rule = rule;
+
+       goto out_flow_group;
+
+err:
+       macsec_fs_tx_destroy(macsec_fs);
+out_flow_group:
+       kvfree(flow_group_in);
+out_spec:
+       kvfree(spec);
+       return err;
+}
+
+static int macsec_fs_tx_ft_get(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       struct mlx5e_macsec_tables *tx_tables;
+       int err = 0;
+
+       tx_tables = &tx_fs->tables;
+       if (tx_tables->refcnt)
+               goto out;
+
+       err = macsec_fs_tx_create(macsec_fs);
+       if (err)
+               return err;
+
+out:
+       tx_tables->refcnt++;
+       return err;
+}
+
+static void macsec_fs_tx_ft_put(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
+
+       if (--tx_tables->refcnt)
+               return;
+
+       macsec_fs_tx_destroy(macsec_fs);
+}
+
+static int macsec_fs_tx_setup_fte(struct mlx5e_macsec_fs *macsec_fs,
+                                 struct mlx5_flow_spec *spec,
+                                 struct mlx5_flow_act *flow_act,
+                                 u32 macsec_obj_id,
+                                 u32 *fs_id)
+{
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       int err = 0;
+       u32 id;
+
+       err = ida_alloc_range(&tx_fs->tx_halloc, 1,
+                             MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES,
+                             GFP_KERNEL);
+       if (err < 0)
+               return err;
+
+       id = err;
+       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
+
+       /* Metadata match */
+       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a,
+                MLX5_ETH_WQE_FT_META_MACSEC_MASK);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a,
+                MLX5_ETH_WQE_FT_META_MACSEC | id << 2);
+
+       *fs_id = id;
+       flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
+       flow_act->crypto.obj_id = macsec_obj_id;
+
+       mlx5_core_dbg(macsec_fs->mdev, "Tx fte: macsec obj_id %u, fs_id %u\n", macsec_obj_id, id);
+       return 0;
+}
+
+static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx,
+                                             char *reformatbf,
+                                             size_t *reformat_size)
+{
+       const struct macsec_secy *secy = ctx->secy;
+       bool sci_present = macsec_send_sci(secy);
+       struct mlx5_sectag_header sectag = {};
+       const struct macsec_tx_sc *tx_sc;
+
+       tx_sc = &secy->tx_sc;
+       sectag.ethertype = htons(ETH_P_MACSEC);
+
+       if (sci_present) {
+               sectag.tci_an |= MACSEC_TCI_SC;
+               memcpy(&sectag.sci, &secy->sci,
+                      sizeof(sectag.sci));
+       } else {
+               if (tx_sc->end_station)
+                       sectag.tci_an |= MACSEC_TCI_ES;
+               if (tx_sc->scb)
+                       sectag.tci_an |= MACSEC_TCI_SCB;
+       }
+
+       /* With GCM, C/E clear for !encrypt, both set for encrypt */
+       if (tx_sc->encrypt)
+               sectag.tci_an |= MACSEC_TCI_CONFID;
+       else if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
+               sectag.tci_an |= MACSEC_TCI_C;
+
+       sectag.tci_an |= tx_sc->encoding_sa;
+
+       *reformat_size = MLX5_MACSEC_TAG_LEN + (sci_present ? MACSEC_SCI_LEN : 0);
+
+       memcpy(reformatbf, &sectag, *reformat_size);
+}
+
+static void macsec_fs_tx_del_rule(struct mlx5e_macsec_fs *macsec_fs,
+                                 struct mlx5e_macsec_tx_rule *tx_rule)
+{
+       if (tx_rule->rule) {
+               mlx5_del_flow_rules(tx_rule->rule);
+               tx_rule->rule = NULL;
+       }
+
+       if (tx_rule->pkt_reformat) {
+               mlx5_packet_reformat_dealloc(macsec_fs->mdev, tx_rule->pkt_reformat);
+               tx_rule->pkt_reformat = NULL;
+       }
+
+       if (tx_rule->fs_id) {
+               ida_free(&macsec_fs->tx_fs->tx_halloc, tx_rule->fs_id);
+               tx_rule->fs_id = 0;
+       }
+
+       kfree(tx_rule);
+
+       macsec_fs_tx_ft_put(macsec_fs);
+}
+
+#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1
+
+static union mlx5e_macsec_rule *
+macsec_fs_tx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
+                     const struct macsec_context *macsec_ctx,
+                     struct mlx5_macsec_rule_attrs *attrs,
+                     u32 *sa_fs_id)
+{
+       char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN];
+       struct mlx5_pkt_reformat_params reformat_params = {};
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       struct net_device *netdev = macsec_fs->netdev;
+       union mlx5e_macsec_rule *macsec_rule = NULL;
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_macsec_tables *tx_tables;
+       struct mlx5e_macsec_tx_rule *tx_rule;
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_handle *rule;
+       struct mlx5_flow_spec *spec;
+       size_t reformat_size;
+       int err = 0;
+       u32 fs_id;
+
+       tx_tables = &tx_fs->tables;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return NULL;
+
+       err = macsec_fs_tx_ft_get(macsec_fs);
+       if (err)
+               goto out_spec;
+
+       macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
+       if (!macsec_rule) {
+               macsec_fs_tx_ft_put(macsec_fs);
+               goto out_spec;
+       }
+
+       tx_rule = &macsec_rule->tx_rule;
+
+       /* Tx crypto table crypto rule */
+       macsec_fs_tx_create_sectag_header(macsec_ctx, reformatbf, &reformat_size);
+
+       reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC;
+       reformat_params.size = reformat_size;
+       reformat_params.data = reformatbf;
+
+       if (is_vlan_dev(macsec_ctx->netdev))
+               reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES;
+
+       flow_act.pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev,
+                                                          &reformat_params,
+                                                          MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
+       if (IS_ERR(flow_act.pkt_reformat)) {
+               err = PTR_ERR(flow_act.pkt_reformat);
+               netdev_err(netdev, "Failed to allocate MACsec Tx reformat context err=%d\n",  err);
+               goto err;
+       }
+       tx_rule->pkt_reformat = flow_act.pkt_reformat;
+
+       err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, &fs_id);
+       if (err) {
+               netdev_err(netdev,
+                          "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n",
+                          err);
+               goto err;
+       }
+
+       tx_rule->fs_id = fs_id;
+       *sa_fs_id = fs_id;
+
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+                         MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
+                         MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+       dest.ft = tx_tables->ft_check;
+       rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to add MACsec TX crypto rule, err=%d\n", err);
+               goto err;
+       }
+       tx_rule->rule = rule;
+
+       goto out_spec;
+
+err:
+       macsec_fs_tx_del_rule(macsec_fs, tx_rule);
+       macsec_rule = NULL;
+out_spec:
+       kvfree(spec);
+
+       return macsec_rule;
+}
+
+static void macsec_fs_tx_cleanup(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tx *tx_fs = macsec_fs->tx_fs;
+       struct mlx5_core_dev *mdev = macsec_fs->mdev;
+       struct mlx5e_macsec_tables *tx_tables;
+
+       if (!tx_fs)
+               return;
+
+       tx_tables = &tx_fs->tables;
+       if (tx_tables->refcnt) {
+               netdev_err(macsec_fs->netdev,
+                          "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n",
+                          tx_tables->refcnt);
+               return;
+       }
+
+       ida_destroy(&tx_fs->tx_halloc);
+
+       if (tx_tables->check_miss_rule_counter) {
+               mlx5_fc_destroy(mdev, tx_tables->check_miss_rule_counter);
+               tx_tables->check_miss_rule_counter = NULL;
+       }
+
+       if (tx_tables->check_rule_counter) {
+               mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
+               tx_tables->check_rule_counter = NULL;
+       }
+
+       kfree(tx_fs);
+       macsec_fs->tx_fs = NULL;
+}
+
+static int macsec_fs_tx_init(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct net_device *netdev = macsec_fs->netdev;
+       struct mlx5_core_dev *mdev = macsec_fs->mdev;
+       struct mlx5e_macsec_tables *tx_tables;
+       struct mlx5e_macsec_tx *tx_fs;
+       struct mlx5_fc *flow_counter;
+       int err;
+
+       tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL);
+       if (!tx_fs)
+               return -ENOMEM;
+
+       tx_tables = &tx_fs->tables;
+
+       flow_counter = mlx5_fc_create(mdev, false);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               netdev_err(netdev,
+                          "Failed to create MACsec Tx encrypt flow counter, err(%d)\n",
+                          err);
+               goto err_encrypt_counter;
+       }
+       tx_tables->check_rule_counter = flow_counter;
+
+       flow_counter = mlx5_fc_create(mdev, false);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               netdev_err(netdev,
+                          "Failed to create MACsec Tx drop flow counter, err(%d)\n",
+                          err);
+               goto err_drop_counter;
+       }
+       tx_tables->check_miss_rule_counter = flow_counter;
+
+       ida_init(&tx_fs->tx_halloc);
+
+       macsec_fs->tx_fs = tx_fs;
+
+       return 0;
+
+err_drop_counter:
+       mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
+       tx_tables->check_rule_counter = NULL;
+
+err_encrypt_counter:
+       kfree(tx_fs);
+       macsec_fs->tx_fs = NULL;
+
+       return err;
+}
+
+static void macsec_fs_rx_destroy(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
+       struct mlx5e_macsec_tables *rx_tables;
+       int i;
+
+       /* Rx check table */
+       for (i = 1; i >= 0; --i) {
+               if (rx_fs->check_rule[i]) {
+                       mlx5_del_flow_rules(rx_fs->check_rule[i]);
+                       rx_fs->check_rule[i] = NULL;
+               }
+
+               if (rx_fs->check_rule_pkt_reformat[i]) {
+                       mlx5_packet_reformat_dealloc(macsec_fs->mdev,
+                                                    rx_fs->check_rule_pkt_reformat[i]);
+                       rx_fs->check_rule_pkt_reformat[i] = NULL;
+               }
+       }
+
+       rx_tables = &rx_fs->tables;
+
+       if (rx_tables->check_miss_rule) {
+               mlx5_del_flow_rules(rx_tables->check_miss_rule);
+               rx_tables->check_miss_rule = NULL;
+       }
+
+       if (rx_tables->ft_check_group) {
+               mlx5_destroy_flow_group(rx_tables->ft_check_group);
+               rx_tables->ft_check_group = NULL;
+       }
+
+       if (rx_tables->ft_check) {
+               mlx5_destroy_flow_table(rx_tables->ft_check);
+               rx_tables->ft_check = NULL;
+       }
+
+       /* Rx crypto table */
+       if (rx_tables->crypto_miss_rule) {
+               mlx5_del_flow_rules(rx_tables->crypto_miss_rule);
+               rx_tables->crypto_miss_rule = NULL;
+       }
+
+       mlx5e_destroy_flow_table(&rx_tables->ft_crypto);
+}
+
+static int macsec_fs_rx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
+       int ix = 0;
+       u32 *in;
+       int err;
+       u8 *mc;
+
+       ft->g = kcalloc(RX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
+       if (!ft->g)
+               return -ENOMEM;
+
+       in = kvzalloc(inlen, GFP_KERNEL);
+       if (!in) {
+               kfree(ft->g);
+               return -ENOMEM;
+       }
+
+       mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
+
+       /* Flow group for SA rule with SCI */
+       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
+                                               MLX5_MATCH_MISC_PARAMETERS_5);
+       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
+
+       MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
+                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK <<
+                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+       MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_2);
+       MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_3);
+
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       /* Flow group for SA rule without SCI */
+       memset(in, 0, inlen);
+       memset(mc, 0, mclen);
+       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
+                                               MLX5_MATCH_MISC_PARAMETERS_5);
+       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_47_16);
+       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_15_0);
+       MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
+
+       MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
+                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       /* Flow Group for l2 traps */
+       memset(in, 0, inlen);
+       memset(mc, 0, mclen);
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       kvfree(in);
+       return 0;
+
+err:
+       err = PTR_ERR(ft->g[ft->num_groups]);
+       ft->g[ft->num_groups] = NULL;
+       kvfree(in);
+
+       return err;
+}
+
+static int macsec_fs_rx_create_check_decap_rule(struct mlx5e_macsec_fs *macsec_fs,
+                                               struct mlx5_flow_destination *dest,
+                                               struct mlx5_flow_act *flow_act,
+                                               struct mlx5_flow_spec *spec,
+                                               int reformat_param_size)
+{
+       int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1;
+       u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI];
+       struct mlx5_pkt_reformat_params reformat_params = {};
+       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
+       struct net_device *netdev = macsec_fs->netdev;
+       struct mlx5e_macsec_tables *rx_tables;
+       struct mlx5_flow_handle *rule;
+       int err = 0;
+
+       rx_tables = &rx_fs->tables;
+
+       /* Rx check table decap 16B rule */
+       memset(dest, 0, sizeof(*dest));
+       memset(flow_act, 0, sizeof(*flow_act));
+       memset(spec, 0, sizeof(*spec));
+
+       reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC;
+       reformat_params.size = reformat_param_size;
+       reformat_params.data = mlx5_reformat_buf;
+       flow_act->pkt_reformat = mlx5_packet_reformat_alloc(macsec_fs->mdev,
+                                                           &reformat_params,
+                                                           MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
+       if (IS_ERR(flow_act->pkt_reformat)) {
+               err = PTR_ERR(flow_act->pkt_reformat);
+               netdev_err(netdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err);
+               return err;
+       }
+       rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat;
+
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
+       /* MACsec syndrome match */
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.macsec_syndrome);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.macsec_syndrome, 0);
+       /* ASO return reg syndrome match */
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
+
+       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
+       /* Sectag TCI SC present bit*/
+       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
+                MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+
+       if (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI)
+               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
+                        MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT <<
+                        MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+
+       flow_act->flags = FLOW_ACT_NO_APPEND;
+       flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO |
+                          MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
+                          MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter);
+       rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to add MACsec Rx check rule, err=%d\n", err);
+               return err;
+       }
+
+       rx_fs->check_rule[rule_index] = rule;
+
+       return 0;
+}
+
+static int macsec_fs_rx_create(struct mlx5e_macsec_fs *macsec_fs)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
+       struct net_device *netdev = macsec_fs->netdev;
+       struct mlx5_flow_table_attr ft_attr = {};
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_macsec_tables *rx_tables;
+       struct mlx5e_flow_table *ft_crypto;
+       struct mlx5_flow_table *flow_table;
+       struct mlx5_flow_group *flow_group;
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_namespace *ns;
+       struct mlx5_flow_handle *rule;
+       struct mlx5_flow_spec *spec;
+       u32 *flow_group_in;
+       int err;
+
+       ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
+       if (!ns)
+               return -ENOMEM;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+
+       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
+       if (!flow_group_in) {
+               err = -ENOMEM;
+               goto free_spec;
+       }
+
+       rx_tables = &rx_fs->tables;
+       ft_crypto = &rx_tables->ft_crypto;
+
+       /* Rx crypto table */
+       ft_attr.level = RX_CRYPTO_TABLE_LEVEL;
+       ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
+
+       flow_table = mlx5_create_flow_table(ns, &ft_attr);
+       if (IS_ERR(flow_table)) {
+               err = PTR_ERR(flow_table);
+               netdev_err(netdev, "Failed to create MACsec Rx crypto table err(%d)\n", err);
+               goto out_flow_group;
+       }
+       ft_crypto->t = flow_table;
+
+       /* Rx crypto table groups */
+       err = macsec_fs_rx_create_crypto_table_groups(ft_crypto);
+       if (err) {
+               netdev_err(netdev,
+                          "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
+                          err);
+               goto err;
+       }
+
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
+       rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev,
+                          "Failed to add MACsec Rx crypto table default miss rule %d\n",
+                          err);
+               goto err;
+       }
+       rx_tables->crypto_miss_rule = rule;
+
+       /* Rx check table */
+       flow_table = macsec_fs_auto_group_table_create(ns,
+                                                      MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT,
+                                                      RX_CHECK_TABLE_LEVEL,
+                                                      RX_CHECK_TABLE_NUM_FTE);
+       if (IS_ERR(flow_table)) {
+               err = PTR_ERR(flow_table);
+               netdev_err(netdev, "fail to create MACsec RX check table, err(%d)\n", err);
+               goto err;
+       }
+       rx_tables->ft_check = flow_table;
+
+       /* Rx check table Default miss group/rule */
+       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
+       flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in);
+       if (IS_ERR(flow_group)) {
+               err = PTR_ERR(flow_group);
+               netdev_err(netdev,
+                          "Failed to create default flow group for MACsec Rx check table err(%d)\n",
+                          err);
+               goto err;
+       }
+       rx_tables->ft_check_group = flow_group;
+
+       /* Rx check table default drop rule */
+       memset(&flow_act, 0, sizeof(flow_act));
+
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dest.counter_id = mlx5_fc_id(rx_tables->check_miss_rule_counter);
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       rule = mlx5_add_flow_rules(rx_tables->ft_check,  NULL, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err);
+               goto err;
+       }
+       rx_tables->check_miss_rule = rule;
+
+       /* Rx check table decap rules */
+       err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
+                                                  MLX5_SECTAG_HEADER_SIZE_WITH_SCI);
+       if (err)
+               goto err;
+
+       err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
+                                                  MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI);
+       if (err)
+               goto err;
+
+       goto out_flow_group;
+
+err:
+       macsec_fs_rx_destroy(macsec_fs);
+out_flow_group:
+       kvfree(flow_group_in);
+free_spec:
+       kvfree(spec);
+       return err;
+}
+
+static int macsec_fs_rx_ft_get(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
+       int err = 0;
+
+       if (rx_tables->refcnt)
+               goto out;
+
+       err = macsec_fs_rx_create(macsec_fs);
+       if (err)
+               return err;
+
+out:
+       rx_tables->refcnt++;
+       return err;
+}
+
+static void macsec_fs_rx_ft_put(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
+
+       if (--rx_tables->refcnt)
+               return;
+
+       macsec_fs_rx_destroy(macsec_fs);
+}
+
+static void macsec_fs_rx_del_rule(struct mlx5e_macsec_fs *macsec_fs,
+                                 struct mlx5e_macsec_rx_rule *rx_rule)
+{
+       int i;
+
+       for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) {
+               if (rx_rule->rule[i]) {
+                       mlx5_del_flow_rules(rx_rule->rule[i]);
+                       rx_rule->rule[i] = NULL;
+               }
+       }
+
+       if (rx_rule->meta_modhdr) {
+               mlx5_modify_header_dealloc(macsec_fs->mdev, rx_rule->meta_modhdr);
+               rx_rule->meta_modhdr = NULL;
+       }
+
+       kfree(rx_rule);
+
+       macsec_fs_rx_ft_put(macsec_fs);
+}
+
+static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec,
+                                  struct mlx5_flow_act *flow_act,
+                                  struct mlx5_macsec_rule_attrs *attrs,
+                                  bool sci_present)
+{
+       u8 tci_an = (sci_present << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) | attrs->assoc_num;
+       struct mlx5_flow_act_crypto_params *crypto_params = &flow_act->crypto;
+       __be32 *sci_p = (__be32 *)(&attrs->sci);
+
+       spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+
+       /* MACsec ethertype */
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_MACSEC);
+
+       spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
+
+       /* Sectag AN + TCI SC present bit*/
+       MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
+                MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
+                tci_an << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
+
+       if (sci_present) {
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                                misc_parameters_5.macsec_tag_2);
+               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_2,
+                        be32_to_cpu(sci_p[0]));
+
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+                                misc_parameters_5.macsec_tag_3);
+               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_3,
+                        be32_to_cpu(sci_p[1]));
+       } else {
+               /* When SCI isn't present in the Sectag, need to match the source */
+               /* MAC address only if the SCI contains the default MACsec PORT   */
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
+               memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers.smac_47_16),
+                      sci_p, ETH_ALEN);
+       }
+
+       crypto_params->type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
+       crypto_params->obj_id = attrs->macsec_obj_id;
+}
+
+static union mlx5e_macsec_rule *
+macsec_fs_rx_add_rule(struct mlx5e_macsec_fs *macsec_fs,
+                     struct mlx5_macsec_rule_attrs *attrs,
+                     u32 fs_id)
+{
+       u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
+       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
+       struct net_device *netdev = macsec_fs->netdev;
+       union mlx5e_macsec_rule *macsec_rule = NULL;
+       struct mlx5_modify_hdr *modify_hdr = NULL;
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_macsec_tables *rx_tables;
+       struct mlx5e_macsec_rx_rule *rx_rule;
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5e_flow_table *ft_crypto;
+       struct mlx5_flow_handle *rule;
+       struct mlx5_flow_spec *spec;
+       int err = 0;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return NULL;
+
+       err = macsec_fs_rx_ft_get(macsec_fs);
+       if (err)
+               goto out_spec;
+
+       macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
+       if (!macsec_rule) {
+               macsec_fs_rx_ft_put(macsec_fs);
+               goto out_spec;
+       }
+
+       rx_rule = &macsec_rule->rx_rule;
+       rx_tables = &rx_fs->tables;
+       ft_crypto = &rx_tables->ft_crypto;
+
+       /* Set bit[31 - 30] macsec marker - 0x01 */
+       /* Set bit[15-0] fs 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_B);
+       MLX5_SET(set_action_in, action, data, MLX5_MACSEC_RX_METADAT_HANDLE(fs_id) | BIT(30));
+       MLX5_SET(set_action_in, action, offset, 0);
+       MLX5_SET(set_action_in, action, length, 32);
+
+       modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC,
+                                             1, action);
+       if (IS_ERR(modify_hdr)) {
+               err = PTR_ERR(modify_hdr);
+               netdev_err(netdev, "fail to alloc MACsec set modify_header_id err=%d\n", err);
+               modify_hdr = NULL;
+               goto err;
+       }
+       rx_rule->meta_modhdr = modify_hdr;
+
+       /* Rx crypto table with SCI rule */
+       macsec_fs_rx_setup_fte(spec, &flow_act, attrs, true);
+
+       flow_act.modify_hdr = modify_hdr;
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+                         MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
+                         MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
+
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+       dest.ft = rx_tables->ft_check;
+       rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
+       if (IS_ERR(rule)) {
+               err = PTR_ERR(rule);
+               netdev_err(netdev,
+                          "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n",
+                          err);
+               goto err;
+       }
+       rx_rule->rule[0] = rule;
+
+       /* Rx crypto table without SCI rule */
+       if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) {
+               memset(spec, 0, sizeof(struct mlx5_flow_spec));
+               memset(&dest, 0, sizeof(struct mlx5_flow_destination));
+               memset(&flow_act, 0, sizeof(flow_act));
+
+               macsec_fs_rx_setup_fte(spec, &flow_act, attrs, false);
+
+               flow_act.modify_hdr = modify_hdr;
+               flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+                                 MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
+                                 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
+
+               dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+               dest.ft = rx_tables->ft_check;
+               rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
+               if (IS_ERR(rule)) {
+                       err = PTR_ERR(rule);
+                       netdev_err(netdev,
+                                  "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n",
+                                  err);
+                       goto err;
+               }
+               rx_rule->rule[1] = rule;
+       }
+
+       kvfree(spec);
+       return macsec_rule;
+
+err:
+       macsec_fs_rx_del_rule(macsec_fs, rx_rule);
+       macsec_rule = NULL;
+out_spec:
+       kvfree(spec);
+       return macsec_rule;
+}
+
+static int macsec_fs_rx_init(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct net_device *netdev = macsec_fs->netdev;
+       struct mlx5_core_dev *mdev = macsec_fs->mdev;
+       struct mlx5e_macsec_tables *rx_tables;
+       struct mlx5e_macsec_rx *rx_fs;
+       struct mlx5_fc *flow_counter;
+       int err;
+
+       rx_fs = kzalloc(sizeof(*rx_fs), GFP_KERNEL);
+       if (!rx_fs)
+               return -ENOMEM;
+
+       flow_counter = mlx5_fc_create(mdev, false);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               netdev_err(netdev,
+                          "Failed to create MACsec Rx encrypt flow counter, err(%d)\n",
+                          err);
+               goto err_encrypt_counter;
+       }
+
+       rx_tables = &rx_fs->tables;
+       rx_tables->check_rule_counter = flow_counter;
+
+       flow_counter = mlx5_fc_create(mdev, false);
+       if (IS_ERR(flow_counter)) {
+               err = PTR_ERR(flow_counter);
+               netdev_err(netdev,
+                          "Failed to create MACsec Rx drop flow counter, err(%d)\n",
+                          err);
+               goto err_drop_counter;
+       }
+       rx_tables->check_miss_rule_counter = flow_counter;
+
+       macsec_fs->rx_fs = rx_fs;
+
+       return 0;
+
+err_drop_counter:
+       mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
+       rx_tables->check_rule_counter = NULL;
+
+err_encrypt_counter:
+       kfree(rx_fs);
+       macsec_fs->rx_fs = NULL;
+
+       return err;
+}
+
+static void macsec_fs_rx_cleanup(struct mlx5e_macsec_fs *macsec_fs)
+{
+       struct mlx5e_macsec_rx *rx_fs = macsec_fs->rx_fs;
+       struct mlx5_core_dev *mdev = macsec_fs->mdev;
+       struct mlx5e_macsec_tables *rx_tables;
+
+       if (!rx_fs)
+               return;
+
+       rx_tables = &rx_fs->tables;
+
+       if (rx_tables->refcnt) {
+               netdev_err(macsec_fs->netdev,
+                          "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n",
+                          rx_tables->refcnt);
+               return;
+       }
+
+       if (rx_tables->check_miss_rule_counter) {
+               mlx5_fc_destroy(mdev, rx_tables->check_miss_rule_counter);
+               rx_tables->check_miss_rule_counter = NULL;
+       }
+
+       if (rx_tables->check_rule_counter) {
+               mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
+               rx_tables->check_rule_counter = NULL;
+       }
+
+       kfree(rx_fs);
+       macsec_fs->rx_fs = NULL;
+}
+
+void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats)
+{
+       struct mlx5e_macsec_stats *stats = (struct mlx5e_macsec_stats *)macsec_stats;
+       struct mlx5e_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
+       struct mlx5e_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
+       struct mlx5_core_dev *mdev = macsec_fs->mdev;
+
+       if (tx_tables->check_rule_counter)
+               mlx5_fc_query(mdev, tx_tables->check_rule_counter,
+                             &stats->macsec_tx_pkts, &stats->macsec_tx_bytes);
+
+       if (tx_tables->check_miss_rule_counter)
+               mlx5_fc_query(mdev, tx_tables->check_miss_rule_counter,
+                             &stats->macsec_tx_pkts_drop, &stats->macsec_tx_bytes_drop);
+
+       if (rx_tables->check_rule_counter)
+               mlx5_fc_query(mdev, rx_tables->check_rule_counter,
+                             &stats->macsec_rx_pkts, &stats->macsec_rx_bytes);
+
+       if (rx_tables->check_miss_rule_counter)
+               mlx5_fc_query(mdev, rx_tables->check_miss_rule_counter,
+                             &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop);
+}
+
+union mlx5e_macsec_rule *
+mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs,
+                        const struct macsec_context *macsec_ctx,
+                        struct mlx5_macsec_rule_attrs *attrs,
+                        u32 *sa_fs_id)
+{
+       return (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
+               macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, sa_fs_id) :
+               macsec_fs_rx_add_rule(macsec_fs, attrs, *sa_fs_id);
+}
+
+void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs,
+                             union mlx5e_macsec_rule *macsec_rule,
+                             int action)
+{
+       (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
+               macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule) :
+               macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule);
+}
+
+void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs)
+{
+       macsec_fs_rx_cleanup(macsec_fs);
+       macsec_fs_tx_cleanup(macsec_fs);
+       kfree(macsec_fs);
+}
+
+struct mlx5e_macsec_fs *
+mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev,
+                    struct net_device *netdev)
+{
+       struct mlx5e_macsec_fs *macsec_fs;
+       int err;
+
+       macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL);
+       if (!macsec_fs)
+               return NULL;
+
+       macsec_fs->mdev = mdev;
+       macsec_fs->netdev = netdev;
+
+       err = macsec_fs_tx_init(macsec_fs);
+       if (err) {
+               netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
+               goto err;
+       }
+
+       err = macsec_fs_rx_init(macsec_fs);
+       if (err) {
+               netdev_err(netdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
+               goto tx_cleanup;
+       }
+
+       return macsec_fs;
+
+tx_cleanup:
+       macsec_fs_tx_cleanup(macsec_fs);
+err:
+       kfree(macsec_fs);
+       return NULL;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.h
new file mode 100644 (file)
index 0000000..b282c08
--- /dev/null
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef __MLX5_MACSEC_STEERING_H__
+#define __MLX5_MACSEC_STEERING_H__
+
+#ifdef CONFIG_MLX5_MACSEC
+
+/* Bit31 - 30: MACsec marker, Bit15-0: MACsec id */
+#define MLX5_MACEC_RX_FS_ID_MAX USHRT_MAX /* Must be power of two */
+#define MLX5_MACSEC_RX_FS_ID_MASK MLX5_MACEC_RX_FS_ID_MAX
+#define MLX5_MACSEC_METADATA_MARKER(metadata)  ((((metadata) >> 30) & 0x3)  == 0x1)
+#define MLX5_MACSEC_RX_METADAT_HANDLE(metadata)  ((metadata) & MLX5_MACSEC_RX_FS_ID_MASK)
+
+#define MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES 16
+
+struct mlx5e_macsec_fs;
+union mlx5e_macsec_rule;
+
+struct mlx5_macsec_rule_attrs {
+       sci_t sci;
+       u32 macsec_obj_id;
+       u8 assoc_num;
+       int action;
+};
+
+struct mlx5e_macsec_stats {
+       u64 macsec_rx_pkts;
+       u64 macsec_rx_bytes;
+       u64 macsec_rx_pkts_drop;
+       u64 macsec_rx_bytes_drop;
+       u64 macsec_tx_pkts;
+       u64 macsec_tx_bytes;
+       u64 macsec_tx_pkts_drop;
+       u64 macsec_tx_bytes_drop;
+};
+
+enum mlx5_macsec_action {
+       MLX5_ACCEL_MACSEC_ACTION_ENCRYPT,
+       MLX5_ACCEL_MACSEC_ACTION_DECRYPT,
+};
+
+void mlx5e_macsec_fs_cleanup(struct mlx5e_macsec_fs *macsec_fs);
+
+struct mlx5e_macsec_fs *
+mlx5e_macsec_fs_init(struct mlx5_core_dev *mdev, struct net_device *netdev);
+
+union mlx5e_macsec_rule *
+mlx5e_macsec_fs_add_rule(struct mlx5e_macsec_fs *macsec_fs,
+                        const struct macsec_context *ctx,
+                        struct mlx5_macsec_rule_attrs *attrs,
+                        u32 *sa_fs_id);
+
+void mlx5e_macsec_fs_del_rule(struct mlx5e_macsec_fs *macsec_fs,
+                             union mlx5e_macsec_rule *macsec_rule,
+                             int action);
+
+void mlx5e_macsec_fs_get_stats_fill(struct mlx5e_macsec_fs *macsec_fs, void *macsec_stats);
+
+#endif
+
+#endif /* __MLX5_MACSEC_STEERING_H__ */