summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuyang Huang <yuyanghuang@google.com>2023-10-10 17:07:08 +0900
committerYuyang Huang <yuyanghuang@google.com>2023-10-13 16:26:49 +0900
commitebbf60d82b6c466af599a6c2af59b46a916d158b (patch)
treed50b79d0bcb61b3d0a3c845dcac3b093a58199c9
parent178ebe0278d3b20e8993a17e3e7962c553a62ed3 (diff)
downloadapf-ebbf60d82b6c466af599a6c2af59b46a916d158b.tar.gz
Support TRANS opcode
The TRANS opcode will trigger the call to apf_transmit_buffer() to actually transmit the packet. The APF program will continue to execute without waiting the packet transmit to be finished. Bug: 293811969 Test: TH Change-Id: I4150d7b087591f59b9b1f619f7309dc56d85062d
-rw-r--r--v5/apf.h5
-rw-r--r--v5/apf_interpreter.c23
2 files changed, 28 insertions, 0 deletions
diff --git a/v5/apf.h b/v5/apf.h
index b9cee6e..c3a7cbc 100644
--- a/v5/apf.h
+++ b/v5/apf.h
@@ -124,6 +124,10 @@
// Number of temporary memory slots, see ldm/stm instructions.
#define MEMORY_ITEMS 16
// Upon program execution, some temporary memory slots are prefilled:
+
+// Offset inside the output buffer where the next byte of output packet should
+// be written to.
+#define MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET 10
#define MEMORY_OFFSET_PROGRAM_SIZE 11 // Size of program (in bytes)
#define MEMORY_OFFSET_DATA_SIZE 12 // Total size of program + data
#define MEMORY_OFFSET_IPV4_HEADER_SIZE 13 // 4*([APF_FRAME_HEADER_SIZE]&15)
@@ -166,6 +170,7 @@
#define SWAP_EXT_OPCODE 34 // Swap, e.g. "swap R0,R1"
#define MOV_EXT_OPCODE 35 // Move, e.g. "move R0,R1"
#define ALLOC_EXT_OPCODE 36 // Allocate buffer, "e.g. ALLOC R0"
+#define TRANS_EXT_OPCODE 37 // Transmit buffer, "e.g. TRANS R0"
#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 cfb69e2..3cef719 100644
--- a/v5/apf_interpreter.c
+++ b/v5/apf_interpreter.c
@@ -70,6 +70,7 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len,
// Memory slot values.
uint32_t memory[MEMORY_ITEMS] = {};
// Fill in pre-filled memory slot values.
+ memory[MEMORY_OFFSET_OUTPUT_BUFFER_OFFSET] = 0;
memory[MEMORY_OFFSET_PROGRAM_SIZE] = program_len;
memory[MEMORY_OFFSET_DATA_SIZE] = ram_len;
memory[MEMORY_OFFSET_PACKET_SIZE] = packet_len;
@@ -280,9 +281,31 @@ int apf_run(uint8_t* program, uint32_t program_len, uint32_t ram_len,
REG = OTHER_REG;
break;
case ALLOC_EXT_OPCODE:
+ ASSERT_RETURN(allocated_buffer == NULL);
allocate_buffer_len = REG;
allocated_buffer = apf_allocate_buffer(allocate_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];
+ // If pkt_len > allocate_buffer_len, it means sth. wrong
+ // happened and the allocated_buffer should be deallocated.
+ if (pkt_len > allocate_buffer_len) {
+ apf_transmit_buffer(
+ allocated_buffer,
+ 0 /* len */,
+ 0 /* dscp */);
+ return PASS_PACKET;
+ }
+ // TODO: calculate packet checksum and get dscp
+ apf_transmit_buffer(
+ allocated_buffer,
+ pkt_len,
+ 0 /* dscp */);
+ allocated_buffer = NULL;
break;
// Unknown extended opcode
default: