--- zzzz-none-000/linux-4.4.271/net/xfrm/xfrm_output.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/net/xfrm/xfrm_output.c 2023-04-19 10:22:30.000000000 +0000 @@ -19,6 +19,9 @@ #include #include +#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); static int xfrm_skb_check_space(struct sk_buff *skb) @@ -134,10 +137,26 @@ 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)) + 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) @@ -199,6 +218,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); @@ -251,3 +272,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(); +}