-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf bpf filter: Introduce basic BPF filter expression
This implements a tiny parser for the filter expressions used for BPF. Each expression will be converted to struct perf_bpf_filter_expr and be passed to a BPF map. For now, I'd like to start with the very basic comparisons like EQ or GT. The LHS should be a term for sample data and the RHS is a number. The expressions are connected by a comma. For example, period > 10000 ip < 0x1000000000000, cpu == 3 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Hao Luo <haoluo@google.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: James Clark <james.clark@arm.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Song Liu <song@kernel.org> Cc: Stephane Eranian <eranian@google.com> Cc: bpf@vger.kernel.org Link: https://lore.kernel.org/r/20230314234237.3008956-2-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
- Loading branch information
Namhyung Kim
authored and
Arnaldo Carvalho de Melo
committed
Mar 15, 2023
1 parent
6e57f69
commit 990a71e
Showing
5 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#include <stdlib.h> | ||
|
||
#include "util/bpf-filter.h" | ||
#include "util/bpf-filter-flex.h" | ||
#include "util/bpf-filter-bison.h" | ||
|
||
struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(unsigned long sample_flags, | ||
enum perf_bpf_filter_op op, | ||
unsigned long val) | ||
{ | ||
struct perf_bpf_filter_expr *expr; | ||
|
||
expr = malloc(sizeof(*expr)); | ||
if (expr != NULL) { | ||
expr->sample_flags = sample_flags; | ||
expr->op = op; | ||
expr->val = val; | ||
} | ||
return expr; | ||
} | ||
|
||
int perf_bpf_filter__parse(struct list_head *expr_head, const char *str) | ||
{ | ||
YY_BUFFER_STATE buffer; | ||
int ret; | ||
|
||
buffer = perf_bpf_filter__scan_string(str); | ||
|
||
ret = perf_bpf_filter_parse(expr_head); | ||
|
||
perf_bpf_filter__flush_buffer(buffer); | ||
perf_bpf_filter__delete_buffer(buffer); | ||
perf_bpf_filter_lex_destroy(); | ||
|
||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef PERF_UTIL_BPF_FILTER_H | ||
#define PERF_UTIL_BPF_FILTER_H | ||
|
||
#include <linux/list.h> | ||
|
||
enum perf_bpf_filter_op { | ||
PBF_OP_EQ, | ||
PBF_OP_NEQ, | ||
PBF_OP_GT, | ||
PBF_OP_GE, | ||
PBF_OP_LT, | ||
PBF_OP_LE, | ||
PBF_OP_AND, | ||
}; | ||
|
||
struct perf_bpf_filter_expr { | ||
struct list_head list; | ||
enum perf_bpf_filter_op op; | ||
unsigned long sample_flags; | ||
unsigned long val; | ||
}; | ||
|
||
#ifdef HAVE_BPF_SKEL | ||
struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(unsigned long sample_flags, | ||
enum perf_bpf_filter_op op, | ||
unsigned long val); | ||
int perf_bpf_filter__parse(struct list_head *expr_head, const char *str); | ||
#else /* !HAVE_BPF_SKEL */ | ||
static inline int perf_bpf_filter__parse(struct list_head *expr_head __maybe_unused, | ||
const char *str __maybe_unused) | ||
{ | ||
return -ENOSYS; | ||
} | ||
#endif /* HAVE_BPF_SKEL*/ | ||
#endif /* PERF_UTIL_BPF_FILTER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
%option prefix="perf_bpf_filter_" | ||
%option noyywrap | ||
|
||
%{ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <linux/perf_event.h> | ||
|
||
#include "bpf-filter.h" | ||
#include "bpf-filter-bison.h" | ||
|
||
static int sample(unsigned long sample_flag) | ||
{ | ||
perf_bpf_filter_lval.sample = sample_flag; | ||
return BFT_SAMPLE; | ||
} | ||
|
||
static int operator(enum perf_bpf_filter_op op) | ||
{ | ||
perf_bpf_filter_lval.op = op; | ||
return BFT_OP; | ||
} | ||
|
||
static int value(int base) | ||
{ | ||
long num; | ||
|
||
errno = 0; | ||
num = strtoul(perf_bpf_filter_text, NULL, base); | ||
if (errno) | ||
return BFT_ERROR; | ||
|
||
perf_bpf_filter_lval.num = num; | ||
return BFT_NUM; | ||
} | ||
|
||
static int error(const char *str) | ||
{ | ||
printf("perf_bpf_filter: Unexpected filter %s: %s\n", str, perf_bpf_filter_text); | ||
return BFT_ERROR; | ||
} | ||
|
||
%} | ||
|
||
num_dec [0-9]+ | ||
num_hex 0[Xx][0-9a-fA-F]+ | ||
space [ \t]+ | ||
ident [_a-zA-Z][_a-zA-Z0-9]+ | ||
|
||
%% | ||
|
||
{num_dec} { return value(10); } | ||
{num_hex} { return value(16); } | ||
{space} { } | ||
|
||
ip { return sample(PERF_SAMPLE_IP); } | ||
id { return sample(PERF_SAMPLE_ID); } | ||
tid { return sample(PERF_SAMPLE_TID); } | ||
cpu { return sample(PERF_SAMPLE_CPU); } | ||
time { return sample(PERF_SAMPLE_TIME); } | ||
addr { return sample(PERF_SAMPLE_ADDR); } | ||
period { return sample(PERF_SAMPLE_PERIOD); } | ||
txn { return sample(PERF_SAMPLE_TRANSACTION); } | ||
weight { return sample(PERF_SAMPLE_WEIGHT); } | ||
phys_addr { return sample(PERF_SAMPLE_PHYS_ADDR); } | ||
code_pgsz { return sample(PERF_SAMPLE_CODE_PAGE_SIZE); } | ||
data_pgsz { return sample(PERF_SAMPLE_DATA_PAGE_SIZE); } | ||
|
||
"==" { return operator(PBF_OP_EQ); } | ||
"!=" { return operator(PBF_OP_NEQ); } | ||
">" { return operator(PBF_OP_GT); } | ||
"<" { return operator(PBF_OP_LT); } | ||
">=" { return operator(PBF_OP_GE); } | ||
"<=" { return operator(PBF_OP_LE); } | ||
"&" { return operator(PBF_OP_AND); } | ||
|
||
"," { return ','; } | ||
|
||
{ident} { return error("ident"); } | ||
. { return error("input"); } | ||
|
||
%% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
%parse-param {struct list_head *expr_head} | ||
%define parse.error verbose | ||
|
||
%{ | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include <linux/compiler.h> | ||
#include <linux/list.h> | ||
#include "bpf-filter.h" | ||
|
||
static void perf_bpf_filter_error(struct list_head *expr __maybe_unused, | ||
char const *msg) | ||
{ | ||
printf("perf_bpf_filter: %s\n", msg); | ||
} | ||
|
||
%} | ||
|
||
%union | ||
{ | ||
unsigned long num; | ||
unsigned long sample; | ||
enum perf_bpf_filter_op op; | ||
struct perf_bpf_filter_expr *expr; | ||
} | ||
|
||
%token BFT_SAMPLE BFT_OP BFT_ERROR BFT_NUM | ||
%type <expr> filter_term | ||
%destructor { free ($$); } <expr> | ||
%type <sample> BFT_SAMPLE | ||
%type <op> BFT_OP | ||
%type <num> BFT_NUM | ||
|
||
%% | ||
|
||
filter: | ||
filter ',' filter_term | ||
{ | ||
list_add_tail(&$3->list, expr_head); | ||
} | ||
| | ||
filter_term | ||
{ | ||
list_add_tail(&$1->list, expr_head); | ||
} | ||
|
||
filter_term: | ||
BFT_SAMPLE BFT_OP BFT_NUM | ||
{ | ||
$$ = perf_bpf_filter_expr__new($1, $2, $3); | ||
} | ||
|
||
%% |