--- zzzz-none-000/linux-4.4.60/net/xfrm/xfrm_input.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/net/xfrm/xfrm_input.c 2021-02-04 17:41:59.000000000 +0000 @@ -16,6 +16,11 @@ #include #include +#ifdef CONFIG_AVM_PA +#include +static struct avm_pa_dev_info xfrm_in_dev_info; +#endif + static struct kmem_cache *secpath_cachep __read_mostly; static DEFINE_SPINLOCK(xfrm_input_afinfo_lock); @@ -154,8 +159,8 @@ if (!pskb_may_pull(skb, hlen)) return -EINVAL; - *spi = *(__be32 *)(skb_transport_header(skb) + offset); - *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); + *spi = net_hdr_word(skb_transport_header(skb) + offset); + *seq = net_hdr_word(skb_transport_header(skb) + offset_seq); return 0; } @@ -294,6 +299,12 @@ skb_dst_force(skb); dev_hold(skb->dev); +#ifdef CONFIG_AVM_PA + avm_pa_add_local_session(skb, NULL); + /* xfrm session is better, allow to take over (if pid is registered) */ + avm_pa_add_xfrm_session(&xfrm_in_dev_info, skb, x); +#endif + nexthdr = x->type->input(x, skb); if (nexthdr == -EINPROGRESS) @@ -344,6 +355,23 @@ goto drop; } +#ifdef CONFIG_AVM_PA + /* Now decrypted and past inner_mode->input() which fixes up + * skb offsets for the inner headers. Try to accelerate the + * other half. Reset ingress_pid_handle to allow for a second + * session. + */ + 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 decrypted packet. Retry + * acceleration even someone said to not accelerate + * the encrypted packet. + */ + AVM_PKT_INFO(skb)->do_not_accelerate = 0; + if (avm_pa_dev_receive(&xfrm_in_dev_info, skb) == AVM_PA_RX_STOLEN) + return 0; +#endif + if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { decaps = 1; break; @@ -367,7 +395,7 @@ if (err) goto drop; - nf_reset(skb); + nf_reset_no_generic_ct(skb); if (decaps) { skb_dst_drop(skb); @@ -392,10 +420,60 @@ } EXPORT_SYMBOL(xfrm_input_resume); +#ifdef CONFIG_AVM_PA +static void xfrm_in_transmit(void *arg, struct sk_buff *skb) +{ + int ret; + struct xfrm_state *x = arg; + + if (skb->protocol == htons(ETH_P_IP)) { + XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; + XFRM_SPI_SKB_CB(skb)->family = AF_INET; + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; + XFRM_SPI_SKB_CB(skb)->family = AF_INET6; + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr); + } else { + net_err_ratelimited("%s: unhandlet protocol %d\n", + __func__, skb->protocol); + kfree_skb(skb); + return; + } + + /* esp_input expects skb->data at esp header because normally + * packets come via ip_local_deliver_finish() + */ + __skb_pull(skb, skb_transport_offset(skb)); + ret = xfrm_input(skb, x->id.proto, 0, 0); + + if (unlikely(ret != 0)) + net_err_ratelimited("%s failed: %d\n", __func__, ret); +} + +static void __init xfrm_input_avm_pa_register(void) +{ + struct avm_pa_pid_cfg cfg = {0}; + int ret; + + snprintf(cfg.name, sizeof(cfg.name), "xfrm_in"); + cfg.framing = avm_pa_framing_ipdev; + cfg.default_mtu = 0xffff; + cfg.tx_func = xfrm_in_transmit; + ret = avm_pa_dev_pid_register(&xfrm_in_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_input_init(void) { secpath_cachep = kmem_cache_create("secpath_cache", sizeof(struct sec_path), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); +#ifdef CONFIG_AVM_PA + xfrm_input_avm_pa_register(); +#endif }