LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - ip4.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 95.7 % 47 45
Test Date: 2025-11-24 12:34:34 Functions: 100.0 % 5 5
Branches: 60.9 % 46 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 <endian.h>
      14                 :             : #include <errno.h>
      15                 :             : #include <stddef.h>
      16                 :             : #include <stdint.h>
      17                 :             : 
      18                 :             : #include <bpfilter/helper.h>
      19                 :             : #include <bpfilter/logger.h>
      20                 :             : #include <bpfilter/matcher.h>
      21                 :             : #include <bpfilter/runtime.h>
      22                 :             : 
      23                 :             : #include "cgen/program.h"
      24                 :             : #include "filter.h"
      25                 :             : 
      26                 :          40 : static int _bf_matcher_generate_ip4_addr(struct bf_program *program,
      27                 :             :                                          const struct bf_matcher *matcher)
      28                 :             : {
      29                 :             :     bf_assert(program && matcher);
      30                 :             : 
      31                 :          40 :     uint32_t *addr = (uint32_t *)bf_matcher_payload(matcher);
      32                 :          40 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_IP4_SADDR ?
      33         [ +  + ]:          40 :                         offsetof(struct iphdr, saddr) :
      34                 :             :                         offsetof(struct iphdr, daddr);
      35                 :             : 
      36         [ -  + ]:          40 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
      37         [ -  + ]:          40 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, *addr));
      38                 :             : 
      39   [ +  +  -  + ]:          60 :     EMIT_FIXUP_JMP_NEXT_RULE(
      40                 :             :         program,
      41                 :             :         BPF_JMP_REG(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
      42                 :             :                                                                   BPF_JEQ,
      43                 :             :                     BPF_REG_1, BPF_REG_2, 0));
      44                 :             : 
      45                 :          40 :     return 0;
      46                 :             : }
      47                 :             : 
      48                 :          50 : static int _bf_matcher_generate_ip4_proto(struct bf_program *program,
      49                 :             :                                           const struct bf_matcher *matcher)
      50                 :             : {
      51                 :             :     bf_assert(program && matcher);
      52                 :             : 
      53                 :          50 :     uint8_t proto = *(uint8_t *)bf_matcher_payload(matcher);
      54                 :             : 
      55         [ -  + ]:          50 :     EMIT(program, BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_6,
      56                 :             :                               offsetof(struct iphdr, protocol)));
      57   [ -  +  -  + ]:          50 :     EMIT_FIXUP_JMP_NEXT_RULE(
      58                 :             :         program,
      59                 :             :         BPF_JMP_IMM(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
      60                 :             :                                                                   BPF_JEQ,
      61                 :             :                     BPF_REG_1, proto, 0));
      62                 :             : 
      63                 :          50 :     return 0;
      64                 :             : }
      65                 :             : 
      66                 :          40 : static void _bf_ip4_prefix_to_mask(uint32_t prefixlen, uint8_t *mask)
      67                 :             : {
      68                 :             :     bf_assert(mask);
      69                 :             : 
      70                 :          40 :     memset(mask, 0x00, 4);
      71                 :             : 
      72                 :          40 :     memset(mask, 0xff, prefixlen / 8);
      73         [ +  + ]:          40 :     if (prefixlen % 8)
      74                 :          30 :         mask[prefixlen / 8] = 0xff << (8 - prefixlen % 8) & 0xff;
      75                 :          40 : }
      76                 :             : 
      77                 :          40 : static int _bf_matcher_generate_ip4_net(struct bf_program *program,
      78                 :             :                                         const struct bf_matcher *matcher)
      79                 :             : {
      80                 :             :     bf_assert(program && matcher);
      81                 :             : 
      82                 :             :     uint32_t mask;
      83                 :             :     struct bf_ip4_lpm_key *addr =
      84                 :          40 :         (struct bf_ip4_lpm_key *)bf_matcher_payload(matcher);
      85                 :          40 :     size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_IP4_SNET ?
      86         [ +  + ]:          40 :                         offsetof(struct iphdr, saddr) :
      87                 :             :                         offsetof(struct iphdr, daddr);
      88                 :             : 
      89                 :          40 :     _bf_ip4_prefix_to_mask(addr->prefixlen, (void *)&mask);
      90                 :             : 
      91         [ -  + ]:          40 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
      92         [ -  + ]:          40 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, addr->data));
      93                 :             : 
      94         [ +  - ]:          40 :     if (mask != ~0U) {
      95         [ -  + ]:          40 :         EMIT(program, BPF_MOV32_IMM(BPF_REG_3, mask));
      96         [ -  + ]:          40 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_1, BPF_REG_3));
      97         [ -  + ]:          40 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_2, BPF_REG_3));
      98                 :             :     }
      99                 :             : 
     100   [ +  +  -  + ]:          60 :     EMIT_FIXUP_JMP_NEXT_RULE(
     101                 :             :         program,
     102                 :             :         BPF_JMP_REG(bf_matcher_get_op(matcher) == BF_MATCHER_EQ ? BPF_JNE :
     103                 :             :                                                                   BPF_JEQ,
     104                 :             :                     BPF_REG_1, BPF_REG_2, 0));
     105                 :             : 
     106                 :          40 :     return 0;
     107                 :             : }
     108                 :             : 
     109                 :         130 : int bf_matcher_generate_ip4(struct bf_program *program,
     110                 :             :                             const struct bf_matcher *matcher)
     111                 :             : {
     112                 :             :     bf_assert(program && matcher);
     113                 :             : 
     114                 :             :     int r;
     115                 :             : 
     116         [ -  + ]:         130 :     EMIT_FIXUP_JMP_NEXT_RULE(
     117                 :             :         program, BPF_JMP_IMM(BPF_JNE, BPF_REG_7, htobe16(ETH_P_IP), 0));
     118                 :             : 
     119         [ -  + ]:         130 :     EMIT(program,
     120                 :             :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l3_hdr)));
     121                 :             : 
     122   [ +  +  +  - ]:         130 :     switch (bf_matcher_get_type(matcher)) {
     123                 :          40 :     case BF_MATCHER_IP4_SADDR:
     124                 :             :     case BF_MATCHER_IP4_DADDR:
     125                 :          40 :         r = _bf_matcher_generate_ip4_addr(program, matcher);
     126                 :          40 :         break;
     127                 :          50 :     case BF_MATCHER_IP4_PROTO:
     128                 :          50 :         r = _bf_matcher_generate_ip4_proto(program, matcher);
     129                 :          50 :         break;
     130                 :          40 :     case BF_MATCHER_IP4_SNET:
     131                 :             :     case BF_MATCHER_IP4_DNET:
     132                 :          40 :         r = _bf_matcher_generate_ip4_net(program, matcher);
     133                 :          40 :         break;
     134                 :           0 :     default:
     135         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "unknown matcher type %d",
     136                 :             :                         bf_matcher_get_type(matcher));
     137                 :             :     };
     138                 :             : 
     139                 :             :     if (r)
     140                 :             :         return r;
     141                 :             : 
     142                 :             :     return 0;
     143                 :             : }
        

Generated by: LCOV version 2.0-1