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

Generated by: LCOV version 2.0-1