1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 4#include <linux/mlx5/device.h> 5#include <linux/mlx5/mlx5_ifc.h> 6#include <linux/xarray.h> 7#include <linux/if_vlan.h> 8 9#include "en.h" 10#include "lib/aso.h" 11#include "lib/crypto.h" 12#include "en_accel/macsec.h" 13 14#define MLX5_MACSEC_EPN_SCOPE_MID 0x80000000L 15#define MLX5E_MACSEC_ASO_CTX_SZ MLX5_ST_SZ_BYTES(macsec_aso) 16 17enum mlx5_macsec_aso_event_arm { 18 MLX5E_ASO_EPN_ARM = BIT(0), 19}; 20 21enum { 22 MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET, 23}; 24 25struct mlx5e_macsec_handle { 26 struct mlx5e_macsec *macsec; 27 u32 obj_id; 28 u8 idx; 29}; 30 31enum { 32 MLX5_MACSEC_EPN, 33}; 34 35struct mlx5e_macsec_aso_out { 36 u8 event_arm; 37 u32 mode_param; 38}; 39 40struct mlx5e_macsec_aso_in { 41 u8 mode; 42 u32 obj_id; 43}; 44 45struct mlx5e_macsec_epn_state { 46 u32 epn_msb; 47 u8 epn_enabled; 48 u8 overlap; 49}; 50 51struct mlx5e_macsec_async_work { 52 struct mlx5e_macsec *macsec; 53 struct mlx5_core_dev *mdev; 54 struct work_struct work; 55 u32 obj_id; 56}; 57 58struct mlx5e_macsec_sa { 59 bool active; 60 u8 assoc_num; 61 u32 macsec_obj_id; 62 u32 enc_key_id; 63 u32 next_pn; 64 sci_t sci; 65 ssci_t ssci; 66 salt_t salt; 67 68 union mlx5_macsec_rule *macsec_rule; 69 struct rcu_head rcu_head; 70 struct mlx5e_macsec_epn_state epn_state; 71}; 72 73struct mlx5e_macsec_rx_sc; 74struct mlx5e_macsec_rx_sc_xarray_element { 75 u32 fs_id; 76 struct mlx5e_macsec_rx_sc *rx_sc; 77}; 78 79struct mlx5e_macsec_rx_sc { 80 bool active; 81 sci_t sci; 82 struct mlx5e_macsec_sa *rx_sa[MACSEC_NUM_AN]; 83 struct list_head rx_sc_list_element; 84 struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element; 85 struct metadata_dst *md_dst; 86 struct rcu_head rcu_head; 87}; 88 89struct mlx5e_macsec_umr { 90 u8 __aligned(64) ctx[MLX5_ST_SZ_BYTES(macsec_aso)]; 91 dma_addr_t dma_addr; 92 u32 mkey; 93}; 94 95struct mlx5e_macsec_aso { 96 /* ASO */ 97 struct mlx5_aso *maso; 98 /* Protects macsec ASO */ 99 struct mutex aso_lock; 100 /* UMR */ 101 struct mlx5e_macsec_umr *umr; 102 103 u32 pdn; 104}; 105 106struct mlx5e_macsec_device { 107 const struct net_device *netdev; 108 struct mlx5e_macsec_sa *tx_sa[MACSEC_NUM_AN]; 109 struct list_head macsec_rx_sc_list_head; 110 unsigned char *dev_addr; 111 struct list_head macsec_device_list_element; 112}; 113 114struct mlx5e_macsec { 115 struct list_head macsec_device_list_head; 116 int num_of_devices; 117 struct mutex lock; /* Protects mlx5e_macsec internal contexts */ 118 119 /* Rx fs_id -> rx_sc mapping */ 120 struct xarray sc_xarray; 121 122 struct mlx5_core_dev *mdev; 123 124 /* ASO */ 125 struct mlx5e_macsec_aso aso; 126 127 struct notifier_block nb; 128 struct workqueue_struct *wq; 129}; 130 131struct mlx5_macsec_obj_attrs { 132 u32 aso_pdn; 133 u32 next_pn; 134 __be64 sci; 135 u32 enc_key_id; 136 bool encrypt; 137 struct mlx5e_macsec_epn_state epn_state; 138 salt_t salt; 139 __be32 ssci; 140 bool replay_protect; 141 u32 replay_window; 142}; 143 144struct mlx5_aso_ctrl_param { 145 u8 data_mask_mode; 146 u8 condition_0_operand; 147 u8 condition_1_operand; 148 u8 condition_0_offset; 149 u8 condition_1_offset; 150 u8 data_offset; 151 u8 condition_operand; 152 u32 condition_0_data; 153 u32 condition_0_mask; 154 u32 condition_1_data; 155 u32 condition_1_mask; 156 u64 bitwise_data; 157 u64 data_mask; 158}; 159 160static int mlx5e_macsec_aso_reg_mr(struct mlx5_core_dev *mdev, struct mlx5e_macsec_aso *aso) 161{ 162 struct mlx5e_macsec_umr *umr; 163 struct device *dma_device; 164 dma_addr_t dma_addr; 165 int err; 166 167 umr = kzalloc(sizeof(*umr), GFP_KERNEL); 168 if (!umr) { 169 err = -ENOMEM; 170 return err; 171 } 172 173 dma_device = mlx5_core_dma_dev(mdev); 174 dma_addr = dma_map_single(dma_device, umr->ctx, sizeof(umr->ctx), DMA_BIDIRECTIONAL); 175 err = dma_mapping_error(dma_device, dma_addr); 176 if (err) { 177 mlx5_core_err(mdev, "Can't map dma device, err=%d\n", err); 178 goto out_dma; 179 } 180 181 err = mlx5e_create_mkey(mdev, aso->pdn, &umr->mkey); 182 if (err) { 183 mlx5_core_err(mdev, "Can't create mkey, err=%d\n", err); 184 goto out_mkey; 185 } 186 187 umr->dma_addr = dma_addr; 188 189 aso->umr = umr; 190 191 return 0; 192 193out_mkey: 194 dma_unmap_single(dma_device, dma_addr, sizeof(umr->ctx), DMA_BIDIRECTIONAL); 195out_dma: 196 kfree(umr); 197 return err; 198} 199 200static void mlx5e_macsec_aso_dereg_mr(struct mlx5_core_dev *mdev, struct mlx5e_macsec_aso *aso) 201{ 202 struct mlx5e_macsec_umr *umr = aso->umr; 203 204 mlx5_core_destroy_mkey(mdev, umr->mkey); 205 dma_unmap_single(&mdev->pdev->dev, umr->dma_addr, sizeof(umr->ctx), DMA_BIDIRECTIONAL); 206 kfree(umr); 207} 208 209static int macsec_set_replay_protection(struct mlx5_macsec_obj_attrs *attrs, void *aso_ctx) 210{ 211 u8 window_sz; 212 213 if (!attrs->replay_protect) 214 return 0; 215 216 switch (attrs->replay_window) { 217 case 256: 218 window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_256BIT; 219 break; 220 case 128: 221 window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_128BIT; 222 break; 223 case 64: 224 window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_64BIT; 225 break; 226 case 32: 227 window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_32BIT; 228 break; 229 default: 230 return -EINVAL; 231 } 232 MLX5_SET(macsec_aso, aso_ctx, window_size, window_sz); 233 MLX5_SET(macsec_aso, aso_ctx, mode, MLX5_MACSEC_ASO_REPLAY_PROTECTION); 234 235 return 0; 236} 237 238static int mlx5e_macsec_create_object(struct mlx5_core_dev *mdev, 239 struct mlx5_macsec_obj_attrs *attrs, 240 bool is_tx, 241 u32 *macsec_obj_id) 242{ 243 u32 in[MLX5_ST_SZ_DW(create_macsec_obj_in)] = {}; 244 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 245 void *aso_ctx; 246 void *obj; 247 int err; 248 249 obj = MLX5_ADDR_OF(create_macsec_obj_in, in, macsec_object); 250 aso_ctx = MLX5_ADDR_OF(macsec_offload_obj, obj, macsec_aso); 251 252 MLX5_SET(macsec_offload_obj, obj, confidentiality_en, attrs->encrypt); 253 MLX5_SET(macsec_offload_obj, obj, dekn, attrs->enc_key_id); 254 MLX5_SET(macsec_offload_obj, obj, aso_return_reg, MLX5_MACSEC_ASO_REG_C_4_5); 255 MLX5_SET(macsec_offload_obj, obj, macsec_aso_access_pd, attrs->aso_pdn); 256 MLX5_SET(macsec_aso, aso_ctx, mode_parameter, attrs->next_pn); 257 258 /* Epn */ 259 if (attrs->epn_state.epn_enabled) { 260 void *salt_p; 261 int i; 262 263 MLX5_SET(macsec_aso, aso_ctx, epn_event_arm, 1); 264 MLX5_SET(macsec_offload_obj, obj, epn_en, 1); 265 MLX5_SET(macsec_offload_obj, obj, epn_msb, attrs->epn_state.epn_msb); 266 MLX5_SET(macsec_offload_obj, obj, epn_overlap, attrs->epn_state.overlap); 267 MLX5_SET64(macsec_offload_obj, obj, sci, (__force u64)attrs->ssci); 268 salt_p = MLX5_ADDR_OF(macsec_offload_obj, obj, salt); 269 for (i = 0; i < 3 ; i++) 270 memcpy((u32 *)salt_p + i, &attrs->salt.bytes[4 * (2 - i)], 4); 271 } else { 272 MLX5_SET64(macsec_offload_obj, obj, sci, (__force u64)(attrs->sci)); 273 } 274 275 MLX5_SET(macsec_aso, aso_ctx, valid, 0x1); 276 if (is_tx) { 277 MLX5_SET(macsec_aso, aso_ctx, mode, MLX5_MACSEC_ASO_INC_SN); 278 } else { 279 err = macsec_set_replay_protection(attrs, aso_ctx); 280 if (err) 281 return err; 282 } 283 284 /* general object fields set */ 285 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 286 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC); 287 288 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 289 if (err) { 290 mlx5_core_err(mdev, 291 "MACsec offload: Failed to create MACsec object (err = %d)\n", 292 err); 293 return err; 294 } 295 296 *macsec_obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 297 298 return err; 299} 300 301static void mlx5e_macsec_destroy_object(struct mlx5_core_dev *mdev, u32 macsec_obj_id) 302{ 303 u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {}; 304 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 305 306 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 307 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC); 308 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, macsec_obj_id); 309 310 mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 311} 312 313static void mlx5e_macsec_cleanup_sa_fs(struct mlx5e_macsec *macsec, 314 struct mlx5e_macsec_sa *sa, bool is_tx, 315 struct net_device *netdev, u32 fs_id) 316{ 317 int action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : 318 MLX5_ACCEL_MACSEC_ACTION_DECRYPT; 319 320 if (!sa->macsec_rule) 321 return; 322 323 mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action, netdev, 324 fs_id); 325 sa->macsec_rule = NULL; 326} 327 328static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec, 329 struct mlx5e_macsec_sa *sa, bool is_tx, 330 struct net_device *netdev, u32 fs_id) 331{ 332 mlx5e_macsec_cleanup_sa_fs(macsec, sa, is_tx, netdev, fs_id); 333 mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id); 334} 335 336static int mlx5e_macsec_init_sa_fs(struct macsec_context *ctx, 337 struct mlx5e_macsec_sa *sa, bool encrypt, 338 bool is_tx, u32 *fs_id) 339{ 340 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 341 struct mlx5_macsec_fs *macsec_fs = priv->mdev->macsec_fs; 342 struct mlx5_macsec_rule_attrs rule_attrs; 343 union mlx5_macsec_rule *macsec_rule; 344 345 rule_attrs.macsec_obj_id = sa->macsec_obj_id; 346 rule_attrs.sci = sa->sci; 347 rule_attrs.assoc_num = sa->assoc_num; 348 rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT : 349 MLX5_ACCEL_MACSEC_ACTION_DECRYPT; 350 351 macsec_rule = mlx5_macsec_fs_add_rule(macsec_fs, ctx, &rule_attrs, fs_id); 352 if (!macsec_rule) 353 return -ENOMEM; 354 355 sa->macsec_rule = macsec_rule; 356 357 return 0; 358} 359 360static int mlx5e_macsec_init_sa(struct macsec_context *ctx, 361 struct mlx5e_macsec_sa *sa, 362 bool encrypt, bool is_tx, u32 *fs_id) 363{ 364 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 365 struct mlx5e_macsec *macsec = priv->macsec; 366 struct mlx5_core_dev *mdev = priv->mdev; 367 struct mlx5_macsec_obj_attrs obj_attrs; 368 int err; 369 370 obj_attrs.next_pn = sa->next_pn; 371 obj_attrs.sci = cpu_to_be64((__force u64)sa->sci); 372 obj_attrs.enc_key_id = sa->enc_key_id; 373 obj_attrs.encrypt = encrypt; 374 obj_attrs.aso_pdn = macsec->aso.pdn; 375 obj_attrs.epn_state = sa->epn_state; 376 377 if (sa->epn_state.epn_enabled) { 378 obj_attrs.ssci = cpu_to_be32((__force u32)sa->ssci); 379 memcpy(&obj_attrs.salt, &sa->salt, sizeof(sa->salt)); 380 } 381 382 obj_attrs.replay_window = ctx->secy->replay_window; 383 obj_attrs.replay_protect = ctx->secy->replay_protect; 384 385 err = mlx5e_macsec_create_object(mdev, &obj_attrs, is_tx, &sa->macsec_obj_id); 386 if (err) 387 return err; 388 389 if (sa->active) { 390 err = mlx5e_macsec_init_sa_fs(ctx, sa, encrypt, is_tx, fs_id); 391 if (err) 392 goto destroy_macsec_object; 393 } 394 395 return 0; 396 397destroy_macsec_object: 398 mlx5e_macsec_destroy_object(mdev, sa->macsec_obj_id); 399 400 return err; 401} 402 403static struct mlx5e_macsec_rx_sc * 404mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head *list, sci_t sci) 405{ 406 struct mlx5e_macsec_rx_sc *iter; 407 408 list_for_each_entry_rcu(iter, list, rx_sc_list_element) { 409 if (iter->sci == sci) 410 return iter; 411 } 412 413 return NULL; 414} 415 416static int macsec_rx_sa_active_update(struct macsec_context *ctx, 417 struct mlx5e_macsec_sa *rx_sa, 418 bool active, u32 *fs_id) 419{ 420 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 421 struct mlx5e_macsec *macsec = priv->macsec; 422 int err = 0; 423 424 if (rx_sa->active == active) 425 return 0; 426 427 rx_sa->active = active; 428 if (!active) { 429 mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, *fs_id); 430 return 0; 431 } 432 433 err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, fs_id); 434 if (err) 435 rx_sa->active = false; 436 437 return err; 438} 439 440static bool mlx5e_macsec_secy_features_validate(struct macsec_context *ctx) 441{ 442 const struct net_device *netdev = ctx->netdev; 443 const struct macsec_secy *secy = ctx->secy; 444 445 if (secy->validate_frames != MACSEC_VALIDATE_STRICT) { 446 netdev_err(netdev, 447 "MACsec offload is supported only when validate_frame is in strict mode\n"); 448 return false; 449 } 450 451 if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN) { 452 netdev_err(netdev, "MACsec offload is supported only when icv_len is %d\n", 453 MACSEC_DEFAULT_ICV_LEN); 454 return false; 455 } 456 457 if (!secy->protect_frames) { 458 netdev_err(netdev, 459 "MACsec offload is supported only when protect_frames is set\n"); 460 return false; 461 } 462 463 if (!ctx->secy->tx_sc.encrypt) { 464 netdev_err(netdev, "MACsec offload: encrypt off isn't supported\n"); 465 return false; 466 } 467 468 return true; 469} 470 471static struct mlx5e_macsec_device * 472mlx5e_macsec_get_macsec_device_context(const struct mlx5e_macsec *macsec, 473 const struct macsec_context *ctx) 474{ 475 struct mlx5e_macsec_device *iter; 476 const struct list_head *list; 477 478 list = &macsec->macsec_device_list_head; 479 list_for_each_entry_rcu(iter, list, macsec_device_list_element) { 480 if (iter->netdev == ctx->secy->netdev) 481 return iter; 482 } 483 484 return NULL; 485} 486 487static void update_macsec_epn(struct mlx5e_macsec_sa *sa, const struct macsec_key *key, 488 const pn_t *next_pn_halves, ssci_t ssci) 489{ 490 struct mlx5e_macsec_epn_state *epn_state = &sa->epn_state; 491 492 sa->ssci = ssci; 493 sa->salt = key->salt; 494 epn_state->epn_enabled = 1; 495 epn_state->epn_msb = next_pn_halves->upper; 496 epn_state->overlap = next_pn_halves->lower < MLX5_MACSEC_EPN_SCOPE_MID ? 0 : 1; 497} 498 499static int mlx5e_macsec_add_txsa(struct macsec_context *ctx) 500{ 501 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 502 const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc; 503 const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa; 504 const struct macsec_secy *secy = ctx->secy; 505 struct mlx5e_macsec_device *macsec_device; 506 struct mlx5_core_dev *mdev = priv->mdev; 507 u8 assoc_num = ctx->sa.assoc_num; 508 struct mlx5e_macsec_sa *tx_sa; 509 struct mlx5e_macsec *macsec; 510 int err = 0; 511 512 mutex_lock(&priv->macsec->lock); 513 514 macsec = priv->macsec; 515 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 516 if (!macsec_device) { 517 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 518 err = -EEXIST; 519 goto out; 520 } 521 522 if (macsec_device->tx_sa[assoc_num]) { 523 netdev_err(ctx->netdev, "MACsec offload tx_sa: %d already exist\n", assoc_num); 524 err = -EEXIST; 525 goto out; 526 } 527 528 tx_sa = kzalloc(sizeof(*tx_sa), GFP_KERNEL); 529 if (!tx_sa) { 530 err = -ENOMEM; 531 goto out; 532 } 533 534 tx_sa->active = ctx_tx_sa->active; 535 tx_sa->next_pn = ctx_tx_sa->next_pn_halves.lower; 536 tx_sa->sci = secy->sci; 537 tx_sa->assoc_num = assoc_num; 538 539 if (secy->xpn) 540 update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves, 541 ctx_tx_sa->ssci); 542 543 err = mlx5_create_encryption_key(mdev, ctx->sa.key, secy->key_len, 544 MLX5_ACCEL_OBJ_MACSEC_KEY, 545 &tx_sa->enc_key_id); 546 if (err) 547 goto destroy_sa; 548 549 macsec_device->tx_sa[assoc_num] = tx_sa; 550 if (!secy->operational) 551 goto out; 552 553 err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL); 554 if (err) 555 goto destroy_encryption_key; 556 557 mutex_unlock(&macsec->lock); 558 559 return 0; 560 561destroy_encryption_key: 562 macsec_device->tx_sa[assoc_num] = NULL; 563 mlx5_destroy_encryption_key(mdev, tx_sa->enc_key_id); 564destroy_sa: 565 kfree(tx_sa); 566out: 567 mutex_unlock(&macsec->lock); 568 569 return err; 570} 571 572static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx) 573{ 574 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 575 const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc; 576 const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa; 577 struct mlx5e_macsec_device *macsec_device; 578 u8 assoc_num = ctx->sa.assoc_num; 579 struct mlx5e_macsec_sa *tx_sa; 580 struct mlx5e_macsec *macsec; 581 struct net_device *netdev; 582 int err = 0; 583 584 mutex_lock(&priv->macsec->lock); 585 586 macsec = priv->macsec; 587 netdev = ctx->netdev; 588 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 589 if (!macsec_device) { 590 netdev_err(netdev, "MACsec offload: Failed to find device context\n"); 591 err = -EINVAL; 592 goto out; 593 } 594 595 tx_sa = macsec_device->tx_sa[assoc_num]; 596 if (!tx_sa) { 597 netdev_err(netdev, "MACsec offload: TX sa 0x%x doesn't exist\n", assoc_num); 598 err = -EEXIST; 599 goto out; 600 } 601 602 if (ctx->sa.update_pn) { 603 netdev_err(netdev, "MACsec offload: update TX sa %d PN isn't supported\n", 604 assoc_num); 605 err = -EINVAL; 606 goto out; 607 } 608 609 if (tx_sa->active == ctx_tx_sa->active) 610 goto out; 611 612 tx_sa->active = ctx_tx_sa->active; 613 if (tx_sa->assoc_num != tx_sc->encoding_sa) 614 goto out; 615 616 if (ctx_tx_sa->active) { 617 err = mlx5e_macsec_init_sa_fs(ctx, tx_sa, tx_sc->encrypt, true, NULL); 618 if (err) 619 goto out; 620 } else { 621 if (!tx_sa->macsec_rule) { 622 err = -EINVAL; 623 goto out; 624 } 625 626 mlx5e_macsec_cleanup_sa_fs(macsec, tx_sa, true, ctx->secy->netdev, 0); 627 } 628out: 629 mutex_unlock(&macsec->lock); 630 631 return err; 632} 633 634static int mlx5e_macsec_del_txsa(struct macsec_context *ctx) 635{ 636 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 637 struct mlx5e_macsec_device *macsec_device; 638 u8 assoc_num = ctx->sa.assoc_num; 639 struct mlx5e_macsec_sa *tx_sa; 640 struct mlx5e_macsec *macsec; 641 int err = 0; 642 643 mutex_lock(&priv->macsec->lock); 644 macsec = priv->macsec; 645 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 646 if (!macsec_device) { 647 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 648 err = -EINVAL; 649 goto out; 650 } 651 652 tx_sa = macsec_device->tx_sa[assoc_num]; 653 if (!tx_sa) { 654 netdev_err(ctx->netdev, "MACsec offload: TX sa 0x%x doesn't exist\n", assoc_num); 655 err = -EEXIST; 656 goto out; 657 } 658 659 mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); 660 mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id); 661 kfree_rcu_mightsleep(tx_sa); 662 macsec_device->tx_sa[assoc_num] = NULL; 663 664out: 665 mutex_unlock(&macsec->lock); 666 667 return err; 668} 669 670static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx) 671{ 672 struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element; 673 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 674 const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc; 675 struct mlx5e_macsec_device *macsec_device; 676 struct mlx5e_macsec_rx_sc *rx_sc; 677 struct list_head *rx_sc_list; 678 struct mlx5e_macsec *macsec; 679 int err = 0; 680 681 mutex_lock(&priv->macsec->lock); 682 macsec = priv->macsec; 683 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 684 if (!macsec_device) { 685 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 686 err = -EINVAL; 687 goto out; 688 } 689 690 rx_sc_list = &macsec_device->macsec_rx_sc_list_head; 691 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(rx_sc_list, ctx_rx_sc->sci); 692 if (rx_sc) { 693 netdev_err(ctx->netdev, "MACsec offload: rx_sc (sci %lld) already exists\n", 694 ctx_rx_sc->sci); 695 err = -EEXIST; 696 goto out; 697 } 698 699 rx_sc = kzalloc(sizeof(*rx_sc), GFP_KERNEL); 700 if (!rx_sc) { 701 err = -ENOMEM; 702 goto out; 703 } 704 705 sc_xarray_element = kzalloc(sizeof(*sc_xarray_element), GFP_KERNEL); 706 if (!sc_xarray_element) { 707 err = -ENOMEM; 708 goto destroy_rx_sc; 709 } 710 711 sc_xarray_element->rx_sc = rx_sc; 712 err = xa_alloc(&macsec->sc_xarray, &sc_xarray_element->fs_id, sc_xarray_element, 713 XA_LIMIT(1, MLX5_MACEC_RX_FS_ID_MAX), GFP_KERNEL); 714 if (err) { 715 if (err == -EBUSY) 716 netdev_err(ctx->netdev, 717 "MACsec offload: unable to create entry for RX SC (%d Rx SCs already allocated)\n", 718 MLX5_MACEC_RX_FS_ID_MAX); 719 goto destroy_sc_xarray_elemenet; 720 } 721 722 rx_sc->md_dst = metadata_dst_alloc(0, METADATA_MACSEC, GFP_KERNEL); 723 if (!rx_sc->md_dst) { 724 err = -ENOMEM; 725 goto erase_xa_alloc; 726 } 727 728 rx_sc->sci = ctx_rx_sc->sci; 729 rx_sc->active = ctx_rx_sc->active; 730 list_add_rcu(&rx_sc->rx_sc_list_element, rx_sc_list); 731 732 rx_sc->sc_xarray_element = sc_xarray_element; 733 rx_sc->md_dst->u.macsec_info.sci = rx_sc->sci; 734 mutex_unlock(&macsec->lock); 735 736 return 0; 737 738erase_xa_alloc: 739 xa_erase(&macsec->sc_xarray, sc_xarray_element->fs_id); 740destroy_sc_xarray_elemenet: 741 kfree(sc_xarray_element); 742destroy_rx_sc: 743 kfree(rx_sc); 744 745out: 746 mutex_unlock(&macsec->lock); 747 748 return err; 749} 750 751static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx) 752{ 753 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 754 const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc; 755 struct mlx5e_macsec_device *macsec_device; 756 struct mlx5e_macsec_rx_sc *rx_sc; 757 struct mlx5e_macsec_sa *rx_sa; 758 struct mlx5e_macsec *macsec; 759 struct list_head *list; 760 int i; 761 int err = 0; 762 763 mutex_lock(&priv->macsec->lock); 764 765 macsec = priv->macsec; 766 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 767 if (!macsec_device) { 768 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 769 err = -EINVAL; 770 goto out; 771 } 772 773 list = &macsec_device->macsec_rx_sc_list_head; 774 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx_rx_sc->sci); 775 if (!rx_sc) { 776 err = -EINVAL; 777 goto out; 778 } 779 780 if (rx_sc->active == ctx_rx_sc->active) 781 goto out; 782 783 rx_sc->active = ctx_rx_sc->active; 784 for (i = 0; i < MACSEC_NUM_AN; ++i) { 785 rx_sa = rx_sc->rx_sa[i]; 786 if (!rx_sa) 787 continue; 788 789 err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active, 790 &rx_sc->sc_xarray_element->fs_id); 791 if (err) 792 goto out; 793 } 794 795out: 796 mutex_unlock(&macsec->lock); 797 798 return err; 799} 800 801static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc, 802 struct net_device *netdev) 803{ 804 struct mlx5e_macsec_sa *rx_sa; 805 int i; 806 807 for (i = 0; i < MACSEC_NUM_AN; ++i) { 808 rx_sa = rx_sc->rx_sa[i]; 809 if (!rx_sa) 810 continue; 811 812 mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, netdev, 813 rx_sc->sc_xarray_element->fs_id); 814 mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id); 815 816 kfree(rx_sa); 817 rx_sc->rx_sa[i] = NULL; 818 } 819 820 /* At this point the relevant MACsec offload Rx rule already removed at 821 * mlx5e_macsec_cleanup_sa need to wait for datapath to finish current 822 * Rx related data propagating using xa_erase which uses rcu to sync, 823 * once fs_id is erased then this rx_sc is hidden from datapath. 824 */ 825 list_del_rcu(&rx_sc->rx_sc_list_element); 826 xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id); 827 metadata_dst_free(rx_sc->md_dst); 828 kfree(rx_sc->sc_xarray_element); 829 kfree_rcu_mightsleep(rx_sc); 830} 831 832static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx) 833{ 834 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 835 struct mlx5e_macsec_device *macsec_device; 836 struct mlx5e_macsec_rx_sc *rx_sc; 837 struct mlx5e_macsec *macsec; 838 struct list_head *list; 839 int err = 0; 840 841 mutex_lock(&priv->macsec->lock); 842 843 macsec = priv->macsec; 844 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 845 if (!macsec_device) { 846 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 847 err = -EINVAL; 848 goto out; 849 } 850 851 list = &macsec_device->macsec_rx_sc_list_head; 852 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx->rx_sc->sci); 853 if (!rx_sc) { 854 netdev_err(ctx->netdev, 855 "MACsec offload rx_sc sci %lld doesn't exist\n", 856 ctx->sa.rx_sa->sc->sci); 857 err = -EINVAL; 858 goto out; 859 } 860 861 macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev); 862out: 863 mutex_unlock(&macsec->lock); 864 865 return err; 866} 867 868static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx) 869{ 870 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 871 const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa; 872 struct mlx5e_macsec_device *macsec_device; 873 struct mlx5_core_dev *mdev = priv->mdev; 874 u8 assoc_num = ctx->sa.assoc_num; 875 struct mlx5e_macsec_rx_sc *rx_sc; 876 sci_t sci = ctx_rx_sa->sc->sci; 877 struct mlx5e_macsec_sa *rx_sa; 878 struct mlx5e_macsec *macsec; 879 struct list_head *list; 880 int err = 0; 881 882 mutex_lock(&priv->macsec->lock); 883 884 macsec = priv->macsec; 885 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 886 if (!macsec_device) { 887 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 888 err = -EINVAL; 889 goto out; 890 } 891 892 list = &macsec_device->macsec_rx_sc_list_head; 893 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci); 894 if (!rx_sc) { 895 netdev_err(ctx->netdev, 896 "MACsec offload rx_sc sci %lld doesn't exist\n", 897 ctx->sa.rx_sa->sc->sci); 898 err = -EINVAL; 899 goto out; 900 } 901 902 if (rx_sc->rx_sa[assoc_num]) { 903 netdev_err(ctx->netdev, 904 "MACsec offload rx_sc sci %lld rx_sa %d already exist\n", 905 sci, assoc_num); 906 err = -EEXIST; 907 goto out; 908 } 909 910 rx_sa = kzalloc(sizeof(*rx_sa), GFP_KERNEL); 911 if (!rx_sa) { 912 err = -ENOMEM; 913 goto out; 914 } 915 916 rx_sa->active = ctx_rx_sa->active; 917 rx_sa->next_pn = ctx_rx_sa->next_pn; 918 rx_sa->sci = sci; 919 rx_sa->assoc_num = assoc_num; 920 921 if (ctx->secy->xpn) 922 update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves, 923 ctx_rx_sa->ssci); 924 925 err = mlx5_create_encryption_key(mdev, ctx->sa.key, ctx->secy->key_len, 926 MLX5_ACCEL_OBJ_MACSEC_KEY, 927 &rx_sa->enc_key_id); 928 if (err) 929 goto destroy_sa; 930 931 rx_sc->rx_sa[assoc_num] = rx_sa; 932 if (!rx_sa->active) 933 goto out; 934 935 //TODO - add support for both authentication and encryption flows 936 err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, &rx_sc->sc_xarray_element->fs_id); 937 if (err) 938 goto destroy_encryption_key; 939 940 goto out; 941 942destroy_encryption_key: 943 rx_sc->rx_sa[assoc_num] = NULL; 944 mlx5_destroy_encryption_key(mdev, rx_sa->enc_key_id); 945destroy_sa: 946 kfree(rx_sa); 947out: 948 mutex_unlock(&macsec->lock); 949 950 return err; 951} 952 953static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx) 954{ 955 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 956 const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa; 957 struct mlx5e_macsec_device *macsec_device; 958 u8 assoc_num = ctx->sa.assoc_num; 959 struct mlx5e_macsec_rx_sc *rx_sc; 960 sci_t sci = ctx_rx_sa->sc->sci; 961 struct mlx5e_macsec_sa *rx_sa; 962 struct mlx5e_macsec *macsec; 963 struct list_head *list; 964 int err = 0; 965 966 mutex_lock(&priv->macsec->lock); 967 968 macsec = priv->macsec; 969 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 970 if (!macsec_device) { 971 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 972 err = -EINVAL; 973 goto out; 974 } 975 976 list = &macsec_device->macsec_rx_sc_list_head; 977 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci); 978 if (!rx_sc) { 979 netdev_err(ctx->netdev, 980 "MACsec offload rx_sc sci %lld doesn't exist\n", 981 ctx->sa.rx_sa->sc->sci); 982 err = -EINVAL; 983 goto out; 984 } 985 986 rx_sa = rx_sc->rx_sa[assoc_num]; 987 if (!rx_sa) { 988 netdev_err(ctx->netdev, 989 "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n", 990 sci, assoc_num); 991 err = -EINVAL; 992 goto out; 993 } 994 995 if (ctx->sa.update_pn) { 996 netdev_err(ctx->netdev, 997 "MACsec offload update RX sa %d PN isn't supported\n", 998 assoc_num); 999 err = -EINVAL; 1000 goto out; 1001 } 1002 1003 err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active, 1004 &rx_sc->sc_xarray_element->fs_id); 1005out: 1006 mutex_unlock(&macsec->lock); 1007 1008 return err; 1009} 1010 1011static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx) 1012{ 1013 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 1014 struct mlx5e_macsec_device *macsec_device; 1015 sci_t sci = ctx->sa.rx_sa->sc->sci; 1016 struct mlx5e_macsec_rx_sc *rx_sc; 1017 u8 assoc_num = ctx->sa.assoc_num; 1018 struct mlx5e_macsec_sa *rx_sa; 1019 struct mlx5e_macsec *macsec; 1020 struct list_head *list; 1021 int err = 0; 1022 1023 mutex_lock(&priv->macsec->lock); 1024 1025 macsec = priv->macsec; 1026 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 1027 if (!macsec_device) { 1028 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 1029 err = -EINVAL; 1030 goto out; 1031 } 1032 1033 list = &macsec_device->macsec_rx_sc_list_head; 1034 rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci); 1035 if (!rx_sc) { 1036 netdev_err(ctx->netdev, 1037 "MACsec offload rx_sc sci %lld doesn't exist\n", 1038 ctx->sa.rx_sa->sc->sci); 1039 err = -EINVAL; 1040 goto out; 1041 } 1042 1043 rx_sa = rx_sc->rx_sa[assoc_num]; 1044 if (!rx_sa) { 1045 netdev_err(ctx->netdev, 1046 "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n", 1047 sci, assoc_num); 1048 err = -EINVAL; 1049 goto out; 1050 } 1051 1052 if (rx_sa->active) 1053 mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, 1054 rx_sc->sc_xarray_element->fs_id); 1055 mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id); 1056 kfree(rx_sa); 1057 rx_sc->rx_sa[assoc_num] = NULL; 1058 1059out: 1060 mutex_unlock(&macsec->lock); 1061 1062 return err; 1063} 1064 1065static int mlx5e_macsec_add_secy(struct macsec_context *ctx) 1066{ 1067 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 1068 const struct net_device *dev = ctx->secy->netdev; 1069 const struct net_device *netdev = ctx->netdev; 1070 struct mlx5e_macsec_device *macsec_device; 1071 struct mlx5e_macsec *macsec; 1072 int err = 0; 1073 1074 if (!mlx5e_macsec_secy_features_validate(ctx)) 1075 return -EINVAL; 1076 1077 mutex_lock(&priv->macsec->lock); 1078 macsec = priv->macsec; 1079 if (mlx5e_macsec_get_macsec_device_context(macsec, ctx)) { 1080 netdev_err(netdev, "MACsec offload: MACsec net_device already exist\n"); 1081 goto out; 1082 } 1083 1084 if (macsec->num_of_devices >= MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES) { 1085 netdev_err(netdev, "Currently, only %d MACsec offload devices can be set\n", 1086 MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES); 1087 err = -EBUSY; 1088 goto out; 1089 } 1090 1091 macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL); 1092 if (!macsec_device) { 1093 err = -ENOMEM; 1094 goto out; 1095 } 1096 1097 macsec_device->dev_addr = kmemdup(dev->dev_addr, dev->addr_len, GFP_KERNEL); 1098 if (!macsec_device->dev_addr) { 1099 kfree(macsec_device); 1100 err = -ENOMEM; 1101 goto out; 1102 } 1103 1104 macsec_device->netdev = dev; 1105 1106 INIT_LIST_HEAD_RCU(&macsec_device->macsec_rx_sc_list_head); 1107 list_add_rcu(&macsec_device->macsec_device_list_element, &macsec->macsec_device_list_head); 1108 1109 ++macsec->num_of_devices; 1110out: 1111 mutex_unlock(&macsec->lock); 1112 1113 return err; 1114} 1115 1116static int macsec_upd_secy_hw_address(struct macsec_context *ctx, 1117 struct mlx5e_macsec_device *macsec_device) 1118{ 1119 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 1120 const struct net_device *dev = ctx->secy->netdev; 1121 struct mlx5e_macsec *macsec = priv->macsec; 1122 struct mlx5e_macsec_rx_sc *rx_sc, *tmp; 1123 struct mlx5e_macsec_sa *rx_sa; 1124 struct list_head *list; 1125 int i, err = 0; 1126 1127 1128 list = &macsec_device->macsec_rx_sc_list_head; 1129 list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) { 1130 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1131 rx_sa = rx_sc->rx_sa[i]; 1132 if (!rx_sa || !rx_sa->macsec_rule) 1133 continue; 1134 1135 mlx5e_macsec_cleanup_sa_fs(macsec, rx_sa, false, ctx->secy->netdev, 1136 rx_sc->sc_xarray_element->fs_id); 1137 } 1138 } 1139 1140 list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) { 1141 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1142 rx_sa = rx_sc->rx_sa[i]; 1143 if (!rx_sa) 1144 continue; 1145 1146 if (rx_sa->active) { 1147 err = mlx5e_macsec_init_sa_fs(ctx, rx_sa, true, false, 1148 &rx_sc->sc_xarray_element->fs_id); 1149 if (err) 1150 goto out; 1151 } 1152 } 1153 } 1154 1155 memcpy(macsec_device->dev_addr, dev->dev_addr, dev->addr_len); 1156out: 1157 return err; 1158} 1159 1160/* this function is called from 2 macsec ops functions: 1161 * macsec_set_mac_address ��� MAC address was changed, therefore we need to destroy 1162 * and create new Tx contexts(macsec object + steering). 1163 * macsec_changelink ��� in this case the tx SC or SecY may be changed, therefore need to 1164 * destroy Tx and Rx contexts(macsec object + steering) 1165 */ 1166static int mlx5e_macsec_upd_secy(struct macsec_context *ctx) 1167{ 1168 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 1169 const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc; 1170 const struct net_device *dev = ctx->secy->netdev; 1171 struct mlx5e_macsec_device *macsec_device; 1172 struct mlx5e_macsec_sa *tx_sa; 1173 struct mlx5e_macsec *macsec; 1174 int i, err = 0; 1175 1176 if (!mlx5e_macsec_secy_features_validate(ctx)) 1177 return -EINVAL; 1178 1179 mutex_lock(&priv->macsec->lock); 1180 1181 macsec = priv->macsec; 1182 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 1183 if (!macsec_device) { 1184 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 1185 err = -EINVAL; 1186 goto out; 1187 } 1188 1189 /* if the dev_addr hasn't change, it mean the callback is from macsec_changelink */ 1190 if (!memcmp(macsec_device->dev_addr, dev->dev_addr, dev->addr_len)) { 1191 err = macsec_upd_secy_hw_address(ctx, macsec_device); 1192 if (err) 1193 goto out; 1194 } 1195 1196 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1197 tx_sa = macsec_device->tx_sa[i]; 1198 if (!tx_sa) 1199 continue; 1200 1201 mlx5e_macsec_cleanup_sa_fs(macsec, tx_sa, true, ctx->secy->netdev, 0); 1202 } 1203 1204 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1205 tx_sa = macsec_device->tx_sa[i]; 1206 if (!tx_sa) 1207 continue; 1208 1209 if (tx_sa->assoc_num == tx_sc->encoding_sa && tx_sa->active) { 1210 err = mlx5e_macsec_init_sa_fs(ctx, tx_sa, tx_sc->encrypt, true, NULL); 1211 if (err) 1212 goto out; 1213 } 1214 } 1215 1216out: 1217 mutex_unlock(&macsec->lock); 1218 1219 return err; 1220} 1221 1222static int mlx5e_macsec_del_secy(struct macsec_context *ctx) 1223{ 1224 struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev); 1225 struct mlx5e_macsec_device *macsec_device; 1226 struct mlx5e_macsec_rx_sc *rx_sc, *tmp; 1227 struct mlx5e_macsec_sa *tx_sa; 1228 struct mlx5e_macsec *macsec; 1229 struct list_head *list; 1230 int err = 0; 1231 int i; 1232 1233 mutex_lock(&priv->macsec->lock); 1234 macsec = priv->macsec; 1235 macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx); 1236 if (!macsec_device) { 1237 netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n"); 1238 err = -EINVAL; 1239 1240 goto out; 1241 } 1242 1243 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1244 tx_sa = macsec_device->tx_sa[i]; 1245 if (!tx_sa) 1246 continue; 1247 1248 mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0); 1249 mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id); 1250 kfree(tx_sa); 1251 macsec_device->tx_sa[i] = NULL; 1252 } 1253 1254 list = &macsec_device->macsec_rx_sc_list_head; 1255 list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) 1256 macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev); 1257 1258 kfree(macsec_device->dev_addr); 1259 macsec_device->dev_addr = NULL; 1260 1261 list_del_rcu(&macsec_device->macsec_device_list_element); 1262 --macsec->num_of_devices; 1263 kfree(macsec_device); 1264 1265out: 1266 mutex_unlock(&macsec->lock); 1267 1268 return err; 1269} 1270 1271static void macsec_build_accel_attrs(struct mlx5e_macsec_sa *sa, 1272 struct mlx5_macsec_obj_attrs *attrs) 1273{ 1274 attrs->epn_state.epn_msb = sa->epn_state.epn_msb; 1275 attrs->epn_state.overlap = sa->epn_state.overlap; 1276} 1277 1278static void macsec_aso_build_wqe_ctrl_seg(struct mlx5e_macsec_aso *macsec_aso, 1279 struct mlx5_wqe_aso_ctrl_seg *aso_ctrl, 1280 struct mlx5_aso_ctrl_param *param) 1281{ 1282 struct mlx5e_macsec_umr *umr = macsec_aso->umr; 1283 1284 memset(aso_ctrl, 0, sizeof(*aso_ctrl)); 1285 aso_ctrl->va_l = cpu_to_be32(umr->dma_addr | ASO_CTRL_READ_EN); 1286 aso_ctrl->va_h = cpu_to_be32((u64)umr->dma_addr >> 32); 1287 aso_ctrl->l_key = cpu_to_be32(umr->mkey); 1288 1289 if (!param) 1290 return; 1291 1292 aso_ctrl->data_mask_mode = param->data_mask_mode << 6; 1293 aso_ctrl->condition_1_0_operand = param->condition_1_operand | 1294 param->condition_0_operand << 4; 1295 aso_ctrl->condition_1_0_offset = param->condition_1_offset | 1296 param->condition_0_offset << 4; 1297 aso_ctrl->data_offset_condition_operand = param->data_offset | 1298 param->condition_operand << 6; 1299 aso_ctrl->condition_0_data = cpu_to_be32(param->condition_0_data); 1300 aso_ctrl->condition_0_mask = cpu_to_be32(param->condition_0_mask); 1301 aso_ctrl->condition_1_data = cpu_to_be32(param->condition_1_data); 1302 aso_ctrl->condition_1_mask = cpu_to_be32(param->condition_1_mask); 1303 aso_ctrl->bitwise_data = cpu_to_be64(param->bitwise_data); 1304 aso_ctrl->data_mask = cpu_to_be64(param->data_mask); 1305} 1306 1307static int mlx5e_macsec_modify_obj(struct mlx5_core_dev *mdev, struct mlx5_macsec_obj_attrs *attrs, 1308 u32 macsec_id) 1309{ 1310 u32 in[MLX5_ST_SZ_DW(modify_macsec_obj_in)] = {}; 1311 u32 out[MLX5_ST_SZ_DW(query_macsec_obj_out)]; 1312 u64 modify_field_select = 0; 1313 void *obj; 1314 int err; 1315 1316 /* General object fields set */ 1317 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT); 1318 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC); 1319 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, macsec_id); 1320 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 1321 if (err) { 1322 mlx5_core_err(mdev, "Query MACsec object failed (Object id %d), err = %d\n", 1323 macsec_id, err); 1324 return err; 1325 } 1326 1327 obj = MLX5_ADDR_OF(query_macsec_obj_out, out, macsec_object); 1328 modify_field_select = MLX5_GET64(macsec_offload_obj, obj, modify_field_select); 1329 1330 /* EPN */ 1331 if (!(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP) || 1332 !(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB)) { 1333 mlx5_core_dbg(mdev, "MACsec object field is not modifiable (Object id %d)\n", 1334 macsec_id); 1335 return -EOPNOTSUPP; 1336 } 1337 1338 obj = MLX5_ADDR_OF(modify_macsec_obj_in, in, macsec_object); 1339 MLX5_SET64(macsec_offload_obj, obj, modify_field_select, 1340 MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP | MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB); 1341 MLX5_SET(macsec_offload_obj, obj, epn_msb, attrs->epn_state.epn_msb); 1342 MLX5_SET(macsec_offload_obj, obj, epn_overlap, attrs->epn_state.overlap); 1343 1344 /* General object fields set */ 1345 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT); 1346 1347 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); 1348} 1349 1350static void macsec_aso_build_ctrl(struct mlx5e_macsec_aso *aso, 1351 struct mlx5_wqe_aso_ctrl_seg *aso_ctrl, 1352 struct mlx5e_macsec_aso_in *in) 1353{ 1354 struct mlx5_aso_ctrl_param param = {}; 1355 1356 param.data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BITWISE_64BIT; 1357 param.condition_0_operand = MLX5_ASO_ALWAYS_TRUE; 1358 param.condition_1_operand = MLX5_ASO_ALWAYS_TRUE; 1359 if (in->mode == MLX5_MACSEC_EPN) { 1360 param.data_offset = MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; 1361 param.bitwise_data = BIT_ULL(54); 1362 param.data_mask = param.bitwise_data; 1363 } 1364 macsec_aso_build_wqe_ctrl_seg(aso, aso_ctrl, ¶m); 1365} 1366 1367static int macsec_aso_set_arm_event(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec, 1368 struct mlx5e_macsec_aso_in *in) 1369{ 1370 struct mlx5e_macsec_aso *aso; 1371 struct mlx5_aso_wqe *aso_wqe; 1372 struct mlx5_aso *maso; 1373 int err; 1374 1375 aso = &macsec->aso; 1376 maso = aso->maso; 1377 1378 mutex_lock(&aso->aso_lock); 1379 aso_wqe = mlx5_aso_get_wqe(maso); 1380 mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id, 1381 MLX5_ACCESS_ASO_OPC_MOD_MACSEC); 1382 macsec_aso_build_ctrl(aso, &aso_wqe->aso_ctrl, in); 1383 mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl); 1384 err = mlx5_aso_poll_cq(maso, false); 1385 mutex_unlock(&aso->aso_lock); 1386 1387 return err; 1388} 1389 1390static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec, 1391 struct mlx5e_macsec_aso_in *in, struct mlx5e_macsec_aso_out *out) 1392{ 1393 struct mlx5e_macsec_aso *aso; 1394 struct mlx5_aso_wqe *aso_wqe; 1395 struct mlx5_aso *maso; 1396 unsigned long expires; 1397 int err; 1398 1399 aso = &macsec->aso; 1400 maso = aso->maso; 1401 1402 mutex_lock(&aso->aso_lock); 1403 1404 aso_wqe = mlx5_aso_get_wqe(maso); 1405 mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id, 1406 MLX5_ACCESS_ASO_OPC_MOD_MACSEC); 1407 macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL); 1408 1409 mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl); 1410 expires = jiffies + msecs_to_jiffies(10); 1411 do { 1412 err = mlx5_aso_poll_cq(maso, false); 1413 if (err) 1414 usleep_range(2, 10); 1415 } while (err && time_is_after_jiffies(expires)); 1416 1417 if (err) 1418 goto err_out; 1419 1420 if (MLX5_GET(macsec_aso, aso->umr->ctx, epn_event_arm)) 1421 out->event_arm |= MLX5E_ASO_EPN_ARM; 1422 1423 out->mode_param = MLX5_GET(macsec_aso, aso->umr->ctx, mode_parameter); 1424 1425err_out: 1426 mutex_unlock(&aso->aso_lock); 1427 return err; 1428} 1429 1430static struct mlx5e_macsec_sa *get_macsec_tx_sa_from_obj_id(const struct mlx5e_macsec *macsec, 1431 const u32 obj_id) 1432{ 1433 const struct list_head *device_list; 1434 struct mlx5e_macsec_sa *macsec_sa; 1435 struct mlx5e_macsec_device *iter; 1436 int i; 1437 1438 device_list = &macsec->macsec_device_list_head; 1439 1440 list_for_each_entry(iter, device_list, macsec_device_list_element) { 1441 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1442 macsec_sa = iter->tx_sa[i]; 1443 if (!macsec_sa || !macsec_sa->active) 1444 continue; 1445 if (macsec_sa->macsec_obj_id == obj_id) 1446 return macsec_sa; 1447 } 1448 } 1449 1450 return NULL; 1451} 1452 1453static struct mlx5e_macsec_sa *get_macsec_rx_sa_from_obj_id(const struct mlx5e_macsec *macsec, 1454 const u32 obj_id) 1455{ 1456 const struct list_head *device_list, *sc_list; 1457 struct mlx5e_macsec_rx_sc *mlx5e_rx_sc; 1458 struct mlx5e_macsec_sa *macsec_sa; 1459 struct mlx5e_macsec_device *iter; 1460 int i; 1461 1462 device_list = &macsec->macsec_device_list_head; 1463 1464 list_for_each_entry(iter, device_list, macsec_device_list_element) { 1465 sc_list = &iter->macsec_rx_sc_list_head; 1466 list_for_each_entry(mlx5e_rx_sc, sc_list, rx_sc_list_element) { 1467 for (i = 0; i < MACSEC_NUM_AN; ++i) { 1468 macsec_sa = mlx5e_rx_sc->rx_sa[i]; 1469 if (!macsec_sa || !macsec_sa->active) 1470 continue; 1471 if (macsec_sa->macsec_obj_id == obj_id) 1472 return macsec_sa; 1473 } 1474 } 1475 } 1476 1477 return NULL; 1478} 1479 1480static void macsec_epn_update(struct mlx5e_macsec *macsec, struct mlx5_core_dev *mdev, 1481 struct mlx5e_macsec_sa *sa, u32 obj_id, u32 mode_param) 1482{ 1483 struct mlx5_macsec_obj_attrs attrs = {}; 1484 struct mlx5e_macsec_aso_in in = {}; 1485 1486 /* When the bottom of the replay protection window (mode_param) crosses 2^31 (half sequence 1487 * number wraparound) hence mode_param > MLX5_MACSEC_EPN_SCOPE_MID the SW should update the 1488 * esn_overlap to OLD (1). 1489 * When the bottom of the replay protection window (mode_param) crosses 2^32 (full sequence 1490 * number wraparound) hence mode_param < MLX5_MACSEC_EPN_SCOPE_MID since it did a 1491 * wraparound, the SW should update the esn_overlap to NEW (0), and increment the esn_msb. 1492 */ 1493 1494 if (mode_param < MLX5_MACSEC_EPN_SCOPE_MID) { 1495 sa->epn_state.epn_msb++; 1496 sa->epn_state.overlap = 0; 1497 } else { 1498 sa->epn_state.overlap = 1; 1499 } 1500 1501 macsec_build_accel_attrs(sa, &attrs); 1502 mlx5e_macsec_modify_obj(mdev, &attrs, obj_id); 1503 1504 /* Re-set EPN arm event */ 1505 in.obj_id = obj_id; 1506 in.mode = MLX5_MACSEC_EPN; 1507 macsec_aso_set_arm_event(mdev, macsec, &in); 1508} 1509 1510static void macsec_async_event(struct work_struct *work) 1511{ 1512 struct mlx5e_macsec_async_work *async_work; 1513 struct mlx5e_macsec_aso_out out = {}; 1514 struct mlx5e_macsec_aso_in in = {}; 1515 struct mlx5e_macsec_sa *macsec_sa; 1516 struct mlx5e_macsec *macsec; 1517 struct mlx5_core_dev *mdev; 1518 u32 obj_id; 1519 1520 async_work = container_of(work, struct mlx5e_macsec_async_work, work); 1521 macsec = async_work->macsec; 1522 mutex_lock(&macsec->lock); 1523 1524 mdev = async_work->mdev; 1525 obj_id = async_work->obj_id; 1526 macsec_sa = get_macsec_tx_sa_from_obj_id(macsec, obj_id); 1527 if (!macsec_sa) { 1528 macsec_sa = get_macsec_rx_sa_from_obj_id(macsec, obj_id); 1529 if (!macsec_sa) { 1530 mlx5_core_dbg(mdev, "MACsec SA is not found (SA object id %d)\n", obj_id); 1531 goto out_async_work; 1532 } 1533 } 1534 1535 /* Query MACsec ASO context */ 1536 in.obj_id = obj_id; 1537 macsec_aso_query(mdev, macsec, &in, &out); 1538 1539 /* EPN case */ 1540 if (macsec_sa->epn_state.epn_enabled && !(out.event_arm & MLX5E_ASO_EPN_ARM)) 1541 macsec_epn_update(macsec, mdev, macsec_sa, obj_id, out.mode_param); 1542 1543out_async_work: 1544 kfree(async_work); 1545 mutex_unlock(&macsec->lock); 1546} 1547 1548static int macsec_obj_change_event(struct notifier_block *nb, unsigned long event, void *data) 1549{ 1550 struct mlx5e_macsec *macsec = container_of(nb, struct mlx5e_macsec, nb); 1551 struct mlx5e_macsec_async_work *async_work; 1552 struct mlx5_eqe_obj_change *obj_change; 1553 struct mlx5_eqe *eqe = data; 1554 u16 obj_type; 1555 u32 obj_id; 1556 1557 if (event != MLX5_EVENT_TYPE_OBJECT_CHANGE) 1558 return NOTIFY_DONE; 1559 1560 obj_change = &eqe->data.obj_change; 1561 obj_type = be16_to_cpu(obj_change->obj_type); 1562 obj_id = be32_to_cpu(obj_change->obj_id); 1563 1564 if (obj_type != MLX5_GENERAL_OBJECT_TYPES_MACSEC) 1565 return NOTIFY_DONE; 1566 1567 async_work = kzalloc(sizeof(*async_work), GFP_ATOMIC); 1568 if (!async_work) 1569 return NOTIFY_DONE; 1570 1571 async_work->macsec = macsec; 1572 async_work->mdev = macsec->mdev; 1573 async_work->obj_id = obj_id; 1574 1575 INIT_WORK(&async_work->work, macsec_async_event); 1576 1577 WARN_ON(!queue_work(macsec->wq, &async_work->work)); 1578 1579 return NOTIFY_OK; 1580} 1581 1582static int mlx5e_macsec_aso_init(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev) 1583{ 1584 struct mlx5_aso *maso; 1585 int err; 1586 1587 err = mlx5_core_alloc_pd(mdev, &aso->pdn); 1588 if (err) { 1589 mlx5_core_err(mdev, 1590 "MACsec offload: Failed to alloc pd for MACsec ASO, err=%d\n", 1591 err); 1592 return err; 1593 } 1594 1595 maso = mlx5_aso_create(mdev, aso->pdn); 1596 if (IS_ERR(maso)) { 1597 err = PTR_ERR(maso); 1598 goto err_aso; 1599 } 1600 1601 err = mlx5e_macsec_aso_reg_mr(mdev, aso); 1602 if (err) 1603 goto err_aso_reg; 1604 1605 mutex_init(&aso->aso_lock); 1606 1607 aso->maso = maso; 1608 1609 return 0; 1610 1611err_aso_reg: 1612 mlx5_aso_destroy(maso); 1613err_aso: 1614 mlx5_core_dealloc_pd(mdev, aso->pdn); 1615 return err; 1616} 1617 1618static void mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev) 1619{ 1620 if (!aso) 1621 return; 1622 1623 mlx5e_macsec_aso_dereg_mr(mdev, aso); 1624 1625 mlx5_aso_destroy(aso->maso); 1626 1627 mlx5_core_dealloc_pd(mdev, aso->pdn); 1628} 1629 1630static const struct macsec_ops macsec_offload_ops = { 1631 .mdo_add_txsa = mlx5e_macsec_add_txsa, 1632 .mdo_upd_txsa = mlx5e_macsec_upd_txsa, 1633 .mdo_del_txsa = mlx5e_macsec_del_txsa, 1634 .mdo_add_rxsc = mlx5e_macsec_add_rxsc, 1635 .mdo_upd_rxsc = mlx5e_macsec_upd_rxsc, 1636 .mdo_del_rxsc = mlx5e_macsec_del_rxsc, 1637 .mdo_add_rxsa = mlx5e_macsec_add_rxsa, 1638 .mdo_upd_rxsa = mlx5e_macsec_upd_rxsa, 1639 .mdo_del_rxsa = mlx5e_macsec_del_rxsa, 1640 .mdo_add_secy = mlx5e_macsec_add_secy, 1641 .mdo_upd_secy = mlx5e_macsec_upd_secy, 1642 .mdo_del_secy = mlx5e_macsec_del_secy, 1643}; 1644 1645bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb) 1646{ 1647 struct metadata_dst *md_dst = skb_metadata_dst(skb); 1648 u32 fs_id; 1649 1650 fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs, 1651 &md_dst->u.macsec_info.sci); 1652 if (!fs_id) 1653 goto err_out; 1654 1655 return true; 1656 1657err_out: 1658 dev_kfree_skb_any(skb); 1659 return false; 1660} 1661 1662void mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec *macsec, 1663 struct sk_buff *skb, 1664 struct mlx5_wqe_eth_seg *eseg) 1665{ 1666 struct metadata_dst *md_dst = skb_metadata_dst(skb); 1667 u32 fs_id; 1668 1669 fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs, 1670 &md_dst->u.macsec_info.sci); 1671 if (!fs_id) 1672 return; 1673 1674 eseg->flow_table_metadata = cpu_to_be32(MLX5_ETH_WQE_FT_META_MACSEC | fs_id << 2); 1675} 1676 1677void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev, 1678 struct sk_buff *skb, 1679 struct mlx5_cqe64 *cqe) 1680{ 1681 struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element; 1682 u32 macsec_meta_data = be32_to_cpu(cqe->ft_metadata); 1683 struct mlx5e_priv *priv = macsec_netdev_priv(netdev); 1684 struct mlx5e_macsec_rx_sc *rx_sc; 1685 struct mlx5e_macsec *macsec; 1686 u32 fs_id; 1687 1688 macsec = priv->macsec; 1689 if (!macsec) 1690 return; 1691 1692 fs_id = MLX5_MACSEC_RX_METADAT_HANDLE(macsec_meta_data); 1693 1694 rcu_read_lock(); 1695 sc_xarray_element = xa_load(&macsec->sc_xarray, fs_id); 1696 rx_sc = sc_xarray_element->rx_sc; 1697 if (rx_sc) { 1698 dst_hold(&rx_sc->md_dst->dst); 1699 skb_dst_set(skb, &rx_sc->md_dst->dst); 1700 } 1701 1702 rcu_read_unlock(); 1703} 1704 1705void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv) 1706{ 1707 struct net_device *netdev = priv->netdev; 1708 1709 if (!mlx5e_is_macsec_device(priv->mdev)) 1710 return; 1711 1712 /* Enable MACsec */ 1713 mlx5_core_dbg(priv->mdev, "mlx5e: MACsec acceleration enabled\n"); 1714 netdev->macsec_ops = &macsec_offload_ops; 1715 netdev->features |= NETIF_F_HW_MACSEC; 1716 netif_keep_dst(netdev); 1717} 1718 1719int mlx5e_macsec_init(struct mlx5e_priv *priv) 1720{ 1721 struct mlx5_core_dev *mdev = priv->mdev; 1722 struct mlx5e_macsec *macsec = NULL; 1723 struct mlx5_macsec_fs *macsec_fs; 1724 int err; 1725 1726 if (!mlx5e_is_macsec_device(priv->mdev)) { 1727 mlx5_core_dbg(mdev, "Not a MACsec offload device\n"); 1728 return 0; 1729 } 1730 1731 macsec = kzalloc(sizeof(*macsec), GFP_KERNEL); 1732 if (!macsec) 1733 return -ENOMEM; 1734 1735 INIT_LIST_HEAD(&macsec->macsec_device_list_head); 1736 mutex_init(&macsec->lock); 1737 1738 err = mlx5e_macsec_aso_init(&macsec->aso, priv->mdev); 1739 if (err) { 1740 mlx5_core_err(mdev, "MACsec offload: Failed to init aso, err=%d\n", err); 1741 goto err_aso; 1742 } 1743 1744 macsec->wq = alloc_ordered_workqueue("mlx5e_macsec_%s", 0, priv->netdev->name); 1745 if (!macsec->wq) { 1746 err = -ENOMEM; 1747 goto err_wq; 1748 } 1749 1750 xa_init_flags(&macsec->sc_xarray, XA_FLAGS_ALLOC1); 1751 1752 priv->macsec = macsec; 1753 1754 macsec->mdev = mdev; 1755 1756 macsec_fs = mlx5_macsec_fs_init(mdev); 1757 if (!macsec_fs) { 1758 err = -ENOMEM; 1759 goto err_out; 1760 } 1761 1762 mdev->macsec_fs = macsec_fs; 1763 1764 macsec->nb.notifier_call = macsec_obj_change_event; 1765 mlx5_notifier_register(mdev, &macsec->nb); 1766 1767 mlx5_core_dbg(mdev, "MACsec attached to netdevice\n"); 1768 1769 return 0; 1770 1771err_out: 1772 destroy_workqueue(macsec->wq); 1773err_wq: 1774 mlx5e_macsec_aso_cleanup(&macsec->aso, priv->mdev); 1775err_aso: 1776 kfree(macsec); 1777 priv->macsec = NULL; 1778 return err; 1779} 1780 1781void mlx5e_macsec_cleanup(struct mlx5e_priv *priv) 1782{ 1783 struct mlx5e_macsec *macsec = priv->macsec; 1784 struct mlx5_core_dev *mdev = priv->mdev; 1785 1786 if (!macsec) 1787 return; 1788 1789 mlx5_notifier_unregister(mdev, &macsec->nb); 1790 mlx5_macsec_fs_cleanup(mdev->macsec_fs); 1791 destroy_workqueue(macsec->wq); 1792 mlx5e_macsec_aso_cleanup(&macsec->aso, mdev); 1793 mutex_destroy(&macsec->lock); 1794 kfree(macsec); 1795} 1796