Snap for 11544945 from ff19d0005a52bdde034c2739cdb0e49db72dcb1f to mainline-odp-release

Change-Id: I019f01de63a54f7037e013d5c3fed80e5db70c80
diff --git a/src/android/net/apf/ApfCounterTracker.java b/src/android/net/apf/ApfCounterTracker.java
index b2b52e9..d06aa57 100644
--- a/src/android/net/apf/ApfCounterTracker.java
+++ b/src/android/net/apf/ApfCounterTracker.java
@@ -64,6 +64,7 @@
         DROPPED_RA,
         DROPPED_GARP_REPLY,
         DROPPED_ARP_OTHER_HOST,
+        DROPPED_ARP_REQUEST_NO_ADDRESS,
         DROPPED_IPV4_L2_BROADCAST,
         DROPPED_IPV4_BROADCAST_ADDR,
         DROPPED_IPV4_BROADCAST_NET,
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 0b2c101..eb6da09 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -1293,7 +1293,7 @@
             gen.addSwap();
             gen.addLoad16(R0, IPV4_TOTAL_LENGTH_OFFSET);
             gen.addNeg(R1);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(1, nextFilterLabel);
 
             // Check that the ports match
@@ -1412,16 +1412,16 @@
             // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2.
             gen.addRightShift(2);
             // R0 += R1 -> R0 contains TCP + IP headers length
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             // Load IPv4 total length
             gen.addLoad16(R1, IPV4_TOTAL_LENGTH_OFFSET);
             gen.addNeg(R0);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(0, nextFilterLabel);
             // Add IPv4 header length
             gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
             gen.addLoadImmediate(R0, ETH_HEADER_LEN);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mPortSeqAckFingerprint, nextFilterLabel);
 
             maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK);
@@ -1526,9 +1526,15 @@
         maybeSetupCounter(gen, Counter.DROPPED_ARP_NON_IPV4);
         gen.addJumpIfBytesAtR0NotEqual(ARP_IPV4_HEADER, mCountAndDropLabel);
 
-        // Drop if unknown ARP opcode.
         gen.addLoad16(R0, ARP_OPCODE_OFFSET);
-        gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check
+        if (mIPv4Address == null) {
+            // Drop if ARP REQUEST and we do not have an IPv4 address
+            maybeSetupCounter(gen, Counter.DROPPED_ARP_REQUEST_NO_ADDRESS);
+            gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, mCountAndDropLabel);
+        } else {
+            gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check
+        }
+        // Drop if unknown ARP opcode.
         maybeSetupCounter(gen, Counter.DROPPED_ARP_UNKNOWN);
         gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndDropLabel);
 
@@ -1601,7 +1607,7 @@
             // Check it's DHCP to our MAC address.
             gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET);
             // NOTE: Relies on R1 containing IPv4 header offset.
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter);
             maybeSetupCounter(gen, Counter.PASSED_DHCP);
             gen.addJump(mCountAndPassLabel);
@@ -1876,7 +1882,7 @@
         // If QDCOUNT == 1, matches the QNAME with allowlist.
         // Load offset for the first QNAME.
         gen.addLoadImmediate(R0, MDNS_QNAME_OFFSET);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
 
         // Check first QNAME against allowlist
         for (int i = 0; i < mMdnsAllowList.size(); ++i) {
diff --git a/src/android/net/apf/ApfV4Generator.java b/src/android/net/apf/ApfV4Generator.java
index e1a017e..a1f7415 100644
--- a/src/android/net/apf/ApfV4Generator.java
+++ b/src/android/net/apf/ApfV4Generator.java
@@ -15,6 +15,8 @@
  */
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.Register.R1;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 /**
@@ -32,4 +34,8 @@
     public ApfV4Generator(int version) throws IllegalInstructionException {
         super(version);
     }
-}
\ No newline at end of file
+
+    final void addArithR1(Opcodes opcode) {
+        append(new Instruction(opcode, R1));
+    }
+}
diff --git a/src/android/net/apf/ApfV4GeneratorBase.java b/src/android/net/apf/ApfV4GeneratorBase.java
index 86caf7c..3ad3162 100644
--- a/src/android/net/apf/ApfV4GeneratorBase.java
+++ b/src/android/net/apf/ApfV4GeneratorBase.java
@@ -46,11 +46,11 @@
         requireApfVersion(MIN_APF_VERSION);
     }
 
-    protected Type self() {
+    final Type self() {
         return (Type) this;
     }
 
-    Type append(Instruction instruction) {
+    final Type append(Instruction instruction) {
         if (mGenerated) {
             throw new IllegalStateException("Program already generated");
         }
@@ -73,21 +73,21 @@
      * </pre>
      * In this case "next_filter" may not have any generated code associated with it.
      */
-    public Type defineLabel(String name) throws IllegalInstructionException {
+    public final Type defineLabel(String name) throws IllegalInstructionException {
         return append(new Instruction(Opcodes.LABEL).setLabel(name));
     }
 
     /**
      * Add an unconditional jump instruction to the end of the program.
      */
-    public Type addJump(String target) {
+    public final Type addJump(String target) {
         return append(new Instruction(Opcodes.JMP).setTargetLabel(target));
     }
 
     /**
      * Add an unconditional jump instruction to the next instruction - ie. a no-op.
      */
-    public Type addNop() {
+    public final Type addNop() {
         return append(new Instruction(Opcodes.JMP).addUnsigned(0));
     }
 
@@ -95,7 +95,7 @@
      * Add an instruction to the end of the program to load the byte at offset {@code offset}
      * bytes from the beginning of the packet into {@code register}.
      */
-    public Type addLoad8(Register r, int ofs) {
+    public final Type addLoad8(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDB, r).addPacketOffset(ofs));
     }
 
@@ -103,7 +103,7 @@
      * Add an instruction to the end of the program to load 16-bits at offset {@code offset}
      * bytes from the beginning of the packet into {@code register}.
      */
-    public Type addLoad16(Register r, int ofs) {
+    public final Type addLoad16(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDH, r).addPacketOffset(ofs));
     }
 
@@ -111,7 +111,7 @@
      * Add an instruction to the end of the program to load 32-bits at offset {@code offset}
      * bytes from the beginning of the packet into {@code register}.
      */
-    public Type addLoad32(Register r, int ofs) {
+    public final Type addLoad32(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDW, r).addPacketOffset(ofs));
     }
 
@@ -120,7 +120,7 @@
      * {@code register}. The offset of the loaded byte from the beginning of the packet is
      * the sum of {@code offset} and the value in register R1.
      */
-    public Type addLoad8Indexed(Register r, int ofs) {
+    public final Type addLoad8Indexed(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDBX, r).addPacketOffset(ofs));
     }
 
@@ -129,7 +129,7 @@
      * {@code register}. The offset of the loaded 16-bits from the beginning of the packet is
      * the sum of {@code offset} and the value in register R1.
      */
-    public Type addLoad16Indexed(Register r, int ofs) {
+    public final Type addLoad16Indexed(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDHX, r).addPacketOffset(ofs));
     }
 
@@ -138,14 +138,14 @@
      * {@code register}. The offset of the loaded 32-bits from the beginning of the packet is
      * the sum of {@code offset} and the value in register R1.
      */
-    public Type addLoad32Indexed(Register r, int ofs) {
+    public final Type addLoad32Indexed(Register r, int ofs) {
         return append(new Instruction(Opcodes.LDWX, r).addPacketOffset(ofs));
     }
 
     /**
      * Add an instruction to the end of the program to add {@code value} to register R0.
      */
-    public Type addAdd(long val) {
+    public final Type addAdd(long val) {
         if (val == 0) return self();  // nop, as APFv6 would '+= R1'
         return append(new Instruction(Opcodes.ADD).addTwosCompUnsigned(val));
     }
@@ -153,14 +153,14 @@
     /**
      * Add an instruction to the end of the program to subtract {@code value} from register R0.
      */
-    public Type addSub(long val) {
+    public final Type addSub(long val) {
         return addAdd(-val);  // note: addSub(4 billion) isn't valid, as addAdd(-4 billion) isn't
     }
 
     /**
      * Add an instruction to the end of the program to multiply register R0 by {@code value}.
      */
-    public Type addMul(long val) {
+    public final Type addMul(long val) {
         if (val == 0) return addLoadImmediate(R0, 0);  // equivalent, as APFv6 would '*= R1'
         return append(new Instruction(Opcodes.MUL).addUnsigned(val));
     }
@@ -168,7 +168,7 @@
     /**
      * Add an instruction to the end of the program to divide register R0 by {@code value}.
      */
-    public Type addDiv(long val) {
+    public final Type addDiv(long val) {
         if (val == 0) return addPass();  // equivalent, as APFv6 would '/= R1'
         return append(new Instruction(Opcodes.DIV).addUnsigned(val));
     }
@@ -176,7 +176,7 @@
     /**
      * Add an instruction to the end of the program to logically and register R0 with {@code value}.
      */
-    public Type addAnd(long val) {
+    public final Type addAnd(long val) {
         if (val == 0) return addLoadImmediate(R0, 0);  // equivalent, as APFv6 would '+= R1'
         return append(new Instruction(Opcodes.AND).addTwosCompUnsigned(val));
     }
@@ -184,7 +184,7 @@
     /**
      * Add an instruction to the end of the program to logically or register R0 with {@code value}.
      */
-    public Type addOr(long val) {
+    public final Type addOr(long val) {
         if (val == 0) return self();  // nop, as APFv6 would '|= R1'
         return append(new Instruction(Opcodes.OR).addTwosCompUnsigned(val));
     }
@@ -193,7 +193,7 @@
      * Add an instruction to the end of the program to shift left register R0 by {@code value} bits.
      */
     // TODO: consider whether should change the argument type to byte
-    public Type addLeftShift(int val) {
+    public final Type addLeftShift(int val) {
         if (val == 0) return self();  // nop, as APFv6 would '<<= R1'
         return append(new Instruction(Opcodes.SH).addSigned(val));
     }
@@ -203,19 +203,17 @@
      * bits.
      */
     // TODO: consider whether should change the argument type to byte
-    public Type addRightShift(int val) {
+    public final Type addRightShift(int val) {
         return addLeftShift(-val);
     }
 
     // Argument should be one of Opcodes.{ADD,MUL,DIV,AND,OR,SH}
-    protected void addArithR1(Opcodes opcode) {
-        append(new Instruction(opcode, R1));
-    }
+    abstract void addArithR1(Opcodes opcode);
 
     /**
      * Add an instruction to the end of the program to add register R1 to register R0.
      */
-    public Type addAddR1() {
+    public final Type addAddR1ToR0() {
         addArithR1(Opcodes.ADD);
         return self();
     }
@@ -223,7 +221,7 @@
     /**
      * Add an instruction to the end of the program to multiply register R0 by register R1.
      */
-    public Type addMulR1() {
+    public final Type addMulR0ByR1() {
         addArithR1(Opcodes.MUL);
         return self();
     }
@@ -231,7 +229,7 @@
     /**
      * Add an instruction to the end of the program to divide register R0 by register R1.
      */
-    public Type addDivR1() {
+    public final Type addDivR0ByR1() {
         addArithR1(Opcodes.DIV);
         return self();
     }
@@ -240,7 +238,7 @@
      * Add an instruction to the end of the program to logically and register R0 with register R1
      * and store the result back into register R0.
      */
-    public Type addAndR1() {
+    public final Type addAndR0WithR1() {
         addArithR1(Opcodes.AND);
         return self();
     }
@@ -249,7 +247,7 @@
      * Add an instruction to the end of the program to logically or register R0 with register R1
      * and store the result back into register R0.
      */
-    public Type addOrR1() {
+    public final Type addOrR0WithR1() {
         addArithR1(Opcodes.OR);
         return self();
     }
@@ -258,7 +256,7 @@
      * Add an instruction to the end of the program to shift register R0 left by the value in
      * register R1.
      */
-    public Type addLeftShiftR1() {
+    public final Type addLeftShiftR0ByR1() {
         addArithR1(Opcodes.SH);
         return self();
     }
@@ -266,7 +264,7 @@
     /**
      * Add an instruction to the end of the program to move {@code value} into {@code register}.
      */
-    public Type addLoadImmediate(Register register, int value) {
+    public final Type addLoadImmediate(Register register, int value) {
         return append(new Instruction(Opcodes.LI, register).addSigned(value));
     }
 
@@ -274,7 +272,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value equals {@code value}.
      */
-    public Type addJumpIfR0Equals(int val, String tgt) {
+    public final Type addJumpIfR0Equals(int val, String tgt) {
         return append(new Instruction(Opcodes.JEQ).addTwosCompUnsigned(val).setTargetLabel(tgt));
     }
 
@@ -282,7 +280,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value does not equal {@code value}.
      */
-    public Type addJumpIfR0NotEquals(int val, String tgt) {
+    public final Type addJumpIfR0NotEquals(int val, String tgt) {
         return append(new Instruction(Opcodes.JNE).addTwosCompUnsigned(val).setTargetLabel(tgt));
     }
 
@@ -290,7 +288,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value is greater than {@code value}.
      */
-    public Type addJumpIfR0GreaterThan(long val, String tgt) {
+    public final Type addJumpIfR0GreaterThan(long val, String tgt) {
         return append(new Instruction(Opcodes.JGT).addUnsigned(val).setTargetLabel(tgt));
     }
 
@@ -298,7 +296,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value is less than {@code value}.
      */
-    public Type addJumpIfR0LessThan(long val, String tgt) {
+    public final Type addJumpIfR0LessThan(long val, String tgt) {
         return append(new Instruction(Opcodes.JLT).addUnsigned(val).setTargetLabel(tgt));
     }
 
@@ -306,14 +304,14 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value has any bits set that are also set in {@code value}.
      */
-    public Type addJumpIfR0AnyBitsSet(int val, String tgt) {
+    public final Type addJumpIfR0AnyBitsSet(int val, String tgt) {
         return append(new Instruction(Opcodes.JSET).addTwosCompUnsigned(val).setTargetLabel(tgt));
     }
     /**
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value equals register R1's value.
      */
-    public Type addJumpIfR0EqualsR1(String tgt) {
+    public final Type addJumpIfR0EqualsR1(String tgt) {
         return append(new Instruction(Opcodes.JEQ, R1).setTargetLabel(tgt));
     }
 
@@ -321,7 +319,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value does not equal register R1's value.
      */
-    public Type addJumpIfR0NotEqualsR1(String tgt) {
+    public final Type addJumpIfR0NotEqualsR1(String tgt) {
         return append(new Instruction(Opcodes.JNE, R1).setTargetLabel(tgt));
     }
 
@@ -329,7 +327,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value is greater than register R1's value.
      */
-    public Type addJumpIfR0GreaterThanR1(String tgt) {
+    public final Type addJumpIfR0GreaterThanR1(String tgt) {
         return append(new Instruction(Opcodes.JGT, R1).setTargetLabel(tgt));
     }
 
@@ -337,7 +335,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value is less than register R1's value.
      */
-    public Type addJumpIfR0LessThanR1(String target) {
+    public final Type addJumpIfR0LessThanR1(String target) {
         return append(new Instruction(Opcodes.JLT, R1).setTargetLabel(target));
     }
 
@@ -345,7 +343,7 @@
      * Add an instruction to the end of the program to jump to {@code target} if register R0's
      * value has any bits set that are also set in R1's value.
      */
-    public Type addJumpIfR0AnyBitsSetR1(String tgt) {
+    public final Type addJumpIfR0AnyBitsSetR1(String tgt) {
         return append(new Instruction(Opcodes.JSET, R1).setTargetLabel(tgt));
     }
 
@@ -354,7 +352,7 @@
      * packet at an offset specified by {@code register} don't match {@code bytes}
      * R=0 means check for not equal
      */
-    public Type addJumpIfBytesAtR0NotEqual(byte[] bytes, String tgt) {
+    public final Type addJumpIfBytesAtR0NotEqual(byte[] bytes, String tgt) {
         return append(new Instruction(Opcodes.JNEBS).addUnsigned(
                 bytes.length).setTargetLabel(tgt).setBytesImm(bytes));
     }
@@ -364,7 +362,7 @@
      * packet at an offset specified by {@code register} match {@code bytes}
      * R=1 means check for equal.
      */
-    public Type addJumpIfBytesAtR0Equal(byte[] bytes, String tgt)
+    public final Type addJumpIfBytesAtR0Equal(byte[] bytes, String tgt)
             throws IllegalInstructionException {
         requireApfVersion(MIN_APF_VERSION_IN_DEV);
         return append(new Instruction(Opcodes.JNEBS, R1).addUnsigned(
@@ -375,7 +373,7 @@
      * Add an instruction to the end of the program to load memory slot {@code slot} into
      * {@code register}.
      */
-    public Type addLoadFromMemory(Register r, int slot)
+    public final Type addLoadFromMemory(Register r, int slot)
             throws IllegalInstructionException {
         return append(new BaseApfGenerator.Instruction(ExtendedOpcodes.LDM, slot, r));
     }
@@ -384,7 +382,7 @@
      * Add an instruction to the end of the program to store {@code register} into memory slot
      * {@code slot}.
      */
-    public Type addStoreToMemory(Register r, int slot)
+    public final Type addStoreToMemory(Register r, int slot)
             throws IllegalInstructionException {
         return append(new Instruction(ExtendedOpcodes.STM, slot, r));
     }
@@ -392,21 +390,21 @@
     /**
      * Add an instruction to the end of the program to logically not {@code register}.
      */
-    public Type addNot(Register r) {
+    public final Type addNot(Register r) {
         return append(new Instruction(ExtendedOpcodes.NOT, r));
     }
 
     /**
      * Add an instruction to the end of the program to negate {@code register}.
      */
-    public Type addNeg(Register r) {
+    public final Type addNeg(Register r) {
         return append(new Instruction(ExtendedOpcodes.NEG, r));
     }
 
     /**
      * Add an instruction to swap the values in register R0 and register R1.
      */
-    public Type addSwap() {
+    public final Type addSwap() {
         return append(new Instruction(ExtendedOpcodes.SWAP));
     }
 
@@ -414,14 +412,14 @@
      * Add an instruction to the end of the program to move the value into
      * {@code register} from the other register.
      */
-    public Type addMove(Register r) {
+    public final Type addMove(Register r) {
         return append(new Instruction(ExtendedOpcodes.MOVE, r));
     }
 
     /**
      * Add an instruction to the end of the program to let the program immediately return PASS.
      */
-    public Type addPass() {
+    public final Type addPass() {
         // PASS requires using Rbit0 because it shares opcode with DROP
         return append(new Instruction(Opcodes.PASSDROP, Rbit0));
     }
@@ -432,7 +430,7 @@
      * @{code offset} to the other register.
      * Requires APF v4 or greater.
      */
-    public Type addLoadData(Register dst, int ofs)
+    public final Type addLoadData(Register dst, int ofs)
             throws IllegalInstructionException {
         requireApfVersion(APF_VERSION_4);
         return append(new Instruction(Opcodes.LDDW, dst).addSigned(ofs));
@@ -444,7 +442,7 @@
      * @{code offset} to the other register.
      * Requires APF v4 or greater.
      */
-    public Type addStoreData(Register src, int ofs)
+    public final Type addStoreData(Register src, int ofs)
             throws IllegalInstructionException {
         requireApfVersion(APF_VERSION_4);
         return append(new Instruction(Opcodes.STDW, src).addSigned(ofs));
diff --git a/src/android/net/apf/ApfV6Generator.java b/src/android/net/apf/ApfV6Generator.java
index de1beb7..8608019 100644
--- a/src/android/net/apf/ApfV6Generator.java
+++ b/src/android/net/apf/ApfV6Generator.java
@@ -15,6 +15,8 @@
  */
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.Register.R1;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 /**
@@ -32,4 +34,8 @@
     public ApfV6Generator() throws IllegalInstructionException {
         super();
     }
-}
\ No newline at end of file
+
+    final void addArithR1(Opcodes opcode) {
+        append(new Instruction(opcode, R1));
+    }
+}
diff --git a/src/android/net/apf/ApfV6GeneratorBase.java b/src/android/net/apf/ApfV6GeneratorBase.java
index fc7cdd8..6882899 100644
--- a/src/android/net/apf/ApfV6GeneratorBase.java
+++ b/src/android/net/apf/ApfV6GeneratorBase.java
@@ -32,6 +32,10 @@
 public abstract class ApfV6GeneratorBase<Type extends ApfV6GeneratorBase<Type>> extends
         ApfV4GeneratorBase<Type> {
 
+    // We have not *yet* switched to APFv6 mode (see addData),
+    // and are thus still in APFv2/4 backward compatibility mode.
+    boolean mIsV6 = false;
+
     /**
      * Creates an ApfV6GeneratorBase instance which is able to emit instructions for the specified
      * {@code version} of the APF interpreter. Throws {@code IllegalInstructionException} if
@@ -46,7 +50,7 @@
      * Add an instruction to the end of the program to increment the counter value and
      * immediately return PASS.
      */
-    public Type addCountAndPass(int cnt) {
+    public final Type addCountAndPass(int cnt) {
         checkRange("CounterNumber", cnt /* value */, 1 /* lowerBound */,
                 1000 /* upperBound */);
         // PASS requires using Rbit0 because it shares opcode with DROP
@@ -56,7 +60,7 @@
     /**
      * Add an instruction to the end of the program to let the program immediately return DROP.
      */
-    public Type addDrop() {
+    public final Type addDrop() {
         // DROP requires using Rbit1 because it shares opcode with PASS
         return append(new Instruction(Opcodes.PASSDROP, Rbit1));
     }
@@ -65,7 +69,7 @@
      * Add an instruction to the end of the program to increment the counter value and
      * immediately return DROP.
      */
-    public Type addCountAndDrop(int cnt) {
+    public final Type addCountAndDrop(int cnt) {
         checkRange("CounterNumber", cnt /* value */, 1 /* lowerBound */,
                 1000 /* upperBound */);
         // DROP requires using Rbit1 because it shares opcode with PASS
@@ -76,7 +80,7 @@
      * Add an instruction to the end of the program to call the apf_allocate_buffer() function.
      * Buffer length to be allocated is stored in register 0.
      */
-    public Type addAllocateR0() {
+    public final Type addAllocateR0() {
         return append(new Instruction(ExtendedOpcodes.ALLOCATE));
     }
 
@@ -85,7 +89,7 @@
      *
      * @param size the buffer length to be allocated.
      */
-    public Type addAllocate(int size) {
+    public final Type addAllocate(int size) {
         // Rbit1 means the extra be16 immediate is present
         return append(new Instruction(ExtendedOpcodes.ALLOCATE, Rbit1).addU16(size));
     }
@@ -94,10 +98,11 @@
      * Add an instruction to the beginning of the program to reserve the data region.
      * @param data the actual data byte
      */
-    public Type addData(byte[] data) throws IllegalInstructionException {
+    public final Type addData(byte[] data) throws IllegalInstructionException {
         if (!mInstructions.isEmpty()) {
             throw new IllegalInstructionException("data instruction has to come first");
         }
+        mIsV6 = true;
         return append(new Instruction(Opcodes.JMP, Rbit1).addUnsigned(data.length)
                 .setBytesImm(data));
     }
@@ -106,14 +111,14 @@
      * Add an instruction to the end of the program to transmit the allocated buffer without
      * checksum.
      */
-    public Type addTransmitWithoutChecksum() {
+    public final Type addTransmitWithoutChecksum() {
         return addTransmit(-1 /* ipOfs */);
     }
 
     /**
      * Add an instruction to the end of the program to transmit the allocated buffer.
      */
-    public Type addTransmit(int ipOfs) {
+    public final Type addTransmit(int ipOfs) {
         if (ipOfs >= 255) {
             throw new IllegalArgumentException("IP offset of " + ipOfs + " must be < 255");
         }
@@ -124,7 +129,7 @@
     /**
      * Add an instruction to the end of the program to transmit the allocated buffer.
      */
-    public Type addTransmitL4(int ipOfs, int csumOfs, int csumStart, int partialCsum,
+    public final Type addTransmitL4(int ipOfs, int csumOfs, int csumStart, int partialCsum,
                                         boolean isUdp) {
         if (ipOfs >= 255) {
             throw new IllegalArgumentException("IP offset of " + ipOfs + " must be < 255");
@@ -141,21 +146,21 @@
     /**
      * Add an instruction to the end of the program to write 1 byte value to output buffer.
      */
-    public Type addWriteU8(int val) {
+    public final Type addWriteU8(int val) {
         return append(new Instruction(Opcodes.WRITE).overrideLenField(1).addU8(val));
     }
 
     /**
      * Add an instruction to the end of the program to write 2 bytes value to output buffer.
      */
-    public Type addWriteU16(int val) {
+    public final Type addWriteU16(int val) {
         return append(new Instruction(Opcodes.WRITE).overrideLenField(2).addU16(val));
     }
 
     /**
      * Add an instruction to the end of the program to write 4 bytes value to output buffer.
      */
-    public Type addWriteU32(long val) {
+    public final Type addWriteU32(long val) {
         return append(new Instruction(Opcodes.WRITE).overrideLenField(4).addU32(val));
     }
 
@@ -163,7 +168,7 @@
      * Add an instruction to the end of the program to write 1 byte value from register to output
      * buffer.
      */
-    public Type addWriteU8(Register reg) {
+    public final Type addWriteU8(Register reg) {
         return append(new Instruction(ExtendedOpcodes.EWRITE1, reg));
     }
 
@@ -171,7 +176,7 @@
      * Add an instruction to the end of the program to write 2 byte value from register to output
      * buffer.
      */
-    public Type addWriteU16(Register reg) {
+    public final Type addWriteU16(Register reg) {
         return append(new Instruction(ExtendedOpcodes.EWRITE2, reg));
     }
 
@@ -179,7 +184,7 @@
      * Add an instruction to the end of the program to write 4 byte value from register to output
      * buffer.
      */
-    public Type addWriteU32(Register reg) {
+    public final Type addWriteU32(Register reg) {
         return append(new Instruction(ExtendedOpcodes.EWRITE4, reg));
     }
 
@@ -192,7 +197,7 @@
      *               one time.
      * @return the Type object
      */
-    public Type addDataCopy(int src, int len) {
+    public final Type addDataCopy(int src, int len) {
         return append(new Instruction(Opcodes.PKTDATACOPY, Rbit1).addDataOffset(src).addU8(len));
     }
 
@@ -205,7 +210,7 @@
      *               one time.
      * @return the Type object
      */
-    public Type addPacketCopy(int src, int len) {
+    public final Type addPacketCopy(int src, int len) {
         return append(new Instruction(Opcodes.PKTDATACOPY, Rbit0).addPacketOffset(src).addU8(len));
     }
 
@@ -217,7 +222,7 @@
      * @param len the number of bytes to be copied, only <= 255 bytes can be copied at once.
      * @return the Type object
      */
-    public Type addDataCopyFromR0(int len) {
+    public final Type addDataCopyFromR0(int len) {
         return append(new Instruction(ExtendedOpcodes.EPKTDATACOPYIMM, Rbit1).addU8(len));
     }
 
@@ -229,7 +234,7 @@
      * @param len the number of bytes to be copied, only <= 255 bytes can be copied at once.
      * @return the Type object
      */
-    public Type addPacketCopyFromR0(int len) {
+    public final Type addPacketCopyFromR0(int len) {
         return append(new Instruction(ExtendedOpcodes.EPKTDATACOPYIMM, Rbit0).addU8(len));
     }
 
@@ -241,7 +246,7 @@
      *
      * @return the Type object
      */
-    public Type addDataCopyFromR0LenR1() {
+    public final Type addDataCopyFromR0LenR1() {
         return append(new Instruction(ExtendedOpcodes.EPKTDATACOPYR1, Rbit1));
     }
 
@@ -253,7 +258,7 @@
      *
      * @return the Type object
      */
-    public Type addPacketCopyFromR0LenR1() {
+    public final Type addPacketCopyFromR0LenR1() {
         return append(new Instruction(ExtendedOpcodes.EPKTDATACOPYR1, Rbit0));
     }
 
@@ -264,7 +269,7 @@
      * R = 0 means check for "does not contain".
      * Drops packets if packets are corrupted.
      */
-    public Type addJumpIfPktAtR0DoesNotContainDnsQ(@NonNull byte[] qnames, int qtype,
+    public final Type addJumpIfPktAtR0DoesNotContainDnsQ(@NonNull byte[] qnames, int qtype,
                                                              @NonNull String tgt) {
         validateNames(qnames);
         return append(new Instruction(ExtendedOpcodes.JDNSQMATCH, Rbit0).setTargetLabel(tgt).addU8(
@@ -275,7 +280,7 @@
      * Same as {@link #addJumpIfPktAtR0DoesNotContainDnsQ} except passes packets if packets are
      * corrupted.
      */
-    public Type addJumpIfPktAtR0DoesNotContainDnsQSafe(@NonNull byte[] qnames, int qtype,
+    public final Type addJumpIfPktAtR0DoesNotContainDnsQSafe(@NonNull byte[] qnames, int qtype,
             @NonNull String tgt) {
         validateNames(qnames);
         return append(new Instruction(ExtendedOpcodes.JDNSQMATCHSAFE, Rbit0).setTargetLabel(
@@ -289,7 +294,7 @@
      * R = 1 means check for "contain".
      * Drops packets if packets are corrupted.
      */
-    public Type addJumpIfPktAtR0ContainDnsQ(@NonNull byte[] qnames, int qtype,
+    public final Type addJumpIfPktAtR0ContainDnsQ(@NonNull byte[] qnames, int qtype,
                                                       @NonNull String tgt) {
         validateNames(qnames);
         return append(new Instruction(ExtendedOpcodes.JDNSQMATCH, Rbit1).setTargetLabel(tgt).addU8(
@@ -300,7 +305,7 @@
      * Same as {@link #addJumpIfPktAtR0ContainDnsQ} except passes packets if packets are
      * corrupted.
      */
-    public Type addJumpIfPktAtR0ContainDnsQSafe(@NonNull byte[] qnames, int qtype,
+    public final Type addJumpIfPktAtR0ContainDnsQSafe(@NonNull byte[] qnames, int qtype,
             @NonNull String tgt) {
         validateNames(qnames);
         return append(new Instruction(ExtendedOpcodes.JDNSQMATCHSAFE, Rbit1).setTargetLabel(
@@ -314,7 +319,7 @@
      * R = 0 means check for "does not contain".
      * Drops packets if packets are corrupted.
      */
-    public Type addJumpIfPktAtR0DoesNotContainDnsA(@NonNull byte[] names,
+    public final Type addJumpIfPktAtR0DoesNotContainDnsA(@NonNull byte[] names,
                                                              @NonNull String tgt) {
         validateNames(names);
         return append(new Instruction(ExtendedOpcodes.JDNSAMATCH, Rbit0).setTargetLabel(tgt)
@@ -325,7 +330,7 @@
      * Same as {@link #addJumpIfPktAtR0DoesNotContainDnsA} except passes packets if packets are
      * corrupted.
      */
-    public Type addJumpIfPktAtR0DoesNotContainDnsASafe(@NonNull byte[] names,
+    public final Type addJumpIfPktAtR0DoesNotContainDnsASafe(@NonNull byte[] names,
             @NonNull String tgt) {
         validateNames(names);
         return append(new Instruction(ExtendedOpcodes.JDNSAMATCHSAFE, Rbit0).setTargetLabel(tgt)
@@ -339,7 +344,7 @@
      * R = 1 means check for "contain".
      * Drops packets if packets are corrupted.
      */
-    public Type addJumpIfPktAtR0ContainDnsA(@NonNull byte[] names,
+    public final Type addJumpIfPktAtR0ContainDnsA(@NonNull byte[] names,
                                                       @NonNull String tgt) {
         validateNames(names);
         return append(new Instruction(ExtendedOpcodes.JDNSAMATCH, Rbit1).setTargetLabel(
@@ -350,7 +355,7 @@
      * Same as {@link #addJumpIfPktAtR0ContainDnsA} except passes packets if packets are
      * corrupted.
      */
-    public Type addJumpIfPktAtR0ContainDnsASafe(@NonNull byte[] names,
+    public final Type addJumpIfPktAtR0ContainDnsASafe(@NonNull byte[] names,
             @NonNull String tgt) {
         validateNames(names);
         return append(new Instruction(ExtendedOpcodes.JDNSAMATCHSAFE, Rbit1).setTargetLabel(
diff --git a/src/android/net/apf/BaseApfGenerator.java b/src/android/net/apf/BaseApfGenerator.java
index 7d23604..d8eda03 100644
--- a/src/android/net/apf/BaseApfGenerator.java
+++ b/src/android/net/apf/BaseApfGenerator.java
@@ -388,7 +388,6 @@
             return this;
         }
 
-
         Instruction addTwosCompUnsigned(long imm) {
             mIntImms.add(IntImmediate.newTwosComplementUnsigned(imm));
             return this;
diff --git a/src/android/net/apf/DnsUtils.java b/src/android/net/apf/DnsUtils.java
index 4fa02be..5afe1d5 100644
--- a/src/android/net/apf/DnsUtils.java
+++ b/src/android/net/apf/DnsUtils.java
@@ -145,7 +145,7 @@
         gen.addLoad16Indexed(R0, 0);
         gen.addAnd(0x3ff);
         gen.addLoadFromMemory(R1, SLOT_DNS_HEADER_OFFSET);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addLoadFromMemory(R1, SLOT_CURRENT_PARSE_OFFSET);
         gen.addJumpIfR0EqualsR1(ApfV4Generator.DROP_LABEL);
         gen.addJumpIfR0GreaterThanR1(ApfV4Generator.DROP_LABEL);
@@ -228,7 +228,7 @@
         gen.addJumpIfR0Equals(0, labelFindNextDnsQuestionNoPointer);
         // It's a pointer. Skip the pointer and question, and return.
         gen.addLoadImmediate(R0, POINTER_AND_QUESTION_HEADER_SIZE);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addStoreToMemory(R0, SLOT_CURRENT_PARSE_OFFSET);
         gen.addJump(labelFindNextDnsQuestionReturn);
 
@@ -240,14 +240,14 @@
         // Skip the label (1 byte) and query (2 bytes qtype, 2 bytes qclass) and return.
         gen.addJumpIfR0NotEquals(0, labelFindNextDnsQuestionLabel);
         gen.addLoadImmediate(R0, LABEL_AND_QUESTION_HEADER_SIZE);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addStoreToMemory(R0, SLOT_CURRENT_PARSE_OFFSET);
         gen.addJump(labelFindNextDnsQuestionReturn);
 
         // Non-zero length label. Consume it and continue.
         gen.defineLabel(labelFindNextDnsQuestionLabel);
         gen.addAdd(1);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addMove(R1);
         gen.addJump(labelFindNextDnsQuestionLoop);
 
diff --git a/src/android/net/apf/LegacyApfFilter.java b/src/android/net/apf/LegacyApfFilter.java
index 20a9e33..6146b97 100644
--- a/src/android/net/apf/LegacyApfFilter.java
+++ b/src/android/net/apf/LegacyApfFilter.java
@@ -1075,7 +1075,7 @@
             gen.addSwap();
             gen.addLoad16(R0, IPV4_TOTAL_LENGTH_OFFSET);
             gen.addNeg(R1);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(1, nextFilterLabel);
 
             // Check that the ports match
@@ -1194,16 +1194,16 @@
             // top bits of the low nibble are guaranteed to be zeroes. Right-shift R0 by 2.
             gen.addRightShift(2);
             // R0 += R1 -> R0 contains TCP + IP headers length
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             // Load IPv4 total length
             gen.addLoad16(R1, IPV4_TOTAL_LENGTH_OFFSET);
             gen.addNeg(R0);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(0, nextFilterLabel);
             // Add IPv4 header length
             gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
             gen.addLoadImmediate(R0, ETH_HEADER_LEN);
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mPortSeqAckFingerprint, nextFilterLabel);
 
             maybeSetupCounter(gen, Counter.DROPPED_IPV4_KEEPALIVE_ACK);
@@ -1395,7 +1395,7 @@
             // Check it's DHCP to our MAC address.
             gen.addLoadImmediate(R0, DHCP_CLIENT_MAC_OFFSET);
             // NOTE: Relies on R1 containing IPv4 header offset.
-            gen.addAddR1();
+            gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mHardwareAddress, skipDhcpv4Filter);
             maybeSetupCounter(gen, Counter.PASSED_DHCP);
             gen.addJump(mCountAndPassLabel);
@@ -1660,7 +1660,7 @@
         // If QDCOUNT == 1, matches the QNAME with allowlist.
         // Load offset for the first QNAME.
         gen.addLoadImmediate(R0, MDNS_QNAME_OFFSET);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
 
         // Check first QNAME against allowlist
         for (int i = 0; i < mMdnsAllowList.size(); ++i) {
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index 7f2e611..adb956f 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -388,21 +388,21 @@
         // Test add.
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R1, 1234567890);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfR0Equals(1234567890, DROP_LABEL);
         assertDrop(gen);
 
         // Test subtract.
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R1, -1234567890);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfR0Equals(-1234567890, DROP_LABEL);
         assertDrop(gen);
 
         // Test or.
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R1, 1234567890);
-        gen.addOrR1();
+        gen.addOrR0WithR1();
         gen.addJumpIfR0Equals(1234567890, DROP_LABEL);
         assertDrop(gen);
 
@@ -410,7 +410,7 @@
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R0, 1234567890);
         gen.addLoadImmediate(R1, 123456789);
-        gen.addAndR1();
+        gen.addAndR0WithR1();
         gen.addJumpIfR0Equals(1234567890 & 123456789, DROP_LABEL);
         assertDrop(gen);
 
@@ -418,7 +418,7 @@
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R0, 1234567890);
         gen.addLoadImmediate(R1, 1);
-        gen.addLeftShiftR1();
+        gen.addLeftShiftR0ByR1();
         gen.addJumpIfR0Equals(1234567890 << 1, DROP_LABEL);
         assertDrop(gen);
 
@@ -426,7 +426,7 @@
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R0, 1234567890);
         gen.addLoadImmediate(R1, -1);
-        gen.addLeftShiftR1();
+        gen.addLeftShiftR0ByR1();
         gen.addJumpIfR0Equals(1234567890 >> 1, DROP_LABEL);
         assertDrop(gen);
 
@@ -434,7 +434,7 @@
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R0, 123456789);
         gen.addLoadImmediate(R1, 2);
-        gen.addMulR1();
+        gen.addMulR0ByR1();
         gen.addJumpIfR0Equals(123456789 * 2, DROP_LABEL);
         assertDrop(gen);
 
@@ -442,13 +442,13 @@
         gen = new ApfV4Generator(MIN_APF_VERSION);
         gen.addLoadImmediate(R0, 1234567890);
         gen.addLoadImmediate(R1, 2);
-        gen.addDivR1();
+        gen.addDivR0ByR1();
         gen.addJumpIfR0Equals(1234567890 / 2, DROP_LABEL);
         assertDrop(gen);
 
         // Test divide by zero.
         gen = new ApfV4Generator(MIN_APF_VERSION);
-        gen.addDivR1();
+        gen.addDivR0ByR1();
         gen.addJump(DROP_LABEL);
         assertPass(gen);
 
@@ -1940,8 +1940,8 @@
 
     private void verifyArpFilter(byte[] program, int filterResult) {
         // Verify ARP request packet
-        assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
-        assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
+        assertVerdict(filterResult, program, arpRequestBroadcast(MOCK_IPV4_ADDR));
+        assertDrop(program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
         assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
 
         // Verify ARP reply packets from different source ip
@@ -1968,17 +1968,17 @@
         TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback,
                 mNetworkQuirkMetrics);
 
-        // Verify initially ARP request filter is off, and GARP filter is on.
-        verifyArpFilter(ipClientCallback.assertProgramUpdateAndGet(), PASS);
+        // Verify initially ARP request filter and GARP filter are on.
+        verifyArpFilter(ipClientCallback.assertProgramUpdateAndGet(), DROP);
 
         // Inform ApfFilter of our address and verify ARP filtering is on
         LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
         LinkProperties lp = new LinkProperties();
         assertTrue(lp.addLinkAddress(linkAddress));
-        verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), DROP);
+        verifyArpFilter(getProgram(ipClientCallback, apfFilter, lp), PASS);
 
-        // Inform ApfFilter of loss of IP and verify ARP filtering is off
-        verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), PASS);
+        // Inform ApfFilter of loss of IP and verify ARP filtering is on
+        verifyArpFilter(getProgram(ipClientCallback, apfFilter, new LinkProperties()), DROP);
 
         apfFilter.shutdown();
     }
@@ -3545,7 +3545,7 @@
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_159");
         gen.addLoadImmediate(R0, 50);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("e212507c6345"), "LABEL_159");
         gen.addLoadImmediate(R1, -12);
         gen.addJump("LABEL_498");
@@ -3698,7 +3698,7 @@
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_151");
         gen.addLoadImmediate(R0, 50);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("f683d58f832b"), "LABEL_151");
         gen.addLoadImmediate(R1, -12);
         gen.addJump("LABEL_277");
@@ -3819,7 +3819,7 @@
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_157");
         gen.addLoadImmediate(R0, 50);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("ea42226789c0"), "LABEL_157");
         gen.addLoadImmediate(R1, -12);
         gen.addJump("LABEL_339");
@@ -3843,7 +3843,7 @@
         gen.addSwap();
         gen.addLoad16(R0, 16);
         gen.addNeg(R1);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfR0NotEquals(0x1, "LABEL_243");
         gen.addLoadFromMemory(R0, 13);
         gen.addAdd(14);
@@ -3961,7 +3961,7 @@
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_165");
         gen.addLoadImmediate(R0, 50);
-        gen.addAddR1();
+        gen.addAddR1ToR0();
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc7008"), "LABEL_165");
         gen.addLoadImmediate(R1, -24);
         gen.addJump("LABEL_576");
diff --git a/tests/unit/src/android/net/apf/Bpf2Apf.java b/tests/unit/src/android/net/apf/Bpf2Apf.java
index 5d2f9a9..57c560e 100644
--- a/tests/unit/src/android/net/apf/Bpf2Apf.java
+++ b/tests/unit/src/android/net/apf/Bpf2Apf.java
@@ -163,17 +163,17 @@
                 if (arg.equals("x")) {
                     switch(opcode) {
                         case "add":
-                            gen.addAddR1();
+                            gen.addAddR1ToR0();
                             break;
                         case "and":
-                            gen.addAndR1();
+                            gen.addAndR0WithR1();
                             break;
                         case "or":
-                            gen.addOrR1();
+                            gen.addOrR0WithR1();
                             break;
                         case "sub":
                             gen.addNeg(R1);
-                            gen.addAddR1();
+                            gen.addAddR1ToR0();
                             gen.addNeg(R1);
                             break;
                     }