David Ahern <[email protected]> writes: > From: David Ahern <[email protected]> > > Add BPF_XDP_DEVMAP attach type for use with programs associated with a > DEVMAP entry. > > Allow DEVMAPs to associate a program with a device entry by adding > a bpf_prog_fd to 'struct devmap_val'. Values read show the program > id, so the fd and id are a union. > > The program associated with the fd must have type XDP with expected > attach type BPF_XDP_DEVMAP. When a program is associated with a device > index, the program is run on an XDP_REDIRECT and before the buffer is > added to the per-cpu queue. At this point rxq data is still valid; the > next patch adds tx device information allowing the prorgam to see both > ingress and egress device indices. > > XDP generic is skb based and XDP programs do not work with skb's. Block > the use case by walking maps used by a program that is to be attached > via xdpgeneric and fail if any of them are DEVMAP / DEVMAP_HASH with > > 4-byte values. > > Block attach of BPF_XDP_DEVMAP programs to devices. > > Signed-off-by: David Ahern <[email protected]> > --- > include/linux/bpf.h | 5 +++ > include/uapi/linux/bpf.h | 5 +++ > kernel/bpf/devmap.c | 79 +++++++++++++++++++++++++++++++++- > net/core/dev.c | 18 ++++++++ > tools/include/uapi/linux/bpf.h | 5 +++ > 5 files changed, 110 insertions(+), 2 deletions(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index efe8836b5c48..088751bc09aa 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -1242,6 +1242,7 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct > xdp_buff *xdp, > struct net_device *dev_rx); > int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff > *skb, > struct bpf_prog *xdp_prog); > +bool dev_map_can_have_prog(struct bpf_map *map); > > struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 > key); > void __cpu_map_flush(void); > @@ -1355,6 +1356,10 @@ static inline struct net_device > *__dev_map_hash_lookup_elem(struct bpf_map *map > { > return NULL; > } > +static inline bool dev_map_can_have_prog(struct bpf_map *map) > +{ > + return false; > +} > > static inline void __dev_flush(void) > { > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index d27302ecaa9c..2d9927b7a922 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -224,6 +224,7 @@ enum bpf_attach_type { > BPF_CGROUP_INET6_GETPEERNAME, > BPF_CGROUP_INET4_GETSOCKNAME, > BPF_CGROUP_INET6_GETSOCKNAME, > + BPF_XDP_DEVMAP, > __MAX_BPF_ATTACH_TYPE > }; > > @@ -3628,6 +3629,10 @@ struct xdp_md { > /* DEVMAP values */ > struct devmap_val { > __u32 ifindex; /* device index */ > + union { > + int bpf_prog_fd; /* prog fd on map write */ > + __u32 bpf_prog_id; /* prog id on map read */ > + }; > }; > > enum sk_action { > diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c > index 069a50113e26..a628585a31e1 100644 > --- a/kernel/bpf/devmap.c > +++ b/kernel/bpf/devmap.c > @@ -64,6 +64,7 @@ struct bpf_dtab_netdev { > struct net_device *dev; /* must be first member, due to tracepoint */ > struct hlist_node index_hlist; > struct bpf_dtab *dtab; > + struct bpf_prog *xdp_prog; > struct rcu_head rcu; > unsigned int idx; > struct devmap_val val; > @@ -219,6 +220,8 @@ static void dev_map_free(struct bpf_map *map) > > hlist_for_each_entry_safe(dev, next, head, index_hlist) > { > hlist_del_rcu(&dev->index_hlist); > + if (dev->xdp_prog) > + bpf_prog_put(dev->xdp_prog); > dev_put(dev->dev); > kfree(dev); > } > @@ -233,6 +236,8 @@ static void dev_map_free(struct bpf_map *map) > if (!dev) > continue; > > + if (dev->xdp_prog) > + bpf_prog_put(dev->xdp_prog); > dev_put(dev->dev); > kfree(dev); > } > @@ -319,6 +324,16 @@ static int dev_map_hash_get_next_key(struct bpf_map > *map, void *key, > return -ENOENT; > } > > +bool dev_map_can_have_prog(struct bpf_map *map) > +{ > + if ((map->map_type == BPF_MAP_TYPE_DEVMAP || > + map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) && > + map->value_size != 4)
nit (since you've gotten rid of the magic sizes everywhere else) how about: map->value_size != sizeof_field(struct devmap_val, ifindex)
