--- zzzz-none-000/linux-4.9.231/net/xfrm/xfrm_input.c 2020-07-22 07:10:54.000000000 +0000 +++ falcon-5530-730/linux-4.9.231/net/xfrm/xfrm_input.c 2022-08-31 08:19:49.000000000 +0000 @@ -15,6 +15,17 @@ #include #include #include +#ifdef CONFIG_AVM_PA +#include +#endif + +#ifdef CONFIG_AVM_PA +#include +#ifdef AVM_PA_ADD_XFRM_SESSION +#define AVM_PA_XFRM +static struct avm_pa_dev_info xfrm_in_dev_info; +#endif +#endif static struct kmem_cache *secpath_cachep __read_mostly; @@ -234,18 +245,21 @@ seq = 0; if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { + secpath_reset(skb); XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); goto drop; } do { if (skb->sp->len == XFRM_MAX_DEPTH) { + secpath_reset(skb); XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); goto drop; } x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family); if (x == NULL) { + secpath_reset(skb); XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); xfrm_audit_state_notfound(skb, family, spi, seq); goto drop; @@ -294,6 +308,12 @@ skb_dst_force(skb); dev_hold(skb->dev); +#ifdef AVM_PA_XFRM + 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 +364,23 @@ goto drop; } +#ifdef AVM_PA_XFRM + /* 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 +404,7 @@ if (err) goto drop; - nf_reset(skb); + nf_reset_no_generic_ct(skb); if (decaps) { skb_dst_drop(skb); @@ -392,10 +429,60 @@ } EXPORT_SYMBOL(xfrm_input_resume); +#ifdef AVM_PA_XFRM +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 AVM_PA_XFRM + xfrm_input_avm_pa_register(); +#endif }