From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c

Change-Id: I3b7db6db18fb5549420d904851a18e1907d07050
---
 .../ethernet/mellanox/mlx5/core/en/tc_tun.c   | 55 +++++++++++++++++--
 1 file changed, 50 insertions(+), 5 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /* Copyright (c) 2018 Mellanox Technologies. */
 
+#ifdef HAVE_TCF_TUNNEL_INFO
 #include <net/inet_ecn.h>
 #include <net/vxlan.h>
 #include <net/gre.h>
@@ -37,15 +38,25 @@ static void mlx5e_tc_tun_route_attr_clea
 
 struct mlx5e_tc_tunnel *mlx5e_get_tc_tun(struct net_device *tunnel_dev)
 {
+#if !defined(HAVE_TC_INDR_API) && !defined(CONFIG_COMPAT_KERNEL_4_14)
+/* in old kernels with egdev we don't pass the netdev so the filter_dev here
+ * is actually priv->netdev. we only assume and support vxlan */
+	return &vxlan_tunnel;
+#endif
+
 	if (netif_is_vxlan(tunnel_dev))
 		return &vxlan_tunnel;
+#ifdef HAVE_FLOW_DISSECTOR_KEY_ENC_OPTS
 	else if (netif_is_geneve(tunnel_dev))
 		return &geneve_tunnel;
+#endif
 	else if (netif_is_gretap(tunnel_dev) ||
 		 netif_is_ip6gretap(tunnel_dev))
 		return &gre_tunnel;
+#if defined(HAVE_NET_BAREUDP_H) && defined(HAVE_FLOW_DISSECTOR_MPLS_LSE)
 	else if (netif_is_bareudp(tunnel_dev))
 		return &mplsoudp_tunnel;
+#endif
 	else
 		return NULL;
 }
@@ -85,7 +96,11 @@ static int get_route_and_out_devs(struct
 	 * it's a LAG device, use the uplink
 	 */
 	*route_dev = dev;
+#ifdef HAVE_NETDEV_PORT_SAME_PARENT_ID
 	if (!netdev_port_same_parent_id(priv->netdev, real_dev) ||
+#else
+	if (!switchdev_port_same_parent_id(priv->netdev, real_dev) ||
+#endif
 	    dst_is_lag_dev || is_vlan_dev(*route_dev) ||
 	    netif_is_ovs_master(*route_dev))
 		*out_dev = uplink_dev;
@@ -140,7 +155,11 @@ static int mlx5e_route_lookup_ipv4_get(s
 		goto err_rt_release;
 	}
 
-	if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) {
+#ifdef HAVE_RT_GW_FAMILY
+       if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) {
+#else
+	if (mlx5_lag_is_multipath(mdev) && !rt->rt_uses_gateway) {
+#endif
 		ret = -ENETUNREACH;
 		goto err_rt_release;
 	}
@@ -443,24 +462,33 @@ release_neigh:
 	return err;
 }
 
-#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
 static int mlx5e_route_lookup_ipv6_get(struct mlx5e_priv *priv,
 				       struct net_device *dev,
 				       struct mlx5e_tc_tun_route_attr *attr)
 {
 	struct mlx5e_tc_tunnel *tunnel = mlx5e_get_tc_tun(dev);
 	struct net_device *route_dev;
+	struct dst_entry *dst = NULL;
 	struct net_device *out_dev;
-	struct dst_entry *dst;
 	struct neighbour *n;
+#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
 	int ret;
 
 	if (tunnel && tunnel->get_remote_ifindex)
 		attr->fl.fl6.flowi6_oif = tunnel->get_remote_ifindex(dev);
+#if defined(HAVE_IPV6_DST_LOOKUP_FLOW) || defined(HAVE_IPV6_DST_LOOKUP_FLOW_ADDR_CONF)
 	dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(dev), NULL, &attr->fl.fl6,
 					      NULL);
 	if (IS_ERR(dst))
 		return PTR_ERR(dst);
+#elif defined(HAVE_IPV6_DST_LOOKUP_TAKES_NET)
+	ret = ipv6_stub->ipv6_dst_lookup(dev_net(dev), NULL, &dst,
+					 &attr->fl.fl6);
+	if (ret < 0)
+		return ret;
+#endif
+	if (!dst)
+		return -EOPNOTSUPP;
 
 	if (!attr->ttl)
 		attr->ttl = ip6_dst_hoplimit(dst);
@@ -468,6 +496,9 @@ static int mlx5e_route_lookup_ipv6_get(s
 	ret = get_route_and_out_devs(priv, dst->dev, &route_dev, &out_dev);
 	if (ret < 0)
 		goto err_dst_release;
+#else
+	return -EOPNOTSUPP;
+#endif
 
 	dev_hold(route_dev);
 	n = dst_neigh_lookup(dst, &attr->fl.fl6.daddr);
@@ -711,7 +742,6 @@ release_neigh:
 	mlx5e_route_lookup_ipv6_put(&attr);
 	return err;
 }
-#endif
 
 int mlx5e_tc_tun_route_lookup(struct mlx5e_priv *priv,
 			      struct mlx5_flow_spec *spec,
@@ -813,9 +843,13 @@ int mlx5e_tc_tun_parse(struct net_device
 				       outer_headers);
 	void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
 				       outer_headers);
+#ifdef HAVE_TC_CLS_OFFLOAD_EXTACK
 	struct netlink_ext_ack *extack = f->common.extack;
+#else
+	struct netlink_ext_ack *extack = NULL;
+#endif
 	int err = 0;
-
+	
 	if (!tunnel) {
 		netdev_warn(priv->netdev,
 			    "decapsulation offload is not supported for %s net device\n",
@@ -829,6 +863,7 @@ int mlx5e_tc_tun_parse(struct net_device
 	if (tunnel->parse_udp_ports) {
 		err = tunnel->parse_udp_ports(priv, spec, f,
 					      headers_c, headers_v);
+
 		if (err)
 			goto out;
 	}
@@ -836,6 +871,7 @@ int mlx5e_tc_tun_parse(struct net_device
 	if (tunnel->parse_tunnel) {
 		err = tunnel->parse_tunnel(priv, spec, f,
 					   headers_c, headers_v);
+
 		if (err)
 			goto out;
 	}
@@ -949,16 +985,21 @@ int mlx5e_tc_tun_parse_udp_ports(struct
 				 struct flow_cls_offload *f,
 				 void *headers_c,
 				 void *headers_v)
+
 {
 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
+#ifdef HAVE_TC_CLS_OFFLOAD_EXTACK
 	struct netlink_ext_ack *extack = f->common.extack;
+#endif
 	struct flow_match_ports enc_ports;
 
 	/* Full udp dst port must be given */
 
 	if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
+#ifdef HAVE_TC_CLS_OFFLOAD_EXTACK
 		NL_SET_ERR_MSG_MOD(extack,
 				   "UDP tunnel decap filter must include enc_dst_port condition");
+#endif
 		netdev_warn(priv->netdev,
 			    "UDP tunnel decap filter must include enc_dst_port condition\n");
 		return -EOPNOTSUPP;
@@ -968,8 +1009,10 @@ int mlx5e_tc_tun_parse_udp_ports(struct
 
 	if (memchr_inv(&enc_ports.mask->dst, 0xff,
 		       sizeof(enc_ports.mask->dst))) {
+#ifdef HAVE_TC_CLS_OFFLOAD_EXTACK
 		NL_SET_ERR_MSG_MOD(extack,
 				   "UDP tunnel decap filter must match enc_dst_port fully");
+#endif
 		netdev_warn(priv->netdev,
 			    "UDP tunnel decap filter must match enc_dst_port fully\n");
 		return -EOPNOTSUPP;
@@ -997,3 +1040,5 @@ int mlx5e_tc_tun_parse_udp_ports(struct
 
 	return 0;
 }
+
+#endif /* HAVE_TCF_TUNNEL_INFO */
