hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
....@@ -40,7 +40,7 @@
4040 #include "en.h"
4141 #include "en_accel/ipsec.h"
4242 #include "en_accel/ipsec_rxtx.h"
43
-
43
+#include "en_accel/ipsec_fs.h"
4444
4545 static struct mlx5e_ipsec_sa_entry *to_ipsec_sa_entry(struct xfrm_state *x)
4646 {
....@@ -75,18 +75,23 @@
7575 return ret;
7676 }
7777
78
-static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry)
78
+static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry,
79
+ unsigned int handle)
7980 {
8081 struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
82
+ struct mlx5e_ipsec_sa_entry *_sa_entry;
8183 unsigned long flags;
82
- int ret;
8384
84
- ret = ida_simple_get(&ipsec->halloc, 1, 0, GFP_KERNEL);
85
- if (ret < 0)
86
- return ret;
85
+ rcu_read_lock();
86
+ hash_for_each_possible_rcu(ipsec->sadb_rx, _sa_entry, hlist, handle)
87
+ if (_sa_entry->handle == handle) {
88
+ rcu_read_unlock();
89
+ return -EEXIST;
90
+ }
91
+ rcu_read_unlock();
8792
8893 spin_lock_irqsave(&ipsec->sadb_rx_lock, flags);
89
- sa_entry->handle = ret;
94
+ sa_entry->handle = handle;
9095 hash_add_rcu(ipsec->sadb_rx, &sa_entry->hlist, sa_entry->handle);
9196 spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
9297
....@@ -103,21 +108,11 @@
103108 spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
104109 }
105110
106
-static void mlx5e_ipsec_sadb_rx_free(struct mlx5e_ipsec_sa_entry *sa_entry)
107
-{
108
- struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
109
-
110
- /* xfrm already doing sync rcu between del and free callbacks */
111
-
112
- ida_simple_remove(&ipsec->halloc, sa_entry->handle);
113
-}
114
-
115111 static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
116112 {
117113 struct xfrm_replay_state_esn *replay_esn;
118
- u32 seq_bottom;
114
+ u32 seq_bottom = 0;
119115 u8 overlap;
120
- u32 *esn;
121116
122117 if (!(sa_entry->x->props.flags & XFRM_STATE_ESN)) {
123118 sa_entry->esn_state.trigger = 0;
....@@ -125,16 +120,16 @@
125120 }
126121
127122 replay_esn = sa_entry->x->replay_esn;
128
- seq_bottom = replay_esn->seq - replay_esn->replay_window + 1;
123
+ if (replay_esn->seq >= replay_esn->replay_window)
124
+ seq_bottom = replay_esn->seq - replay_esn->replay_window + 1;
125
+
129126 overlap = sa_entry->esn_state.overlap;
130127
131128 sa_entry->esn_state.esn = xfrm_replay_seqhi(sa_entry->x,
132129 htonl(seq_bottom));
133
- esn = &sa_entry->esn_state.esn;
134130
135131 sa_entry->esn_state.trigger = 1;
136132 if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) {
137
- ++(*esn);
138133 sa_entry->esn_state.overlap = 0;
139134 return true;
140135 } else if (unlikely(!overlap &&
....@@ -199,11 +194,19 @@
199194 attrs->flags |= (x->props.mode == XFRM_MODE_TRANSPORT) ?
200195 MLX5_ACCEL_ESP_FLAGS_TRANSPORT :
201196 MLX5_ACCEL_ESP_FLAGS_TUNNEL;
197
+
198
+ /* spi */
199
+ attrs->spi = x->id.spi;
200
+
201
+ /* source , destination ips */
202
+ memcpy(&attrs->saddr, x->props.saddr.a6, sizeof(attrs->saddr));
203
+ memcpy(&attrs->daddr, x->id.daddr.a6, sizeof(attrs->daddr));
204
+ attrs->is_ipv6 = (x->props.family != AF_INET);
202205 }
203206
204207 static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
205208 {
206
- struct net_device *netdev = x->xso.dev;
209
+ struct net_device *netdev = x->xso.real_dev;
207210 struct mlx5e_priv *priv;
208211
209212 priv = netdev_priv(netdev);
....@@ -278,14 +281,34 @@
278281 return 0;
279282 }
280283
284
+static int mlx5e_xfrm_fs_add_rule(struct mlx5e_priv *priv,
285
+ struct mlx5e_ipsec_sa_entry *sa_entry)
286
+{
287
+ if (!mlx5_is_ipsec_device(priv->mdev))
288
+ return 0;
289
+
290
+ return mlx5e_accel_ipsec_fs_add_rule(priv, &sa_entry->xfrm->attrs,
291
+ sa_entry->ipsec_obj_id,
292
+ &sa_entry->ipsec_rule);
293
+}
294
+
295
+static void mlx5e_xfrm_fs_del_rule(struct mlx5e_priv *priv,
296
+ struct mlx5e_ipsec_sa_entry *sa_entry)
297
+{
298
+ if (!mlx5_is_ipsec_device(priv->mdev))
299
+ return;
300
+
301
+ mlx5e_accel_ipsec_fs_del_rule(priv, &sa_entry->xfrm->attrs,
302
+ &sa_entry->ipsec_rule);
303
+}
304
+
281305 static int mlx5e_xfrm_add_state(struct xfrm_state *x)
282306 {
283307 struct mlx5e_ipsec_sa_entry *sa_entry = NULL;
284
- struct net_device *netdev = x->xso.dev;
308
+ struct net_device *netdev = x->xso.real_dev;
285309 struct mlx5_accel_esp_xfrm_attrs attrs;
286310 struct mlx5e_priv *priv;
287
- __be32 saddr[4] = {0}, daddr[4] = {0}, spi;
288
- bool is_ipv6 = false;
311
+ unsigned int sa_handle;
289312 int err;
290313
291314 priv = netdev_priv(netdev);
....@@ -303,20 +326,6 @@
303326 sa_entry->x = x;
304327 sa_entry->ipsec = priv->ipsec;
305328
306
- /* Add the SA to handle processed incoming packets before the add SA
307
- * completion was received
308
- */
309
- if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
310
- err = mlx5e_ipsec_sadb_rx_add(sa_entry);
311
- if (err) {
312
- netdev_info(netdev, "Failed adding to SADB_RX: %d\n", err);
313
- goto err_entry;
314
- }
315
- } else {
316
- sa_entry->set_iv_op = (x->props.flags & XFRM_STATE_ESN) ?
317
- mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
318
- }
319
-
320329 /* check esn */
321330 mlx5e_ipsec_update_esn_state(sa_entry);
322331
....@@ -327,41 +336,45 @@
327336 MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA);
328337 if (IS_ERR(sa_entry->xfrm)) {
329338 err = PTR_ERR(sa_entry->xfrm);
330
- goto err_sadb_rx;
339
+ goto err_sa_entry;
331340 }
332341
333342 /* create hw context */
334
- if (x->props.family == AF_INET) {
335
- saddr[3] = x->props.saddr.a4;
336
- daddr[3] = x->id.daddr.a4;
337
- } else {
338
- memcpy(saddr, x->props.saddr.a6, sizeof(saddr));
339
- memcpy(daddr, x->id.daddr.a6, sizeof(daddr));
340
- is_ipv6 = true;
341
- }
342
- spi = x->id.spi;
343343 sa_entry->hw_context =
344344 mlx5_accel_esp_create_hw_context(priv->mdev,
345345 sa_entry->xfrm,
346
- saddr, daddr, spi,
347
- is_ipv6);
346
+ &sa_handle);
348347 if (IS_ERR(sa_entry->hw_context)) {
349348 err = PTR_ERR(sa_entry->hw_context);
350349 goto err_xfrm;
351350 }
352351
352
+ sa_entry->ipsec_obj_id = sa_handle;
353
+ err = mlx5e_xfrm_fs_add_rule(priv, sa_entry);
354
+ if (err)
355
+ goto err_hw_ctx;
356
+
357
+ if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
358
+ err = mlx5e_ipsec_sadb_rx_add(sa_entry, sa_handle);
359
+ if (err)
360
+ goto err_add_rule;
361
+ } else {
362
+ sa_entry->set_iv_op = (x->props.flags & XFRM_STATE_ESN) ?
363
+ mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
364
+ }
365
+
353366 x->xso.offload_handle = (unsigned long)sa_entry;
354367 goto out;
355368
369
+err_add_rule:
370
+ mlx5e_xfrm_fs_del_rule(priv, sa_entry);
371
+err_hw_ctx:
372
+ mlx5_accel_esp_free_hw_context(priv->mdev, sa_entry->hw_context);
356373 err_xfrm:
357374 mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm);
358
-err_sadb_rx:
359
- if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
360
- mlx5e_ipsec_sadb_rx_del(sa_entry);
361
- mlx5e_ipsec_sadb_rx_free(sa_entry);
362
- }
363
-err_entry:
375
+err_sa_entry:
364376 kfree(sa_entry);
377
+
365378 out:
366379 return err;
367380 }
....@@ -380,18 +393,17 @@
380393 static void mlx5e_xfrm_free_state(struct xfrm_state *x)
381394 {
382395 struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
396
+ struct mlx5e_priv *priv = netdev_priv(x->xso.dev);
383397
384398 if (!sa_entry)
385399 return;
386400
387401 if (sa_entry->hw_context) {
388402 flush_workqueue(sa_entry->ipsec->wq);
389
- mlx5_accel_esp_free_hw_context(sa_entry->hw_context);
403
+ mlx5e_xfrm_fs_del_rule(priv, sa_entry);
404
+ mlx5_accel_esp_free_hw_context(sa_entry->xfrm->mdev, sa_entry->hw_context);
390405 mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm);
391406 }
392
-
393
- if (x->xso.flags & XFRM_OFFLOAD_INBOUND)
394
- mlx5e_ipsec_sadb_rx_free(sa_entry);
395407
396408 kfree(sa_entry);
397409 }
....@@ -422,6 +434,8 @@
422434 kfree(ipsec);
423435 return -ENOMEM;
424436 }
437
+
438
+ mlx5e_accel_ipsec_fs_init(priv);
425439 netdev_dbg(priv->netdev, "IPSec attached to netdevice\n");
426440 return 0;
427441 }
....@@ -433,7 +447,7 @@
433447 if (!ipsec)
434448 return;
435449
436
- drain_workqueue(ipsec->wq);
450
+ mlx5e_accel_ipsec_fs_cleanup(priv);
437451 destroy_workqueue(ipsec->wq);
438452
439453 ida_destroy(&ipsec->halloc);
....@@ -540,6 +554,9 @@
540554 return;
541555 }
542556
557
+ if (mlx5_is_ipsec_device(mdev))
558
+ netdev->gso_partial_features |= NETIF_F_GSO_ESP;
559
+
543560 mlx5_core_dbg(mdev, "mlx5e: ESP GSO capability turned on\n");
544561 netdev->features |= NETIF_F_GSO_ESP;
545562 netdev->hw_features |= NETIF_F_GSO_ESP;