Sometimes we want to traverse the map elements and make use of the map value one by one. So add new function map->ops->map_traverse_elem() to traverse map elements.
Signed-off-by: kaixu xia <xiaka...@huawei.com> --- include/linux/bpf.h | 3 +++ kernel/bpf/arraymap.c | 17 +++++++++++++++++ kernel/bpf/hashtab.c | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 2634a25..f593199 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -13,6 +13,8 @@ struct bpf_map; +typedef int (*bpf_map_traverse_callback)(void *value); + /* map is generic key/value storage optionally accesible by eBPF programs */ struct bpf_map_ops { /* funcs callable from userspace (via syscall) */ @@ -24,6 +26,7 @@ struct bpf_map_ops { void *(*map_lookup_elem)(struct bpf_map *map, void *key); 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_traverse_elem)(bpf_map_traverse_callback func, struct bpf_map *map); }; struct bpf_map { diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index cb31229..3306916 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -114,6 +114,22 @@ static int array_map_delete_elem(struct bpf_map *map, void *key) return -EINVAL; } +static int array_map_traverse_elem(bpf_map_traverse_callback func, struct bpf_map *map) +{ + struct bpf_array *array = container_of(map, struct bpf_array, map); + void *value; + int i; + + for(i = 0; i < array->map.max_entries; i++) { + value = array->value + array->elem_size * i; + + if (func(value) < 0) + return -EINVAL; + } + + return 0; +} + /* Called when map->refcnt goes to zero, either from workqueue or from syscall */ static void array_map_free(struct bpf_map *map) { @@ -136,6 +152,7 @@ static const struct bpf_map_ops array_ops = { .map_lookup_elem = array_map_lookup_elem, .map_update_elem = array_map_update_elem, .map_delete_elem = array_map_delete_elem, + .map_traverse_elem = array_map_traverse_elem, }; static struct bpf_map_type_list array_type __read_mostly = { diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 83c209d..fa7887e 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -325,6 +325,32 @@ static void delete_all_elements(struct bpf_htab *htab) } } +static int htab_map_traverse_elem(bpf_map_traverse_callback func, struct bpf_map *map) +{ + struct bpf_htab *htab = container_of(map, struct bpf_htab, map); + struct hlist_head *head; + struct htab_elem *l; + u32 key_size; + void *value; + int i; + + key_size = map->key_size; + + for (i = 0; i < htab->n_buckets; i++) { + head = select_bucket(htab, i); + + hlist_for_each_entry_rcu(l, head, hash_node) { + value = l->key + round_up(key_size, 8); + + if (func(value) < 0) + return -EINVAL; + } + + } + + return 0; +} + /* Called when map->refcnt goes to zero, either from workqueue or from syscall */ static void htab_map_free(struct bpf_map *map) { @@ -352,6 +378,7 @@ static const struct bpf_map_ops htab_ops = { .map_lookup_elem = htab_map_lookup_elem, .map_update_elem = htab_map_update_elem, .map_delete_elem = htab_map_delete_elem, + .map_traverse_elem = htab_map_traverse_elem, }; static struct bpf_map_type_list htab_type __read_mostly = { -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/