diff options
author | Maciej Żenczykowski <maze@google.com> | 2024-03-19 12:12:26 -0700 |
---|---|---|
committer | Maciej Żenczykowski <maze@google.com> | 2024-03-19 22:52:49 +0000 |
commit | 13f3eb85bef46c60bc850b8783133971b7db7128 (patch) | |
tree | 1d02d2830a081303f574086b370d47a844ff6afe | |
parent | 03c86c94ba3022c7b019f6a30c8f58251cc7b449 (diff) | |
download | apf-13f3eb85bef46c60bc850b8783133971b7db7128.tar.gz |
v5: implement JONEOF_OPCODE
This unfortunately ends up requiring a fair bit of interpreter code space.
After:
text data bss dec hex filename
4104 0 0 4104 1008 apf_interpreter.arm.o
text data bss dec hex filename
5026 0 0 5026 13a2 apf_interpreter.x86.o
Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ieb833b47490ec94ecc24f99cad8c44811061aae4
-rw-r--r-- | v5/apf.h | 11 | ||||
-rw-r--r-- | v5/apf_interpreter.c | 30 | ||||
-rw-r--r-- | v5/apf_interpreter_source.c | 19 |
3 files changed, 58 insertions, 2 deletions
@@ -283,6 +283,17 @@ typedef union { #define JDNSAMATCH_EXT_OPCODE 44 #define JDNSAMATCHSAFE_EXT_OPCODE 46 +/* Jump if register is [not] one of the list of values + * R bit - specifies the register (R0/R1) to test + * imm1: Extended opcode + * imm2: Jump label offset + * imm3(u8): top 5 bits - number of following u8/be16/be32 values - 1 + * middle 2 bits - 1..4 length of immediates + * bottom 1 bit - =0 jmp if in set, =1 if not in set + * imm4(imm3 * 1/2/3/4 bytes): the values to compare against + */ +#define JONEOF_EXT_OPCODE 47 + // This extended opcode is used to implement PKTDATACOPY_OPCODE #define PKTDATACOPYIMM_EXT_OPCODE 65536 diff --git a/v5/apf_interpreter.c b/v5/apf_interpreter.c index f71db4d..7a9f68f 100644 --- a/v5/apf_interpreter.c +++ b/v5/apf_interpreter.c @@ -355,6 +355,17 @@ typedef union { #define JDNSAMATCH_EXT_OPCODE 44 #define JDNSAMATCHSAFE_EXT_OPCODE 46 +/* Jump if register is [not] one of the list of values + * R bit - specifies the register (R0/R1) to test + * imm1: Extended opcode + * imm2: Jump label offset + * imm3(u8): top 5 bits - number of following u8/be16/be32 values - 1 + * middle 2 bits - 1..4 length of immediates + * bottom 1 bit - =0 jmp if in set, =1 if not in set + * imm4(imm3 * 1/2/3/4 bytes): the values to compare against + */ +#define JONEOF_EXT_OPCODE 47 + /* This extended opcode is used to implement PKTDATACOPY_OPCODE */ #define PKTDATACOPYIMM_EXT_OPCODE 65536 @@ -596,7 +607,7 @@ extern void APF_TRACE_HOOK(u32 pc, const u32* regs, const u8* program, #define ENFORCE_UNSIGNED(c) ((c)==(u32)(c)) u32 apf_version(void) { - return 20240314; + return 20240315; } typedef struct { @@ -972,6 +983,23 @@ static int do_apf_run(apf_context* ctx) { } break; } + case JONEOF_EXT_OPCODE: { + const u32 imm_len = 1 << (len_field - 1); /* ext opcode len_field guaranteed > 0 */ + u32 jump_offs = decode_imm(ctx, imm_len); /* 2nd imm, at worst 8 B past prog_len */ + u8 imm3 = DECODE_U8(); /* 3rd imm, at worst 9 bytes past prog_len */ + Boolean jmp = imm3 & 1; /* =0 jmp on match, =1 jmp on no match */ + u8 len = ((imm3 >> 1) & 3) + 1; /* size [1..4] in bytes of an element */ + u8 cnt = (imm3 >> 3) + 1; /* number [1..32] of elements in set */ + if (ctx->pc + cnt * len > ctx->program_len) return PASS_PACKET; + while (cnt--) { + u32 v = 0; + int i; + for (i = 0; i < len; ++i) v = (v << 8) | DECODE_U8(); + if (REG == v) jmp ^= True; + } + if (jmp) ctx->pc += jump_offs; + return PASS_PACKET; + } default: /* Unknown extended opcode */ return PASS_PACKET; /* Bail out */ } diff --git a/v5/apf_interpreter_source.c b/v5/apf_interpreter_source.c index 5523ac1..7438029 100644 --- a/v5/apf_interpreter_source.c +++ b/v5/apf_interpreter_source.c @@ -61,7 +61,7 @@ extern void APF_TRACE_HOOK(u32 pc, const u32* regs, const u8* program, #define ENFORCE_UNSIGNED(c) ((c)==(u32)(c)) u32 apf_version(void) { - return 20240314; + return 20240315; } typedef struct { @@ -437,6 +437,23 @@ static int do_apf_run(apf_context* ctx) { } break; } + case JONEOF_EXT_OPCODE: { + const u32 imm_len = 1 << (len_field - 1); // ext opcode len_field guaranteed > 0 + u32 jump_offs = decode_imm(ctx, imm_len); // 2nd imm, at worst 8 B past prog_len + u8 imm3 = DECODE_U8(); // 3rd imm, at worst 9 bytes past prog_len + bool jmp = imm3 & 1; // =0 jmp on match, =1 jmp on no match + u8 len = ((imm3 >> 1) & 3) + 1; // size [1..4] in bytes of an element + u8 cnt = (imm3 >> 3) + 1; // number [1..32] of elements in set + if (ctx->pc + cnt * len > ctx->program_len) return PASS_PACKET; + while (cnt--) { + u32 v = 0; + int i; + for (i = 0; i < len; ++i) v = (v << 8) | DECODE_U8(); + if (REG == v) jmp ^= true; + } + if (jmp) ctx->pc += jump_offs; + return PASS_PACKET; + } default: // Unknown extended opcode return PASS_PACKET; // Bail out } |