LCOV - code coverage report
Current view: top level - bpfilter/cgen - cgroup.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 30 0
Test Date: 2025-05-09 22:39:08 Functions: 0.0 % 3 0

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-2.0-only */
       2              : /*
       3              :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4              :  */
       5              : 
       6              : #include "bpfilter/cgen/cgroup.h"
       7              : 
       8              : #include <linux/bpf_common.h>
       9              : #include <linux/if_ether.h>
      10              : 
      11              : #include <stddef.h>
      12              : #include <stdint.h>
      13              : #include <sys/socket.h>
      14              : 
      15              : #include "bpfilter/cgen/cgen.h"
      16              : #include "bpfilter/cgen/program.h"
      17              : #include "bpfilter/cgen/stub.h"
      18              : #include "bpfilter/cgen/swich.h"
      19              : #include "core/btf.h"
      20              : #include "core/flavor.h"
      21              : #include "core/helper.h"
      22              : #include "core/verdict.h"
      23              : #include "linux/bpf.h"
      24              : 
      25              : #include "external/filter.h"
      26              : 
      27              : // Forward definition to avoid headers clusterfuck.
      28              : uint16_t htons(uint16_t hostshort);
      29              : 
      30            0 : static int _bf_cgroup_gen_inline_prologue(struct bf_program *program)
      31              : {
      32              :     int offset;
      33              :     int r;
      34              : 
      35            0 :     bf_assert(program);
      36              : 
      37              :     // Calculate the packet size (+ETH_HLEN) and store it into the runtime context
      38            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
      39              :                               offsetof(struct __sk_buff, data)));
      40            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
      41              :                               offsetof(struct __sk_buff, data_end)));
      42            0 :     EMIT(program, BPF_ALU64_REG(BPF_SUB, BPF_REG_3, BPF_REG_2));
      43            0 :     EMIT(program, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, ETH_HLEN));
      44            0 :     EMIT(program,
      45              :          BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_3, BF_PROG_CTX_OFF(pkt_size)));
      46              : 
      47              :     /** The @c __sk_buff structure contains two fields related to the interface
      48              :      * index: @c ingress_ifindex and @c ifindex . @c ingress_ifindex is the
      49              :      * interface index the packet has been received on. However, we use
      50              :      * @c ifindex which is the interface index the packet is processed by: if
      51              :      * a packet is redirected locally from interface #1 to interface #2, then
      52              :      * @c ingress_ifindex will contain @c 1 but @c ifindex will contains @c 2 .
      53              :      * For egress, only @c ifindex is used.
      54              :      */
      55            0 :     if ((r = bf_btf_get_field_off("__sk_buff", "ifindex")) < 0)
      56              :         return r;
      57            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, r));
      58            0 :     EMIT(program,
      59              :          BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_CTX_OFF(ifindex)));
      60              : 
      61              :     /* BPF_PROG_TYPE_CGROUP_SKB doesn't provide access the the Ethernet header,
      62              :      * so we can't parse it and discover the L3 protocol ID.
      63              :      * Instead, we use the __sk_buff.family value and convert it to the
      64              :      * corresponding ethertype. */
      65            0 :     if ((offset = bf_btf_get_field_off("__sk_buff", "family")) < 0)
      66              :         return offset;
      67            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offset));
      68              : 
      69              :     {
      70            0 :         _cleanup_bf_swich_ struct bf_swich swich =
      71            0 :             bf_swich_get(program, BPF_REG_2);
      72              : 
      73            0 :         EMIT_SWICH_OPTION(&swich, AF_INET,
      74              :                           BPF_MOV64_IMM(BPF_REG_7, htons(ETH_P_IP)));
      75            0 :         EMIT_SWICH_OPTION(&swich, AF_INET6,
      76              :                           BPF_MOV64_IMM(BPF_REG_7, htons(ETH_P_IPV6)));
      77            0 :         EMIT_SWICH_DEFAULT(&swich, BPF_MOV64_IMM(BPF_REG_7, 0));
      78              : 
      79            0 :         r = bf_swich_generate(&swich);
      80            0 :         if (r)
      81              :             return r;
      82              :     }
      83              : 
      84            0 :     EMIT(program, BPF_ST_MEM(BPF_W, BPF_REG_10, BF_PROG_CTX_OFF(l3_offset), 0));
      85              : 
      86            0 :     r = bf_stub_make_ctx_skb_dynptr(program, BPF_REG_1);
      87            0 :     if (r)
      88              :         return r;
      89              : 
      90            0 :     r = bf_stub_parse_l3_hdr(program);
      91            0 :     if (r)
      92              :         return r;
      93              : 
      94            0 :     r = bf_stub_parse_l4_hdr(program);
      95              :     if (r)
      96              :         return r;
      97              : 
      98              :     return 0;
      99              : }
     100              : 
     101            0 : static int _bf_cgroup_gen_inline_epilogue(struct bf_program *program)
     102              : {
     103              :     UNUSED(program);
     104              : 
     105            0 :     return 0;
     106              : }
     107              : 
     108              : /**
     109              :  * Convert a standard verdict into a return value.
     110              :  *
     111              :  * @param verdict Verdict to convert. Must be valid.
     112              :  * @return TC return code corresponding to the verdict, as an integer.
     113              :  */
     114            0 : static int _bf_cgroup_get_verdict(enum bf_verdict verdict)
     115              : {
     116            0 :     bf_assert(0 <= verdict && verdict < _BF_TERMINAL_VERDICT_MAX);
     117              : 
     118              :     static const int verdicts[] = {
     119              :         [BF_VERDICT_ACCEPT] = 1,
     120              :         [BF_VERDICT_DROP] = 0,
     121              :     };
     122              : 
     123              :     static_assert(ARRAY_SIZE(verdicts) == _BF_TERMINAL_VERDICT_MAX);
     124              : 
     125            0 :     return verdicts[verdict];
     126              : }
     127              : 
     128              : const struct bf_flavor_ops bf_flavor_ops_cgroup = {
     129              :     .gen_inline_prologue = _bf_cgroup_gen_inline_prologue,
     130              :     .gen_inline_epilogue = _bf_cgroup_gen_inline_epilogue,
     131              :     .get_verdict = _bf_cgroup_get_verdict,
     132              : };
        

Generated by: LCOV version 2.0-1