devmap: Formalize map value as a named struct
Add 'struct bpf_devmap_val' to formalize the expected values that can be passed in for a DEVMAP. Update devmap code to use the struct. Signed-off-by: David Ahern <dsahern@kernel.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Toke Høiland-Jørgensen <toke@redhat.com> Link: https://lore.kernel.org/bpf/20200529220716.75383-2-dsahern@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
b36e62eb85
commit
7f1c04269f
@ -60,12 +60,18 @@ struct xdp_dev_bulk_queue {
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
/* DEVMAP values */
|
||||
struct bpf_devmap_val {
|
||||
u32 ifindex; /* device index */
|
||||
};
|
||||
|
||||
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 rcu_head rcu;
|
||||
unsigned int idx;
|
||||
struct bpf_devmap_val val;
|
||||
};
|
||||
|
||||
struct bpf_dtab {
|
||||
@ -472,18 +478,15 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
|
||||
static void *dev_map_lookup_elem(struct bpf_map *map, void *key)
|
||||
{
|
||||
struct bpf_dtab_netdev *obj = __dev_map_lookup_elem(map, *(u32 *)key);
|
||||
struct net_device *dev = obj ? obj->dev : NULL;
|
||||
|
||||
return dev ? &dev->ifindex : NULL;
|
||||
return obj ? &obj->val : NULL;
|
||||
}
|
||||
|
||||
static void *dev_map_hash_lookup_elem(struct bpf_map *map, void *key)
|
||||
{
|
||||
struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map,
|
||||
*(u32 *)key);
|
||||
struct net_device *dev = obj ? obj->dev : NULL;
|
||||
|
||||
return dev ? &dev->ifindex : NULL;
|
||||
return obj ? &obj->val : NULL;
|
||||
}
|
||||
|
||||
static void __dev_map_entry_free(struct rcu_head *rcu)
|
||||
@ -541,7 +544,7 @@ static int dev_map_hash_delete_elem(struct bpf_map *map, void *key)
|
||||
|
||||
static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
|
||||
struct bpf_dtab *dtab,
|
||||
u32 ifindex,
|
||||
struct bpf_devmap_val *val,
|
||||
unsigned int idx)
|
||||
{
|
||||
struct bpf_dtab_netdev *dev;
|
||||
@ -551,16 +554,18 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
|
||||
if (!dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dev->dev = dev_get_by_index(net, ifindex);
|
||||
if (!dev->dev) {
|
||||
kfree(dev);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
dev->dev = dev_get_by_index(net, val->ifindex);
|
||||
if (!dev->dev)
|
||||
goto err_out;
|
||||
|
||||
dev->idx = idx;
|
||||
dev->dtab = dtab;
|
||||
dev->val.ifindex = val->ifindex;
|
||||
|
||||
return dev;
|
||||
err_out:
|
||||
kfree(dev);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
|
||||
@ -568,7 +573,7 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
|
||||
{
|
||||
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
|
||||
struct bpf_dtab_netdev *dev, *old_dev;
|
||||
u32 ifindex = *(u32 *)value;
|
||||
struct bpf_devmap_val val = { };
|
||||
u32 i = *(u32 *)key;
|
||||
|
||||
if (unlikely(map_flags > BPF_EXIST))
|
||||
@ -578,10 +583,13 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
|
||||
if (unlikely(map_flags == BPF_NOEXIST))
|
||||
return -EEXIST;
|
||||
|
||||
if (!ifindex) {
|
||||
/* already verified value_size <= sizeof val */
|
||||
memcpy(&val, value, map->value_size);
|
||||
|
||||
if (!val.ifindex) {
|
||||
dev = NULL;
|
||||
} else {
|
||||
dev = __dev_map_alloc_node(net, dtab, ifindex, i);
|
||||
dev = __dev_map_alloc_node(net, dtab, &val, i);
|
||||
if (IS_ERR(dev))
|
||||
return PTR_ERR(dev);
|
||||
}
|
||||
@ -609,12 +617,15 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map,
|
||||
{
|
||||
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
|
||||
struct bpf_dtab_netdev *dev, *old_dev;
|
||||
u32 ifindex = *(u32 *)value;
|
||||
struct bpf_devmap_val val = { };
|
||||
u32 idx = *(u32 *)key;
|
||||
unsigned long flags;
|
||||
int err = -EEXIST;
|
||||
|
||||
if (unlikely(map_flags > BPF_EXIST || !ifindex))
|
||||
/* already verified value_size <= sizeof val */
|
||||
memcpy(&val, value, map->value_size);
|
||||
|
||||
if (unlikely(map_flags > BPF_EXIST || !val.ifindex))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dtab->index_lock, flags);
|
||||
@ -623,7 +634,7 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map,
|
||||
if (old_dev && (map_flags & BPF_NOEXIST))
|
||||
goto out_err;
|
||||
|
||||
dev = __dev_map_alloc_node(net, dtab, ifindex, idx);
|
||||
dev = __dev_map_alloc_node(net, dtab, &val, idx);
|
||||
if (IS_ERR(dev)) {
|
||||
err = PTR_ERR(dev);
|
||||
goto out_err;
|
||||
|
Loading…
Reference in New Issue
Block a user