bpf: BPF for lightweight tunnel encapsulation
Subsystems (6)
v4 cover bpf: BPF for lightweight tunnel encapsulation
This series implements BPF program invocation from dst entries via the lightweight tunnels infrastructure. The BPF program can be attached to lwtunnel_input(), lwtunnel_output() or lwtunnel_xmit() and see an L3 skb as context. Programs attached to input and output are read-only. Programs attached to lwtunnel_xmit() can modify and redirect, push headers and redirect packets.
The facility can be used to:
- Collect statistics and generate sampling data for a subset of traffic based on the dst utilized by the packet thus allowing to extend the existing realms.
- Apply additional per route/dst filters to prohibit certain outgoing or incoming packets based on BPF filters. In particular, this allows to maintain per dst custom state across multiple packets in BPF maps and apply filters based on statistics and behaviour observed over time.
- Attachment of L2 headers at transmit where resolving the L2 address is not required.
- Possibly many more.
v3 -> v4:
- Bumped LWT_BPF_MAX_HEADROOM from 128 to 256 (Alexei)
- Renamed bpf_skb_push() helper to bpf_skb_change_head() to relate to existing bpf_skb_change_tail() helper (Alexei/Daniel)
- Added check in __bpf_redirect_common() to verify that program added a link header before redirecting to a l2 device. Adding the check to lwt-bpf code was considered but dropped due to massive code required due to retrieval of net_device via per-cpu redirect buffer. A test case was added to cover the scenario when a program directs to an l2 device without adding an appropriate l2 header.
(Alexei)
- Prohibited access to tc_classid (Daniel)
- Collapsed bpf_verifier_ops instance for lwt in/out as they are identical (Daniel)
- Some cosmetic changes
v2 -> v3:
- Added real world sample lwt_len_hist_kern.c which demonstrates how to collect a histogram on packet sizes for all packets flowing through a number of routes.
- Restricted output to be read-only. Since the header can no longer be modified, the rerouting functionality has been removed again.
- Added test case which cover destructive modification of packet data.
v1 -> v2:
- Added new BPF_LWT_REROUTE return code for program to indicate that new route lookup should be performed. Suggested by Tom.
- New sample to illustrate rerouting
- New patch 05: Recursion limit for lwtunnel_output for the case when user creates circular dst redirection. Also resolves the issue for ILA.
- Fix to ensure headroom for potential future L2 header is still guaranteed
Thomas Graf (4):
route: Set orig_output when redirecting to lwt on locally generated
traffic
route: Set lwtstate for local traffic and cached input dsts
bpf: BPF for lightweight tunnel infrastructure
bpf: Add tests and samples for LWT-BPF
include/linux/filter.h | 2 +- include/uapi/linux/bpf.h | 32 +++- include/uapi/linux/lwtunnel.h | 23 +++ kernel/bpf/verifier.c | 14 +- net/Kconfig | 8 + net/core/Makefile | 1 + net/core/filter.c | 173 +++++++++++++++++ net/core/lwt_bpf.c | 396 +++++++++++++++++++++++++++++++++++++++ net/core/lwtunnel.c | 2 + net/ipv4/route.c | 37 ++-- samples/bpf/Makefile | 4 + samples/bpf/bpf_helpers.h | 4 + samples/bpf/lwt_len_hist.sh | 37 ++++ samples/bpf/lwt_len_hist_kern.c | 82 +++++++++ samples/bpf/lwt_len_hist_user.c | 76 ++++++++ samples/bpf/test_lwt_bpf.c | 253 +++++++++++++++++++++++++ samples/bpf/test_lwt_bpf.sh | 399 ++++++++++++++++++++++++++++++++++++++++ 17 files changed, 1527 insertions(+), 16 deletions(-) create mode 100644 net/core/lwt_bpf.c create mode 100755 samples/bpf/lwt_len_hist.sh create mode 100644 samples/bpf/lwt_len_hist_kern.c create mode 100644 samples/bpf/lwt_len_hist_user.c create mode 100644 samples/bpf/test_lwt_bpf.c create mode 100755 samples/bpf/test_lwt_bpf.sh
Signature · 1 line
2.7.4
PATCH v4 1/4 route: Set orig_output when redirecting to lwt on locally generated traffic
orig_output for IPv4 was only set for dsts which hit an input route. Set it consistently for locally generated traffic as well to allow lwt to continue the dst_output() path as configured by the nexthop.
--- net/ipv4/route.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv4/route.c +3 -1
@@ -2154,8 +2154,10 @@ static struct rtable *__mkroute_output(const struct fib_result *res, }rt_set_nexthop (rth, fl4->daddr, res, fnhe, fi, type,0 ); -if (lwtunnel_output_redirect (rth->dst.lwtstate)) +if (lwtunnel_output_redirect (rth->dst.lwtstate)) { + rth->dst.lwtstate->orig_output = rth->dst.output; rth->dst.output = lwtunnel_output; + }return rth; }
Signature · 1 line
2.7.4
PATCH v4 2/4 route: Set lwtstate for local traffic and cached input dsts
In reply to Thomas GrafA route on the output path hitting a RTN_LOCAL route will keep the dst associated on its way through the loopback device. On the receive path, the dst_input() call will thus invoke the input handler of the route created in the output path. Thus, lwt redirection for input must be done for dsts allocated in the otuput path as well.
Also, if a route is cached in the input path, the allocated dst should respect lwtunnel configuration on the nexthop as well.
--- net/ipv4/route.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-)
net/ipv4/route.c +26 -13
@@ -1602,6 +1602,19 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)spin_unlock_bh (&fnhe_lock); } +static void set_lwt_redirect (struct rtable *rth) +{ +if (lwtunnel_output_redirect (rth->dst.lwtstate)) { + rth->dst.lwtstate->orig_output = rth->dst.output; + rth->dst.output = lwtunnel_output; + } + +if (lwtunnel_input_redirect (rth->dst.lwtstate)) { + rth->dst.lwtstate->orig_input = rth->dst.input; + rth->dst.input = lwtunnel_input; + } +} +/* called in rcu_read_lock() section */ static int __mkroute_input(struct sk_buff *skb, const struct fib_result *res,
@@ -1691,14 +1704,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->dst.input = ip_forward;rt_set_nexthop (rth, daddr, res, fnhe, res->fi, res->type, itag); -if (lwtunnel_output_redirect (rth->dst.lwtstate)) { - rth->dst.lwtstate->orig_output = rth->dst.output; - rth->dst.output = lwtunnel_output; - } -if (lwtunnel_input_redirect (rth->dst.lwtstate)) { - rth->dst.lwtstate->orig_input = rth->dst.input; - rth->dst.input = lwtunnel_input; - } +set_lwt_redirect (rth);skb_dst_set (skb, &rth->dst); out: err =0 ;
@@ -1925,8 +1931,18 @@ out: return err; rth->dst.error= -err; rth->rt_flags &= ~RTCF_LOCAL ; } +if (do_cache) { -if (unlikely (!rt_cache_route (&FIB_RES_NH (res), rth))) { +struct fib_nh *nh = &FIB_RES_NH (res); + + rth->dst.lwtstate =lwtstate_get (nh->nh_lwtstate); +if (lwtunnel_input_redirect (rth->dst.lwtstate)) { +WARN_ON (rth->dst.input == lwtunnel_input); + rth->dst.lwtstate->orig_input = rth->dst.input; + rth->dst.input = lwtunnel_input; + } + +if (unlikely (!rt_cache_route (nh, rth))) { rth->dst.flags |=DST_NOCACHE ;rt_add_uncached_list (rth); }
@@ -2154,10 +2170,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, }rt_set_nexthop (rth, fl4->daddr, res, fnhe, fi, type,0 ); -if (lwtunnel_output_redirect (rth->dst.lwtstate)) { - rth->dst.lwtstate->orig_output = rth->dst.output; - rth->dst.output = lwtunnel_output; - } +set_lwt_redirect (rth);return rth; }
Signature · 1 line
2.7.4
PATCH v4 3/4 bpf: BPF for lightweight tunnel infrastructure
In reply to Thomas GrafRegisters new BPF program types which correspond to the LWT hooks:
- BPF_PROG_TYPE_LWT_IN => dst_input()
- BPF_PROG_TYPE_LWT_OUT => dst_output()
- BPF_PROG_TYPE_LWT_XMIT => lwtunnel_xmit()
The separate program types are required to differentiate between the capabilities each LWT hook allows:
* Programs attached to dst_input() or dst_output() are restricted and may only read the data of an skb. This prevent modification and possible invalidation of already validated packet headers on receive and the construction of illegal headers while the IP headers are still being assembled.
* Programs attached to lwtunnel_xmit() are allowed to modify packet content as well as prepending an L2 header via a newly introduced helper bpf_skb_change_head(). This is safe as lwtunnel_xmit() is invoked after the IP header has been assembled completely.
All BPF programs receive an skb with L3 headers attached and may return one of the following error codes:
BPF_OK - Continue routing as per nexthop
BPF_DROP - Drop skb and return EPERM
BPF_REDIRECT - Redirect skb to device as per redirect() helper.
(Only valid in lwtunnel_xmit() context)
The return codes are binary compatible with their TC_ACT_ relatives to ease compatibility.
--- include/linux/filter.h | 2 +- include/uapi/linux/bpf.h | 32 +++- include/uapi/linux/lwtunnel.h | 23 +++ kernel/bpf/verifier.c | 14 +- net/Kconfig | 8 + net/core/Makefile | 1 + net/core/filter.c | 173 ++++++++++++++++++ net/core/lwt_bpf.c | 396 ++++++++++++++++++++++++++++++++++++++++++ net/core/lwtunnel.c | 2 + 9 files changed, 646 insertions(+), 5 deletions(-) create mode 100644 net/core/lwt_bpf.c
include/linux/filter.h +1 -1
@@ -438,7 +438,7 @@ struct xdp_buff { };/* compute the linear packet data range [data, data_end) which -* will be accessed by cls_bpf and act_bpf programs +* will be accessed by cls_bpf, act_bpf and lwt programs */ static inline void bpf_compute_data_end (struct sk_buff *skb) {
include/uapi/linux/bpf.h +31 -1
@@ -101,6 +101,9 @@ enum bpf_prog_type {BPF_PROG_TYPE_XDP ,BPF_PROG_TYPE_PERF_EVENT ,BPF_PROG_TYPE_CGROUP_SKB , +BPF_PROG_TYPE_LWT_IN , +BPF_PROG_TYPE_LWT_OUT , + BPF_PROG_TYPE_LWT_XMIT, }; enum bpf_attach_type {
@@ -409,6 +412,16 @@ union bpf_attr {* * int bpf_get_numa_node_id() * Return: Id of current NUMA node. +* +* int bpf_skb_change_head() +* Grows headroom of skb and adjusts MAC header offset accordingly. +* Will extends/reallocae as required automatically. +* May change skb data pointer and will thus invalidate any check +* performed for direct packet access. +* @skb: pointer to skb +* @len: length of header to be pushed in front +* @flags: Flags (unused for now) +* Return: 0 on success or negative error */ #define __BPF_FUNC_MAPPER (FN ) \ FN(unspec), \
@@ -453,7 +466,8 @@ union bpf_attr {FN (skb_pull_data), \FN (csum_update), \FN (set_hash_invalid), \ -FN (get_numa_node_id), +FN (get_numa_node_id), \ +FN (skb_change_head),/* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call
@@ -537,6 +551,22 @@ struct bpf_tunnel_key {__u32 tunnel_label; }; +/* Generic BPF return codes which all BPF program types may support. +* The values are binary compatible with their TC_ACT_* counter-part to +* provide backwards compatibility with existing SCHED_CLS and SCHED_ACT +* programs. +* +* XDP is handled seprately, see XDP_*. +*/ +enum bpf_ret_code { +BPF_OK =0 , +/* 1 reserved */ +BPF_DROP =2 , +/* 3-6 reserved */ +BPF_REDIRECT =7 , +/* >127 are reserved for prog type specific return codes */ +}; +/* User return codes for XDP prog type. * A valid XDP program must return one of these defined values. All other * return codes are reserved for future use. Unknown return codes will result
include/uapi/linux/lwtunnel.h +23 -0
@@ -10,6 +10,7 @@ enum lwtunnel_encap_types {LWTUNNEL_ENCAP_ILA ,LWTUNNEL_ENCAP_IP6 ,LWTUNNEL_ENCAP_SEG6 , +LWTUNNEL_ENCAP_BPF , __LWTUNNEL_ENCAP_MAX, };
@@ -43,4 +44,26 @@ enum lwtunnel_ip6_t {#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) +enum { +LWT_BPF_PROG_UNSPEC , +LWT_BPF_PROG_FD , +LWT_BPF_PROG_NAME , + __LWT_BPF_PROG_MAX, +}; + +#define LWT_BPF_PROG_MAX (__LWT_BPF_PROG_MAX - 1) + +enum { +LWT_BPF_UNSPEC , +LWT_BPF_IN , +LWT_BPF_OUT , +LWT_BPF_XMIT , +LWT_BPF_XMIT_HEADROOM , + __LWT_BPF_MAX, +}; + +#define LWT_BPF_MAX (__LWT_BPF_MAX - 1) + +#define LWT_BPF_MAX_HEADROOM 256 +#endif /* _UAPI_LWTUNNEL_H_ */
kernel/bpf/verifier.c +11 -3
@@ -633,12 +633,19 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, int off,#define MAX_PACKET_OFF 0xffffstatic bool may_access_direct_pkt_data (struct bpf_verifier_env *env, -const struct bpf_call_arg_meta *meta) +const struct bpf_call_arg_meta *meta, +enum bpf_access_type t) {switch (env->prog->type) { +case BPF_PROG_TYPE_LWT_IN : +case BPF_PROG_TYPE_LWT_OUT : +/* dst_input() and dst_output() can't write for now */ +if (t ==BPF_WRITE ) +return false;case BPF_PROG_TYPE_SCHED_CLS :case BPF_PROG_TYPE_SCHED_ACT :case BPF_PROG_TYPE_XDP : +case BPF_PROG_TYPE_LWT_XMIT :if (meta)return meta->pkt_access;
@@ -837,7 +844,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off, err =check_stack_read (state, off, size, value_regno); } }else if (state->regs[regno].type ==PTR_TO_PACKET ) { -if (t ==BPF_WRITE && !may_access_direct_pkt_data (env,NULL )) { +if (t ==BPF_WRITE && !may_access_direct_pkt_data (env,NULL , t)) {verbose ("cannot write into packet\n" );return -EACCES ; }
@@ -970,7 +977,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,return 0 ; } -if (type ==PTR_TO_PACKET && !may_access_direct_pkt_data (env, meta)) { +if (type ==PTR_TO_PACKET && + !may_access_direct_pkt_data (env, meta,BPF_READ )) {verbose ("helper access to the packet is not allowed\n" );return -EACCES ; }
net/Kconfig +8 -0
@@ -402,6 +402,14 @@ config LWTUNNEL weight tunnel endpoint. Tunnel encapsulation parameters are stored with light weight tunnel state associated with fib routes. +config LWTUNNEL_BPF + bool "Execute BPF program as route nexthop action" + depends on LWTUNNEL + default y if LWTUNNEL=y + ---help--- + Allows to run BPF programs as a nexthop action following a route + lookup for incoming and outgoing packets. + config DST_CACHE bool default n
net/core/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o obj-$(CONFIG_LWTUNNEL) += lwtunnel.o +obj-$(CONFIG_LWTUNNEL_BPF) += lwt_bpf.o obj-$(CONFIG_DST_CACHE) += dst_cache.o obj-$(CONFIG_HWBM) += hwbm.o obj-$(CONFIG_NET_DEVLINK) += devlink.o
net/core/filter.c +173 -0
221 lines not on this page · raw message
net/core/lwt_bpf.c new file +396 -0
396 lines not on this page · raw message
net/core/lwtunnel.c +2 -0
@@ -41,6 +41,8 @@ static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)return "ILA" ;case LWTUNNEL_ENCAP_SEG6 :return "SEG6" ; +case LWTUNNEL_ENCAP_BPF : +return "BPF" ;case LWTUNNEL_ENCAP_IP6 :case LWTUNNEL_ENCAP_IP :case LWTUNNEL_ENCAP_NONE :
Signature · 1 line
2.7.4
Re: [PATCH net-next v4 3/4] bpf: BPF for lightweight tunnel infrastructure
Quoted 27 lines · Thomas Graf
Registers new BPF program types which correspond to the LWT hooks:
-BPF_PROG_TYPE_LWT_IN=>dst_input()
-BPF_PROG_TYPE_LWT_OUT=>dst_output()
-BPF_PROG_TYPE_LWT_XMIT=>lwtunnel_xmit()The separate program types are required to differentiate between the capabilities each LWT hook allows:
* Programs attached to
dst_input()ordst_output()are restricted and may only read the data of an skb. This prevent modification and possible invalidation of already validated packet headers on receive and the construction of illegal headers while the IP headers are still being assembled.* Programs attached to
lwtunnel_xmit()are allowed to modify packet content as well as prepending an L2 header via a newly introduced helperbpf_skb_change_head(). This is safe aslwtunnel_xmit()is invoked after the IP header has been assembled completely.All BPF programs receive an skb with L3 headers attached and may return one of the following error codes:
BPF_OK- Continue routing as per nexthop
BPF_DROP- Drop skb and return EPERM
BPF_REDIRECT- Redirect skb to device as perredirect()helper.
(Only valid inlwtunnel_xmit()context)
Quoted 4 lines
The return codes are binary compatible with their
TC_ACT_relatives to ease compatibility.Signed-off-by Thomas Graf <[email protected]>
Looks great.
Re: [PATCH net-next v4 3/4] bpf: BPF for lightweight tunnel infrastructure
In reply to Thomas GrafQuoted 18 lines · Thomas Graf
Registers new BPF program types which correspond to the LWT hooks:
-BPF_PROG_TYPE_LWT_IN=>dst_input()
-BPF_PROG_TYPE_LWT_OUT=>dst_output()
-BPF_PROG_TYPE_LWT_XMIT=>lwtunnel_xmit()The separate program types are required to differentiate between the capabilities each LWT hook allows:
* Programs attached to
dst_input()ordst_output()are restricted and may only read the data of an skb. This prevent modification and possible invalidation of already validated packet headers on receive and the construction of illegal headers while the IP headers are still being assembled.* Programs attached to
lwtunnel_xmit()are allowed to modify packet content as well as prepending an L2 header via a newly introduced helperbpf_skb_change_head(). This is safe aslwtunnel_xmit()is invoked after the IP header has been assembled completely.
[...]
Quoted 2 lines
Signed-off-by Thomas Graf <[email protected]>
LGTMAFAICT, so:
For the verifier change in may_access_direct_pkt_data(), would be great if you could later on follow up with a selftest-suite case, one where BPF_PROG_TYPE_LWT_IN/OUT prog tries to write and fails, and one where BPF_PROG_TYPE_LWT_IN/OUT prog uses pkt data to pass to helpers, for example, so that we can keep testing it when future changes in that area are made. Thanks.
Re: [PATCH net-next v4 3/4] bpf: BPF for lightweight tunnel infrastructure
Quoted 6 lines · Daniel Borkmann
For the verifier change in
may_access_direct_pkt_data(), would be great if you could later on follow up with a selftest-suite case, one where BPF_PROG_TYPE_LWT_IN/OUT prog tries to write and fails, and one where BPF_PROG_TYPE_LWT_IN/OUT prog uses pkt data to pass to helpers, for example, so that we can keep testing it when future changes in that area are made. Thanks.
Good idea, will do.
PATCH v4 4/4 bpf: Add tests and samples for LWT-BPF
In reply to Thomas GrafAdds a series of tests to verify the functionality of attaching BPF programs at LWT hooks.
Also adds a sample which collects a histogram of packet sizes which pass through an LWT hook.
$ ./lwt_len_hist.sh Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.253.2 () port 0 AF_INET : demo Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec
87380 16384 16384 10.00 39857.69
1 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 0 | |
16 -> 31 : 0 | |
32 -> 63 : 22 | |
64 -> 127 : 98 | |
128 -> 255 : 213 | |
256 -> 511 : 1444251 |******** |
512 -> 1023 : 660610 |*** |
1024 -> 2047 : 535241 |** |
2048 -> 4095 : 19 | |
4096 -> 8191 : 180 | |
8192 -> 16383 : 5578023 |************************************* |
16384 -> 32767 : 632099 |*** |
32768 -> 65535 : 6575 | |--- samples/bpf/Makefile | 4 + samples/bpf/bpf_helpers.h | 4 + samples/bpf/lwt_len_hist.sh | 37 ++++ samples/bpf/lwt_len_hist_kern.c | 82 +++++++++ samples/bpf/lwt_len_hist_user.c | 76 ++++++++ samples/bpf/test_lwt_bpf.c | 253 +++++++++++++++++++++++++ samples/bpf/test_lwt_bpf.sh | 399 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 855 insertions(+) create mode 100755 samples/bpf/lwt_len_hist.sh create mode 100644 samples/bpf/lwt_len_hist_kern.c create mode 100644 samples/bpf/lwt_len_hist_user.c create mode 100644 samples/bpf/test_lwt_bpf.c create mode 100755 samples/bpf/test_lwt_bpf.sh
samples/bpf/Makefile +4 -0
@@ -29,6 +29,7 @@ hostprogs-y += test_current_task_under_cgroup hostprogs-y += trace_event hostprogs-y += sampleip hostprogs-y += tc_l2_redirect +hostprogs-y += lwt_len_hist test_lru_dist-objs := test_lru_dist.o libbpf.o sock_example-objs := sock_example.o libbpf.o
@@ -59,6 +60,7 @@ test_current_task_under_cgroup-objs := bpf_load.o libbpf.o \ trace_event-objs := bpf_load.o libbpf.o trace_event_user.o sampleip-objs := bpf_load.o libbpf.o sampleip_user.o tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o +lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o # Tell kbuild to always build the programs always := $(hostprogs-y)
@@ -89,6 +91,7 @@ always += xdp2_kern.o always += test_current_task_under_cgroup_kern.o always += trace_event_kern.o always += sampleip_kern.o +always += lwt_len_hist_kern.o HOSTCFLAGS += -I$(objtree)/usr/include HOSTCFLAGS += -I$(objtree)/tools/testing/selftests/bpf/
@@ -117,6 +120,7 @@ HOSTLOADLIBES_test_current_task_under_cgroup += -lelf HOSTLOADLIBES_trace_event += -lelf HOSTLOADLIBES_sampleip += -lelf HOSTLOADLIBES_tc_l2_redirect += -l elf +HOSTLOADLIBES_lwt_len_hist += -l elf # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
samples/bpf/bpf_helpers.h +4 -0
@@ -80,6 +80,8 @@ struct bpf_map_def {unsigned int map_flags; }; +static int (*bpf_skb_load_bytes)(void *ctx,int off,void *to,int len) = + (void *) BPF_FUNC_skb_load_bytes;static int (*bpf_skb_store_bytes)(void *ctx,int off,void *from,int len,int flags) = (void *) BPF_FUNC_skb_store_bytes; static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) =
@@ -88,6 +90,8 @@ static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flag (void *) BPF_FUNC_l4_csum_replace;static int (*bpf_skb_under_cgroup)(void *ctx,void *map,int index) = (void *) BPF_FUNC_skb_under_cgroup; +static int (*bpf_skb_change_head)(void *,int len,int flags) = + (void *) BPF_FUNC_skb_change_head;#if defined(__x86_64__)
samples/bpf/lwt_len_hist.sh new file +37 -0
@@ -0,0 +1,37 @@ +#!/bin/bash + +NS1=lwt_ns1 +VETH0=tst_lwt1a +VETH1=tst_lwt1b + +TRACE_ROOT=/sys/kernel/debug/tracing + +function cleanup { + ip route del 192.168.253.2/32 dev $VETH0 2> /dev/null + ip link del $VETH0 2> /dev/null + ip link del $VETH1 2> /dev/null + ip netns exec $NS1 killall netserver + ip netns delete $NS1 2> /dev/null +} + +cleanup + +ip netns add $NS1 +ip link add $VETH0 type veth peer name $VETH1 +ip link set dev $VETH0 up +ip addr add 192.168.253.1/24 dev $VETH0 +ip link set $VETH1 netns $NS1 +ip netns exec $NS1 ip link set dev $VETH1 up +ip netns exec $NS1 ip addr add 192.168.253.2/24 dev $VETH1 +ip netns exec $NS1 netserver + +echo 1 > ${TRACE_ROOT}/tracing_on +cp /dev/null ${TRACE_ROOT}/trace +ip route add 192.168.253.2/32 encap bpf out obj lwt_len_hist_kern.o section len_hist dev $VETH0 +netperf -H 192.168.253.2 -t TCP_STREAM +cat ${TRACE_ROOT}/trace | grep -v '^#' +./lwt_len_hist +cleanup +echo 0 > ${TRACE_ROOT}/tracing_on + +exit 0
samples/bpf/lwt_len_hist_kern.c new file +82 -0
82 lines not on this page · raw message
samples/bpf/lwt_len_hist_user.c new file +76 -0
76 lines not on this page · raw message
samples/bpf/test_lwt_bpf.c new file +253 -0
253 lines not on this page · raw message
samples/bpf/test_lwt_bpf.sh new file +399 -0
399 lines not on this page · raw message
Signature · 1 line
2.7.4
Re: [PATCH net-next v4 4/4] bpf: Add tests and samples for LWT-BPF
Quoted 47 lines · Thomas Graf
Adds a series of tests to verify the functionality of attaching BPF programs at LWT hooks.
Also adds a sample which collects a histogram of packet sizes which pass through an LWT hook.
$ ./lwt_len_hist.sh Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.253.2 () port 0 AF_INET : demo Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec87380 16384 16384 10.00 39857.69
1 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 22 | | 64 -> 127 : 98 | | 128 -> 255 : 213 | | 256 -> 511 : 1444251 |******** | 512 -> 1023 : 660610 |*** | 1024 -> 2047 : 535241 |** | 2048 -> 4095 : 19 | | 4096 -> 8191 : 180 | | 8192 -> 16383 : 5578023 |************************************* | 16384 -> 32767 : 632099 |*** | 32768 -> 65535 : 6575 | |Signed-off-by Thomas Graf <[email protected]>--- samples/bpf/Makefile | 4 + samples/bpf/bpf_helpers.h | 4 + samples/bpf/lwt_len_hist.sh | 37 ++++ samples/bpf/lwt_len_hist_kern.c | 82 +++++++++ samples/bpf/lwt_len_hist_user.c | 76 ++++++++ samples/bpf/test_lwt_bpf.c | 253 +++++++++++++++++++++++++ samples/bpf/test_lwt_bpf.sh | 399 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 855 insertions(+) create mode 100755 samples/bpf/lwt_len_hist.sh create mode 100644 samples/bpf/lwt_len_hist_kern.c create mode 100644 samples/bpf/lwt_len_hist_user.c create mode 100644 samples/bpf/test_lwt_bpf.c create mode 100755 samples/bpf/test_lwt_bpf.sh
...
Quoted 24 lines
samples/bpf/test_lwt_bpf.c new file +24
-0+static inline void __fill_garbage (struct __sk_buff *skb) +{ +uint64_t f =0xFFFFFFFFFFFFFFFF ; + +bpf_skb_store_bytes (skb,0 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,8 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,16 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,24 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,32 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,40 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,48 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,56 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,64 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,72 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,80 , &f,sizeof (f),0 ); +bpf_skb_store_bytes (skb,88 , &f,sizeof (f),0 ); +} + +SEC("fill_garbage") +int do_fill_garbage (struct __sk_buff *skb) +{ +__fill_garbage (skb); +printk ("Set initial 96 bytes of header to FF\n" ); +return BPF_OK ;
samples/bpf/test_lwt_bpf.c line 243
Quoted 10 lines
samples/bpf/test_lwt_bpf.c new file +10
-0+} + +SEC("fill_garbage_and_redirect") +int do_fill_garbage_and_redirect (struct __sk_buff *skb) +{ +int ifindex =DST_IFINDEX ; +__fill_garbage (skb); +printk ("redirected to %d\n" , ifindex); +return bpf_redirect (ifindex,0 ); +}
Two 'garbage' tests! Pure garbage ;)
David Miller
maintainerFrom: Thomas Graf <[email protected]>
Date: Wed, 30 Nov 2016 17:10:07 +0100
Quoted 2 lines
This series implements BPF program invocation from dst entries via the lightweight tunnels infrastructure.
Nice work, applied, thanks Thomas.