diff options
-rw-r--r-- | apf_interpreter.h | 6 | ||||
-rw-r--r-- | apf_run.c | 4 | ||||
-rw-r--r-- | disassembler.c | 60 | ||||
-rw-r--r-- | v5/Android.bp | 19 | ||||
-rw-r--r-- | v5/apf.h | 15 | ||||
-rw-r--r-- | v5/apf_interpreter.c | 100 | ||||
-rw-r--r-- | v5/apf_interpreter.h | 136 | ||||
-rw-r--r-- | v5/test_buf_allocator.c | 15 |
8 files changed, 250 insertions, 105 deletions
diff --git a/apf_interpreter.h b/apf_interpreter.h index 368ae04..1c8e7c9 100644 --- a/apf_interpreter.h +++ b/apf_interpreter.h @@ -37,9 +37,9 @@ extern "C" { * begins at program + program_len and ends at program + ram_len - 1, * as described in the following diagram: * - * program program + program_len program + ram_len - * | text section | data section | - * +--------------------+------------------------+ + * program program + program_len program + ram_len + * | text section | data section | + * +--------------------+------------------------+ * * @param program the program bytecode, followed by the writable data region. * @param program_len the length in bytes of the read-only portion of the APF @@ -176,7 +176,7 @@ void packet_handler(int use_apf_v6_interpreter, uint8_t* program, int ret; if (use_apf_v6_interpreter) { - ret = apf_run(program, program_len, ram_len, packet, packet_len, + ret = apf_run(NULL, program, program_len, ram_len, packet, packet_len, filter_age); } else { ret = accept_packet(program, program_len, ram_len, packet, packet_len, @@ -234,7 +234,7 @@ void file_handler(int use_apf_v6_interpreter, uint8_t* program, int result; if (use_apf_v6_interpreter) { - result = apf_run(program, program_len, ram_len, apf_packet, + result = apf_run(NULL, program, program_len, ram_len, apf_packet, apf_header.len, filter_age); } else { result = accept_packet(program, program_len, ram_len, apf_packet, diff --git a/disassembler.c b/disassembler.c index 6db8d7d..06a164b 100644 --- a/disassembler.c +++ b/disassembler.c @@ -113,6 +113,10 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, const uint32_t opcode = EXTRACT_OPCODE(bytecode); #define PRINT_OPCODE() \ print_opcode(opcode_names[opcode], output_buffer, output_buffer_len, offset) +#define DECODE_IMM(value, length) \ + for (uint32_t i = 0; i < (length) && pc < program_len; i++) \ + value = (value << 8) | program[pc++] + const uint32_t reg_num = EXTRACT_REGISTER(bytecode); // All instructions have immediate fields, so load them now. const uint32_t len_field = EXTRACT_IMM_LENGTH(bytecode); @@ -120,8 +124,7 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, int32_t signed_imm = 0; if (len_field != 0) { const uint32_t imm_len = 1 << (len_field - 1); - for (uint32_t i = 0; i < imm_len && pc < program_len; i++) - imm = (imm << 8) | program[pc++]; + DECODE_IMM(imm, imm_len); // Sign extend imm into signed_imm. signed_imm = imm << ((4 - imm_len) * 8); signed_imm >>= (4 - imm_len) * 8; @@ -193,10 +196,7 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, ASSERT_RET_INBOUND(ret); offset += ret; } else { - uint32_t cmp_imm_len = 1 << (len_field - 1); - uint32_t i; - for (i = 0; i < cmp_imm_len && pc < program_len; i++) - cmp_imm = (cmp_imm << 8) | program[pc++]; + DECODE_IMM(cmp_imm, 1 << (len_field - 1)); ret = snprintf(output_buffer + offset, output_buffer_len - offset, "0x%x, ", cmp_imm); ASSERT_RET_INBOUND(ret); @@ -381,6 +381,32 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, offset += ret; break; } + case EDATACOPY: + case EPKTCOPY: { + if (imm == EPKTCOPY) { + ret = print_opcode("pcopy", output_buffer, + output_buffer_len, offset); + } else { + ret = print_opcode("dcopy", output_buffer, + output_buffer_len, offset); + } + ASSERT_RET_INBOUND(ret); + offset += ret; + if (len_field > 0) { + const uint32_t imm_len = 1 << (len_field - 1); + uint32_t relative_offs = 0; + DECODE_IMM(relative_offs, imm_len); + uint32_t copy_len = 0; + DECODE_IMM(copy_len, 1); + + ret = snprintf( + output_buffer + offset, output_buffer_len - offset, + "[r%u+%d], %d", reg_num, relative_offs, copy_len); + ASSERT_RET_INBOUND(ret); + offset += ret; + } + break; + } default: ret = snprintf(output_buffer + offset, output_buffer_len - offset, "unknown_ext %u", @@ -437,6 +463,28 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, } break; } + case MEMCOPY_OPCODE: { + if (reg_num == 0) { + ret = print_opcode("pcopy", output_buffer, output_buffer_len, + offset); + } else { + ret = print_opcode("dcopy", output_buffer, output_buffer_len, + offset); + } + ASSERT_RET_INBOUND(ret); + offset += ret; + if (len_field > 0) { + uint32_t src_offs = imm; + uint32_t copy_len = 0; + DECODE_IMM(copy_len, 1); + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "%d, %d", src_offs, copy_len); + ASSERT_RET_INBOUND(ret); + offset += ret; + } + break; + } // Unknown opcode default: ret = snprintf(output_buffer + offset, output_buffer_len - offset, diff --git a/v5/Android.bp b/v5/Android.bp index 9dbfd9f..23bfa9c 100644 --- a/v5/Android.bp +++ b/v5/Android.bp @@ -18,9 +18,26 @@ package { default_applicable_licenses: ["hardware_google_apf_license"], } +cc_defaults { + name: "apfv5_defaults", + + cflags: [ + "-Wall", + "-Werror", + "-Werror=implicit-fallthrough", + "-Werror=strict-prototypes", + "-Wnullable-to-nonnull-conversion", + "-Wsign-compare", + "-Wsign-conversion", + "-Wthread-safety", + "-Wunused-parameter", + "-Wuninitialized", + ], +} + cc_library_static { name: "libapf_v5", - defaults: ["apf_defaults"], + defaults: ["apfv5_defaults"], srcs: [ "apf_interpreter.c", "test_buf_allocator.c" @@ -159,6 +159,11 @@ #define LDDW_OPCODE 22 // Load 4 bytes from data address (register + simm): "lddw R0, [5+R1]" #define STDW_OPCODE 23 // Store 4 bytes to data address (register + simm): "stdw R0, [5+R1]" #define WRITE_OPCODE 24 // Write 1, 2 or 4 bytes imm to the output buffer, e.g. "WRITE 5" +// Copy the data from input packet or APF data region to output buffer. Register bit is +// used to specify the source of data copy: R=0 means copy from packet, R=1 means copy +// from APF data region. The source offset is encoded in the first imm and the copy length +// is encoded in the second imm. "e.g. MEMCOPY(R=0), 5, 5" +#define MEMCOPY_OPCODE 25 // Extended opcodes. These all have an opcode of EXT_OPCODE // and specify the actual opcode in the immediate field. @@ -175,6 +180,16 @@ #define EWRITE1_EXT_OPCODE 38 // Write 1 byte from register to the output buffer, e.g. "EWRITE1 R0" #define EWRITE2_EXT_OPCODE 39 // Write 2 bytes from register to the output buffer, e.g. "EWRITE2 R0" #define EWRITE4_EXT_OPCODE 40 // Write 4 bytes from register to the output buffer, e.g. "EWRITE4 R0" +// Copy the data from input packet to output buffer. The source offset is encoded as [Rx + second imm]. +// The copy length is encoded in the third imm. "e.g. EPKTCOPY [R0 + 5], 5" +#define EPKTCOPY 41 +// Copy the data from APF data region to output buffer. The source offset is encoded as [Rx + second imm]. +// The copy length is encoded in the third imm. "e.g. EDATACOPY [R0 + 5], 5" +#define EDATACOPY 42 +// It is executed as a jump, it tells how many bytes of the program regions +// are used to store the data and followed by the actual data bytes. +// "e.g. data 5, abcde" +#define DATA_EXT_OPCODE 43 #define EXTRACT_OPCODE(i) (((i) >> 3) & 31) #define EXTRACT_REGISTER(i) ((i) & 1) diff --git a/v5/apf_interpreter.c b/v5/apf_interpreter.c index 3cef719..6679c72 100644 --- a/v5/apf_interpreter.c +++ b/v5/apf_interpreter.c @@ -17,7 +17,7 @@ #include "apf_interpreter.h" // TODO: Remove the dependency of the standard library and make the interpreter self-contained. -#include <string.h> // For memcmp +#include <string.h>// For memcmp #include "apf.h" @@ -32,6 +32,8 @@ extern void APF_TRACE_HOOK(uint32_t pc, const uint32_t* regs, const uint8_t* pro } while (0) #endif +// Frame header size should be 14 +#define APF_FRAME_HEADER_SIZE 14 // Return code indicating "packet" should accepted. #define PASS_PACKET 1 // Return code indicating "packet" should be dropped. @@ -43,11 +45,17 @@ extern void APF_TRACE_HOOK(uint32_t pc, const uint32_t* regs, const uint8_t* pro // superfluous ">= 0" with unsigned expressions generates compile warnings. #define ENFORCE_UNSIGNED(c) ((c)==(uint32_t)(c)) -int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, - const uint8_t* packet, uint32_t packet_len, - uint32_t filter_age) { +uint32_t apf_version(void) { + return 20231214; +} + +int apf_run(void* ctx, uint8_t* const program, const uint32_t program_len, + const uint32_t ram_len, const uint8_t* const packet, + const uint32_t packet_len, const uint32_t filter_age_16384ths) { // Is offset within program bounds? #define IN_PROGRAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < program_len) +// Is offset within ram bounds? +#define IN_RAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < ram_len) // Is offset within packet bounds? #define IN_PACKET_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < packet_len) // Is access to offset |p| length |size| within data bounds? @@ -58,6 +66,8 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, (p) + (size) >= (p)) // catch wraparounds // Accept packet if not within program bounds #define ASSERT_IN_PROGRAM_BOUNDS(p) ASSERT_RETURN(IN_PROGRAM_BOUNDS(p)) +// Accept packet if not within ram bounds +#define ASSERT_IN_RAM_BOUNDS(p) ASSERT_RETURN(IN_RAM_BOUNDS(p)) // Accept packet if not within packet bounds #define ASSERT_IN_PACKET_BOUNDS(p) ASSERT_RETURN(IN_PACKET_BOUNDS(p)) // Accept packet if not within data bounds @@ -74,7 +84,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, memory[MEMORY_OFFSET_PROGRAM_SIZE] = program_len; memory[MEMORY_OFFSET_DATA_SIZE] = ram_len; memory[MEMORY_OFFSET_PACKET_SIZE] = packet_len; - memory[MEMORY_OFFSET_FILTER_AGE] = filter_age; + memory[MEMORY_OFFSET_FILTER_AGE] = filter_age_16384ths >> 14; ASSERT_IN_PACKET_BOUNDS(APF_FRAME_HEADER_SIZE); // Only populate if IP version is IPv4. if ((packet[APF_FRAME_HEADER_SIZE] & 0xf0) == 0x40) { @@ -91,7 +101,22 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, // The output buffer pointer uint8_t* allocated_buffer = NULL; // The length of the output buffer - uint32_t allocate_buffer_len = 0; + uint32_t allocated_buffer_len = 0; +// Is access to offset |p| length |size| within output buffer bounds? +#define IN_OUTPUT_BOUNDS(p, size) (ENFORCE_UNSIGNED(p) && \ + ENFORCE_UNSIGNED(size) && \ + (p) + (size) <= allocated_buffer_len && \ + (p) + (size) >= (p)) +// Accept packet if not write within allocated output buffer +#define ASSERT_IN_OUTPUT_BOUNDS(p, size) ASSERT_RETURN(IN_OUTPUT_BOUNDS(p, size)) + +// Decode the imm length. +#define DECODE_IMM(value, length) \ + do { \ + uint32_t i; \ + for (i = 0; i < (length) && pc < program_len; i++) \ + value = (value << 8) | program[pc++]; \ + } while (0) do { APF_TRACE_HOOK(pc, registers, program, program_len, packet, packet_len, memory, ram_len); @@ -113,11 +138,9 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, if (len_field != 0) { const uint32_t imm_len = 1 << (len_field - 1); ASSERT_FORWARD_IN_PROGRAM(pc + imm_len - 1); - uint32_t i; - for (i = 0; i < imm_len; i++) - imm = (imm << 8) | program[pc++]; + DECODE_IMM(imm, imm_len); // Sign extend imm into signed_imm. - signed_imm = imm << ((4 - imm_len) * 8); + signed_imm = (int32_t) (imm << ((4 - imm_len) * 8)); signed_imm >>= (4 - imm_len) * 8; } @@ -134,7 +157,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, offs += registers[1]; } ASSERT_IN_PACKET_BOUNDS(offs); - uint32_t load_size; + uint32_t load_size = 0; switch (opcode) { case LDB_OPCODE: case LDBX_OPCODE: @@ -178,9 +201,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, } else if (len_field != 0) { uint32_t cmp_imm_len = 1 << (len_field - 1); ASSERT_FORWARD_IN_PROGRAM(pc + cmp_imm_len - 1); - uint32_t i; - for (i = 0; i < cmp_imm_len; i++) - cmp_imm = (cmp_imm << 8) | program[pc++]; + DECODE_IMM(cmp_imm, cmp_imm_len); } switch (opcode) { case JEQ_OPCODE: @@ -249,7 +270,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, break; } case LI_OPCODE: - REG = signed_imm; + REG = (uint32_t) signed_imm; break; case EXT_OPCODE: if ( @@ -282,19 +303,20 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, break; case ALLOC_EXT_OPCODE: ASSERT_RETURN(allocated_buffer == NULL); - allocate_buffer_len = REG; - allocated_buffer = apf_allocate_buffer(allocate_buffer_len); + allocated_buffer_len = REG; + allocated_buffer = + apf_allocate_buffer(ctx, allocated_buffer_len); ASSERT_RETURN(allocated_buffer != NULL); memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET] = 0; break; case TRANS_EXT_OPCODE: ASSERT_RETURN(allocated_buffer != NULL); - uint32_t pkt_len = - memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET]; + uint32_t pkt_len = memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET]; // If pkt_len > allocate_buffer_len, it means sth. wrong // happened and the allocated_buffer should be deallocated. - if (pkt_len > allocate_buffer_len) { + if (pkt_len > allocated_buffer_len) { apf_transmit_buffer( + ctx, allocated_buffer, 0 /* len */, 0 /* dscp */); @@ -302,11 +324,20 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, } // TODO: calculate packet checksum and get dscp apf_transmit_buffer( + ctx, allocated_buffer, pkt_len, 0 /* dscp */); allocated_buffer = NULL; break; + case DATA_EXT_OPCODE: { + ASSERT_FORWARD_IN_PROGRAM(pc + 1); + uint32_t skip_len = 0; + DECODE_IMM(skip_len, 2); + ASSERT_FORWARD_IN_PROGRAM(pc + skip_len - 1); + pc += skip_len; + break; + } // Unknown extended opcode default: // Bail out @@ -314,7 +345,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, } break; case LDDW_OPCODE: { - uint32_t offs = OTHER_REG + signed_imm; + uint32_t offs = OTHER_REG + (uint32_t) signed_imm; uint32_t size = 4; uint32_t val = 0; // Negative offsets wrap around the end of the address space. @@ -330,7 +361,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, break; } case STDW_OPCODE: { - uint32_t offs = OTHER_REG + signed_imm; + uint32_t offs = OTHER_REG + (uint32_t) signed_imm; uint32_t size = 4; uint32_t val = REG; // Negative offsets wrap around the end of the address space. @@ -346,6 +377,31 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, } break; } + case MEMCOPY_OPCODE: { + ASSERT_RETURN(allocated_buffer != NULL); + ASSERT_RETURN(len_field > 0); + uint32_t src_offs = imm; + uint32_t copy_len = 0; + DECODE_IMM(copy_len, 1); + uint32_t dst_offs = memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET]; + ASSERT_IN_OUTPUT_BOUNDS(dst_offs, copy_len); + // reg_num == 0 copy from packet, reg_num == 1 copy from data. + if (reg_num == 0) { + ASSERT_IN_PACKET_BOUNDS(src_offs); + const uint32_t last_packet_offs = src_offs + copy_len - 1; + ASSERT_RETURN(last_packet_offs >= src_offs); + ASSERT_IN_PACKET_BOUNDS(last_packet_offs); + memmove(allocated_buffer + dst_offs, packet + src_offs, + copy_len); + } else { + ASSERT_IN_RAM_BOUNDS(src_offs + copy_len - 1); + memmove(allocated_buffer + dst_offs, program + src_offs, + copy_len); + } + dst_offs += copy_len; + memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET] = dst_offs; + break; + } // Unknown opcode default: // Bail out diff --git a/v5/apf_interpreter.h b/v5/apf_interpreter.h index 461d3ee..6ef4cc9 100644 --- a/v5/apf_interpreter.h +++ b/v5/apf_interpreter.h @@ -24,93 +24,107 @@ extern "C" { #endif /** - * Version of APF instruction set processed by apf_run(). - * Should be returned by wifi_get_packet_filter_info. + * Returns the max version of the APF instruction set supported by apf_run(). + * APFv6 is a superset of APFv4. APFv6 interpreters are able to run APFv4 code. */ -uint32_t apf_version(); +uint32_t apf_version(void); /** - * Allocates a buffer for APF program to write the transmit packet. - * - * The implementations must always support allocating at least one 1500 bytes - * buffer until it is effectively transmitted. Before passing a memory region - * back to the caller, the implementations must zero it out. - * - * The firmware is responsible for freeing everything that was allocated by APF. - * It is OK if the firmware decides only to limit allocations to at most one - * response packet for every packet received by APF. In other words, while - * processing a single received packet, it is OK for apf_allocate_buffer() to - * succeed only once and return NULL after that. - * - * @param size the size of buffer to allocate, it should be the size of the - * packet to be transmitted. - * @return the pointer to the allocated region. The function can return null to - * indicate the allocation failure due to not enough memory. This may - * happened if there are too many buffers allocated that have not been - * transmitted and deallocated yet. + * Allocates a buffer for the APF program to build a reply packet. + * + * Unless in a critical low memory state, the firmware must allow allocating at + * least one 1500 byte buffer for every call to apf_run(). The interpreter will + * have at most one active allocation at any given time, and will always either + * transmit or deallocate the buffer before apf_run() returns. + * + * It is OK if the firmware decides to limit allocations to at most one per + * apf_run() invocation. + * + * The firmware MAY choose to allocate a larger buffer than requested, and + * give the apf_interpreter a pointer to the middle of the buffer. This will + * allow firmware to later (during or after apf_transmit_buffer call) populate + * any required headers, trailers, etc. + * + * @param ctx - unmodified ctx pointer passed into apf_run(). + * @param size - the minimum size of buffer to allocate + * @return the pointer to the allocated region. The function can return NULL to + * indicate allocation failure, for example if too many buffers are + * pending transmit. Returning NULL will most likely result in the + * apf_run() returning PASS. */ -uint8_t* apf_allocate_buffer(uint32_t size); +uint8_t* apf_allocate_buffer(void* ctx, uint32_t size); /** - * Transmits the allocated buffer and deallocates the memory region. + * Transmits the allocated buffer and deallocates it. * - * The function is responsible to verify if the range [ptr, ptr + len) is within - * the buffer it allocated for the program when apf_transmit_buffer() is called. + * The apf_interpreter will not read/write from/to the buffer once it calls + * this function. * - * The content of the buffer between [ptr, ptr + len) is the transmit packet - * bytes, starting from the 802.3 header and not including any CRC bytes at the - * end. - * - * The firmware must guarantee the transmit packet is not modified after the APF - * calls the apf_transmit_buffer(). + * The content of the buffer between [ptr, ptr + len) are the bytes to be + * transmitted, starting from the ethernet header and not including any + * CRC bytes at the end. * * The firmware is expected to make its best effort to transmit. If it * exhausts retries, or if there is no channel for too long and the transmit - * queue is full, then it is OK for the packet to be dropped. - * - * @param ptr pointer to the transmit buffer - * @param len the length of buffer to be transmitted, 0 means don't transmit the - * buffer but only deallocate it - * @param dscp the first 6 bits of the TOS field in the IPv4 header or traffic + * queue is full, then it is OK for the packet to be dropped. The firmware should + * prefer to fail allocation if transmit is likely to fail. + * + * apf_transmit_buffer() should be asynchronous, which means the actual packet + * transmission can happen sometime after the function returns. + * + * @param ctx - unmodified ctx pointer passed into apf_run(). + * @param ptr - pointer to the transmit buffer, must have been previously + * returned by apf_allocate_buffer and not deallocated. + * @param len - the number of bytes to be transmitted (possibly less than + * the allocated buffer), 0 means don't transmit the buffer + * but only deallocate it + * @param dscp - the upper 6 bits of the TOS field in the IPv4 header or traffic * class field in the IPv6 header. + * @return non-zero if the firmware *knows* the transmit will fail, zero if + * the firmware thinks the transmit will succeed. Returning an error + * will likely result in apf_run() returning PASS. */ -void apf_transmit_buffer(uint8_t *ptr, uint32_t len, uint8_t dscp); +int apf_transmit_buffer(void* ctx, uint8_t* ptr, uint32_t len, uint8_t dscp); /** - * Runs a packet filtering program over a packet. + * Runs an APF program over a packet. * - * The return value of the apf_run indicates whether the packet should be - * passed to AP or not. As a part of apf_run execution, the packet filtering + * The return value of apf_run indicates whether the packet should + * be passed or dropped. As a part of apf_run execution, the APF * program can call apf_allocate_buffer()/apf_transmit_buffer() to construct - * an egress packet to transmit it. + * a reply packet and transmit it. * * The text section containing the program instructions starts at address * program and stops at + program_len - 1, and the writable data section * begins at program + program_len and ends at program + ram_len - 1, * as described in the following diagram: * - * program program + program_len program + ram_len - * | text section | data section | - * +--------------------+------------------------+ + * program program + program_len program + ram_len + * | text section | data section | + * +--------------------+------------------------+ * - * @param program the program bytecode, followed by the writable data region. - * @param program_len the length in bytes of the read-only portion of the APF + * @param ctx - pointer to any additional context required for allocation and transmit. + may be null if no such context is required. this is opaque to + the interpreter and will be passed through unmodified + to apf_allocate_buffer() and apf_transmit_buffer() calls. + * @param program - the program bytecode, followed by the writable data region. + * @param program_len - the length in bytes of the read-only portion of the APF * buffer pointed to by {@code program}. - * @param ram_len total length of the APF buffer pointed to by {@code program}, - * including the read-only bytecode portion and the read-write - * data portion. - * @param packet the packet bytes, starting from the 802.3 header and not - * including any CRC bytes at the end. - * @param packet_len the length of {@code packet} in bytes. - * @param filter_age the number of seconds since the filter was programmed. - * - * @return non-zero if packet should be passed to AP, zero if - * packet should be dropped. Return 1 indicating the packet is accepted - * without error. Negative return values are reserved for error code. + * @param ram_len - total length of the APF buffer pointed to by + * {@code program}, including the read-only bytecode + * portion and the read-write data portion. + * @param packet - the packet bytes, starting from the ethernet header. + * @param packet_len - the length of {@code packet} in bytes, not + * including trailers/CRC. + * @param filter_age_16384ths - the number of 1/16384 seconds since the filter + * was programmed. + * + * @return non-zero if packet should be passed, zero if packet should + * be dropped. */ -int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len, - const uint8_t* packet, uint32_t packet_len, - uint32_t filter_age); +int apf_run(void* ctx, uint8_t* const program, const uint32_t program_len, + const uint32_t ram_len, const uint8_t* const packet, + const uint32_t packet_len, const uint32_t filter_age_16384ths); #ifdef __cplusplus } diff --git a/v5/test_buf_allocator.c b/v5/test_buf_allocator.c index 1358063..a889dea 100644 --- a/v5/test_buf_allocator.c +++ b/v5/test_buf_allocator.c @@ -25,18 +25,11 @@ uint32_t apf_test_tx_packet_len; uint8_t apf_test_tx_dscp; /** - * Test implementation of apf_version() - */ -uint32_t apf_version() { - return 5; -} - -/** * Test implementation of apf_allocate_buffer() * * Clean up the apf_test_buffer and return the pointer to beginning of the buffer region. */ -uint8_t* apf_allocate_buffer(uint32_t size) { +uint8_t* apf_allocate_buffer(__attribute__ ((unused)) void* ctx, uint32_t size) { if (size > APF_TX_BUFFER_SIZE) { return NULL; } @@ -49,8 +42,10 @@ uint8_t* apf_allocate_buffer(uint32_t size) { * * Copy the content of allocated buffer to the apf_test_tx_packet region. */ -void apf_transmit_buffer(uint8_t* ptr, uint32_t len, uint8_t dscp) { +int apf_transmit_buffer(__attribute__((unused)) void* ctx, uint8_t* ptr, + uint32_t len, uint8_t dscp) { apf_test_tx_packet_len = len; apf_test_tx_dscp = dscp; - memcpy(apf_test_tx_packet, ptr, len); + memcpy(apf_test_tx_packet, ptr, (size_t) len); + return 0; } |