Updated PKTCOPY/DATACOPY opcode logic to reflect latest design. * design doc: go/apf-v6-proposal Bug: 293811969 Test: TH Change-Id: Ibff3a4b57db28c522e6b9b701b215c6d6e79c932
diff --git a/src/android/net/apf/ApfGenerator.java b/src/android/net/apf/ApfGenerator.java index 49fbf68..f465341 100644 --- a/src/android/net/apf/ApfGenerator.java +++ b/src/android/net/apf/ApfGenerator.java
@@ -86,11 +86,12 @@ // Write 1, 2 or 4 bytes immediate to the output buffer and auto-increment the pointer to // write. e.g. "write 5" WRITE(24), - // 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" - MEMCOPY(25); + // Copy memory region from input packet/APF program/data region to output buffer and + // auto-increment the output buffer pointer. + // Register bit is used to specify the source of data copy. R=0 means copy from packet, + // R=1 means copy from APF program/data region. + // e.g. "pktdatacopy 5, 5" + PKTDATACOPY(25); final int value; @@ -1099,53 +1100,38 @@ // return this; // } - // TODO: add back when support PKTCOPY/DATACOPY opcode -// /** -// * Add an instruction to the end of the program to copy data from APF data region to output -// * buffer. -// * -// * @param srcOffset the offset inside the APF data region for where to start copy -// * @param length the length of bytes needed to be copied, only <= 255 bytes can be copied at -// * one time. -// * @return the ApfGenerator object -// * @throws IllegalInstructionException throws when imm size is incorrectly set. -// */ -// public ApfGenerator addDataCopy(int srcOffset, int length) -// throws IllegalInstructionException { -// return addMemCopy(srcOffset, length, Register.R1); -// } -// -// /** -// * Add an instruction to the end of the program to copy data from input packet to output -// buffer. -// * -// * @param srcOffset the offset inside the input packet for where to start copy -// * @param length the length of bytes needed to be copied, only <= 255 bytes can be copied at -// * one time. -// * @return the ApfGenerator object -// * @throws IllegalInstructionException throws when imm size is incorrectly set. -// */ -// public ApfGenerator addPacketCopy(int srcOffset, int length) -// throws IllegalInstructionException { -// return addMemCopy(srcOffset, length, Register.R0); -// } -// -// private ApfGenerator addMemCopy(int srcOffset, int length, Register register) -// throws IllegalInstructionException { -// requireApfVersion(5); -// checkCopyLength(length); -// checkCopyOffset(srcOffset); -// Instruction instruction = new Instruction(Opcodes.MEMCOPY, register); -// // if the offset == 0, it should still be encoded with 1 byte size. -// if (srcOffset == 0) { -// instruction.addUnsignedImm(srcOffset, (byte) 1 /* size */); -// } else { -// instruction.addUnsignedImm(srcOffset); -// } -// instruction.addUnsignedImm(length, (byte) 1 /* size */); -// addInstruction(instruction); -// return this; -// } + /** + * Add an instruction to the end of the program to copy data from APF program/data region to + * output buffer and auto-increment the output buffer pointer. + * + * @param src the offset inside the APF program/data region for where to start copy. + * @param len the length of bytes needed to be copied, only <= 255 bytes can be copied at + * one time. + * @return the ApfGenerator object + */ + public ApfGenerator addDataCopy(int src, int len) + throws IllegalInstructionException { + requireApfVersion(MIN_APF_VERSION_IN_DEV); + return append(new Instruction(Opcodes.PKTDATACOPY, R1).addUnsignedIndeterminate( + src).addUnsigned8(len)); + } + + /** + * Add an instruction to the end of the program to copy data from input packet to output + * buffer and auto-increment the output buffer pointer. + * + * @param src the offset inside the input packet for where to start copy. + * @param len the length of bytes needed to be copied, only <= 255 bytes can be copied at + * one time. + * @return the ApfGenerator object + */ + public ApfGenerator addPacketCopy(int src, int len) + throws IllegalInstructionException { + requireApfVersion(MIN_APF_VERSION_IN_DEV); + return append(new Instruction(Opcodes.PKTDATACOPY, R0).addUnsignedIndeterminate( + src).addUnsigned8(len)); + } + // TODO: add back when support EPKTCOPY/EDATACOPY opcode // /** // * Add an instruction to the end of the program to copy data from APF data region to output
diff --git a/tests/unit/src/android/net/apf/ApfV5Test.kt b/tests/unit/src/android/net/apf/ApfV5Test.kt index 0fa73a4..318c243 100644 --- a/tests/unit/src/android/net/apf/ApfV5Test.kt +++ b/tests/unit/src/android/net/apf/ApfV5Test.kt
@@ -45,6 +45,8 @@ assertFailsWith<IllegalInstructionException> { gen.addWrite1(100) } assertFailsWith<IllegalInstructionException> { gen.addWrite2(100) } assertFailsWith<IllegalInstructionException> { gen.addWrite4(100) } + assertFailsWith<IllegalInstructionException> { gen.addPacketCopy(100, 100) } + assertFailsWith<IllegalInstructionException> { gen.addDataCopy(100, 100) } } @Test @@ -59,6 +61,12 @@ var gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV) assertFailsWith<IllegalArgumentException> { gen.addAllocate(65536) } assertFailsWith<IllegalArgumentException> { gen.addAllocate(-1) } + assertFailsWith<IllegalArgumentException> { gen.addDataCopy(-1, 1) } + assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(-1, 1) } + assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, 256) } + assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, 256) } + assertFailsWith<IllegalArgumentException> { gen.addDataCopy(1, -1) } + assertFailsWith<IllegalArgumentException> { gen.addPacketCopy(1, -1) } } @Test @@ -179,20 +187,23 @@ // " 2: write r0, 2", // " 4: write r0, 4"), ApfJniUtils.disassembleApf(program)) - // TODO: add back the following test case when implementing EPKTCOPY, EDATACOPY opcodes. -// gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV) -// gen.addDataCopy(1, 5) -// gen.addPacketCopy(1000, 255) -// program = gen.generate() -// assertContentEquals(byteArrayOf( -// encodeInstruction(25, 1, 1), 1, 5, -// encodeInstruction(25, 2, 0), -// 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(), -// ), program) + gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV) + gen.addDataCopy(0, 10) + gen.addDataCopy(1, 5) + gen.addPacketCopy(1000, 255) + program = gen.generate() + assertContentEquals(byteArrayOf( + encodeInstruction(25, 0, 1), 10, + encodeInstruction(25, 1, 1), 1, 5, + encodeInstruction(25, 2, 0), + 0x03.toByte(), 0xe8.toByte(), 0xff.toByte(), + ), program) + // TODO: add back disassembling test check after we update the apf_disassembler // assertContentEquals(arrayOf( -// " 0: dcopy 1, 5", +// " 0: dcopy 0, 5", // " 3: pcopy 1000, 255"), ApfJniUtils.disassembleApf(program)) -// + + // TODO: add back the following test case when implementing EPKTCOPY, EDATACOPY opcodes. // gen = ApfGenerator(ApfGenerator.MIN_APF_VERSION_IN_DEV) // gen.addDataCopy(ApfGenerator.Register.R1, 0, 5) // gen.addPacketCopy(ApfGenerator.Register.R0, 1000, 255)