penguin/monok8s

k8s image for Mono Gateway Dev Kit

patches/ask/kernel/0136-net__xfrm__xfrm_policy.c.patch

raw ยท 4689 bytes

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 62486f8..3cbe4f8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -48,6 +48,11 @@
 #include <net/inet_dscp.h>
 
 #include "xfrm_hash.h"
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+#include "ipsec_flow.h"
+#endif
+#endif
 
 #define XFRM_QUEUE_TMO_MIN ((unsigned)(HZ/10))
 #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
@@ -179,6 +184,15 @@ static struct xfrm_policy_afinfo const __rcu *xfrm_policy_afinfo[AF_INET6 + 1]
 
 static struct kmem_cache *xfrm_dst_cache __ro_after_init;
 
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+extern int ipsec_nlkey_flow(u16 xfrm_nr, u16 *xfrm_handle,
+		const struct flowi *fl, u16 family, u16 dir, u16 ignore_neigh);
+int ipsec_flow_init(struct net *net);
+void ipsec_flow_fini(struct net *net);
+#endif
+#endif
+
 static struct rhashtable xfrm_policy_inexact_table;
 static const struct rhashtable_params xfrm_pol_inexact_params;
 
@@ -2599,6 +2613,17 @@ static dscp_t xfrm_get_dscp(const struct flowi *fl, int family)
 	return 0;
 }
 
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+int xfrm_get_tos(const struct flowi *fl, int family)
+{
+	if (family == AF_INET)
+		return inet_dscp_to_dsfield(fl->u.ip4.flowi4_dscp) & INET_DSCP_MASK;
+
+	return 0;
+}
+EXPORT_SYMBOL(xfrm_get_tos);
+#endif
+
 static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
 {
 	const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
@@ -3295,6 +3320,37 @@ no_transform:
 		dst = dst_orig;
 	}
 
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+	{
+		struct dst_entry *dst1 = dst;
+		struct xfrm_state *x;
+		u16 xfrm_handle[XFRM_POLICY_TYPE_MAX];
+		u16 ignore_neigh = 0;
+
+		num_xfrms = 0;
+		memset(xfrm_handle, 0, XFRM_POLICY_TYPE_MAX * sizeof(u16));
+		while (((x = dst1->xfrm) != NULL) &&
+		       (num_xfrms < XFRM_POLICY_TYPE_MAX)) {
+			xfrm_handle[num_xfrms++] = x->handle;
+			if (x->props.mode == XFRM_MODE_TUNNEL)
+				ignore_neigh = 1;
+			dst1 = xfrm_dst_child(dst1);
+
+			if (dst1 == NULL) {
+				err = -EHOSTUNREACH;
+				goto error;
+			}
+		}
+		if (ipsec_flow_add(net, fl, family, dir, xfrm_handle)) {
+			/* sent flow notification to cmm with sa_handle */
+			ipsec_nlkey_flow(num_xfrms, xfrm_handle, fl, family,
+					 (unsigned short)dir, ignore_neigh);
+		}
+	}
+#endif
+#endif
+
 ok:
 	xfrm_pols_put(pols, drop_pols);
 	if (dst->xfrm &&
@@ -3853,6 +3909,34 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 			goto reject;
 		}
 
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+		{
+			struct xfrm_state *x;
+			u16 xfrm_handle[XFRM_POLICY_TYPE_MAX];
+
+			xfrm_nr = 0;
+			memset(xfrm_handle, 0, XFRM_POLICY_TYPE_MAX * sizeof(u16));
+			for (i = sp->len - 1;
+			     (i >= 0) && (xfrm_nr < XFRM_POLICY_TYPE_MAX); i--) {
+				x = sp->xvec[i];
+				xfrm_handle[xfrm_nr++] = x->handle;
+			}
+			if (ipsec_flow_add(net, (const struct flowi *)&fl, family, dir,
+					   xfrm_handle)) {
+				/* sent flow notification to cmm with sa_handle */
+				ipsec_nlkey_flow(xfrm_nr, xfrm_handle,
+						 (const struct flowi *)&fl, family, dir, 0);
+			}
+		}
+
+		/* Hub and spoke changes: Setting the POLICY_IN direction in the packet */
+		skb->ipsec_xfrm_dir |= (1 << XFRM_POLICY_IN);
+
+std_path:
+#endif
+#endif
+
 		xfrm_pols_put(pols, npols);
 		sp->verified_cnt = k;
 
@@ -4328,6 +4412,14 @@ static int __net_init xfrm_net_init(struct net *net)
 	if (rv < 0)
 		goto out_sysctl;
 
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+	rv = ipsec_flow_init(net);
+	if (rv < 0)
+		goto out_ipsec_flow;
+#endif
+#endif
+
 	rv = xfrm_nat_keepalive_net_init(net);
 	if (rv < 0)
 		goto out_nat_keepalive;
@@ -4335,6 +4427,12 @@ static int __net_init xfrm_net_init(struct net *net)
 	return 0;
 
 out_nat_keepalive:
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+	ipsec_flow_fini(net);
+out_ipsec_flow:
+#endif
+#endif
 	xfrm_sysctl_fini(net);
 out_sysctl:
 	xfrm_policy_fini(net);
@@ -4349,6 +4447,11 @@ out_statistics:
 static void __net_exit xfrm_net_exit(struct net *net)
 {
 	xfrm_nat_keepalive_net_fini(net);
+#ifdef IPSEC_FLOW_CACHE
+#if defined(CONFIG_INET_IPSEC_OFFLOAD) || defined(CONFIG_INET6_IPSEC_OFFLOAD)
+	ipsec_flow_fini(net);
+#endif
+#endif
 	xfrm_sysctl_fini(net);
 	xfrm_policy_fini(net);
 	xfrm_state_fini(net);