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

Change-Id: I8de9e75cfcf25e60d065737a33b2791cb771d1ae
---
 .../mellanox/mlx5/core/en_accel/ipsec.c       | 138 +++++++++++++++++-
 1 file changed, 132 insertions(+), 6 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -35,6 +35,7 @@
 #include <crypto/aead.h>
 #include <linux/inetdevice.h>
 #include <linux/netdevice.h>
+#include <net/arp.h>
 #include <net/netevent.h>
 
 #include "en.h"
@@ -51,10 +52,12 @@ static struct mlx5e_ipsec_sa_entry *to_i
 	return (struct mlx5e_ipsec_sa_entry *)x->xso.offload_handle;
 }
 
+#ifdef HAVE_XDO_DEV_POLICY_ADD
 static struct mlx5e_ipsec_pol_entry *to_ipsec_pol_entry(struct xfrm_policy *x)
 {
 	return (struct mlx5e_ipsec_pol_entry *)x->xdo.offload_handle;
 }
+#endif
 
 static void mlx5e_ipsec_handle_sw_limits(struct work_struct *_work)
 {
@@ -89,6 +92,7 @@ static void mlx5e_ipsec_handle_sw_limits
 
 static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
 {
+#ifdef HAVE_XFRM_DEV_TYPE
 	struct xfrm_state *x = sa_entry->x;
 	u32 seq_bottom = 0;
 	u32 esn, esn_msb;
@@ -148,6 +152,7 @@ static bool mlx5e_ipsec_update_esn_state
 		sa_entry->esn_state.overlap = 1;
 		return true;
 	}
+#endif
 
 	return false;
 }
@@ -280,7 +285,11 @@ static void mlx5e_ipsec_init_macs(struct
 	    attrs->type != XFRM_DEV_OFFLOAD_PACKET)
 		return;
 
+#if defined(HAVE_XFRM_STATE_REAL_DEV) || defined(HAVE_XFRM_DEV_REAL_DEV)
 	netdev = x->xso.real_dev;
+#else
+	netdev = x->xso.dev;
+#endif
 
 	mlx5_query_mac_address(mdev, addr);
 	switch (attrs->dir) {
@@ -345,7 +354,14 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(
 	/* iv len */
 	aes_gcm->icv_len = x->aead->alg_icv_len;
 
+#ifdef HAVE_XFRM_DEV_DIR
 	attrs->dir = x->xso.dir;
+#else
+	if (x->xso.flags & XFRM_OFFLOAD_INBOUND)
+		attrs->dir = XFRM_DEV_OFFLOAD_IN;
+	else
+		attrs->dir = XFRM_DEV_OFFLOAD_OUT;
+#endif
 
 	/* esn */
 	if (x->props.flags & XFRM_STATE_ESN) {
@@ -387,7 +403,11 @@ skip_replay_window:
 	memcpy(&attrs->saddr, x->props.saddr.a6, sizeof(attrs->saddr));
 	memcpy(&attrs->daddr, x->id.daddr.a6, sizeof(attrs->daddr));
 	attrs->family = x->props.family;
+#ifdef HAVE_XFRM_DEV_TYPE
 	attrs->type = x->xso.type;
+#else
+	attrs->type = XFRM_DEV_OFFLOAD_CRYPTO;
+#endif
 	attrs->reqid = x->props.reqid;
 	attrs->upspec.dport = ntohs(x->sel.dport);
 	attrs->upspec.dport_mask = ntohs(x->sel.dport_mask);
@@ -447,10 +467,12 @@ static int mlx5e_xfrm_validate_state(str
 			return -EINVAL;
 		}
 
+#ifdef HAVE_XFRM_DEV_TYPE
 		if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET) {
 			NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in packet offload mode only");
 			return -EINVAL;
 		}
+#endif
 
 		if (x->props.mode != XFRM_MODE_TRANSPORT) {
 			NL_SET_ERR_MSG_MOD(extack, "Encapsulation is supported in transport mode only");
@@ -494,6 +516,7 @@ static int mlx5e_xfrm_validate_state(str
 		return -EINVAL;
 	}
 
+#ifdef HAVE_XFRM_DEV_TYPE
 	switch (x->xso.type) {
 	case XFRM_DEV_OFFLOAD_CRYPTO:
 		if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_CRYPTO)) {
@@ -557,6 +580,7 @@ static int mlx5e_xfrm_validate_state(str
 		NL_SET_ERR_MSG_MOD(extack, "Unsupported xfrm offload type");
 		return -EINVAL;
 	}
+#endif
 	return 0;
 }
 
@@ -576,9 +600,11 @@ static void mlx5e_ipsec_set_esn_ops(stru
 {
 	struct xfrm_state *x = sa_entry->x;
 
+#if defined(HAVE_XFRM_DEV_DIR) && defined(HAVE_XFRM_DEV_TYPE)
 	if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO ||
 	    x->xso.dir != XFRM_DEV_OFFLOAD_OUT)
 		return;
+#endif
 
 	if (x->props.flags & XFRM_STATE_ESN) {
 		sa_entry->set_iv_op = mlx5e_ipsec_set_iv_esn;
@@ -588,6 +614,7 @@ static void mlx5e_ipsec_set_esn_ops(stru
 	sa_entry->set_iv_op = mlx5e_ipsec_set_iv;
 }
 
+#if defined(HAVE_XFRM_DEV_TYPE) && defined(HAVE_XFRM_DEV_DIR)
 static void mlx5e_ipsec_handle_netdev_event(struct work_struct *_work)
 {
 	struct mlx5e_ipsec_work *work =
@@ -611,9 +638,11 @@ static void mlx5e_ipsec_handle_netdev_ev
 	attrs->drop = false;
 	mlx5e_accel_ipsec_fs_modify(sa_entry);
 }
+#endif
 
 static int mlx5_ipsec_create_work(struct mlx5e_ipsec_sa_entry *sa_entry)
 {
+#if defined(HAVE_XFRM_DEV_TYPE) && defined(HAVE_XFRM_DEV_DIR)
 	struct xfrm_state *x = sa_entry->x;
 	struct mlx5e_ipsec_work *work;
 	void *data = NULL;
@@ -662,7 +691,35 @@ static int mlx5_ipsec_create_work(struct
 
 free_work:
 	kfree(work);
-	return -ENOMEM;
+
+	return 0;
+#else
+	struct xfrm_state *x = sa_entry->x;
+	struct mlx5e_ipsec_work *work;
+	void *data = NULL;
+
+	if (!(x->props.flags & XFRM_STATE_ESN))
+		return 0;
+
+	work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	data = kzalloc(sizeof(*sa_entry), GFP_KERNEL);
+	if (!data)
+		goto free_work;
+
+	INIT_WORK(&work->work, mlx5e_ipsec_modify_state);
+	work->data = data;
+	work->sa_entry = sa_entry;
+	sa_entry->work = work;
+	return 0;
+
+free_work:
+	kfree(work);
+
+	return 0;
+#endif
 }
 
 static int mlx5e_ipsec_create_dwork(struct mlx5e_ipsec_sa_entry *sa_entry)
@@ -670,8 +727,10 @@ static int mlx5e_ipsec_create_dwork(stru
 	struct xfrm_state *x = sa_entry->x;
 	struct mlx5e_ipsec_dwork *dwork;
 
+#ifdef HAVE_XFRM_DEV_TYPE
 	if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
 		return 0;
+#endif
 
 	if (x->lft.soft_packet_limit == XFRM_INF &&
 	    x->lft.hard_packet_limit == XFRM_INF &&
@@ -689,22 +748,37 @@ static int mlx5e_ipsec_create_dwork(stru
 	return 0;
 }
 
-static int mlx5e_xfrm_add_state(struct xfrm_state *x,
-				struct netlink_ext_ack *extack)
+static int mlx5e_xfrm_add_state(struct xfrm_state *x
+#ifdef HAVE_XDO_XFRM_ADD_STATE_GET_EXTACK
+				, struct netlink_ext_ack *extack
+#endif
+				)
 {
 	struct mlx5e_ipsec_sa_entry *sa_entry = NULL;
+#if defined(HAVE_XFRM_STATE_REAL_DEV) || defined(HAVE_XFRM_DEV_REAL_DEV)
 	struct net_device *netdev = x->xso.real_dev;
+#else
+	struct net_device *netdev = x->xso.dev;
+#endif
 	struct mlx5e_ipsec *ipsec;
 	struct mlx5e_priv *priv;
 	gfp_t gfp;
 	int err;
+#ifndef HAVE_XDO_XFRM_ADD_STATE_GET_EXTACK
+	struct netlink_ext_ack *extack;
+	extack = NULL;
+#endif
 
 	priv = netdev_priv(netdev);
 	if (!priv->ipsec)
 		return -EOPNOTSUPP;
 
 	ipsec = priv->ipsec;
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 	gfp = (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) ? GFP_ATOMIC : GFP_KERNEL;
+#else
+	gfp = GFP_ATOMIC;
+#endif
 	sa_entry = kzalloc(sizeof(*sa_entry), gfp);
 	if (!sa_entry)
 		return -ENOMEM;
@@ -712,8 +786,10 @@ static int mlx5e_xfrm_add_state(struct x
 	sa_entry->x = x;
 	sa_entry->ipsec = ipsec;
 	/* Check if this SA is originated from acquire flow temporary SA */
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
 		goto out;
+#endif
 
 	err = mlx5e_xfrm_validate_state(priv->mdev, x, extack);
 	if (err)
@@ -747,6 +823,7 @@ static int mlx5e_xfrm_add_state(struct x
 	if (err)
 		goto err_hw_ctx;
 
+#ifdef HAVE_XFRM_DEV_TYPE
 	if (x->props.mode == XFRM_MODE_TUNNEL &&
 	    x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
 	    !mlx5e_ipsec_fs_tunnel_enabled(sa_entry)) {
@@ -754,6 +831,7 @@ static int mlx5e_xfrm_add_state(struct x
 		err = -EINVAL;
 		goto err_add_rule;
 	}
+#endif
 
 	/* We use *_bh() variant because xfrm_timer_handler(), which runs
 	 * in softirq context, can reach our state delete logic and we need
@@ -770,12 +848,16 @@ static int mlx5e_xfrm_add_state(struct x
 		queue_delayed_work(ipsec->wq, &sa_entry->dwork->dwork,
 				   MLX5_IPSEC_RESCHED);
 
+#ifdef HAVE_XFRM_DEV_TYPE
 	if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
 	    x->props.mode == XFRM_MODE_TUNNEL)
 		xa_set_mark(&ipsec->sadb, sa_entry->ipsec_obj_id,
 			    MLX5E_IPSEC_TUNNEL_SA);
+#endif
 
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 out:
+#endif
 	x->xso.offload_handle = (unsigned long)sa_entry;
 	return 0;
 
@@ -793,7 +875,12 @@ unblock_ipsec:
 	mlx5_eswitch_unblock_ipsec(priv->mdev);
 err_xfrm:
 	kfree(sa_entry);
+#ifdef HAVE_NL_SET_ERR_MSG_WEAK_MOD
 	NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state");
+#else
+	if ((extack) && !(extack)->_msg)
+		NL_SET_ERR_MSG_MOD((extack), "Device failed to offload this state");
+#endif
 	return err;
 }
 
@@ -804,8 +891,10 @@ static void mlx5e_xfrm_del_state(struct
 	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 	struct mlx5e_ipsec_sa_entry *old;
 
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
 		return;
+#endif
 
 	old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id);
 	WARN_ON(old != sa_entry);
@@ -822,8 +911,10 @@ static void mlx5e_xfrm_free_state(struct
 	struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
 	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
 		goto sa_entry_free;
+#endif
 
 	if (sa_entry->work)
 		cancel_work_sync(&sa_entry->work->work);
@@ -838,7 +929,9 @@ static void mlx5e_xfrm_free_state(struct
 		kfree(sa_entry->work->data);
 	kfree(sa_entry->work);
 	mlx5_eswitch_unblock_ipsec(ipsec->mdev);
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 sa_entry_free:
+#endif
 	kfree(sa_entry);
 }
 
@@ -872,7 +965,11 @@ static int mlx5e_ipsec_netevent_event(st
 		}
 
 		x = sa_entry->x;
+#if defined(HAVE_XFRM_STATE_REAL_DEV) || defined(HAVE_XFRM_DEV_REAL_DEV)
 		netdev = x->xso.real_dev;
+#else
+		netdev = x->xso.dev;
+#endif
 		data = sa_entry->work->data;
 
 		neigh_ha_snapshot(data->addr, n, netdev);
@@ -995,6 +1092,7 @@ static void mlx5e_xfrm_advance_esn_state
 	queue_work(sa_entry->ipsec->wq, &work->work);
 }
 
+#if defined(HAVE_XDO_DEV_STATE_UPDATE_STATS) || defined(HAVE_XDO_DEV_STATE_UPDATE_CURLFT)
 static void mlx5e_xfrm_update_stats(struct xfrm_state *x)
 {
 	struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
@@ -1011,8 +1109,10 @@ static void mlx5e_xfrm_update_stats(stru
 		       lockdep_is_held(&dev_net(x->xso.real_dev)->xfrm.xfrm_cfg_mutex) ||
 		       lockdep_is_held(&dev_net(x->xso.real_dev)->xfrm.xfrm_state_lock));
 
+#ifdef HAVE_XFRM_DEV_OFFLOAD_FLAG_ACQ
 	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
 		return;
+#endif
 
 	if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) {
 		mlx5_fc_query_cached(ipsec_rule->auth.fc, &auth_bytes,
@@ -1053,7 +1153,9 @@ static void mlx5e_xfrm_update_stats(stru
 	success_bytes = bytes - auth_bytes - trailer_bytes - replay_bytes;
 	x->curlft.bytes += success_bytes - headers * success_packets;
 }
+#endif
 
+#ifdef HAVE_XDO_DEV_POLICY_ADD
 static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
 				      struct xfrm_policy *x,
 				      struct netlink_ext_ack *extack)
@@ -1071,11 +1173,13 @@ static int mlx5e_xfrm_validate_policy(st
 		return -EINVAL;
 	}
 
+#ifdef HAVE_XFRM_DEV_DIR
 	if (x->xdo.dir != XFRM_DEV_OFFLOAD_IN &&
 	    x->xdo.dir != XFRM_DEV_OFFLOAD_OUT) {
 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload forward policy");
 		return -EINVAL;
 	}
+#endif
 
 	if (!x->xfrm_vec[0].reqid && sel->proto == IPPROTO_IP &&
 	    addr6_all_zero(sel->saddr.a6) && addr6_all_zero(sel->daddr.a6)) {
@@ -1083,10 +1187,12 @@ static int mlx5e_xfrm_validate_policy(st
 		return -EINVAL;
 	}
 
+#ifdef HAVE_XFRM_DEV_TYPE
 	if (x->xdo.type != XFRM_DEV_OFFLOAD_PACKET) {
 		NL_SET_ERR_MSG_MOD(extack, "Unsupported xfrm offload type");
 		return -EINVAL;
 	}
+#endif
 
 	if (x->selector.proto != IPPROTO_IP &&
 	    x->selector.proto != IPPROTO_UDP &&
@@ -1115,7 +1221,9 @@ static int mlx5e_xfrm_validate_policy(st
 
 	return 0;
 }
+#endif
 
+#ifdef HAVE_XDO_DEV_POLICY_ADD
 static void
 mlx5e_ipsec_build_accel_pol_attrs(struct mlx5e_ipsec_pol_entry *pol_entry,
 				  struct mlx5_accel_pol_xfrm_attrs *attrs)
@@ -1140,14 +1248,24 @@ mlx5e_ipsec_build_accel_pol_attrs(struct
 	attrs->upspec.proto = sel->proto;
 	attrs->prio = x->priority;
 }
+#endif
 
-static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
-				 struct netlink_ext_ack *extack)
+#ifdef HAVE_XDO_DEV_POLICY_ADD
+static int mlx5e_xfrm_add_policy(struct xfrm_policy *x
+#ifdef HAVE_XDO_DEV_POLICY_ADD_GET_EXTACK
+				 , struct netlink_ext_ack *extack)
+#else
+				)
+#endif
 {
 	struct net_device *netdev = x->xdo.real_dev;
 	struct mlx5e_ipsec_pol_entry *pol_entry;
 	struct mlx5e_priv *priv;
 	int err;
+#ifndef HAVE_XDO_DEV_POLICY_ADD_GET_EXTACK
+	struct netlink_ext_ack *extack;
+	extack = NULL;
+#endif
 
 	priv = netdev_priv(netdev);
 	if (!priv->ipsec) {
@@ -1201,6 +1319,7 @@ static void mlx5e_xfrm_free_policy(struc
 
 	kfree(pol_entry);
 }
+#endif
 
 static const struct xfrmdev_ops mlx5e_ipsec_xfrmdev_ops = {
 	.xdo_dev_state_add	= mlx5e_xfrm_add_state,
@@ -1209,10 +1328,17 @@ static const struct xfrmdev_ops mlx5e_ip
 	.xdo_dev_offload_ok	= mlx5e_ipsec_offload_ok,
 	.xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state,
 
+#ifdef HAVE_XDO_DEV_STATE_UPDATE_STATS
 	.xdo_dev_state_update_stats = mlx5e_xfrm_update_stats,
+#endif
+#ifdef HAVE_XDO_DEV_STATE_UPDATE_CURLFT
+	.xdo_dev_state_update_curlft = mlx5e_xfrm_update_stats,
+#endif
+#ifdef HAVE_XDO_DEV_POLICY_ADD
 	.xdo_dev_policy_add = mlx5e_xfrm_add_policy,
 	.xdo_dev_policy_delete = mlx5e_xfrm_del_policy,
 	.xdo_dev_policy_free = mlx5e_xfrm_free_policy,
+#endif
 };
 
 void mlx5e_ipsec_build_netdev(struct mlx5e_priv *priv)
