dfilter: Add a flag to return field values for the tree root
In many grammatical contexts fields are only tested for existence instead of loading the values into a register, because that's all that is needed to determine if a filter passes or not. Add a dfilter option to load the field values from the tree and return them when a field (including field at a certain protocol layer) is the root of the filter syntax tree. This is useful for columns, especially for parsing columns defined with the layer operator, but it can't completely replace the current custom column handling because we don't yet return exactly which hfinfo was present, if more than one has the same abbreviation, and it's possible for fields with the same abbreviation to have different strings, and hence different "resolved" values. $ ./run/dftest -s "@ip.proto#1" Filter: @ip.proto#1 Syntax tree: 0 FIELD(@ip.proto#[1:1] <FT_BYTES>) Instructions: 0000 CHECK_EXISTS_R ip.proto#[1:1] 0001 RETURN $ ./run/dftest -s "@ip.proto#1" --return-vals Filter: @ip.proto#1 Syntax tree: 0 FIELD(@ip.proto#[1:1] <FT_BYTES>) Instructions: 0000 READ_TREE_R @ip.proto#[1:1] -> R0 0001 NO_OP 0002 RETURN R0 Related to #18588
This commit is contained in:
parent
098462e703
commit
49934c1d14
10
dftest.c
10
dftest.c
|
@ -49,6 +49,7 @@ static int opt_debug_level = 0; /* currently up to 2 */
|
|||
static int opt_flex = 0;
|
||||
static int opt_lemon = 0;
|
||||
static int opt_syntax_tree = 0;
|
||||
static int opt_return_vals = 0;
|
||||
static int opt_timer = 0;
|
||||
static long opt_optimize = 1;
|
||||
static int opt_show_types = 0;
|
||||
|
@ -108,6 +109,7 @@ print_usage(int status)
|
|||
fprintf(fp, " -s, --syntax print syntax tree\n");
|
||||
fprintf(fp, " -m --macros print saved macros\n");
|
||||
fprintf(fp, " -t, --timer print elapsed compilation time\n");
|
||||
fprintf(fp, " -r --return-vals return field values for the tree root\n");
|
||||
fprintf(fp, " -0, --optimize=0 do not optimize (check syntax)\n");
|
||||
fprintf(fp, " --types show field value types\n");
|
||||
/* NOTE: References are loaded during runtime and dftest only does compilation.
|
||||
|
@ -216,6 +218,8 @@ compile_filter(const char *text, dfilter_t **dfp)
|
|||
df_flags |= DF_DEBUG_FLEX;
|
||||
if (opt_lemon)
|
||||
df_flags |= DF_DEBUG_LEMON;
|
||||
if (opt_return_vals)
|
||||
df_flags |= DF_RETURN_VALUES;
|
||||
|
||||
start = g_get_monotonic_time();
|
||||
ok = dfilter_compile_full(text, dfp, &df_err, df_flags, "dftest");
|
||||
|
@ -278,7 +282,7 @@ main(int argc, char **argv)
|
|||
|
||||
ws_init_version_info("DFTest", NULL, NULL);
|
||||
|
||||
const char *optstring = "hvdDflsmtV0";
|
||||
const char *optstring = "hvdDflsmrtV0";
|
||||
static struct ws_option long_options[] = {
|
||||
{ "help", ws_no_argument, 0, 'h' },
|
||||
{ "version", ws_no_argument, 0, 'v' },
|
||||
|
@ -289,6 +293,7 @@ main(int argc, char **argv)
|
|||
{ "macros", ws_no_argument, 0, 'm' },
|
||||
{ "timer", ws_no_argument, 0, 't' },
|
||||
{ "verbose", ws_no_argument, 0, 'V' },
|
||||
{ "return-vals", ws_no_argument, 0, 'r' },
|
||||
{ "optimize", ws_required_argument, 0, 1000 },
|
||||
{ "types", ws_no_argument, 0, 2000 },
|
||||
{ "refs", ws_no_argument, 0, 3000 },
|
||||
|
@ -335,6 +340,9 @@ main(int argc, char **argv)
|
|||
case 't':
|
||||
opt_timer = 1;
|
||||
break;
|
||||
case 'r':
|
||||
opt_return_vals = 1;
|
||||
break;
|
||||
case '0':
|
||||
opt_optimize = 0;
|
||||
break;
|
||||
|
|
|
@ -73,6 +73,9 @@ dfilter_expand(const char *expr, df_error_t **err_ret);
|
|||
#define DF_DEBUG_FLEX (1U << 3)
|
||||
/* Enable debug trace for lemon. */
|
||||
#define DF_DEBUG_LEMON (1U << 4)
|
||||
/* If the root of the syntax tree is a field, load and return the field values.
|
||||
* By default the field is only checked for existence. */
|
||||
#define DF_RETURN_VALUES (1U << 5)
|
||||
|
||||
/* Compiles a string to a dfilter_t.
|
||||
* On success, sets the dfilter* pointed to by dfp
|
||||
|
|
|
@ -657,6 +657,18 @@ gen_exists(dfwork_t *dfw, stnode_t *st_node)
|
|||
}
|
||||
}
|
||||
|
||||
static dfvm_value_t*
|
||||
gen_field(dfwork_t *dfw, stnode_t *st_node)
|
||||
{
|
||||
dfvm_value_t *val1;
|
||||
GSList *jumps = NULL;
|
||||
|
||||
val1 = gen_entity(dfw, st_node, &jumps);
|
||||
g_slist_foreach(jumps, fixup_jumps, dfw);
|
||||
g_slist_free(jumps);
|
||||
return val1;
|
||||
}
|
||||
|
||||
static dfvm_value_t*
|
||||
gen_notzero(dfwork_t *dfw, stnode_t *st_node)
|
||||
{
|
||||
|
@ -805,12 +817,22 @@ static dfvm_value_t*
|
|||
gencode(dfwork_t *dfw, stnode_t *st_node)
|
||||
{
|
||||
dfvm_value_t* val = NULL;
|
||||
/* If the root of the tree is a field, load and return the
|
||||
* values if we were asked to do so. If not, or anywhere
|
||||
* other than the root, just test for existence.
|
||||
*/
|
||||
bool return_val = dfw->flags & DF_RETURN_VALUES;
|
||||
dfw->flags &= ~DF_RETURN_VALUES;
|
||||
switch (stnode_type_id(st_node)) {
|
||||
case STTYPE_TEST:
|
||||
gen_test(dfw, st_node);
|
||||
break;
|
||||
case STTYPE_FIELD:
|
||||
gen_exists(dfw, st_node);
|
||||
if (return_val) {
|
||||
val = gen_field(dfw, st_node);
|
||||
} else {
|
||||
gen_exists(dfw, st_node);
|
||||
}
|
||||
break;
|
||||
case STTYPE_ARITHMETIC:
|
||||
case STTYPE_FUNCTION:
|
||||
|
|
Loading…
Reference in New Issue