--- zzzz-none-000/linux-4.9.276/net/xfrm/xfrm_state.c 2021-07-20 14:21:16.000000000 +0000 +++ falcon-5530-750/linux-4.9.276/net/xfrm/xfrm_state.c 2023-04-05 08:19:02.000000000 +0000 @@ -27,7 +27,16 @@ #include #include "xfrm_hash.h" - +#if IS_ENABLED(CONFIG_PPA_MPE_IP97) +#include +#include +#include +#include +struct ltq_crypto_ipsec_params *(*ltq_ipsec_get_param_hook)(u32 spi) = NULL; +EXPORT_SYMBOL(ltq_ipsec_get_param_hook); +void (*ltq_destroy_ipsec_sa_hook)(struct ltq_crypto_ipsec_params *req) = NULL; +EXPORT_SYMBOL(ltq_destroy_ipsec_sa_hook); +#endif #define xfrm_state_deref_prot(table, net) \ rcu_dereference_protected((table), lockdep_is_held(&(net)->xfrm.xfrm_state_lock)) @@ -404,6 +413,9 @@ long next = LONG_MAX; int warn = 0; int err = 0; +#if defined(CONFIG_PPA_MPE_IP97) + struct ltq_crypto_ipsec_params *params = NULL; +#endif spin_lock(&x->lock); if (x->km.state == XFRM_STATE_DEAD) @@ -478,6 +490,21 @@ xfrm_audit_state_delete(x, err ? 0 : 1, true); +#if defined(CONFIG_PPA_MPE_IP97) + /* PPA Del SA callback needs to be invoked after re-keyed timeout, where older SA is removed */ + if (ppa_hook_session_ipsec_del_fn) + ppa_hook_session_ipsec_del_fn(x); + + if (ltq_ipsec_get_param_hook && ltq_destroy_ipsec_sa_hook) { + params = ltq_ipsec_get_param_hook(x->id.spi); + if (!params) { + pr_err("No entry found for spi = 0x%08x, unable to remove SA after rekeyed timeout\n", x->id.spi); + goto out; + } + ltq_destroy_ipsec_sa_hook(params); + } +#endif /* CONFIG_PPA_MPE_IP97 */ + out: spin_unlock(&x->lock); return HRTIMER_NORESTART; @@ -628,6 +655,7 @@ } } } + if (cnt) err = 0; @@ -797,6 +825,7 @@ int error = 0; struct xfrm_state *best = NULL; u32 mark = pol->mark.v & pol->mark.m; + u32 if_id = fl->flowi_xfrm.if_id; unsigned short encap_family = tmpl->encap_family; unsigned int sequence; struct km_event c; @@ -811,6 +840,7 @@ if (x->props.family == encap_family && x->props.reqid == tmpl->reqid && (mark & x->mark.m) == x->mark.v && + x->if_id == if_id && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, encap_family) && tmpl->mode == x->props.mode && @@ -827,6 +857,7 @@ if (x->props.family == encap_family && x->props.reqid == tmpl->reqid && (mark & x->mark.m) == x->mark.v && + x->if_id == if_id && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_addr_equal(&x->id.daddr, daddr, encap_family) && tmpl->mode == x->props.mode && @@ -866,6 +897,7 @@ * to current session. */ xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family); memcpy(&x->mark, &pol->mark, sizeof(x->mark)); + x->if_id = if_id; error = security_xfrm_state_alloc_acquire(x, pol->security, fl->flowi_secid); if (error) { @@ -923,7 +955,7 @@ } struct xfrm_state * -xfrm_stateonly_find(struct net *net, u32 mark, +xfrm_stateonly_find(struct net *net, u32 mark, u32 if_id, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, u8 mode, u8 proto, u32 reqid) { @@ -936,6 +968,7 @@ if (x->props.family == family && x->props.reqid == reqid && (mark & x->mark.m) == x->mark.v && + x->if_id == if_id && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && mode == x->props.mode && @@ -1016,11 +1049,13 @@ struct xfrm_state *x; unsigned int h; u32 mark = xnew->mark.v & xnew->mark.m; + u32 if_id = xnew->if_id; h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == reqid && + x->if_id == if_id && (mark & x->mark.m) == x->mark.v && xfrm_addr_equal(&x->id.daddr, &xnew->id.daddr, family) && xfrm_addr_equal(&x->props.saddr, &xnew->props.saddr, family)) @@ -1043,7 +1078,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, const struct xfrm_mark *m, unsigned short family, u8 mode, - u32 reqid, u8 proto, + u32 reqid, u32 if_id, u8 proto, const xfrm_address_t *daddr, const xfrm_address_t *saddr, int create) @@ -1098,6 +1133,7 @@ x->props.family = family; x->props.mode = mode; x->props.reqid = reqid; + x->if_id = if_id; x->mark.v = m->v; x->mark.m = m->m; x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; @@ -1152,7 +1188,7 @@ if (use_spi && !x1) x1 = __find_acq_core(net, &x->mark, family, x->props.mode, - x->props.reqid, x->id.proto, + x->props.reqid, x->if_id, x->id.proto, &x->id.daddr, &x->props.saddr, 0); __xfrm_state_bump_genids(x); @@ -1244,6 +1280,7 @@ x->props.flags = orig->props.flags; x->props.extra_flags = orig->props.extra_flags; + x->if_id = orig->if_id; x->tfcpad = orig->tfcpad; x->replay_maxdiff = orig->replay_maxdiff; x->replay_maxage = orig->replay_maxage; @@ -1461,13 +1498,13 @@ struct xfrm_state * xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid, - u8 proto, const xfrm_address_t *daddr, + u32 if_id, u8 proto, const xfrm_address_t *daddr, const xfrm_address_t *saddr, int create, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&net->xfrm.xfrm_state_lock); - x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create); + x = __find_acq_core(net, mark, family, mode, reqid, if_id, proto, daddr, saddr, create); spin_unlock_bh(&net->xfrm.xfrm_state_lock); return x;