LCOV - code coverage report
Current view: top level - bpfilter/cgen - tc.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 39 0
Test Date: 2025-02-26 17:59:59 Functions: 0.0 % 5 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/tc.h"
       7              : 
       8              : #include <linux/bpf.h>
       9              : #include <linux/bpf_common.h>
      10              : #include <linux/pkt_cls.h>
      11              : 
      12              : #include <stddef.h>
      13              : 
      14              : #include "bpfilter/cgen/cgen.h"
      15              : #include "bpfilter/cgen/prog/link.h"
      16              : #include "bpfilter/cgen/program.h"
      17              : #include "bpfilter/cgen/stub.h"
      18              : #include "core/btf.h"
      19              : #include "core/flavor.h"
      20              : #include "core/helper.h"
      21              : #include "core/hook.h"
      22              : #include "core/list.h"
      23              : #include "core/logger.h"
      24              : #include "core/verdict.h"
      25              : 
      26              : #include "external/filter.h"
      27              : 
      28              : static int _bf_tc_gen_inline_prologue(struct bf_program *program);
      29              : static int _bf_tc_gen_inline_epilogue(struct bf_program *program);
      30              : static int _bf_tc_get_verdict(enum bf_verdict verdict);
      31              : static int _bf_tc_attach_prog(
      32              :     struct bf_program *new_prog, struct bf_program *old_prog,
      33              :     int (*get_new_link_cb)(struct bf_program *prog, struct bf_link *old_link,
      34              :                            struct bf_link **new_link));
      35              : static int _bf_tc_detach_prog(struct bf_program *program);
      36              : 
      37              : const struct bf_flavor_ops bf_flavor_ops_tc = {
      38              :     .gen_inline_prologue = _bf_tc_gen_inline_prologue,
      39              :     .gen_inline_epilogue = _bf_tc_gen_inline_epilogue,
      40              :     .get_verdict = _bf_tc_get_verdict,
      41              :     .attach_prog = _bf_tc_attach_prog,
      42              :     .detach_prog = _bf_tc_detach_prog,
      43              : };
      44              : 
      45            0 : static int _bf_tc_gen_inline_prologue(struct bf_program *program)
      46              : {
      47              :     int r;
      48              : 
      49            0 :     bf_assert(program);
      50              : 
      51              :     // Calculate the packet size and store it into the runtime context
      52            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
      53              :                               offsetof(struct __sk_buff, data)));
      54            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
      55              :                               offsetof(struct __sk_buff, data_end)));
      56            0 :     EMIT(program, BPF_ALU64_REG(BPF_SUB, BPF_REG_3, BPF_REG_2));
      57            0 :     EMIT(program,
      58              :          BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_3, BF_PROG_CTX_OFF(pkt_size)));
      59              : 
      60              :     /** The @c __sk_buff structure contains two fields related to the interface
      61              :      * index: @c ingress_ifindex and @c ifindex . @c ingress_ifindex is the
      62              :      * interface index the packet has been received on. However, we use
      63              :      * @c ifindex which is the interface index the packet is processed by: if
      64              :      * a packet is redirected locally from interface #1 to interface #2, then
      65              :      * @c ingress_ifindex will contain @c 1 but @c ifindex will contains @c 2 .
      66              :      * For egress, only @c ifindex is used.
      67              :      */
      68            0 :     if ((r = bf_btf_get_field_off("__sk_buff", "ifindex")) < 0)
      69              :         return r;
      70            0 :     EMIT(program, BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, r));
      71            0 :     EMIT(program,
      72              :          BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, BF_PROG_CTX_OFF(ifindex)));
      73              : 
      74            0 :     r = bf_stub_make_ctx_skb_dynptr(program, BPF_REG_1);
      75            0 :     if (r)
      76              :         return r;
      77              : 
      78            0 :     r = bf_stub_parse_l2_ethhdr(program);
      79            0 :     if (r)
      80              :         return r;
      81              : 
      82            0 :     r = bf_stub_parse_l3_hdr(program);
      83            0 :     if (r)
      84              :         return r;
      85              : 
      86            0 :     r = bf_stub_parse_l4_hdr(program);
      87              :     if (r)
      88              :         return r;
      89              : 
      90              :     return 0;
      91              : }
      92              : 
      93            0 : static int _bf_tc_gen_inline_epilogue(struct bf_program *program)
      94              : {
      95              :     UNUSED(program);
      96              : 
      97            0 :     return 0;
      98              : }
      99              : 
     100              : /**
     101              :  * Convert a standard verdict into a return value.
     102              :  *
     103              :  * @param verdict Verdict to convert. Must be valid.
     104              :  * @return TC return code corresponding to the verdict, as an integer.
     105              :  */
     106            0 : static int _bf_tc_get_verdict(enum bf_verdict verdict)
     107              : {
     108            0 :     bf_assert(0 <= verdict && verdict < _BF_TERMINAL_VERDICT_MAX);
     109              : 
     110              :     static const int verdicts[] = {
     111              :         [BF_VERDICT_ACCEPT] = TC_ACT_OK,
     112              :         [BF_VERDICT_DROP] = TC_ACT_SHOT,
     113              :     };
     114              : 
     115              :     static_assert(ARRAY_SIZE(verdicts) == _BF_TERMINAL_VERDICT_MAX);
     116              : 
     117            0 :     return verdicts[verdict];
     118              : }
     119              : 
     120            0 : static int _bf_tc_attach_prog(struct bf_program *new_prog,
     121              :                               struct bf_program *old_prog,
     122              :                               int (*get_new_link_cb)(struct bf_program *prog,
     123              :                                                      struct bf_link *old_link,
     124              :                                                      struct bf_link **new_link))
     125              : {
     126              :     struct bf_link *new_link;
     127              :     struct bf_link *old_link;
     128              :     int new_fd;
     129              :     unsigned int ifindex;
     130              :     int r;
     131              : 
     132            0 :     bf_assert(new_prog && get_new_link_cb);
     133              : 
     134            0 :     old_link = old_prog ? bf_list_get_at(&old_prog->links, 0) : NULL;
     135            0 :     new_fd = new_prog->runtime.prog_fd;
     136            0 :     ifindex = new_prog->runtime.chain->hook_opts.ifindex;
     137              : 
     138            0 :     r = get_new_link_cb(new_prog, old_link, &new_link);
     139            0 :     if (r)
     140            0 :         return bf_err_r(r, "failed to create new TC link");
     141              : 
     142            0 :     if (old_link) {
     143            0 :         r = bf_link_update(new_link, new_fd);
     144            0 :         if (r) {
     145            0 :             return bf_err_r(r,
     146              :                             "failed to update existing link for TC bf_program");
     147              :         }
     148              :     } else {
     149            0 :         r = bf_link_attach_tc(new_link, new_fd, ifindex);
     150            0 :         if (r)
     151            0 :             return bf_err_r(r, "failed to attach TC program");
     152              :     }
     153              : 
     154              :     return 0;
     155              : }
     156              : 
     157              : /**
     158              :  * Detach the TC BPF program.
     159              :  *
     160              :  * @param program Attached TC BPF program. Can't be NULL.
     161              :  * @return 0 on success, negative errno value on failure.
     162              :  */
     163            0 : static int _bf_tc_detach_prog(struct bf_program *program)
     164              : {
     165            0 :     bf_assert(program);
     166              : 
     167            0 :     return bf_link_detach(bf_list_get_at(&program->links, 0));
     168              : }
        

Generated by: LCOV version 2.0-1