LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - ip4.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 81.8 % 55 45
Test Date: 2026-02-04 15:18:55 Functions: 83.3 % 6 5
Branches: 52.8 % 53 28

             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/ip4.h"
       7                 :             : 
       8                 :             : #include <linux/bpf.h>
       9                 :             : #include <linux/bpf_common.h>
      10                 :             : #include <linux/if_ether.h>
      11                 :             : #include <linux/ip.h>
      12                 :             : 
      13                 :             : #include <assert.h>
      14                 :             : #include <endian.h>
      15                 :             : #include <errno.h>
      16                 :             : #include <stddef.h>
      17                 :             : #include <stdint.h>
      18                 :             : 
      19                 :             : #include <bpfilter/helper.h>
      20                 :             : #include <bpfilter/logger.h>
      21                 :             : #include <bpfilter/matcher.h>
      22                 :             : #include <bpfilter/runtime.h>
      23                 :             : 
      24                 :             : #include "cgen/program.h"
      25                 :             : #include "filter.h"
      26                 :             : 
      27                 :          40 : static int _bf_matcher_generate_ip4_addr(struct bf_program *program,
      28                 :             :                                          const struct bf_matcher *matcher)
      29                 :             : {
      30                 :             :     assert(program);
      31                 :             :     assert(matcher);
      32                 :             : 
      33                 :          40 :     uint32_t *addr = (uint32_t *)bf_matcher_payload(matcher);
      34                 :          40 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_IP4_SADDR ?
      35         [ +  + ]:          40 :                         offsetof(struct iphdr, saddr) :
      36                 :             :                         offsetof(struct iphdr, daddr);
      37                 :             : 
      38         [ -  + ]:          40 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
      39         [ -  + ]:          40 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, *addr));
      40                 :             : 
      41   [ +  +  -  + ]:          60 :     EMIT_FIXUP_JMP_NEXT_RULE(
      42                 :             :         program,
      43                 :             :         BPF_JMP_REG(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
      44                 :             :                                                                   BPF_JEQ,
      45                 :             :                     BPF_REG_1, BPF_REG_2, 0));
      46                 :             : 
      47                 :          40 :     return 0;
      48                 :             : }
      49                 :             : 
      50                 :          64 : static int _bf_matcher_generate_ip4_proto(struct bf_program *program,
      51                 :             :                                           const struct bf_matcher *matcher)
      52                 :             : {
      53                 :             :     assert(program);
      54                 :             :     assert(matcher);
      55                 :             : 
      56                 :          64 :     uint8_t proto = *(uint8_t *)bf_matcher_payload(matcher);
      57                 :             : 
      58         [ -  + ]:          64 :     EMIT(program, BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_6,
      59                 :             :                               offsetof(struct iphdr, protocol)));
      60   [ -  +  -  + ]:          64 :     EMIT_FIXUP_JMP_NEXT_RULE(
      61                 :             :         program,
      62                 :             :         BPF_JMP_IMM(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
      63                 :             :                                                                   BPF_JEQ,
      64                 :             :                     BPF_REG_1, proto, 0));
      65                 :             : 
      66                 :          64 :     return 0;
      67                 :             : }
      68                 :             : 
      69                 :           0 : static int _bf_matcher_generate_ip4_dscp(struct bf_program *program,
      70                 :             :                                          const struct bf_matcher *matcher)
      71                 :             : {
      72                 :             :     uint8_t dscp;
      73                 :             : 
      74                 :             :     assert(program);
      75                 :             :     assert(matcher);
      76                 :             : 
      77                 :           0 :     dscp = *(uint8_t *)bf_matcher_payload(matcher);
      78                 :             : 
      79         [ #  # ]:           0 :     EMIT(program,
      80                 :             :          BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_6, offsetof(struct iphdr, tos)));
      81   [ #  #  #  # ]:           0 :     EMIT_FIXUP_JMP_NEXT_RULE(
      82                 :             :         program,
      83                 :             :         BPF_JMP_IMM(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
      84                 :             :                                                                   BPF_JEQ,
      85                 :             :                     BPF_REG_1, dscp, 0));
      86                 :             : 
      87                 :           0 :     return 0;
      88                 :             : }
      89                 :             : 
      90                 :          40 : static void _bf_ip4_prefix_to_mask(uint32_t prefixlen, uint8_t *mask)
      91                 :             : {
      92                 :             :     assert(mask);
      93                 :             : 
      94                 :          40 :     memset(mask, 0x00, 4);
      95                 :             : 
      96                 :          40 :     memset(mask, 0xff, prefixlen / 8);
      97         [ +  + ]:          40 :     if (prefixlen % 8)
      98                 :          30 :         mask[prefixlen / 8] = 0xff << (8 - prefixlen % 8) & 0xff;
      99                 :          40 : }
     100                 :             : 
     101                 :          40 : static int _bf_matcher_generate_ip4_net(struct bf_program *program,
     102                 :             :                                         const struct bf_matcher *matcher)
     103                 :             : {
     104                 :             :     assert(program);
     105                 :             :     assert(matcher);
     106                 :             : 
     107                 :             :     uint32_t mask;
     108                 :             :     struct bf_ip4_lpm_key *addr =
     109                 :          40 :         (struct bf_ip4_lpm_key *)bf_matcher_payload(matcher);
     110                 :          40 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_IP4_SNET ?
     111         [ +  + ]:          40 :                         offsetof(struct iphdr, saddr) :
     112                 :             :                         offsetof(struct iphdr, daddr);
     113                 :             : 
     114                 :          40 :     _bf_ip4_prefix_to_mask(addr->prefixlen, (void *)&mask);
     115                 :             : 
     116         [ -  + ]:          40 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
     117         [ -  + ]:          40 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, addr->data));
     118                 :             : 
     119         [ +  - ]:          40 :     if (mask != ~0U) {
     120         [ -  + ]:          40 :         EMIT(program, BPF_MOV32_IMM(BPF_REG_3, mask));
     121         [ -  + ]:          40 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_1, BPF_REG_3));
     122         [ -  + ]:          40 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_2, BPF_REG_3));
     123                 :             :     }
     124                 :             : 
     125   [ +  +  -  + ]:          60 :     EMIT_FIXUP_JMP_NEXT_RULE(
     126                 :             :         program,
     127                 :             :         BPF_JMP_REG(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
     128                 :             :                                                                   BPF_JEQ,
     129                 :             :                     BPF_REG_1, BPF_REG_2, 0));
     130                 :             : 
     131                 :          40 :     return 0;
     132                 :             : }
     133                 :             : 
     134                 :         144 : int bf_matcher_generate_ip4(struct bf_program *program,
     135                 :             :                             const struct bf_matcher *matcher)
     136                 :             : {
     137                 :             :     assert(program);
     138                 :             :     assert(matcher);
     139                 :             : 
     140                 :             :     int r;
     141                 :             : 
     142         [ -  + ]:         144 :     EMIT_FIXUP_JMP_NEXT_RULE(
     143                 :             :         program, BPF_JMP_IMM(BPF_JNE, BPF_REG_7, htobe16(ETH_P_IP), 0));
     144                 :             : 
     145         [ -  + ]:         144 :     EMIT(program,
     146                 :             :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l3_hdr)));
     147                 :             : 
     148   [ +  +  -  +  :         144 :     switch (bf_matcher_get_type(matcher)) {
                      - ]
     149                 :          40 :     case BF_MATCHER_IP4_SADDR:
     150                 :             :     case BF_MATCHER_IP4_DADDR:
     151                 :          40 :         r = _bf_matcher_generate_ip4_addr(program, matcher);
     152                 :          40 :         break;
     153                 :          64 :     case BF_MATCHER_IP4_PROTO:
     154                 :          64 :         r = _bf_matcher_generate_ip4_proto(program, matcher);
     155                 :          64 :         break;
     156                 :           0 :     case BF_MATCHER_IP4_DSCP:
     157                 :           0 :         r = _bf_matcher_generate_ip4_dscp(program, matcher);
     158                 :           0 :         break;
     159                 :          40 :     case BF_MATCHER_IP4_SNET:
     160                 :             :     case BF_MATCHER_IP4_DNET:
     161                 :          40 :         r = _bf_matcher_generate_ip4_net(program, matcher);
     162                 :          40 :         break;
     163                 :           0 :     default:
     164         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "unknown matcher type %d",
     165                 :             :                         bf_matcher_get_type(matcher));
     166                 :             :     };
     167                 :             : 
     168                 :             :     if (r)
     169                 :             :         return r;
     170                 :             : 
     171                 :             :     return 0;
     172                 :             : }
        

Generated by: LCOV version 2.0-1