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