APFv6.1: addTransmitL4() optimizations

After this:
  atest 'NetworkStackTests:com.android.networkstack.android.net.apf.ApfFilterTest#testAllOffloadFeatureEnabled'
Generates a program with the following transmit instructions:
  (   1) 2297: transmit
  (   2) 2460: transmit    offload=ipv4/alert/icmp, partial_csum=0x0
  (   2) 2487: transmit    offload=ipv4/alert/icmp, partial_csum=0x0
  (   2) 2505: transmit    offload=ipv4/alert/icmp, partial_csum=0x0
  (   2) 2726: transmit    offload=ipv4/icmp, partial_csum=0x0
  (   3) 2890: transmit    offload=ipv6/alert/icmp, partial_csum=0xa6
  (   3) 2913: transmit    offload=ipv6/alert/icmp, partial_csum=0x52
  (   3) 2935: transmit    offload=ipv6/alert/icmp, partial_csum=0x52
  (   3) 2957: transmit    offload=ipv6/alert/icmp, partial_csum=0x52
  (   3) 2979: transmit    offload=ipv6/alert/icmp, partial_csum=0x52
  (   3) 3001: transmit    offload=ipv6/alert/icmp, partial_csum=0x52
  (   3) 3192: transmit    offload=ipv6/icmp, partial_csum=0x3a
  (   3) 3435: transmit    offload=ipv6/icmp, partial_csum=0x3a
  (   3) 4047: transmitudp offload=ipv4/udp, partial_csum=0x1ff
  (   3) 4078: transmitudp offload=ipv6/udp, partial_csum=0x1ff
  (   3) 4196: transmitudp offload=ipv4/udp, partial_csum=0x149
  (   3) 4227: transmitudp offload=ipv6/udp, partial_csum=0x149
  (   3) 4327: transmitudp offload=ipv4/udp, partial_csum=0x176
  (   3) 4358: transmitudp offload=ipv6/udp, partial_csum=0x176
  (   3) 4465: transmitudp offload=ipv4/udp, partial_csum=0x1b9
  (   3) 4496: transmitudp offload=ipv6/udp, partial_csum=0x1b9
  (   0) 4503: PASS

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I5391fedfbb7c32345392f2b9a013c839de3f2703
diff --git a/src/android/net/apf/ApfV61GeneratorBase.java b/src/android/net/apf/ApfV61GeneratorBase.java
index 7707f6d..464b16e 100644
--- a/src/android/net/apf/ApfV61GeneratorBase.java
+++ b/src/android/net/apf/ApfV61GeneratorBase.java
@@ -212,6 +212,25 @@
         return append(new Instruction(Opcodes.ALLOC_XMIT, Rbit0));
     }
 
+    @Override
+    protected boolean handleOptimizedTransmit(int ipOfs, int csumOfs, int csumStart,
+                                              int partialCsum, boolean isUdp) {
+        if (ipOfs != 14) return false;
+        int v = -1;
+        if ( isUdp && csumStart == 26 && csumOfs == 40) v = 0;  // ether/ipv4/udp
+        if (!isUdp && csumStart == 26 && csumOfs == 44) v = 1;  // ether/ipv4/tcp
+        if (!isUdp && csumStart == 34 && csumOfs == 36) v = 2;  // ether/ipv4/icmp
+        if (!isUdp && csumStart == 38 && csumOfs == 40) v = 3;  // ether/ipv4/routeralert/icmp
+        if ( isUdp && csumStart == 22 && csumOfs == 60) v = 4;  // ether/ipv6/udp
+        if (!isUdp && csumStart == 22 && csumOfs == 64) v = 5;  // ether/ipv6/tcp
+        if (!isUdp && csumStart == 22 && csumOfs == 56) v = 6;  // ether/ipv6/icmp
+        if (!isUdp && csumStart == 22 && csumOfs == 64) v = 7;  // ether/ipv6/routeralert/icmp
+        if (v < 0) return false;
+        v |= partialCsum << 3;
+        append(new Instruction(Opcodes.ALLOC_XMIT, Rbit0).addUnsigned(v));
+        return true;
+    }
+
     private List<byte[]> addJumpIfBytesAtOffsetEqualsHelper(int offset,
             @NonNull List<byte[]> bytesList, short tgt, boolean jumpOnMatch)
             throws IllegalInstructionException {
diff --git a/src/android/net/apf/ApfV6Generator.java b/src/android/net/apf/ApfV6Generator.java
index 13682b3..045423b 100644
--- a/src/android/net/apf/ApfV6Generator.java
+++ b/src/android/net/apf/ApfV6Generator.java
@@ -292,4 +292,10 @@
     public ApfV6Generator addTransmitWithoutChecksum() {
         return addTransmit(-1 /* ipOfs */);
     }
+
+    @Override
+    protected boolean handleOptimizedTransmit(int ipOfs, int csumOfs, int csumStart,
+                                              int partialCsum, boolean isUdp) {
+        return false;
+    }
 }
diff --git a/src/android/net/apf/ApfV6GeneratorBase.java b/src/android/net/apf/ApfV6GeneratorBase.java
index 62fdfc1..68a29c5 100644
--- a/src/android/net/apf/ApfV6GeneratorBase.java
+++ b/src/android/net/apf/ApfV6GeneratorBase.java
@@ -163,6 +163,8 @@
         return append(new Instruction(ExtendedOpcodes.TRANSMIT, Rbit0).addU8(ipOfs).addU8(255));
     }
 
+    protected abstract boolean handleOptimizedTransmit(int ipOfs, int csumOfs, int csumStart, int partialCsum, boolean isUdp);
+
     /**
      * Add an instruction to the end of the program to transmit the allocated buffer.
      */
@@ -176,6 +178,8 @@
             throw new IllegalArgumentException("L4 checksum requires csum offset of "
                                                + csumOfs + " < 255");
         }
+        if (handleOptimizedTransmit(ipOfs, csumOfs, csumStart, partialCsum, isUdp))
+            return self();
         return append(new Instruction(ExtendedOpcodes.TRANSMIT, isUdp ? Rbit1 : Rbit0)
                 .addU8(ipOfs).addU8(csumOfs).addU8(csumStart).addU16(partialCsum));
     }