--- zzzz-none-000/linux-4.9.218/net/xfrm/xfrm_output.c 2020-04-02 15:20:41.000000000 +0000 +++ seale-7590ac-750/linux-4.9.218/net/xfrm/xfrm_output.c 2022-11-30 09:46:20.000000000 +0000 @@ -18,6 +18,12 @@ #include #include #include +#if IS_ENABLED(CONFIG_PPA_MPE_IP97) +#include +#endif + +#include +static struct avm_pa_dev_info xfrm_out_dev_info __read_mostly; static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb); @@ -137,10 +143,56 @@ struct net *net = xs_net(skb_dst(skb)->xfrm); while (likely((err = xfrm_output_one(skb, err)) == 0)) { - nf_reset(skb); +#if IS_ENABLED(CONFIG_PPA_MPE_IP97) + if (ppa_hook_session_add_fn) { +#if IS_ENABLED(CONFIG_INTEL_IPQOS_ACCEL_DISABLE) + /* check for 13th bit in NFMARK set by IPQOS classifier */ + /* If this bit is set, dont call PPA session add fn*/ + bool accel_st = 0; +#if IS_ENABLED(CONFIG_NETWORK_EXTMARK) + GET_DATA_FROM_MARK_OPT(skb->extmark, ACCELSEL_MASK, + ACCELSEL_START_BIT_POS, accel_st); +#endif /* CONFIG_NETWORK_EXTMARK*/ + if (accel_st == 0) { +#endif /* CONFIG_INTEL_IPQOS_ACCEL_DISABLE*/ + + struct nf_conn *ct = NULL; + enum ip_conntrack_info ctinfo; + uint32_t flags; + + ct = nf_ct_get(skb, &ctinfo); + + flags = 0; /* post routing */ + flags |= CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL ? + PPA_F_SESSION_ORG_DIR : + PPA_F_SESSION_REPLY_DIR; + + ppa_hook_session_add_fn(skb, ct, flags); +#if IS_ENABLED(CONFIG_INTEL_IPQOS_ACCEL_DISABLE) + } +#endif + } +#endif + nf_reset_no_generic_ct(skb); - err = skb_dst(skb)->ops->local_out(net, skb->sk, skb); - if (unlikely(err != 1)) + if (!skb_dst(skb)->xfrm) { + /* Now encrypted, try to accelerate the other half. + * The skb must be reset to allow for a secondary session. + */ + avm_pa_reset_skb(skb); + } + /* We want to invert the likely indication because avm_pa + * very likely accelerates the packet. We take the opportunity + * and do a direct call optimization as well. + */ + if (skb_dst(skb)->ops->local_out == __ip_local_out) + err = __ip_local_out(net, skb->sk, skb); + else if (skb_dst(skb)->ops->local_out == __ip6_local_out) + err = __ip6_local_out(net, skb->sk, skb); + else + err = skb_dst(skb)->ops->local_out(net, skb->sk, skb); + + if (likely(err != 1)) /* likely accelerated by avm_pa */ goto out; if (!skb_dst(skb)->xfrm) @@ -202,6 +254,8 @@ struct net *net = dev_net(skb_dst(skb)->dev); int err; + avm_pa_add_xfrm_session(&xfrm_out_dev_info, skb, skb_dst(skb)->xfrm); + if (skb_is_gso(skb)) return xfrm_output_gso(net, sk, skb); @@ -253,3 +307,32 @@ xfrm_state_put_afinfo(afinfo); } EXPORT_SYMBOL_GPL(xfrm_local_error); + +static void xfrm_out_transmit(void *arg, struct sk_buff *skb) +{ + int ret; + + ret = xfrm_output(NULL, skb); + if (unlikely(ret < 0)) + net_err_ratelimited("%s failed: %d\n", __func__, ret); +} + +static void __init xfrm_output_avm_pa_register(void) +{ + struct avm_pa_pid_cfg cfg = {0}; + int ret; + + snprintf(cfg.name, sizeof(cfg.name), "xfrm_out"); + cfg.framing = avm_pa_framing_ipdev; + cfg.default_mtu = 0xffff; + cfg.tx_func = xfrm_out_transmit; + ret = avm_pa_dev_pid_register(&xfrm_out_dev_info, &cfg); + if (ret < 0) + pr_err("%s: failed to register avm_pa pid %s: %d\n", + __func__, cfg.name, ret); +} + +void __init xfrm_output_init(void) +{ + xfrm_output_avm_pa_register(); +}