Skip to content

Commit 08388ef

Browse files
author
Martin KaFai Lau
committed
Merge branch 'xfrm: interface: Add unstable helpers for XFRM metadata'
Eyal Birger says: ==================== This patch series adds xfrm metadata helpers using the unstable kfunc call interface for the TC-BPF hooks. This allows steering traffic towards different IPsec connections based on logic implemented in bpf programs. The helpers are integrated into the xfrm_interface module. For this purpose the main functionality of this module is moved to xfrm_interface_core.c. --- changes in v6: fix sparse warning in patch 2 changes in v5: - avoid cleanup of percpu dsts as detailed in patch 2 changes in v3: - tag bpf-next tree instead of ipsec-next - add IFLA_XFRM_COLLECT_METADATA sync patch ==================== Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
2 parents ab0350c + 90a3a05 commit 08388ef

File tree

13 files changed

+574
-2
lines changed

13 files changed

+574
-2
lines changed

include/net/dst_metadata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct macsec_info {
2626
struct xfrm_md_info {
2727
u32 if_id;
2828
int link;
29+
struct dst_entry *dst_orig;
2930
};
3031

3132
struct metadata_dst {

include/net/xfrm.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,4 +2086,21 @@ static inline bool xfrm6_local_dontfrag(const struct sock *sk)
20862086
return false;
20872087
}
20882088
#endif
2089+
2090+
#if (IS_BUILTIN(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
2091+
(IS_MODULE(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
2092+
2093+
extern struct metadata_dst __percpu *xfrm_bpf_md_dst;
2094+
2095+
int register_xfrm_interface_bpf(void);
2096+
2097+
#else
2098+
2099+
static inline int register_xfrm_interface_bpf(void)
2100+
{
2101+
return 0;
2102+
}
2103+
2104+
#endif
2105+
20892106
#endif /* _NET_XFRM_H */

net/core/dst.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ void metadata_dst_free(struct metadata_dst *md_dst)
316316
if (md_dst->type == METADATA_IP_TUNNEL)
317317
dst_cache_destroy(&md_dst->u.tun_info.dst_cache);
318318
#endif
319+
if (md_dst->type == METADATA_XFRM)
320+
dst_release(md_dst->u.xfrm_info.dst_orig);
319321
kfree(md_dst);
320322
}
321323
EXPORT_SYMBOL_GPL(metadata_dst_free);
@@ -340,16 +342,18 @@ EXPORT_SYMBOL_GPL(metadata_dst_alloc_percpu);
340342

341343
void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst)
342344
{
343-
#ifdef CONFIG_DST_CACHE
344345
int cpu;
345346

346347
for_each_possible_cpu(cpu) {
347348
struct metadata_dst *one_md_dst = per_cpu_ptr(md_dst, cpu);
348349

350+
#ifdef CONFIG_DST_CACHE
349351
if (one_md_dst->type == METADATA_IP_TUNNEL)
350352
dst_cache_destroy(&one_md_dst->u.tun_info.dst_cache);
351-
}
352353
#endif
354+
if (one_md_dst->type == METADATA_XFRM)
355+
dst_release(one_md_dst->u.xfrm_info.dst_orig);
356+
}
353357
free_percpu(md_dst);
354358
}
355359
EXPORT_SYMBOL_GPL(metadata_dst_free_percpu);

net/core/filter.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5631,6 +5631,15 @@ static const struct bpf_func_proto bpf_bind_proto = {
56315631
};
56325632

56335633
#ifdef CONFIG_XFRM
5634+
5635+
#if (IS_BUILTIN(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
5636+
(IS_MODULE(CONFIG_XFRM_INTERFACE) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
5637+
5638+
struct metadata_dst __percpu *xfrm_bpf_md_dst;
5639+
EXPORT_SYMBOL_GPL(xfrm_bpf_md_dst);
5640+
5641+
#endif
5642+
56345643
BPF_CALL_5(bpf_skb_get_xfrm_state, struct sk_buff *, skb, u32, index,
56355644
struct bpf_xfrm_state *, to, u32, size, u64, flags)
56365645
{

net/xfrm/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
# Makefile for the XFRM subsystem.
44
#
55

6+
xfrm_interface-$(CONFIG_XFRM_INTERFACE) += xfrm_interface_core.o
7+
8+
ifeq ($(CONFIG_XFRM_INTERFACE),m)
9+
xfrm_interface-$(CONFIG_DEBUG_INFO_BTF_MODULES) += xfrm_interface_bpf.o
10+
else ifeq ($(CONFIG_XFRM_INTERFACE),y)
11+
xfrm_interface-$(CONFIG_DEBUG_INFO_BTF) += xfrm_interface_bpf.o
12+
endif
13+
614
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
715
xfrm_input.o xfrm_output.o \
816
xfrm_sysctl.o xfrm_replay.o xfrm_device.o

net/xfrm/xfrm_interface_bpf.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Unstable XFRM Helpers for TC-BPF hook
3+
*
4+
* These are called from SCHED_CLS BPF programs. Note that it is
5+
* allowed to break compatibility for these functions since the interface they
6+
* are exposed through to BPF programs is explicitly unstable.
7+
*/
8+
9+
#include <linux/bpf.h>
10+
#include <linux/btf_ids.h>
11+
12+
#include <net/dst_metadata.h>
13+
#include <net/xfrm.h>
14+
15+
/* bpf_xfrm_info - XFRM metadata information
16+
*
17+
* Members:
18+
* @if_id - XFRM if_id:
19+
* Transmit: if_id to be used in policy and state lookups
20+
* Receive: if_id of the state matched for the incoming packet
21+
* @link - Underlying device ifindex:
22+
* Transmit: used as the underlying device in VRF routing
23+
* Receive: the device on which the packet had been received
24+
*/
25+
struct bpf_xfrm_info {
26+
u32 if_id;
27+
int link;
28+
};
29+
30+
__diag_push();
31+
__diag_ignore_all("-Wmissing-prototypes",
32+
"Global functions as their definitions will be in xfrm_interface BTF");
33+
34+
/* bpf_skb_get_xfrm_info - Get XFRM metadata
35+
*
36+
* Parameters:
37+
* @skb_ctx - Pointer to ctx (__sk_buff) in TC program
38+
* Cannot be NULL
39+
* @to - Pointer to memory to which the metadata will be copied
40+
* Cannot be NULL
41+
*/
42+
__used noinline
43+
int bpf_skb_get_xfrm_info(struct __sk_buff *skb_ctx, struct bpf_xfrm_info *to)
44+
{
45+
struct sk_buff *skb = (struct sk_buff *)skb_ctx;
46+
struct xfrm_md_info *info;
47+
48+
info = skb_xfrm_md_info(skb);
49+
if (!info)
50+
return -EINVAL;
51+
52+
to->if_id = info->if_id;
53+
to->link = info->link;
54+
return 0;
55+
}
56+
57+
/* bpf_skb_get_xfrm_info - Set XFRM metadata
58+
*
59+
* Parameters:
60+
* @skb_ctx - Pointer to ctx (__sk_buff) in TC program
61+
* Cannot be NULL
62+
* @from - Pointer to memory from which the metadata will be copied
63+
* Cannot be NULL
64+
*/
65+
__used noinline
66+
int bpf_skb_set_xfrm_info(struct __sk_buff *skb_ctx,
67+
const struct bpf_xfrm_info *from)
68+
{
69+
struct sk_buff *skb = (struct sk_buff *)skb_ctx;
70+
struct metadata_dst *md_dst;
71+
struct xfrm_md_info *info;
72+
73+
if (unlikely(skb_metadata_dst(skb)))
74+
return -EINVAL;
75+
76+
if (!xfrm_bpf_md_dst) {
77+
struct metadata_dst __percpu *tmp;
78+
79+
tmp = metadata_dst_alloc_percpu(0, METADATA_XFRM, GFP_ATOMIC);
80+
if (!tmp)
81+
return -ENOMEM;
82+
if (cmpxchg(&xfrm_bpf_md_dst, NULL, tmp))
83+
metadata_dst_free_percpu(tmp);
84+
}
85+
md_dst = this_cpu_ptr(xfrm_bpf_md_dst);
86+
87+
info = &md_dst->u.xfrm_info;
88+
89+
info->if_id = from->if_id;
90+
info->link = from->link;
91+
skb_dst_force(skb);
92+
info->dst_orig = skb_dst(skb);
93+
94+
dst_hold((struct dst_entry *)md_dst);
95+
skb_dst_set(skb, (struct dst_entry *)md_dst);
96+
return 0;
97+
}
98+
99+
__diag_pop()
100+
101+
BTF_SET8_START(xfrm_ifc_kfunc_set)
102+
BTF_ID_FLAGS(func, bpf_skb_get_xfrm_info)
103+
BTF_ID_FLAGS(func, bpf_skb_set_xfrm_info)
104+
BTF_SET8_END(xfrm_ifc_kfunc_set)
105+
106+
static const struct btf_kfunc_id_set xfrm_interface_kfunc_set = {
107+
.owner = THIS_MODULE,
108+
.set = &xfrm_ifc_kfunc_set,
109+
};
110+
111+
int __init register_xfrm_interface_bpf(void)
112+
{
113+
return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
114+
&xfrm_interface_kfunc_set);
115+
}

net/xfrm/xfrm_interface.c renamed to net/xfrm/xfrm_interface_core.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,14 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
396396

397397
if_id = md_info->if_id;
398398
fl->flowi_oif = md_info->link;
399+
if (md_info->dst_orig) {
400+
struct dst_entry *tmp_dst = dst;
401+
402+
dst = md_info->dst_orig;
403+
skb_dst_set(skb, dst);
404+
md_info->dst_orig = NULL;
405+
dst_release(tmp_dst);
406+
}
399407
} else {
400408
if_id = xi->p.if_id;
401409
}
@@ -1162,12 +1170,18 @@ static int __init xfrmi_init(void)
11621170
if (err < 0)
11631171
goto rtnl_link_failed;
11641172

1173+
err = register_xfrm_interface_bpf();
1174+
if (err < 0)
1175+
goto kfunc_failed;
1176+
11651177
lwtunnel_encap_add_ops(&xfrmi_encap_ops, LWTUNNEL_ENCAP_XFRM);
11661178

11671179
xfrm_if_register_cb(&xfrm_if_cb);
11681180

11691181
return err;
11701182

1183+
kfunc_failed:
1184+
rtnl_link_unregister(&xfrmi_link_ops);
11711185
rtnl_link_failed:
11721186
xfrmi6_fini();
11731187
xfrmi6_failed:

tools/include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ enum {
673673
IFLA_XFRM_UNSPEC,
674674
IFLA_XFRM_LINK,
675675
IFLA_XFRM_IF_ID,
676+
IFLA_XFRM_COLLECT_METADATA,
676677
__IFLA_XFRM_MAX
677678
};
678679

tools/testing/selftests/bpf/DENYLIST.s390x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,4 @@ xdp_bonding # failed to auto-attach program 'trace_
8585
xdp_bpf2bpf # failed to auto-attach program 'trace_on_entry': -524 (trampoline)
8686
xdp_do_redirect # prog_run_max_size unexpected error: -22 (errno 22)
8787
xdp_synproxy # JIT does not support calling kernel function (kfunc)
88+
xfrm_info # JIT does not support calling kernel function (kfunc)

tools/testing/selftests/bpf/config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ CONFIG_IKCONFIG_PROC=y
2323
CONFIG_IMA=y
2424
CONFIG_IMA_READ_POLICY=y
2525
CONFIG_IMA_WRITE_POLICY=y
26+
CONFIG_INET_ESP=y
2627
CONFIG_IP_NF_FILTER=y
2728
CONFIG_IP_NF_RAW=y
2829
CONFIG_IP_NF_TARGET_SYNPROXY=y
@@ -74,3 +75,4 @@ CONFIG_TEST_BPF=y
7475
CONFIG_USERFAULTFD=y
7576
CONFIG_VXLAN=y
7677
CONFIG_XDP_SOCKETS=y
78+
CONFIG_XFRM_INTERFACE=y

0 commit comments

Comments
 (0)