LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - ip4.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 94 0
Test Date: 2025-07-24 21:09:26 Functions: 0.0 % 8 0

            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 "bpfilter/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/cgen/program.h"
      19              : #include "core/helper.h"
      20              : #include "core/list.h"
      21              : #include "core/logger.h"
      22              : #include "core/matcher.h"
      23              : #include "core/set.h"
      24              : 
      25              : #include "external/filter.h"
      26              : 
      27              : static int
      28            0 : _bf_matcher_generate_ip4_addr_unique(struct bf_program *program,
      29              :                                      const struct bf_matcher *matcher)
      30              : {
      31              :     uint32_t *addr = (uint32_t *)&matcher->payload;
      32            0 :     size_t offset = matcher->type == BF_MATCHER_IP4_SADDR ?
      33            0 :                         offsetof(struct iphdr, saddr) :
      34              :                         offsetof(struct iphdr, daddr);
      35              : 
      36            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
      37            0 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, *addr));
      38              : 
      39            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
      40              :         program, BPF_JMP_REG(matcher->op == BF_MATCHER_EQ ? BPF_JNE : BPF_JEQ,
      41              :                              BPF_REG_1, BPF_REG_2, 0));
      42              : 
      43            0 :     return 0;
      44              : }
      45              : 
      46            0 : static int _bf_matcher_generate_ip4_addr_set(struct bf_program *program,
      47              :                                              const struct bf_matcher *matcher)
      48              : {
      49              :     uint32_t set_id;
      50              :     struct bf_set *set;
      51              :     int16_t offset;
      52              : 
      53            0 :     bf_assert(program);
      54            0 :     bf_assert(matcher);
      55              : 
      56            0 :     set_id = *(uint32_t *)matcher->payload;
      57            0 :     set = bf_list_get_at(&program->runtime.chain->sets, set_id);
      58              : 
      59            0 :     switch (set->type) {
      60            0 :     case BF_SET_IP4:
      61            0 :         offset = matcher->type == BF_MATCHER_IP4_SADDR ?
      62              :                      offsetof(struct iphdr, saddr) :
      63              :                      offsetof(struct iphdr, daddr);
      64            0 :         EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_6, offset));
      65            0 :         EMIT(program,
      66              :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_SCR_OFF(0)));
      67              :         break;
      68            0 :     default:
      69            0 :         return bf_err_r(-EINVAL, "unsupported set type: %s",
      70              :                         bf_set_type_to_str(set->type));
      71              :     }
      72              : 
      73            0 :     EMIT_LOAD_SET_FD_FIXUP(program, BPF_REG_1, set_id);
      74            0 :     EMIT(program, BPF_MOV64_REG(BPF_REG_2, BPF_REG_10));
      75            0 :     EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, BF_PROG_SCR_OFF(0)));
      76              : 
      77            0 :     EMIT(program, BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem));
      78              : 
      79              :     // Jump to the next rule if map_lookup_elem returned 0
      80            0 :     EMIT_FIXUP_JMP_NEXT_RULE(program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 0));
      81              : 
      82            0 :     return 0;
      83              : }
      84              : 
      85            0 : static int _bf_matcher_generate_ip4_addr(struct bf_program *program,
      86              :                                          const struct bf_matcher *matcher)
      87              : {
      88            0 :     switch (matcher->op) {
      89            0 :     case BF_MATCHER_EQ:
      90              :     case BF_MATCHER_NE:
      91            0 :         return _bf_matcher_generate_ip4_addr_unique(program, matcher);
      92            0 :     case BF_MATCHER_IN:
      93            0 :         return _bf_matcher_generate_ip4_addr_set(program, matcher);
      94              :     default:
      95              :         return -EINVAL;
      96              :     }
      97              : 
      98              :     return 0;
      99              : }
     100              : 
     101            0 : static int _bf_matcher_generate_ip4_proto(struct bf_program *program,
     102              :                                           const struct bf_matcher *matcher)
     103              : {
     104            0 :     uint8_t proto = *(uint8_t *)&matcher->payload;
     105              : 
     106            0 :     EMIT(program, BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_6,
     107              :                               offsetof(struct iphdr, protocol)));
     108            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
     109              :         program, BPF_JMP_IMM(matcher->op == BF_MATCHER_EQ ? BPF_JNE : BPF_JEQ,
     110              :                              BPF_REG_1, proto, 0));
     111              : 
     112            0 :     return 0;
     113              : }
     114              : 
     115            0 : static int _bf_matcher_generate_ip4_net_single(struct bf_program *program,
     116              :                                                const struct bf_matcher *matcher)
     117              : {
     118              :     struct bf_matcher_ip4_addr *addr =
     119              :         (struct bf_matcher_ip4_addr *)&matcher->payload;
     120            0 :     size_t offset = matcher->type == BF_MATCHER_IP4_SNET ?
     121            0 :                         offsetof(struct iphdr, saddr) :
     122              :                         offsetof(struct iphdr, daddr);
     123              : 
     124            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offset));
     125            0 :     EMIT(program, BPF_MOV32_IMM(BPF_REG_2, addr->addr));
     126              : 
     127            0 :     if (addr->mask != ~0U) {
     128            0 :         EMIT(program, BPF_MOV32_IMM(BPF_REG_3, addr->mask));
     129            0 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_1, BPF_REG_3));
     130            0 :         EMIT(program, BPF_ALU32_REG(BPF_AND, BPF_REG_2, BPF_REG_3));
     131              :     }
     132              : 
     133            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
     134              :         program, BPF_JMP_REG(matcher->op == BF_MATCHER_EQ ? BPF_JNE : BPF_JEQ,
     135              :                              BPF_REG_1, BPF_REG_2, 0));
     136              : 
     137            0 :     return 0;
     138              : }
     139              : 
     140            0 : static int _bf_matcher_generate_ip4_net_in(struct bf_program *program,
     141              :                                            const struct bf_matcher *matcher)
     142              : {
     143              :     uint32_t set_id;
     144              :     struct bf_set *set;
     145              :     int16_t offset;
     146              : 
     147            0 :     bf_assert(program && matcher);
     148              : 
     149            0 :     set_id = *(uint32_t *)matcher->payload;
     150            0 :     set = bf_list_get_at(&program->runtime.chain->sets, set_id);
     151            0 :     if (!set)
     152            0 :         return bf_err_r(-ENOENT, "set #%d not found", set_id);
     153              : 
     154            0 :     switch (set->type) {
     155            0 :     case BF_SET_IP4_SUBNET:
     156            0 :         offset = matcher->type == BF_MATCHER_IP4_SNET ?
     157              :                      offsetof(struct iphdr, saddr) :
     158              :                      offsetof(struct iphdr, daddr);
     159            0 :         EMIT(program, BPF_MOV64_IMM(BPF_REG_3, 32));
     160            0 :         EMIT(program,
     161              :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_3, BF_PROG_SCR_OFF(0)));
     162            0 :         EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_6, offset));
     163            0 :         EMIT(program,
     164              :              BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_SCR_OFF(4)));
     165              :         break;
     166            0 :     default:
     167            0 :         return bf_err_r(-EINVAL, "unsupported set type: %s",
     168              :                         bf_set_type_to_str(set->type));
     169              :     }
     170              : 
     171            0 :     EMIT_LOAD_SET_FD_FIXUP(program, BPF_REG_1, set_id);
     172            0 :     EMIT(program, BPF_MOV64_REG(BPF_REG_2, BPF_REG_10));
     173            0 :     EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, BF_PROG_SCR_OFF(0)));
     174              : 
     175            0 :     EMIT(program, BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem));
     176              : 
     177              :     // Jump to the next rule if map_lookup_elem returned 0
     178            0 :     EMIT_FIXUP_JMP_NEXT_RULE(program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 0));
     179              : 
     180            0 :     return 0;
     181              : }
     182              : 
     183            0 : static int _bf_matcher_generate_ip4_net(struct bf_program *program,
     184              :                                         const struct bf_matcher *matcher)
     185              : {
     186            0 :     bf_assert(program && matcher);
     187              : 
     188              :     int r;
     189              : 
     190            0 :     switch (matcher->op) {
     191            0 :     case BF_MATCHER_EQ:
     192              :     case BF_MATCHER_NE:
     193            0 :         r = _bf_matcher_generate_ip4_net_single(program, matcher);
     194            0 :         break;
     195            0 :     case BF_MATCHER_IN:
     196            0 :         r = _bf_matcher_generate_ip4_net_in(program, matcher);
     197            0 :         break;
     198            0 :     default:
     199            0 :         return bf_err_r(-ENOTSUP, "unsupported operator %s for matcher %s",
     200              :                         bf_matcher_type_to_str(matcher->type),
     201              :                         bf_matcher_op_to_str(matcher->op));
     202              :     }
     203              : 
     204              :     return r;
     205              : }
     206              : 
     207            0 : int bf_matcher_generate_ip4(struct bf_program *program,
     208              :                             const struct bf_matcher *matcher)
     209              : {
     210              :     int r;
     211              : 
     212            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
     213              :         program, BPF_JMP_IMM(BPF_JNE, BPF_REG_7, htobe16(ETH_P_IP), 0));
     214              : 
     215            0 :     EMIT(program,
     216              :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l3_hdr)));
     217              : 
     218            0 :     switch (matcher->type) {
     219            0 :     case BF_MATCHER_IP4_SADDR:
     220              :     case BF_MATCHER_IP4_DADDR:
     221            0 :         r = _bf_matcher_generate_ip4_addr(program, matcher);
     222            0 :         break;
     223            0 :     case BF_MATCHER_IP4_PROTO:
     224            0 :         r = _bf_matcher_generate_ip4_proto(program, matcher);
     225            0 :         break;
     226            0 :     case BF_MATCHER_IP4_SNET:
     227              :     case BF_MATCHER_IP4_DNET:
     228            0 :         r = _bf_matcher_generate_ip4_net(program, matcher);
     229            0 :         break;
     230            0 :     default:
     231            0 :         return bf_err_r(-EINVAL, "unknown matcher type %d", matcher->type);
     232              :     };
     233              : 
     234              :     if (r)
     235              :         return r;
     236              : 
     237              :     return 0;
     238              : }
        

Generated by: LCOV version 2.0-1