1*264c2186SDonald Hunter.. SPDX-License-Identifier: GPL-2.0-only 2*264c2186SDonald Hunter.. Copyright (C) 2022 Red Hat, Inc. 3*264c2186SDonald Hunter 4*264c2186SDonald Hunter========================= 5*264c2186SDonald HunterBPF_MAP_TYPE_BLOOM_FILTER 6*264c2186SDonald Hunter========================= 7*264c2186SDonald Hunter 8*264c2186SDonald Hunter.. note:: 9*264c2186SDonald Hunter - ``BPF_MAP_TYPE_BLOOM_FILTER`` was introduced in kernel version 5.16 10*264c2186SDonald Hunter 11*264c2186SDonald Hunter``BPF_MAP_TYPE_BLOOM_FILTER`` provides a BPF bloom filter map. Bloom 12*264c2186SDonald Hunterfilters are a space-efficient probabilistic data structure used to 13*264c2186SDonald Hunterquickly test whether an element exists in a set. In a bloom filter, 14*264c2186SDonald Hunterfalse positives are possible whereas false negatives are not. 15*264c2186SDonald Hunter 16*264c2186SDonald HunterThe bloom filter map does not have keys, only values. When the bloom 17*264c2186SDonald Hunterfilter map is created, it must be created with a ``key_size`` of 0. The 18*264c2186SDonald Hunterbloom filter map supports two operations: 19*264c2186SDonald Hunter 20*264c2186SDonald Hunter- push: adding an element to the map 21*264c2186SDonald Hunter- peek: determining whether an element is present in the map 22*264c2186SDonald Hunter 23*264c2186SDonald HunterBPF programs must use ``bpf_map_push_elem`` to add an element to the 24*264c2186SDonald Hunterbloom filter map and ``bpf_map_peek_elem`` to query the map. These 25*264c2186SDonald Hunteroperations are exposed to userspace applications using the existing 26*264c2186SDonald Hunter``bpf`` syscall in the following way: 27*264c2186SDonald Hunter 28*264c2186SDonald Hunter- ``BPF_MAP_UPDATE_ELEM`` -> push 29*264c2186SDonald Hunter- ``BPF_MAP_LOOKUP_ELEM`` -> peek 30*264c2186SDonald Hunter 31*264c2186SDonald HunterThe ``max_entries`` size that is specified at map creation time is used 32*264c2186SDonald Hunterto approximate a reasonable bitmap size for the bloom filter, and is not 33*264c2186SDonald Hunterotherwise strictly enforced. If the user wishes to insert more entries 34*264c2186SDonald Hunterinto the bloom filter than ``max_entries``, this may lead to a higher 35*264c2186SDonald Hunterfalse positive rate. 36*264c2186SDonald Hunter 37*264c2186SDonald HunterThe number of hashes to use for the bloom filter is configurable using 38*264c2186SDonald Hunterthe lower 4 bits of ``map_extra`` in ``union bpf_attr`` at map creation 39*264c2186SDonald Huntertime. If no number is specified, the default used will be 5 hash 40*264c2186SDonald Hunterfunctions. In general, using more hashes decreases both the false 41*264c2186SDonald Hunterpositive rate and the speed of a lookup. 42*264c2186SDonald Hunter 43*264c2186SDonald HunterIt is not possible to delete elements from a bloom filter map. A bloom 44*264c2186SDonald Hunterfilter map may be used as an inner map. The user is responsible for 45*264c2186SDonald Huntersynchronising concurrent updates and lookups to ensure no false negative 46*264c2186SDonald Hunterlookups occur. 47*264c2186SDonald Hunter 48*264c2186SDonald HunterUsage 49*264c2186SDonald Hunter===== 50*264c2186SDonald Hunter 51*264c2186SDonald HunterKernel BPF 52*264c2186SDonald Hunter---------- 53*264c2186SDonald Hunter 54*264c2186SDonald Hunterbpf_map_push_elem() 55*264c2186SDonald Hunter~~~~~~~~~~~~~~~~~~~ 56*264c2186SDonald Hunter 57*264c2186SDonald Hunter.. code-block:: c 58*264c2186SDonald Hunter 59*264c2186SDonald Hunter long bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) 60*264c2186SDonald Hunter 61*264c2186SDonald HunterA ``value`` can be added to a bloom filter using the 62*264c2186SDonald Hunter``bpf_map_push_elem()`` helper. The ``flags`` parameter must be set to 63*264c2186SDonald Hunter``BPF_ANY`` when adding an entry to the bloom filter. This helper 64*264c2186SDonald Hunterreturns ``0`` on success, or negative error in case of failure. 65*264c2186SDonald Hunter 66*264c2186SDonald Hunterbpf_map_peek_elem() 67*264c2186SDonald Hunter~~~~~~~~~~~~~~~~~~~ 68*264c2186SDonald Hunter 69*264c2186SDonald Hunter.. code-block:: c 70*264c2186SDonald Hunter 71*264c2186SDonald Hunter long bpf_map_peek_elem(struct bpf_map *map, void *value) 72*264c2186SDonald Hunter 73*264c2186SDonald HunterThe ``bpf_map_peek_elem()`` helper is used to determine whether 74*264c2186SDonald Hunter``value`` is present in the bloom filter map. This helper returns ``0`` 75*264c2186SDonald Hunterif ``value`` is probably present in the map, or ``-ENOENT`` if ``value`` 76*264c2186SDonald Hunteris definitely not present in the map. 77*264c2186SDonald Hunter 78*264c2186SDonald HunterUserspace 79*264c2186SDonald Hunter--------- 80*264c2186SDonald Hunter 81*264c2186SDonald Hunterbpf_map_update_elem() 82*264c2186SDonald Hunter~~~~~~~~~~~~~~~~~~~~~ 83*264c2186SDonald Hunter 84*264c2186SDonald Hunter.. code-block:: c 85*264c2186SDonald Hunter 86*264c2186SDonald Hunter int bpf_map_update_elem (int fd, const void *key, const void *value, __u64 flags) 87*264c2186SDonald Hunter 88*264c2186SDonald HunterA userspace program can add a ``value`` to a bloom filter using libbpf's 89*264c2186SDonald Hunter``bpf_map_update_elem`` function. The ``key`` parameter must be set to 90*264c2186SDonald Hunter``NULL`` and ``flags`` must be set to ``BPF_ANY``. Returns ``0`` on 91*264c2186SDonald Huntersuccess, or negative error in case of failure. 92*264c2186SDonald Hunter 93*264c2186SDonald Hunterbpf_map_lookup_elem() 94*264c2186SDonald Hunter~~~~~~~~~~~~~~~~~~~~~ 95*264c2186SDonald Hunter 96*264c2186SDonald Hunter.. code-block:: c 97*264c2186SDonald Hunter 98*264c2186SDonald Hunter int bpf_map_lookup_elem (int fd, const void *key, void *value) 99*264c2186SDonald Hunter 100*264c2186SDonald HunterA userspace program can determine the presence of ``value`` in a bloom 101*264c2186SDonald Hunterfilter using libbpf's ``bpf_map_lookup_elem`` function. The ``key`` 102*264c2186SDonald Hunterparameter must be set to ``NULL``. Returns ``0`` if ``value`` is 103*264c2186SDonald Hunterprobably present in the map, or ``-ENOENT`` if ``value`` is definitely 104*264c2186SDonald Hunternot present in the map. 105*264c2186SDonald Hunter 106*264c2186SDonald HunterExamples 107*264c2186SDonald Hunter======== 108*264c2186SDonald Hunter 109*264c2186SDonald HunterKernel BPF 110*264c2186SDonald Hunter---------- 111*264c2186SDonald Hunter 112*264c2186SDonald HunterThis snippet shows how to declare a bloom filter in a BPF program: 113*264c2186SDonald Hunter 114*264c2186SDonald Hunter.. code-block:: c 115*264c2186SDonald Hunter 116*264c2186SDonald Hunter struct { 117*264c2186SDonald Hunter __uint(type, BPF_MAP_TYPE_BLOOM_FILTER); 118*264c2186SDonald Hunter __type(value, __u32); 119*264c2186SDonald Hunter __uint(max_entries, 1000); 120*264c2186SDonald Hunter __uint(map_extra, 3); 121*264c2186SDonald Hunter } bloom_filter SEC(".maps"); 122*264c2186SDonald Hunter 123*264c2186SDonald HunterThis snippet shows how to determine presence of a value in a bloom 124*264c2186SDonald Hunterfilter in a BPF program: 125*264c2186SDonald Hunter 126*264c2186SDonald Hunter.. code-block:: c 127*264c2186SDonald Hunter 128*264c2186SDonald Hunter void *lookup(__u32 key) 129*264c2186SDonald Hunter { 130*264c2186SDonald Hunter if (bpf_map_peek_elem(&bloom_filter, &key) == 0) { 131*264c2186SDonald Hunter /* Verify not a false positive and fetch an associated 132*264c2186SDonald Hunter * value using a secondary lookup, e.g. in a hash table 133*264c2186SDonald Hunter */ 134*264c2186SDonald Hunter return bpf_map_lookup_elem(&hash_table, &key); 135*264c2186SDonald Hunter } 136*264c2186SDonald Hunter return 0; 137*264c2186SDonald Hunter } 138*264c2186SDonald Hunter 139*264c2186SDonald HunterUserspace 140*264c2186SDonald Hunter--------- 141*264c2186SDonald Hunter 142*264c2186SDonald HunterThis snippet shows how to use libbpf to create a bloom filter map from 143*264c2186SDonald Hunteruserspace: 144*264c2186SDonald Hunter 145*264c2186SDonald Hunter.. code-block:: c 146*264c2186SDonald Hunter 147*264c2186SDonald Hunter int create_bloom() 148*264c2186SDonald Hunter { 149*264c2186SDonald Hunter LIBBPF_OPTS(bpf_map_create_opts, opts, 150*264c2186SDonald Hunter .map_extra = 3); /* number of hashes */ 151*264c2186SDonald Hunter 152*264c2186SDonald Hunter return bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, 153*264c2186SDonald Hunter "ipv6_bloom", /* name */ 154*264c2186SDonald Hunter 0, /* key size, must be zero */ 155*264c2186SDonald Hunter sizeof(ipv6_addr), /* value size */ 156*264c2186SDonald Hunter 10000, /* max entries */ 157*264c2186SDonald Hunter &opts); /* create options */ 158*264c2186SDonald Hunter } 159*264c2186SDonald Hunter 160*264c2186SDonald HunterThis snippet shows how to add an element to a bloom filter from 161*264c2186SDonald Hunteruserspace: 162*264c2186SDonald Hunter 163*264c2186SDonald Hunter.. code-block:: c 164*264c2186SDonald Hunter 165*264c2186SDonald Hunter int add_element(struct bpf_map *bloom_map, __u32 value) 166*264c2186SDonald Hunter { 167*264c2186SDonald Hunter int bloom_fd = bpf_map__fd(bloom_map); 168*264c2186SDonald Hunter return bpf_map_update_elem(bloom_fd, NULL, &value, BPF_ANY); 169*264c2186SDonald Hunter } 170*264c2186SDonald Hunter 171*264c2186SDonald HunterReferences 172*264c2186SDonald Hunter========== 173*264c2186SDonald Hunter 174*264c2186SDonald Hunterhttps://lwn.net/ml/bpf/20210831225005.2762202-1-joannekoong@fb.com/ 175