Skip to content

Commit 47e22e8

Browse files
committed
daemon: cgen: use float for meta.probability matcher
Unify meta.probability and meta.flow_probability to share the same floating-point parsing and printing logic, replacing the integer-only code path. This allows meta.probability to accept fractional percentages (e.g., "33.33%") and removes duplicate parser/printer functions.
1 parent 0703e67 commit 47e22e8

File tree

6 files changed

+40
-52
lines changed

6 files changed

+40
-52
lines changed

doc/usage/bfcli.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ Meta
539539
- ``meta.probability``
540540
- ``eq``
541541
- ``$PROBABILITY``
542-
- ``$PROBABILITY`` is a valid decimal percentage value (i.e., within [0%, 100%]).
542+
- ``$PROBABILITY`` is a floating-point percentage value (i.e., within [0%, 100%], e.g., "50%" or "33.33%").
543543
* - :rspan:`1` Mark
544544
- :rspan:`1` ``meta.mark``
545545
- ``eq``

src/bfcli/lexer.l

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
%s STATE_MATCHER_META_FLOW_HASH
3333
%s STATE_MATCHER_L4_PROTO
3434
%s STATE_MATCHER_META_PROBA
35-
%s STATE_MATCHER_META_FLOW_PROBA
3635
%s STATE_MATCHER_IPV4_ADDR
3736
%s STATE_MATCHER_IP4_NET
3837
%s STATE_MATCHER_IP4_DSCP
@@ -155,17 +154,8 @@ ip6\.nexthdr { BEGIN(STATE_MATCHER_L4_PROTO); yylval.sval = strdup(yytext); r
155154
}
156155

157156
meta\.probability { BEGIN(STATE_MATCHER_META_PROBA); yylval.sval = strdup(yytext); return MATCHER_TYPE; }
157+
meta\.flow_probability { BEGIN(STATE_MATCHER_META_PROBA); yylval.sval = strdup(yytext); return MATCHER_TYPE; }
158158
<STATE_MATCHER_META_PROBA>{
159-
(eq) { yylval.sval = strdup(yytext); return MATCHER_OP; }
160-
{int}% {
161-
BEGIN(INITIAL);
162-
yylval.sval = strdup(yytext);
163-
return RAW_PAYLOAD;
164-
}
165-
}
166-
167-
meta\.flow_probability { BEGIN(STATE_MATCHER_META_FLOW_PROBA); yylval.sval = strdup(yytext); return MATCHER_TYPE; }
168-
<STATE_MATCHER_META_FLOW_PROBA>{
169159
(eq) { yylval.sval = strdup(yytext); return MATCHER_OP; }
170160
{float}% {
171161
BEGIN(INITIAL);

src/bpfilter/cgen/matcher/meta.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ static int
6767
_bf_matcher_generate_meta_probability(struct bf_program *program,
6868
const struct bf_matcher *matcher)
6969
{
70-
uint8_t proba = *(uint8_t *)bf_matcher_payload(matcher);
70+
float proba = *(float *)bf_matcher_payload(matcher);
7171

7272
EMIT(program, BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32));
7373
EMIT_FIXUP_JMP_NEXT_RULE(
7474
program,
7575
BPF_JMP_IMM(BPF_JGT, BPF_REG_0,
76-
(uint32_t)((uint64_t)UINT32_MAX * (proba / 100.0)), 0));
76+
(uint32_t)((double)UINT32_MAX * (proba / 100.0)), 0));
7777

7878
return 0;
7979
}

src/libbpfilter/matcher.c

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -377,36 +377,6 @@ static int _bf_parse_probability(enum bf_matcher_type type,
377377
assert(payload);
378378
assert(raw_payload);
379379

380-
unsigned long proba;
381-
char *endptr;
382-
383-
proba = strtoul(raw_payload, &endptr, BF_BASE_10);
384-
if (endptr[0] == '%' && endptr[1] == '\0' && proba <= 100) {
385-
*(uint8_t *)payload = (uint8_t)proba;
386-
return 0;
387-
}
388-
389-
bf_err(
390-
"\"%s %s\" expects a valid decimal percentage value (i.e., within [0%%, 100%%]), not '%s'",
391-
bf_matcher_type_to_str(type), bf_matcher_op_to_str(op), raw_payload);
392-
393-
return -EINVAL;
394-
}
395-
396-
void _bf_print_probability(const void *payload)
397-
{
398-
assert(payload);
399-
400-
(void)fprintf(stdout, "%" PRIu8 "%%", *(uint8_t *)payload);
401-
}
402-
403-
static int _bf_parse_flow_probability(enum bf_matcher_type type,
404-
enum bf_matcher_op op, void *payload,
405-
const char *raw_payload)
406-
{
407-
assert(payload);
408-
assert(raw_payload);
409-
410380
double proba;
411381
char *endptr;
412382

@@ -424,7 +394,7 @@ static int _bf_parse_flow_probability(enum bf_matcher_type type,
424394
return -EINVAL;
425395
}
426396

427-
static void _bf_print_flow_probability(const void *payload)
397+
void _bf_print_probability(const void *payload)
428398
{
429399
assert(payload);
430400

@@ -928,7 +898,7 @@ static struct bf_matcher_meta _bf_matcher_metas[_BF_MATCHER_TYPE_MAX] = {
928898
.layer = BF_MATCHER_NO_LAYER,
929899
.ops =
930900
{
931-
BF_MATCHER_OPS(BF_MATCHER_EQ, sizeof(uint8_t),
901+
BF_MATCHER_OPS(BF_MATCHER_EQ, sizeof(float),
932902
_bf_parse_probability,
933903
_bf_print_probability),
934904
},
@@ -971,8 +941,8 @@ static struct bf_matcher_meta _bf_matcher_metas[_BF_MATCHER_TYPE_MAX] = {
971941
.ops =
972942
{
973943
BF_MATCHER_OPS(BF_MATCHER_EQ, sizeof(float),
974-
_bf_parse_flow_probability,
975-
_bf_print_flow_probability),
944+
_bf_parse_probability,
945+
_bf_print_probability),
976946
},
977947
},
978948
[BF_MATCHER_IP4_SADDR] =

tests/e2e/matchers/meta_probability.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@
55
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 0% counter DROP"
66
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 50% counter DROP"
77
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 100% counter DROP"
8+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 33.33% counter DROP"
9+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 0.1% counter DROP"
10+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 99.99% counter DROP"
11+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 50.0% counter DROP"
12+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 0.00% counter DROP"
13+
bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 100.00% counter DROP"
814

915
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 0 counter DROP")
1016
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq -10% counter DROP")
1117
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 1000 counter DROP")
1218
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 1000% counter DROP")
13-
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 15.5% counter DROP")
19+
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq 100.01% counter DROP")
1420
(! bfcli ruleset set --dry-run --from-str "chain xdp BF_HOOK_XDP ACCEPT rule meta.probability eq teapot counter DROP")

tests/unit/libbpfilter/matcher.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -554,23 +554,41 @@ static void meta_probability(void **state)
554554
assert_ok(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
555555
BF_MATCHER_EQ, "0%"));
556556
assert_non_null(matcher);
557-
assert_int_equal(*(uint8_t *)bf_matcher_payload(matcher), 0);
557+
assert_true(*(float *)bf_matcher_payload(matcher) == 0.0f);
558558
bf_matcher_dump(matcher, &prefix);
559559
bf_matcher_free(&matcher);
560560

561561
// Test with 50%
562562
assert_ok(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
563563
BF_MATCHER_EQ, "50%"));
564564
assert_non_null(matcher);
565-
assert_int_equal(*(uint8_t *)bf_matcher_payload(matcher), 50);
565+
assert_true(*(float *)bf_matcher_payload(matcher) == 50.0f);
566566
bf_matcher_dump(matcher, &prefix);
567567
bf_matcher_free(&matcher);
568568

569569
// Test with 100%
570570
assert_ok(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
571571
BF_MATCHER_EQ, "100%"));
572572
assert_non_null(matcher);
573-
assert_int_equal(*(uint8_t *)bf_matcher_payload(matcher), 100);
573+
assert_true(*(float *)bf_matcher_payload(matcher) == 100.0f);
574+
bf_matcher_dump(matcher, &prefix);
575+
bf_matcher_free(&matcher);
576+
577+
// Test with floating-point value
578+
assert_ok(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
579+
BF_MATCHER_EQ, "33.33%"));
580+
assert_non_null(matcher);
581+
assert_true(*(float *)bf_matcher_payload(matcher) > 33.32f);
582+
assert_true(*(float *)bf_matcher_payload(matcher) < 33.34f);
583+
bf_matcher_dump(matcher, &prefix);
584+
bf_matcher_free(&matcher);
585+
586+
// Test with small floating-point value
587+
assert_ok(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
588+
BF_MATCHER_EQ, "0.1%"));
589+
assert_non_null(matcher);
590+
assert_true(*(float *)bf_matcher_payload(matcher) > 0.09f);
591+
assert_true(*(float *)bf_matcher_payload(matcher) < 0.11f);
574592
bf_matcher_dump(matcher, &prefix);
575593
}
576594

@@ -584,6 +602,10 @@ static void meta_probability_invalid(void **state)
584602
assert_err(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
585603
BF_MATCHER_EQ, "101%"));
586604

605+
// Test with value slightly over 100%
606+
assert_err(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
607+
BF_MATCHER_EQ, "100.01%"));
608+
587609
// Test without % sign
588610
assert_err(bf_matcher_new_from_raw(&matcher, BF_MATCHER_META_PROBABILITY,
589611
BF_MATCHER_EQ, "50"));

0 commit comments

Comments
 (0)