Skip to content

Commit 94619ea

Browse files
author
Paolo Abeni
committed
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>
2 parents 8aad37d + 95cfe23 commit 94619ea

File tree

2 files changed

+58
-38
lines changed

2 files changed

+58
-38
lines changed

net/xfrm/xfrm_input.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
503503
/* An encap_type of -1 indicates async resumption. */
504504
if (encap_type == -1) {
505505
async = 1;
506+
dev_put(skb->dev);
506507
seq = XFRM_SKB_CB(skb)->seq.input.low;
507508
goto resume;
508509
}
@@ -649,18 +650,18 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
649650
XFRM_SKB_CB(skb)->seq.input.low = seq;
650651
XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
651652

652-
dev_hold(skb->dev);
653-
654-
if (crypto_done)
653+
if (crypto_done) {
655654
nexthdr = x->type_offload->input_tail(x, skb);
656-
else
655+
} else {
656+
dev_hold(skb->dev);
657+
657658
nexthdr = x->type->input(x, skb);
659+
if (nexthdr == -EINPROGRESS)
660+
return 0;
658661

659-
if (nexthdr == -EINPROGRESS)
660-
return 0;
662+
dev_put(skb->dev);
663+
}
661664
resume:
662-
dev_put(skb->dev);
663-
664665
spin_lock(&x->lock);
665666
if (nexthdr < 0) {
666667
if (nexthdr == -EBADMSG) {

net/xfrm/xfrm_state.c

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,26 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi,
17111711
}
17121712
EXPORT_SYMBOL(xfrm_state_lookup_byspi);
17131713

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+
17141734
static void __xfrm_state_insert(struct xfrm_state *x)
17151735
{
17161736
struct net *net = xs_net(x);
@@ -2262,7 +2282,12 @@ EXPORT_SYMBOL(xfrm_state_update);
22622282

22632283
int xfrm_state_check_expire(struct xfrm_state *x)
22642284
{
2265-
xfrm_dev_state_update_stats(x);
2285+
/* All counters which are needed to decide if state is expired
2286+
* are handled by SW for non-packet offload modes. Simply skip
2287+
* the following update and save extra boilerplate in drivers.
2288+
*/
2289+
if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET)
2290+
xfrm_dev_state_update_stats(x);
22662291

22672292
if (!READ_ONCE(x->curlft.use_time))
22682293
WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds());
@@ -2555,10 +2580,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
25552580
unsigned int h;
25562581
struct xfrm_state *x0;
25572582
int err = -ENOENT;
2558-
__be32 minspi = htonl(low);
2559-
__be32 maxspi = htonl(high);
2583+
u32 range = high - low + 1;
25602584
__be32 newspi = 0;
2561-
u32 mark = x->mark.v & x->mark.m;
25622585

25632586
spin_lock_bh(&x->lock);
25642587
if (x->km.state == XFRM_STATE_DEAD) {
@@ -2572,38 +2595,34 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high,
25722595

25732596
err = -ENOENT;
25742597

2575-
if (minspi == maxspi) {
2576-
x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family);
2577-
if (x0) {
2578-
NL_SET_ERR_MSG(extack, "Requested SPI is already in use");
2579-
xfrm_state_put(x0);
2598+
for (h = 0; h < range; h++) {
2599+
u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high);
2600+
newspi = htonl(spi);
2601+
2602+
spin_lock_bh(&net->xfrm.xfrm_state_lock);
2603+
x0 = xfrm_state_lookup_spi_proto(net, newspi, x->id.proto);
2604+
if (!x0) {
2605+
x->id.spi = newspi;
2606+
h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family);
2607+
XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type);
2608+
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
2609+
err = 0;
25802610
goto unlock;
25812611
}
2582-
newspi = minspi;
2583-
} else {
2584-
u32 spi = 0;
2585-
for (h = 0; h < high-low+1; h++) {
2586-
spi = get_random_u32_inclusive(low, high);
2587-
x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family);
2588-
if (x0 == NULL) {
2589-
newspi = htonl(spi);
2590-
break;
2591-
}
2592-
xfrm_state_put(x0);
2612+
xfrm_state_put(x0);
2613+
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
2614+
2615+
if (signal_pending(current)) {
2616+
err = -ERESTARTSYS;
2617+
goto unlock;
25932618
}
2619+
2620+
if (low == high)
2621+
break;
25942622
}
2595-
if (newspi) {
2596-
spin_lock_bh(&net->xfrm.xfrm_state_lock);
2597-
x->id.spi = newspi;
2598-
h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
2599-
XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h,
2600-
x->xso.type);
2601-
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
26022623

2603-
err = 0;
2604-
} else {
2624+
if (err)
26052625
NL_SET_ERR_MSG(extack, "No SPI available in the requested range");
2606-
}
26072626

26082627
unlock:
26092628
spin_unlock_bh(&x->lock);

0 commit comments

Comments
 (0)