All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
@ 2022-07-18 12:58 Donald Hunter
  2022-07-18 17:28 ` sdf
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Donald Hunter @ 2022-07-18 12:58 UTC (permalink / raw)
  To: bpf, linux-doc; +Cc: Jonathan Corbet, sdf, yhs, Donald Hunter

Add documentation for BPF_MAP_TYPE_HASH including kernel version
introduced, usage and examples. Document BPF_MAP_TYPE_PERCPU_HASH,
BPF_MAP_TYPE_LRU_HASH and BPF_MAP_TYPE_LRU_PERCPU_HASH variations.

Note that this file is included in the BPF documentation by the glob in
Documentation/bpf/maps.rst

v3:
Fix typos reported by Stanislav Fomichev and Yonghong Song.
Add note about iteration and deletion as requested by Yonghong Song.

v2:
Describe memory allocation semantics as suggested by Stanislav Fomichev.
Fix u64 typo reported by Stanislav Fomichev.
Cut down usage examples to only show usage in context.
Updated patch description to follow style recommendation, reported by
Bagas Sanjaya.

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
---
 Documentation/bpf/map_hash.rst | 186 +++++++++++++++++++++++++++++++++
 1 file changed, 186 insertions(+)
 create mode 100644 Documentation/bpf/map_hash.rst

diff --git a/Documentation/bpf/map_hash.rst b/Documentation/bpf/map_hash.rst
new file mode 100644
index 000000000000..b1d6562f36ae
--- /dev/null
+++ b/Documentation/bpf/map_hash.rst
@@ -0,0 +1,186 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+.. Copyright (C) 2022 Red Hat, Inc.
+
+===============================================
+BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants
+===============================================
+
+.. note::
+   - ``BPF_MAP_TYPE_HASH`` was introduced in kernel version 3.19
+   - ``BPF_MAP_TYPE_PERCPU_HASH`` was introduced in version 4.6
+   - Both ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
+     were introduced in version 4.10
+
+``BPF_MAP_TYPE_HASH`` and ``BPF_MAP_TYPE_PERCPU_HASH`` provide general
+purpose hash map storage. Both the key and the value can be structs,
+allowing for composite keys and values.
+
+The kernel is responsible for allocating and freeing key/value pairs, up
+to the max_entries limit that you specify. Hash maps use pre-allocation
+of hash table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be
+used to disable pre-allocation when it is too memory expensive.
+
+``BPF_MAP_TYPE_PERCPU_HASH`` provides a separate value slot per
+CPU. The per-cpu values are stored internally in an array.
+
+The ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
+variants add LRU semantics to their respective hash tables. An LRU hash
+will automatically evict the least recently used entries when the hash
+table reaches capacity. An LRU hash maintains an internal LRU list that
+is used to select elements for eviction. This internal LRU list is
+shared across CPUs but it is possible to request a per CPU LRU list with
+the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``.
+
+Usage
+=====
+
+.. c:function::
+   long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
+
+Hash entries can be added or updated using the ``bpf_map_update_elem()``
+helper. This helper replaces existing elements atomically. The ``flags``
+parameter can be used to control the update behaviour:
+
+- ``BPF_ANY`` will create a new element or update an existing element
+- ``BPF_NOTEXIST`` will create a new element only if one did not already
+  exist
+- ``BPF_EXIST`` will update an existing element
+
+``bpf_map_update_elem()`` returns 0 on success, or negative error in
+case of failure.
+
+.. c:function::
+   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
+
+Hash entries can be retrieved using the ``bpf_map_lookup_elem()``
+helper. This helper returns a pointer to the value associated with
+``key``, or ``NULL`` if no entry was found.
+
+.. c:function::
+   long bpf_map_delete_elem(struct bpf_map *map, const void *key)
+
+Hash entries can be deleted using the ``bpf_map_delete_elem()``
+helper. This helper will return 0 on success, or negative error in case
+of failure.
+
+Per CPU Hashes
+--------------
+
+For ``BPF_MAP_TYPE_PERCPU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
+the ``bpf_map_update_elem()`` and ``bpf_map_lookup_elem()`` helpers
+automatically access the hash slot for the current CPU.
+
+.. c:function::
+   void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu)
+
+The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the
+value in the hash slot for a specific CPU. Returns value associated with
+``key`` on ``cpu`` , or ``NULL`` if no entry was found or ``cpu`` is
+invalid.
+
+Concurrency
+-----------
+
+Values stored in ``BPF_MAP_TYPE_HASH`` can be accessed concurrently by
+programs running on different CPUs.  Since Kernel version 5.1, the BPF
+infrastructure provides ``struct bpf_spin_lock`` to synchronise access.
+See ``tools/testing/selftests/bpf/progs/test_spin_lock.c``.
+
+Userspace
+---------
+
+.. c:function::
+   int bpf_map_get_next_key (int fd, const void *cur_key, void *next_key)
+
+In userspace, it is possible to iterate through the keys of a hash using
+the ``bpf_map_get_next_key()`` function. The first key can be fetched by
+calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
+``NULL``. Subsequent calls will fetch the next key that follows the
+current key. ``bpf_map_get_next_key()`` returns 0 on success, -ENOENT if
+cur_key is the last key in the hash, or negative error in case of
+failure.
+
+Note that if ``cur_key`` gets deleted then ``bpf_map_get_next_key()``
+will instead return the *first* key in the hash table which is
+undesirable. It is recommended to use batched lookup if there is going
+to be key deletion intermixed with ``bpf_map_get_next_key()``.
+
+Examples
+========
+
+Please see the ``tools/testing/selftests/bpf`` directory for functional
+examples.  The code snippets below demonstrates API usage.
+
+This example shows how to declare an LRU Hash with a struct key and a
+struct value.
+
+.. code-block:: c
+
+    #include <linux/bpf.h>
+    #include <bpf/bpf_helpers.h>
+
+    struct key {
+        __u32 srcip;
+    };
+
+    struct value {
+        __u64 packets;
+        __u64 bytes;
+    };
+
+    struct {
+            __uint(type, BPF_MAP_TYPE_LRU_HASH);
+            __uint(max_entries, 32);
+            __type(key, struct key);
+            __type(value, struct value);
+    } packet_stats SEC(".maps");
+
+This example shows how to create or update hash values using atomic
+instructions:
+
+.. code-block:: c
+
+    static inline void (__u32 srcip, int bytes)
+    {
+            struct key key = {
+                    .srcip = srcip
+            };
+            struct value *value = bpf_map_lookup_elem(&packet_stats, &key);
+            if (value) {
+                    __sync_fetch_and_add(&value->packets, 1);
+                    __sync_fetch_and_add(&value->bytes, bytes);
+            } else {
+                    struct value newval = { 1, bytes };
+                    bpf_map_update_elem(&packet_stats, &key, &newval, BPF_NOEXIST);
+            }
+    }
+
+Userspace walking the map elements from the map declared above:
+
+.. code-block:: c
+
+    #include <bpf/libbpf.h>
+    #include <bpf/bpf.h>
+
+    static void walk_hash_elements(int map_fd)
+    {
+            struct key *cur_key = NULL;
+            struct key next_key;
+            int next;
+            do {
+                    // error checking omitted
+                    next = bpf_map_get_next_key(stats_fd, cur_key, &next_key);
+                    if (next == -ENOENT)
+                            break;
+
+                    struct in_addr src_addr = {
+                            .s_addr = next_key.srcip
+                    };
+                    struct value value;
+                    int ret = bpf_map_lookup_elem(stats_fd, &next_key, &value);
+
+                    // Use key and value here
+
+                    cur_key = &next_key;
+            } while (next == 0);
+    }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
  2022-07-18 12:58 [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants Donald Hunter
@ 2022-07-18 17:28 ` sdf
  2022-07-19 16:03 ` Yonghong Song
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: sdf @ 2022-07-18 17:28 UTC (permalink / raw)
  To: Donald Hunter; +Cc: bpf, linux-doc, Jonathan Corbet, yhs

On 07/18, Donald Hunter wrote:
> Add documentation for BPF_MAP_TYPE_HASH including kernel version
> introduced, usage and examples. Document BPF_MAP_TYPE_PERCPU_HASH,
> BPF_MAP_TYPE_LRU_HASH and BPF_MAP_TYPE_LRU_PERCPU_HASH variations.

> Note that this file is included in the BPF documentation by the glob in
> Documentation/bpf/maps.rst

> v3:
> Fix typos reported by Stanislav Fomichev and Yonghong Song.
> Add note about iteration and deletion as requested by Yonghong Song.

> v2:
> Describe memory allocation semantics as suggested by Stanislav Fomichev.
> Fix u64 typo reported by Stanislav Fomichev.
> Cut down usage examples to only show usage in context.
> Updated patch description to follow style recommendation, reported by
> Bagas Sanjaya.

> Signed-off-by: Donald Hunter <donald.hunter@gmail.com>

Reviewed-by: Stanislav Fomichev <sdf@google.com>

In the future, can you try to add bpf/bpf-next subtree into the subj?
This email should have been [PATCH bpf-next v3].

> ---
>   Documentation/bpf/map_hash.rst | 186 +++++++++++++++++++++++++++++++++
>   1 file changed, 186 insertions(+)
>   create mode 100644 Documentation/bpf/map_hash.rst

> diff --git a/Documentation/bpf/map_hash.rst  
> b/Documentation/bpf/map_hash.rst
> new file mode 100644
> index 000000000000..b1d6562f36ae
> --- /dev/null
> +++ b/Documentation/bpf/map_hash.rst
> @@ -0,0 +1,186 @@
> +.. SPDX-License-Identifier: GPL-2.0-only
> +.. Copyright (C) 2022 Red Hat, Inc.
> +
> +===============================================
> +BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants
> +===============================================
> +
> +.. note::
> +   - ``BPF_MAP_TYPE_HASH`` was introduced in kernel version 3.19
> +   - ``BPF_MAP_TYPE_PERCPU_HASH`` was introduced in version 4.6
> +   - Both ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +     were introduced in version 4.10
> +
> +``BPF_MAP_TYPE_HASH`` and ``BPF_MAP_TYPE_PERCPU_HASH`` provide general
> +purpose hash map storage. Both the key and the value can be structs,
> +allowing for composite keys and values.
> +
> +The kernel is responsible for allocating and freeing key/value pairs, up
> +to the max_entries limit that you specify. Hash maps use pre-allocation
> +of hash table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be
> +used to disable pre-allocation when it is too memory expensive.
> +
> +``BPF_MAP_TYPE_PERCPU_HASH`` provides a separate value slot per
> +CPU. The per-cpu values are stored internally in an array.
> +
> +The ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +variants add LRU semantics to their respective hash tables. An LRU hash
> +will automatically evict the least recently used entries when the hash
> +table reaches capacity. An LRU hash maintains an internal LRU list that
> +is used to select elements for eviction. This internal LRU list is
> +shared across CPUs but it is possible to request a per CPU LRU list with
> +the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``.
> +
> +Usage
> +=====
> +
> +.. c:function::
> +   long bpf_map_update_elem(struct bpf_map *map, const void *key, const  
> void *value, u64 flags)
> +
> +Hash entries can be added or updated using the ``bpf_map_update_elem()``
> +helper. This helper replaces existing elements atomically. The ``flags``
> +parameter can be used to control the update behaviour:
> +
> +- ``BPF_ANY`` will create a new element or update an existing element
> +- ``BPF_NOTEXIST`` will create a new element only if one did not already
> +  exist
> +- ``BPF_EXIST`` will update an existing element
> +
> +``bpf_map_update_elem()`` returns 0 on success, or negative error in
> +case of failure.
> +
> +.. c:function::
> +   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
> +
> +Hash entries can be retrieved using the ``bpf_map_lookup_elem()``
> +helper. This helper returns a pointer to the value associated with
> +``key``, or ``NULL`` if no entry was found.
> +
> +.. c:function::
> +   long bpf_map_delete_elem(struct bpf_map *map, const void *key)
> +
> +Hash entries can be deleted using the ``bpf_map_delete_elem()``
> +helper. This helper will return 0 on success, or negative error in case
> +of failure.
> +
> +Per CPU Hashes
> +--------------
> +
> +For ``BPF_MAP_TYPE_PERCPU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +the ``bpf_map_update_elem()`` and ``bpf_map_lookup_elem()`` helpers
> +automatically access the hash slot for the current CPU.
> +
> +.. c:function::
> +   void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void  
> *key, u32 cpu)
> +
> +The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the
> +value in the hash slot for a specific CPU. Returns value associated with
> +``key`` on ``cpu`` , or ``NULL`` if no entry was found or ``cpu`` is
> +invalid.
> +
> +Concurrency
> +-----------
> +
> +Values stored in ``BPF_MAP_TYPE_HASH`` can be accessed concurrently by
> +programs running on different CPUs.  Since Kernel version 5.1, the BPF
> +infrastructure provides ``struct bpf_spin_lock`` to synchronise access.
> +See ``tools/testing/selftests/bpf/progs/test_spin_lock.c``.
> +
> +Userspace
> +---------
> +
> +.. c:function::
> +   int bpf_map_get_next_key (int fd, const void *cur_key, void *next_key)
> +
> +In userspace, it is possible to iterate through the keys of a hash using
> +the ``bpf_map_get_next_key()`` function. The first key can be fetched by
> +calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
> +``NULL``. Subsequent calls will fetch the next key that follows the
> +current key. ``bpf_map_get_next_key()`` returns 0 on success, -ENOENT if
> +cur_key is the last key in the hash, or negative error in case of
> +failure.
> +
> +Note that if ``cur_key`` gets deleted then ``bpf_map_get_next_key()``
> +will instead return the *first* key in the hash table which is
> +undesirable. It is recommended to use batched lookup if there is going
> +to be key deletion intermixed with ``bpf_map_get_next_key()``.
> +
> +Examples
> +========
> +
> +Please see the ``tools/testing/selftests/bpf`` directory for functional
> +examples.  The code snippets below demonstrates API usage.
> +
> +This example shows how to declare an LRU Hash with a struct key and a
> +struct value.
> +
> +.. code-block:: c
> +
> +    #include <linux/bpf.h>
> +    #include <bpf/bpf_helpers.h>
> +
> +    struct key {
> +        __u32 srcip;
> +    };
> +
> +    struct value {
> +        __u64 packets;
> +        __u64 bytes;
> +    };
> +
> +    struct {
> +            __uint(type, BPF_MAP_TYPE_LRU_HASH);
> +            __uint(max_entries, 32);
> +            __type(key, struct key);
> +            __type(value, struct value);
> +    } packet_stats SEC(".maps");
> +
> +This example shows how to create or update hash values using atomic
> +instructions:
> +
> +.. code-block:: c
> +
> +    static inline void (__u32 srcip, int bytes)
> +    {
> +            struct key key = {
> +                    .srcip = srcip
> +            };
> +            struct value *value = bpf_map_lookup_elem(&packet_stats,  
> &key);
> +            if (value) {
> +                    __sync_fetch_and_add(&value->packets, 1);
> +                    __sync_fetch_and_add(&value->bytes, bytes);
> +            } else {
> +                    struct value newval = { 1, bytes };
> +                    bpf_map_update_elem(&packet_stats, &key, &newval,  
> BPF_NOEXIST);
> +            }
> +    }
> +
> +Userspace walking the map elements from the map declared above:
> +
> +.. code-block:: c
> +
> +    #include <bpf/libbpf.h>
> +    #include <bpf/bpf.h>
> +
> +    static void walk_hash_elements(int map_fd)
> +    {
> +            struct key *cur_key = NULL;
> +            struct key next_key;
> +            int next;
> +            do {
> +                    // error checking omitted
> +                    next = bpf_map_get_next_key(stats_fd, cur_key,  
> &next_key);
> +                    if (next == -ENOENT)
> +                            break;
> +
> +                    struct in_addr src_addr = {
> +                            .s_addr = next_key.srcip
> +                    };
> +                    struct value value;
> +                    int ret = bpf_map_lookup_elem(stats_fd, &next_key,  
> &value);
> +
> +                    // Use key and value here
> +
> +                    cur_key = &next_key;
> +            } while (next == 0);
> +    }
> --
> 2.35.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
  2022-07-18 12:58 [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants Donald Hunter
  2022-07-18 17:28 ` sdf
@ 2022-07-19 16:03 ` Yonghong Song
  2022-07-19 17:40 ` Alexei Starovoitov
  2022-07-19 17:50 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Yonghong Song @ 2022-07-19 16:03 UTC (permalink / raw)
  To: Donald Hunter, bpf, linux-doc; +Cc: Jonathan Corbet, sdf



On 7/18/22 5:58 AM, Donald Hunter wrote:
> Add documentation for BPF_MAP_TYPE_HASH including kernel version
> introduced, usage and examples. Document BPF_MAP_TYPE_PERCPU_HASH,
> BPF_MAP_TYPE_LRU_HASH and BPF_MAP_TYPE_LRU_PERCPU_HASH variations.
> 
> Note that this file is included in the BPF documentation by the glob in
> Documentation/bpf/maps.rst
> 
> v3:
> Fix typos reported by Stanislav Fomichev and Yonghong Song.
> Add note about iteration and deletion as requested by Yonghong Song.
> 
> v2:
> Describe memory allocation semantics as suggested by Stanislav Fomichev.
> Fix u64 typo reported by Stanislav Fomichev.
> Cut down usage examples to only show usage in context.
> Updated patch description to follow style recommendation, reported by
> Bagas Sanjaya.
> 
> Signed-off-by: Donald Hunter <donald.hunter@gmail.com>

Acked-by: Yonghong Song <yhs@fb.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
  2022-07-18 12:58 [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants Donald Hunter
  2022-07-18 17:28 ` sdf
  2022-07-19 16:03 ` Yonghong Song
@ 2022-07-19 17:40 ` Alexei Starovoitov
  2022-07-19 17:50 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: Alexei Starovoitov @ 2022-07-19 17:40 UTC (permalink / raw)
  To: Donald Hunter
  Cc: bpf, open list:DOCUMENTATION, Jonathan Corbet,
	Stanislav Fomichev, Yonghong Song

On Mon, Jul 18, 2022 at 6:02 AM Donald Hunter <donald.hunter@gmail.com> wrote:
>
> Add documentation for BPF_MAP_TYPE_HASH including kernel version
> introduced, usage and examples. Document BPF_MAP_TYPE_PERCPU_HASH,
> BPF_MAP_TYPE_LRU_HASH and BPF_MAP_TYPE_LRU_PERCPU_HASH variations.
>
> Note that this file is included in the BPF documentation by the glob in
> Documentation/bpf/maps.rst
>
> v3:
> Fix typos reported by Stanislav Fomichev and Yonghong Song.
> Add note about iteration and deletion as requested by Yonghong Song.
>
> v2:
> Describe memory allocation semantics as suggested by Stanislav Fomichev.
> Fix u64 typo reported by Stanislav Fomichev.
> Cut down usage examples to only show usage in context.
> Updated patch description to follow style recommendation, reported by
> Bagas Sanjaya.
>
> Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
> ---
>  Documentation/bpf/map_hash.rst | 186 +++++++++++++++++++++++++++++++++
>  1 file changed, 186 insertions(+)
>  create mode 100644 Documentation/bpf/map_hash.rst
>
> diff --git a/Documentation/bpf/map_hash.rst b/Documentation/bpf/map_hash.rst
> new file mode 100644
> index 000000000000..b1d6562f36ae
> --- /dev/null
> +++ b/Documentation/bpf/map_hash.rst
> @@ -0,0 +1,186 @@
> +.. SPDX-License-Identifier: GPL-2.0-only
> +.. Copyright (C) 2022 Red Hat, Inc.
> +
> +===============================================
> +BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants
> +===============================================
> +
> +.. note::
> +   - ``BPF_MAP_TYPE_HASH`` was introduced in kernel version 3.19
> +   - ``BPF_MAP_TYPE_PERCPU_HASH`` was introduced in version 4.6
> +   - Both ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +     were introduced in version 4.10
> +
> +``BPF_MAP_TYPE_HASH`` and ``BPF_MAP_TYPE_PERCPU_HASH`` provide general
> +purpose hash map storage. Both the key and the value can be structs,
> +allowing for composite keys and values.
> +
> +The kernel is responsible for allocating and freeing key/value pairs, up
> +to the max_entries limit that you specify. Hash maps use pre-allocation
> +of hash table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be
> +used to disable pre-allocation when it is too memory expensive.
> +
> +``BPF_MAP_TYPE_PERCPU_HASH`` provides a separate value slot per
> +CPU. The per-cpu values are stored internally in an array.
> +
> +The ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +variants add LRU semantics to their respective hash tables. An LRU hash
> +will automatically evict the least recently used entries when the hash
> +table reaches capacity. An LRU hash maintains an internal LRU list that
> +is used to select elements for eviction. This internal LRU list is
> +shared across CPUs but it is possible to request a per CPU LRU list with
> +the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``.
> +
> +Usage
> +=====
> +
> +.. c:function::
> +   long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
> +
> +Hash entries can be added or updated using the ``bpf_map_update_elem()``
> +helper. This helper replaces existing elements atomically. The ``flags``
> +parameter can be used to control the update behaviour:
> +
> +- ``BPF_ANY`` will create a new element or update an existing element
> +- ``BPF_NOTEXIST`` will create a new element only if one did not already

typo.

> +  exist
> +- ``BPF_EXIST`` will update an existing element
> +
> +``bpf_map_update_elem()`` returns 0 on success, or negative error in
> +case of failure.
> +
> +.. c:function::
> +   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
> +
> +Hash entries can be retrieved using the ``bpf_map_lookup_elem()``
> +helper. This helper returns a pointer to the value associated with
> +``key``, or ``NULL`` if no entry was found.
> +
> +.. c:function::
> +   long bpf_map_delete_elem(struct bpf_map *map, const void *key)
> +
> +Hash entries can be deleted using the ``bpf_map_delete_elem()``
> +helper. This helper will return 0 on success, or negative error in case
> +of failure.
> +
> +Per CPU Hashes
> +--------------
> +
> +For ``BPF_MAP_TYPE_PERCPU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
> +the ``bpf_map_update_elem()`` and ``bpf_map_lookup_elem()`` helpers
> +automatically access the hash slot for the current CPU.
> +
> +.. c:function::
> +   void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu)
> +
> +The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the
> +value in the hash slot for a specific CPU. Returns value associated with
> +``key`` on ``cpu`` , or ``NULL`` if no entry was found or ``cpu`` is
> +invalid.
> +
> +Concurrency
> +-----------
> +
> +Values stored in ``BPF_MAP_TYPE_HASH`` can be accessed concurrently by
> +programs running on different CPUs.  Since Kernel version 5.1, the BPF
> +infrastructure provides ``struct bpf_spin_lock`` to synchronise access.
> +See ``tools/testing/selftests/bpf/progs/test_spin_lock.c``.
> +
> +Userspace
> +---------
> +
> +.. c:function::
> +   int bpf_map_get_next_key (int fd, const void *cur_key, void *next_key)

unnecessary space.

> +
> +In userspace, it is possible to iterate through the keys of a hash using
> +the ``bpf_map_get_next_key()`` function. The first key can be fetched by

clarified that this is libbpf's function.

> +calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
> +``NULL``. Subsequent calls will fetch the next key that follows the
> +current key. ``bpf_map_get_next_key()`` returns 0 on success, -ENOENT if
> +cur_key is the last key in the hash, or negative error in case of
> +failure.
> +
> +Note that if ``cur_key`` gets deleted then ``bpf_map_get_next_key()``
> +will instead return the *first* key in the hash table which is
> +undesirable. It is recommended to use batched lookup if there is going
> +to be key deletion intermixed with ``bpf_map_get_next_key()``.
> +
> +Examples
> +========
> +
> +Please see the ``tools/testing/selftests/bpf`` directory for functional
> +examples.  The code snippets below demonstrates API usage.
> +
> +This example shows how to declare an LRU Hash with a struct key and a
> +struct value.
> +
> +.. code-block:: c
> +
> +    #include <linux/bpf.h>
> +    #include <bpf/bpf_helpers.h>
> +
> +    struct key {
> +        __u32 srcip;
> +    };
> +
> +    struct value {
> +        __u64 packets;
> +        __u64 bytes;
> +    };
> +
> +    struct {
> +            __uint(type, BPF_MAP_TYPE_LRU_HASH);
> +            __uint(max_entries, 32);
> +            __type(key, struct key);
> +            __type(value, struct value);
> +    } packet_stats SEC(".maps");
> +
> +This example shows how to create or update hash values using atomic
> +instructions:
> +
> +.. code-block:: c
> +
> +    static inline void (__u32 srcip, int bytes)

bug. no name function?

called it 'update_stats' and dropped 'inline',
since it's unnecessary.

> +    {
> +            struct key key = {
> +                    .srcip = srcip

added comma

> +            };
> +            struct value *value = bpf_map_lookup_elem(&packet_stats, &key);

added empty line.

> +            if (value) {
> +                    __sync_fetch_and_add(&value->packets, 1);
> +                    __sync_fetch_and_add(&value->bytes, bytes);
> +            } else {
> +                    struct value newval = { 1, bytes };

added empty line.

> +                    bpf_map_update_elem(&packet_stats, &key, &newval, BPF_NOEXIST);
> +            }
> +    }
> +
> +Userspace walking the map elements from the map declared above:
> +
> +.. code-block:: c
> +
> +    #include <bpf/libbpf.h>
> +    #include <bpf/bpf.h>
> +
> +    static void walk_hash_elements(int map_fd)
> +    {
> +            struct key *cur_key = NULL;
> +            struct key next_key;
> +            int next;

added empty line

> +            do {
> +                    // error checking omitted
> +                    next = bpf_map_get_next_key(stats_fd, cur_key, &next_key);

s/stats_fd/map_fd/

> +                    if (next == -ENOENT)
> +                            break;

converted to if (err) break;
since it's a bad idea to use next_key on any error.
Not just ENOENT.

> +
> +                    struct in_addr src_addr = {
> +                            .s_addr = next_key.srcip
> +                    };

removed. It adds no value. Only confused the reader.

> +                    struct value value;

moved the top

> +                    int ret = bpf_map_lookup_elem(stats_fd, &next_key, &value);

remove 'int ret', since compilers will complain.

> +
> +                    // Use key and value here
> +
> +                    cur_key = &next_key;
> +            } while (next == 0);

converted to 'for (;;)' since 'err == 0' is already checked.

Please pay attention to such details in the future.
The doc shouldn't be sloppy.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
  2022-07-18 12:58 [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants Donald Hunter
                   ` (2 preceding siblings ...)
  2022-07-19 17:40 ` Alexei Starovoitov
@ 2022-07-19 17:50 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-07-19 17:50 UTC (permalink / raw)
  To: Donald Hunter; +Cc: bpf, linux-doc, corbet, sdf, yhs

Hello:

This patch was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Mon, 18 Jul 2022 13:58:47 +0100 you wrote:
> Add documentation for BPF_MAP_TYPE_HASH including kernel version
> introduced, usage and examples. Document BPF_MAP_TYPE_PERCPU_HASH,
> BPF_MAP_TYPE_LRU_HASH and BPF_MAP_TYPE_LRU_PERCPU_HASH variations.
> 
> Note that this file is included in the BPF documentation by the glob in
> Documentation/bpf/maps.rst
> 
> [...]

Here is the summary with links:
  - [v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants
    https://git.kernel.org/bpf/bpf-next/c/979855d30264

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-07-19 17:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-18 12:58 [PATCH v3] bpf, docs: document BPF_MAP_TYPE_HASH and variants Donald Hunter
2022-07-18 17:28 ` sdf
2022-07-19 16:03 ` Yonghong Song
2022-07-19 17:40 ` Alexei Starovoitov
2022-07-19 17:50 ` patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.