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

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.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent b36e62eb
Loading
Loading
Loading
Loading
+28 −17
Original line number Diff line number Diff line
@@ -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;