Apf: introduce MemorySlot enum

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I0307d3fb88faf831403e0f2accf3db11393fef97
diff --git a/src/android/net/apf/ApfConstant.java b/src/android/net/apf/ApfConstant.java
index bb03bcc..68580be 100644
--- a/src/android/net/apf/ApfConstant.java
+++ b/src/android/net/apf/ApfConstant.java
@@ -56,7 +56,7 @@
 
     public static final int IPPROTO_HOPOPTS = 0;
 
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
+    // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE
     public static final int TCP_UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
     public static final int UDP_HEADER_LEN = 8;
 
@@ -64,7 +64,6 @@
 
     public static final int DHCP_SERVER_PORT = 67;
     public static final int DHCP_CLIENT_PORT = 68;
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
 
     public static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
     public static final byte[] ARP_IPV4_HEADER = {
@@ -92,7 +91,7 @@
     public static final int ECHO_PORT = 7;
     public static final int DNS_HEADER_LEN = 12;
     public static final int DNS_QDCOUNT_OFFSET = 4;
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT, or the
+    // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE, or the
     // IPv6 header length.
     public static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
     public static final int MDNS_QDCOUNT_OFFSET =
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index e568281..986bd2e 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -57,12 +57,9 @@
 import static android.net.apf.ApfConstant.MDNS_QNAME_OFFSET;
 import static android.net.apf.ApfConstant.TCP_HEADER_SIZE_OFFSET;
 import static android.net.apf.ApfConstant.TCP_UDP_DESTINATION_PORT_OFFSET;
-import static android.net.apf.BaseApfGenerator.FILTER_AGE_MEMORY_SLOT;
-import static android.net.apf.BaseApfGenerator.IPV4_HEADER_SIZE_MEMORY_SLOT;
-import static android.net.apf.BaseApfGenerator.PACKET_SIZE_MEMORY_SLOT;
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 import static android.net.apf.BaseApfGenerator.Register.R1;
-import static android.net.apf.BaseApfGenerator.TX_BUFFER_OUTPUT_POINTER_MEMORY_SLOT;
 import static android.net.util.SocketUtils.makePacketSocketAddress;
 import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
 import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
@@ -1114,10 +1111,10 @@
                 throws IllegalInstructionException {
             String nextFilterLabel = "Ra" + getUniqueNumberLocked();
             // Skip if packet is not the right size
-            gen.addLoadFromMemory(R0, PACKET_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE);
             gen.addJumpIfR0NotEquals(mPacket.capacity(), nextFilterLabel);
             // Skip filter if expired
-            gen.addLoadFromMemory(R0, FILTER_AGE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
             gen.addJumpIfR0GreaterThan(getRemainingFilterLft(timeSeconds), nextFilterLabel);
             for (PacketSection section : mPacketSections) {
                 // Generate code to match the packet bytes.
@@ -1262,7 +1259,7 @@
 
             // A NAT-T keepalive packet contains 1 byte payload with the value 0xff
             // Check payload length is 1
-            gen.addLoadFromMemory(R0, IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
             gen.addAdd(UDP_HEADER_LEN);
             gen.addSwap();
             gen.addLoad16(R0, IPV4_TOTAL_LENGTH_OFFSET);
@@ -1271,7 +1268,7 @@
             gen.addJumpIfR0NotEquals(1, nextFilterLabel);
 
             // Check that the ports match
-            gen.addLoadFromMemory(R0, IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
             gen.addAdd(ETH_HEADER_LEN);
             gen.addJumpIfBytesAtR0NotEqual(mPortFingerprint, nextFilterLabel);
 
@@ -1379,7 +1376,7 @@
             // Skip to the next filter if it's not zero-sized :
             // TCP_HEADER_SIZE + IPV4_HEADER_SIZE - ipv4_total_length == 0
             // Load the IP header size into R1
-            gen.addLoadFromMemory(R1, IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             // Load the TCP header size into R0 (it's indexed by R1)
             gen.addLoad8Indexed(R0, ETH_HEADER_LEN + TCP_HEADER_SIZE_OFFSET);
             // Size offset is in the top nibble, but it must be multiplied by 4, and the two
@@ -1393,7 +1390,7 @@
             gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(0, nextFilterLabel);
             // Add IPv4 header length
-            gen.addLoadFromMemory(R1, IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             gen.addLoadImmediate(R0, ETH_HEADER_LEN);
             gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mPortSeqAckFingerprint, nextFilterLabel);
@@ -1570,9 +1567,9 @@
                         .addWrite32(mIPv4Address)
                         .addPacketCopy(ETHER_SRC_ADDR_OFFSET, ETHER_ADDR_LEN)
                         .addPacketCopy(ARP_SOURCE_IP_ADDRESS_OFFSET, IPV4_ADDR_LEN)
-                        .addLoadFromMemory(R0, TX_BUFFER_OUTPUT_POINTER_MEMORY_SLOT)
+                        .addLoadFromMemory(R0, MemorySlot.TX_BUFFER_OUTPUT_POINTER)
                         .addAdd(18)
-                        .addStoreToMemory(TX_BUFFER_OUTPUT_POINTER_MEMORY_SLOT, R0)
+                        .addStoreToMemory(MemorySlot.TX_BUFFER_OUTPUT_POINTER, R0)
                         .addTransmitWithoutChecksum()
                         .addCountAndDrop(Counter.DROPPED_ARP_REQUEST_REPLIED);
             }
@@ -1617,7 +1614,7 @@
             gen.addLoad16(R0, IPV4_FRAGMENT_OFFSET_OFFSET);
             gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipDhcpv4Filter);
             // Check it's addressed to DHCP client port.
-            gen.addLoadFromMemory(R1, IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET);
             gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter);
             // Check it's DHCP to our MAC address.
@@ -1855,7 +1852,7 @@
         gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipMdnsFilter);
 
         // Set R1 to IPv4 header.
-        gen.addLoadFromMemory(R1, IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addJump(checkMdnsUdpPort);
 
         gen.defineLabel(skipMdnsv4Filter);
@@ -1930,7 +1927,7 @@
         gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipPort7V4Filter);
 
         // Check it's destination port 7.
-        gen.addLoadFromMemory(R1, IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET);
         gen.addJumpIfR0NotEquals(ECHO_PORT, skipPort7V4Filter);
 
@@ -1988,15 +1985,15 @@
                 gen.addIncrementCounter(Counter.TOTAL_PACKETS);
             }
 
-            gen.addLoadFromMemory(R0, 15);  // m[15] is filter age in seconds
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
             gen.addStoreCounter(Counter.FILTER_AGE_SECONDS, R0);
 
             // requires a new enough APFv5+ interpreter, otherwise will be 0
-            gen.addLoadFromMemory(R0, 9);  // m[9] is filter age in 16384ths
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_16384THS);
             gen.addStoreCounter(Counter.FILTER_AGE_16384THS, R0);
 
             // requires a new enough APFv5+ interpreter, otherwise will be 0
-            gen.addLoadFromMemory(R0, 8);  // m[8] is apf version
+            gen.addLoadFromMemory(R0, MemorySlot.APF_VERSION);
             gen.addStoreCounter(Counter.APF_VERSION, R0);
 
             // store this program's sequential id, for later comparison
diff --git a/src/android/net/apf/ApfV4GeneratorBase.java b/src/android/net/apf/ApfV4GeneratorBase.java
index a8b306d..604dc6b 100644
--- a/src/android/net/apf/ApfV4GeneratorBase.java
+++ b/src/android/net/apf/ApfV4GeneratorBase.java
@@ -430,18 +430,18 @@
      * Add an instruction to the end of the program to load memory slot {@code slot} into
      * {@code register}.
      */
-    public final Type addLoadFromMemory(Register r, int slot)
+    public final Type addLoadFromMemory(Register r, MemorySlot slot)
             throws IllegalInstructionException {
-        return append(new BaseApfGenerator.Instruction(ExtendedOpcodes.LDM, slot, r));
+        return append(new BaseApfGenerator.Instruction(ExtendedOpcodes.LDM, slot.value, r));
     }
 
     /**
      * Add an instruction to the end of the program to store {@code register} into memory slot
      * {@code slot}.
      */
-    public final Type addStoreToMemory(int slot, Register r)
+    public final Type addStoreToMemory(MemorySlot slot, Register r)
             throws IllegalInstructionException {
-        return append(new Instruction(ExtendedOpcodes.STM, slot, r));
+        return append(new Instruction(ExtendedOpcodes.STM, slot.value, r));
     }
 
     /**
diff --git a/src/android/net/apf/BaseApfGenerator.java b/src/android/net/apf/BaseApfGenerator.java
index 23e903b..f4ac5e9 100644
--- a/src/android/net/apf/BaseApfGenerator.java
+++ b/src/android/net/apf/BaseApfGenerator.java
@@ -788,45 +788,87 @@
      */
     public static final int MEMORY_SLOTS = 16;
 
-    /**
-     * Slot #10 starts at zero, implicitly used as tx buffer output pointer.
-     */
-    public static final int TX_BUFFER_OUTPUT_POINTER_MEMORY_SLOT = 10;
+    public enum MemorySlot {
+        SLOT_0(0),
+        SLOT_1(1),
+        SLOT_2(2),
+        SLOT_3(3),
+        SLOT_4(4),
+        SLOT_5(5),
+        SLOT_6(6),
+        SLOT_7(7),
 
-    /**
-     * Memory slot number that is prefilled with the IPv4 header length.
-     * Note that this memory slot may be overwritten by a program that
-     * executes stores to this memory slot. This must be kept in sync with
-     * the APF interpreter.
-     */
-    public static final int IPV4_HEADER_SIZE_MEMORY_SLOT = 13;
+        APF_VERSION(8),
+        FILTER_AGE_16384THS(9),
 
-    /**
-     * Memory slot number that is prefilled with the size of the packet being filtered in bytes.
-     * Note that this memory slot may be overwritten by a program that
-     * executes stores to this memory slot. This must be kept in sync with the APF interpreter.
-     */
-    public static final int PACKET_SIZE_MEMORY_SLOT = 14;
+        /**
+         * Slot #10 starts at zero, implicitly used as tx buffer output pointer.
+         */
+        TX_BUFFER_OUTPUT_POINTER(10),
 
-    /**
-     * Memory slot number that is prefilled with the age of the filter in seconds. The age of the
-     * filter is the time since the filter was installed until now.
-     * Note that this memory slot may be overwritten by a program that
-     * executes stores to this memory slot. This must be kept in sync with the APF interpreter.
-     */
-    public static final int FILTER_AGE_MEMORY_SLOT = 15;
+        PROGRAM_SIZE(11),
+        RAM_LEN(12),
 
-    /**
-     * First memory slot containing prefilled values. Can be used in range comparisons to determine
-     * if memory slot index is within prefilled slots.
-     */
-    public static final int FIRST_PREFILLED_MEMORY_SLOT = 8;
+        /**
+         * Memory slot number that is prefilled with the IPv4 header length.
+         * Note that this memory slot may be overwritten by a program that
+         * executes stores to this memory slot. This must be kept in sync with
+         * the APF interpreter.
+         */
+        IPV4_HEADER_SIZE(13),
 
-    /**
-     * Last memory slot containing prefilled values. Can be used in range comparisons to determine
-     * if memory slot index is within prefilled slots.
-     */
-    public static final int LAST_PREFILLED_MEMORY_SLOT = FILTER_AGE_MEMORY_SLOT;
+        /**
+         * Memory slot number that is prefilled with the size of the packet being filtered in bytes.
+         * Note that this memory slot may be overwritten by a program that
+         * executes stores to this memory slot. This must be kept in sync with the APF interpreter.
+         */
+        PACKET_SIZE(14),
+
+        /**
+         * Memory slot number that is prefilled with the age of the filter in seconds.
+         * The age of the filter is the time since the filter was installed until now.
+         * Note that this memory slot may be overwritten by a program that
+         * executes stores to this memory slot.
+         * This must be kept in sync with the APF interpreter.
+         */
+        FILTER_AGE_SECONDS(15),
+
+        /**
+         * First memory slot containing prefilled values. Can be used in range comparisons
+         * to determine if memory slot index is within prefilled slots.
+         */
+        FIRST_PREFILLED(8),
+
+        /**
+         * Last memory slot containing prefilled values. Can be used in range comparisons
+         * to determine if memory slot index is within prefilled slots.
+         */
+        LAST_PREFILLED(15);
+
+        public final int value;
+
+        MemorySlot(int value) {
+            this.value = value;
+        }
+
+        /**
+         * Bpf2Apf.java needs to create MemorySlot by index
+         */
+        public static MemorySlot byIndex(int value) {
+            switch (value) {
+                case 0: return SLOT_0;
+                case 1: return SLOT_1;
+                case 2: return SLOT_2;
+                case 3: return SLOT_3;
+                case 4: return SLOT_4;
+                case 5: return SLOT_5;
+                case 6: return SLOT_6;
+                case 7: return SLOT_7;
+            }
+            throw new IllegalArgumentException(
+                    String.format("Memory slot %d not in range 0..7", value));
+        }
+    }
 
     // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
     public static final int APF_VERSION_2 = 2;
diff --git a/src/android/net/apf/DnsUtils.java b/src/android/net/apf/DnsUtils.java
index 8001bea..1233c08 100644
--- a/src/android/net/apf/DnsUtils.java
+++ b/src/android/net/apf/DnsUtils.java
@@ -16,6 +16,7 @@
 
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 import static android.net.apf.BaseApfGenerator.Register.R1;
 
@@ -47,23 +48,23 @@
     private static final int POINTER_AND_QUESTION_HEADER_SIZE = POINTER_SIZE + QUESTION_HEADER_SIZE;
 
     /** Memory slot that stores the offset within the packet of the DNS header. */
-    private static final int SLOT_DNS_HEADER_OFFSET = 1;
+    private static final MemorySlot SLOT_DNS_HEADER_OFFSET = MemorySlot.SLOT_1;
     /** Memory slot that stores the current parsing offset. */
-    private static final int SLOT_CURRENT_PARSE_OFFSET = 2;
+    private static final MemorySlot SLOT_CURRENT_PARSE_OFFSET = MemorySlot.SLOT_2;
     /**
      * Memory slot that stores the offset after the current question, if the code is currently
      * parsing a pointer, or 0 if it is not.
      */
-    private static final int SLOT_AFTER_POINTER_OFFSET = 3;
+    private static final MemorySlot SLOT_AFTER_POINTER_OFFSET = MemorySlot.SLOT_3;
     /**
      * Contains qdcount remaining, as a negative number. For example, will be -1 when starting to
      * parse a DNS packet with one question in it. It's stored as a negative number because adding 1
      * is much easier than subtracting 1 (which can't be done just by adding -1, because that just
      * adds 254).
      */
-    private static final int SLOT_NEGATIVE_QDCOUNT_REMAINING = 4;
+    private static final MemorySlot SLOT_NEGATIVE_QDCOUNT_REMAINING = MemorySlot.SLOT_4;
     /** Memory slot used by the jump table. */
-    private static final int SLOT_RETURN_VALUE_INDEX = 5;
+    private static final MemorySlot SLOT_RETURN_VALUE_INDEX = MemorySlot.SLOT_5;
 
     /**
      * APF function: parse_dns_label
diff --git a/src/android/net/apf/JumpTable.java b/src/android/net/apf/JumpTable.java
index 016b01b..1d80538 100644
--- a/src/android/net/apf/JumpTable.java
+++ b/src/android/net/apf/JumpTable.java
@@ -16,6 +16,7 @@
 
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 
 import androidx.annotation.NonNull;
@@ -80,16 +81,17 @@
     /** Label to jump to to execute this jump table. */
     private final String mStartLabel;
     /** Memory slot that contains the return value index. */
-    private final int mReturnAddressMemorySlot;
+    private final MemorySlot mReturnAddressMemorySlot;
 
     private int mIndex = 0;
 
-    public JumpTable(@NonNull String startLabel, int returnAddressMemorySlot) {
+    public JumpTable(@NonNull String startLabel, MemorySlot returnAddressMemorySlot) {
         Objects.requireNonNull(startLabel);
         mStartLabel = startLabel;
-        if (returnAddressMemorySlot < 0
-                || returnAddressMemorySlot >= ApfV4Generator.FIRST_PREFILLED_MEMORY_SLOT) {
-            throw new IllegalArgumentException("Invalid memory slot " + returnAddressMemorySlot);
+        if (returnAddressMemorySlot.value < 0
+                || returnAddressMemorySlot.value >= MemorySlot.FIRST_PREFILLED.value) {
+            throw new IllegalArgumentException(
+                    "Invalid memory slot " + returnAddressMemorySlot.value);
         }
         mReturnAddressMemorySlot = returnAddressMemorySlot;
     }
diff --git a/src/android/net/apf/LegacyApfFilter.java b/src/android/net/apf/LegacyApfFilter.java
index b8955e6..83200be 100644
--- a/src/android/net/apf/LegacyApfFilter.java
+++ b/src/android/net/apf/LegacyApfFilter.java
@@ -16,6 +16,7 @@
 
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 import static android.net.apf.BaseApfGenerator.Register.R1;
 import static android.net.util.SocketUtils.makePacketSocketAddress;
@@ -262,14 +263,14 @@
 
     private static final int IPPROTO_HOPOPTS = 0;
 
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
+    // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE
     private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 2;
     private static final int UDP_HEADER_LEN = 8;
 
     private static final int TCP_HEADER_SIZE_OFFSET = 12;
 
     private static final int DHCP_CLIENT_PORT = 68;
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT
+    // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE
     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
 
     private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
@@ -298,7 +299,7 @@
     private static final int MDNS_PORT = 5353;
     private static final int DNS_HEADER_LEN = 12;
     private static final int DNS_QDCOUNT_OFFSET = 4;
-    // NOTE: this must be added to the IPv4 header length in IPV4_HEADER_SIZE_MEMORY_SLOT, or the
+    // NOTE: this must be added to the IPv4 header length in MemorySlot.IPV4_HEADER_SIZE, or the
     // IPv6 header length.
     private static final int MDNS_QDCOUNT_OFFSET =
             ETH_HEADER_LEN + UDP_HEADER_LEN + DNS_QDCOUNT_OFFSET;
@@ -984,10 +985,10 @@
         long generateFilterLocked(ApfV4Generator gen) throws IllegalInstructionException {
             String nextFilterLabel = "Ra" + getUniqueNumberLocked();
             // Skip if packet is not the right size
-            gen.addLoadFromMemory(R0, gen.PACKET_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE);
             gen.addJumpIfR0NotEquals(mPacket.capacity(), nextFilterLabel);
             // Skip filter if expired
-            gen.addLoadFromMemory(R0, gen.FILTER_AGE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
             gen.addJumpIfR0GreaterThan(filterLifetime(), nextFilterLabel);
             for (PacketSection section : mPacketSections) {
                 // Generate code to match the packet bytes.
@@ -1081,7 +1082,7 @@
 
             // A NAT-T keepalive packet contains 1 byte payload with the value 0xff
             // Check payload length is 1
-            gen.addLoadFromMemory(R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
             gen.addAdd(UDP_HEADER_LEN);
             gen.addSwap();
             gen.addLoad16(R0, IPV4_TOTAL_LENGTH_OFFSET);
@@ -1090,7 +1091,7 @@
             gen.addJumpIfR0NotEquals(1, nextFilterLabel);
 
             // Check that the ports match
-            gen.addLoadFromMemory(R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
             gen.addAdd(ETH_HEADER_LEN);
             gen.addJumpIfBytesAtR0NotEqual(mPortFingerprint, nextFilterLabel);
 
@@ -1198,7 +1199,7 @@
             // Skip to the next filter if it's not zero-sized :
             // TCP_HEADER_SIZE + IPV4_HEADER_SIZE - ipv4_total_length == 0
             // Load the IP header size into R1
-            gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             // Load the TCP header size into R0 (it's indexed by R1)
             gen.addLoad8Indexed(R0, ETH_HEADER_LEN + TCP_HEADER_SIZE_OFFSET);
             // Size offset is in the top nibble, but it must be multiplied by 4, and the two
@@ -1212,7 +1213,7 @@
             gen.addAddR1ToR0();
             gen.addJumpIfR0NotEquals(0, nextFilterLabel);
             // Add IPv4 header length
-            gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             gen.addLoadImmediate(R0, ETH_HEADER_LEN);
             gen.addAddR1ToR0();
             gen.addJumpIfBytesAtR0NotEqual(mPortSeqAckFingerprint, nextFilterLabel);
@@ -1400,7 +1401,7 @@
             gen.addLoad16(R0, IPV4_FRAGMENT_OFFSET_OFFSET);
             gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipDhcpv4Filter);
             // Check it's addressed to DHCP client port.
-            gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
             gen.addLoad16Indexed(R0, UDP_DESTINATION_PORT_OFFSET);
             gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter);
             // Check it's DHCP to our MAC address.
@@ -1639,7 +1640,7 @@
         gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET);
         gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipMdnsFilter);
         // Set R1 to IPv4 header.
-        gen.addLoadFromMemory(R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addJump(checkMdnsUdpPort);
 
         gen.defineLabel(skipMdnsv4Filter);
@@ -1735,17 +1736,17 @@
             gen.addStoreData(R0, 0);  // write-back counter
 
             maybeSetupCounter(gen, Counter.FILTER_AGE_SECONDS);
-            gen.addLoadFromMemory(R0, 15);  // m[15] is filter age in seconds
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
             gen.addStoreData(R0, 0);  // store 'counter'
 
             // requires a new enough APFv5+ interpreter, otherwise will be 0
             maybeSetupCounter(gen, Counter.FILTER_AGE_16384THS);
-            gen.addLoadFromMemory(R0, 9);  // m[9] is filter age in 16384ths
+            gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_16384THS);
             gen.addStoreData(R0, 0);  // store 'counter'
 
             // requires a new enough APFv5+ interpreter, otherwise will be 0
             maybeSetupCounter(gen, Counter.APF_VERSION);
-            gen.addLoadFromMemory(R0, 8);  // m[8] is apf version
+            gen.addLoadFromMemory(R0, MemorySlot.APF_VERSION);
             gen.addStoreData(R0, 0);  // store 'counter'
 
             // store this program's sequential id, for later comparison
diff --git a/tests/unit/src/android/net/apf/ApfStandaloneTest.kt b/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
index 7a58ea6..6012ed1 100644
--- a/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
+++ b/tests/unit/src/android/net/apf/ApfStandaloneTest.kt
@@ -25,6 +25,7 @@
 import android.net.apf.ApfConstant.IPV6_NEXT_HEADER_OFFSET
 import android.net.apf.ApfConstant.TCP_UDP_DESTINATION_PORT_OFFSET
 import android.net.apf.BaseApfGenerator.APF_VERSION_4
+import android.net.apf.BaseApfGenerator.MemorySlot
 import android.net.apf.BaseApfGenerator.Register.R0
 import android.net.apf.BaseApfGenerator.Register.R1
 import android.system.OsConstants
@@ -56,8 +57,11 @@
 
     fun runApfTest(isSuspendMode: Boolean) {
         val program = generateApfV4Program(isSuspendMode)
-        Log.w(TAG, "Program should be run in SETSUSPENDMODE $isSuspendMode: " +
-                HexDump.toHexString(program))
+        Log.w(
+            TAG,
+            "Program should be run in SETSUSPENDMODE $isSuspendMode: " +
+                HexDump.toHexString(program)
+        )
         // packet that in ethertype denylist:
         // ###[ Ethernet ]###
         //   dst       = ff:ff:ff:ff:ff:ff
@@ -72,11 +76,17 @@
         val packetBadEtherType =
                 HexDump.hexStringToByteArray("ffffffffffff047bcb463fb588a201")
         val dataRegion = ByteArray(Counter.totalSize()) { 0 }
-        ApfTestUtils.assertVerdict(APF_VERSION_4, ApfTestUtils.DROP,
-                program, packetBadEtherType, dataRegion)
+        ApfTestUtils.assertVerdict(
+            APF_VERSION_4,
+            ApfTestUtils.DROP,
+            program,
+            packetBadEtherType,
+            dataRegion
+        )
         assertEquals(mapOf<Counter, Long>(
                 Counter.TOTAL_PACKETS to 1,
-                Counter.DROPPED_ETHERTYPE_DENYLISTED to 1), decodeCountersIntoMap(dataRegion))
+                Counter.DROPPED_ETHERTYPE_DENYLISTED to 1
+        ), decodeCountersIntoMap(dataRegion))
 
         // dhcp request packet.
         // ###[ Ethernet ]###
@@ -124,13 +134,21 @@
         // raw bytes:
         // ffffffffffff047bcb463fb508004500011c00010000401179d100000000ffffffff004400430108393b010106000000000b000000000000000000000000000000000000000030343a37623a63623a34363a33663a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000638253633501033604c0a801013204c0a80164ff
 
-        val dhcpRequestPkt = HexDump.hexStringToByteArray("ffffffffffff047bcb463fb508004500011c00010000401179d100000000ffffffff004400430108393b010106000000000b000000000000000000000000000000000000000030343a37623a63623a34363a33663a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000638253633501033604c0a801013204c0a80164ff")
-        ApfTestUtils.assertVerdict(APF_VERSION_4, ApfTestUtils.DROP,
-                program, dhcpRequestPkt, dataRegion)
+        val dhcpRequestPkt = HexDump.hexStringToByteArray(
+            "ffffffffffff047bcb463fb508004500011c00010000401179d100000000ffffffff004400430108393b010106000000000b000000000000000000000000000000000000000030343a37623a63623a34363a33663a62000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000638253633501033604c0a801013204c0a80164ff"
+        )
+        ApfTestUtils.assertVerdict(
+            APF_VERSION_4,
+            ApfTestUtils.DROP,
+            program,
+            dhcpRequestPkt,
+            dataRegion
+        )
         assertEquals(mapOf<Counter, Long>(
                 Counter.TOTAL_PACKETS to 2,
                 Counter.DROPPED_ETHERTYPE_DENYLISTED to 1,
-                Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1), decodeCountersIntoMap(dataRegion))
+                Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1
+        ), decodeCountersIntoMap(dataRegion))
 
         // RS packet:
         // ###[ Ethernet ]###
@@ -154,13 +172,16 @@
         //
         // raw bytes:
         // ffffffffffff047bcb463fb586dd6000000000083afffe8000000000000030b45e42ef3d36e5ff0200000000000000000000000000028500c81d00000000
-        val rsPkt = HexDump.hexStringToByteArray("ffffffffffff047bcb463fb586dd6000000000083afffe8000000000000030b45e42ef3d36e5ff0200000000000000000000000000028500c81d00000000")
+        val rsPkt = HexDump.hexStringToByteArray(
+            "ffffffffffff047bcb463fb586dd6000000000083afffe8000000000000030b45e42ef3d36e5ff0200000000000000000000000000028500c81d00000000"
+        )
         ApfTestUtils.assertVerdict(APF_VERSION_4, ApfTestUtils.DROP, program, rsPkt, dataRegion)
         assertEquals(mapOf<Counter, Long>(
                 Counter.TOTAL_PACKETS to 3,
                 Counter.DROPPED_RS to 1,
                 Counter.DROPPED_ETHERTYPE_DENYLISTED to 1,
-                Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1), decodeCountersIntoMap(dataRegion))
+                Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1
+        ), decodeCountersIntoMap(dataRegion))
         if (isSuspendMode) {
             // Ping request packet
             // ###[ Ethernet ]###
@@ -191,14 +212,23 @@
             //
             // raw bytes: 84
             // ffffffffffff047bcb463fb508004500001c000100004001a52d644f6154080808080800f7ff00000000
-            val pingRequestPkt = HexDump.hexStringToByteArray("ffffffffffff047bcb463fb508004500001c000100004001a52d644f6154080808080800f7ff00000000")
-            ApfTestUtils.assertVerdict(APF_VERSION_4, ApfTestUtils.DROP, program, pingRequestPkt, dataRegion)
+            val pingRequestPkt = HexDump.hexStringToByteArray(
+                "ffffffffffff047bcb463fb508004500001c000100004001a52d644f6154080808080800f7ff00000000"
+            )
+            ApfTestUtils.assertVerdict(
+                APF_VERSION_4,
+                ApfTestUtils.DROP,
+                program,
+                pingRequestPkt,
+                dataRegion
+            )
             assertEquals(mapOf<Counter, Long>(
                     Counter.TOTAL_PACKETS to 4,
                     Counter.DROPPED_RS to 1,
                     Counter.DROPPED_ICMP4_ECHO_REQUEST to 1,
                     Counter.DROPPED_ETHERTYPE_DENYLISTED to 1,
-                    Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1), decodeCountersIntoMap(dataRegion))
+                    Counter.DROPPED_DHCP_REQUEST_DISCOVERY to 1
+            ), decodeCountersIntoMap(dataRegion))
         }
     }
 
@@ -226,11 +256,11 @@
         gen.addStoreData(R0, 0)
 
         maybeSetupCounter(gen, Counter.FILTER_AGE_SECONDS)
-        gen.addLoadFromMemory(R0, 15)
+        gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS)
         gen.addStoreData(R0, 0)
 
         maybeSetupCounter(gen, Counter.FILTER_AGE_16384THS)
-        gen.addLoadFromMemory(R0, 9)
+        gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_16384THS)
         gen.addStoreData(R0, 0)
 
         // ethtype filter
@@ -257,7 +287,7 @@
         gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET)
         gen.addJumpIfR0NotEquals(OsConstants.IPPROTO_UDP.toLong(), endOfDhcpFilter)
         // Check it's addressed to DHCP client port.
-        gen.addLoadFromMemory(R1, BaseApfGenerator.IPV4_HEADER_SIZE_MEMORY_SLOT)
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE)
         gen.addLoad16Indexed(R0, TCP_UDP_DESTINATION_PORT_OFFSET)
         gen.addJumpIfR0NotEquals(DHCP_SERVER_PORT.toLong(), endOfDhcpFilter)
         // drop dhcp the discovery and request
@@ -293,7 +323,7 @@
             gen.addLoad8(R0, IPV4_PROTOCOL_OFFSET)
             gen.addJumpIfR0NotEquals(OsConstants.IPPROTO_ICMP.toLong(), endOfPingFilter)
             // Check if it is echo request
-            gen.addLoadFromMemory(R1, BaseApfGenerator.IPV4_HEADER_SIZE_MEMORY_SLOT)
+            gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE)
             gen.addLoad8Indexed(R0, ETH_HEADER_LEN)
             gen.addJumpIfR0NotEquals(8, endOfPingFilter)
             // drop ping request
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index 15f23dc..a53a01e 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.apf.BaseApfGenerator.APF_VERSION_4;
 import static android.net.apf.BaseApfGenerator.DROP_LABEL;
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.PASS_LABEL;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 import static android.net.apf.BaseApfGenerator.Register.R1;
@@ -646,33 +647,33 @@
 
         // Test load from memory.
         gen = new ApfV4Generator(APF_VERSION_2);
-        gen.addLoadFromMemory(R0, 0);
+        gen.addLoadFromMemory(R0, MemorySlot.SLOT_0);
         gen.addJumpIfR0Equals(0, DROP_LABEL);
         assertDrop(gen);
 
         // Test store to memory.
         gen = new ApfV4Generator(APF_VERSION_2);
         gen.addLoadImmediate(R1, 1234567890);
-        gen.addStoreToMemory(12, R1);
-        gen.addLoadFromMemory(R0, 12);
+        gen.addStoreToMemory(MemorySlot.RAM_LEN, R1);
+        gen.addLoadFromMemory(R0, MemorySlot.RAM_LEN);
         gen.addJumpIfR0Equals(1234567890, DROP_LABEL);
         assertDrop(gen);
 
         // Test filter age pre-filled memory.
         gen = new ApfV4Generator(APF_VERSION_2);
-        gen.addLoadFromMemory(R0, gen.FILTER_AGE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
         gen.addJumpIfR0Equals(123, DROP_LABEL);
         assertDrop(gen, new byte[MIN_PKT_SIZE], 123);
 
         // Test packet size pre-filled memory.
         gen = new ApfV4Generator(APF_VERSION_2);
-        gen.addLoadFromMemory(R0, gen.PACKET_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE);
         gen.addJumpIfR0Equals(MIN_PKT_SIZE, DROP_LABEL);
         assertDrop(gen);
 
         // Test IPv4 header size pre-filled memory.
         gen = new ApfV4Generator(APF_VERSION_2);
-        gen.addLoadFromMemory(R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
         gen.addJumpIfR0Equals(20, DROP_LABEL);
         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
 
@@ -3580,7 +3581,7 @@
         gen.addJumpIfR0NotEquals(0x11, "LABEL_159");
         gen.addLoad16(R0, 20);
         gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_159");
-        gen.addLoadFromMemory(R1, 13);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_159");
         gen.addLoadImmediate(R0, 50);
@@ -3633,9 +3634,9 @@
         gen.addJump("LABEL_504");
 
         gen.defineLabel("LABEL_283");
-        gen.addLoadFromMemory(R0, 14);
+        gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE);
         gen.addJumpIfR0NotEquals(0xa6, "LABEL_496");
-        gen.addLoadFromMemory(R0, 15);
+        gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
         gen.addJumpIfR0GreaterThan(0x254, "LABEL_496");
         gen.addLoadImmediate(R0, 0);
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("e212507c6345648788fd6df086dd68"), "LABEL_496");
@@ -3733,7 +3734,7 @@
         gen.addJumpIfR0NotEquals(0x11, "LABEL_151");
         gen.addLoad16(R0, 20);
         gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_151");
-        gen.addLoadFromMemory(R1, 13);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_151");
         gen.addLoadImmediate(R0, 50);
@@ -3854,7 +3855,7 @@
         gen.addJumpIfR0NotEquals(0x11, "LABEL_157");
         gen.addLoad16(R0, 20);
         gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_157");
-        gen.addLoadFromMemory(R1, 13);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_157");
         gen.addLoadImmediate(R0, 50);
@@ -3877,14 +3878,14 @@
         gen.addJumpIfR0NotEquals(0x11, "LABEL_243");
         gen.addLoadImmediate(R0, 26);
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("6b7a1f1fc0a801be"), "LABEL_243");
-        gen.addLoadFromMemory(R0, 13);
+        gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
         gen.addAdd(8);
         gen.addSwap();
         gen.addLoad16(R0, 16);
         gen.addNeg(R1);
         gen.addAddR1ToR0();
         gen.addJumpIfR0NotEquals(0x1, "LABEL_243");
-        gen.addLoadFromMemory(R0, 13);
+        gen.addLoadFromMemory(R0, MemorySlot.IPV4_HEADER_SIZE);
         gen.addAdd(14);
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("1194ceca"), "LABEL_243");
         gen.addAdd(8);
@@ -3996,7 +3997,7 @@
         gen.addJumpIfR0NotEquals(0x11, "LABEL_165");
         gen.addLoad16(R0, 20);
         gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_165");
-        gen.addLoadFromMemory(R1, 13);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x44, "LABEL_165");
         gen.addLoadImmediate(R0, 50);
@@ -4019,7 +4020,7 @@
         gen.addJumpIfR0NotEquals(0x6, "LABEL_225");
         gen.addLoad16(R0, 20);
         gen.addJumpIfR0AnyBitsSet(0x1fff, "LABEL_225");
-        gen.addLoadFromMemory(R1, 13);
+        gen.addLoadFromMemory(R1, MemorySlot.IPV4_HEADER_SIZE);
         gen.addLoad16Indexed(R0, 16);
         gen.addJumpIfR0NotEquals(0x7, "LABEL_225");
         gen.addLoadImmediate(R1, -148);
@@ -4063,9 +4064,9 @@
         gen.addJump("LABEL_582");
 
         gen.defineLabel("LABEL_333");
-        gen.addLoadFromMemory(R0, 14);
+        gen.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE);
         gen.addJumpIfR0NotEquals(0x96, "LABEL_574");
-        gen.addLoadFromMemory(R0, 15);
+        gen.addLoadFromMemory(R0, MemorySlot.FILTER_AGE_SECONDS);
         gen.addJumpIfR0GreaterThan(0x48e, "LABEL_574");
         gen.addLoadImmediate(R0, 0);
         gen.addJumpIfBytesAtR0NotEqual(hexStringToByteArray("7e9046bc700828c68e23672c86dd60"), "LABEL_574");
diff --git a/tests/unit/src/android/net/apf/ApfV5Test.kt b/tests/unit/src/android/net/apf/ApfV5Test.kt
index e66042b..7119d53 100644
--- a/tests/unit/src/android/net/apf/ApfV5Test.kt
+++ b/tests/unit/src/android/net/apf/ApfV5Test.kt
@@ -39,6 +39,7 @@
 import android.net.apf.BaseApfGenerator.APF_VERSION_6
 import android.net.apf.BaseApfGenerator.DROP_LABEL
 import android.net.apf.BaseApfGenerator.IllegalInstructionException
+import android.net.apf.BaseApfGenerator.MemorySlot
 import android.net.apf.BaseApfGenerator.Register.R0
 import android.net.apf.BaseApfGenerator.Register.R1
 import android.os.Build
@@ -983,7 +984,7 @@
                 .addAllocate(14)
                 // len: 13 is less than ETH_HLEN, trigger transmit failure.
                 .addLoadImmediate(R0, 13)
-                .addStoreToMemory(10, R0)
+                .addStoreToMemory(MemorySlot.TX_BUFFER_OUTPUT_POINTER, R0)
                 .addTransmitWithoutChecksum()
                 .addDrop()
                 .generate()
diff --git a/tests/unit/src/android/net/apf/Bpf2Apf.java b/tests/unit/src/android/net/apf/Bpf2Apf.java
index 58845e8..de22e99 100644
--- a/tests/unit/src/android/net/apf/Bpf2Apf.java
+++ b/tests/unit/src/android/net/apf/Bpf2Apf.java
@@ -16,6 +16,7 @@
 
 package android.net.apf;
 
+import static android.net.apf.BaseApfGenerator.MemorySlot;
 import static android.net.apf.BaseApfGenerator.Register.R0;
 import static android.net.apf.BaseApfGenerator.Register.R1;
 
@@ -75,14 +76,14 @@
                     if (!opcode.equals("ldxb")) {
                         throw new IllegalArgumentException("Unhandled instruction: " + line);
                     }
-                    gen.addLoadFromMemory(dest, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+                    gen.addLoadFromMemory(dest, MemorySlot.IPV4_HEADER_SIZE);
                     break;
                 }
                 if (arg.equals("#pktlen")) {
                     if (!opcode.equals("ld")) {
                         throw new IllegalArgumentException("Unhandled instruction: " + line);
                     }
-                    gen.addLoadFromMemory(dest, gen.PACKET_SIZE_MEMORY_SLOT);
+                    gen.addLoadFromMemory(dest, MemorySlot.PACKET_SIZE);
                     break;
                 }
                 if (arg.startsWith("#0x")) {
@@ -100,11 +101,11 @@
                     if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
                             // Disallow use of pre-filled slots as BPF programs might
                             // wrongfully assume they're initialized to 0.
-                            (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
-                                    memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
+                            (memory_slot >= MemorySlot.FIRST_PREFILLED.value
+                                    && memory_slot <= MemorySlot.LAST_PREFILLED.value)) {
                         throw new IllegalArgumentException("Unhandled instruction: " + line);
                     }
-                    gen.addLoadFromMemory(dest, memory_slot);
+                    gen.addLoadFromMemory(dest, MemorySlot.byIndex(memory_slot));
                     break;
                 }
                 if (arg.startsWith("[x + ")) {
@@ -150,11 +151,11 @@
                 int memory_slot = Integer.parseInt(arg.substring(2, arg.length() - 1));
                 if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
                         // Disallow overwriting pre-filled slots
-                        (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
-                                memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
+                        (memory_slot >= MemorySlot.FIRST_PREFILLED.value
+                                && memory_slot <= MemorySlot.LAST_PREFILLED.value)) {
                     throw new IllegalArgumentException("Unhandled instruction: " + line);
                 }
-                gen.addStoreToMemory(memory_slot, src);
+                gen.addStoreToMemory(MemorySlot.byIndex(memory_slot), src);
                 break;
             case "add":
             case "and":
diff --git a/tests/unit/src/android/net/apf/JumpTableTest.kt b/tests/unit/src/android/net/apf/JumpTableTest.kt
index 4a8e35e..066c34a 100644
--- a/tests/unit/src/android/net/apf/JumpTableTest.kt
+++ b/tests/unit/src/android/net/apf/JumpTableTest.kt
@@ -16,6 +16,7 @@
 
 package android.net.apf
 
+import android.net.apf.BaseApfGenerator.MemorySlot
 import android.net.apf.BaseApfGenerator.Register.R0
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
@@ -45,36 +46,31 @@
     @Test(expected = NullPointerException::class)
     fun testNullStartLabel() {
         // Can't use "null" because the method is @NonNull.
-        JumpTable(AtomicReference<String>(null).get(), 10)
-    }
-
-    @Test(expected = IllegalArgumentException::class)
-    fun testNegativeSlot() {
-        JumpTable("my_jump_table", -1)
+        JumpTable(AtomicReference<String>(null).get(), MemorySlot.SLOT_0)
     }
 
     @Test(expected = IllegalArgumentException::class)
     fun testSlotTooLarge() {
-        JumpTable("my_jump_table", 13)
+        JumpTable("my_jump_table", MemorySlot.IPV4_HEADER_SIZE)
     }
 
     @Test
     fun testValidSlotNumbers() {
-        JumpTable("my_jump_table", 1)
-        JumpTable("my_jump_table", 4)
-        JumpTable("my_jump_table", 6)
+        JumpTable("my_jump_table", MemorySlot.SLOT_1)
+        JumpTable("my_jump_table", MemorySlot.SLOT_4)
+        JumpTable("my_jump_table", MemorySlot.SLOT_6)
     }
 
     @Test
     fun testGetStartLabel() {
-        assertEquals("xyz", JumpTable("xyz", 3).startLabel)
-        assertEquals("abc", JumpTable("abc", 5).startLabel)
+        assertEquals("xyz", JumpTable("xyz", MemorySlot.SLOT_3).startLabel)
+        assertEquals("abc", JumpTable("abc", MemorySlot.SLOT_5).startLabel)
     }
 
     @Test
     fun testCodeGeneration() {
         val name = "my_jump_table"
-        val slot = 7
+        val slot = MemorySlot.SLOT_7
 
         val j = JumpTable(name, slot)
         j.addLabel("foo")