LCOV - code coverage report
Current view: top level - libbpfilter/cgen - handle.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 76.2 % 260 198
Test Date: 2026-05-28 10:53:42 Functions: 100.0 % 12 12
Branches: 43.0 % 256 110

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "cgen/handle.h"
       7                 :             : 
       8                 :             : #include <assert.h>
       9                 :             : #include <bpf/libbpf.h>
      10                 :             : #include <errno.h>
      11                 :             : #include <stdlib.h>
      12                 :             : #include <string.h>
      13                 :             : #include <unistd.h>
      14                 :             : 
      15                 :             : #include <bpfilter/bpf.h>
      16                 :             : #include <bpfilter/core/list.h>
      17                 :             : #include <bpfilter/counter.h>
      18                 :             : #include <bpfilter/dump.h>
      19                 :             : #include <bpfilter/helper.h>
      20                 :             : #include <bpfilter/hook.h>
      21                 :             : #include <bpfilter/logger.h>
      22                 :             : #include <bpfilter/pack.h>
      23                 :             : 
      24                 :             : #include "cgen/prog/link.h"
      25                 :             : #include "cgen/prog/map.h"
      26                 :             : #include "core/lock.h"
      27                 :             : 
      28                 :             : #define _BF_LINK_NAME "bf_link"
      29                 :             : 
      30                 :        6639 : int bf_handle_new(struct bf_handle **handle, const char *prog_name)
      31                 :             : {
      32                 :        6639 :     _free_bf_handle_ struct bf_handle *_handle = NULL;
      33                 :             : 
      34                 :             :     assert(handle);
      35                 :             :     assert(prog_name);
      36                 :             : 
      37                 :        6639 :     _handle = calloc(1, sizeof(*_handle));
      38         [ +  - ]:        6639 :     if (!_handle)
      39                 :             :         return -ENOMEM;
      40                 :             : 
      41                 :        6639 :     (void)snprintf(_handle->prog_name, BPF_OBJ_NAME_LEN, "%s", prog_name);
      42                 :        6639 :     _handle->prog_fd = -1;
      43                 :        6639 :     _handle->sets = bf_list_default(bf_map_free, bf_map_pack);
      44                 :             : 
      45                 :        6639 :     *handle = TAKE_PTR(_handle);
      46                 :             : 
      47                 :        6639 :     return 0;
      48                 :             : }
      49                 :             : 
      50                 :        5328 : int bf_handle_new_from_pack(struct bf_handle **handle, struct bf_lock *lock,
      51                 :             :                             bf_rpack_node_t node)
      52                 :             : {
      53                 :        5328 :     _free_bf_handle_ struct bf_handle *_handle = NULL;
      54                 :        5328 :     _cleanup_free_ char *name = NULL;
      55                 :             :     bf_rpack_node_t child, array_node;
      56                 :             :     int dir_fd;
      57                 :             :     int r;
      58                 :             : 
      59                 :             :     assert(handle);
      60                 :             :     assert(lock);
      61                 :             : 
      62                 :        5328 :     dir_fd = lock->chain_fd;
      63                 :             : 
      64                 :        5328 :     r = bf_rpack_kv_str(node, "prog_name", &name);
      65         [ -  + ]:        5328 :     if (r)
      66         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.name");
      67                 :             : 
      68                 :        5328 :     r = bf_handle_new(&_handle, name);
      69         [ +  - ]:        5328 :     if (r)
      70                 :             :         return r;
      71                 :             : 
      72                 :        5328 :     r = bf_bpf_obj_get(_handle->prog_name, dir_fd, &_handle->prog_fd);
      73         [ -  + ]:        5328 :     if (r < 0)
      74         [ #  # ]:           0 :         return bf_err_r(r, "failed to restore bf_handle.prog_fd from pin");
      75                 :             : 
      76                 :        5328 :     r = bf_rpack_kv_node(node, "link", &child);
      77         [ -  + ]:        5328 :     if (r)
      78         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.link");
      79         [ +  + ]:        5328 :     if (!bf_rpack_is_nil(child)) {
      80                 :         159 :         r = bf_link_new_from_pack(&_handle->link, dir_fd, child);
      81         [ -  + ]:         159 :         if (r)
      82         [ #  # ]:           0 :             return bf_rpack_key_err(r, "bf_handle.link");
      83                 :             :     }
      84                 :             : 
      85                 :        5328 :     r = bf_rpack_kv_node(node, "cmap", &child);
      86         [ -  + ]:        5328 :     if (r)
      87         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.cmap");
      88         [ +  - ]:        5328 :     if (!bf_rpack_is_nil(child)) {
      89                 :        5328 :         r = bf_map_new_from_pack(&_handle->cmap, dir_fd, child);
      90         [ -  + ]:        5328 :         if (r)
      91         [ #  # ]:           0 :             return bf_rpack_key_err(r, "bf_handle.cmap");
      92                 :             :     }
      93                 :             : 
      94                 :        5328 :     r = bf_rpack_kv_node(node, "pmap", &child);
      95         [ -  + ]:        5328 :     if (r)
      96         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.pmap");
      97         [ +  - ]:        5328 :     if (!bf_rpack_is_nil(child)) {
      98                 :        5328 :         r = bf_map_new_from_pack(&_handle->pmap, dir_fd, child);
      99         [ -  + ]:        5328 :         if (r)
     100         [ #  # ]:           0 :             return bf_rpack_key_err(r, "bf_handle.pmap");
     101                 :             :     }
     102                 :             : 
     103                 :        5328 :     r = bf_rpack_kv_node(node, "lmap", &child);
     104         [ -  + ]:        5328 :     if (r)
     105         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.lmap");
     106         [ +  + ]:        5328 :     if (!bf_rpack_is_nil(child)) {
     107                 :          20 :         r = bf_map_new_from_pack(&_handle->lmap, dir_fd, child);
     108         [ -  + ]:          20 :         if (r)
     109         [ #  # ]:           0 :             return bf_rpack_key_err(r, "bf_handle.lmap");
     110                 :             :     }
     111                 :             : 
     112                 :        5328 :     r = bf_rpack_kv_node(node, "smap", &child);
     113         [ -  + ]:        5328 :     if (r)
     114         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.smap");
     115         [ -  + ]:        5328 :     if (!bf_rpack_is_nil(child)) {
     116                 :           0 :         r = bf_map_new_from_pack(&_handle->smap, dir_fd, child);
     117         [ #  # ]:           0 :         if (r)
     118         [ #  # ]:           0 :             return bf_rpack_key_err(r, "bf_handle.smap");
     119                 :             :     }
     120                 :             : 
     121                 :        5328 :     r = bf_rpack_kv_array(node, "sets", &child);
     122         [ -  + ]:        5328 :     if (r)
     123         [ #  # ]:           0 :         return bf_rpack_key_err(r, "bf_handle.sets");
     124   [ +  +  -  +  :        7342 :     bf_rpack_array_foreach (child, array_node) {
                   +  + ]
     125                 :           0 :         _free_bf_map_ struct bf_map *map = NULL;
     126                 :             : 
     127         [ -  + ]:        1007 :         if (bf_rpack_is_nil(array_node)) {
     128                 :           0 :             r = bf_list_add_tail(&_handle->sets, NULL);
     129         [ #  # ]:           0 :             if (r)
     130                 :             :                 return r;
     131                 :             :             continue;
     132                 :             :         }
     133                 :             : 
     134   [ +  -  +  -  :        1007 :         r = bf_list_emplace(&_handle->sets, bf_map_new_from_pack, map, dir_fd,
             -  -  -  - ]
     135                 :             :                             array_node);
     136                 :             :         if (r)
     137         [ #  # ]:           0 :             return bf_err_r(r, "failed to unpack bf_map into bf_handle.sets");
     138                 :             :     }
     139                 :             : 
     140                 :        5328 :     *handle = TAKE_PTR(_handle);
     141                 :             : 
     142                 :        5328 :     return 0;
     143                 :             : }
     144                 :             : 
     145                 :       18606 : void bf_handle_free(struct bf_handle **handle)
     146                 :             : {
     147                 :             :     assert(handle);
     148                 :             : 
     149         [ +  + ]:       18606 :     if (!*handle)
     150                 :             :         return;
     151                 :             : 
     152                 :        6639 :     closep(&(*handle)->prog_fd);
     153                 :             : 
     154                 :        6639 :     bf_link_free(&(*handle)->link);
     155                 :        6639 :     bf_map_free(&(*handle)->cmap);
     156                 :        6639 :     bf_map_free(&(*handle)->pmap);
     157                 :        6639 :     bf_map_free(&(*handle)->lmap);
     158                 :        6639 :     bf_map_free(&(*handle)->smap);
     159                 :        6639 :     bf_list_clean(&(*handle)->sets);
     160                 :             : 
     161                 :        6639 :     free(*handle);
     162                 :        6639 :     *handle = NULL;
     163                 :             : }
     164                 :             : 
     165                 :        1330 : int bf_handle_pack(const struct bf_handle *handle, bf_wpack_t *pack)
     166                 :             : {
     167                 :             :     assert(handle);
     168                 :             :     assert(pack);
     169                 :             : 
     170                 :        1330 :     bf_wpack_kv_str(pack, "prog_name", handle->prog_name);
     171                 :             : 
     172         [ +  + ]:        1330 :     if (handle->link) {
     173                 :         144 :         bf_wpack_open_object(pack, "link");
     174                 :         144 :         bf_link_pack(handle->link, pack);
     175                 :         144 :         bf_wpack_close_object(pack);
     176                 :             :     } else {
     177                 :             :         bf_wpack_kv_nil(pack, "link");
     178                 :             :     }
     179                 :             : 
     180         [ +  - ]:        1330 :     if (handle->cmap) {
     181                 :        1330 :         bf_wpack_open_object(pack, "cmap");
     182                 :        1330 :         bf_map_pack(handle->cmap, pack);
     183                 :        1330 :         bf_wpack_close_object(pack);
     184                 :             :     } else {
     185                 :             :         bf_wpack_kv_nil(pack, "cmap");
     186                 :             :     }
     187                 :             : 
     188         [ +  - ]:        1330 :     if (handle->pmap) {
     189                 :        1330 :         bf_wpack_open_object(pack, "pmap");
     190                 :        1330 :         bf_map_pack(handle->pmap, pack);
     191                 :        1330 :         bf_wpack_close_object(pack);
     192                 :             :     } else {
     193                 :             :         bf_wpack_kv_nil(pack, "pmap");
     194                 :             :     }
     195                 :             : 
     196         [ +  + ]:        1330 :     if (handle->lmap) {
     197                 :          31 :         bf_wpack_open_object(pack, "lmap");
     198                 :          31 :         bf_map_pack(handle->lmap, pack);
     199                 :          31 :         bf_wpack_close_object(pack);
     200                 :             :     } else {
     201                 :             :         bf_wpack_kv_nil(pack, "lmap");
     202                 :             :     }
     203                 :             : 
     204         [ -  + ]:        1330 :     if (handle->smap) {
     205                 :           0 :         bf_wpack_open_object(pack, "smap");
     206                 :           0 :         bf_map_pack(handle->smap, pack);
     207                 :           0 :         bf_wpack_close_object(pack);
     208                 :             :     } else {
     209                 :             :         bf_wpack_kv_nil(pack, "smap");
     210                 :             :     }
     211                 :             : 
     212                 :        1330 :     bf_wpack_kv_list(pack, "sets", &handle->sets);
     213                 :             : 
     214         [ -  + ]:        1330 :     return bf_wpack_is_valid(pack) ? 0 : -EINVAL;
     215                 :             : }
     216                 :             : 
     217                 :          16 : void bf_handle_dump(const struct bf_handle *handle, prefix_t *prefix)
     218                 :             : {
     219                 :             :     assert(handle);
     220                 :             :     assert(prefix);
     221                 :             : 
     222         [ -  + ]:          16 :     DUMP(prefix, "struct bf_handle at %p", handle);
     223                 :             : 
     224                 :          16 :     bf_dump_prefix_push(prefix);
     225                 :             : 
     226         [ -  + ]:          16 :     DUMP(prefix, "prog_name: %s", handle->prog_name);
     227         [ -  + ]:          16 :     DUMP(prefix, "prog_fd: %d", handle->prog_fd);
     228                 :             : 
     229         [ -  + ]:          16 :     if (handle->link) {
     230         [ #  # ]:           0 :         DUMP(prefix, "link: struct bf_link *");
     231                 :           0 :         bf_dump_prefix_push(prefix);
     232                 :           0 :         bf_link_dump(handle->link, bf_dump_prefix_last(prefix));
     233                 :           0 :         bf_dump_prefix_pop(prefix);
     234                 :             :     } else {
     235         [ -  + ]:          16 :         DUMP(prefix, "link: struct bf_link * (NULL)");
     236                 :             :     }
     237                 :             : 
     238         [ +  - ]:          16 :     if (handle->cmap) {
     239         [ -  + ]:          16 :         DUMP(prefix, "cmap: struct bf_map *");
     240                 :          16 :         bf_dump_prefix_push(prefix);
     241                 :          16 :         bf_map_dump(handle->cmap, bf_dump_prefix_last(prefix));
     242                 :          16 :         bf_dump_prefix_pop(prefix);
     243                 :             :     } else {
     244         [ #  # ]:           0 :         DUMP(prefix, "cmap: struct bf_map * (NULL)");
     245                 :             :     }
     246                 :             : 
     247         [ +  - ]:          16 :     if (handle->pmap) {
     248         [ -  + ]:          16 :         DUMP(prefix, "pmap: struct bf_map *");
     249                 :          16 :         bf_dump_prefix_push(prefix);
     250                 :          16 :         bf_map_dump(handle->pmap, bf_dump_prefix_last(prefix));
     251                 :          16 :         bf_dump_prefix_pop(prefix);
     252                 :             :     } else {
     253         [ #  # ]:           0 :         DUMP(prefix, "pmap: struct bf_map * (NULL)");
     254                 :             :     }
     255                 :             : 
     256         [ +  + ]:          16 :     if (handle->lmap) {
     257         [ -  + ]:           3 :         DUMP(prefix, "lmap: struct bf_map *");
     258                 :           3 :         bf_dump_prefix_push(prefix);
     259                 :           3 :         bf_map_dump(handle->lmap, bf_dump_prefix_last(prefix));
     260                 :           3 :         bf_dump_prefix_pop(prefix);
     261                 :             :     } else {
     262         [ -  + ]:          13 :         DUMP(prefix, "lmap: struct bf_map * (NULL)");
     263                 :             :     }
     264                 :             : 
     265         [ -  + ]:          16 :     if (handle->smap) {
     266         [ #  # ]:           0 :         DUMP(prefix, "smap: struct bf_map *");
     267                 :           0 :         bf_dump_prefix_push(prefix);
     268                 :           0 :         bf_map_dump(handle->smap, bf_dump_prefix_last(prefix));
     269                 :           0 :         bf_dump_prefix_pop(prefix);
     270                 :             :     } else {
     271         [ -  + ]:          16 :         DUMP(prefix, "smap: struct bf_map * (NULL)");
     272                 :             :     }
     273                 :             : 
     274         [ -  + ]:          16 :     DUMP(bf_dump_prefix_last(prefix), "sets: bf_list<bf_map>[%lu]",
     275                 :             :          bf_list_size(&handle->sets));
     276                 :          16 :     bf_dump_prefix_push(prefix);
     277   [ -  +  -  -  :          32 :     bf_list_foreach (&handle->sets, map_node) {
                   -  + ]
     278                 :             :         struct bf_map *map = bf_list_node_get_data(map_node);
     279                 :             : 
     280         [ #  # ]:           0 :         if (bf_list_is_tail(&handle->sets, map_node))
     281                 :           0 :             bf_dump_prefix_last(prefix);
     282                 :             : 
     283         [ #  # ]:           0 :         if (!map) {
     284         [ #  # ]:           0 :             DUMP(prefix, "struct bf_map * (NULL)");
     285                 :           0 :             continue;
     286                 :             :         }
     287                 :             : 
     288                 :           0 :         bf_map_dump(map, prefix);
     289                 :             :     }
     290                 :          16 :     bf_dump_prefix_pop(prefix);
     291                 :             : 
     292                 :          16 :     bf_dump_prefix_pop(prefix);
     293                 :          16 : }
     294                 :             : 
     295                 :        1305 : int bf_handle_pin(struct bf_handle *handle, struct bf_lock *lock)
     296                 :             : {
     297                 :             :     int dir_fd;
     298                 :             :     int r;
     299                 :             : 
     300                 :             :     assert(handle);
     301                 :             :     assert(lock);
     302                 :             : 
     303                 :        1305 :     dir_fd = lock->chain_fd;
     304                 :             : 
     305                 :        1305 :     r = bf_bpf_obj_pin(handle->prog_name, handle->prog_fd, dir_fd);
     306         [ +  + ]:        1305 :     if (r) {
     307         [ +  - ]:           1 :         bf_err_r(r, "failed to pin BPF program");
     308                 :           1 :         goto err_unpin_all;
     309                 :             :     }
     310                 :             : 
     311         [ +  - ]:        1304 :     if (handle->cmap) {
     312                 :        1304 :         r = bf_map_pin(handle->cmap, dir_fd);
     313         [ -  + ]:        1304 :         if (r) {
     314         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF counters map");
     315                 :           0 :             goto err_unpin_all;
     316                 :             :         }
     317                 :             :     }
     318                 :             : 
     319         [ +  - ]:        1304 :     if (handle->pmap) {
     320                 :        1304 :         r = bf_map_pin(handle->pmap, dir_fd);
     321         [ -  + ]:        1304 :         if (r) {
     322         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF printer map");
     323                 :           0 :             goto err_unpin_all;
     324                 :             :         }
     325                 :             :     }
     326                 :             : 
     327         [ +  + ]:        1304 :     if (handle->lmap) {
     328                 :          27 :         r = bf_map_pin(handle->lmap, dir_fd);
     329         [ -  + ]:          27 :         if (r) {
     330         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF log map");
     331                 :           0 :             goto err_unpin_all;
     332                 :             :         }
     333                 :             :     }
     334                 :             : 
     335         [ -  + ]:        1304 :     if (handle->smap) {
     336                 :           0 :         r = bf_map_pin(handle->smap, dir_fd);
     337         [ #  # ]:           0 :         if (r) {
     338         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF state map");
     339                 :           0 :             goto err_unpin_all;
     340                 :             :         }
     341                 :             :     }
     342                 :             : 
     343   [ +  +  +  +  :        3210 :     bf_list_foreach (&handle->sets, set_node) {
                   +  + ]
     344                 :             :         struct bf_map *map = bf_list_node_get_data(set_node);
     345                 :             : 
     346         [ -  + ]:         301 :         if (!map)
     347                 :           0 :             continue;
     348                 :             : 
     349                 :         301 :         r = bf_map_pin(map, dir_fd);
     350         [ -  + ]:         301 :         if (r) {
     351         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF set map");
     352                 :           0 :             goto err_unpin_all;
     353                 :             :         }
     354                 :             :     }
     355                 :             : 
     356         [ +  + ]:        1304 :     if (handle->link) {
     357                 :         120 :         r = bf_link_pin(handle->link, lock);
     358         [ -  + ]:         120 :         if (r) {
     359         [ #  # ]:           0 :             bf_err_r(r, "failed to pin BPF link");
     360                 :           0 :             goto err_unpin_all;
     361                 :             :         }
     362                 :             :     }
     363                 :             : 
     364                 :             :     return 0;
     365                 :             : 
     366                 :           1 : err_unpin_all:
     367                 :           1 :     bf_handle_unpin(handle, lock);
     368                 :           1 :     return r;
     369                 :             : }
     370                 :             : 
     371                 :        1279 : void bf_handle_unpin(struct bf_handle *handle, struct bf_lock *lock)
     372                 :             : {
     373                 :             :     int dir_fd;
     374                 :             : 
     375                 :             :     assert(handle);
     376                 :             :     assert(lock);
     377                 :             : 
     378                 :        1279 :     dir_fd = lock->chain_fd;
     379                 :             : 
     380         [ +  - ]:        1279 :     if (handle->cmap)
     381                 :        1279 :         bf_map_unpin(handle->cmap, dir_fd);
     382         [ +  - ]:        1279 :     if (handle->pmap)
     383                 :        1279 :         bf_map_unpin(handle->pmap, dir_fd);
     384         [ +  + ]:        1279 :     if (handle->lmap)
     385                 :          15 :         bf_map_unpin(handle->lmap, dir_fd);
     386         [ -  + ]:        1279 :     if (handle->smap)
     387                 :           0 :         bf_map_unpin(handle->smap, dir_fd);
     388                 :             : 
     389   [ +  +  -  +  :        3002 :     bf_list_foreach (&handle->sets, set_node) {
                   +  + ]
     390                 :             :         struct bf_map *map = bf_list_node_get_data(set_node);
     391                 :             : 
     392         [ -  + ]:         222 :         if (!map)
     393                 :           0 :             continue;
     394                 :             : 
     395                 :         222 :         bf_map_unpin(map, dir_fd);
     396                 :             :     }
     397                 :             : 
     398         [ +  + ]:        1279 :     if (handle->link)
     399                 :         123 :         bf_link_unpin(handle->link, lock);
     400                 :             : 
     401                 :        1279 :     unlinkat(dir_fd, handle->prog_name, 0);
     402                 :        1279 : }
     403                 :             : 
     404                 :        3479 : int bf_handle_get_counter(const struct bf_handle *handle, uint32_t counter_idx,
     405                 :             :                           struct bf_counter *counter)
     406                 :             : {
     407                 :             :     _cleanup_free_ struct bf_counter *percpu = NULL;
     408                 :             :     int num_cpus;
     409                 :             :     int r;
     410                 :             : 
     411                 :             :     assert(handle);
     412                 :             :     assert(counter);
     413                 :             : 
     414         [ -  + ]:        3479 :     if (!handle->cmap)
     415         [ #  # ]:           0 :         return bf_err_r(-ENOENT, "handle has no counters map");
     416                 :             : 
     417                 :        3479 :     num_cpus = libbpf_num_possible_cpus();
     418         [ -  + ]:        3479 :     if (num_cpus < 0)
     419         [ #  # ]:           0 :         return bf_err_r(num_cpus, "failed to get number of possible CPUs");
     420                 :             : 
     421                 :        3479 :     percpu = calloc(num_cpus, sizeof(*percpu));
     422         [ +  - ]:        3479 :     if (!percpu)
     423                 :             :         return -ENOMEM;
     424                 :             : 
     425                 :        3479 :     r = bf_bpf_map_lookup_elem(handle->cmap->fd, &counter_idx, percpu);
     426         [ -  + ]:        3479 :     if (r < 0)
     427         [ #  # ]:           0 :         return bf_err_r(r, "failed to lookup counters map");
     428                 :             : 
     429                 :        3479 :     counter->count = 0;
     430                 :        3479 :     counter->size = 0;
     431         [ +  + ]:       31311 :     for (int i = 0; i < num_cpus; i++) {
     432                 :       27832 :         counter->count += percpu[i].count;
     433                 :       27832 :         counter->size += percpu[i].size;
     434                 :             :     }
     435                 :             : 
     436                 :             :     return 0;
     437                 :             : }
     438                 :             : 
     439                 :           5 : int bf_handle_set_counter(struct bf_handle *handle, uint32_t counter_idx,
     440                 :             :                           const struct bf_counter *counter)
     441                 :             : {
     442                 :             :     _cleanup_free_ struct bf_counter *percpu = NULL;
     443                 :             :     int num_cpus;
     444                 :             :     int r;
     445                 :             : 
     446                 :             :     assert(handle);
     447                 :             :     assert(counter);
     448                 :             : 
     449         [ -  + ]:           5 :     if (!handle->cmap)
     450         [ #  # ]:           0 :         return bf_err_r(-ENOENT, "handle has no counters map");
     451                 :             : 
     452                 :           5 :     num_cpus = libbpf_num_possible_cpus();
     453         [ -  + ]:           5 :     if (num_cpus < 0)
     454         [ #  # ]:           0 :         return bf_err_r(num_cpus, "failed to get number of possible CPUs");
     455                 :             : 
     456                 :           5 :     percpu = calloc(num_cpus, sizeof(*percpu));
     457         [ +  - ]:           5 :     if (!percpu)
     458                 :             :         return -ENOMEM;
     459                 :             : 
     460                 :           5 :     percpu[0] = *counter;
     461                 :             : 
     462                 :           5 :     r = bf_bpf_map_update_elem(handle->cmap->fd, &counter_idx, percpu, 0);
     463         [ -  + ]:           5 :     if (r < 0)
     464         [ #  # ]:           0 :         return bf_err_r(r, "failed to update counters map");
     465                 :             : 
     466                 :             :     return 0;
     467                 :             : }
     468                 :             : 
     469                 :         124 : int bf_handle_attach(struct bf_handle *handle, enum bf_hook hook,
     470                 :             :                      struct bf_hookopts **hookopts)
     471                 :             : {
     472                 :             :     int r;
     473                 :             : 
     474                 :             :     assert(handle);
     475                 :             :     assert(hookopts);
     476                 :             : 
     477         [ -  + ]:         124 :     if (handle->link)
     478         [ #  # ]:           0 :         return bf_err_r(-EEXIST, "program is already attached");
     479                 :             : 
     480                 :         124 :     r = bf_link_new(&handle->link, _BF_LINK_NAME, hook, hookopts,
     481                 :             :                     handle->prog_fd);
     482         [ +  + ]:         124 :     if (r)
     483         [ +  - ]:           4 :         return bf_err_r(r, "failed to attach bf_link");
     484                 :             : 
     485                 :             :     return 0;
     486                 :             : }
     487                 :             : 
     488                 :        1264 : void bf_handle_detach(struct bf_handle *handle)
     489                 :             : {
     490                 :             :     assert(handle);
     491                 :             : 
     492         [ +  + ]:        1264 :     if (handle->link) {
     493                 :         111 :         (void)bf_bpf_link_detach(handle->link->fd);
     494         [ +  + ]:         111 :         if (handle->link->fd_extra >= 0)
     495                 :           6 :             (void)bf_bpf_link_detach(handle->link->fd_extra);
     496                 :             :     }
     497                 :             : 
     498                 :        1264 :     bf_link_free(&handle->link);
     499                 :        1264 : }
     500                 :             : 
     501                 :        1264 : void bf_handle_unload(struct bf_handle *handle)
     502                 :             : {
     503                 :             :     assert(handle);
     504                 :             : 
     505                 :        1264 :     closep(&handle->prog_fd);
     506                 :             : 
     507                 :             :     /* Explicitly detach the BPF link before closing it. Relying solely on
     508                 :             :      * close() is not sufficient when the link is pinned (the pin holds a
     509                 :             :      * kernel reference that keeps the link alive). Using BPF_LINK_DETACH
     510                 :             :      * ensures the program is removed from the hook immediately. */
     511                 :        1264 :     bf_handle_detach(handle);
     512                 :             : 
     513                 :        1264 :     bf_link_free(&handle->link);
     514                 :        1264 :     bf_map_free(&handle->cmap);
     515                 :        1264 :     bf_map_free(&handle->pmap);
     516                 :        1264 :     bf_map_free(&handle->lmap);
     517                 :        1264 :     bf_map_free(&handle->smap);
     518                 :        1264 :     bf_list_clean(&handle->sets);
     519                 :        1264 : }
        

Generated by: LCOV version 2.0-1