--- zzzz-none-000/linux-4.4.60/net/xfrm/xfrm_output.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/net/xfrm/xfrm_output.c 2021-02-04 17:41:59.000000000 +0000 @@ -19,6 +19,11 @@ #include #include +#ifdef CONFIG_AVM_PA +#include +static struct avm_pa_dev_info xfrm_out_dev_info; +#endif + static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb); static int xfrm_skb_check_space(struct sk_buff *skb) @@ -134,11 +139,41 @@ struct net *net = xs_net(skb_dst(skb)->xfrm); while (likely((err = xfrm_output_one(skb, err)) == 0)) { - nf_reset(skb); + nf_reset_no_generic_ct(skb); - err = skb_dst(skb)->ops->local_out(net, skb->sk, skb); - if (unlikely(err != 1)) - goto out; +#ifdef CONFIG_AVM_PA + /* Now encrypted, try to accelerate the other half. + * Reset ingress_pid_handle to allow for a secondary session. + */ + if (!skb_dst(skb)->xfrm) { + AVM_PKT_INFO(skb)->ingress_pid_handle = 0; + /* The packet is wildy different now and we are going to + * open a separate session for the encrypted packet. Retry + * acceleration even someone said to not accelerate + * the decrypted packet. + */ + AVM_PKT_INFO(skb)->do_not_accelerate = 0; + /* Record local_out_pid_handle, this will enable the general + * call to avm_pa_local_out_receive() down the road + * to open a session. + */ + AVM_PKT_INFO(skb)->local_out_pid_handle = xfrm_out_dev_info.pid_handle; + } + /* We want to invert the likely indication because avm_pa + * very likely accelerates the packet. We take the opportunity + * and do a static call optimization for __ip_local_out as well. + */ + if (skb_dst(skb)->ops->local_out == __ip_local_out) { + err = __ip_local_out(net, skb->sk, skb); + if (likely(err != 1)) /* likely accelerated */ + goto out; + } else +#endif + { + err = skb_dst(skb)->ops->local_out(net, skb->sk, skb); + if (unlikely(err != 1)) + goto out; + } if (!skb_dst(skb)->xfrm) return dst_output(net, skb->sk, skb); @@ -199,6 +234,10 @@ struct net *net = dev_net(skb_dst(skb)->dev); int err; +#ifdef CONFIG_AVM_PA + avm_pa_add_xfrm_session(&xfrm_out_dev_info, skb, skb_dst(skb)->xfrm); +#endif + if (skb_is_gso(skb)) return xfrm_output_gso(net, sk, skb); @@ -250,3 +289,36 @@ xfrm_state_put_afinfo(afinfo); } EXPORT_SYMBOL_GPL(xfrm_local_error); + +#ifdef CONFIG_AVM_PA +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); +} +#endif + +void __init xfrm_output_init(void) +{ +#ifdef CONFIG_AVM_PA + xfrm_output_avm_pa_register(); +#endif +}