Skip to content

Commit 5017273

Browse files
committed
Merge tag 'mlx5-updates-2020-10-12' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux
Saeed Mahameed says: ==================== mlx5-updates-2020-10-12 Updates to mlx5 driver: - Cleanup fix of uininitialized pointer read - xfrm IPSec TX offload ==================== Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents d5e6f06 + 5be0190 commit 5017273

13 files changed

Lines changed: 406 additions & 36 deletions

File tree

drivers/net/ethernet/mellanox/mlx5/core/en/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ struct mlx5e_accel_fs_tcp;
236236

237237
struct mlx5e_flow_steering {
238238
struct mlx5_flow_namespace *ns;
239+
struct mlx5_flow_namespace *egress_ns;
239240
#ifdef CONFIG_MLX5_EN_RXNFC
240241
struct mlx5e_ethtool_steering ethtool;
241242
#endif

drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ struct mlx5e_accel_tx_state {
107107
#ifdef CONFIG_MLX5_EN_TLS
108108
struct mlx5e_accel_tx_tls_state tls;
109109
#endif
110+
#ifdef CONFIG_MLX5_EN_IPSEC
111+
struct mlx5e_accel_tx_ipsec_state ipsec;
112+
#endif
110113
};
111114

112115
static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
@@ -125,22 +128,46 @@ static inline bool mlx5e_accel_tx_begin(struct net_device *dev,
125128
}
126129
#endif
127130

131+
#ifdef CONFIG_MLX5_EN_IPSEC
132+
if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state) && xfrm_offload(skb)) {
133+
if (unlikely(!mlx5e_ipsec_handle_tx_skb(dev, skb, &state->ipsec)))
134+
return false;
135+
}
136+
#endif
137+
128138
return true;
129139
}
130140

141+
static inline bool mlx5e_accel_tx_is_ipsec_flow(struct mlx5e_accel_tx_state *state)
142+
{
143+
#ifdef CONFIG_MLX5_EN_IPSEC
144+
return mlx5e_ipsec_is_tx_flow(&state->ipsec);
145+
#endif
146+
147+
return false;
148+
}
149+
150+
static inline unsigned int mlx5e_accel_tx_ids_len(struct mlx5e_txqsq *sq,
151+
struct mlx5e_accel_tx_state *state)
152+
{
153+
#ifdef CONFIG_MLX5_EN_IPSEC
154+
if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state))
155+
return mlx5e_ipsec_tx_ids_len(&state->ipsec);
156+
#endif
157+
158+
return 0;
159+
}
160+
131161
/* Part of the eseg touched by TX offloads */
132162
#define MLX5E_ACCEL_ESEG_LEN offsetof(struct mlx5_wqe_eth_seg, mss)
133163

134164
static inline bool mlx5e_accel_tx_eseg(struct mlx5e_priv *priv,
135-
struct mlx5e_txqsq *sq,
136165
struct sk_buff *skb,
137166
struct mlx5_wqe_eth_seg *eseg)
138167
{
139168
#ifdef CONFIG_MLX5_EN_IPSEC
140-
if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state)) {
141-
if (unlikely(!mlx5e_ipsec_handle_tx_skb(priv, eseg, skb)))
142-
return false;
143-
}
169+
if (xfrm_offload(skb))
170+
mlx5e_ipsec_tx_build_eseg(priv, skb, eseg);
144171
#endif
145172

146173
#if IS_ENABLED(CONFIG_GENEVE)
@@ -153,11 +180,18 @@ static inline bool mlx5e_accel_tx_eseg(struct mlx5e_priv *priv,
153180

154181
static inline void mlx5e_accel_tx_finish(struct mlx5e_txqsq *sq,
155182
struct mlx5e_tx_wqe *wqe,
156-
struct mlx5e_accel_tx_state *state)
183+
struct mlx5e_accel_tx_state *state,
184+
struct mlx5_wqe_inline_seg *inlseg)
157185
{
158186
#ifdef CONFIG_MLX5_EN_TLS
159187
mlx5e_tls_handle_tx_wqe(sq, &wqe->ctrl, &state->tls);
160188
#endif
189+
190+
#ifdef CONFIG_MLX5_EN_IPSEC
191+
if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state) &&
192+
state->ipsec.xo && state->ipsec.tailen)
193+
mlx5e_ipsec_handle_tx_wqe(wqe, &state->ipsec, inlseg);
194+
#endif
161195
}
162196

163197
static inline int mlx5e_accel_init_rx(struct mlx5e_priv *priv)

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,9 @@ void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv)
560560
return;
561561
}
562562

563+
if (mlx5_is_ipsec_device(mdev))
564+
netdev->gso_partial_features |= NETIF_F_GSO_ESP;
565+
563566
mlx5_core_dbg(mdev, "mlx5e: ESP GSO capability turned on\n");
564567
netdev->features |= NETIF_F_GSO_ESP;
565568
netdev->hw_features |= NETIF_F_GSO_ESP;

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct mlx5e_ipsec_stats {
7676
};
7777

7878
struct mlx5e_accel_fs_esp;
79+
struct mlx5e_ipsec_tx;
7980

8081
struct mlx5e_ipsec {
8182
struct mlx5e_priv *en_priv;
@@ -87,6 +88,7 @@ struct mlx5e_ipsec {
8788
struct mlx5e_ipsec_stats stats;
8889
struct workqueue_struct *wq;
8990
struct mlx5e_accel_fs_esp *rx_fs;
91+
struct mlx5e_ipsec_tx *tx_fs;
9092
};
9193

9294
struct mlx5e_ipsec_esn_state {

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c

Lines changed: 174 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ struct mlx5e_accel_fs_esp {
3434
struct mlx5e_accel_fs_esp_prot fs_prot[ACCEL_FS_ESP_NUM_TYPES];
3535
};
3636

37+
struct mlx5e_ipsec_tx {
38+
struct mlx5_flow_table *ft;
39+
struct mutex mutex; /* Protect IPsec TX steering */
40+
u32 refcnt;
41+
};
42+
3743
/* IPsec RX flow steering */
3844
static enum mlx5e_traffic_types fs_esp2tt(enum accel_fs_esp_type i)
3945
{
@@ -323,6 +329,77 @@ static void rx_ft_put(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
323329
mutex_unlock(&fs_prot->prot_mutex);
324330
}
325331

332+
/* IPsec TX flow steering */
333+
static int tx_create(struct mlx5e_priv *priv)
334+
{
335+
struct mlx5_flow_table_attr ft_attr = {};
336+
struct mlx5e_ipsec *ipsec = priv->ipsec;
337+
struct mlx5_flow_table *ft;
338+
int err;
339+
340+
priv->fs.egress_ns =
341+
mlx5_get_flow_namespace(priv->mdev,
342+
MLX5_FLOW_NAMESPACE_EGRESS_KERNEL);
343+
if (!priv->fs.egress_ns)
344+
return -EOPNOTSUPP;
345+
346+
ft_attr.max_fte = NUM_IPSEC_FTE;
347+
ft_attr.autogroup.max_num_groups = 1;
348+
ft = mlx5_create_auto_grouped_flow_table(priv->fs.egress_ns, &ft_attr);
349+
if (IS_ERR(ft)) {
350+
err = PTR_ERR(ft);
351+
netdev_err(priv->netdev, "fail to create ipsec tx ft err=%d\n", err);
352+
return err;
353+
}
354+
ipsec->tx_fs->ft = ft;
355+
return 0;
356+
}
357+
358+
static void tx_destroy(struct mlx5e_priv *priv)
359+
{
360+
struct mlx5e_ipsec *ipsec = priv->ipsec;
361+
362+
if (IS_ERR_OR_NULL(ipsec->tx_fs->ft))
363+
return;
364+
365+
mlx5_destroy_flow_table(ipsec->tx_fs->ft);
366+
ipsec->tx_fs->ft = NULL;
367+
}
368+
369+
static int tx_ft_get(struct mlx5e_priv *priv)
370+
{
371+
struct mlx5e_ipsec_tx *tx_fs = priv->ipsec->tx_fs;
372+
int err = 0;
373+
374+
mutex_lock(&tx_fs->mutex);
375+
if (tx_fs->refcnt++)
376+
goto out;
377+
378+
err = tx_create(priv);
379+
if (err) {
380+
tx_fs->refcnt--;
381+
goto out;
382+
}
383+
384+
out:
385+
mutex_unlock(&tx_fs->mutex);
386+
return err;
387+
}
388+
389+
static void tx_ft_put(struct mlx5e_priv *priv)
390+
{
391+
struct mlx5e_ipsec_tx *tx_fs = priv->ipsec->tx_fs;
392+
393+
mutex_lock(&tx_fs->mutex);
394+
if (--tx_fs->refcnt)
395+
goto out;
396+
397+
tx_destroy(priv);
398+
399+
out:
400+
mutex_unlock(&tx_fs->mutex);
401+
}
402+
326403
static void setup_fte_common(struct mlx5_accel_esp_xfrm_attrs *attrs,
327404
u32 ipsec_obj_id,
328405
struct mlx5_flow_spec *spec,
@@ -457,6 +534,54 @@ static int rx_add_rule(struct mlx5e_priv *priv,
457534
return err;
458535
}
459536

537+
static int tx_add_rule(struct mlx5e_priv *priv,
538+
struct mlx5_accel_esp_xfrm_attrs *attrs,
539+
u32 ipsec_obj_id,
540+
struct mlx5e_ipsec_rule *ipsec_rule)
541+
{
542+
struct mlx5_flow_act flow_act = {};
543+
struct mlx5_flow_handle *rule;
544+
struct mlx5_flow_spec *spec;
545+
int err = 0;
546+
547+
err = tx_ft_get(priv);
548+
if (err)
549+
return err;
550+
551+
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
552+
if (!spec) {
553+
err = -ENOMEM;
554+
goto out;
555+
}
556+
557+
setup_fte_common(attrs, ipsec_obj_id, spec, &flow_act);
558+
559+
/* Add IPsec indicator in metadata_reg_a */
560+
spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
561+
MLX5_SET(fte_match_param, spec->match_criteria, misc_parameters_2.metadata_reg_a,
562+
MLX5_ETH_WQE_FT_META_IPSEC);
563+
MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_a,
564+
MLX5_ETH_WQE_FT_META_IPSEC);
565+
566+
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW |
567+
MLX5_FLOW_CONTEXT_ACTION_IPSEC_ENCRYPT;
568+
rule = mlx5_add_flow_rules(priv->ipsec->tx_fs->ft, spec, &flow_act, NULL, 0);
569+
if (IS_ERR(rule)) {
570+
err = PTR_ERR(rule);
571+
netdev_err(priv->netdev, "fail to add ipsec rule attrs->action=0x%x, err=%d\n",
572+
attrs->action, err);
573+
goto out;
574+
}
575+
576+
ipsec_rule->rule = rule;
577+
578+
out:
579+
kvfree(spec);
580+
if (err)
581+
tx_ft_put(priv);
582+
return err;
583+
}
584+
460585
static void rx_del_rule(struct mlx5e_priv *priv,
461586
struct mlx5_accel_esp_xfrm_attrs *attrs,
462587
struct mlx5e_ipsec_rule *ipsec_rule)
@@ -470,15 +595,27 @@ static void rx_del_rule(struct mlx5e_priv *priv,
470595
rx_ft_put(priv, attrs->is_ipv6 ? ACCEL_FS_ESP6 : ACCEL_FS_ESP4);
471596
}
472597

598+
static void tx_del_rule(struct mlx5e_priv *priv,
599+
struct mlx5e_ipsec_rule *ipsec_rule)
600+
{
601+
mlx5_del_flow_rules(ipsec_rule->rule);
602+
ipsec_rule->rule = NULL;
603+
604+
tx_ft_put(priv);
605+
}
606+
473607
int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_priv *priv,
474608
struct mlx5_accel_esp_xfrm_attrs *attrs,
475609
u32 ipsec_obj_id,
476610
struct mlx5e_ipsec_rule *ipsec_rule)
477611
{
478-
if (!priv->ipsec->rx_fs || attrs->action != MLX5_ACCEL_ESP_ACTION_DECRYPT)
612+
if (!priv->ipsec->rx_fs)
479613
return -EOPNOTSUPP;
480614

481-
return rx_add_rule(priv, attrs, ipsec_obj_id, ipsec_rule);
615+
if (attrs->action == MLX5_ACCEL_ESP_ACTION_DECRYPT)
616+
return rx_add_rule(priv, attrs, ipsec_obj_id, ipsec_rule);
617+
else
618+
return tx_add_rule(priv, attrs, ipsec_obj_id, ipsec_rule);
482619
}
483620

484621
void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv,
@@ -488,7 +625,18 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv,
488625
if (!priv->ipsec->rx_fs)
489626
return;
490627

491-
rx_del_rule(priv, attrs, ipsec_rule);
628+
if (attrs->action == MLX5_ACCEL_ESP_ACTION_DECRYPT)
629+
rx_del_rule(priv, attrs, ipsec_rule);
630+
else
631+
tx_del_rule(priv, ipsec_rule);
632+
}
633+
634+
static void fs_cleanup_tx(struct mlx5e_priv *priv)
635+
{
636+
mutex_destroy(&priv->ipsec->tx_fs->mutex);
637+
WARN_ON(priv->ipsec->tx_fs->refcnt);
638+
kfree(priv->ipsec->tx_fs);
639+
priv->ipsec->tx_fs = NULL;
492640
}
493641

494642
static void fs_cleanup_rx(struct mlx5e_priv *priv)
@@ -507,6 +655,17 @@ static void fs_cleanup_rx(struct mlx5e_priv *priv)
507655
priv->ipsec->rx_fs = NULL;
508656
}
509657

658+
static int fs_init_tx(struct mlx5e_priv *priv)
659+
{
660+
priv->ipsec->tx_fs =
661+
kzalloc(sizeof(struct mlx5e_ipsec_tx), GFP_KERNEL);
662+
if (!priv->ipsec->tx_fs)
663+
return -ENOMEM;
664+
665+
mutex_init(&priv->ipsec->tx_fs->mutex);
666+
return 0;
667+
}
668+
510669
static int fs_init_rx(struct mlx5e_priv *priv)
511670
{
512671
struct mlx5e_accel_fs_esp_prot *fs_prot;
@@ -532,13 +691,24 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_priv *priv)
532691
if (!priv->ipsec->rx_fs)
533692
return;
534693

694+
fs_cleanup_tx(priv);
535695
fs_cleanup_rx(priv);
536696
}
537697

538698
int mlx5e_accel_ipsec_fs_init(struct mlx5e_priv *priv)
539699
{
700+
int err;
701+
540702
if (!mlx5_is_ipsec_device(priv->mdev) || !priv->ipsec)
541703
return -EOPNOTSUPP;
542704

543-
return fs_init_rx(priv);
705+
err = fs_init_tx(priv);
706+
if (err)
707+
return err;
708+
709+
err = fs_init_rx(priv);
710+
if (err)
711+
fs_cleanup_tx(priv);
712+
713+
return err;
544714
}

0 commit comments

Comments
 (0)