Commit 3274f520 authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by David S. Miller

bpf: add 'flags' attribute to BPF_MAP_UPDATE_ELEM command

the current meaning of BPF_MAP_UPDATE_ELEM syscall command is:
either update existing map element or create a new one.
Initially the plan was to add a new command to handle the case of
'create new element if it didn't exist', but 'flags' style looks
cleaner and overall diff is much smaller (more code reused), so add 'flags'
attribute to BPF_MAP_UPDATE_ELEM command with the following meaning:
 #define BPF_ANY	0 /* create new element or update existing */
 #define BPF_NOEXIST	1 /* create new element if it didn't exist */
 #define BPF_EXIST	2 /* update existing element */

bpf_update_elem(fd, key, value, BPF_NOEXIST) call can fail with EEXIST
if element already exists.

bpf_update_elem(fd, key, value, BPF_EXIST) can fail with ENOENT
if element doesn't exist.

Userspace will call it as:
int bpf_update_elem(int fd, void *key, void *value, __u64 flags)
{
    union bpf_attr attr = {
        .map_fd = fd,
        .key = ptr_to_u64(key),
        .value = ptr_to_u64(value),
        .flags = flags;
    };

    return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}

First two bits of 'flags' are used to encode style of bpf_update_elem() command.
Bits 2-63 are reserved for future use.
Signed-off-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1bbf148d
...@@ -22,7 +22,7 @@ struct bpf_map_ops { ...@@ -22,7 +22,7 @@ struct bpf_map_ops {
/* funcs callable from userspace and from eBPF programs */ /* funcs callable from userspace and from eBPF programs */
void *(*map_lookup_elem)(struct bpf_map *map, void *key); void *(*map_lookup_elem)(struct bpf_map *map, void *key);
int (*map_update_elem)(struct bpf_map *map, void *key, void *value); int (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
int (*map_delete_elem)(struct bpf_map *map, void *key); int (*map_delete_elem)(struct bpf_map *map, void *key);
}; };
......
...@@ -82,7 +82,7 @@ enum bpf_cmd { ...@@ -82,7 +82,7 @@ enum bpf_cmd {
/* create or update key/value pair in a given map /* create or update key/value pair in a given map
* err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size) * err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size)
* Using attr->map_fd, attr->key, attr->value * Using attr->map_fd, attr->key, attr->value, attr->flags
* returns zero or negative error * returns zero or negative error
*/ */
BPF_MAP_UPDATE_ELEM, BPF_MAP_UPDATE_ELEM,
...@@ -117,6 +117,11 @@ enum bpf_prog_type { ...@@ -117,6 +117,11 @@ enum bpf_prog_type {
BPF_PROG_TYPE_UNSPEC, BPF_PROG_TYPE_UNSPEC,
}; };
/* flags for BPF_MAP_UPDATE_ELEM command */
#define BPF_ANY 0 /* create new element or update existing */
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
#define BPF_EXIST 2 /* update existing element */
union bpf_attr { union bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */ struct { /* anonymous struct used by BPF_MAP_CREATE command */
__u32 map_type; /* one of enum bpf_map_type */ __u32 map_type; /* one of enum bpf_map_type */
...@@ -132,6 +137,7 @@ union bpf_attr { ...@@ -132,6 +137,7 @@ union bpf_attr {
__aligned_u64 value; __aligned_u64 value;
__aligned_u64 next_key; __aligned_u64 next_key;
}; };
__u64 flags;
}; };
struct { /* anonymous struct used by BPF_PROG_LOAD command */ struct { /* anonymous struct used by BPF_PROG_LOAD command */
......
...@@ -190,7 +190,7 @@ static int map_lookup_elem(union bpf_attr *attr) ...@@ -190,7 +190,7 @@ static int map_lookup_elem(union bpf_attr *attr)
return err; return err;
} }
#define BPF_MAP_UPDATE_ELEM_LAST_FIELD value #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
static int map_update_elem(union bpf_attr *attr) static int map_update_elem(union bpf_attr *attr)
{ {
...@@ -231,7 +231,7 @@ static int map_update_elem(union bpf_attr *attr) ...@@ -231,7 +231,7 @@ static int map_update_elem(union bpf_attr *attr)
* therefore all map accessors rely on this fact, so do the same here * therefore all map accessors rely on this fact, so do the same here
*/ */
rcu_read_lock(); rcu_read_lock();
err = map->ops->map_update_elem(map, key, value); err = map->ops->map_update_elem(map, key, value, attr->flags);
rcu_read_unlock(); rcu_read_unlock();
free_value: free_value:
......
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