Hi Phil, On Fri, Aug 24, 2018 at 01:26:57PM +0200, Phil Sutter wrote: > Of all possible TCP flags, 'ecn' is special since it is recognized by > lex as a keyword (there is a a field in IPv4 and IPv6 headers with the > same name). Therefore it is listed in keyword_expr, but that was > sufficient for RHS only. The following statement reproduces the issue: > > | tcp flags & (syn | ecn) == (syn | ecn) > > The solution is to limit binop expressions to accept an RHS expression > on RHS ("real" LHS expressions don't make much sense there anyway), > which then allows keyword_expr to occur there. In order to maintain the > recursive behaviour if braces are present, allow primary_rhs_expr to > consist of a basic_rhs_expr enclosed in braces. This in turn requires > for braced RHS part in relational_expr to be dropped, otherwise bison > complains about shift/reduce conflict. Sorry, I think I misunderstood this email. The following is: nft add rule x y tcp flags & (syn | ecn) == (syn | ecn) Same thing with: nft add rule x y 'tcp flags and (fin | syn | rst | psh | ack | urg | ecn | cwr) eq (fin | syn | rst | psh | ack | urg | ecn | cwr) So, what is what we don't support anymore after your patch? Thanks! > Signed-off-by: Phil Sutter <phil@xxxxxx> > --- > src/parser_bison.y | 15 ++++++--------- > tests/py/inet/tcp.t | 1 + > tests/py/inet/tcp.t.json | 23 +++++++++++++++++++++++ > tests/py/inet/tcp.t.json.output | 16 ++++++++++++++++ > tests/py/inet/tcp.t.payload | 8 ++++++++ > 5 files changed, 54 insertions(+), 9 deletions(-) > > diff --git a/src/parser_bison.y b/src/parser_bison.y > index bc6f72779dd70..7114843cb0b16 100644 > --- a/src/parser_bison.y > +++ b/src/parser_bison.y > @@ -3043,32 +3043,32 @@ osf_expr : OSF NAME > ; > > shift_expr : primary_expr > - | shift_expr LSHIFT primary_expr > + | shift_expr LSHIFT primary_rhs_expr > { > $$ = binop_expr_alloc(&@$, OP_LSHIFT, $1, $3); > } > - | shift_expr RSHIFT primary_expr > + | shift_expr RSHIFT primary_rhs_expr > { > $$ = binop_expr_alloc(&@$, OP_RSHIFT, $1, $3); > } > ; > > and_expr : shift_expr > - | and_expr AMPERSAND shift_expr > + | and_expr AMPERSAND shift_rhs_expr > { > $$ = binop_expr_alloc(&@$, OP_AND, $1, $3); > } > ; > > exclusive_or_expr : and_expr > - | exclusive_or_expr CARET and_expr > + | exclusive_or_expr CARET and_rhs_expr > { > $$ = binop_expr_alloc(&@$, OP_XOR, $1, $3); > } > ; > > inclusive_or_expr : exclusive_or_expr > - | inclusive_or_expr '|' exclusive_or_expr > + | inclusive_or_expr '|' exclusive_or_rhs_expr > { > $$ = binop_expr_alloc(&@$, OP_OR, $1, $3); > } > @@ -3347,10 +3347,6 @@ relational_expr : expr /* implicit */ rhs_expr > { > $$ = relational_expr_alloc(&@2, $2, $1, $3); > } > - | expr relational_op '(' rhs_expr ')' > - { > - $$ = relational_expr_alloc(&@2, $2, $1, $4); > - } > ; > > list_rhs_expr : basic_rhs_expr COMMA basic_rhs_expr > @@ -3534,6 +3530,7 @@ primary_rhs_expr : symbol_expr { $$ = $1; } > BYTEORDER_HOST_ENDIAN, > sizeof(data) * BITS_PER_BYTE, &data); > } > + | '(' basic_rhs_expr ')' { $$ = $2; } > ; > > relational_op : EQ { $$ = OP_EQ; } > diff --git a/tests/py/inet/tcp.t b/tests/py/inet/tcp.t > index d66ba8438a32f..f96e3634f41ed 100644 > --- a/tests/py/inet/tcp.t > +++ b/tests/py/inet/tcp.t > @@ -78,6 +78,7 @@ tcp flags cwr;ok > tcp flags != cwr;ok > tcp flags == syn;ok > tcp flags & (syn|fin) == (syn|fin);ok;tcp flags & (fin | syn) == fin | syn > +tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr;ok;tcp flags == 0xff > > tcp window 22222;ok > tcp window 22;ok > diff --git a/tests/py/inet/tcp.t.json b/tests/py/inet/tcp.t.json > index 5744e5942eb12..babe592089259 100644 > --- a/tests/py/inet/tcp.t.json > +++ b/tests/py/inet/tcp.t.json > @@ -1101,6 +1101,29 @@ > } > ] > > +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr > +[ > + { > + "match": { > + "left": { > + "&": [ > + { > + "payload": { > + "field": "flags", > + "protocol": "tcp" > + } > + }, > + { > + "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] > + } > + ] > + }, > + "op": "==", > + "right": { "|": [ "fin", { "|": [ "syn", { "|": [ "rst", { "|": [ "psh", { "|": [ "ack", { "|": [ "urg", { "|": [ "ecn", "cwr" ] } ] } ] } ] } ] } ] } ] } > + } > + } > +] > + > # tcp window 22222 > [ > { > diff --git a/tests/py/inet/tcp.t.json.output b/tests/py/inet/tcp.t.json.output > index 50282ec530080..143490f7322d2 100644 > --- a/tests/py/inet/tcp.t.json.output > +++ b/tests/py/inet/tcp.t.json.output > @@ -139,3 +139,19 @@ > } > ] > > +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr > +[ > + { > + "match": { > + "left": { > + "payload": { > + "field": "flags", > + "protocol": "tcp" > + } > + }, > + "op": "==", > + "right": 255 > + } > + } > +] > + > diff --git a/tests/py/inet/tcp.t.payload b/tests/py/inet/tcp.t.payload > index 09538aed746c9..2390a24ead15c 100644 > --- a/tests/py/inet/tcp.t.payload > +++ b/tests/py/inet/tcp.t.payload > @@ -436,6 +436,14 @@ inet test-inet input > [ bitwise reg 1 = (reg=1 & 0x00000003 ) ^ 0x00000000 ] > [ cmp eq reg 1 0x00000003 ] > > +# tcp flags & (fin | syn | rst | psh | ack | urg | ecn | cwr) == fin | syn | rst | psh | ack | urg | ecn | cwr > +inet test-inet input > + [ meta load l4proto => reg 1 ] > + [ cmp eq reg 1 0x00000006 ] > + [ payload load 1b @ transport header + 13 => reg 1 ] > + [ bitwise reg 1 = (reg=1 & 0x000000ff ) ^ 0x00000000 ] > + [ cmp eq reg 1 0x000000ff ] > + > # tcp window 22222 > inet test-inet input > [ meta load l4proto => reg 1 ] > -- > 2.18.0 >