LCOV - code coverage report
Current view: top level - core - rule.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 68.0 % 97 66
Test Date: 2025-08-19 17:27:08 Functions: 62.5 % 8 5

            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 "core/rule.h"
       7              : 
       8              : #include <errno.h>
       9              : #include <stdlib.h>
      10              : #include <string.h>
      11              : 
      12              : #include "core/dump.h"
      13              : #include "core/helper.h"
      14              : #include "core/list.h"
      15              : #include "core/logger.h"
      16              : #include "core/marsh.h"
      17              : #include "core/matcher.h"
      18              : #include "core/runtime.h"
      19              : #include "core/verdict.h"
      20              : 
      21              : static const char *_bf_pkthdr_strs[] = {
      22              :     [BF_PKTHDR_LINK] = "link",
      23              :     [BF_PKTHDR_INTERNET] = "internet",
      24              :     [BF_PKTHDR_TRANSPORT] = "transport",
      25              : };
      26              : static_assert_enum_mapping(_bf_pkthdr_strs, _BF_PKTHDR_MAX);
      27              : 
      28            0 : const char *bf_pkthdr_to_str(enum bf_pkthdr hdr)
      29              : {
      30            0 :     bf_assert(hdr < _BF_PKTHDR_MAX);
      31              : 
      32            0 :     return _bf_pkthdr_strs[hdr];
      33              : }
      34              : 
      35            0 : int bf_pkthdr_from_str(const char *str, enum bf_pkthdr *hdr)
      36              : {
      37            0 :     bf_assert(str);
      38              : 
      39            0 :     for (int i = 0; i < _BF_PKTHDR_MAX; ++i) {
      40            0 :         if (bf_streq_i(str, _bf_pkthdr_strs[i])) {
      41            0 :             *hdr = (enum bf_pkthdr)i;
      42            0 :             return 0;
      43              :         }
      44              :     }
      45              : 
      46              :     return -EINVAL;
      47              : }
      48              : 
      49           17 : int bf_rule_new(struct bf_rule **rule)
      50              : {
      51              :     struct bf_rule *_rule;
      52              : 
      53           17 :     bf_assert(rule);
      54              : 
      55           16 :     _rule = calloc(1, sizeof(*_rule));
      56           16 :     if (!_rule)
      57              :         return -ENOMEM;
      58              : 
      59           15 :     bf_list_init(
      60              :         &_rule->matchers,
      61           15 :         (bf_list_ops[]) {{.free = (bf_list_ops_free)bf_matcher_free,
      62              :                           .marsh = (bf_list_ops_marsh)bf_matcher_marsh}});
      63              : 
      64           15 :     *rule = _rule;
      65              : 
      66           15 :     return 0;
      67              : }
      68              : 
      69           34 : void bf_rule_free(struct bf_rule **rule)
      70              : {
      71           34 :     bf_assert(rule);
      72              : 
      73           33 :     if (!*rule)
      74              :         return;
      75              : 
      76           15 :     bf_list_clean(&(*rule)->matchers);
      77              : 
      78           15 :     free(*rule);
      79           15 :     *rule = NULL;
      80              : }
      81              : 
      82            8 : int bf_rule_marsh(const struct bf_rule *rule, struct bf_marsh **marsh)
      83              : {
      84            6 :     _free_bf_marsh_ struct bf_marsh *_marsh = NULL;
      85              :     int r;
      86              : 
      87            8 :     bf_assert(rule);
      88            7 :     bf_assert(marsh);
      89              : 
      90            6 :     r = bf_marsh_new(&_marsh, NULL, 0);
      91            6 :     if (r < 0)
      92              :         return r;
      93              : 
      94            5 :     r = bf_marsh_add_child_raw(&_marsh, &rule->index, sizeof(rule->index));
      95            5 :     if (r < 0)
      96              :         return r;
      97              : 
      98              :     {
      99            5 :         _free_bf_marsh_ struct bf_marsh *child = NULL;
     100              : 
     101            5 :         r = bf_list_marsh(&rule->matchers, &child);
     102            5 :         if (r < 0)
     103              :             return r;
     104              : 
     105            5 :         r = bf_marsh_add_child_obj(&_marsh, child);
     106            5 :         if (r)
     107              :             return r;
     108              :     }
     109              : 
     110            5 :     r |= bf_marsh_add_child_raw(&_marsh, &rule->log, sizeof(rule->log));
     111            5 :     r |= bf_marsh_add_child_raw(&_marsh, &rule->counters,
     112              :                                 sizeof(rule->counters));
     113            5 :     r |= bf_marsh_add_child_raw(&_marsh, &rule->verdict,
     114              :                                 sizeof(enum bf_verdict));
     115            5 :     if (r)
     116            0 :         return bf_err_r(r, "Failed to serialize rule");
     117              : 
     118            5 :     *marsh = TAKE_PTR(_marsh);
     119              : 
     120            5 :     return 0;
     121              : }
     122              : 
     123            7 : int bf_rule_unmarsh(const struct bf_marsh *marsh, struct bf_rule **rule)
     124              : {
     125            5 :     _free_bf_rule_ struct bf_rule *_rule = NULL;
     126              :     struct bf_marsh *rule_elem = NULL;
     127              :     int r;
     128              : 
     129            7 :     bf_assert(marsh);
     130            6 :     bf_assert(rule);
     131              : 
     132            5 :     r = bf_rule_new(&_rule);
     133            5 :     if (r < 0)
     134              :         return r;
     135              : 
     136            5 :     if (!(rule_elem = bf_marsh_next_child(marsh, NULL)))
     137              :         return -EINVAL;
     138            5 :     memcpy(&_rule->index, rule_elem->data, sizeof(_rule->index));
     139              : 
     140            5 :     if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
     141              :         return -EINVAL;
     142              : 
     143              :     {
     144              :         struct bf_marsh *matcher_elem = NULL;
     145              : 
     146           27 :         while ((matcher_elem = bf_marsh_next_child(rule_elem, matcher_elem))) {
     147            0 :             _free_bf_matcher_ struct bf_matcher *matcher = NULL;
     148              : 
     149           22 :             r = bf_matcher_new_from_marsh(&matcher, matcher_elem);
     150           22 :             if (r)
     151              :                 return r;
     152              : 
     153           22 :             r = bf_list_add_tail(&_rule->matchers, matcher);
     154           22 :             if (r)
     155              :                 return r;
     156              : 
     157           22 :             TAKE_PTR(matcher);
     158              :         }
     159              :     }
     160              : 
     161            5 :     if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
     162              :         return -EINVAL;
     163            5 :     memcpy(&_rule->log, rule_elem->data, sizeof(_rule->log));
     164              : 
     165            5 :     if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
     166              :         return -EINVAL;
     167            5 :     memcpy(&_rule->counters, rule_elem->data, sizeof(_rule->counters));
     168              : 
     169            5 :     if (!(rule_elem = bf_marsh_next_child(marsh, rule_elem)))
     170              :         return -EINVAL;
     171            5 :     memcpy(&_rule->verdict, rule_elem->data, sizeof(_rule->verdict));
     172              : 
     173            5 :     if (bf_marsh_next_child(marsh, rule_elem))
     174            0 :         bf_warn("codegen marsh has more children than expected");
     175              : 
     176            5 :     *rule = TAKE_PTR(_rule);
     177              : 
     178            5 :     return 0;
     179              : }
     180              : 
     181            0 : void bf_rule_dump(const struct bf_rule *rule, prefix_t *prefix)
     182              : {
     183            0 :     bf_assert(rule);
     184            0 :     bf_assert(prefix);
     185              : 
     186            0 :     DUMP(prefix, "struct bf_rule at %p", rule);
     187              : 
     188            0 :     bf_dump_prefix_push(prefix);
     189              : 
     190            0 :     DUMP(prefix, "index: %u", rule->index);
     191              : 
     192              :     // Matchers
     193            0 :     DUMP(prefix, "matchers: %lu", bf_list_size(&rule->matchers));
     194            0 :     bf_dump_prefix_push(prefix);
     195            0 :     bf_list_foreach (&rule->matchers, matcher_node) {
     196            0 :         struct bf_matcher *matcher = bf_list_node_get_data(matcher_node);
     197              : 
     198            0 :         if (bf_list_is_tail(&rule->matchers, matcher_node))
     199            0 :             bf_dump_prefix_last(prefix);
     200              : 
     201            0 :         bf_matcher_dump(matcher, prefix);
     202              :     }
     203            0 :     bf_dump_prefix_pop(prefix);
     204              : 
     205            0 :     DUMP(prefix, "log: %02x", rule->log);
     206            0 :     DUMP(prefix, "counters: %s", rule->counters ? "yes" : "no");
     207            0 :     DUMP(bf_dump_prefix_last(prefix), "verdict: %s",
     208              :          bf_verdict_to_str(rule->verdict));
     209              : 
     210            0 :     bf_dump_prefix_pop(prefix);
     211            0 : }
     212              : 
     213           20 : int bf_rule_add_matcher(struct bf_rule *rule, enum bf_matcher_type type,
     214              :                         enum bf_matcher_op op, const void *payload,
     215              :                         size_t payload_len)
     216              : {
     217           20 :     _free_bf_matcher_ struct bf_matcher *matcher = NULL;
     218              :     int r;
     219              : 
     220           20 :     bf_assert(rule);
     221              : 
     222           20 :     r = bf_matcher_new(&matcher, type, op, payload, payload_len);
     223           20 :     if (r)
     224              :         return r;
     225              : 
     226           20 :     r = bf_list_add_tail(&rule->matchers, matcher);
     227           20 :     if (r)
     228              :         return r;
     229              : 
     230           20 :     TAKE_PTR(matcher);
     231              : 
     232           20 :     return 0;
     233              : }
        

Generated by: LCOV version 2.0-1