Commit 7f1c0426 authored by David Ahern's avatar David Ahern Committed by Alexei Starovoitov

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: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarToke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/bpf/20200529220716.75383-2-dsahern@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent b36e62eb
...@@ -60,12 +60,18 @@ struct xdp_dev_bulk_queue { ...@@ -60,12 +60,18 @@ struct xdp_dev_bulk_queue {
unsigned int count; unsigned int count;
}; };
/* DEVMAP values */
struct bpf_devmap_val {
u32 ifindex; /* device index */
};
struct bpf_dtab_netdev { struct bpf_dtab_netdev {
struct net_device *dev; /* must be first member, due to tracepoint */ struct net_device *dev; /* must be first member, due to tracepoint */
struct hlist_node index_hlist; struct hlist_node index_hlist;
struct bpf_dtab *dtab; struct bpf_dtab *dtab;
struct rcu_head rcu; struct rcu_head rcu;
unsigned int idx; unsigned int idx;
struct bpf_devmap_val val;
}; };
struct bpf_dtab { struct bpf_dtab {
...@@ -472,18 +478,15 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb, ...@@ -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) 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 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) static void *dev_map_hash_lookup_elem(struct bpf_map *map, void *key)
{ {
struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map, struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map,
*(u32 *)key); *(u32 *)key);
struct net_device *dev = obj ? obj->dev : NULL; return obj ? &obj->val : NULL;
return dev ? &dev->ifindex : NULL;
} }
static void __dev_map_entry_free(struct rcu_head *rcu) 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) ...@@ -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, static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
struct bpf_dtab *dtab, struct bpf_dtab *dtab,
u32 ifindex, struct bpf_devmap_val *val,
unsigned int idx) unsigned int idx)
{ {
struct bpf_dtab_netdev *dev; struct bpf_dtab_netdev *dev;
...@@ -551,16 +554,18 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, ...@@ -551,16 +554,18 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
if (!dev) if (!dev)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
dev->dev = dev_get_by_index(net, ifindex); dev->dev = dev_get_by_index(net, val->ifindex);
if (!dev->dev) { if (!dev->dev)
kfree(dev); goto err_out;
return ERR_PTR(-EINVAL);
}
dev->idx = idx; dev->idx = idx;
dev->dtab = dtab; dev->dtab = dtab;
dev->val.ifindex = val->ifindex;
return dev; return dev;
err_out:
kfree(dev);
return ERR_PTR(-EINVAL);
} }
static int __dev_map_update_elem(struct net *net, struct bpf_map *map, 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, ...@@ -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 *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *dev, *old_dev; struct bpf_dtab_netdev *dev, *old_dev;
u32 ifindex = *(u32 *)value; struct bpf_devmap_val val = { };
u32 i = *(u32 *)key; u32 i = *(u32 *)key;
if (unlikely(map_flags > BPF_EXIST)) if (unlikely(map_flags > BPF_EXIST))
...@@ -578,10 +583,13 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map, ...@@ -578,10 +583,13 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
if (unlikely(map_flags == BPF_NOEXIST)) if (unlikely(map_flags == BPF_NOEXIST))
return -EEXIST; return -EEXIST;
if (!ifindex) { /* already verified value_size <= sizeof val */
memcpy(&val, value, map->value_size);
if (!val.ifindex) {
dev = NULL; dev = NULL;
} else { } else {
dev = __dev_map_alloc_node(net, dtab, ifindex, i); dev = __dev_map_alloc_node(net, dtab, &val, i);
if (IS_ERR(dev)) if (IS_ERR(dev))
return PTR_ERR(dev); return PTR_ERR(dev);
} }
...@@ -609,12 +617,15 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, ...@@ -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 *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *dev, *old_dev; struct bpf_dtab_netdev *dev, *old_dev;
u32 ifindex = *(u32 *)value; struct bpf_devmap_val val = { };
u32 idx = *(u32 *)key; u32 idx = *(u32 *)key;
unsigned long flags; unsigned long flags;
int err = -EEXIST; 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; return -EINVAL;
spin_lock_irqsave(&dtab->index_lock, flags); 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, ...@@ -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)) if (old_dev && (map_flags & BPF_NOEXIST))
goto out_err; 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)) { if (IS_ERR(dev)) {
err = PTR_ERR(dev); err = PTR_ERR(dev);
goto out_err; goto out_err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment