--- zzzz-none-000/linux-4.19.183/net/xfrm/xfrm_input.c 2021-03-24 10:07:39.000000000 +0000 +++ bcm63-7530ax-756/linux-4.19.183/net/xfrm/xfrm_input.c 2023-06-28 08:54:21.000000000 +0000 @@ -21,6 +21,9 @@ #include #include +#include +static struct avm_pa_dev_info xfrm_in_dev_info __read_mostly; + struct xfrm_trans_tasklet { struct tasklet_struct tasklet; struct sk_buff_head queue; @@ -396,6 +399,9 @@ dev_hold(skb->dev); + /* xfrm session is better, allow to take over (if pid is registered) */ + avm_pa_add_xfrm_session(&xfrm_in_dev_info, skb, x); + if (crypto_done) nexthdr = x->type_offload->input_tail(x, skb); else @@ -449,6 +455,10 @@ goto drop; } + avm_pa_reset_skb(skb); + if (avm_pa_dev_local_out(&xfrm_in_dev_info, skb) == AVM_PA_RX_STOLEN) + return 0; + if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { decaps = 1; break; @@ -473,7 +483,7 @@ if (err) goto drop; - nf_reset(skb); + nf_reset_no_generic_ct(skb); if (decaps) { if (skb->sp) @@ -544,6 +554,51 @@ } EXPORT_SYMBOL(xfrm_trans_queue); +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); +} + void __init xfrm_input_init(void) { int err; @@ -567,4 +622,6 @@ tasklet_init(&trans->tasklet, xfrm_trans_reinject, (unsigned long)trans); } + + xfrm_input_avm_pa_register(); }