dfilter: Allow writing references without curly braces

Allow references without braces, for a less cluttered syntax:

    Filter:
     frame.number > $frame.number

    Instructions:
     0000 READ_TREE        frame.number     -> R0
     0001 IF_FALSE_GOTO    5
     0002 READ_REFERENCE   ${frame.number}  -> R1
     0003 IF_FALSE_GOTO    5
     0004 ANY_GT           R0 > R1
     0005 RETURN

The original syntax of ${reference} came from macros but the
braces don't add much. In any case they are still allowed.
This commit is contained in:
João Valverde 2023-10-30 19:24:13 +00:00
parent db49708b17
commit 813be7fe50
4 changed files with 42 additions and 5 deletions

View File

@ -61,6 +61,9 @@ The following features are new (or have been significantly updated) since versio
"bool_test(some.field)" instead of having to write "bool_test(some.field) == True"
(both forms are now valid).
** Display filter references can be written without curly braces. It
is now possible to write `$frame.number` instead of `${frame.number}` for example.
* Display filter autocompletions now also include display filter functions.
//=== Removed Features and Support

View File

@ -540,13 +540,17 @@ Do not confuse this usage of curly brackets with set membership.
=== Protocol field references
A variable using a sigil with the form ${some.proto.field} is called a field
A variable using a sigil with the form $some.proto.field or ${some.proto.field} is called a field
reference. A field reference is a field value read from the currently
selected frame in the GUI. This is useful to build dynamic filters such as,
frames since the last five minutes to the selected frame:
frame.time_relative >= ${frame.time_relative} - 300
or more simply
frame.time_relative >= $frame.time_relative - 300
Field references share a similar notation to macros but are distinct
syntactical elements in the filter language.

View File

@ -20,6 +20,9 @@
#pragma warning(disable:4671)
#endif
static stnode_t *
new_reference(dfsyntax_t *dfs, stnode_t *node);
static stnode_t *
new_function(dfsyntax_t *dfs, stnode_t *node);
@ -205,18 +208,35 @@ rawable_field(X) ::= ATSIGN(A) layered_field(F).
stnode_free(A);
}
%code {
static stnode_t *
new_reference(dfsyntax_t *dfs _U_, stnode_t *node)
{
/* convert field to reference */
stnode_t *ref = stnode_new(STTYPE_REFERENCE, sttype_field_hfinfo(node), NULL, stnode_location(node));
sttype_field_set_drange(ref, sttype_field_drange_steal(node));
sttype_field_set_raw(ref, sttype_field_raw(node));
return ref;
}
}
reference(X) ::= DOLLAR(D) LBRACE rawable_field(F) RBRACE(R).
{
/* convert field to reference */
X = stnode_new(STTYPE_REFERENCE, sttype_field_hfinfo(F), NULL, stnode_location(F));
sttype_field_set_drange(X, sttype_field_drange_steal(F));
sttype_field_set_raw(X, sttype_field_raw(F));
X = new_reference(dfs, F);
stnode_merge_location(X, D, R);
stnode_free(F);
stnode_free(D);
stnode_free(R);
}
reference(X) ::= DOLLAR(D) rawable_field(F).
{
X = new_reference(dfs, F);
stnode_merge_location(X, D, F);
stnode_free(F);
stnode_free(D);
}
entity(E) ::= atom(A). { E = A; }
entity(E) ::= slice(R). { E = R; }
entity(E) ::= function(F). { E = F; }

View File

@ -343,6 +343,16 @@ class TestDfilterFieldReference:
# select frame 1, expect 1 frames out of 2.
checkDFilterCountWithSelectedFrame(dfilter, 1, 1)
def test_ref_3(self, checkDFilterCountWithSelectedFrame):
dfilter = 'frame.number < $frame.number'
# select frame 2, expect 1 frames out of 2.
checkDFilterCountWithSelectedFrame(dfilter, 1, 2)
def test_ref_4(self, checkDFilterCountWithSelectedFrame):
dfilter = 'ip.src#3 == $ip.src#4'
# select frame 1, expect 1 frames out of 2.
checkDFilterCountWithSelectedFrame(dfilter, 1, 1)
class TestDfilterLayer:
trace_file = "ipoipoip.pcap"