Blame SOURCES/0237-netdrv-net-mlx5e-Restore-tunnel-metadata-on-miss.patch

d8f823
From a4c8a21efaa55f5607829f5b667a06f32e00a2b0 Mon Sep 17 00:00:00 2001
d8f823
From: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Date: Tue, 19 May 2020 07:48:59 -0400
d8f823
Subject: [PATCH 237/312] [netdrv] net/mlx5e: Restore tunnel metadata on miss
d8f823
d8f823
Message-id: <20200519074934.6303-29-ahleihel@redhat.com>
d8f823
Patchwork-id: 310532
d8f823
Patchwork-instance: patchwork
d8f823
O-Subject: [RHEL8.3 BZ 1663246 28/63] net/mlx5e: Restore tunnel metadata on miss
d8f823
Bugzilla: 1790219 1790218 1663246
d8f823
RH-Acked-by: Marcelo Leitner <mleitner@redhat.com>
d8f823
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
d8f823
RH-Acked-by: John Linville <linville@redhat.com>
d8f823
RH-Acked-by: Ivan Vecera <ivecera@redhat.com>
d8f823
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
d8f823
RH-Acked-by: Kamal Heib <kheib@redhat.com>
d8f823
d8f823
Bugzilla: http://bugzilla.redhat.com/1663246
d8f823
Bugzilla: http://bugzilla.redhat.com/1790219
d8f823
Bugzilla: http://bugzilla.redhat.com/1790218
d8f823
Upstream: v5.7-rc1
d8f823
d8f823
commit b8ce90370977dbe24d2ed7271b65710ec9c40166
d8f823
Author: Paul Blakey <paulb@mellanox.com>
d8f823
Date:   Sun Feb 16 12:01:36 2020 +0200
d8f823
d8f823
    net/mlx5e: Restore tunnel metadata on miss
d8f823
d8f823
    In tunnel and chains setup, we decapsulate the packets on first chain hop,
d8f823
    if we miss on later chains, the packet will comes up without tunnel header,
d8f823
    so it won't be taken by the tunnel device automatically, which fills the
d8f823
    tunnel metadata, and further tc tunnel matches won't work.
d8f823
d8f823
    On miss, we get the tunnel mapping id, which was set on the chain 0 rule
d8f823
    that decapsulated the packet. This rule matched the tunnel outer
d8f823
    headers. From the tunnel mapping id, we get to this tunnel matches
d8f823
    and restore the equivalent tunnel info metadata dst on the skb.
d8f823
    We also set the skb->dev to the relevant device (tunnel device).
d8f823
    Now further tc processing can be done on the relevant device.
d8f823
d8f823
    Signed-off-by: Paul Blakey <paulb@mellanox.com>
d8f823
    Reviewed-by: Roi Dayan <roid@mellanox.com>
d8f823
    Reviewed-by: Oz Shlomo <ozsh@mellanox.com>
d8f823
    Reviewed-by: Mark Bloch <markb@mellanox.com>
d8f823
    Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
d8f823
d8f823
Signed-off-by: Alaa Hleihel <ahleihel@redhat.com>
d8f823
Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>
d8f823
---
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c |  10 ++-
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 110 ++++++++++++++++++++++--
d8f823
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.h |   9 +-
d8f823
 3 files changed, 117 insertions(+), 12 deletions(-)
d8f823
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
d8f823
index 1baeba194794..7aad59376ff4 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
d8f823
@@ -1194,6 +1194,7 @@ void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
d8f823
 	struct mlx5e_priv *priv = netdev_priv(netdev);
d8f823
 	struct mlx5e_rep_priv *rpriv  = priv->ppriv;
d8f823
 	struct mlx5_eswitch_rep *rep = rpriv->rep;
d8f823
+	struct mlx5e_tc_update_priv tc_priv = {};
d8f823
 	struct mlx5_wq_cyc *wq = &rq->wqe.wq;
d8f823
 	struct mlx5e_wqe_frag_info *wi;
d8f823
 	struct sk_buff *skb;
d8f823
@@ -1226,11 +1227,13 @@ void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
d8f823
 	if (rep->vlan && skb_vlan_tag_present(skb))
d8f823
 		skb_vlan_pop(skb);
d8f823
 
d8f823
-	if (!mlx5e_tc_rep_update_skb(cqe, skb))
d8f823
+	if (!mlx5e_tc_rep_update_skb(cqe, skb, &tc_priv))
d8f823
 		goto free_wqe;
d8f823
 
d8f823
 	napi_gro_receive(rq->cq.napi, skb);
d8f823
 
d8f823
+	mlx5_tc_rep_post_napi_receive(&tc_priv);
d8f823
+
d8f823
 free_wqe:
d8f823
 	mlx5e_free_rx_wqe(rq, wi, true);
d8f823
 wq_cyc_pop:
d8f823
@@ -1247,6 +1250,7 @@ void mlx5e_handle_rx_cqe_mpwrq_rep(struct mlx5e_rq *rq,
d8f823
 	u32 wqe_offset     = stride_ix << rq->mpwqe.log_stride_sz;
d8f823
 	u32 head_offset    = wqe_offset & (PAGE_SIZE - 1);
d8f823
 	u32 page_idx       = wqe_offset >> PAGE_SHIFT;
d8f823
+	struct mlx5e_tc_update_priv tc_priv = {};
d8f823
 	struct mlx5e_rx_wqe_ll *wqe;
d8f823
 	struct mlx5_wq_ll *wq;
d8f823
 	struct sk_buff *skb;
d8f823
@@ -1279,11 +1283,13 @@ void mlx5e_handle_rx_cqe_mpwrq_rep(struct mlx5e_rq *rq,
d8f823
 
d8f823
 	mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
d8f823
 
d8f823
-	if (!mlx5e_tc_rep_update_skb(cqe, skb))
d8f823
+	if (!mlx5e_tc_rep_update_skb(cqe, skb, &tc_priv))
d8f823
 		goto mpwrq_cqe_out;
d8f823
 
d8f823
 	napi_gro_receive(rq->cq.napi, skb);
d8f823
 
d8f823
+	mlx5_tc_rep_post_napi_receive(&tc_priv);
d8f823
+
d8f823
 mpwrq_cqe_out:
d8f823
 	if (likely(wi->consumed_strides < rq->mpwqe.num_strides))
d8f823
 		return;
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
d8f823
index a7d3cca88718..269258c5f961 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
d8f823
@@ -4689,19 +4689,102 @@ void mlx5e_tc_reoffload_flows_work(struct work_struct *work)
d8f823
 	mutex_unlock(&rpriv->unready_flows_lock);
d8f823
 }
d8f823
 
d8f823
+#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
d8f823
+static bool mlx5e_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb,
d8f823
+				 struct mlx5e_tc_update_priv *tc_priv,
d8f823
+				 u32 tunnel_id)
d8f823
+{
d8f823
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
d8f823
+	struct flow_dissector_key_enc_opts enc_opts = {};
d8f823
+	struct mlx5_rep_uplink_priv *uplink_priv;
d8f823
+	struct mlx5e_rep_priv *uplink_rpriv;
d8f823
+	struct metadata_dst *tun_dst;
d8f823
+	struct tunnel_match_key key;
d8f823
+	u32 tun_id, enc_opts_id;
d8f823
+	struct net_device *dev;
d8f823
+	int err;
d8f823
+
d8f823
+	enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK;
d8f823
+	tun_id = tunnel_id >> ENC_OPTS_BITS;
d8f823
+
d8f823
+	if (!tun_id)
d8f823
+		return true;
d8f823
+
d8f823
+	uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
d8f823
+	uplink_priv = &uplink_rpriv->uplink_priv;
d8f823
+
d8f823
+	err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key);
d8f823
+	if (err) {
d8f823
+		WARN_ON_ONCE(true);
d8f823
+		netdev_dbg(priv->netdev,
d8f823
+			   "Couldn't find tunnel for tun_id: %d, err: %d\n",
d8f823
+			   tun_id, err);
d8f823
+		return false;
d8f823
+	}
d8f823
+
d8f823
+	if (enc_opts_id) {
d8f823
+		err = mapping_find(uplink_priv->tunnel_enc_opts_mapping,
d8f823
+				   enc_opts_id, &enc_opts);
d8f823
+		if (err) {
d8f823
+			netdev_dbg(priv->netdev,
d8f823
+				   "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n",
d8f823
+				   enc_opts_id, err);
d8f823
+			return false;
d8f823
+		}
d8f823
+	}
d8f823
+
d8f823
+	tun_dst = tun_rx_dst(enc_opts.len);
d8f823
+	if (!tun_dst) {
d8f823
+		WARN_ON_ONCE(true);
d8f823
+		return false;
d8f823
+	}
d8f823
+
d8f823
+	ip_tunnel_key_init(&tun_dst->u.tun_info.key,
d8f823
+			   key.enc_ipv4.src, key.enc_ipv4.dst,
d8f823
+			   key.enc_ip.tos, key.enc_ip.ttl,
d8f823
+			   0, /* label */
d8f823
+			   key.enc_tp.src, key.enc_tp.dst,
d8f823
+			   key32_to_tunnel_id(key.enc_key_id.keyid),
d8f823
+			   TUNNEL_KEY);
d8f823
+
d8f823
+	if (enc_opts.len)
d8f823
+		ip_tunnel_info_opts_set(&tun_dst->u.tun_info, enc_opts.data,
d8f823
+					enc_opts.len, enc_opts.dst_opt_type);
d8f823
+
d8f823
+	skb_dst_set(skb, (struct dst_entry *)tun_dst);
d8f823
+	dev = dev_get_by_index(&init_net, key.filter_ifindex);
d8f823
+	if (!dev) {
d8f823
+		netdev_dbg(priv->netdev,
d8f823
+			   "Couldn't find tunnel device with ifindex: %d\n",
d8f823
+			   key.filter_ifindex);
d8f823
+		return false;
d8f823
+	}
d8f823
+
d8f823
+	/* Set tun_dev so we do dev_put() after datapath */
d8f823
+	tc_priv->tun_dev = dev;
d8f823
+
d8f823
+	skb->dev = dev;
d8f823
+
d8f823
+	return true;
d8f823
+}
d8f823
+#endif /* CONFIG_NET_TC_SKB_EXT */
d8f823
+
d8f823
 bool mlx5e_tc_rep_update_skb(struct mlx5_cqe64 *cqe,
d8f823
-			     struct sk_buff *skb)
d8f823
+			     struct sk_buff *skb,
d8f823
+			     struct mlx5e_tc_update_priv *tc_priv)
d8f823
 {
d8f823
 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
d8f823
+	u32 chain = 0, reg_c0, reg_c1, tunnel_id;
d8f823
 	struct tc_skb_ext *tc_skb_ext;
d8f823
 	struct mlx5_eswitch *esw;
d8f823
 	struct mlx5e_priv *priv;
d8f823
-	u32 chain = 0, reg_c0;
d8f823
+	int tunnel_moffset;
d8f823
 	int err;
d8f823
 
d8f823
 	reg_c0 = (be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK);
d8f823
 	if (reg_c0 == MLX5_FS_DEFAULT_FLOW_TAG)
d8f823
 		reg_c0 = 0;
d8f823
+	reg_c1 = be32_to_cpu(cqe->imm_inval_pkey);
d8f823
 
d8f823
 	if (!reg_c0)
d8f823
 		return true;
d8f823
@@ -4717,17 +4800,26 @@ bool mlx5e_tc_rep_update_skb(struct mlx5_cqe64 *cqe,
d8f823
 		return false;
d8f823
 	}
d8f823
 
d8f823
-	if (!chain)
d8f823
-		return true;
d8f823
+	if (chain) {
d8f823
+		tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
d8f823
+		if (!tc_skb_ext) {
d8f823
+			WARN_ON(1);
d8f823
+			return false;
d8f823
+		}
d8f823
 
d8f823
-	tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
d8f823
-	if (!tc_skb_ext) {
d8f823
-		WARN_ON_ONCE(1);
d8f823
-		return false;
d8f823
+		tc_skb_ext->chain = chain;
d8f823
 	}
d8f823
 
d8f823
-	tc_skb_ext->chain = chain;
d8f823
+	tunnel_moffset = mlx5e_tc_attr_to_reg_mappings[TUNNEL_TO_REG].moffset;
d8f823
+	tunnel_id = reg_c1 >> (8 * tunnel_moffset);
d8f823
+	return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id);
d8f823
 #endif /* CONFIG_NET_TC_SKB_EXT */
d8f823
 
d8f823
 	return true;
d8f823
 }
d8f823
+
d8f823
+void mlx5_tc_rep_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv)
d8f823
+{
d8f823
+	if (tc_priv->tun_dev)
d8f823
+		dev_put(tc_priv->tun_dev);
d8f823
+}
d8f823
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
d8f823
index 2fab76b0bec5..21cbde472b64 100644
d8f823
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
d8f823
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
d8f823
@@ -109,7 +109,14 @@ extern struct mlx5e_tc_attr_to_reg_mapping mlx5e_tc_attr_to_reg_mappings[];
d8f823
 bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
d8f823
 				    struct net_device *out_dev);
d8f823
 
d8f823
-bool mlx5e_tc_rep_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb);
d8f823
+struct mlx5e_tc_update_priv {
d8f823
+	struct net_device *tun_dev;
d8f823
+};
d8f823
+
d8f823
+bool mlx5e_tc_rep_update_skb(struct mlx5_cqe64 *cqe, struct sk_buff *skb,
d8f823
+			     struct mlx5e_tc_update_priv *tc_priv);
d8f823
+
d8f823
+void mlx5_tc_rep_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv);
d8f823
 
d8f823
 struct mlx5e_tc_mod_hdr_acts {
d8f823
 	int num_actions;
d8f823
-- 
d8f823
2.13.6
d8f823