Skip to content

Commit cf51abc

Browse files
author
Alexei Starovoitov
committed
Merge branch 'Link-based-attach-to-netns'
Jakub Sitnicki says: ==================== One of the pieces of feedback from recent review of BPF hooks for socket lookup [0] was that new program types should use bpf_link-based attachment. This series introduces new bpf_link type for attaching to network namespace. All link operations are supported. Errors returned from ops follow cgroup example. Patch 4 description goes into error semantics. The major change in v2 is a switch away from RCU to mutex-only synchronization. Andrii pointed out that it is not needed, and it makes sense to keep locking straightforward. Also, there were a couple of bugs in update_prog and fill_info initial implementation, one picked up by kbuild. Those are now fixed. Tests have been extended to cover them. Full changelog below. Series is organized as so: Patches 1-3 prepare a space in struct net to keep state for attached BPF programs, and massage the code in flow_dissector to make it attach type agnostic, to finally move it under kernel/bpf/. Patch 4, the most important one, introduces new bpf_link link type for attaching to network namespace. Patch 5 unifies the update error (ENOLINK) between BPF cgroup and netns. Patches 6-8 make libbpf and bpftool aware of the new link type. Patches 9-12 Add and extend tests to check that link low- and high-level API for operating on links to netns works as intended. Thanks to Alexei, Andrii, Lorenz, Marek, and Stanislav for feedback. -jkbs [0] https://lore.kernel.org/bpf/[email protected]/ Cc: Alexei Starovoitov <[email protected]> Cc: Andrii Nakryiko <[email protected]> Cc: Lorenz Bauer <[email protected]> Cc: Marek Majkowski <[email protected]> Cc: Stanislav Fomichev <[email protected]> v1 -> v2: - Switch to mutex-only synchronization. Don't rely on RCU grace period guarantee when accessing struct net from link release / update / fill_info, and when accessing bpf_link from pernet pre_exit callback. (Andrii) - Drop patch 1, no longer needed with mutex-only synchronization. - Don't leak uninitialized variable contents from fill_info callback when link is in defunct state. (kbuild) - Make fill_info treat the link as defunct (i.e. no attached netns) when struct net refcount is 0, but link has not been yet auto-detached. - Add missing BPF_LINK_TYPE define in bpf_types.h for new link type. - Fix link update_prog callback to update the prog that will run, and not just the link itself. - Return EEXIST on prog attach when link already exists, and on link create when prog is already attached directly. (Andrii) - Return EINVAL on prog detach when link is attached. (Andrii) - Fold __netns_bpf_link_attach into its only caller. (Stanislav) - Get rid of a wrapper around container_of() (Andrii) - Use rcu_dereference_protected instead of rcu_access_pointer on update-side. (Stanislav) - Make return-on-success from netns_bpf_link_create less confusing. (Andrii) - Adapt bpf_link for cgroup to return ENOLINK when updating a defunct link. (Andrii, Alexei) - Order new exported symbols in libbpf.map alphabetically (Andrii) - Keep libbpf's "failed to attach link" warning message clear as to what we failed to attach to (cgroup vs netns). (Andrii) - Extract helpers for printing link attach type. (bpftool, Andrii) - Switch flow_dissector tests to BPF skeleton and extend them to exercise link-based flow dissector attachment. (Andrii) - Harden flow dissector attachment tests with prog query checks after prog attach/detach, or link create/update/close. - Extend flow dissector tests to cover fill_info for defunct links. - Rebase onto recent bpf-next ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents febeb6d + 06716e0 commit cf51abc

File tree

20 files changed

+1248
-247
lines changed

20 files changed

+1248
-247
lines changed

include/linux/bpf-netns.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _BPF_NETNS_H
3+
#define _BPF_NETNS_H
4+
5+
#include <linux/mutex.h>
6+
#include <uapi/linux/bpf.h>
7+
8+
enum netns_bpf_attach_type {
9+
NETNS_BPF_INVALID = -1,
10+
NETNS_BPF_FLOW_DISSECTOR = 0,
11+
MAX_NETNS_BPF_ATTACH_TYPE
12+
};
13+
14+
static inline enum netns_bpf_attach_type
15+
to_netns_bpf_attach_type(enum bpf_attach_type attach_type)
16+
{
17+
switch (attach_type) {
18+
case BPF_FLOW_DISSECTOR:
19+
return NETNS_BPF_FLOW_DISSECTOR;
20+
default:
21+
return NETNS_BPF_INVALID;
22+
}
23+
}
24+
25+
/* Protects updates to netns_bpf */
26+
extern struct mutex netns_bpf_mutex;
27+
28+
union bpf_attr;
29+
struct bpf_prog;
30+
31+
#ifdef CONFIG_NET
32+
int netns_bpf_prog_query(const union bpf_attr *attr,
33+
union bpf_attr __user *uattr);
34+
int netns_bpf_prog_attach(const union bpf_attr *attr,
35+
struct bpf_prog *prog);
36+
int netns_bpf_prog_detach(const union bpf_attr *attr);
37+
int netns_bpf_link_create(const union bpf_attr *attr,
38+
struct bpf_prog *prog);
39+
#else
40+
static inline int netns_bpf_prog_query(const union bpf_attr *attr,
41+
union bpf_attr __user *uattr)
42+
{
43+
return -EOPNOTSUPP;
44+
}
45+
46+
static inline int netns_bpf_prog_attach(const union bpf_attr *attr,
47+
struct bpf_prog *prog)
48+
{
49+
return -EOPNOTSUPP;
50+
}
51+
52+
static inline int netns_bpf_prog_detach(const union bpf_attr *attr)
53+
{
54+
return -EOPNOTSUPP;
55+
}
56+
57+
static inline int netns_bpf_link_create(const union bpf_attr *attr,
58+
struct bpf_prog *prog)
59+
{
60+
return -EOPNOTSUPP;
61+
}
62+
#endif
63+
64+
#endif /* _BPF_NETNS_H */

include/linux/bpf_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,6 @@ BPF_LINK_TYPE(BPF_LINK_TYPE_TRACING, tracing)
126126
BPF_LINK_TYPE(BPF_LINK_TYPE_CGROUP, cgroup)
127127
#endif
128128
BPF_LINK_TYPE(BPF_LINK_TYPE_ITER, iter)
129+
#ifdef CONFIG_NET
130+
BPF_LINK_TYPE(BPF_LINK_TYPE_NETNS, netns)
131+
#endif

include/linux/skbuff.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,32 +1283,6 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
12831283
const struct flow_dissector_key *key,
12841284
unsigned int key_count);
12851285

1286-
#ifdef CONFIG_NET
1287-
int skb_flow_dissector_prog_query(const union bpf_attr *attr,
1288-
union bpf_attr __user *uattr);
1289-
int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
1290-
struct bpf_prog *prog);
1291-
1292-
int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr);
1293-
#else
1294-
static inline int skb_flow_dissector_prog_query(const union bpf_attr *attr,
1295-
union bpf_attr __user *uattr)
1296-
{
1297-
return -EOPNOTSUPP;
1298-
}
1299-
1300-
static inline int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
1301-
struct bpf_prog *prog)
1302-
{
1303-
return -EOPNOTSUPP;
1304-
}
1305-
1306-
static inline int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr)
1307-
{
1308-
return -EOPNOTSUPP;
1309-
}
1310-
#endif
1311-
13121286
struct bpf_flow_dissector;
13131287
bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
13141288
__be16 proto, int nhoff, int hlen, unsigned int flags);

include/net/flow_dissector.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <linux/string.h>
99
#include <uapi/linux/if_ether.h>
1010

11+
struct bpf_prog;
12+
struct net;
1113
struct sk_buff;
1214

1315
/**
@@ -369,4 +371,8 @@ flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
369371
memset(key_basic, 0, sizeof(*key_basic));
370372
}
371373

374+
#ifdef CONFIG_BPF_SYSCALL
375+
int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog);
376+
#endif /* CONFIG_BPF_SYSCALL */
377+
372378
#endif

include/net/net_namespace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <net/netns/mpls.h>
3434
#include <net/netns/can.h>
3535
#include <net/netns/xdp.h>
36+
#include <net/netns/bpf.h>
3637
#include <linux/ns_common.h>
3738
#include <linux/idr.h>
3839
#include <linux/skbuff.h>
@@ -162,7 +163,8 @@ struct net {
162163
#endif
163164
struct net_generic __rcu *gen;
164165

165-
struct bpf_prog __rcu *flow_dissector_prog;
166+
/* Used to store attached BPF programs */
167+
struct netns_bpf bpf;
166168

167169
/* Note : following structs are cache line aligned */
168170
#ifdef CONFIG_XFRM

include/net/netns/bpf.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* BPF programs attached to network namespace
4+
*/
5+
6+
#ifndef __NETNS_BPF_H__
7+
#define __NETNS_BPF_H__
8+
9+
#include <linux/bpf-netns.h>
10+
11+
struct bpf_prog;
12+
13+
struct netns_bpf {
14+
struct bpf_prog __rcu *progs[MAX_NETNS_BPF_ATTACH_TYPE];
15+
struct bpf_link *links[MAX_NETNS_BPF_ATTACH_TYPE];
16+
};
17+
18+
#endif /* __NETNS_BPF_H__ */

include/uapi/linux/bpf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ enum bpf_link_type {
237237
BPF_LINK_TYPE_TRACING = 2,
238238
BPF_LINK_TYPE_CGROUP = 3,
239239
BPF_LINK_TYPE_ITER = 4,
240+
BPF_LINK_TYPE_NETNS = 5,
240241

241242
MAX_BPF_LINK_TYPE,
242243
};
@@ -3839,6 +3840,10 @@ struct bpf_link_info {
38393840
__u64 cgroup_id;
38403841
__u32 attach_type;
38413842
} cgroup;
3843+
struct {
3844+
__u32 netns_ino;
3845+
__u32 attach_type;
3846+
} netns;
38423847
};
38433848
} __attribute__((aligned(8)));
38443849

kernel/bpf/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ ifeq ($(CONFIG_NET),y)
1313
obj-$(CONFIG_BPF_SYSCALL) += devmap.o
1414
obj-$(CONFIG_BPF_SYSCALL) += cpumap.o
1515
obj-$(CONFIG_BPF_SYSCALL) += offload.o
16+
obj-$(CONFIG_BPF_SYSCALL) += net_namespace.o
1617
endif
1718
ifeq ($(CONFIG_PERF_EVENTS),y)
1819
obj-$(CONFIG_BPF_SYSCALL) += stackmap.o

kernel/bpf/cgroup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ static int cgroup_bpf_replace(struct bpf_link *link, struct bpf_prog *new_prog,
595595
mutex_lock(&cgroup_mutex);
596596
/* link might have been auto-released by dying cgroup, so fail */
597597
if (!cg_link->cgroup) {
598-
ret = -EINVAL;
598+
ret = -ENOLINK;
599599
goto out_unlock;
600600
}
601601
if (old_prog && link->prog != old_prog) {

0 commit comments

Comments
 (0)