Got cmm working

This commit is contained in:
2026-05-11 07:01:39 +08:00
parent 35f2edc0b5
commit 7411e1994b
23 changed files with 213 additions and 40 deletions

View File

@@ -0,0 +1,163 @@
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);