Minor BPF follow-ups
Subsystems (6)
Daniel Borkmann
maintainercover Minor BPF follow-ups
Some minor last follow-ups I still had in my queue. The first one adds readability support for __sk_buff's tc_classid member, the remaining two are some minor cleanups. For details please see individual patches.
Thanks!
Daniel Borkmann (3):
bpf: make skb->tc_classid also readable
bpf, dst: add and use dst_tclassid helper ip_tunnels, bpf: define IP_TUNNEL_OPTS_MAX and use it
include/net/dst.h | 12 ++++++++++++ include/net/ip_tunnels.h | 7 +++++++ net/core/filter.c | 30 +++++++++--------------------- net/ipv4/ip_tunnel_core.c | 6 ++++++ net/openvswitch/flow.h | 2 +- 5 files changed, 35 insertions(+), 22 deletions(-)
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 1/3 bpf: make skb->tc_classid also readable
Currently, the tc_classid from eBPF skb context is write-only, but there's no good reason for tc programs to limit it to write-only. For example, it can be used to transfer its state via tail calls where the resulting tc_classid gets filled gradually.
--- net/core/filter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
net/core/filter.c +6 -6
@@ -2069,16 +2069,14 @@ static bool sk_filter_is_valid_access(int off, int size,static bool tc_cls_act_is_valid_access (int off,int size,enum bpf_access_type type) { -if (off == offsetof(struct __sk_buff , tc_classid)) -return type ==BPF_WRITE ? true : false; -if (type ==BPF_WRITE ) {switch (off) {case offsetof(struct __sk_buff , mark):case offsetof(struct __sk_buff , tc_index):case offsetof(struct __sk_buff , priority): case offsetof(struct __sk_buff, cb[0]) ... - offsetof(struct __sk_buff, cb[4]): + offsetof(struct __sk_buff, cb[4]): +case offsetof(struct __sk_buff , tc_classid):break ;default :return false;
@@ -2195,8 +2193,10 @@ static u32 bpf_net_convert_ctx_access(enum bpf_access_type type, int dst_reg, ctx_off -= offsetof(struct __sk_buff , tc_classid); ctx_off += offsetof(struct sk_buff , cb); ctx_off += offsetof(struct qdisc_skb_cb , tc_classid); -WARN_ON (type !=BPF_WRITE ); - *insn++ =BPF_STX_MEM (BPF_H , dst_reg, src_reg, ctx_off); +if (type ==BPF_WRITE ) + *insn++ =BPF_STX_MEM (BPF_H , dst_reg, src_reg, ctx_off); +else + *insn++ =BPF_LDX_MEM (BPF_H , dst_reg, src_reg, ctx_off);break ;case offsetof(struct __sk_buff , tc_index):
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 2/3 bpf, dst: add and use dst_tclassid helper
In reply to Daniel BorkmannWe can just add a small helper dst_tclassid() for retrieving the dst->tclassid value. It makes the code a bit better in that we can get rid of the ifdef from filter.c by moving this into the header.
--- include/net/dst.h | 12 ++++++++++++ net/core/filter.c | 9 +-------- 2 files changed, 13 insertions(+), 8 deletions(-)
include/net/dst.h +12 -0
@@ -398,6 +398,18 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,__skb_tunnel_rx (skb, dev, net); } +static inline u32 dst_tclassid (const struct sk_buff *skb) +{ +#ifdef CONFIG_IP_ROUTE_CLASSID +const struct dst_entry *dst; + + dst =skb_dst (skb); +if (dst) +return dst->tclassid; +#endif +return 0 ; +} +int dst_discard_out (struct net *net,struct sock *sk,struct sk_buff *skb);static inline int dst_discard (struct sk_buff *skb) {
net/core/filter.c +1 -8
@@ -1682,14 +1682,7 @@ static const struct bpf_func_proto bpf_get_cgroup_classid_proto = {static u64 bpf_get_route_realm (u64 r1,u64 r2,u64 r3,u64 r4,u64 r5) { -#ifdef CONFIG_IP_ROUTE_CLASSID -const struct dst_entry *dst; - - dst =skb_dst ((struct sk_buff *) (unsigned long ) r1); -if (dst) -return dst->tclassid; -#endif -return 0 ; +return dst_tclassid ((struct sk_buff *) (unsigned long ) r1); }static const struct bpf_func_proto bpf_get_route_realm_proto = {
Signature · 1 line
1.9.3
Daniel Borkmann
maintainerPATCH 3/3 ip_tunnels, bpf: define IP_TUNNEL_OPTS_MAX and use it
In reply to Daniel BorkmanneBPF defines this as BPF_TUNLEN_MAX and OVS just uses the hard-coded value inside struct sw_flow_key. Thus, add and use IP_TUNNEL_OPTS_MAX for this, which makes the code a bit more generic and allows to remove BPF_TUNLEN_MAX from eBPF code.
--- include/net/ip_tunnels.h | 7 +++++++ net/core/filter.c | 9 ++------- net/ipv4/ip_tunnel_core.c | 6 ++++++ net/openvswitch/flow.h | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-)
include/net/ip_tunnels.h +7 -0
@@ -7,6 +7,8 @@#include <linux/socket.h> #include <linux/types.h> #include <linux/u64_stats_sync.h> +#include <linux/bitops.h> +#include <net/dsfield.h> #include <net/gro_cells.h> #include <net/inet_ecn.h>
@@ -57,6 +59,11 @@ struct ip_tunnel_key {#define IP_TUNNEL_INFO_TX 0x01/* represents tx tunnel parameters */ #define IP_TUNNEL_INFO_IPV6 0x02/* key contains IPv6 addresses */ +/* Maximum tunnel options length. */ +#define IP_TUNNEL_OPTS_MAX \ + GENMASK((FIELD_SIZEOF(struct ip_tunnel_info, \ + options_len) * BITS_PER_BYTE) - 1, 0) +struct ip_tunnel_info {struct ip_tunnel_key key;#ifdef CONFIG_DST_CACHE
net/core/filter.c +2 -7
@@ -1904,8 +1904,6 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = { .arg4_type = ARG_ANYTHING, }; -#define BPF_TUNLEN_MAX 255 -static u64 bpf_skb_set_tunnel_opt (u64 r1,u64 r2,u64 size,u64 r4,u64 r5) {struct sk_buff *skb = (struct sk_buff *) (long ) r1;
@@ -1915,7 +1913,7 @@ static u64 bpf_skb_set_tunnel_opt(u64 r1, u64 r2, u64 size, u64 r4, u64 r5)if (unlikely (info != &md->u.tun_info || (size & (sizeof (u32) -1 ))))return -EINVAL ; -if (unlikely (size >BPF_TUNLEN_MAX )) +if (unlikely (size >IP_TUNNEL_OPTS_MAX ))return -ENOMEM ;ip_tunnel_info_opts_set (info, from, size);
@@ -1936,13 +1934,10 @@ static const struct bpf_func_proto * bpf_get_skb_set_tunnel_proto(enum bpf_func_id which) {if (!md_dst) { -BUILD_BUG_ON (FIELD_SIZEOF (struct ip_tunnel_info , - options_len) != 1); -/* Race is not possible, since it's called from verifier * that is holding verifier mutex. */ - md_dst =metadata_dst_alloc_percpu (BPF_TUNLEN_MAX , + md_dst =metadata_dst_alloc_percpu (IP_TUNNEL_OPTS_MAX ,GFP_KERNEL );if (!md_dst)return NULL ;
net/ipv4/ip_tunnel_core.c +6 -0
@@ -398,6 +398,12 @@ static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {void __init ip_tunnel_core_init (void ) { +/* If you land here, make sure whether increasing ip_tunnel_info's +* options_len is a reasonable choice with its usage in front ends +* (f.e., it's part of flow keys, etc). +*/ +BUILD_BUG_ON (IP_TUNNEL_OPTS_MAX !=255 ); +lwtunnel_encap_add_ops (&ip_tun_lwt_ops,LWTUNNEL_ENCAP_IP );lwtunnel_encap_add_ops (&ip6_tun_lwt_ops,LWTUNNEL_ENCAP_IP6 ); }
net/openvswitch/flow.h +1 -1
@@ -55,7 +55,7 @@ struct ovs_tunnel_info { FIELD_SIZEOF(struct sw_flow_key, recirc_id))struct sw_flow_key { - u8 tun_opts[255]; +u8 tun_opts[IP_TUNNEL_OPTS_MAX ];u8 tun_opts_len;struct ip_tunnel_key tun_key;/* Encapsulating tunnel key. */ struct {
Signature · 1 line
1.9.3
David Miller
maintainerFrom: Daniel Borkmann <[email protected]>
Date: Wed, 16 Mar 2016 01:42:48 +0100
Quoted 3 lines
Some minor last follow-ups I still had in my queue. The first one adds readability support for __sk_buff's
tc_classidmember, the remaining two are some minor cleanups. For details please see individual patches.
Series applied.