LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - set.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 78.7 % 61 48
Test Date: 2026-02-04 15:18:55 Functions: 100.0 % 2 2
Branches: 38.6 % 88 34

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "cgen/matcher/set.h"
       7                 :             : 
       8                 :             : #include <bpfilter/chain.h>
       9                 :             : #include <bpfilter/matcher.h>
      10                 :             : #include <bpfilter/set.h>
      11                 :             : 
      12                 :             : #include "cgen/program.h"
      13                 :             : #include "cgen/stub.h"
      14                 :             : 
      15                 :          20 : static int _bf_matcher_generate_set_trie(struct bf_program *program,
      16                 :             :                                          const struct bf_matcher *matcher)
      17                 :             : {
      18                 :             :     assert(program);
      19                 :             :     assert(matcher);
      20                 :             : 
      21                 :             :     const struct bf_set *set =
      22                 :          20 :         bf_chain_get_set_for_matcher(program->runtime.chain, matcher);
      23                 :          20 :     enum bf_matcher_type type = set->key[0];
      24                 :          20 :     const struct bf_matcher_meta *meta = bf_matcher_get_meta(type);
      25                 :             :     int r;
      26                 :             : 
      27                 :             :     if (!set) {
      28                 :             :         return bf_err_r(-ENOENT, "set #%u not found in %s",
      29                 :             :                         *(uint32_t *)bf_matcher_payload(matcher),
      30                 :             :                         program->runtime.chain->name);
      31                 :             :     }
      32                 :             : 
      33                 :          20 :     r = bf_stub_rule_check_protocol(program, meta);
      34         [ -  + ]:          20 :     if (r)
      35         [ #  # ]:           0 :         return bf_err_r(r, "failed to check for protocol");
      36                 :             : 
      37                 :          20 :     r = bf_stub_load_header(program, meta, BPF_REG_6);
      38         [ -  + ]:          20 :     if (r)
      39         [ #  # ]:           0 :         return bf_err_r(r, "failed to load protocol header into BPF_REG_6");
      40                 :             : 
      41         [ -  + ]:          20 :     if (BF_FLAG(type) & (BF_FLAGS(BF_MATCHER_IP4_SNET, BF_MATCHER_IP4_DNET))) {
      42         [ #  # ]:           0 :         EMIT(program, BPF_MOV64_IMM(BPF_REG_1, 32));
      43         [ #  # ]:           0 :         EMIT(program,
      44                 :             :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, BF_PROG_SCR_OFF(4)));
      45         [ #  # ]:           0 :         EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6,
      46                 :             :                                   meta->hdr_payload_offset));
      47         [ #  # ]:           0 :         EMIT(program,
      48                 :             :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, BF_PROG_SCR_OFF(8)));
      49         [ +  - ]:          20 :     } else if (BF_FLAG(type) &
      50                 :             :                (BF_FLAGS(BF_MATCHER_IP6_SNET, BF_MATCHER_IP6_DNET))) {
      51         [ -  + ]:          20 :         EMIT(program, BPF_MOV64_IMM(BPF_REG_1, 128));
      52         [ -  + ]:          20 :         EMIT(program,
      53                 :             :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, BF_PROG_SCR_OFF(4)));
      54                 :             : 
      55         [ -  + ]:          20 :         EMIT(program, BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
      56                 :             :                                   meta->hdr_payload_offset));
      57         [ -  + ]:          20 :         EMIT(program,
      58                 :             :              BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, BF_PROG_SCR_OFF(8)));
      59                 :             : 
      60         [ -  + ]:          20 :         EMIT(program, BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
      61                 :             :                                   meta->hdr_payload_offset + 8));
      62         [ -  + ]:          20 :         EMIT(program,
      63                 :             :              BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, BF_PROG_SCR_OFF(16)));
      64                 :             :     } else {
      65         [ #  # ]:           0 :         return bf_err_r(-EINVAL,
      66                 :             :                         "set key '%s' (%d) should not use a LPM trie map",
      67                 :             :                         bf_matcher_type_to_str(type), type);
      68                 :             :     }
      69                 :             : 
      70   [ +  -  +  - ]:          20 :     EMIT_LOAD_SET_FD_FIXUP(program, BPF_REG_1,
      71                 :             :                            *(uint32_t *)bf_matcher_payload(matcher));
      72         [ -  + ]:          20 :     EMIT(program, BPF_MOV64_REG(BPF_REG_2, BPF_REG_10));
      73         [ -  + ]:          20 :     EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, BF_PROG_SCR_OFF(4)));
      74         [ -  + ]:          20 :     EMIT(program, BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem));
      75                 :             : 
      76                 :             :     // Jump to the next rule if map_lookup_elem returned 0
      77         [ -  + ]:          20 :     EMIT_FIXUP_JMP_NEXT_RULE(program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 0));
      78                 :          20 :     return 0;
      79                 :             : }
      80                 :             : 
      81                 :          81 : int bf_matcher_generate_set(struct bf_program *program,
      82                 :             :                             const struct bf_matcher *matcher)
      83                 :             : {
      84                 :             :     assert(program);
      85                 :             :     assert(matcher);
      86                 :             : 
      87                 :             :     const struct bf_set *set =
      88                 :          81 :         bf_chain_get_set_for_matcher(program->runtime.chain, matcher);
      89                 :             :     size_t offset = 0;
      90                 :             :     int r;
      91                 :             : 
      92         [ -  + ]:          81 :     if (!set) {
      93         [ #  # ]:           0 :         return bf_err_r(-ENOENT, "set #%u not found in %s",
      94                 :             :                         *(uint32_t *)bf_matcher_payload(matcher),
      95                 :             :                         program->runtime.chain->name);
      96                 :             :     }
      97                 :             : 
      98         [ +  + ]:          81 :     if (set->use_trie)
      99                 :          20 :         return _bf_matcher_generate_set_trie(program, matcher);
     100                 :             : 
     101                 :             :     // Ensure the packet uses the required protocols
     102         [ +  + ]:         142 :     for (size_t i = 0; i < set->n_comps; ++i) {
     103                 :          81 :         enum bf_matcher_type type = set->key[i];
     104                 :          81 :         const struct bf_matcher_meta *meta = bf_matcher_get_meta(type);
     105                 :             : 
     106         [ -  + ]:          81 :         if (!meta) {
     107         [ #  # ]:           0 :             return bf_err_r(-ENOENT, "meta for '%s' not found",
     108                 :             :                             bf_matcher_type_to_str(type));
     109                 :             :         }
     110                 :             : 
     111                 :          81 :         r = bf_stub_rule_check_protocol(program, meta);
     112         [ -  + ]:          81 :         if (r)
     113         [ #  # ]:           0 :             return bf_err_r(r, "failed to check for protocol");
     114                 :             :     }
     115                 :             : 
     116                 :             :     // Generate the bytecode to build the set key
     117         [ +  + ]:         142 :     for (size_t i = 0; i < set->n_comps; ++i) {
     118                 :          81 :         enum bf_matcher_type type = set->key[i];
     119                 :          81 :         const struct bf_matcher_meta *meta = bf_matcher_get_meta(type);
     120                 :             : 
     121         [ -  + ]:          81 :         if (!meta) {
     122         [ #  # ]:           0 :             return bf_err_r(-ENOENT, "meta for '%s' not found",
     123                 :             :                             bf_matcher_type_to_str(type));
     124                 :             :         }
     125                 :             : 
     126                 :          81 :         r = bf_stub_load_header(program, meta, BPF_REG_6);
     127         [ -  + ]:          81 :         if (r)
     128         [ #  # ]:           0 :             return bf_err_r(r, "failed to load protocol header into BPF_REG_6");
     129                 :             : 
     130                 :          81 :         r = bf_stub_stx_payload(program, meta, offset);
     131         [ -  + ]:          81 :         if (r) {
     132         [ #  # ]:           0 :             return bf_err_r(r,
     133                 :             :                             "failed to generate bytecode to load packet data");
     134                 :             :         }
     135                 :             : 
     136                 :          81 :         offset += meta->hdr_payload_size;
     137                 :             :     }
     138                 :             : 
     139   [ +  -  +  - ]:          61 :     EMIT_LOAD_SET_FD_FIXUP(program, BPF_REG_1,
     140                 :             :                            *(uint32_t *)bf_matcher_payload(matcher));
     141         [ -  + ]:          61 :     EMIT(program, BPF_MOV64_REG(BPF_REG_2, BPF_REG_10));
     142         [ -  + ]:          61 :     EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, BF_PROG_SCR_OFF(0)));
     143         [ -  + ]:          61 :     EMIT(program, BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem));
     144                 :             : 
     145                 :             :     // Jump to the next rule if map_lookup_elem returned 0
     146         [ -  + ]:          61 :     EMIT_FIXUP_JMP_NEXT_RULE(program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 0));
     147                 :             : 
     148                 :          61 :     return 0;
     149                 :             : }
        

Generated by: LCOV version 2.0-1