From d0d58d9333dd53e8c2a468d190885a3cf5585af8 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Thu, 6 Nov 2025 17:23:03 +0000 Subject: [PATCH 1/4] Fix GENEVE- and VXLAN-encapsulated matching. In my recent commit 1687065 the filter programs for "vxlan [NUM]", "vxlan and vxlan", "geneve [NUM]" and "geneve and geneve" have become substantially shorter. As it turns out, the missing instructions are the outputs of gen_geneve_offsets() and gen_vxlan_offsets(), so filtering of protocols encapsulated in GENEVE and VXLAN is no longer correct. Because libpcap does not have any apply filter tests for the affected syntax, this was not apparent until a tcpdump test failed. The instructions went missing because gen_geneve() and gen_vxlan() need to use these as a block, but instead of making a new block from scratch the functions take the result of gen_true() and modify it to add side effects. After the commit the block with the wanted side effects ended up incorrectly marked as a Boolean constant and susequently gen_and() started to discard it. In gen_cond() take an optional list of side effect instructions and make a Boolean constant block a specific case of a block with a degenerate branch statement. Switch gen_geneve() and gen_vxlan() from gen_true() to gen_uncond() to reduce the violation of layers. Restore the six previously affected tests exactly as they were before. --- gencode.c | 31 +-- testprogs/TESTrun | 535 +++++++++++++++++++++++++++++----------------- 2 files changed, 352 insertions(+), 214 deletions(-) diff --git a/gencode.c b/gencode.c index b77d45f166..976b804a07 100644 --- a/gencode.c +++ b/gencode.c @@ -657,7 +657,7 @@ static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *, static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int, u_int); static struct slist *gen_loadx_iphdrlen(compiler_state_t *); -static struct block *gen_uncond(compiler_state_t *, int); +static struct block *gen_uncond(compiler_state_t *, const u_char, struct slist *); static inline struct block *gen_true(compiler_state_t *); static inline struct block *gen_false(compiler_state_t *); static struct block *gen_ether_linktype(compiler_state_t *, bpf_u_int32); @@ -2526,29 +2526,40 @@ gen_loadx_iphdrlen(compiler_state_t *cstate) return s; } - +/* + * Produce an instruction block with the given optional side effect statements + * and a final branch statement that takes the true branch iff rsense is not + * zero. Since this function detects Boolean constants for potential later + * use, the resulting block must not be modified directly afterwards, instead + * it should be used as an argument to gen_and(), gen_or() and gen_not(). + */ static struct block * -gen_uncond(compiler_state_t *cstate, int rsense) +gen_uncond(compiler_state_t *cstate, const u_char rsense, struct slist *stmts) { struct slist *s; s = new_stmt(cstate, BPF_LD|BPF_IMM); s->s.k = !rsense; + if (stmts) { + sappend(stmts, s); + s = stmts; + } struct block *ret = gen_jmp_k(cstate, BPF_JEQ, 0, s); - ret->meaning = rsense ? IS_TRUE : IS_FALSE; + if (! stmts) + ret->meaning = rsense ? IS_TRUE : IS_FALSE; return ret; } static inline struct block * gen_true(compiler_state_t *cstate) { - return gen_uncond(cstate, 1); + return gen_uncond(cstate, 1, NULL); } static inline struct block * gen_false(compiler_state_t *cstate) { - return gen_uncond(cstate, 0); + return gen_uncond(cstate, 0, NULL); } /* @@ -9123,9 +9134,7 @@ gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni) * it gets executed in the event that the Geneve filter matches. */ s = gen_geneve_offsets(cstate); - b1 = gen_true(cstate); - sappend(s, b1->stmts); - b1->stmts = s; + b1 = gen_uncond(cstate, 1, s); b1 = gen_and(b0, b1); @@ -9313,9 +9322,7 @@ gen_vxlan(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni) * it gets executed in the event that the VXLAN filter matches. */ s = gen_vxlan_offsets(cstate); - b1 = gen_true(cstate); - sappend(s, b1->stmts); - b1->stmts = s; + b1 = gen_uncond(cstate, 1, s); b1 = gen_and(b0, b1); diff --git a/testprogs/TESTrun b/testprogs/TESTrun index 3cd7a8931b..ccfd614291 100755 --- a/testprogs/TESTrun +++ b/testprogs/TESTrun @@ -6565,18 +6565,28 @@ my @accept_blocks = ( (013) txa (014) jeq x jt 26 jf 15 (015) ldh [12] - (016) jeq #0x86dd jt 17 jf 27 + (016) jeq #0x86dd jt 17 jf 37 (017) ldb [20] - (018) jeq #0x11 jt 19 jf 27 + (018) jeq #0x11 jt 19 jf 37 (019) ldh [56] - (020) jeq #0x12b5 jt 21 jf 27 + (020) jeq #0x12b5 jt 21 jf 37 (021) ldb [62] - (022) jeq #0x8 jt 23 jf 27 + (022) jeq #0x8 jt 23 jf 37 (023) ld #0x28 (024) tax - (025) jeq x jt 26 jf 27 - (026) ret #262144 - (027) ret #0 + (025) jeq x jt 26 jf 37 + (026) add #22 + (027) add #8 + (028) st M[0] + (029) add #12 + (030) st M[1] + (031) add #2 + (032) tax + (033) stx M[2] + (034) ld #0x0 + (035) jeq #0x0 jt 36 jf 37 + (036) ret #262144 + (037) ret #0 ', }, # vxlan_nullary { @@ -6634,21 +6644,31 @@ my @accept_blocks = ( (017) txa (018) jeq x jt 33 jf 19 (019) ldh [12] - (020) jeq #0x86dd jt 21 jf 34 + (020) jeq #0x86dd jt 21 jf 44 (021) ldb [20] - (022) jeq #0x11 jt 23 jf 34 + (022) jeq #0x11 jt 23 jf 44 (023) ldh [56] - (024) jeq #0x12b5 jt 25 jf 34 + (024) jeq #0x12b5 jt 25 jf 44 (025) ldb [62] - (026) jeq #0x8 jt 27 jf 34 + (026) jeq #0x8 jt 27 jf 44 (027) ld [66] (028) and #0xffffff00 - (029) jeq #0x303900 jt 30 jf 34 + (029) jeq #0x303900 jt 30 jf 44 (030) ld #0x28 (031) tax - (032) jeq x jt 33 jf 34 - (033) ret #262144 - (034) ret #0 + (032) jeq x jt 33 jf 44 + (033) add #22 + (034) add #8 + (035) st M[0] + (036) add #12 + (037) st M[1] + (038) add #2 + (039) tax + (040) stx M[2] + (041) ld #0x0 + (042) jeq #0x0 jt 43 jf 44 + (043) ret #262144 + (044) ret #0 ', }, # vxlan_unary { @@ -6659,72 +6679,79 @@ my @accept_blocks = ( (000) ldh [12] (001) jeq #0x800 jt 2 jf 13 (002) ldb [23] - (003) jeq #0x11 jt 4 jf 68 + (003) jeq #0x11 jt 4 jf 75 (004) ldh [20] - (005) jset #0x1fff jt 68 jf 6 + (005) jset #0x1fff jt 75 jf 6 (006) ldxb 4*([14]&0xf) (007) ldh [x + 16] - (008) jeq #0x12b5 jt 9 jf 68 + (008) jeq #0x12b5 jt 9 jf 75 (009) ldb [x + 22] - (010) jeq #0x8 jt 11 jf 68 + (010) jeq #0x8 jt 11 jf 75 (011) txa - (012) jeq x jt 20 jf 68 - (013) jeq #0x86dd jt 14 jf 68 + (012) jeq x jt 23 jf 75 + (013) jeq #0x86dd jt 14 jf 75 (014) ldb [20] - (015) jeq #0x11 jt 16 jf 68 + (015) jeq #0x11 jt 16 jf 75 (016) ldh [56] - (017) jeq #0x12b5 jt 18 jf 68 + (017) jeq #0x12b5 jt 18 jf 75 (018) ldb [62] - (019) jeq #0x8 jt 20 jf 68 - (020) ldx M[1] - (021) ldh [x + 0] - (022) jeq #0x800 jt 23 jf 52 - (023) ldx M[2] - (024) ldb [x + 9] - (025) jeq #0x11 jt 26 jf 68 - (026) ldx M[2] - (027) ldh [x + 6] - (028) jset #0x1fff jt 68 jf 29 - (029) ldx M[2] - (030) ldb [x + 0] - (031) and #0xf - (032) lsh #2 - (033) add x - (034) tax - (035) ldh [x + 2] - (036) jeq #0x12b5 jt 37 jf 68 - (037) ldx M[2] - (038) ldb [x + 0] - (039) and #0xf - (040) lsh #2 - (041) add x - (042) tax - (043) ldb [x + 8] - (044) jeq #0x8 jt 45 jf 68 - (045) ldx M[2] - (046) ldb [x + 0] - (047) and #0xf - (048) lsh #2 - (049) add x - (050) tax - (051) jeq x jt 67 jf 68 - (052) jeq #0x86dd jt 53 jf 68 - (053) ldx M[2] - (054) ldb [x + 6] - (055) jeq #0x11 jt 56 jf 68 - (056) ldx M[2] - (057) ldh [x + 42] - (058) jeq #0x12b5 jt 59 jf 68 - (059) ldx M[2] - (060) ldb [x + 48] - (061) jeq #0x8 jt 62 jf 68 - (062) ldx M[2] - (063) ld #0x28 - (064) add x - (065) tax - (066) jeq x jt 67 jf 68 - (067) ret #262144 - (068) ret #0 + (019) jeq #0x8 jt 20 jf 75 + (020) ldx #0x28 + (021) txa + (022) jeq #0x28 jt 23 jf 23 + (023) add #22 + (024) add #8 + (025) add #12 + (026) st M[1] + (027) add #2 + (028) tax + (029) stx M[2] + (030) ld #0x0 + (031) jeq #0x0 jt 32 jf 32 + (032) ldx M[1] + (033) ldh [x + 0] + (034) jeq #0x800 jt 35 jf 62 + (035) ldx M[2] + (036) ldb [x + 9] + (037) jeq #0x11 jt 38 jf 75 + (038) ldh [x + 6] + (039) jset #0x1fff jt 75 jf 40 + (040) ldb [x + 0] + (041) and #0xf + (042) lsh #2 + (043) add x + (044) tax + (045) ldh [x + 2] + (046) jeq #0x12b5 jt 47 jf 75 + (047) ldx M[2] + (048) ldb [x + 0] + (049) and #0xf + (050) lsh #2 + (051) add x + (052) tax + (053) ldb [x + 8] + (054) jeq #0x8 jt 55 jf 75 + (055) ldx M[2] + (056) ldb [x + 0] + (057) and #0xf + (058) lsh #2 + (059) add x + (060) tax + (061) jeq x jt 74 jf 75 + (062) jeq #0x86dd jt 63 jf 75 + (063) ldx M[2] + (064) ldb [x + 6] + (065) jeq #0x11 jt 66 jf 75 + (066) ldh [x + 42] + (067) jeq #0x12b5 jt 68 jf 75 + (068) ldb [x + 48] + (069) jeq #0x8 jt 70 jf 75 + (070) ld #0x28 + (071) add x + (072) tax + (073) jeq x jt 74 jf 75 + (074) ret #262144 + (075) ret #0 ', unopt => ' (000) ldh [12] @@ -6743,68 +6770,88 @@ my @accept_blocks = ( (013) txa (014) jeq x jt 26 jf 15 (015) ldh [12] - (016) jeq #0x86dd jt 17 jf 77 + (016) jeq #0x86dd jt 17 jf 97 (017) ldb [20] - (018) jeq #0x11 jt 19 jf 77 + (018) jeq #0x11 jt 19 jf 97 (019) ldh [56] - (020) jeq #0x12b5 jt 21 jf 77 + (020) jeq #0x12b5 jt 21 jf 97 (021) ldb [62] - (022) jeq #0x8 jt 23 jf 77 + (022) jeq #0x8 jt 23 jf 97 (023) ld #0x28 (024) tax - (025) jeq x jt 26 jf 77 - (026) ldx M[1] - (027) ldh [x + 0] - (028) jeq #0x800 jt 29 jf 59 - (029) ldx M[2] - (030) ldb [x + 9] - (031) jeq #0x11 jt 32 jf 59 - (032) ldx M[2] - (033) ldh [x + 6] - (034) jset #0x1fff jt 59 jf 35 - (035) ldx M[2] - (036) ldb [x + 0] - (037) and #0xf - (038) lsh #2 - (039) add x - (040) tax - (041) ldh [x + 2] - (042) jeq #0x12b5 jt 43 jf 59 - (043) ldx M[2] - (044) ldb [x + 0] - (045) and #0xf - (046) lsh #2 - (047) add x - (048) tax - (049) ldb [x + 8] - (050) jeq #0x8 jt 51 jf 59 - (051) ldx M[2] - (052) ldb [x + 0] - (053) and #0xf - (054) lsh #2 - (055) add x - (056) tax - (057) txa - (058) jeq x jt 76 jf 59 - (059) ldx M[1] - (060) ldh [x + 0] - (061) jeq #0x86dd jt 62 jf 77 - (062) ldx M[2] - (063) ldb [x + 6] - (064) jeq #0x11 jt 65 jf 77 - (065) ldx M[2] - (066) ldh [x + 42] - (067) jeq #0x12b5 jt 68 jf 77 - (068) ldx M[2] - (069) ldb [x + 48] - (070) jeq #0x8 jt 71 jf 77 - (071) ldx M[2] - (072) ld #0x28 - (073) add x - (074) tax - (075) jeq x jt 76 jf 77 - (076) ret #262144 - (077) ret #0 + (025) jeq x jt 26 jf 97 + (026) add #22 + (027) add #8 + (028) st M[0] + (029) add #12 + (030) st M[1] + (031) add #2 + (032) tax + (033) stx M[2] + (034) ld #0x0 + (035) jeq #0x0 jt 36 jf 97 + (036) ldx M[1] + (037) ldh [x + 0] + (038) jeq #0x800 jt 39 jf 69 + (039) ldx M[2] + (040) ldb [x + 9] + (041) jeq #0x11 jt 42 jf 69 + (042) ldx M[2] + (043) ldh [x + 6] + (044) jset #0x1fff jt 69 jf 45 + (045) ldx M[2] + (046) ldb [x + 0] + (047) and #0xf + (048) lsh #2 + (049) add x + (050) tax + (051) ldh [x + 2] + (052) jeq #0x12b5 jt 53 jf 69 + (053) ldx M[2] + (054) ldb [x + 0] + (055) and #0xf + (056) lsh #2 + (057) add x + (058) tax + (059) ldb [x + 8] + (060) jeq #0x8 jt 61 jf 69 + (061) ldx M[2] + (062) ldb [x + 0] + (063) and #0xf + (064) lsh #2 + (065) add x + (066) tax + (067) txa + (068) jeq x jt 86 jf 69 + (069) ldx M[1] + (070) ldh [x + 0] + (071) jeq #0x86dd jt 72 jf 97 + (072) ldx M[2] + (073) ldb [x + 6] + (074) jeq #0x11 jt 75 jf 97 + (075) ldx M[2] + (076) ldh [x + 42] + (077) jeq #0x12b5 jt 78 jf 97 + (078) ldx M[2] + (079) ldb [x + 48] + (080) jeq #0x8 jt 81 jf 97 + (081) ldx M[2] + (082) ld #0x28 + (083) add x + (084) tax + (085) jeq x jt 86 jf 97 + (086) add #8 + (087) add #8 + (088) st M[3] + (089) add #12 + (090) st M[4] + (091) add #2 + (092) tax + (093) stx M[5] + (094) ld #0x0 + (095) jeq #0x0 jt 96 jf 97 + (096) ret #262144 + (097) ret #0 ', }, # vxlan_and_vxlan { @@ -6829,19 +6876,40 @@ my @accept_blocks = ( (014) txa (015) jeq x jt 28 jf 16 (016) ldh [12] - (017) jeq #0x86dd jt 18 jf 29 + (017) jeq #0x86dd jt 18 jf 50 (018) ldb [20] - (019) jeq #0x11 jt 20 jf 29 + (019) jeq #0x11 jt 20 jf 50 (020) ldh [56] - (021) jeq #0x17c1 jt 22 jf 29 + (021) jeq #0x17c1 jt 22 jf 50 (022) ldb [62] (023) and #0xc0 - (024) jeq #0x0 jt 25 jf 29 + (024) jeq #0x0 jt 25 jf 50 (025) ld #0x28 (026) tax - (027) jeq x jt 28 jf 29 - (028) ret #262144 - (029) ret #0 + (027) jeq x jt 28 jf 50 + (028) add #22 + (029) tax + (030) add #2 + (031) st M[0] + (032) ldb [x + 0] + (033) and #0x3f + (034) mul #4 + (035) add #8 + (036) add x + (037) st M[1] + (038) ldh [x + 2] + (039) ldx M[1] + (040) jeq #0x6558 jt 41 jf 46 + (041) txa + (042) add #12 + (043) st M[0] + (044) add #2 + (045) tax + (046) stx M[2] + (047) ld #0x0 + (048) jeq #0x0 jt 49 jf 50 + (049) ret #262144 + (050) ret #0 ', }, # geneve_nullary { @@ -6870,22 +6938,43 @@ my @accept_blocks = ( (018) txa (019) jeq x jt 35 jf 20 (020) ldh [12] - (021) jeq #0x86dd jt 22 jf 36 + (021) jeq #0x86dd jt 22 jf 57 (022) ldb [20] - (023) jeq #0x11 jt 24 jf 36 + (023) jeq #0x11 jt 24 jf 57 (024) ldh [56] - (025) jeq #0x17c1 jt 26 jf 36 + (025) jeq #0x17c1 jt 26 jf 57 (026) ldb [62] (027) and #0xc0 - (028) jeq #0x0 jt 29 jf 36 + (028) jeq #0x0 jt 29 jf 57 (029) ld [66] (030) and #0xffffff00 - (031) jeq #0x303900 jt 32 jf 36 + (031) jeq #0x303900 jt 32 jf 57 (032) ld #0x28 (033) tax - (034) jeq x jt 35 jf 36 - (035) ret #262144 - (036) ret #0 + (034) jeq x jt 35 jf 57 + (035) add #22 + (036) tax + (037) add #2 + (038) st M[0] + (039) ldb [x + 0] + (040) and #0x3f + (041) mul #4 + (042) add #8 + (043) add x + (044) st M[1] + (045) ldh [x + 2] + (046) ldx M[1] + (047) jeq #0x6558 jt 48 jf 53 + (048) txa + (049) add #12 + (050) st M[0] + (051) add #2 + (052) tax + (053) stx M[2] + (054) ld #0x0 + (055) jeq #0x0 jt 56 jf 57 + (056) ret #262144 + (057) ret #0 ', }, # geneve_unary { @@ -6910,71 +6999,113 @@ my @accept_blocks = ( (014) txa (015) jeq x jt 28 jf 16 (016) ldh [12] - (017) jeq #0x86dd jt 18 jf 81 + (017) jeq #0x86dd jt 18 jf 123 (018) ldb [20] - (019) jeq #0x11 jt 20 jf 81 + (019) jeq #0x11 jt 20 jf 123 (020) ldh [56] - (021) jeq #0x17c1 jt 22 jf 81 + (021) jeq #0x17c1 jt 22 jf 123 (022) ldb [62] (023) and #0xc0 - (024) jeq #0x0 jt 25 jf 81 + (024) jeq #0x0 jt 25 jf 123 (025) ld #0x28 (026) tax - (027) jeq x jt 28 jf 81 - (028) ldx M[0] - (029) ldh [x + 0] - (030) jeq #0x800 jt 31 jf 62 - (031) ldx M[2] - (032) ldb [x + 9] - (033) jeq #0x11 jt 34 jf 62 - (034) ldx M[2] - (035) ldh [x + 6] - (036) jset #0x1fff jt 62 jf 37 - (037) ldx M[2] - (038) ldb [x + 0] - (039) and #0xf - (040) lsh #2 - (041) add x - (042) tax - (043) ldh [x + 2] - (044) jeq #0x17c1 jt 45 jf 62 - (045) ldx M[2] - (046) ldb [x + 0] - (047) and #0xf - (048) lsh #2 - (049) add x - (050) tax - (051) ldb [x + 8] - (052) and #0xc0 - (053) jeq #0x0 jt 54 jf 62 - (054) ldx M[2] - (055) ldb [x + 0] - (056) and #0xf - (057) lsh #2 - (058) add x - (059) tax - (060) txa - (061) jeq x jt 80 jf 62 - (062) ldx M[0] - (063) ldh [x + 0] - (064) jeq #0x86dd jt 65 jf 81 - (065) ldx M[2] - (066) ldb [x + 6] - (067) jeq #0x11 jt 68 jf 81 - (068) ldx M[2] - (069) ldh [x + 42] - (070) jeq #0x17c1 jt 71 jf 81 - (071) ldx M[2] - (072) ldb [x + 48] + (027) jeq x jt 28 jf 123 + (028) add #22 + (029) tax + (030) add #2 + (031) st M[0] + (032) ldb [x + 0] + (033) and #0x3f + (034) mul #4 + (035) add #8 + (036) add x + (037) st M[1] + (038) ldh [x + 2] + (039) ldx M[1] + (040) jeq #0x6558 jt 41 jf 46 + (041) txa + (042) add #12 + (043) st M[0] + (044) add #2 + (045) tax + (046) stx M[2] + (047) ld #0x0 + (048) jeq #0x0 jt 49 jf 123 + (049) ldx M[0] + (050) ldh [x + 0] + (051) jeq #0x800 jt 52 jf 83 + (052) ldx M[2] + (053) ldb [x + 9] + (054) jeq #0x11 jt 55 jf 83 + (055) ldx M[2] + (056) ldh [x + 6] + (057) jset #0x1fff jt 83 jf 58 + (058) ldx M[2] + (059) ldb [x + 0] + (060) and #0xf + (061) lsh #2 + (062) add x + (063) tax + (064) ldh [x + 2] + (065) jeq #0x17c1 jt 66 jf 83 + (066) ldx M[2] + (067) ldb [x + 0] + (068) and #0xf + (069) lsh #2 + (070) add x + (071) tax + (072) ldb [x + 8] (073) and #0xc0 - (074) jeq #0x0 jt 75 jf 81 + (074) jeq #0x0 jt 75 jf 83 (075) ldx M[2] - (076) ld #0x28 - (077) add x - (078) tax - (079) jeq x jt 80 jf 81 - (080) ret #262144 - (081) ret #0 + (076) ldb [x + 0] + (077) and #0xf + (078) lsh #2 + (079) add x + (080) tax + (081) txa + (082) jeq x jt 101 jf 83 + (083) ldx M[0] + (084) ldh [x + 0] + (085) jeq #0x86dd jt 86 jf 123 + (086) ldx M[2] + (087) ldb [x + 6] + (088) jeq #0x11 jt 89 jf 123 + (089) ldx M[2] + (090) ldh [x + 42] + (091) jeq #0x17c1 jt 92 jf 123 + (092) ldx M[2] + (093) ldb [x + 48] + (094) and #0xc0 + (095) jeq #0x0 jt 96 jf 123 + (096) ldx M[2] + (097) ld #0x28 + (098) add x + (099) tax + (100) jeq x jt 101 jf 123 + (101) add #8 + (102) tax + (103) add #2 + (104) st M[3] + (105) ldb [x + 0] + (106) and #0x3f + (107) mul #4 + (108) add #8 + (109) add x + (110) st M[4] + (111) ldh [x + 2] + (112) ldx M[4] + (113) jeq #0x6558 jt 114 jf 119 + (114) txa + (115) add #12 + (116) st M[3] + (117) add #2 + (118) tax + (119) stx M[5] + (120) ld #0x0 + (121) jeq #0x0 jt 122 jf 123 + (122) ret #262144 + (123) ret #0 ', }, # geneve_and_geneve From 2e15d1a1744ce4447c303c3603f1a1241b1ae5e8 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Thu, 6 Nov 2025 18:52:46 +0000 Subject: [PATCH 2/4] TESTrun: Test GENEVE and VXLAN a bit better. To detect gen_geneve() and gen_vxlan() regressions that affect filtering of encapsulated protocols, define two new apply filter tests. For now these stand for IPv4 only. --- testprogs/TESTrun | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testprogs/TESTrun b/testprogs/TESTrun index ccfd614291..fa52c9b5e8 100755 --- a/testprogs/TESTrun +++ b/testprogs/TESTrun @@ -17973,6 +17973,12 @@ my @apply_blocks = ( expr => 'vxlan 101', results => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }, + { + name => 'vxlan_and_icmp_reply', + savefile => 'vxlan.pcap', + expr => 'vxlan and icmp[icmptype] == icmp-echo', + results => [1500, 0, 0, 0, 1500, 0, 1500, 0, 1500, 0], + }, { name => 'geneve', savefile => 'geneve.pcap', @@ -17991,6 +17997,12 @@ my @apply_blocks = ( expr => 'geneve 11', results => [0, 262144, 262144, 0, 262144, 0, 262144, 262144, 0, 262144], }, + { + name => 'geneve_and_tcp_src_port', + savefile => 'geneve.pcap', + expr => 'geneve and tcp src port 22', + results => [0, 0, 0, 262144, 0, 262144, 0, 0, 262144, 0], + }, { name => 'ip_protochain_17_deepstack', skip => skip_config_def1 ('NO_PROTOCHAIN'), From 9309458887afa106752e5e34eed001cc42f32181 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Thu, 6 Nov 2025 23:07:08 +0000 Subject: [PATCH 3/4] TESTrun: Add detailed tests for AND/OR reductions. Six tests make it easy to see another regression I have introduced in commit 1687065. --- testprogs/TESTrun | 158 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/testprogs/TESTrun b/testprogs/TESTrun index fa52c9b5e8..1f8bfdfbdf 100755 --- a/testprogs/TESTrun +++ b/testprogs/TESTrun @@ -17240,6 +17240,146 @@ my @accept_blocks = ( (004) ret #262144 ', }, # byte_and + + # Assorted AND/OR reductions. + # + # On DLT_IPV4 in the current implementation: + # * "ip" produces a "true" block, + # * "ip6" produces a "false" block, + # * "not ip" produces a "not true" block, and + # * "not ip6" produces a "not false" block. + # The "true" and "not false" blocks comprise sequences of statements + # that are not identical, but have equivalent effect, the same holds + # for the "false" and "not true" pair. The aliases below will have to + # account for these differences until these have converged. + { + name => 'bool_reduction_returns_true', + DLT => 'IPV4', + aliases => [ + # gen_and() + 'ip and ip', # [1] True and true is true. + 'not ip6 and ip', # [1] Not false and true is true. + # gen_or() + 'ip or ip6', # [2] True or false is true. + 'ip or not ip', # [2] True or not true is true. + 'ip6 or ip', # [3] False or true is true. + 'not ip or ip', # [3] Not true or true is true. + 'ip or ip', # [4] True or true is true. + 'not ip6 or ip', # [4] Not false or true is not false. (BUG!) + ], + opt => ' + (000) ret #262144 + ', + unopt => ' + (000) ld #0x0 + (001) jeq #0x0 jt 2 jf 3 + (002) ret #262144 + (003) ret #0 + ', + }, # bool_reduction_returns_true + { + name => 'bool_reduction_returns_not_false', + DLT => 'IPV4', + aliases => [ + # gen_and() + 'not ip6 and not ip6', # [1] Not false and not false is not false. + 'ip and not ip6', # [1] True and not false is not false. + # gen_or() + 'not ip6 or ip6', # [2] Not false or false is not false. + 'not ip6 or not ip', # [2] Not false or not true is not false. + 'ip6 or not ip6', # [3] False or not false is not false. + 'not ip or not ip6', # [3] Not true or not false is not false. + 'not ip6 or not ip6', # [4] Not false or not false is not false. + 'ip or not ip6', # [4] True or not false is true. (BUG!) + ], + opt => ' + (000) ret #262144 + ', + unopt => ' + (000) ld #0x1 + (001) jeq #0x0 jt 2 jf 3 + (002) ret #0 + (003) ret #262144 + ', + }, # bool_reduction_returns_not_false + { + name => 'bool_reduction_returns_x', + DLT => 'IPV4', + aliases => [ + # gen_and() + 'ip and igmp', # [5] True and X is X. + 'not ip6 and igmp', # [5] Not false and X is X. + 'igmp and ip', # [6] X and true is X. + 'igmp and not ip6', # [6] X and not false is X. + # gen_or() + 'ip6 or igmp', # [7] False or X is X. + 'not ip or igmp', # [7] Not true or X is X. + 'igmp or ip6', # [8] X or false is X. + 'igmp or not ip', # [8] X or not true is X. + 'ip or igmp', # [9] True or X is true. (BUG!) + 'not ip6 or igmp', # [9] Not false or X is not false. (BUG!) + 'igmp or ip', # [10] X or true is true. (BUG!) + 'igmp or not ip6', # [10] X or not false is not false. (BUG!) + ], + optunopt => ' + (000) ldb [9] + (001) jeq #0x2 jt 2 jf 3 + (002) ret #262144 + (003) ret #0 + ', + }, # bool_reduction_returns_x + { + name => 'bool_reduction_returns_false', + DLT => 'IPV4', + aliases => [ + # gen_and() + 'ip6 and ip6', # [11] False and false is false. + 'ip6 and not ip', # [11] False and not true is false. + 'ip6 and ip', # [12] False and true is false. + 'ip6 and not ip6', # [12] False and not false is false. + 'ip and ip6', # [13] True and false is false. + 'not ip6 and ip6', # [13] Not false and false is false. + 'ip6 and igmp', # [14] False and X is false. + 'igmp and ip6', # [15] X and false is false. + # gen_or() + 'ip6 or ip6', # [16] False or false is false. + 'not ip or ip6', # [16] Not true or false is false. + ], + # The "opt" leg of this block is a reject test. + opt => undef, + unopt => ' + (000) ld #0x1 + (001) jeq #0x0 jt 2 jf 3 + (002) ret #262144 + (003) ret #0 + ', + }, # bool_reduction_returns_false + { + name => 'bool_reduction_returns_not_true', + DLT => 'IPV4', + aliases => [ + # gen_and() + 'not ip and ip6', # [11] Not true and false is not true. + 'not ip and not ip', # [11] Not true and not true is not true. + 'not ip and ip', # [12] Not true and true is not true. + 'not ip and not ip6', # [12] Not true and not false is not true. + 'ip and not ip', # [13] True and not true is not true. + 'not ip6 and not ip', # [13] Not false and not true is not true. + 'not ip and igmp', # [14] Not true and X is not true. + 'igmp and not ip', # [15] X and not true is not true. + # gen_or() + 'not ip or not ip', # [16] Not true or not true is not true. + 'ip6 or not ip', # [16] False or not true is not true. + ], + # The "opt" leg of this block is a reject test. + opt => undef, + unopt => ' + (000) ld #0x0 + (001) jeq #0x0 jt 2 jf 3 + (002) ret #0 + (003) ret #262144 + ', + }, # bool_reduction_returns_not_true ); # In apply_blocks each test block always generates two tests: optimized and @@ -19413,6 +19553,24 @@ my @reject_tests = ( savefile => 'shb-option-too-long.pcapng', errstr => 'Failed opening: block total length in header and trailer don\'t match', }, + + { + name => 'bool_reduction_returns_false', + DLT => 'IPV4', + # Test only one alias of the accept block: so long as the + # accept block passes, all accept aliases produce the same + # unoptimized instruction block, therefore the optimized + # result will be the same. + expr => 'ip6 and igmp', + errstr => errstr_rejects_all, + }, + { + name => 'bool_reduction_returns_not true', + DLT => 'IPV4', + # Idem. + expr => 'not ip and ip6', + errstr => errstr_rejects_all, + }, ); # "proto" qualifiers without any lexer-level aliases (the entries correspond From 3ed0cd024e96bd3a0b016c49f0a1128e4563850a Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Fri, 7 Nov 2025 00:22:28 +0000 Subject: [PATCH 4/4] Always pick the correct argument in gen_or(). I got the comments right, but not all of the code, fix that and update the tests. --- gencode.c | 4 ++-- testprogs/TESTrun | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gencode.c b/gencode.c index 976b804a07..a2cdcebc5b 100644 --- a/gencode.c +++ b/gencode.c @@ -1462,10 +1462,10 @@ gen_or(struct block *b0, struct block *b1) return b0; // True or X is true. if (b0->meaning == IS_TRUE) - return b1; + return b0; // X or true is true. if (b1->meaning == IS_TRUE) - return b0; + return b1; // b0->meaning == IS_UNCERTAIN && b1->meaning == IS_UNCERTAIN b0->sense = !b0->sense; diff --git a/testprogs/TESTrun b/testprogs/TESTrun index 1f8bfdfbdf..f284263734 100755 --- a/testprogs/TESTrun +++ b/testprogs/TESTrun @@ -17265,7 +17265,9 @@ my @accept_blocks = ( 'ip6 or ip', # [3] False or true is true. 'not ip or ip', # [3] Not true or true is true. 'ip or ip', # [4] True or true is true. - 'not ip6 or ip', # [4] Not false or true is not false. (BUG!) + 'ip or not ip6', # [4] True or not false is true. + 'ip or igmp', # [9] True or X is true. + 'igmp or ip', # [10] X or true is true. ], opt => ' (000) ret #262144 @@ -17289,8 +17291,10 @@ my @accept_blocks = ( 'not ip6 or not ip', # [2] Not false or not true is not false. 'ip6 or not ip6', # [3] False or not false is not false. 'not ip or not ip6', # [3] Not true or not false is not false. + 'not ip6 or ip', # [4] Not false or true is not false. 'not ip6 or not ip6', # [4] Not false or not false is not false. - 'ip or not ip6', # [4] True or not false is true. (BUG!) + 'not ip6 or igmp', # [9] Not false or X is not false. + 'igmp or not ip6', # [10] X or not false is not false. ], opt => ' (000) ret #262144 @@ -17316,10 +17320,6 @@ my @accept_blocks = ( 'not ip or igmp', # [7] Not true or X is X. 'igmp or ip6', # [8] X or false is X. 'igmp or not ip', # [8] X or not true is X. - 'ip or igmp', # [9] True or X is true. (BUG!) - 'not ip6 or igmp', # [9] Not false or X is not false. (BUG!) - 'igmp or ip', # [10] X or true is true. (BUG!) - 'igmp or not ip6', # [10] X or not false is not false. (BUG!) ], optunopt => ' (000) ldb [9]