Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: GPL-2.0-only
0002 .. Copyright (C) 2022 Red Hat, Inc.
0003 
0004 ===============================================
0005 BPF_MAP_TYPE_HASH, with PERCPU and LRU Variants
0006 ===============================================
0007 
0008 .. note::
0009    - ``BPF_MAP_TYPE_HASH`` was introduced in kernel version 3.19
0010    - ``BPF_MAP_TYPE_PERCPU_HASH`` was introduced in version 4.6
0011    - Both ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
0012      were introduced in version 4.10
0013 
0014 ``BPF_MAP_TYPE_HASH`` and ``BPF_MAP_TYPE_PERCPU_HASH`` provide general
0015 purpose hash map storage. Both the key and the value can be structs,
0016 allowing for composite keys and values.
0017 
0018 The kernel is responsible for allocating and freeing key/value pairs, up
0019 to the max_entries limit that you specify. Hash maps use pre-allocation
0020 of hash table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be
0021 used to disable pre-allocation when it is too memory expensive.
0022 
0023 ``BPF_MAP_TYPE_PERCPU_HASH`` provides a separate value slot per
0024 CPU. The per-cpu values are stored internally in an array.
0025 
0026 The ``BPF_MAP_TYPE_LRU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
0027 variants add LRU semantics to their respective hash tables. An LRU hash
0028 will automatically evict the least recently used entries when the hash
0029 table reaches capacity. An LRU hash maintains an internal LRU list that
0030 is used to select elements for eviction. This internal LRU list is
0031 shared across CPUs but it is possible to request a per CPU LRU list with
0032 the ``BPF_F_NO_COMMON_LRU`` flag when calling ``bpf_map_create``.
0033 
0034 Usage
0035 =====
0036 
0037 .. c:function::
0038    long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
0039 
0040 Hash entries can be added or updated using the ``bpf_map_update_elem()``
0041 helper. This helper replaces existing elements atomically. The ``flags``
0042 parameter can be used to control the update behaviour:
0043 
0044 - ``BPF_ANY`` will create a new element or update an existing element
0045 - ``BPF_NOEXIST`` will create a new element only if one did not already
0046   exist
0047 - ``BPF_EXIST`` will update an existing element
0048 
0049 ``bpf_map_update_elem()`` returns 0 on success, or negative error in
0050 case of failure.
0051 
0052 .. c:function::
0053    void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
0054 
0055 Hash entries can be retrieved using the ``bpf_map_lookup_elem()``
0056 helper. This helper returns a pointer to the value associated with
0057 ``key``, or ``NULL`` if no entry was found.
0058 
0059 .. c:function::
0060    long bpf_map_delete_elem(struct bpf_map *map, const void *key)
0061 
0062 Hash entries can be deleted using the ``bpf_map_delete_elem()``
0063 helper. This helper will return 0 on success, or negative error in case
0064 of failure.
0065 
0066 Per CPU Hashes
0067 --------------
0068 
0069 For ``BPF_MAP_TYPE_PERCPU_HASH`` and ``BPF_MAP_TYPE_LRU_PERCPU_HASH``
0070 the ``bpf_map_update_elem()`` and ``bpf_map_lookup_elem()`` helpers
0071 automatically access the hash slot for the current CPU.
0072 
0073 .. c:function::
0074    void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu)
0075 
0076 The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the
0077 value in the hash slot for a specific CPU. Returns value associated with
0078 ``key`` on ``cpu`` , or ``NULL`` if no entry was found or ``cpu`` is
0079 invalid.
0080 
0081 Concurrency
0082 -----------
0083 
0084 Values stored in ``BPF_MAP_TYPE_HASH`` can be accessed concurrently by
0085 programs running on different CPUs.  Since Kernel version 5.1, the BPF
0086 infrastructure provides ``struct bpf_spin_lock`` to synchronise access.
0087 See ``tools/testing/selftests/bpf/progs/test_spin_lock.c``.
0088 
0089 Userspace
0090 ---------
0091 
0092 .. c:function::
0093    int bpf_map_get_next_key(int fd, const void *cur_key, void *next_key)
0094 
0095 In userspace, it is possible to iterate through the keys of a hash using
0096 libbpf's ``bpf_map_get_next_key()`` function. The first key can be fetched by
0097 calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
0098 ``NULL``. Subsequent calls will fetch the next key that follows the
0099 current key. ``bpf_map_get_next_key()`` returns 0 on success, -ENOENT if
0100 cur_key is the last key in the hash, or negative error in case of
0101 failure.
0102 
0103 Note that if ``cur_key`` gets deleted then ``bpf_map_get_next_key()``
0104 will instead return the *first* key in the hash table which is
0105 undesirable. It is recommended to use batched lookup if there is going
0106 to be key deletion intermixed with ``bpf_map_get_next_key()``.
0107 
0108 Examples
0109 ========
0110 
0111 Please see the ``tools/testing/selftests/bpf`` directory for functional
0112 examples.  The code snippets below demonstrates API usage.
0113 
0114 This example shows how to declare an LRU Hash with a struct key and a
0115 struct value.
0116 
0117 .. code-block:: c
0118 
0119     #include <linux/bpf.h>
0120     #include <bpf/bpf_helpers.h>
0121 
0122     struct key {
0123         __u32 srcip;
0124     };
0125 
0126     struct value {
0127         __u64 packets;
0128         __u64 bytes;
0129     };
0130 
0131     struct {
0132             __uint(type, BPF_MAP_TYPE_LRU_HASH);
0133             __uint(max_entries, 32);
0134             __type(key, struct key);
0135             __type(value, struct value);
0136     } packet_stats SEC(".maps");
0137 
0138 This example shows how to create or update hash values using atomic
0139 instructions:
0140 
0141 .. code-block:: c
0142 
0143     static void update_stats(__u32 srcip, int bytes)
0144     {
0145             struct key key = {
0146                     .srcip = srcip,
0147             };
0148             struct value *value = bpf_map_lookup_elem(&packet_stats, &key);
0149 
0150             if (value) {
0151                     __sync_fetch_and_add(&value->packets, 1);
0152                     __sync_fetch_and_add(&value->bytes, bytes);
0153             } else {
0154                     struct value newval = { 1, bytes };
0155 
0156                     bpf_map_update_elem(&packet_stats, &key, &newval, BPF_NOEXIST);
0157             }
0158     }
0159 
0160 Userspace walking the map elements from the map declared above:
0161 
0162 .. code-block:: c
0163 
0164     #include <bpf/libbpf.h>
0165     #include <bpf/bpf.h>
0166 
0167     static void walk_hash_elements(int map_fd)
0168     {
0169             struct key *cur_key = NULL;
0170             struct key next_key;
0171             struct value value;
0172             int err;
0173 
0174             for (;;) {
0175                     err = bpf_map_get_next_key(map_fd, cur_key, &next_key);
0176                     if (err)
0177                             break;
0178 
0179                     bpf_map_lookup_elem(map_fd, &next_key, &value);
0180 
0181                     // Use key and value here
0182 
0183                     cur_key = &next_key;
0184             }
0185     }