Skip to content

Commit 296a681

Browse files
committed
Merge tag 'ipsec-next-2024-11-15' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
Steffen Klassert says: ==================== ipsec-next-11-15 1) Add support for RFC 9611 per cpu xfrm state handling. 2) Add inbound and outbound xfrm state caches to speed up state lookups. 3) Convert xfrm to dscp_t. From Guillaume Nault. 4) Fix error handling in build_aevent. From Everest K.C. 5) Replace strncpy with strscpy_pad in copy_to_user_auth. From Daniel Yang. 6) Fix an uninitialized symbol during acquire state insertion. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 38f83a5 + a356728 commit 296a681

12 files changed

Lines changed: 284 additions & 40 deletions

File tree

include/net/netns/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ struct netns_xfrm {
4343
struct hlist_head __rcu *state_bysrc;
4444
struct hlist_head __rcu *state_byspi;
4545
struct hlist_head __rcu *state_byseq;
46+
struct hlist_head __percpu *state_cache_input;
4647
unsigned int state_hmask;
4748
unsigned int state_num;
4849
struct work_struct state_hash_work;

include/net/xfrm.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <net/sock.h>
2121
#include <net/dst.h>
22+
#include <net/inet_dscp.h>
2223
#include <net/ip.h>
2324
#include <net/route.h>
2425
#include <net/ipv6.h>
@@ -184,10 +185,13 @@ struct xfrm_state {
184185
};
185186
struct hlist_node byspi;
186187
struct hlist_node byseq;
188+
struct hlist_node state_cache;
189+
struct hlist_node state_cache_input;
187190

188191
refcount_t refcnt;
189192
spinlock_t lock;
190193

194+
u32 pcpu_num;
191195
struct xfrm_id id;
192196
struct xfrm_selector sel;
193197
struct xfrm_mark mark;
@@ -351,7 +355,7 @@ void xfrm_if_unregister_cb(void);
351355

352356
struct xfrm_dst_lookup_params {
353357
struct net *net;
354-
int tos;
358+
dscp_t dscp;
355359
int oif;
356360
xfrm_address_t *saddr;
357361
xfrm_address_t *daddr;
@@ -536,6 +540,7 @@ struct xfrm_policy_queue {
536540
* @xp_net: network namespace the policy lives in
537541
* @bydst: hlist node for SPD hash table or rbtree list
538542
* @byidx: hlist node for index hash table
543+
* @state_cache_list: hlist head for policy cached xfrm states
539544
* @lock: serialize changes to policy structure members
540545
* @refcnt: reference count, freed once it reaches 0
541546
* @pos: kernel internal tie-breaker to determine age of policy
@@ -566,6 +571,8 @@ struct xfrm_policy {
566571
struct hlist_node bydst;
567572
struct hlist_node byidx;
568573

574+
struct hlist_head state_cache_list;
575+
569576
/* This lock only affects elements except for entry. */
570577
rwlock_t lock;
571578
refcount_t refcnt;
@@ -1645,6 +1652,10 @@ int xfrm_state_update(struct xfrm_state *x);
16451652
struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
16461653
const xfrm_address_t *daddr, __be32 spi,
16471654
u8 proto, unsigned short family);
1655+
struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
1656+
const xfrm_address_t *daddr,
1657+
__be32 spi, u8 proto,
1658+
unsigned short family);
16481659
struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
16491660
const xfrm_address_t *daddr,
16501661
const xfrm_address_t *saddr,
@@ -1684,7 +1695,7 @@ struct xfrmk_spdinfo {
16841695
u32 spdhmcnt;
16851696
};
16861697

1687-
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
1698+
struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num);
16881699
int xfrm_state_delete(struct xfrm_state *x);
16891700
int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
16901701
int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
@@ -1796,7 +1807,7 @@ int verify_spi_info(u8 proto, u32 min, u32 max, struct netlink_ext_ack *extack);
17961807
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi,
17971808
struct netlink_ext_ack *extack);
17981809
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
1799-
u8 mode, u32 reqid, u32 if_id, u8 proto,
1810+
u8 mode, u32 reqid, u32 if_id, u32 pcpu_num, u8 proto,
18001811
const xfrm_address_t *daddr,
18011812
const xfrm_address_t *saddr, int create,
18021813
unsigned short family);

include/uapi/linux/xfrm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ enum xfrm_attr_type_t {
322322
XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */
323323
XFRMA_SA_DIR, /* __u8 */
324324
XFRMA_NAT_KEEPALIVE_INTERVAL, /* __u32 in seconds for NAT keepalive */
325+
XFRMA_SA_PCPU, /* __u32 */
325326
__XFRMA_MAX
326327

327328
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
@@ -437,6 +438,7 @@ struct xfrm_userpolicy_info {
437438
#define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
438439
/* Automatically expand selector to include matching ICMP payloads. */
439440
#define XFRM_POLICY_ICMP 2
441+
#define XFRM_POLICY_CPU_ACQUIRE 4
440442
__u8 share;
441443
};
442444

net/ipv4/esp4_offload.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
5353
if (sp->len == XFRM_MAX_DEPTH)
5454
goto out_reset;
5555

56-
x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
57-
(xfrm_address_t *)&ip_hdr(skb)->daddr,
58-
spi, IPPROTO_ESP, AF_INET);
56+
x = xfrm_input_state_lookup(dev_net(skb->dev), skb->mark,
57+
(xfrm_address_t *)&ip_hdr(skb)->daddr,
58+
spi, IPPROTO_ESP, AF_INET);
5959

6060
if (unlikely(x && x->dir && x->dir != XFRM_SA_DIR_IN)) {
6161
/* non-offload path will record the error and audit log */

net/ipv4/xfrm4_policy.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/inetdevice.h>
1515
#include <net/dst.h>
1616
#include <net/xfrm.h>
17+
#include <net/inet_dscp.h>
1718
#include <net/ip.h>
1819
#include <net/l3mdev.h>
1920

@@ -24,7 +25,7 @@ static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
2425

2526
memset(fl4, 0, sizeof(*fl4));
2627
fl4->daddr = params->daddr->a4;
27-
fl4->flowi4_tos = params->tos;
28+
fl4->flowi4_tos = inet_dscp_to_dsfield(params->dscp);
2829
fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(params->net,
2930
params->oif);
3031
fl4->flowi4_mark = params->mark;

net/ipv6/esp6_offload.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
8080
if (sp->len == XFRM_MAX_DEPTH)
8181
goto out_reset;
8282

83-
x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
84-
(xfrm_address_t *)&ipv6_hdr(skb)->daddr,
85-
spi, IPPROTO_ESP, AF_INET6);
83+
x = xfrm_input_state_lookup(dev_net(skb->dev), skb->mark,
84+
(xfrm_address_t *)&ipv6_hdr(skb)->daddr,
85+
spi, IPPROTO_ESP, AF_INET6);
8686

8787
if (unlikely(x && x->dir && x->dir != XFRM_SA_DIR_IN)) {
8888
/* non-offload path will record the error and audit log */

net/key/af_key.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,15 +1354,16 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
13541354
}
13551355

13561356
if (hdr->sadb_msg_seq) {
1357-
x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1357+
x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq, UINT_MAX);
13581358
if (x && !xfrm_addr_equal(&x->id.daddr, xdaddr, family)) {
13591359
xfrm_state_put(x);
13601360
x = NULL;
13611361
}
13621362
}
13631363

13641364
if (!x)
1365-
x = xfrm_find_acq(net, &dummy_mark, mode, reqid, 0, proto, xdaddr, xsaddr, 1, family);
1365+
x = xfrm_find_acq(net, &dummy_mark, mode, reqid, 0, UINT_MAX,
1366+
proto, xdaddr, xsaddr, 1, family);
13661367

13671368
if (x == NULL)
13681369
return -ENOENT;
@@ -1417,7 +1418,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb
14171418
if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0)
14181419
return 0;
14191420

1420-
x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq);
1421+
x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq, UINT_MAX);
14211422
if (x == NULL)
14221423
return 0;
14231424

net/xfrm/xfrm_compat.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
132132
[XFRMA_MTIMER_THRESH] = { .type = NLA_U32 },
133133
[XFRMA_SA_DIR] = NLA_POLICY_RANGE(NLA_U8, XFRM_SA_DIR_IN, XFRM_SA_DIR_OUT),
134134
[XFRMA_NAT_KEEPALIVE_INTERVAL] = { .type = NLA_U32 },
135+
[XFRMA_SA_PCPU] = { .type = NLA_U32 },
135136
};
136137

137138
static struct nlmsghdr *xfrm_nlmsg_put_compat(struct sk_buff *skb,
@@ -282,9 +283,10 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src)
282283
case XFRMA_MTIMER_THRESH:
283284
case XFRMA_SA_DIR:
284285
case XFRMA_NAT_KEEPALIVE_INTERVAL:
286+
case XFRMA_SA_PCPU:
285287
return xfrm_nla_cpy(dst, src, nla_len(src));
286288
default:
287-
BUILD_BUG_ON(XFRMA_MAX != XFRMA_NAT_KEEPALIVE_INTERVAL);
289+
BUILD_BUG_ON(XFRMA_MAX != XFRMA_SA_PCPU);
288290
pr_warn_once("unsupported nla_type %d\n", src->nla_type);
289291
return -EOPNOTSUPP;
290292
}
@@ -439,7 +441,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla,
439441
int err;
440442

441443
if (type > XFRMA_MAX) {
442-
BUILD_BUG_ON(XFRMA_MAX != XFRMA_NAT_KEEPALIVE_INTERVAL);
444+
BUILD_BUG_ON(XFRMA_MAX != XFRMA_SA_PCPU);
443445
NL_SET_ERR_MSG(extack, "Bad attribute");
444446
return -EOPNOTSUPP;
445447
}

net/xfrm/xfrm_input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
572572
goto drop;
573573
}
574574

575-
x = xfrm_state_lookup(net, mark, daddr, spi, nexthdr, family);
575+
x = xfrm_input_state_lookup(net, mark, daddr, spi, nexthdr, family);
576576
if (x == NULL) {
577577
secpath_reset(skb);
578578
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);

net/xfrm/xfrm_policy.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ struct dst_entry *__xfrm_dst_lookup(int family,
289289
EXPORT_SYMBOL(__xfrm_dst_lookup);
290290

291291
static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
292-
int tos, int oif,
292+
dscp_t dscp, int oif,
293293
xfrm_address_t *prev_saddr,
294294
xfrm_address_t *prev_daddr,
295295
int family, u32 mark)
@@ -312,7 +312,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
312312
params.net = net;
313313
params.saddr = saddr;
314314
params.daddr = daddr;
315-
params.tos = tos;
315+
params.dscp = dscp;
316316
params.oif = oif;
317317
params.mark = mark;
318318
params.ipproto = x->id.proto;
@@ -434,6 +434,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
434434
if (policy) {
435435
write_pnet(&policy->xp_net, net);
436436
INIT_LIST_HEAD(&policy->walk.all);
437+
INIT_HLIST_HEAD(&policy->state_cache_list);
437438
INIT_HLIST_NODE(&policy->bydst);
438439
INIT_HLIST_NODE(&policy->byidx);
439440
rwlock_init(&policy->lock);
@@ -475,6 +476,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy);
475476

476477
static void xfrm_policy_kill(struct xfrm_policy *policy)
477478
{
479+
struct net *net = xp_net(policy);
480+
struct xfrm_state *x;
481+
478482
xfrm_dev_policy_delete(policy);
479483

480484
write_lock_bh(&policy->lock);
@@ -490,6 +494,13 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
490494
if (del_timer(&policy->timer))
491495
xfrm_pol_put(policy);
492496

497+
/* XXX: Flush state cache */
498+
spin_lock_bh(&net->xfrm.xfrm_state_lock);
499+
hlist_for_each_entry_rcu(x, &policy->state_cache_list, state_cache) {
500+
hlist_del_init_rcu(&x->state_cache);
501+
}
502+
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
503+
493504
xfrm_pol_put(policy);
494505
}
495506

@@ -2576,10 +2587,10 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, const struct flowi *fl,
25762587

25772588
}
25782589

2579-
static int xfrm_get_tos(const struct flowi *fl, int family)
2590+
static dscp_t xfrm_get_dscp(const struct flowi *fl, int family)
25802591
{
25812592
if (family == AF_INET)
2582-
return fl->u.ip4.flowi4_tos & INET_DSCP_MASK;
2593+
return inet_dsfield_to_dscp(fl->u.ip4.flowi4_tos);
25832594

25842595
return 0;
25852596
}
@@ -2667,13 +2678,13 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
26672678
int header_len = 0;
26682679
int nfheader_len = 0;
26692680
int trailer_len = 0;
2670-
int tos;
26712681
int family = policy->selector.family;
26722682
xfrm_address_t saddr, daddr;
2683+
dscp_t dscp;
26732684

26742685
xfrm_flowi_addr_get(fl, &saddr, &daddr, family);
26752686

2676-
tos = xfrm_get_tos(fl, family);
2687+
dscp = xfrm_get_dscp(fl, family);
26772688

26782689
dst_hold(dst);
26792690

@@ -2721,8 +2732,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
27212732
family = xfrm[i]->props.family;
27222733

27232734
oif = fl->flowi_oif ? : fl->flowi_l3mdev;
2724-
dst = xfrm_dst_lookup(xfrm[i], tos, oif,
2725-
&saddr, &daddr, family, mark);
2735+
dst = xfrm_dst_lookup(xfrm[i], dscp, oif, &saddr,
2736+
&daddr, family, mark);
27262737
err = PTR_ERR(dst);
27272738
if (IS_ERR(dst))
27282739
goto put_states;
@@ -3275,6 +3286,7 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
32753286
dst_release(dst);
32763287
dst = dst_orig;
32773288
}
3289+
32783290
ok:
32793291
xfrm_pols_put(pols, drop_pols);
32803292
if (dst && dst->xfrm &&

0 commit comments

Comments
 (0)