File Index
Files and directories
Sign in
FILE

macsec_fs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c C
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
   3
   4#include <net/macsec.h>
   5#include <linux/mlx5/qp.h>
   6#include <linux/if_vlan.h>
   7#include <linux/mlx5/fs_helpers.h>
   8#include <linux/mlx5/macsec.h>
   9#include "fs_core.h"
  10#include "lib/macsec_fs.h"
  11#include "mlx5_core.h"
  12
  13/* MACsec TX flow steering */
  14#define CRYPTO_NUM_MAXSEC_FTE BIT(15)
  15#define CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE 1
  16
  17#define TX_CRYPTO_TABLE_LEVEL 0
  18#define TX_CRYPTO_TABLE_NUM_GROUPS 3
  19#define TX_CRYPTO_TABLE_MKE_GROUP_SIZE 1
  20#define TX_CRYPTO_TABLE_SA_GROUP_SIZE \
  21	(CRYPTO_NUM_MAXSEC_FTE - (TX_CRYPTO_TABLE_MKE_GROUP_SIZE + \
  22				  CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE))
  23#define TX_CHECK_TABLE_LEVEL 1
  24#define TX_CHECK_TABLE_NUM_FTE 2
  25#define RX_CRYPTO_TABLE_LEVEL 0
  26#define RX_CHECK_TABLE_LEVEL 1
  27#define RX_ROCE_TABLE_LEVEL 2
  28#define RX_CHECK_TABLE_NUM_FTE 3
  29#define RX_ROCE_TABLE_NUM_FTE 2
  30#define RX_CRYPTO_TABLE_NUM_GROUPS 3
  31#define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \
  32	((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2)
  33#define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \
  34	(CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE)
  35#define RX_NUM_OF_RULES_PER_SA 2
  36
  37#define RDMA_RX_ROCE_IP_TABLE_LEVEL 0
  38#define RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL 1
  39
  40#define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */
  41#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23
  42#define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET 0x8
  43#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET 0x5
  44#define MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT (0x1 << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET)
  45#define MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI 0x8
  46#define MLX5_SECTAG_HEADER_SIZE_WITH_SCI (MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI + MACSEC_SCI_LEN)
  47
  48/* MACsec fs_id handling for steering */
  49#define macsec_fs_set_rx_fs_id(fs_id) ((fs_id) | BIT(30))
  50
  51struct mlx5_sectag_header {
  52	__be16 ethertype;
  53	u8 tci_an;
  54	u8 sl;
  55	u32 pn;
  56	u8 sci[MACSEC_SCI_LEN]; /* optional */
  57}  __packed;
  58
  59struct mlx5_roce_macsec_tx_rule {
  60	u32 fs_id;
  61	u16 gid_idx;
  62	struct list_head entry;
  63	struct mlx5_flow_handle *rule;
  64	struct mlx5_modify_hdr *meta_modhdr;
  65};
  66
  67struct mlx5_macsec_tx_rule {
  68	struct mlx5_flow_handle *rule;
  69	struct mlx5_pkt_reformat *pkt_reformat;
  70	u32 fs_id;
  71};
  72
  73struct mlx5_macsec_flow_table {
  74	int num_groups;
  75	struct mlx5_flow_table *t;
  76	struct mlx5_flow_group **g;
  77};
  78
  79struct mlx5_macsec_tables {
  80	struct mlx5_macsec_flow_table ft_crypto;
  81	struct mlx5_flow_handle *crypto_miss_rule;
  82
  83	struct mlx5_flow_table *ft_check;
  84	struct mlx5_flow_group  *ft_check_group;
  85	struct mlx5_fc *check_miss_rule_counter;
  86	struct mlx5_flow_handle *check_miss_rule;
  87	struct mlx5_fc *check_rule_counter;
  88
  89	u32 refcnt;
  90};
  91
  92struct mlx5_fs_id {
  93	u32 id;
  94	refcount_t refcnt;
  95	sci_t sci;
  96	struct rhash_head hash;
  97};
  98
  99struct mlx5_macsec_device {
 100	struct list_head macsec_devices_list_entry;
 101	void *macdev;
 102	struct xarray tx_id_xa;
 103	struct xarray rx_id_xa;
 104};
 105
 106struct mlx5_macsec_tx {
 107	struct mlx5_flow_handle *crypto_mke_rule;
 108	struct mlx5_flow_handle *check_rule;
 109
 110	struct ida tx_halloc;
 111
 112	struct mlx5_macsec_tables tables;
 113
 114	struct mlx5_flow_table *ft_rdma_tx;
 115};
 116
 117struct mlx5_roce_macsec_rx_rule {
 118	u32 fs_id;
 119	u16 gid_idx;
 120	struct mlx5_flow_handle *op;
 121	struct mlx5_flow_handle *ip;
 122	struct list_head entry;
 123};
 124
 125struct mlx5_macsec_rx_rule {
 126	struct mlx5_flow_handle *rule[RX_NUM_OF_RULES_PER_SA];
 127	struct mlx5_modify_hdr *meta_modhdr;
 128};
 129
 130struct mlx5_macsec_miss {
 131	struct mlx5_flow_group *g;
 132	struct mlx5_flow_handle *rule;
 133};
 134
 135struct mlx5_macsec_rx_roce {
 136	/* Flow table/rules in NIC domain, to check if it's a RoCE packet */
 137	struct mlx5_flow_group *g;
 138	struct mlx5_flow_table *ft;
 139	struct mlx5_flow_handle *rule;
 140	struct mlx5_modify_hdr *copy_modify_hdr;
 141	struct mlx5_macsec_miss nic_miss;
 142
 143	/* Flow table/rule in RDMA domain, to check dgid */
 144	struct mlx5_flow_table *ft_ip_check;
 145	struct mlx5_flow_table *ft_macsec_op_check;
 146	struct mlx5_macsec_miss miss;
 147};
 148
 149struct mlx5_macsec_rx {
 150	struct mlx5_flow_handle *check_rule[2];
 151	struct mlx5_pkt_reformat *check_rule_pkt_reformat[2];
 152
 153	struct mlx5_macsec_tables tables;
 154	struct mlx5_macsec_rx_roce roce;
 155};
 156
 157union mlx5_macsec_rule {
 158	struct mlx5_macsec_tx_rule tx_rule;
 159	struct mlx5_macsec_rx_rule rx_rule;
 160};
 161
 162static const struct rhashtable_params rhash_sci = {
 163	.key_len = sizeof_field(struct mlx5_fs_id, sci),
 164	.key_offset = offsetof(struct mlx5_fs_id, sci),
 165	.head_offset = offsetof(struct mlx5_fs_id, hash),
 166	.automatic_shrinking = true,
 167	.min_size = 1,
 168};
 169
 170static const struct rhashtable_params rhash_fs_id = {
 171	.key_len = sizeof_field(struct mlx5_fs_id, id),
 172	.key_offset = offsetof(struct mlx5_fs_id, id),
 173	.head_offset = offsetof(struct mlx5_fs_id, hash),
 174	.automatic_shrinking = true,
 175	.min_size = 1,
 176};
 177
 178struct mlx5_macsec_fs {
 179	struct mlx5_core_dev *mdev;
 180	struct mlx5_macsec_tx *tx_fs;
 181	struct mlx5_macsec_rx *rx_fs;
 182
 183	/* Stats manage */
 184	struct mlx5_macsec_stats stats;
 185
 186	/* Tx sci -> fs id mapping handling */
 187	struct rhashtable sci_hash;      /* sci -> mlx5_fs_id */
 188
 189	/* RX fs_id -> mlx5_fs_id mapping handling */
 190	struct rhashtable fs_id_hash;      /* fs_id -> mlx5_fs_id */
 191
 192	/* TX & RX fs_id lists per macsec device */
 193	struct list_head macsec_devices_list;
 194};
 195
 196static void macsec_fs_destroy_groups(struct mlx5_macsec_flow_table *ft)
 197{
 198	int i;
 199
 200	for (i = ft->num_groups - 1; i >= 0; i--) {
 201		if (!IS_ERR_OR_NULL(ft->g[i]))
 202			mlx5_destroy_flow_group(ft->g[i]);
 203		ft->g[i] = NULL;
 204	}
 205	ft->num_groups = 0;
 206}
 207
 208static void macsec_fs_destroy_flow_table(struct mlx5_macsec_flow_table *ft)
 209{
 210	macsec_fs_destroy_groups(ft);
 211	kfree(ft->g);
 212	mlx5_destroy_flow_table(ft->t);
 213	ft->t = NULL;
 214}
 215
 216static void macsec_fs_tx_destroy(struct mlx5_macsec_fs *macsec_fs)
 217{
 218	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 219	struct mlx5_macsec_tables *tx_tables;
 220
 221	if (mlx5_is_macsec_roce_supported(macsec_fs->mdev))
 222		mlx5_destroy_flow_table(tx_fs->ft_rdma_tx);
 223
 224	tx_tables = &tx_fs->tables;
 225
 226	/* Tx check table */
 227	if (tx_fs->check_rule) {
 228		mlx5_del_flow_rules(tx_fs->check_rule);
 229		tx_fs->check_rule = NULL;
 230	}
 231
 232	if (tx_tables->check_miss_rule) {
 233		mlx5_del_flow_rules(tx_tables->check_miss_rule);
 234		tx_tables->check_miss_rule = NULL;
 235	}
 236
 237	if (tx_tables->ft_check_group) {
 238		mlx5_destroy_flow_group(tx_tables->ft_check_group);
 239		tx_tables->ft_check_group = NULL;
 240	}
 241
 242	if (tx_tables->ft_check) {
 243		mlx5_destroy_flow_table(tx_tables->ft_check);
 244		tx_tables->ft_check = NULL;
 245	}
 246
 247	/* Tx crypto table */
 248	if (tx_fs->crypto_mke_rule) {
 249		mlx5_del_flow_rules(tx_fs->crypto_mke_rule);
 250		tx_fs->crypto_mke_rule = NULL;
 251	}
 252
 253	if (tx_tables->crypto_miss_rule) {
 254		mlx5_del_flow_rules(tx_tables->crypto_miss_rule);
 255		tx_tables->crypto_miss_rule = NULL;
 256	}
 257
 258	macsec_fs_destroy_flow_table(&tx_tables->ft_crypto);
 259}
 260
 261static int macsec_fs_tx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft)
 262{
 263	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 264	int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
 265	int ix = 0;
 266	u32 *in;
 267	int err;
 268	u8 *mc;
 269
 270	ft->g = kcalloc(TX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
 271	if (!ft->g)
 272		return -ENOMEM;
 273	in = kvzalloc(inlen, GFP_KERNEL);
 274
 275	if (!in) {
 276		kfree(ft->g);
 277		ft->g = NULL;
 278		return -ENOMEM;
 279	}
 280
 281	mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
 282
 283	/* Flow Group for MKE match */
 284	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
 285	MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
 286
 287	MLX5_SET_CFG(in, start_flow_index, ix);
 288	ix += TX_CRYPTO_TABLE_MKE_GROUP_SIZE;
 289	MLX5_SET_CFG(in, end_flow_index, ix - 1);
 290	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
 291	if (IS_ERR(ft->g[ft->num_groups]))
 292		goto err;
 293	ft->num_groups++;
 294
 295	/* Flow Group for SA rules */
 296	memset(in, 0, inlen);
 297	memset(mc, 0, mclen);
 298	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2);
 299	MLX5_SET(fte_match_param, mc, misc_parameters_2.metadata_reg_a,
 300		 MLX5_ETH_WQE_FT_META_MACSEC_MASK);
 301
 302	MLX5_SET_CFG(in, start_flow_index, ix);
 303	ix += TX_CRYPTO_TABLE_SA_GROUP_SIZE;
 304	MLX5_SET_CFG(in, end_flow_index, ix - 1);
 305	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
 306	if (IS_ERR(ft->g[ft->num_groups]))
 307		goto err;
 308	ft->num_groups++;
 309
 310	/* Flow Group for l2 traps */
 311	memset(in, 0, inlen);
 312	memset(mc, 0, mclen);
 313	MLX5_SET_CFG(in, start_flow_index, ix);
 314	ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
 315	MLX5_SET_CFG(in, end_flow_index, ix - 1);
 316	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
 317	if (IS_ERR(ft->g[ft->num_groups]))
 318		goto err;
 319	ft->num_groups++;
 320
 321	kvfree(in);
 322	return 0;
 323
 324err:
 325	err = PTR_ERR(ft->g[ft->num_groups]);
 326	ft->g[ft->num_groups] = NULL;
 327	kvfree(in);
 328
 329	return err;
 330}
 331
 332static struct mlx5_flow_table
 333	*macsec_fs_auto_group_table_create(struct mlx5_flow_namespace *ns, int flags,
 334					   int level, int max_fte)
 335{
 336	struct mlx5_flow_table_attr ft_attr = {};
 337	struct mlx5_flow_table *fdb = NULL;
 338
 339	/* reserve entry for the match all miss group and rule */
 340	ft_attr.autogroup.num_reserved_entries = 1;
 341	ft_attr.autogroup.max_num_groups = 1;
 342	ft_attr.prio = 0;
 343	ft_attr.flags = flags;
 344	ft_attr.level = level;
 345	ft_attr.max_fte = max_fte;
 346
 347	fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
 348
 349	return fdb;
 350}
 351
 352enum {
 353	RDMA_TX_MACSEC_LEVEL = 0,
 354};
 355
 356static int macsec_fs_tx_roce_create(struct mlx5_macsec_fs *macsec_fs)
 357{
 358	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 359	struct mlx5_core_dev *mdev = macsec_fs->mdev;
 360	struct mlx5_flow_namespace *ns;
 361	struct mlx5_flow_table *ft;
 362	int err;
 363
 364	if (!mlx5_is_macsec_roce_supported(mdev)) {
 365		mlx5_core_dbg(mdev, "Failed to init RoCE MACsec, capabilities not supported\n");
 366		return 0;
 367	}
 368
 369	ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC);
 370	if (!ns)
 371		return -ENOMEM;
 372
 373	/* Tx RoCE crypto table  */
 374	ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_TX_MACSEC_LEVEL, CRYPTO_NUM_MAXSEC_FTE);
 375	if (IS_ERR(ft)) {
 376		err = PTR_ERR(ft);
 377		mlx5_core_err(mdev, "Failed to create MACsec RoCE Tx crypto table err(%d)\n", err);
 378		return err;
 379	}
 380	tx_fs->ft_rdma_tx = ft;
 381
 382	return 0;
 383}
 384
 385static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs)
 386{
 387	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 388	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 389	struct mlx5_core_dev *mdev = macsec_fs->mdev;
 390	struct mlx5_flow_table_attr ft_attr = {};
 391	struct mlx5_flow_destination dest = {};
 392	struct mlx5_macsec_tables *tx_tables;
 393	struct mlx5_flow_act flow_act = {};
 394	struct mlx5_macsec_flow_table *ft_crypto;
 395	struct mlx5_flow_table *flow_table;
 396	struct mlx5_flow_group *flow_group;
 397	struct mlx5_flow_namespace *ns;
 398	struct mlx5_flow_handle *rule;
 399	struct mlx5_flow_spec *spec;
 400	u32 *flow_group_in;
 401	int err;
 402
 403	ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
 404	if (!ns)
 405		return -ENOMEM;
 406
 407	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 408	if (!spec)
 409		return -ENOMEM;
 410
 411	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
 412	if (!flow_group_in) {
 413		err = -ENOMEM;
 414		goto out_spec;
 415	}
 416
 417	tx_tables = &tx_fs->tables;
 418	ft_crypto = &tx_tables->ft_crypto;
 419
 420	/* Tx crypto table  */
 421	ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
 422	ft_attr.level = TX_CRYPTO_TABLE_LEVEL;
 423	ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
 424
 425	flow_table = mlx5_create_flow_table(ns, &ft_attr);
 426	if (IS_ERR(flow_table)) {
 427		err = PTR_ERR(flow_table);
 428		mlx5_core_err(mdev, "Failed to create MACsec Tx crypto table err(%d)\n", err);
 429		goto out_flow_group;
 430	}
 431	ft_crypto->t = flow_table;
 432
 433	/* Tx crypto table groups */
 434	err = macsec_fs_tx_create_crypto_table_groups(ft_crypto);
 435	if (err) {
 436		mlx5_core_err(mdev,
 437			      "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
 438			      err);
 439		goto err;
 440	}
 441
 442	/* Tx crypto table MKE rule - MKE packets shouldn't be offloaded */
 443	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 444
 445	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
 446	MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_PAE);
 447	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
 448
 449	rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, NULL, 0);
 450	if (IS_ERR(rule)) {
 451		err = PTR_ERR(rule);
 452		mlx5_core_err(mdev, "Failed to add MACsec TX MKE rule, err=%d\n", err);
 453		goto err;
 454	}
 455	tx_fs->crypto_mke_rule = rule;
 456
 457	/* Tx crypto table Default miss rule */
 458	memset(&flow_act, 0, sizeof(flow_act));
 459	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
 460	rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
 461	if (IS_ERR(rule)) {
 462		err = PTR_ERR(rule);
 463		mlx5_core_err(mdev, "Failed to add MACsec Tx table default miss rule %d\n", err);
 464		goto err;
 465	}
 466	tx_tables->crypto_miss_rule = rule;
 467
 468	/* Tx check table */
 469	flow_table = macsec_fs_auto_group_table_create(ns, 0, TX_CHECK_TABLE_LEVEL,
 470						       TX_CHECK_TABLE_NUM_FTE);
 471	if (IS_ERR(flow_table)) {
 472		err = PTR_ERR(flow_table);
 473		mlx5_core_err(mdev, "Fail to create MACsec TX check table, err(%d)\n", err);
 474		goto err;
 475	}
 476	tx_tables->ft_check = flow_table;
 477
 478	/* Tx check table Default miss group/rule */
 479	memset(flow_group_in, 0, inlen);
 480	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
 481	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
 482	flow_group = mlx5_create_flow_group(tx_tables->ft_check, flow_group_in);
 483	if (IS_ERR(flow_group)) {
 484		err = PTR_ERR(flow_group);
 485		mlx5_core_err(mdev,
 486			      "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
 487			      err);
 488		goto err;
 489	}
 490	tx_tables->ft_check_group = flow_group;
 491
 492	/* Tx check table default drop rule */
 493	memset(&dest, 0, sizeof(struct mlx5_flow_destination));
 494	memset(&flow_act, 0, sizeof(flow_act));
 495	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
 496	dest.counter = tx_tables->check_miss_rule_counter;
 497	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
 498	rule = mlx5_add_flow_rules(tx_tables->ft_check,  NULL, &flow_act, &dest, 1);
 499	if (IS_ERR(rule)) {
 500		err = PTR_ERR(rule);
 501		mlx5_core_err(mdev, "Failed to added MACsec tx check drop rule, err(%d)\n", err);
 502		goto err;
 503	}
 504	tx_tables->check_miss_rule = rule;
 505
 506	/* Tx check table rule */
 507	memset(spec, 0, sizeof(struct mlx5_flow_spec));
 508	memset(&dest, 0, sizeof(struct mlx5_flow_destination));
 509	memset(&flow_act, 0, sizeof(flow_act));
 510
 511	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
 512	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
 513	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
 514
 515	flow_act.flags = FLOW_ACT_NO_APPEND;
 516	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT;
 517	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
 518	dest.counter = tx_tables->check_rule_counter;
 519	rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1);
 520	if (IS_ERR(rule)) {
 521		err = PTR_ERR(rule);
 522		mlx5_core_err(mdev, "Failed to add MACsec check rule, err=%d\n", err);
 523		goto err;
 524	}
 525	tx_fs->check_rule = rule;
 526
 527	err = macsec_fs_tx_roce_create(macsec_fs);
 528	if (err)
 529		goto err;
 530
 531	kvfree(flow_group_in);
 532	kvfree(spec);
 533	return 0;
 534
 535err:
 536	macsec_fs_tx_destroy(macsec_fs);
 537out_flow_group:
 538	kvfree(flow_group_in);
 539out_spec:
 540	kvfree(spec);
 541	return err;
 542}
 543
 544static int macsec_fs_tx_ft_get(struct mlx5_macsec_fs *macsec_fs)
 545{
 546	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 547	struct mlx5_macsec_tables *tx_tables;
 548	int err = 0;
 549
 550	tx_tables = &tx_fs->tables;
 551	if (tx_tables->refcnt)
 552		goto out;
 553
 554	err = macsec_fs_tx_create(macsec_fs);
 555	if (err)
 556		return err;
 557
 558out:
 559	tx_tables->refcnt++;
 560	return err;
 561}
 562
 563static void macsec_fs_tx_ft_put(struct mlx5_macsec_fs *macsec_fs)
 564{
 565	struct mlx5_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
 566
 567	if (--tx_tables->refcnt)
 568		return;
 569
 570	macsec_fs_tx_destroy(macsec_fs);
 571}
 572
 573static int macsec_fs_tx_setup_fte(struct mlx5_macsec_fs *macsec_fs,
 574				  struct mlx5_flow_spec *spec,
 575				  struct mlx5_flow_act *flow_act,
 576				  u32 macsec_obj_id,
 577				  u32 *fs_id)
 578{
 579	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 580	int err = 0;
 581	u32 id;
 582
 583	err = ida_alloc_range(&tx_fs->tx_halloc, 1,
 584			      MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES,
 585			      GFP_KERNEL);
 586	if (err < 0)
 587		return err;
 588
 589	id = err;
 590	spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
 591
 592	/* Metadata match */
 593	MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a,
 594		 MLX5_ETH_WQE_FT_META_MACSEC_MASK);
 595	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a,
 596		 MLX5_MACSEC_TX_METADATA(id));
 597
 598	*fs_id = id;
 599	flow_act->crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
 600	flow_act->crypto.obj_id = macsec_obj_id;
 601
 602	mlx5_core_dbg(macsec_fs->mdev, "Tx fte: macsec obj_id %u, fs_id %u\n", macsec_obj_id, id);
 603	return 0;
 604}
 605
 606static void macsec_fs_tx_create_sectag_header(const struct macsec_context *ctx,
 607					      char *reformatbf,
 608					      size_t *reformat_size)
 609{
 610	const struct macsec_secy *secy = ctx->secy;
 611	bool sci_present = macsec_send_sci(secy);
 612	struct mlx5_sectag_header sectag = {};
 613	const struct macsec_tx_sc *tx_sc;
 614
 615	tx_sc = &secy->tx_sc;
 616	sectag.ethertype = htons(ETH_P_MACSEC);
 617
 618	if (sci_present) {
 619		sectag.tci_an |= MACSEC_TCI_SC;
 620		memcpy(&sectag.sci, &secy->sci,
 621		       sizeof(sectag.sci));
 622	} else {
 623		if (tx_sc->end_station)
 624			sectag.tci_an |= MACSEC_TCI_ES;
 625		if (tx_sc->scb)
 626			sectag.tci_an |= MACSEC_TCI_SCB;
 627	}
 628
 629	/* With GCM, C/E clear for !encrypt, both set for encrypt */
 630	if (tx_sc->encrypt)
 631		sectag.tci_an |= MACSEC_TCI_CONFID;
 632	else if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
 633		sectag.tci_an |= MACSEC_TCI_C;
 634
 635	sectag.tci_an |= tx_sc->encoding_sa;
 636
 637	*reformat_size = MLX5_MACSEC_TAG_LEN + (sci_present ? MACSEC_SCI_LEN : 0);
 638
 639	memcpy(reformatbf, &sectag, *reformat_size);
 640}
 641
 642static bool macsec_fs_is_macsec_device_empty(struct mlx5_macsec_device *macsec_device)
 643{
 644	if (xa_empty(&macsec_device->tx_id_xa) &&
 645	    xa_empty(&macsec_device->rx_id_xa))
 646		return true;
 647
 648	return false;
 649}
 650
 651static void macsec_fs_id_del(struct list_head *macsec_devices_list, u32 fs_id,
 652			     void *macdev, struct rhashtable *hash_table, bool is_tx)
 653{
 654	const struct rhashtable_params *rhash = (is_tx) ? &rhash_sci : &rhash_fs_id;
 655	struct mlx5_macsec_device *iter, *macsec_device = NULL;
 656	struct mlx5_fs_id *fs_id_found;
 657	struct xarray *fs_id_xa;
 658
 659	list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) {
 660		if (iter->macdev == macdev) {
 661			macsec_device = iter;
 662			break;
 663		}
 664	}
 665	WARN_ON(!macsec_device);
 666
 667	fs_id_xa = (is_tx) ? &macsec_device->tx_id_xa :
 668			     &macsec_device->rx_id_xa;
 669	xa_lock(fs_id_xa);
 670	fs_id_found = xa_load(fs_id_xa, fs_id);
 671	WARN_ON(!fs_id_found);
 672
 673	if (!refcount_dec_and_test(&fs_id_found->refcnt)) {
 674		xa_unlock(fs_id_xa);
 675		return;
 676	}
 677
 678	if (fs_id_found->id) {
 679		/* Make sure ongoing datapath readers sees a valid SA */
 680		rhashtable_remove_fast(hash_table, &fs_id_found->hash, *rhash);
 681		fs_id_found->id = 0;
 682	}
 683	xa_unlock(fs_id_xa);
 684
 685	xa_erase(fs_id_xa, fs_id);
 686
 687	kfree(fs_id_found);
 688
 689	if (macsec_fs_is_macsec_device_empty(macsec_device)) {
 690		list_del(&macsec_device->macsec_devices_list_entry);
 691		kfree(macsec_device);
 692	}
 693}
 694
 695static int macsec_fs_id_add(struct list_head *macsec_devices_list, u32 fs_id,
 696			    void *macdev, struct rhashtable *hash_table, sci_t sci,
 697			    bool is_tx)
 698{
 699	const struct rhashtable_params *rhash = (is_tx) ? &rhash_sci : &rhash_fs_id;
 700	struct mlx5_macsec_device *iter, *macsec_device = NULL;
 701	struct mlx5_fs_id *fs_id_iter;
 702	struct xarray *fs_id_xa;
 703	int err;
 704
 705	if (!is_tx) {
 706		rcu_read_lock();
 707		fs_id_iter = rhashtable_lookup(hash_table, &fs_id, rhash_fs_id);
 708		if (fs_id_iter) {
 709			refcount_inc(&fs_id_iter->refcnt);
 710			rcu_read_unlock();
 711			return 0;
 712		}
 713		rcu_read_unlock();
 714	}
 715
 716	fs_id_iter = kzalloc(sizeof(*fs_id_iter), GFP_KERNEL);
 717	if (!fs_id_iter)
 718		return -ENOMEM;
 719
 720	list_for_each_entry(iter, macsec_devices_list, macsec_devices_list_entry) {
 721		if (iter->macdev == macdev) {
 722			macsec_device = iter;
 723			break;
 724		}
 725	}
 726
 727	if (!macsec_device) { /* first time adding a SA to that device */
 728		macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL);
 729		if (!macsec_device) {
 730			err = -ENOMEM;
 731			goto err_alloc_dev;
 732		}
 733		macsec_device->macdev = macdev;
 734		xa_init(&macsec_device->tx_id_xa);
 735		xa_init(&macsec_device->rx_id_xa);
 736		list_add(&macsec_device->macsec_devices_list_entry, macsec_devices_list);
 737	}
 738
 739	fs_id_xa = (is_tx) ? &macsec_device->tx_id_xa :
 740			     &macsec_device->rx_id_xa;
 741	fs_id_iter->id = fs_id;
 742	refcount_set(&fs_id_iter->refcnt, 1);
 743	fs_id_iter->sci = sci;
 744	err = xa_err(xa_store(fs_id_xa, fs_id, fs_id_iter, GFP_KERNEL));
 745	if (err)
 746		goto err_store_id;
 747
 748	err = rhashtable_insert_fast(hash_table, &fs_id_iter->hash, *rhash);
 749	if (err)
 750		goto err_hash_insert;
 751
 752	return 0;
 753
 754err_hash_insert:
 755	xa_erase(fs_id_xa, fs_id);
 756err_store_id:
 757	if (macsec_fs_is_macsec_device_empty(macsec_device)) {
 758		list_del(&macsec_device->macsec_devices_list_entry);
 759		kfree(macsec_device);
 760	}
 761err_alloc_dev:
 762	kfree(fs_id_iter);
 763	return err;
 764}
 765
 766static void macsec_fs_tx_del_rule(struct mlx5_macsec_fs *macsec_fs,
 767				  struct mlx5_macsec_tx_rule *tx_rule,
 768				  void *macdev)
 769{
 770	macsec_fs_id_del(&macsec_fs->macsec_devices_list, tx_rule->fs_id, macdev,
 771			 &macsec_fs->sci_hash, true);
 772
 773	if (tx_rule->rule) {
 774		mlx5_del_flow_rules(tx_rule->rule);
 775		tx_rule->rule = NULL;
 776	}
 777
 778	if (tx_rule->pkt_reformat) {
 779		mlx5_packet_reformat_dealloc(macsec_fs->mdev, tx_rule->pkt_reformat);
 780		tx_rule->pkt_reformat = NULL;
 781	}
 782
 783	if (tx_rule->fs_id) {
 784		ida_free(&macsec_fs->tx_fs->tx_halloc, tx_rule->fs_id);
 785		tx_rule->fs_id = 0;
 786	}
 787
 788	kfree(tx_rule);
 789
 790	macsec_fs_tx_ft_put(macsec_fs);
 791}
 792
 793#define MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES 1
 794
 795static union mlx5_macsec_rule *
 796macsec_fs_tx_add_rule(struct mlx5_macsec_fs *macsec_fs,
 797		      const struct macsec_context *macsec_ctx,
 798		      struct mlx5_macsec_rule_attrs *attrs, u32 *fs_id)
 799{
 800	char reformatbf[MLX5_MACSEC_TAG_LEN + MACSEC_SCI_LEN];
 801	struct mlx5_pkt_reformat_params reformat_params = {};
 802	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 803	struct mlx5_core_dev *mdev = macsec_fs->mdev;
 804	union mlx5_macsec_rule *macsec_rule = NULL;
 805	struct mlx5_flow_destination dest = {};
 806	struct mlx5_macsec_tables *tx_tables;
 807	struct mlx5_macsec_tx_rule *tx_rule;
 808	struct mlx5_flow_act flow_act = {};
 809	struct mlx5_flow_handle *rule;
 810	struct mlx5_flow_spec *spec;
 811	size_t reformat_size;
 812	int err = 0;
 813
 814	tx_tables = &tx_fs->tables;
 815
 816	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 817	if (!spec)
 818		return NULL;
 819
 820	err = macsec_fs_tx_ft_get(macsec_fs);
 821	if (err)
 822		goto out_spec;
 823
 824	macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
 825	if (!macsec_rule) {
 826		macsec_fs_tx_ft_put(macsec_fs);
 827		goto out_spec;
 828	}
 829
 830	tx_rule = &macsec_rule->tx_rule;
 831
 832	/* Tx crypto table crypto rule */
 833	macsec_fs_tx_create_sectag_header(macsec_ctx, reformatbf, &reformat_size);
 834
 835	reformat_params.type = MLX5_REFORMAT_TYPE_ADD_MACSEC;
 836	reformat_params.size = reformat_size;
 837	reformat_params.data = reformatbf;
 838
 839	if (is_vlan_dev(macsec_ctx->netdev))
 840		reformat_params.param_0 = MLX5_REFORMAT_PARAM_ADD_MACSEC_OFFSET_4_BYTES;
 841
 842	flow_act.pkt_reformat = mlx5_packet_reformat_alloc(mdev,
 843							   &reformat_params,
 844							   MLX5_FLOW_NAMESPACE_EGRESS_MACSEC);
 845	if (IS_ERR(flow_act.pkt_reformat)) {
 846		err = PTR_ERR(flow_act.pkt_reformat);
 847		mlx5_core_err(mdev, "Failed to allocate MACsec Tx reformat context err=%d\n",  err);
 848		goto err;
 849	}
 850	tx_rule->pkt_reformat = flow_act.pkt_reformat;
 851
 852	err = macsec_fs_tx_setup_fte(macsec_fs, spec, &flow_act, attrs->macsec_obj_id, fs_id);
 853	if (err) {
 854		mlx5_core_err(mdev,
 855			      "Failed to add packet reformat for MACsec TX crypto rule, err=%d\n",
 856			      err);
 857		goto err;
 858	}
 859
 860	tx_rule->fs_id = *fs_id;
 861
 862	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
 863			  MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
 864			  MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
 865	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 866	dest.ft = tx_tables->ft_check;
 867	rule = mlx5_add_flow_rules(tx_tables->ft_crypto.t, spec, &flow_act, &dest, 1);
 868	if (IS_ERR(rule)) {
 869		err = PTR_ERR(rule);
 870		mlx5_core_err(mdev, "Failed to add MACsec TX crypto rule, err=%d\n", err);
 871		goto err;
 872	}
 873	tx_rule->rule = rule;
 874
 875	err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, *fs_id, macsec_ctx->secy->netdev,
 876			       &macsec_fs->sci_hash, attrs->sci, true);
 877	if (err) {
 878		mlx5_core_err(mdev, "Failed to save fs_id, err=%d\n", err);
 879		goto err;
 880	}
 881
 882	goto out_spec;
 883
 884err:
 885	macsec_fs_tx_del_rule(macsec_fs, tx_rule, macsec_ctx->secy->netdev);
 886	macsec_rule = NULL;
 887out_spec:
 888	kvfree(spec);
 889
 890	return macsec_rule;
 891}
 892
 893static void macsec_fs_tx_cleanup(struct mlx5_macsec_fs *macsec_fs)
 894{
 895	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
 896	struct mlx5_core_dev *mdev = macsec_fs->mdev;
 897	struct mlx5_macsec_tables *tx_tables;
 898
 899	if (!tx_fs)
 900		return;
 901
 902	tx_tables = &tx_fs->tables;
 903	if (tx_tables->refcnt) {
 904		mlx5_core_err(mdev,
 905			      "Can't destroy MACsec offload tx_fs, refcnt(%u) isn't 0\n",
 906			      tx_tables->refcnt);
 907		return;
 908	}
 909
 910	ida_destroy(&tx_fs->tx_halloc);
 911
 912	if (tx_tables->check_miss_rule_counter) {
 913		mlx5_fc_destroy(mdev, tx_tables->check_miss_rule_counter);
 914		tx_tables->check_miss_rule_counter = NULL;
 915	}
 916
 917	if (tx_tables->check_rule_counter) {
 918		mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
 919		tx_tables->check_rule_counter = NULL;
 920	}
 921
 922	kfree(tx_fs);
 923	macsec_fs->tx_fs = NULL;
 924}
 925
 926static int macsec_fs_tx_init(struct mlx5_macsec_fs *macsec_fs)
 927{
 928	struct mlx5_core_dev *mdev = macsec_fs->mdev;
 929	struct mlx5_macsec_tables *tx_tables;
 930	struct mlx5_macsec_tx *tx_fs;
 931	struct mlx5_fc *flow_counter;
 932	int err;
 933
 934	tx_fs = kzalloc(sizeof(*tx_fs), GFP_KERNEL);
 935	if (!tx_fs)
 936		return -ENOMEM;
 937
 938	tx_tables = &tx_fs->tables;
 939
 940	flow_counter = mlx5_fc_create(mdev, false);
 941	if (IS_ERR(flow_counter)) {
 942		err = PTR_ERR(flow_counter);
 943		mlx5_core_err(mdev,
 944			      "Failed to create MACsec Tx encrypt flow counter, err(%d)\n",
 945			      err);
 946		goto err_encrypt_counter;
 947	}
 948	tx_tables->check_rule_counter = flow_counter;
 949
 950	flow_counter = mlx5_fc_create(mdev, false);
 951	if (IS_ERR(flow_counter)) {
 952		err = PTR_ERR(flow_counter);
 953		mlx5_core_err(mdev,
 954			      "Failed to create MACsec Tx drop flow counter, err(%d)\n",
 955			      err);
 956		goto err_drop_counter;
 957	}
 958	tx_tables->check_miss_rule_counter = flow_counter;
 959
 960	ida_init(&tx_fs->tx_halloc);
 961	INIT_LIST_HEAD(&macsec_fs->macsec_devices_list);
 962
 963	macsec_fs->tx_fs = tx_fs;
 964
 965	return 0;
 966
 967err_drop_counter:
 968	mlx5_fc_destroy(mdev, tx_tables->check_rule_counter);
 969	tx_tables->check_rule_counter = NULL;
 970
 971err_encrypt_counter:
 972	kfree(tx_fs);
 973	macsec_fs->tx_fs = NULL;
 974
 975	return err;
 976}
 977
 978static void macsec_fs_rx_roce_miss_destroy(struct mlx5_macsec_miss *miss)
 979{
 980	mlx5_del_flow_rules(miss->rule);
 981	mlx5_destroy_flow_group(miss->g);
 982}
 983
 984static void macsec_fs_rdma_rx_destroy(struct mlx5_macsec_rx_roce *roce, struct mlx5_core_dev *mdev)
 985{
 986	if (!mlx5_is_macsec_roce_supported(mdev))
 987		return;
 988
 989	mlx5_del_flow_rules(roce->nic_miss.rule);
 990	mlx5_del_flow_rules(roce->rule);
 991	mlx5_modify_header_dealloc(mdev, roce->copy_modify_hdr);
 992	mlx5_destroy_flow_group(roce->nic_miss.g);
 993	mlx5_destroy_flow_group(roce->g);
 994	mlx5_destroy_flow_table(roce->ft);
 995
 996	macsec_fs_rx_roce_miss_destroy(&roce->miss);
 997	mlx5_destroy_flow_table(roce->ft_macsec_op_check);
 998	mlx5_destroy_flow_table(roce->ft_ip_check);
 999}
1000
1001static void macsec_fs_rx_destroy(struct mlx5_macsec_fs *macsec_fs)
1002{
1003	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1004	struct mlx5_macsec_tables *rx_tables;
1005	int i;
1006
1007	/* Rx check table */
1008	for (i = 1; i >= 0; --i) {
1009		if (rx_fs->check_rule[i]) {
1010			mlx5_del_flow_rules(rx_fs->check_rule[i]);
1011			rx_fs->check_rule[i] = NULL;
1012		}
1013
1014		if (rx_fs->check_rule_pkt_reformat[i]) {
1015			mlx5_packet_reformat_dealloc(macsec_fs->mdev,
1016						     rx_fs->check_rule_pkt_reformat[i]);
1017			rx_fs->check_rule_pkt_reformat[i] = NULL;
1018		}
1019	}
1020
1021	rx_tables = &rx_fs->tables;
1022
1023	if (rx_tables->check_miss_rule) {
1024		mlx5_del_flow_rules(rx_tables->check_miss_rule);
1025		rx_tables->check_miss_rule = NULL;
1026	}
1027
1028	if (rx_tables->ft_check_group) {
1029		mlx5_destroy_flow_group(rx_tables->ft_check_group);
1030		rx_tables->ft_check_group = NULL;
1031	}
1032
1033	if (rx_tables->ft_check) {
1034		mlx5_destroy_flow_table(rx_tables->ft_check);
1035		rx_tables->ft_check = NULL;
1036	}
1037
1038	/* Rx crypto table */
1039	if (rx_tables->crypto_miss_rule) {
1040		mlx5_del_flow_rules(rx_tables->crypto_miss_rule);
1041		rx_tables->crypto_miss_rule = NULL;
1042	}
1043
1044	macsec_fs_destroy_flow_table(&rx_tables->ft_crypto);
1045
1046	macsec_fs_rdma_rx_destroy(&macsec_fs->rx_fs->roce, macsec_fs->mdev);
1047}
1048
1049static int macsec_fs_rx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft)
1050{
1051	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1052	int mclen = MLX5_ST_SZ_BYTES(fte_match_param);
1053	int ix = 0;
1054	u32 *in;
1055	int err;
1056	u8 *mc;
1057
1058	ft->g = kcalloc(RX_CRYPTO_TABLE_NUM_GROUPS, sizeof(*ft->g), GFP_KERNEL);
1059	if (!ft->g)
1060		return -ENOMEM;
1061
1062	in = kvzalloc(inlen, GFP_KERNEL);
1063	if (!in) {
1064		kfree(ft->g);
1065		return -ENOMEM;
1066	}
1067
1068	mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1069
1070	/* Flow group for SA rule with SCI */
1071	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
1072						MLX5_MATCH_MISC_PARAMETERS_5);
1073	MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
1074
1075	MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
1076		 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK <<
1077		 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1078	MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_2);
1079	MLX5_SET_TO_ONES(fte_match_param, mc, misc_parameters_5.macsec_tag_3);
1080
1081	MLX5_SET_CFG(in, start_flow_index, ix);
1082	ix += RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE;
1083	MLX5_SET_CFG(in, end_flow_index, ix - 1);
1084	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1085	if (IS_ERR(ft->g[ft->num_groups]))
1086		goto err;
1087	ft->num_groups++;
1088
1089	/* Flow group for SA rule without SCI */
1090	memset(in, 0, inlen);
1091	memset(mc, 0, mclen);
1092	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS |
1093						MLX5_MATCH_MISC_PARAMETERS_5);
1094	MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_47_16);
1095	MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.smac_15_0);
1096	MLX5_SET_TO_ONES(fte_match_param, mc, outer_headers.ethertype);
1097
1098	MLX5_SET(fte_match_param, mc, misc_parameters_5.macsec_tag_0,
1099		 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1100
1101	MLX5_SET_CFG(in, start_flow_index, ix);
1102	ix += RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE;
1103	MLX5_SET_CFG(in, end_flow_index, ix - 1);
1104	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1105	if (IS_ERR(ft->g[ft->num_groups]))
1106		goto err;
1107	ft->num_groups++;
1108
1109	/* Flow Group for l2 traps */
1110	memset(in, 0, inlen);
1111	memset(mc, 0, mclen);
1112	MLX5_SET_CFG(in, start_flow_index, ix);
1113	ix += CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE;
1114	MLX5_SET_CFG(in, end_flow_index, ix - 1);
1115	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
1116	if (IS_ERR(ft->g[ft->num_groups]))
1117		goto err;
1118	ft->num_groups++;
1119
1120	kvfree(in);
1121	return 0;
1122
1123err:
1124	err = PTR_ERR(ft->g[ft->num_groups]);
1125	ft->g[ft->num_groups] = NULL;
1126	kvfree(in);
1127
1128	return err;
1129}
1130
1131static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs,
1132						struct mlx5_flow_destination *dest,
1133						struct mlx5_flow_act *flow_act,
1134						struct mlx5_flow_spec *spec,
1135						int reformat_param_size)
1136{
1137	int rule_index = (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI) ? 0 : 1;
1138	u8 mlx5_reformat_buf[MLX5_SECTAG_HEADER_SIZE_WITH_SCI];
1139	struct mlx5_pkt_reformat_params reformat_params = {};
1140	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1141	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1142	struct mlx5_flow_destination roce_dest[2];
1143	struct mlx5_macsec_tables *rx_tables;
1144	struct mlx5_flow_handle *rule;
1145	int err = 0, dstn = 0;
1146
1147	rx_tables = &rx_fs->tables;
1148
1149	/* Rx check table decap 16B rule */
1150	memset(dest, 0, sizeof(*dest));
1151	memset(flow_act, 0, sizeof(*flow_act));
1152	memset(spec, 0, sizeof(*spec));
1153
1154	reformat_params.type = MLX5_REFORMAT_TYPE_DEL_MACSEC;
1155	reformat_params.size = reformat_param_size;
1156	reformat_params.data = mlx5_reformat_buf;
1157	flow_act->pkt_reformat = mlx5_packet_reformat_alloc(mdev,
1158							    &reformat_params,
1159							    MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
1160	if (IS_ERR(flow_act->pkt_reformat)) {
1161		err = PTR_ERR(flow_act->pkt_reformat);
1162		mlx5_core_err(mdev, "Failed to allocate MACsec Rx reformat context err=%d\n", err);
1163		return err;
1164	}
1165	rx_fs->check_rule_pkt_reformat[rule_index] = flow_act->pkt_reformat;
1166
1167	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
1168	/* MACsec syndrome match */
1169	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.macsec_syndrome);
1170	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.macsec_syndrome, 0);
1171	/* ASO return reg syndrome match */
1172	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_4);
1173	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_4, 0);
1174
1175	spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
1176	/* Sectag TCI SC present bit*/
1177	MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
1178		 MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1179
1180	if (reformat_param_size == MLX5_SECTAG_HEADER_SIZE_WITH_SCI)
1181		MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
1182			 MLX5_MACSEC_SECTAG_TCI_SC_FIELD_BIT <<
1183			 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1184
1185	flow_act->flags = FLOW_ACT_NO_APPEND;
1186
1187	if (rx_fs->roce.ft) {
1188		flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1189		roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1190		roce_dest[dstn].ft = rx_fs->roce.ft;
1191		dstn++;
1192	} else {
1193		flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1194	}
1195
1196	flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
1197			    MLX5_FLOW_CONTEXT_ACTION_COUNT;
1198	roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1199	roce_dest[dstn].counter = rx_tables->check_rule_counter;
1200	rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, roce_dest, dstn + 1);
1201
1202	if (IS_ERR(rule)) {
1203		err = PTR_ERR(rule);
1204		mlx5_core_err(mdev, "Failed to add MACsec Rx check rule, err=%d\n", err);
1205		return err;
1206	}
1207
1208	rx_fs->check_rule[rule_index] = rule;
1209
1210	return 0;
1211}
1212
1213static int macsec_fs_rx_roce_miss_create(struct mlx5_core_dev *mdev,
1214					 struct mlx5_macsec_rx_roce *roce)
1215{
1216	struct mlx5_flow_act flow_act = {};
1217	struct mlx5_flow_group *flow_group;
1218	struct mlx5_flow_handle *rule;
1219	u32 *flow_group_in;
1220	int err;
1221
1222	flow_group_in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL);
1223	if (!flow_group_in)
1224		return -ENOMEM;
1225
1226	/* IP check ft has no miss rule since we use default miss action which is go to next PRIO */
1227	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index,
1228		 roce->ft_macsec_op_check->max_fte - 1);
1229	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
1230		 roce->ft_macsec_op_check->max_fte - 1);
1231	flow_group = mlx5_create_flow_group(roce->ft_macsec_op_check, flow_group_in);
1232	if (IS_ERR(flow_group)) {
1233		err = PTR_ERR(flow_group);
1234		mlx5_core_err(mdev,
1235			      "Failed to create miss flow group for MACsec RoCE operation check table err(%d)\n",
1236			      err);
1237		goto err_macsec_op_miss_group;
1238	}
1239	roce->miss.g = flow_group;
1240
1241	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1242	rule = mlx5_add_flow_rules(roce->ft_macsec_op_check,  NULL, &flow_act, NULL, 0);
1243	if (IS_ERR(rule)) {
1244		err = PTR_ERR(rule);
1245		mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE operation check table err(%d)\n",
1246			      err);
1247		goto err_macsec_op_rule;
1248	}
1249	roce->miss.rule = rule;
1250
1251	kvfree(flow_group_in);
1252	return 0;
1253
1254err_macsec_op_rule:
1255	mlx5_destroy_flow_group(roce->miss.g);
1256err_macsec_op_miss_group:
1257	kvfree(flow_group_in);
1258	return err;
1259}
1260
1261#define MLX5_RX_ROCE_GROUP_SIZE BIT(0)
1262
1263static int macsec_fs_rx_roce_jump_to_rdma_groups_create(struct mlx5_core_dev *mdev,
1264							struct mlx5_macsec_rx_roce *roce)
1265{
1266	struct mlx5_flow_group *g;
1267	void *outer_headers_c;
1268	int ix = 0;
1269	u32 *in;
1270	int err;
1271	u8 *mc;
1272
1273	in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL);
1274	if (!in)
1275		return -ENOMEM;
1276
1277	mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
1278	outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers);
1279	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol);
1280	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, udp_dport);
1281
1282	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1283	MLX5_SET_CFG(in, start_flow_index, ix);
1284	ix += MLX5_RX_ROCE_GROUP_SIZE;
1285	MLX5_SET_CFG(in, end_flow_index, ix - 1);
1286	g = mlx5_create_flow_group(roce->ft, in);
1287	if (IS_ERR(g)) {
1288		err = PTR_ERR(g);
1289		mlx5_core_err(mdev, "Failed to create main flow group for MACsec RoCE NIC UDP table err(%d)\n",
1290			      err);
1291		goto err_udp_group;
1292	}
1293	roce->g = g;
1294
1295	memset(in, 0, MLX5_ST_SZ_BYTES(create_flow_group_in));
1296	MLX5_SET_CFG(in, start_flow_index, ix);
1297	ix += MLX5_RX_ROCE_GROUP_SIZE;
1298	MLX5_SET_CFG(in, end_flow_index, ix - 1);
1299	g = mlx5_create_flow_group(roce->ft, in);
1300	if (IS_ERR(g)) {
1301		err = PTR_ERR(g);
1302		mlx5_core_err(mdev, "Failed to create miss flow group for MACsec RoCE NIC UDP table err(%d)\n",
1303			      err);
1304		goto err_udp_miss_group;
1305	}
1306	roce->nic_miss.g = g;
1307
1308	kvfree(in);
1309	return 0;
1310
1311err_udp_miss_group:
1312	mlx5_destroy_flow_group(roce->g);
1313err_udp_group:
1314	kvfree(in);
1315	return err;
1316}
1317
1318static int macsec_fs_rx_roce_jump_to_rdma_rules_create(struct mlx5_macsec_fs *macsec_fs,
1319						       struct mlx5_macsec_rx_roce *roce)
1320{
1321	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
1322	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1323	struct mlx5_flow_destination dst = {};
1324	struct mlx5_modify_hdr *modify_hdr;
1325	MLX5_DECLARE_FLOW_ACT(flow_act);
1326	struct mlx5_flow_handle *rule;
1327	struct mlx5_flow_spec *spec;
1328	int err;
1329
1330	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1331	if (!spec)
1332		return -ENOMEM;
1333
1334	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1335	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol);
1336	MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_UDP);
1337	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.udp_dport);
1338	MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_dport, ROCE_V2_UDP_DPORT);
1339
1340	MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY);
1341	MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
1342	MLX5_SET(copy_action_in, action, src_offset, 0);
1343	MLX5_SET(copy_action_in, action, length, 32);
1344	MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_5);
1345	MLX5_SET(copy_action_in, action, dst_offset, 0);
1346
1347	modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC,
1348					      1, action);
1349
1350	if (IS_ERR(modify_hdr)) {
1351		err = PTR_ERR(modify_hdr);
1352		mlx5_core_err(mdev,
1353			      "Failed to alloc macsec copy modify_header_id err(%d)\n", err);
1354		goto err_alloc_hdr;
1355	}
1356
1357	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1358	flow_act.modify_hdr = modify_hdr;
1359	dst.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE;
1360	dst.ft = roce->ft_ip_check;
1361	rule = mlx5_add_flow_rules(roce->ft, spec, &flow_act, &dst, 1);
1362	if (IS_ERR(rule)) {
1363		err = PTR_ERR(rule);
1364		mlx5_core_err(mdev, "Failed to add rule to MACsec RoCE NIC UDP table err(%d)\n",
1365			      err);
1366		goto err_add_rule;
1367	}
1368	roce->rule = rule;
1369	roce->copy_modify_hdr = modify_hdr;
1370
1371	memset(&flow_act, 0, sizeof(flow_act));
1372	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1373	rule = mlx5_add_flow_rules(roce->ft, NULL, &flow_act, NULL, 0);
1374	if (IS_ERR(rule)) {
1375		err = PTR_ERR(rule);
1376		mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE NIC UDP table err(%d)\n",
1377			      err);
1378		goto err_add_rule2;
1379	}
1380	roce->nic_miss.rule = rule;
1381
1382	kvfree(spec);
1383	return 0;
1384
1385err_add_rule2:
1386	mlx5_del_flow_rules(roce->rule);
1387err_add_rule:
1388	mlx5_modify_header_dealloc(macsec_fs->mdev, modify_hdr);
1389err_alloc_hdr:
1390	kvfree(spec);
1391	return err;
1392}
1393
1394static int macsec_fs_rx_roce_jump_to_rdma_create(struct mlx5_macsec_fs *macsec_fs,
1395						 struct mlx5_macsec_rx_roce *roce)
1396{
1397	int err;
1398
1399	err = macsec_fs_rx_roce_jump_to_rdma_groups_create(macsec_fs->mdev, roce);
1400	if (err)
1401		return err;
1402
1403	err = macsec_fs_rx_roce_jump_to_rdma_rules_create(macsec_fs, roce);
1404	if (err)
1405		goto err;
1406
1407	return 0;
1408err:
1409	mlx5_destroy_flow_group(roce->nic_miss.g);
1410	mlx5_destroy_flow_group(roce->g);
1411	return err;
1412}
1413
1414static int macsec_fs_rx_roce_create(struct mlx5_macsec_fs *macsec_fs)
1415{
1416	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1417	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1418	struct mlx5_flow_table_attr ft_attr = {};
1419	struct mlx5_flow_namespace *ns;
1420	struct mlx5_flow_table *ft;
1421	int err = 0;
1422
1423	if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev)) {
1424		mlx5_core_dbg(mdev, "Failed to init RoCE MACsec, capabilities not supported\n");
1425		return 0;
1426	}
1427
1428	ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC);
1429	if (!ns)
1430		return -ENOMEM;
1431
1432	ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_IP_TABLE_LEVEL,
1433					       CRYPTO_NUM_MAXSEC_FTE);
1434	if (IS_ERR(ft)) {
1435		err = PTR_ERR(ft);
1436		mlx5_core_err(mdev,
1437			      "Failed to create MACsec IP check RoCE table err(%d)\n", err);
1438		return err;
1439	}
1440	rx_fs->roce.ft_ip_check = ft;
1441
1442	ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL,
1443					       CRYPTO_NUM_MAXSEC_FTE);
1444	if (IS_ERR(ft)) {
1445		err = PTR_ERR(ft);
1446		mlx5_core_err(mdev,
1447			      "Failed to create MACsec operation check RoCE table err(%d)\n",
1448			      err);
1449		goto err_macsec_op;
1450	}
1451	rx_fs->roce.ft_macsec_op_check = ft;
1452
1453	err = macsec_fs_rx_roce_miss_create(mdev, &rx_fs->roce);
1454	if (err)
1455		goto err_miss_create;
1456
1457	ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
1458	if (!ns) {
1459		err = -EOPNOTSUPP;
1460		goto err_ns;
1461	}
1462
1463	ft_attr.level = RX_ROCE_TABLE_LEVEL;
1464	ft_attr.max_fte = RX_ROCE_TABLE_NUM_FTE;
1465	ft = mlx5_create_flow_table(ns, &ft_attr);
1466	if (IS_ERR(ft)) {
1467		err = PTR_ERR(ft);
1468		mlx5_core_err(mdev,
1469			      "Failed to create MACsec jump to RX RoCE, NIC table err(%d)\n", err);
1470		goto err_ns;
1471	}
1472	rx_fs->roce.ft = ft;
1473
1474	err = macsec_fs_rx_roce_jump_to_rdma_create(macsec_fs, &rx_fs->roce);
1475	if (err)
1476		goto err_udp_ft;
1477
1478	return 0;
1479
1480err_udp_ft:
1481	mlx5_destroy_flow_table(rx_fs->roce.ft);
1482err_ns:
1483	macsec_fs_rx_roce_miss_destroy(&rx_fs->roce.miss);
1484err_miss_create:
1485	mlx5_destroy_flow_table(rx_fs->roce.ft_macsec_op_check);
1486err_macsec_op:
1487	mlx5_destroy_flow_table(rx_fs->roce.ft_ip_check);
1488	return err;
1489}
1490
1491static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs)
1492{
1493	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1494	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1495	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1496	struct mlx5_macsec_flow_table *ft_crypto;
1497	struct mlx5_flow_table_attr ft_attr = {};
1498	struct mlx5_flow_destination dest = {};
1499	struct mlx5_macsec_tables *rx_tables;
1500	struct mlx5_flow_table *flow_table;
1501	struct mlx5_flow_group *flow_group;
1502	struct mlx5_flow_act flow_act = {};
1503	struct mlx5_flow_namespace *ns;
1504	struct mlx5_flow_handle *rule;
1505	struct mlx5_flow_spec *spec;
1506	u32 *flow_group_in;
1507	int err;
1508
1509	ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC);
1510	if (!ns)
1511		return -ENOMEM;
1512
1513	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1514	if (!spec)
1515		return -ENOMEM;
1516
1517	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1518	if (!flow_group_in) {
1519		err = -ENOMEM;
1520		goto free_spec;
1521	}
1522
1523	rx_tables = &rx_fs->tables;
1524	ft_crypto = &rx_tables->ft_crypto;
1525
1526	err = macsec_fs_rx_roce_create(macsec_fs);
1527	if (err)
1528		goto out_flow_group;
1529
1530	/* Rx crypto table */
1531	ft_attr.level = RX_CRYPTO_TABLE_LEVEL;
1532	ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE;
1533
1534	flow_table = mlx5_create_flow_table(ns, &ft_attr);
1535	if (IS_ERR(flow_table)) {
1536		err = PTR_ERR(flow_table);
1537		mlx5_core_err(mdev, "Failed to create MACsec Rx crypto table err(%d)\n", err);
1538		goto err;
1539	}
1540	ft_crypto->t = flow_table;
1541
1542	/* Rx crypto table groups */
1543	err = macsec_fs_rx_create_crypto_table_groups(ft_crypto);
1544	if (err) {
1545		mlx5_core_err(mdev,
1546			      "Failed to create default flow group for MACsec Tx crypto table err(%d)\n",
1547			      err);
1548		goto err;
1549	}
1550
1551	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
1552	rule = mlx5_add_flow_rules(ft_crypto->t, NULL, &flow_act, NULL, 0);
1553	if (IS_ERR(rule)) {
1554		err = PTR_ERR(rule);
1555		mlx5_core_err(mdev,
1556			      "Failed to add MACsec Rx crypto table default miss rule %d\n",
1557			      err);
1558		goto err;
1559	}
1560	rx_tables->crypto_miss_rule = rule;
1561
1562	/* Rx check table */
1563	flow_table = macsec_fs_auto_group_table_create(ns,
1564						       MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT,
1565						       RX_CHECK_TABLE_LEVEL,
1566						       RX_CHECK_TABLE_NUM_FTE);
1567	if (IS_ERR(flow_table)) {
1568		err = PTR_ERR(flow_table);
1569		mlx5_core_err(mdev, "Fail to create MACsec RX check table, err(%d)\n", err);
1570		goto err;
1571	}
1572	rx_tables->ft_check = flow_table;
1573
1574	/* Rx check table Default miss group/rule */
1575	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_table->max_fte - 1);
1576	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_table->max_fte - 1);
1577	flow_group = mlx5_create_flow_group(rx_tables->ft_check, flow_group_in);
1578	if (IS_ERR(flow_group)) {
1579		err = PTR_ERR(flow_group);
1580		mlx5_core_err(mdev,
1581			      "Failed to create default flow group for MACsec Rx check table err(%d)\n",
1582			      err);
1583		goto err;
1584	}
1585	rx_tables->ft_check_group = flow_group;
1586
1587	/* Rx check table default drop rule */
1588	memset(&flow_act, 0, sizeof(flow_act));
1589
1590	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1591	dest.counter = rx_tables->check_miss_rule_counter;
1592	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
1593	rule = mlx5_add_flow_rules(rx_tables->ft_check,  NULL, &flow_act, &dest, 1);
1594	if (IS_ERR(rule)) {
1595		err = PTR_ERR(rule);
1596		mlx5_core_err(mdev, "Failed to added MACsec Rx check drop rule, err(%d)\n", err);
1597		goto err;
1598	}
1599	rx_tables->check_miss_rule = rule;
1600
1601	/* Rx check table decap rules */
1602	err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
1603						   MLX5_SECTAG_HEADER_SIZE_WITH_SCI);
1604	if (err)
1605		goto err;
1606
1607	err = macsec_fs_rx_create_check_decap_rule(macsec_fs, &dest, &flow_act, spec,
1608						   MLX5_SECTAG_HEADER_SIZE_WITHOUT_SCI);
1609	if (err)
1610		goto err;
1611
1612	goto out_flow_group;
1613
1614err:
1615	macsec_fs_rx_destroy(macsec_fs);
1616out_flow_group:
1617	kvfree(flow_group_in);
1618free_spec:
1619	kvfree(spec);
1620	return err;
1621}
1622
1623static int macsec_fs_rx_ft_get(struct mlx5_macsec_fs *macsec_fs)
1624{
1625	struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
1626	int err = 0;
1627
1628	if (rx_tables->refcnt)
1629		goto out;
1630
1631	err = macsec_fs_rx_create(macsec_fs);
1632	if (err)
1633		return err;
1634
1635out:
1636	rx_tables->refcnt++;
1637	return err;
1638}
1639
1640static void macsec_fs_rx_ft_put(struct mlx5_macsec_fs *macsec_fs)
1641{
1642	struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
1643
1644	if (--rx_tables->refcnt)
1645		return;
1646
1647	macsec_fs_rx_destroy(macsec_fs);
1648}
1649
1650static void macsec_fs_rx_del_rule(struct mlx5_macsec_fs *macsec_fs,
1651				  struct mlx5_macsec_rx_rule *rx_rule,
1652				  void *macdev, u32 fs_id)
1653{
1654	int i;
1655
1656	macsec_fs_id_del(&macsec_fs->macsec_devices_list, fs_id, macdev,
1657			 &macsec_fs->fs_id_hash, false);
1658
1659	for (i = 0; i < RX_NUM_OF_RULES_PER_SA; ++i) {
1660		if (rx_rule->rule[i]) {
1661			mlx5_del_flow_rules(rx_rule->rule[i]);
1662			rx_rule->rule[i] = NULL;
1663		}
1664	}
1665
1666	if (rx_rule->meta_modhdr) {
1667		mlx5_modify_header_dealloc(macsec_fs->mdev, rx_rule->meta_modhdr);
1668		rx_rule->meta_modhdr = NULL;
1669	}
1670
1671	kfree(rx_rule);
1672
1673	macsec_fs_rx_ft_put(macsec_fs);
1674}
1675
1676static void macsec_fs_rx_setup_fte(struct mlx5_flow_spec *spec,
1677				   struct mlx5_flow_act *flow_act,
1678				   struct mlx5_macsec_rule_attrs *attrs,
1679				   bool sci_present)
1680{
1681	u8 tci_an = (sci_present << MLX5_MACSEC_SECTAG_TCI_SC_FIELD_OFFSET) | attrs->assoc_num;
1682	struct mlx5_flow_act_crypto_params *crypto_params = &flow_act->crypto;
1683	__be32 *sci_p = (__be32 *)(&attrs->sci);
1684
1685	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1686
1687	/* MACsec ethertype */
1688	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ethertype);
1689	MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, ETH_P_MACSEC);
1690
1691	spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_5;
1692
1693	/* Sectag AN + TCI SC present bit*/
1694	MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_5.macsec_tag_0,
1695		 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1696	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_0,
1697		 tci_an << MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET);
1698
1699	if (sci_present) {
1700		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
1701				 misc_parameters_5.macsec_tag_2);
1702		MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_2,
1703			 be32_to_cpu(sci_p[0]));
1704
1705		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
1706				 misc_parameters_5.macsec_tag_3);
1707		MLX5_SET(fte_match_param, spec->match_value, misc_parameters_5.macsec_tag_3,
1708			 be32_to_cpu(sci_p[1]));
1709	} else {
1710		/* When SCI isn't present in the Sectag, need to match the source */
1711		/* MAC address only if the SCI contains the default MACsec PORT	  */
1712		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
1713		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
1714		memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers.smac_47_16),
1715		       sci_p, ETH_ALEN);
1716	}
1717
1718	crypto_params->type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_MACSEC;
1719	crypto_params->obj_id = attrs->macsec_obj_id;
1720}
1721
1722static union mlx5_macsec_rule *
1723macsec_fs_rx_add_rule(struct mlx5_macsec_fs *macsec_fs,
1724		      const struct macsec_context *macsec_ctx,
1725		      struct mlx5_macsec_rule_attrs *attrs,
1726		      u32 fs_id)
1727{
1728	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
1729	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1730	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1731	union mlx5_macsec_rule *macsec_rule = NULL;
1732	struct mlx5_modify_hdr *modify_hdr = NULL;
1733	struct mlx5_macsec_flow_table *ft_crypto;
1734	struct mlx5_flow_destination dest = {};
1735	struct mlx5_macsec_tables *rx_tables;
1736	struct mlx5_macsec_rx_rule *rx_rule;
1737	struct mlx5_flow_act flow_act = {};
1738	struct mlx5_flow_handle *rule;
1739	struct mlx5_flow_spec *spec;
1740	int err = 0;
1741
1742	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1743	if (!spec)
1744		return NULL;
1745
1746	err = macsec_fs_rx_ft_get(macsec_fs);
1747	if (err)
1748		goto out_spec;
1749
1750	macsec_rule = kzalloc(sizeof(*macsec_rule), GFP_KERNEL);
1751	if (!macsec_rule) {
1752		macsec_fs_rx_ft_put(macsec_fs);
1753		goto out_spec;
1754	}
1755
1756	rx_rule = &macsec_rule->rx_rule;
1757	rx_tables = &rx_fs->tables;
1758	ft_crypto = &rx_tables->ft_crypto;
1759
1760	/* Set bit[31 - 30] macsec marker - 0x01 */
1761	/* Set bit[15-0] fs id */
1762	MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
1763	MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_B);
1764	MLX5_SET(set_action_in, action, data, macsec_fs_set_rx_fs_id(fs_id));
1765	MLX5_SET(set_action_in, action, offset, 0);
1766	MLX5_SET(set_action_in, action, length, 32);
1767
1768	modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC,
1769					      1, action);
1770	if (IS_ERR(modify_hdr)) {
1771		err = PTR_ERR(modify_hdr);
1772		mlx5_core_err(mdev, "Fail to alloc MACsec set modify_header_id err=%d\n", err);
1773		modify_hdr = NULL;
1774		goto err;
1775	}
1776	rx_rule->meta_modhdr = modify_hdr;
1777
1778	/* Rx crypto table with SCI rule */
1779	macsec_fs_rx_setup_fte(spec, &flow_act, attrs, true);
1780
1781	flow_act.modify_hdr = modify_hdr;
1782	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1783			  MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
1784			  MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1785
1786	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1787	dest.ft = rx_tables->ft_check;
1788	rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
1789	if (IS_ERR(rule)) {
1790		err = PTR_ERR(rule);
1791		mlx5_core_err(mdev,
1792			      "Failed to add SA with SCI rule to Rx crypto rule, err=%d\n",
1793			      err);
1794		goto err;
1795	}
1796	rx_rule->rule[0] = rule;
1797
1798	/* Rx crypto table without SCI rule */
1799	if ((cpu_to_be64((__force u64)attrs->sci) & 0xFFFF) == ntohs(MACSEC_PORT_ES)) {
1800		memset(spec, 0, sizeof(struct mlx5_flow_spec));
1801		memset(&dest, 0, sizeof(struct mlx5_flow_destination));
1802		memset(&flow_act, 0, sizeof(flow_act));
1803
1804		macsec_fs_rx_setup_fte(spec, &flow_act, attrs, false);
1805
1806		flow_act.modify_hdr = modify_hdr;
1807		flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1808				  MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
1809				  MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
1810
1811		dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
1812		dest.ft = rx_tables->ft_check;
1813		rule = mlx5_add_flow_rules(ft_crypto->t, spec, &flow_act, &dest, 1);
1814		if (IS_ERR(rule)) {
1815			err = PTR_ERR(rule);
1816			mlx5_core_err(mdev,
1817				      "Failed to add SA without SCI rule to Rx crypto rule, err=%d\n",
1818				      err);
1819			goto err;
1820		}
1821		rx_rule->rule[1] = rule;
1822	}
1823
1824	err = macsec_fs_id_add(&macsec_fs->macsec_devices_list, fs_id, macsec_ctx->secy->netdev,
1825			       &macsec_fs->fs_id_hash, attrs->sci, false);
1826	if (err) {
1827		mlx5_core_err(mdev, "Failed to save fs_id, err=%d\n", err);
1828		goto err;
1829	}
1830
1831	kvfree(spec);
1832	return macsec_rule;
1833
1834err:
1835	macsec_fs_rx_del_rule(macsec_fs, rx_rule, macsec_ctx->secy->netdev, fs_id);
1836	macsec_rule = NULL;
1837out_spec:
1838	kvfree(spec);
1839	return macsec_rule;
1840}
1841
1842static int macsec_fs_rx_init(struct mlx5_macsec_fs *macsec_fs)
1843{
1844	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1845	struct mlx5_macsec_tables *rx_tables;
1846	struct mlx5_macsec_rx *rx_fs;
1847	struct mlx5_fc *flow_counter;
1848	int err;
1849
1850	rx_fs =	kzalloc(sizeof(*rx_fs), GFP_KERNEL);
1851	if (!rx_fs)
1852		return -ENOMEM;
1853
1854	flow_counter = mlx5_fc_create(mdev, false);
1855	if (IS_ERR(flow_counter)) {
1856		err = PTR_ERR(flow_counter);
1857		mlx5_core_err(mdev,
1858			      "Failed to create MACsec Rx encrypt flow counter, err(%d)\n",
1859			      err);
1860		goto err_encrypt_counter;
1861	}
1862
1863	rx_tables = &rx_fs->tables;
1864	rx_tables->check_rule_counter = flow_counter;
1865
1866	flow_counter = mlx5_fc_create(mdev, false);
1867	if (IS_ERR(flow_counter)) {
1868		err = PTR_ERR(flow_counter);
1869		mlx5_core_err(mdev,
1870			      "Failed to create MACsec Rx drop flow counter, err(%d)\n",
1871			      err);
1872		goto err_drop_counter;
1873	}
1874	rx_tables->check_miss_rule_counter = flow_counter;
1875
1876	macsec_fs->rx_fs = rx_fs;
1877
1878	return 0;
1879
1880err_drop_counter:
1881	mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
1882	rx_tables->check_rule_counter = NULL;
1883
1884err_encrypt_counter:
1885	kfree(rx_fs);
1886	macsec_fs->rx_fs = NULL;
1887
1888	return err;
1889}
1890
1891static void macsec_fs_rx_cleanup(struct mlx5_macsec_fs *macsec_fs)
1892{
1893	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
1894	struct mlx5_core_dev *mdev = macsec_fs->mdev;
1895	struct mlx5_macsec_tables *rx_tables;
1896
1897	if (!rx_fs)
1898		return;
1899
1900	rx_tables = &rx_fs->tables;
1901
1902	if (rx_tables->refcnt) {
1903		mlx5_core_err(mdev,
1904			      "Can't destroy MACsec offload rx_fs, refcnt(%u) isn't 0\n",
1905			      rx_tables->refcnt);
1906		return;
1907	}
1908
1909	if (rx_tables->check_miss_rule_counter) {
1910		mlx5_fc_destroy(mdev, rx_tables->check_miss_rule_counter);
1911		rx_tables->check_miss_rule_counter = NULL;
1912	}
1913
1914	if (rx_tables->check_rule_counter) {
1915		mlx5_fc_destroy(mdev, rx_tables->check_rule_counter);
1916		rx_tables->check_rule_counter = NULL;
1917	}
1918
1919	kfree(rx_fs);
1920	macsec_fs->rx_fs = NULL;
1921}
1922
1923static void set_ipaddr_spec_v4(struct sockaddr_in *in, struct mlx5_flow_spec *spec, bool is_dst_ip)
1924{
1925	MLX5_SET(fte_match_param, spec->match_value,
1926		 outer_headers.ip_version, MLX5_FS_IPV4_VERSION);
1927
1928	if (is_dst_ip) {
1929		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
1930				 outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
1931		memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
1932				    outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
1933		       &in->sin_addr.s_addr, 4);
1934	} else {
1935		MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
1936				 outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4);
1937		memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
1938				    outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4),
1939		       &in->sin_addr.s_addr, 4);
1940	}
1941}
1942
1943static void set_ipaddr_spec_v6(struct sockaddr_in6 *in6, struct mlx5_flow_spec *spec,
1944			       bool is_dst_ip)
1945{
1946	MLX5_SET(fte_match_param, spec->match_value,
1947		 outer_headers.ip_version, MLX5_FS_IPV6_VERSION);
1948
1949	if (is_dst_ip) {
1950		memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1951				    outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
1952		       0xff, 16);
1953		memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
1954				    outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
1955		       &in6->sin6_addr, 16);
1956	} else {
1957		memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
1958				    outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
1959		       0xff, 16);
1960		memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
1961				    outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
1962		       &in6->sin6_addr, 16);
1963	}
1964}
1965
1966static void set_ipaddr_spec(const struct sockaddr *addr,
1967			    struct mlx5_flow_spec *spec, bool is_dst_ip)
1968{
1969	struct sockaddr_in6 *in6;
1970
1971	spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
1972	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
1973			 outer_headers.ip_version);
1974
1975	if (addr->sa_family == AF_INET) {
1976		struct sockaddr_in *in = (struct sockaddr_in *)addr;
1977
1978		set_ipaddr_spec_v4(in, spec, is_dst_ip);
1979		return;
1980	}
1981
1982	in6 = (struct sockaddr_in6 *)addr;
1983	set_ipaddr_spec_v6(in6, spec, is_dst_ip);
1984}
1985
1986static void macsec_fs_del_roce_rule_rx(struct mlx5_roce_macsec_rx_rule *rx_rule)
1987{
1988	mlx5_del_flow_rules(rx_rule->op);
1989	mlx5_del_flow_rules(rx_rule->ip);
1990	list_del(&rx_rule->entry);
1991	kfree(rx_rule);
1992}
1993
1994static void macsec_fs_del_roce_rules_rx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id,
1995					struct list_head *rx_rules_list)
1996{
1997	struct mlx5_roce_macsec_rx_rule *rx_rule, *next;
1998
1999	if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev))
2000		return;
2001
2002	list_for_each_entry_safe(rx_rule, next, rx_rules_list, entry) {
2003		if (rx_rule->fs_id == fs_id)
2004			macsec_fs_del_roce_rule_rx(rx_rule);
2005	}
2006}
2007
2008static void macsec_fs_del_roce_rule_tx(struct mlx5_core_dev *mdev,
2009				       struct mlx5_roce_macsec_tx_rule *tx_rule)
2010{
2011	mlx5_del_flow_rules(tx_rule->rule);
2012	mlx5_modify_header_dealloc(mdev, tx_rule->meta_modhdr);
2013	list_del(&tx_rule->entry);
2014	kfree(tx_rule);
2015}
2016
2017static void macsec_fs_del_roce_rules_tx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id,
2018					struct list_head *tx_rules_list)
2019{
2020	struct mlx5_roce_macsec_tx_rule *tx_rule, *next;
2021
2022	if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev))
2023		return;
2024
2025	list_for_each_entry_safe(tx_rule, next, tx_rules_list, entry) {
2026		if (tx_rule->fs_id == fs_id)
2027			macsec_fs_del_roce_rule_tx(macsec_fs->mdev, tx_rule);
2028	}
2029}
2030
2031void mlx5_macsec_fs_get_stats_fill(struct mlx5_macsec_fs *macsec_fs, void *macsec_stats)
2032{
2033	struct mlx5_macsec_stats *stats = (struct mlx5_macsec_stats *)macsec_stats;
2034	struct mlx5_macsec_tables *tx_tables = &macsec_fs->tx_fs->tables;
2035	struct mlx5_macsec_tables *rx_tables = &macsec_fs->rx_fs->tables;
2036	struct mlx5_core_dev *mdev = macsec_fs->mdev;
2037
2038	if (tx_tables->check_rule_counter)
2039		mlx5_fc_query(mdev, tx_tables->check_rule_counter,
2040			      &stats->macsec_tx_pkts, &stats->macsec_tx_bytes);
2041
2042	if (tx_tables->check_miss_rule_counter)
2043		mlx5_fc_query(mdev, tx_tables->check_miss_rule_counter,
2044			      &stats->macsec_tx_pkts_drop, &stats->macsec_tx_bytes_drop);
2045
2046	if (rx_tables->check_rule_counter)
2047		mlx5_fc_query(mdev, rx_tables->check_rule_counter,
2048			      &stats->macsec_rx_pkts, &stats->macsec_rx_bytes);
2049
2050	if (rx_tables->check_miss_rule_counter)
2051		mlx5_fc_query(mdev, rx_tables->check_miss_rule_counter,
2052			      &stats->macsec_rx_pkts_drop, &stats->macsec_rx_bytes_drop);
2053}
2054
2055struct mlx5_macsec_stats *mlx5_macsec_fs_get_stats(struct mlx5_macsec_fs *macsec_fs)
2056{
2057	if (!macsec_fs)
2058		return NULL;
2059
2060	return &macsec_fs->stats;
2061}
2062
2063u32 mlx5_macsec_fs_get_fs_id_from_hashtable(struct mlx5_macsec_fs *macsec_fs, sci_t *sci)
2064{
2065	struct mlx5_fs_id *mlx5_fs_id;
2066	u32 fs_id = 0;
2067
2068	rcu_read_lock();
2069	mlx5_fs_id = rhashtable_lookup(&macsec_fs->sci_hash, sci, rhash_sci);
2070	if (mlx5_fs_id)
2071		fs_id = mlx5_fs_id->id;
2072	rcu_read_unlock();
2073
2074	return fs_id;
2075}
2076
2077union mlx5_macsec_rule *
2078mlx5_macsec_fs_add_rule(struct mlx5_macsec_fs *macsec_fs,
2079			const struct macsec_context *macsec_ctx,
2080			struct mlx5_macsec_rule_attrs *attrs,
2081			u32 *sa_fs_id)
2082{
2083	struct mlx5_macsec_event_data data = {.macsec_fs = macsec_fs,
2084					      .macdev = macsec_ctx->secy->netdev,
2085					      .is_tx =
2086					      (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT)
2087	};
2088	union mlx5_macsec_rule *macsec_rule;
2089	u32 tx_new_fs_id;
2090
2091	macsec_rule = (attrs->action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
2092		macsec_fs_tx_add_rule(macsec_fs, macsec_ctx, attrs, &tx_new_fs_id) :
2093		macsec_fs_rx_add_rule(macsec_fs, macsec_ctx, attrs, *sa_fs_id);
2094
2095	data.fs_id = (data.is_tx) ? tx_new_fs_id : *sa_fs_id;
2096	if (macsec_rule)
2097		blocking_notifier_call_chain(&macsec_fs->mdev->macsec_nh,
2098					     MLX5_DRIVER_EVENT_MACSEC_SA_ADDED,
2099					     &data);
2100
2101	return macsec_rule;
2102}
2103
2104void mlx5_macsec_fs_del_rule(struct mlx5_macsec_fs *macsec_fs,
2105			     union mlx5_macsec_rule *macsec_rule,
2106			     int action, void *macdev, u32 sa_fs_id)
2107{
2108	struct mlx5_macsec_event_data data = {.macsec_fs = macsec_fs,
2109					      .macdev = macdev,
2110					      .is_tx = (action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT)
2111	};
2112
2113	data.fs_id = (data.is_tx) ? macsec_rule->tx_rule.fs_id : sa_fs_id;
2114	blocking_notifier_call_chain(&macsec_fs->mdev->macsec_nh,
2115				     MLX5_DRIVER_EVENT_MACSEC_SA_DELETED,
2116				     &data);
2117
2118	(action == MLX5_ACCEL_MACSEC_ACTION_ENCRYPT) ?
2119		macsec_fs_tx_del_rule(macsec_fs, &macsec_rule->tx_rule, macdev) :
2120		macsec_fs_rx_del_rule(macsec_fs, &macsec_rule->rx_rule, macdev, sa_fs_id);
2121}
2122
2123static int mlx5_macsec_fs_add_roce_rule_rx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, u16 gid_idx,
2124					   const struct sockaddr *addr,
2125					   struct list_head *rx_rules_list)
2126{
2127	struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs;
2128	struct mlx5_roce_macsec_rx_rule *rx_rule;
2129	struct mlx5_flow_destination dest = {};
2130	struct mlx5_flow_act flow_act = {};
2131	struct mlx5_flow_handle *new_rule;
2132	struct mlx5_flow_spec *spec;
2133	int err = 0;
2134
2135	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2136	if (!spec)
2137		return -ENOMEM;
2138
2139	rx_rule = kzalloc(sizeof(*rx_rule), GFP_KERNEL);
2140	if (!rx_rule) {
2141		err = -ENOMEM;
2142		goto out;
2143	}
2144
2145	set_ipaddr_spec(addr, spec, true);
2146
2147	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2148	dest.ft = rx_fs->roce.ft_macsec_op_check;
2149	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2150	new_rule = mlx5_add_flow_rules(rx_fs->roce.ft_ip_check, spec, &flow_act,
2151				       &dest, 1);
2152	if (IS_ERR(new_rule)) {
2153		err = PTR_ERR(new_rule);
2154		goto ip_rule_err;
2155	}
2156	rx_rule->ip = new_rule;
2157
2158	memset(&flow_act, 0, sizeof(flow_act));
2159	memset(spec, 0, sizeof(*spec));
2160
2161	spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
2162	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_c_5);
2163	MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_5,
2164		 macsec_fs_set_rx_fs_id(fs_id));
2165	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
2166	new_rule = mlx5_add_flow_rules(rx_fs->roce.ft_macsec_op_check, spec, &flow_act,
2167				       NULL, 0);
2168	if (IS_ERR(new_rule)) {
2169		err = PTR_ERR(new_rule);
2170		goto op_rule_err;
2171	}
2172	rx_rule->op = new_rule;
2173	rx_rule->gid_idx = gid_idx;
2174	rx_rule->fs_id = fs_id;
2175	list_add_tail(&rx_rule->entry, rx_rules_list);
2176
2177	goto out;
2178
2179op_rule_err:
2180	mlx5_del_flow_rules(rx_rule->ip);
2181	rx_rule->ip = NULL;
2182ip_rule_err:
2183	kfree(rx_rule);
2184out:
2185	kvfree(spec);
2186	return err;
2187}
2188
2189static int mlx5_macsec_fs_add_roce_rule_tx(struct mlx5_macsec_fs *macsec_fs, u32 fs_id, u16 gid_idx,
2190					   const struct sockaddr *addr,
2191					   struct list_head *tx_rules_list)
2192{
2193	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
2194	struct mlx5_macsec_tx *tx_fs = macsec_fs->tx_fs;
2195	struct mlx5_core_dev *mdev = macsec_fs->mdev;
2196	struct mlx5_modify_hdr *modify_hdr = NULL;
2197	struct mlx5_roce_macsec_tx_rule *tx_rule;
2198	struct mlx5_flow_destination dest = {};
2199	struct mlx5_flow_act flow_act = {};
2200	struct mlx5_flow_handle *new_rule;
2201	struct mlx5_flow_spec *spec;
2202	int err = 0;
2203
2204	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2205	if (!spec)
2206		return -ENOMEM;
2207
2208	tx_rule = kzalloc(sizeof(*tx_rule), GFP_KERNEL);
2209	if (!tx_rule) {
2210		err = -ENOMEM;
2211		goto out;
2212	}
2213
2214	set_ipaddr_spec(addr, spec, false);
2215
2216	MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
2217	MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_A);
2218	MLX5_SET(set_action_in, action, data,
2219		 mlx5_macsec_fs_set_tx_fs_id(fs_id));
2220	MLX5_SET(set_action_in, action, offset,
2221		 MLX5_ETH_WQE_FT_META_MACSEC_SHIFT);
2222	MLX5_SET(set_action_in, action, length, 8);
2223
2224	modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC,
2225					      1, action);
2226	if (IS_ERR(modify_hdr)) {
2227		err = PTR_ERR(modify_hdr);
2228		mlx5_core_err(mdev, "Fail to alloc ROCE MACsec set modify_header_id err=%d\n",
2229			      err);
2230		modify_hdr = NULL;
2231		goto modify_hdr_err;
2232	}
2233	tx_rule->meta_modhdr = modify_hdr;
2234
2235	flow_act.modify_hdr = modify_hdr;
2236	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
2237
2238	dest.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE;
2239	dest.ft = tx_fs->tables.ft_crypto.t;
2240	new_rule = mlx5_add_flow_rules(tx_fs->ft_rdma_tx, spec, &flow_act, &dest, 1);
2241	if (IS_ERR(new_rule)) {
2242		err = PTR_ERR(new_rule);
2243		mlx5_core_err(mdev, "Failed to add ROCE TX rule, err=%d\n", err);
2244		goto rule_err;
2245	}
2246	tx_rule->rule = new_rule;
2247	tx_rule->gid_idx = gid_idx;
2248	tx_rule->fs_id = fs_id;
2249	list_add_tail(&tx_rule->entry, tx_rules_list);
2250
2251	goto out;
2252
2253rule_err:
2254	mlx5_modify_header_dealloc(mdev, tx_rule->meta_modhdr);
2255modify_hdr_err:
2256	kfree(tx_rule);
2257out:
2258	kvfree(spec);
2259	return err;
2260}
2261
2262void mlx5_macsec_del_roce_rule(u16 gid_idx, struct mlx5_macsec_fs *macsec_fs,
2263			       struct list_head *tx_rules_list, struct list_head *rx_rules_list)
2264{
2265	struct mlx5_roce_macsec_rx_rule *rx_rule, *next_rx;
2266	struct mlx5_roce_macsec_tx_rule *tx_rule, *next_tx;
2267
2268	list_for_each_entry_safe(tx_rule, next_tx, tx_rules_list, entry) {
2269		if (tx_rule->gid_idx == gid_idx)
2270			macsec_fs_del_roce_rule_tx(macsec_fs->mdev, tx_rule);
2271	}
2272
2273	list_for_each_entry_safe(rx_rule, next_rx, rx_rules_list, entry) {
2274		if (rx_rule->gid_idx == gid_idx)
2275			macsec_fs_del_roce_rule_rx(rx_rule);
2276	}
2277}
2278EXPORT_SYMBOL_GPL(mlx5_macsec_del_roce_rule);
2279
2280int mlx5_macsec_add_roce_rule(void *macdev, const struct sockaddr *addr, u16 gid_idx,
2281			      struct list_head *tx_rules_list, struct list_head *rx_rules_list,
2282			      struct mlx5_macsec_fs *macsec_fs)
2283{
2284	struct mlx5_macsec_device *iter, *macsec_device = NULL;
2285	struct mlx5_core_dev *mdev = macsec_fs->mdev;
2286	struct mlx5_fs_id *fs_id_iter;
2287	unsigned long index = 0;
2288	int err;
2289
2290	list_for_each_entry(iter, &macsec_fs->macsec_devices_list, macsec_devices_list_entry) {
2291		if (iter->macdev == macdev) {
2292			macsec_device = iter;
2293			break;
2294		}
2295	}
2296
2297	if (!macsec_device)
2298		return 0;
2299
2300	xa_for_each(&macsec_device->tx_id_xa, index, fs_id_iter) {
2301		err = mlx5_macsec_fs_add_roce_rule_tx(macsec_fs, fs_id_iter->id, gid_idx, addr,
2302						      tx_rules_list);
2303		if (err) {
2304			mlx5_core_err(mdev, "MACsec offload: Failed to add roce TX rule\n");
2305			goto out;
2306		}
2307	}
2308
2309	index = 0;
2310	xa_for_each(&macsec_device->rx_id_xa, index, fs_id_iter) {
2311		err = mlx5_macsec_fs_add_roce_rule_rx(macsec_fs, fs_id_iter->id, gid_idx, addr,
2312						      rx_rules_list);
2313		if (err) {
2314			mlx5_core_err(mdev, "MACsec offload: Failed to add roce TX rule\n");
2315			goto out;
2316		}
2317	}
2318
2319	return 0;
2320out:
2321	mlx5_macsec_del_roce_rule(gid_idx, macsec_fs, tx_rules_list, rx_rules_list);
2322	return err;
2323}
2324EXPORT_SYMBOL_GPL(mlx5_macsec_add_roce_rule);
2325
2326void mlx5_macsec_add_roce_sa_rules(u32 fs_id, const struct sockaddr *addr, u16 gid_idx,
2327				   struct list_head *tx_rules_list,
2328				   struct list_head *rx_rules_list,
2329				   struct mlx5_macsec_fs *macsec_fs, bool is_tx)
2330{
2331	(is_tx) ?
2332		mlx5_macsec_fs_add_roce_rule_tx(macsec_fs, fs_id, gid_idx, addr,
2333						tx_rules_list) :
2334		mlx5_macsec_fs_add_roce_rule_rx(macsec_fs, fs_id, gid_idx, addr,
2335						rx_rules_list);
2336}
2337EXPORT_SYMBOL_GPL(mlx5_macsec_add_roce_sa_rules);
2338
2339void mlx5_macsec_del_roce_sa_rules(u32 fs_id, struct mlx5_macsec_fs *macsec_fs,
2340				   struct list_head *tx_rules_list,
2341				   struct list_head *rx_rules_list, bool is_tx)
2342{
2343	(is_tx) ?
2344		macsec_fs_del_roce_rules_tx(macsec_fs, fs_id, tx_rules_list) :
2345		macsec_fs_del_roce_rules_rx(macsec_fs, fs_id, rx_rules_list);
2346}
2347EXPORT_SYMBOL_GPL(mlx5_macsec_del_roce_sa_rules);
2348
2349void mlx5_macsec_fs_cleanup(struct mlx5_macsec_fs *macsec_fs)
2350{
2351	macsec_fs_rx_cleanup(macsec_fs);
2352	macsec_fs_tx_cleanup(macsec_fs);
2353	rhashtable_destroy(&macsec_fs->fs_id_hash);
2354	rhashtable_destroy(&macsec_fs->sci_hash);
2355	kfree(macsec_fs);
2356}
2357
2358struct mlx5_macsec_fs *
2359mlx5_macsec_fs_init(struct mlx5_core_dev *mdev)
2360{
2361	struct mlx5_macsec_fs *macsec_fs;
2362	int err;
2363
2364	macsec_fs = kzalloc(sizeof(*macsec_fs), GFP_KERNEL);
2365	if (!macsec_fs)
2366		return NULL;
2367
2368	macsec_fs->mdev = mdev;
2369
2370	err = rhashtable_init(&macsec_fs->sci_hash, &rhash_sci);
2371	if (err) {
2372		mlx5_core_err(mdev, "MACsec offload: Failed to init SCI hash table, err=%d\n",
2373			      err);
2374		goto err_hash;
2375	}
2376
2377	err = rhashtable_init(&macsec_fs->fs_id_hash, &rhash_fs_id);
2378	if (err) {
2379		mlx5_core_err(mdev, "MACsec offload: Failed to init FS_ID hash table, err=%d\n",
2380			      err);
2381		goto sci_hash_cleanup;
2382	}
2383
2384	err = macsec_fs_tx_init(macsec_fs);
2385	if (err) {
2386		mlx5_core_err(mdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
2387		goto fs_id_hash_cleanup;
2388	}
2389
2390	err = macsec_fs_rx_init(macsec_fs);
2391	if (err) {
2392		mlx5_core_err(mdev, "MACsec offload: Failed to init tx_fs, err=%d\n", err);
2393		goto tx_cleanup;
2394	}
2395
2396	BLOCKING_INIT_NOTIFIER_HEAD(&mdev->macsec_nh);
2397
2398	return macsec_fs;
2399
2400tx_cleanup:
2401	macsec_fs_tx_cleanup(macsec_fs);
2402fs_id_hash_cleanup:
2403	rhashtable_destroy(&macsec_fs->fs_id_hash);
2404sci_hash_cleanup:
2405	rhashtable_destroy(&macsec_fs->sci_hash);
2406err_hash:
2407	kfree(macsec_fs);
2408	return NULL;
2409}
~/ Read-only file preview.