Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'ipsec-next-2025-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next

Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2025-07-23

1) Optimize to hold device only for the asynchronous decryption,
where it is really needed.
From Jianbo Liu.

2) Align our inbund SA lookup to RFC 4301. Only SPI and protocol
should be used for an inbound SA lookup.
From Aakash Kumar S.

3) Skip redundant statistics update for xfrm crypto offload.
From Jianbo Liu.

Please pull or let me know if there are problems.

* tag 'ipsec-next-2025-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next:
xfrm: Skip redundant statistics update for crypto offload
xfrm: Duplicate SPI Handling
xfrm: hold device only for the asynchronous decryption
====================

Link: https://patch.msgid.link/20250723080402.3439619-1-steffen.klassert@secunet.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+59 -39
+9 -8
net/xfrm/xfrm_input.c
··· 503 503 /* An encap_type of -1 indicates async resumption. */ 504 504 if (encap_type == -1) { 505 505 async = 1; 506 + dev_put(skb->dev); 506 507 seq = XFRM_SKB_CB(skb)->seq.input.low; 507 508 goto resume; 508 509 } ··· 650 649 XFRM_SKB_CB(skb)->seq.input.low = seq; 651 650 XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; 652 651 653 - dev_hold(skb->dev); 654 - 655 - if (crypto_done) 652 + if (crypto_done) { 656 653 nexthdr = x->type_offload->input_tail(x, skb); 657 - else 654 + } else { 655 + dev_hold(skb->dev); 656 + 658 657 nexthdr = x->type->input(x, skb); 658 + if (nexthdr == -EINPROGRESS) 659 + return 0; 659 660 660 - if (nexthdr == -EINPROGRESS) 661 - return 0; 661 + dev_put(skb->dev); 662 + } 662 663 resume: 663 - dev_put(skb->dev); 664 - 665 664 spin_lock(&x->lock); 666 665 if (nexthdr < 0) { 667 666 if (nexthdr == -EBADMSG) {
+50 -31
net/xfrm/xfrm_state.c
··· 1711 1711 } 1712 1712 EXPORT_SYMBOL(xfrm_state_lookup_byspi); 1713 1713 1714 + static struct xfrm_state *xfrm_state_lookup_spi_proto(struct net *net, __be32 spi, u8 proto) 1715 + { 1716 + struct xfrm_state *x; 1717 + unsigned int i; 1718 + 1719 + rcu_read_lock(); 1720 + for (i = 0; i <= net->xfrm.state_hmask; i++) { 1721 + hlist_for_each_entry_rcu(x, &net->xfrm.state_byspi[i], byspi) { 1722 + if (x->id.spi == spi && x->id.proto == proto) { 1723 + if (!xfrm_state_hold_rcu(x)) 1724 + continue; 1725 + rcu_read_unlock(); 1726 + return x; 1727 + } 1728 + } 1729 + } 1730 + rcu_read_unlock(); 1731 + return NULL; 1732 + } 1733 + 1714 1734 static void __xfrm_state_insert(struct xfrm_state *x) 1715 1735 { 1716 1736 struct net *net = xs_net(x); ··· 2282 2262 2283 2263 int xfrm_state_check_expire(struct xfrm_state *x) 2284 2264 { 2285 - xfrm_dev_state_update_stats(x); 2265 + /* All counters which are needed to decide if state is expired 2266 + * are handled by SW for non-packet offload modes. Simply skip 2267 + * the following update and save extra boilerplate in drivers. 2268 + */ 2269 + if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET) 2270 + xfrm_dev_state_update_stats(x); 2286 2271 2287 2272 if (!READ_ONCE(x->curlft.use_time)) 2288 2273 WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds()); ··· 2580 2555 unsigned int h; 2581 2556 struct xfrm_state *x0; 2582 2557 int err = -ENOENT; 2583 - __be32 minspi = htonl(low); 2584 - __be32 maxspi = htonl(high); 2558 + u32 range = high - low + 1; 2585 2559 __be32 newspi = 0; 2586 - u32 mark = x->mark.v & x->mark.m; 2587 2560 2588 2561 spin_lock_bh(&x->lock); 2589 2562 if (x->km.state == XFRM_STATE_DEAD) { ··· 2595 2572 2596 2573 err = -ENOENT; 2597 2574 2598 - if (minspi == maxspi) { 2599 - x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); 2600 - if (x0) { 2601 - NL_SET_ERR_MSG(extack, "Requested SPI is already in use"); 2602 - xfrm_state_put(x0); 2575 + for (h = 0; h < range; h++) { 2576 + u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high); 2577 + newspi = htonl(spi); 2578 + 2579 + spin_lock_bh(&net->xfrm.xfrm_state_lock); 2580 + x0 = xfrm_state_lookup_spi_proto(net, newspi, x->id.proto); 2581 + if (!x0) { 2582 + x->id.spi = newspi; 2583 + h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family); 2584 + XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type); 2585 + spin_unlock_bh(&net->xfrm.xfrm_state_lock); 2586 + err = 0; 2603 2587 goto unlock; 2604 2588 } 2605 - newspi = minspi; 2606 - } else { 2607 - u32 spi = 0; 2608 - for (h = 0; h < high-low+1; h++) { 2609 - spi = get_random_u32_inclusive(low, high); 2610 - x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); 2611 - if (x0 == NULL) { 2612 - newspi = htonl(spi); 2613 - break; 2614 - } 2615 - xfrm_state_put(x0); 2616 - } 2617 - } 2618 - if (newspi) { 2619 - spin_lock_bh(&net->xfrm.xfrm_state_lock); 2620 - x->id.spi = newspi; 2621 - h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); 2622 - XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, 2623 - x->xso.type); 2589 + xfrm_state_put(x0); 2624 2590 spin_unlock_bh(&net->xfrm.xfrm_state_lock); 2625 2591 2626 - err = 0; 2627 - } else { 2628 - NL_SET_ERR_MSG(extack, "No SPI available in the requested range"); 2592 + if (signal_pending(current)) { 2593 + err = -ERESTARTSYS; 2594 + goto unlock; 2595 + } 2596 + 2597 + if (low == high) 2598 + break; 2629 2599 } 2600 + 2601 + if (err) 2602 + NL_SET_ERR_MSG(extack, "No SPI available in the requested range"); 2630 2603 2631 2604 unlock: 2632 2605 spin_unlock_bh(&x->lock);