LCOV - code coverage report
Current view: top level - bpfilter/cgen/matcher - meta.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 51 0
Test Date: 2025-03-25 15:17:39 Functions: 0.0 % 5 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/meta.h"
       7              : 
       8              : #include <linux/bpf.h>
       9              : #include <linux/bpf_common.h>
      10              : #include <linux/in.h> // NOLINT
      11              : #include <linux/tcp.h>
      12              : #include <linux/udp.h>
      13              : 
      14              : #include <endian.h>
      15              : #include <errno.h>
      16              : #include <stddef.h>
      17              : #include <stdint.h>
      18              : 
      19              : #include "bpfilter/cgen/program.h"
      20              : #include "bpfilter/cgen/swich.h"
      21              : #include "core/logger.h"
      22              : #include "core/matcher.h"
      23              : 
      24              : #include "external/filter.h"
      25              : 
      26            0 : static int _bf_matcher_generate_meta_ifindex(struct bf_program *program,
      27              :                                              const struct bf_matcher *matcher)
      28              : {
      29            0 :     EMIT(program,
      30              :          BPF_LDX_MEM(BPF_H, BPF_REG_1, BPF_REG_10, BF_PROG_CTX_OFF(ifindex)));
      31            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
      32              :         program,
      33              :         BPF_JMP_IMM(BPF_JNE, BPF_REG_1, *(uint32_t *)&matcher->payload, 0));
      34              : 
      35            0 :     return 0;
      36              : }
      37              : 
      38            0 : static int _bf_matcher_generate_meta_l3_proto(struct bf_program *program,
      39              :                                               const struct bf_matcher *matcher)
      40              : {
      41            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
      42              :         program, BPF_JMP_IMM(BPF_JNE, BPF_REG_7,
      43              :                              htobe16(*(uint16_t *)&matcher->payload), 0));
      44              : 
      45            0 :     return 0;
      46              : }
      47              : 
      48            0 : static int _bf_matcher_generate_meta_l4_proto(struct bf_program *program,
      49              :                                               const struct bf_matcher *matcher)
      50              : {
      51            0 :     EMIT_FIXUP_JMP_NEXT_RULE(
      52              :         program,
      53              :         BPF_JMP_IMM(BPF_JNE, BPF_REG_8, *(uint8_t *)&matcher->payload, 0));
      54              : 
      55            0 :     return 0;
      56              : }
      57              : 
      58            0 : static int _bf_matcher_generate_meta_port(struct bf_program *program,
      59              :                                           const struct bf_matcher *matcher)
      60              : {
      61            0 :     _cleanup_bf_swich_ struct bf_swich swich;
      62              :     uint16_t *port = (uint16_t *)&matcher->payload;
      63              :     int r;
      64              : 
      65              :     // Load L4 header address into r6
      66            0 :     EMIT(program,
      67              :          BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l4_hdr)));
      68              : 
      69              :     // Get the packet's port into r1
      70            0 :     swich = bf_swich_get(program, BPF_REG_8);
      71            0 :     EMIT_SWICH_OPTION(&swich, IPPROTO_TCP,
      72              :                       BPF_LDX_MEM(BPF_H, BPF_REG_1, BPF_REG_6,
      73              :                                   matcher->type == BF_MATCHER_META_SPORT ?
      74              :                                       offsetof(struct tcphdr, source) :
      75              :                                       offsetof(struct tcphdr, dest)));
      76            0 :     EMIT_SWICH_OPTION(&swich, IPPROTO_UDP,
      77              :                       BPF_LDX_MEM(BPF_H, BPF_REG_1, BPF_REG_6,
      78              :                                   matcher->type == BF_MATCHER_META_SPORT ?
      79              :                                       offsetof(struct udphdr, source) :
      80              :                                       offsetof(struct udphdr, dest)));
      81            0 :     EMIT_SWICH_DEFAULT(&swich, BPF_MOV64_IMM(BPF_REG_1, 0));
      82              : 
      83            0 :     r = bf_swich_generate(&swich);
      84            0 :     if (r)
      85            0 :         return bf_err_r(r, "failed to generate swich for meta.(s|d)port");
      86              : 
      87              :     // If r1 == 0: no TCP nor UDP header found, jump to the next rule
      88            0 :     EMIT_FIXUP_JMP_NEXT_RULE(program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 0));
      89              : 
      90            0 :     switch (matcher->op) {
      91            0 :     case BF_MATCHER_EQ:
      92            0 :         EMIT_FIXUP_JMP_NEXT_RULE(
      93              :             program, BPF_JMP_IMM(BPF_JNE, BPF_REG_1, htobe16(*port), 0));
      94            0 :         break;
      95            0 :     case BF_MATCHER_NE:
      96            0 :         EMIT_FIXUP_JMP_NEXT_RULE(
      97              :             program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, htobe16(*port), 0));
      98            0 :         break;
      99            0 :     case BF_MATCHER_RANGE:
     100              :         /* Convert the big-endian value stored in the packet into a
     101              :          * little-endian value for x86 and arm before comparing it to the
     102              :          * reference value. This is a JLT/JGT comparison, we need to have the
     103              :          * MSB where the machine expects then. */
     104            0 :         EMIT(program, BPF_BSWAP(BPF_REG_1, 16));
     105            0 :         EMIT_FIXUP_JMP_NEXT_RULE(
     106              :             program, BPF_JMP_IMM(BPF_JLT, BPF_REG_1, port[0], 0));
     107            0 :         EMIT_FIXUP_JMP_NEXT_RULE(
     108              :             program, BPF_JMP_IMM(BPF_JGT, BPF_REG_1, port[1], 0));
     109            0 :         break;
     110            0 :     default:
     111            0 :         return bf_err_r(-EINVAL, "unknown matcher operator '%s' (%d)",
     112              :                         bf_matcher_op_to_str(matcher->op), matcher->op);
     113              :     }
     114              : 
     115              :     return 0;
     116              : }
     117              : 
     118            0 : int bf_matcher_generate_meta(struct bf_program *program,
     119              :                              const struct bf_matcher *matcher)
     120              : {
     121              :     int r;
     122              : 
     123            0 :     switch (matcher->type) {
     124            0 :     case BF_MATCHER_META_IFINDEX:
     125            0 :         r = _bf_matcher_generate_meta_ifindex(program, matcher);
     126            0 :         break;
     127            0 :     case BF_MATCHER_META_L3_PROTO:
     128            0 :         r = _bf_matcher_generate_meta_l3_proto(program, matcher);
     129            0 :         break;
     130            0 :     case BF_MATCHER_META_L4_PROTO:
     131            0 :         r = _bf_matcher_generate_meta_l4_proto(program, matcher);
     132            0 :         break;
     133            0 :     case BF_MATCHER_META_SPORT:
     134              :     case BF_MATCHER_META_DPORT:
     135            0 :         r = _bf_matcher_generate_meta_port(program, matcher);
     136            0 :         break;
     137            0 :     default:
     138            0 :         return bf_err_r(-EINVAL, "unknown matcher type %d", matcher->type);
     139              :     };
     140              : 
     141              :     if (r)
     142              :         return r;
     143              : 
     144              :     return 0;
     145              : }
        

Generated by: LCOV version 2.0-1