19132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen/*
29132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Copyright (C) 2012 The Android Open Source Project
39132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *
49132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Licensed under the Apache License, Version 2.0 (the "License");
59132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * you may not use this file except in compliance with the License.
69132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * You may obtain a copy of the License at
79132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *
89132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *      http://www.apache.org/licenses/LICENSE-2.0
99132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *
109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Unless required by applicable law or agreed to in writing, software
119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * distributed under the License is distributed on an "AS IS" BASIS,
129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * See the License for the specific language governing permissions and
149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * limitations under the License.
159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */
169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenpackage android.net.apf;
189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
197d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkAddress;
207d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkProperties;
217d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.NetworkUtils;
229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfCapabilities;
239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfFilter;
249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator;
259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.IllegalInstructionException;
269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.Register;
279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.ip.IpManager;
286ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.IpConnectivityLog;
296ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.RaEvent;
309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.os.ConditionVariable;
316ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.os.Parcelable;
324456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichiimport android.os.SystemClock;
339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.ErrnoException;
349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.Os;
359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.test.AndroidTestCase;
364456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichiimport android.text.format.DateUtils;
375d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichiimport android.test.suitebuilder.annotation.SmallTest;
380668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport static android.system.OsConstants.*;
390668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi
407ceef950a02b22bdf90609bdab8119b4bcd88edfLorenzo Colittiimport com.android.frameworks.tests.net.R;
410668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport com.android.internal.util.HexDump;
42495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichiimport static com.android.internal.util.BitUtils.bytesToBEInt;
43495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichiimport static com.android.internal.util.BitUtils.put;
449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
456ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.ArgumentCaptor;
466ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.Mock;
476ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.MockitoAnnotations;
486ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.atLeastOnce;
496ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.verify;
506ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.File;
529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileDescriptor;
539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileOutputStream;
549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.IOException;
559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.InputStream;
569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.OutputStream;
579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.InetAddress;
589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.NetworkInterface;
599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.nio.ByteBuffer;
606ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport java.util.List;
610668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichiimport java.util.Random;
629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.IoUtils;
649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.Streams;
659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen/**
679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Tests for APF program generator and interpreter.
689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *
699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Build, install and run with:
70495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichi *  runtest frameworks-net -c android.net.apf.ApfTest
719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */
729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenpublic class ApfTest extends AndroidTestCase {
739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int TIMEOUT_MS = 500;
749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
756ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    @Mock IpConnectivityLog mLog;
766ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @Override
789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void setUp() throws Exception {
799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        super.setUp();
806ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        MockitoAnnotations.initMocks(this);
819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Load up native shared library containing APF interpreter exposed via JNI.
827ceef950a02b22bdf90609bdab8119b4bcd88edfLorenzo Colitti        System.loadLibrary("frameworksnettestsjni");
839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Expected return codes from APF interpreter.
869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int PASS = 1;
879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int DROP = 0;
889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Interpreter will just accept packets without link layer headers, so pad fake packet to at
899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // least the minimum packet size.
909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int MIN_PKT_SIZE = 15;
919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
926ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private final static boolean DROP_MULTICAST = true;
936ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private final static boolean ALLOW_MULTICAST = false;
946ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
954dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy    private final static boolean DROP_802_3_FRAMES = true;
964dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy    private final static boolean ALLOW_802_3_FRAMES = false;
974dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
98961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static String label(int code) {
99961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        switch (code) {
100961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            case PASS: return "PASS";
101961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            case DROP: return "DROP";
102961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            default:   return "UNKNOWN";
103961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        }
104961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
105961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
106961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static void assertReturnCodesEqual(int expected, int got) {
107961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertEquals(label(expected), label(got));
108961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
109961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
111961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge));
112961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
113961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
114961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertVerdict(int expected, byte[] program, byte[] packet) {
115961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(program, packet, 0));
1169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(byte[] program, byte[] packet, int filterAge) {
1199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, program, packet, filterAge);
1209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
122961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertPass(byte[] program, byte[] packet) {
123961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(PASS, program, packet);
124961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
125961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(byte[] program, byte[] packet, int filterAge) {
1279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, program, packet, filterAge);
1289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
130961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertDrop(byte[] program, byte[] packet) {
131961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(DROP, program, packet);
132961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
133961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
1359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
136961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge));
1379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
1409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, gen, packet, filterAge);
1429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
1459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, gen, packet, filterAge);
1479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(ApfGenerator gen)
1509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
1529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(ApfGenerator gen)
1559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
1579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
1609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Test each instruction by generating a program containing the instruction,
1619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * generating bytecode for that program and running it through the
1629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * interpreter to verify it functions correctly.
1639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
164cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
1659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfInstructions() throws IllegalInstructionException {
1669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Empty program should pass because having the program counter reach the
1679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // location immediately after the program indicates the packet should be
1689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // passed to the AP.
1699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ApfGenerator gen = new ApfGenerator();
1709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
1719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping to pass label.
1739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.PASS_LABEL);
1759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = gen.generate();
1769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program.length);
1779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
1789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(program, new byte[MIN_PKT_SIZE], 0);
1799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping to drop label.
1819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
1839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = gen.generate();
1849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(2, program.length);
1859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
1869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[1]);
1879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(program, new byte[15], 15);
1889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if equal to 0.
1909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
1929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
1939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if not equal to 0.
1959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
1979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
1989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
2009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
2019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if registers equal.
2049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
2069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if registers not equal.
2099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
2119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
2129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
2149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
2159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test load immediate.
2189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test add.
2249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAdd(1234567890);
2269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test subtract.
2309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAdd(-1234567890);
2329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
2339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test or.
2369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addOr(1234567890);
2389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test and.
2429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAnd(123456789);
2459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
2469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test left shift.
2499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLeftShift(1);
2529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
2539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test right shift.
2569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addRightShift(1);
2599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
2609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test multiply.
2639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMul(2);
2669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
2679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide.
2709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDiv(2);
2739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
2749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide by zero.
2779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDiv(0);
2799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
2809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
2819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test add.
2839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
2859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAddR1();
2869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test subtract.
2909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, -1234567890);
2929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAddR1();
2939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
2949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test or.
2979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
2999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addOrR1();
3009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
3019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test and.
3049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 123456789);
3079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAndR1();
3089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
3099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test left shift.
3129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLeftShiftR1();
3169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
3179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test right shift.
3209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, -1);
3239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLeftShiftR1();
3249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
3259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test multiply.
3289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 2);
3319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMulR1();
3329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
3339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide.
3369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 2);
3399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDivR1();
3409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
3419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide by zero.
3449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDivR1();
3469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
3479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
3489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test byte load.
3509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8(Register.R0, 1);
3529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
3539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test out of bounds load.
3569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8(Register.R0, 16);
3589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
3599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test half-word load.
3629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad16(Register.R0, 1);
3649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
3659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test word load.
3689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad32(Register.R0, 1);
3709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
3719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
3729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test byte indexed load.
3749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8Indexed(Register.R0, 0);
3779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
3789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test out of bounds indexed load.
3819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 8);
3839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8Indexed(Register.R0, 8);
3849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
3859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test half-word indexed load.
3889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad16Indexed(Register.R0, 0);
3919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
3929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test word indexed load.
3959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad32Indexed(Register.R0, 0);
3989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
3999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
4009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if greater than.
4029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
4049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
4079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
4089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if less than.
4119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
4139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
4169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if any bits set.
4199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
4249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 3);
4289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if register greater than.
4329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
4349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 2);
4379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
4389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
4399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if register less than.
4429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
4449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
4479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
4489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if any bits set in register.
4519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
4589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 3);
4639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test load from memory.
4679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, 0);
4699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
4709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test store to memory.
4739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
4759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addStoreToMemory(Register.R1, 12);
4769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, 12);
4779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
4789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test filter age pre-filled memory.
4819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
4839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
4849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
4859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test packet size pre-filled memory.
4879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
4899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
4909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test IPv4 header size pre-filled memory.
4939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
4959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
4969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
4979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test not.
4999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addNot(Register.R0);
5029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
5039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test negate.
5069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addNeg(Register.R0);
5099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
5109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test move.
5139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
5159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMove(Register.R0);
5169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMove(Register.R1);
5219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test swap.
5259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
5279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addSwap();
5289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addSwap();
5339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
5349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jump if bytes not equal.
5379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
5409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = gen.generate();
5419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(6, program.length);
5429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
5439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[1]);
5449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
5459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[3]);
5469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[4]);
5479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(123, program[5]);
5489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(program, new byte[MIN_PKT_SIZE], 0);
5499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
552961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
5539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, packet123, 0);
5549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
5569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, packet123, 0);
5579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
560961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
5619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, packet12345, 0);
5629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
5659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, packet12345, 0);
5669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
5679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
5699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Generate some BPF programs, translate them to APF, then run APF and BPF programs
5709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * over packet traces and verify both programs filter out the same packets.
5719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
572cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
5739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfAgainstBpf() throws Exception {
5749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
5759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
5769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
5779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
5789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        String pcap_filename = stageFile(R.raw.apf);
5799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        for (String tcpdump_filter : tcpdump_filters) {
5809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
5819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            assertTrue("Failed to match for filter: " + tcpdump_filter,
5829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                    compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
5839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
5859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private class MockIpManagerCallback extends IpManager.Callback {
5879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private final ConditionVariable mGotApfProgram = new ConditionVariable();
5889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private byte[] mLastApfProgram;
5899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
5919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void installPacketFilter(byte[] filter) {
5929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mLastApfProgram = filter;
5939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mGotApfProgram.open();
5949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void resetApfProgramWait() {
5979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mGotApfProgram.close();
5989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public byte[] getApfProgram() {
6019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            assertTrue(mGotApfProgram.block(TIMEOUT_MS));
6029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            return mLastApfProgram;
6039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6048995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
6058995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        public void assertNoProgramUpdate() {
6068995d85b9432387520c9f04a69251536754b996bLorenzo Colitti            assertFalse(mGotApfProgram.block(TIMEOUT_MS));
6078995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        }
6089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
6099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static class TestApfFilter extends ApfFilter {
611961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
6129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private FileDescriptor mWriteSocket;
6139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6144456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        private final long mFixedTimeMs = SystemClock.elapsedRealtime();
6154456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi
6166ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
6174dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                boolean ieee802_3Filter, IpConnectivityLog log) throws Exception {
6180dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi            super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
6194dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                    ipManagerCallback, multicastFilter, ieee802_3Filter, log);
6209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Pretend an RA packet has been received and show it to ApfFilter.
6239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
6249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // ApfFilter's ReceiveThread will be waiting to read this.
6259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            Os.write(mWriteSocket, packet, 0, packet.length);
6269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
6294456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        protected long currentTimeSeconds() {
6304456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi            return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
6314456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        }
6324456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi
6334456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        @Override
6349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        void maybeStartFilter() {
6359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mHardwareAddress = MOCK_MAC_ADDR;
6369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            installNewProgramLocked();
6379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
6399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            FileDescriptor readSocket = new FileDescriptor();
6409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mWriteSocket = new FileDescriptor();
6419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            try {
6429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
6439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            } catch (ErrnoException e) {
6449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                fail();
6459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                return;
6469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            }
6479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
6489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
6499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mReceiveThread = new ReceiveThread(readSocket);
6509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mReceiveThread.start();
6519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
6549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void shutdown() {
6559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            super.shutdown();
6569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            IoUtils.closeQuietly(mWriteSocket);
6579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
6599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ETH_HEADER_LEN = 14;
66138db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static final int ETH_DEST_ADDR_OFFSET = 0;
6629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ETH_ETHERTYPE_OFFSET = 12;
663961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
664961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
6659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
6679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
6689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
669961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] IPV4_BROADCAST_ADDRESS =
670961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
6719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
6739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_HEADER_LEN = 40;
6749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
6759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // The IPv6 all nodes address ff02::1
6769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final byte[] IPV6_ALL_NODES_ADDRESS =
677961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
67802428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi    private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
67902428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi            { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
6809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
68202428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi    private static final int ICMP6_ROUTER_SOLICITATION = 133;
6839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
68402428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi    private static final int ICMP6_NEIGHBOR_SOLICITATION = 135;
6859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
6869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_HEADER_LEN = 16;
6889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
6899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
6909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_CHECKSUM_OFFSET =
6919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
6929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_OPTION_OFFSET =
6939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
6949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
6969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_LEN = 32;
6979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
6989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
6999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC6106: Recursive DNS Server option
7019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
7029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC6106: DNS Search List option
7039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
7049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC4191: Route Information option
7069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
7079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Above three options all have the same format:
7089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
7099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
7109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
7119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int UDP_HEADER_LEN = 8;
7139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
7149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int DHCP_CLIENT_PORT = 68;
7169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
7179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7184fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi    private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
719961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ARP_IPV4_REQUEST_HEADER = {
7209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            0, 1, // Hardware type: Ethernet (1)
7219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            8, 0, // Protocol type: IP (0x0800)
7229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            6,    // Hardware size: 6
7239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            4,    // Protocol size: 4
7249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            0, 1  // Opcode: request (1)
7259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    };
726961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ARP_IPV4_REPLY_HEADER = {
72738db976514ff2ad12d207a927219762eab179882Hugo Benichi            0, 1, // Hardware type: Ethernet (1)
72838db976514ff2ad12d207a927219762eab179882Hugo Benichi            8, 0, // Protocol type: IP (0x0800)
72938db976514ff2ad12d207a927219762eab179882Hugo Benichi            6,    // Hardware size: 6
73038db976514ff2ad12d207a927219762eab179882Hugo Benichi            4,    // Protocol size: 4
73138db976514ff2ad12d207a927219762eab179882Hugo Benichi            0, 2  // Opcode: reply (2)
73238db976514ff2ad12d207a927219762eab179882Hugo Benichi    };
7334fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi    private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
7349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
735961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
7367d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
737961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
738961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
739961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
7409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
741cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
7429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterIPv4() throws Exception {
7439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
7447d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
7457d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkProperties lp = new LinkProperties();
7467d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        lp.addLinkAddress(link);
7470dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi
7484dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
7494dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                ALLOW_802_3_FRAMES, mLog);
7507d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
7510dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi
7529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
7539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty packet of 100 zero bytes is passed
7559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
756961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify unicast IPv4 packet is passed
759961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
7609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
761961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
762961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
763961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
7640dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi        // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
765961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
7660dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi        assertDrop(program, packet.array());
767961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
7687d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, packet.array());
769961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
770961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
771961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
772961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
774961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
776961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
778961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
779961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
780961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
781961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
782961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
783961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
784961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify broadcast IPv4 DHCP to us is passed
787961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
788961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
789961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
790961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Verify unicast IPv4 DHCP to us is passed
791961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
792961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
7959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
7969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
797cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
7989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterIPv6() throws Exception {
7999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
8004dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
8014dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                ALLOW_802_3_FRAMES, mLog);
8029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
8039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty IPv6 packet is passed
8059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
8069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
807961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
8089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty ICMPv6 packet is passed
8109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
811961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
8129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty ICMPv6 NA packet is passed
8149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
815961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
8169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify ICMPv6 NA to ff02::1 is dropped
818961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
819961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
8209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
82102428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi        // Verify ICMPv6 RS to any is dropped
82202428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi        packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
82302428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi        assertDrop(program, packet.array());
82402428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi        put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
82502428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi        assertDrop(program, packet.array());
82602428988ad90a2bd294b9ce752c2fced5b649519Hugo Benichi
8279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
8289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
8299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
830cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
83111e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti    public void testApfFilterMulticast() throws Exception {
832961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
8337d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
834961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
835961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
836961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
8377d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
8387d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
8397d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkProperties lp = new LinkProperties();
8407d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        lp.addLinkAddress(link);
8417d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
8424dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
8434dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
8447d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
8457d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
8467d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        byte[] program = ipManagerCallback.getApfProgram();
8477d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
84811e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        // Construct IPv4 and IPv6 multicast packets.
849f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
850f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
851961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
852f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen
853f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
854f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
855f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
856961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
857f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen
858f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        // Construct IPv4 broadcast packet.
859961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
860961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
861961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
862961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
863961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
864961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
865961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
866961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
867961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
868961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
869961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
870961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
871961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
872961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
873961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
87411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti
8759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify initially disabled multicast filter is off
876961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv4packet.array());
877961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
878961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet1.array());
879961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet2.array());
880961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4unicastl2packet.array());
8819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Turn on multicast filter and verify it works
8839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
8849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.setMulticastFilter(true);
8859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
886961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv4packet.array());
887961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv6packet.array());
888961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet1.array());
889961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet2.array());
8907d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, bcastv4unicastl2packet.array());
8919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Turn off multicast filter and verify it's off
8939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
8949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.setMulticastFilter(false);
8959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
896961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv4packet.array());
897961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
898961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet1.array());
899961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet2.array());
900961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4unicastl2packet.array());
9019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify it can be initialized to on
9039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
9049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
9054dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
9064dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
9077d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
9089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
909961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv4packet.array());
910961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv6packet.array());
911961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet1.array());
9127d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, bcastv4unicastl2packet.array());
91311e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti
91411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        // Verify that ICMPv6 multicast is not dropped.
915f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
916961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
9179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
9199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9214dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy    @SmallTest
9224dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy    public void testApfFilter802_3() throws Exception {
9234dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
9244dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
9254dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        LinkProperties lp = new LinkProperties();
9264dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        lp.addLinkAddress(link);
9274dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9284dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
9294dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                ALLOW_802_3_FRAMES, mLog);
9304dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter.setLinkProperties(lp);
9314dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9324dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        byte[] program = ipManagerCallback.getApfProgram();
9334dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9344dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify empty packet of 100 zero bytes is passed
9354dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Note that eth-type = 0 makes it an IEEE802.3 frame
9364dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
9374dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertPass(program, packet.array());
9384dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9394dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify empty packet with IPv4 is passed
9404dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
9414dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertPass(program, packet.array());
9424dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9434dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify empty IPv6 packet is passed
9444dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
9454dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertPass(program, packet.array());
9464dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9474dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Now turn on the filter
9484dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ipManagerCallback.resetApfProgramWait();
9494dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter.shutdown();
9504dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
9514dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
9524dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter.setLinkProperties(lp);
9534dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        program = ipManagerCallback.getApfProgram();
9544dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9554dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify that IEEE802.3 frame is dropped
9564dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // In this case ethtype is used for payload length
9574dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
9584dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertDrop(program, packet.array());
9594dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9604dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify that IPv4 (as example of Ethernet II) frame will pass
9614dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
9624dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertPass(program, packet.array());
9634dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9644dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        // Verify that IPv6 (as example of Ethernet II) frame will pass
9654dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
9664dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        assertPass(program, packet.array());
9674dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
9684dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        apfFilter.shutdown();
9694dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy    }
9704dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy
97138db976514ff2ad12d207a927219762eab179882Hugo Benichi    private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
97238db976514ff2ad12d207a927219762eab179882Hugo Benichi        cb.resetApfProgramWait();
97338db976514ff2ad12d207a927219762eab179882Hugo Benichi        filter.setLinkProperties(lp);
97438db976514ff2ad12d207a927219762eab179882Hugo Benichi        return cb.getApfProgram();
97538db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
97638db976514ff2ad12d207a927219762eab179882Hugo Benichi
97738db976514ff2ad12d207a927219762eab179882Hugo Benichi    private void verifyArpFilter(byte[] program, int filterResult) {
97838db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify ARP request packet
979961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
980961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
981961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
98238db976514ff2ad12d207a927219762eab179882Hugo Benichi
98338db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify unicast ARP reply packet is always accepted.
984961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
985961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
986961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
98738db976514ff2ad12d207a927219762eab179882Hugo Benichi
98838db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify GARP reply packets are always filtered
989961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, garpReply());
9909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
992cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
9939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterArp() throws Exception {
9949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
9954dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
9964dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
9979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
99838db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify initially ARP request filter is off, and GARP filter is on.
99938db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
10009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Inform ApfFilter of our address and verify ARP filtering is on
100238db976514ff2ad12d207a927219762eab179882Hugo Benichi        LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
10039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        LinkProperties lp = new LinkProperties();
100438db976514ff2ad12d207a927219762eab179882Hugo Benichi        assertTrue(lp.addLinkAddress(linkAddress));
100538db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP);
10069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Inform ApfFilter of loss of IP and verify ARP filtering is off
100838db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS);
10099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
10119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
10129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
101338db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] arpRequestBroadcast(byte[] tip) {
101438db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
101538db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1016961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1017961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1018961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
101938db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
102038db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
102138db976514ff2ad12d207a927219762eab179882Hugo Benichi
102238db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] arpReplyUnicast(byte[] tip) {
102338db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
102438db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1025961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1026961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
102738db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
102838db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
102938db976514ff2ad12d207a927219762eab179882Hugo Benichi
103038db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] garpReply() {
103138db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
103238db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
1033961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
1034961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
1035961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
103638db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
103738db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
103838db976514ff2ad12d207a927219762eab179882Hugo Benichi
10399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Verify that the last program pushed to the IpManager.Callback properly filters the
10409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // given packet for the given lifetime.
10414456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi    private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
10424456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int FRACTION_OF_LIFETIME = 6;
10434456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
10449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10454456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
1046961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
10474456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        assertDrop(program, packet.array(), ageLimit);
10484456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        assertPass(program, packet.array(), ageLimit + 1);
10499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(program, packet.array(), lifetime);
10509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify RA checksum is ignored
10514456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
10529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
1053961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
10549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
1055961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
10564456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
10579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify other changes to RA make it not match filter
10594456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final byte originalFirstByte = packet.get(0);
10609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(0, (byte)-1);
1061961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
10629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(0, (byte)0);
1063961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
10644456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        packet.put(0, originalFirstByte);
10659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
10669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Test that when ApfFilter is shown the given packet, it generates a program to filter it
10689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // for the given lifetime.
10699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void testRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
10709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
10719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify new program generated if ApfFilter witnesses RA
10729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
10739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.pretendPacketReceived(packet.array());
10744456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        byte[] program = ipManagerCallback.getApfProgram();
10754456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, packet, lifetime);
10769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
10779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10786ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private void verifyRaEvent(RaEvent expected) {
10796ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
10806ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verify(mLog, atLeastOnce()).log(captor.capture());
10816ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        RaEvent got = lastRaEvent(captor.getAllValues());
10826ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        if (!raEventEquals(expected, got)) {
10836ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            assertEquals(expected, got);  // fail for printing an assertion error message.
10846ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        }
10856ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
10866ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
10876ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private RaEvent lastRaEvent(List<Parcelable> events) {
10886ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        RaEvent got = null;
10896ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        for (Parcelable ev : events) {
10906ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            if (ev instanceof RaEvent) {
10916ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                got = (RaEvent) ev;
10926ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            }
10936ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        }
10946ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        return got;
10956ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
10966ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
10976ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
10986ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        return (ev1 != null) && (ev2 != null)
10996ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.routerLifetime == ev2.routerLifetime)
11006ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
11016ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
11026ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
11036ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.rdnssLifetime == ev2.rdnssLifetime)
11046ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.dnsslLifetime == ev2.dnsslLifetime);
11056ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
11066ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
11078995d85b9432387520c9f04a69251536754b996bLorenzo Colitti    private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
11088995d85b9432387520c9f04a69251536754b996bLorenzo Colitti            ByteBuffer packet) throws IOException, ErrnoException {
11098995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ipManagerCallback.resetApfProgramWait();
11108995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        apfFilter.pretendPacketReceived(packet.array());
11118995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ipManagerCallback.assertNoProgramUpdate();
11128995d85b9432387520c9f04a69251536754b996bLorenzo Colitti    }
11138995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
1114cfcc1cb7bf9caae440bf7c2c93efb43c9f90aa73Hugo Benichi    @SmallTest
11159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterRa() throws Exception {
11169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
11174dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
11184dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
11199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
11209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11214456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int ROUTER_LIFETIME = 1000;
11224456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int PREFIX_VALID_LIFETIME = 200;
11234456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int PREFIX_PREFERRED_LIFETIME = 100;
11244456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int RDNSS_LIFETIME  = 300;
11254456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int ROUTE_LIFETIME  = 400;
11264456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
11274456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        final int DNSSL_LIFETIME  = 2000;
1128967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        final int VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET = ETH_HEADER_LEN;
1129967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        // IPv6, traffic class = 0, flow label = 0x12345
1130967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        final int VERSION_TRAFFIC_CLASS_FLOW_LABEL = 0x60012345;
11314456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi
11329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify RA is passed the first time
11339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
11349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
1135967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        basePacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1136967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz                VERSION_TRAFFIC_CLASS_FLOW_LABEL);
11379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
11389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
11394456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
114011e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        basePacket.position(IPV6_DEST_ADDR_OFFSET);
114111e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        basePacket.put(IPV6_ALL_NODES_ADDRESS);
1142961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, basePacket.array());
11439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11444456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
11454456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
11469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1147967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        ByteBuffer newFlowLabelPacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
1148967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        basePacket.clear();
1149967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        newFlowLabelPacket.put(basePacket);
1150967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        // Check that changes are ignored in every byte of the flow label.
1151967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        newFlowLabelPacket.putInt(VERSION_TRAFFIC_CLASS_FLOW_LABEL_OFFSET,
1152967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz                VERSION_TRAFFIC_CLASS_FLOW_LABEL + 0x11111);
1153967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz
11548995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        // Ensure zero-length options cause the packet to be silently skipped.
11558995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        // Do this before we test other packets. http://b/29586253
11568995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
11578995d85b9432387520c9f04a69251536754b996bLorenzo Colitti                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
11588995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        basePacket.clear();
11598995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put(basePacket);
11608995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
11618995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put((byte)0);
11628995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket);
11638995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
11649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Generate several RAs with different options and lifetimes, and verify when
11659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // ApfFilter is shown these packets, it generates programs to filter them for the
11669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // appropriate lifetime.
11679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
11689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
11699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
11709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put(basePacket);
11719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
11729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
11739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.putInt(
11744456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
11754456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                PREFIX_PREFERRED_LIFETIME);
11769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.putInt(
11774456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
11784456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                PREFIX_VALID_LIFETIME);
11794456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
11804456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaEvent(new RaEvent(
11814456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
11829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
11849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
11859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
11869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put(basePacket);
11879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
11889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
11899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.putInt(
11904456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
11914456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
11924456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
11939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
11959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
11969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
11979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put(basePacket);
11989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
11999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
12009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.putInt(
12014456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
12024456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
12034456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
12049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
12059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
12069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
12079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
12089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put(basePacket);
12099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
12109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
12119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.putInt(
12124456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
12134456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
12144456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
12159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
12169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify that current program filters all five RAs:
12174456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        program = ipManagerCallback.getApfProgram();
12184456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
1219967dec794b1974574d95c9d2dea0a0133fa19717Joel Scherpelz        verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
12204456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
12214456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
12224456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
12234456f33a958a7f09e608399da83c4d12b2e7d191Hugo Benichi        verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
12249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
12259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
12269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
12279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
12289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
12299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
12309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * copy that resource into the app's data directory and return the path to it.
12319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
12329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private String stageFile(int rawId) throws Exception {
12339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        File file = new File(getContext().getFilesDir(), "staged_file");
12349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        new File(file.getParent()).mkdirs();
12359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        InputStream in = null;
12369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        OutputStream out = null;
12379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        try {
12389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            in = getContext().getResources().openRawResource(rawId);
12399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            out = new FileOutputStream(file);
12409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            Streams.copy(in, out);
12419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        } finally {
12429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            if (in != null) in.close();
12439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            if (out != null) out.close();
12449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
12459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        return file.getAbsolutePath();
12469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
12479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1248961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static void put(ByteBuffer buffer, int position, byte[] bytes) {
1249961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final int original = buffer.position();
1250961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.position(position);
1251961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.put(bytes);
1252961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.position(original);
1253961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
1254961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
12555d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi    @SmallTest
12560668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi    public void testRaParsing() throws Exception {
12570668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        final int maxRandomPacketSize = 512;
12580668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        final Random r = new Random();
12590668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        MockIpManagerCallback cb = new MockIpManagerCallback();
12604dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
12614dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
12620668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        for (int i = 0; i < 1000; i++) {
12630668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
12640668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            r.nextBytes(packet);
12650668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            try {
12660668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi                apfFilter.new Ra(packet, packet.length);
12670668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            } catch (ApfFilter.InvalidRaException e) {
12680668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            } catch (Exception e) {
12690668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
12700668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            }
12710668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        }
12720668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi    }
12730668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi
12745d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi    @SmallTest
12750668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi    public void testRaProcessing() throws Exception {
12760668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        final int maxRandomPacketSize = 512;
12770668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        final Random r = new Random();
12780668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        MockIpManagerCallback cb = new MockIpManagerCallback();
12794dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
12804dd7c58fc8fcc5a2c50de5e8eff05ddc5c3b0b8bAhmed ElArabawy                DROP_802_3_FRAMES, mLog);
12810668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        for (int i = 0; i < 1000; i++) {
12820668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
12830668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            r.nextBytes(packet);
12840668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            try {
12850668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi                apfFilter.processRa(packet, packet.length);
12860668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            } catch (Exception e) {
12870668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi                throw new Exception("bad packet: " + HexDump.toHexString(packet), e);
12880668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi            }
12890668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi        }
12900668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi    }
12910668a61d82a424fb3714b6222f0e4213c18fc7b1Hugo Benichi
12929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
12939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Call the APF interpreter the run {@code program} on {@code packet} pretending the
12949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * filter was installed {@code filter_age} seconds ago.
12959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
12969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static int apfSimulate(byte[] program, byte[] packet, int filter_age);
12979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
12989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
12999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
13009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
13019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
13029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static String compileToBpf(String filter);
13039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
13049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
13059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
13069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
13079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * at the same time using APF program {@code apf_program}.  Return {@code true} if
13089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * both APF and BPF programs filter out exactly the same packets.
13099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
13109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static boolean compareBpfApf(String filter, String pcap_filename,
13119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            byte[] apf_program);
13127d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
13135d2654124e9e77dbda102a4435595c552cbc8e36Hugo Benichi    @SmallTest
13147d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    public void testBroadcastAddress() throws Exception {
13157d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
13167d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
13177d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
13187d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
13197d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
13207d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
13217d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
13227d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
13237d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
13247d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    }
13257d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
13267d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    public void assertEqualsIp(String expected, int got) throws Exception {
1327495a17b332e57ea4c0162a4ae63d820b947e3719Hugo Benichi        int want = bytesToBEInt(InetAddress.getByName(expected).getAddress());
13287d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(want, got);
13297d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    }
13309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen}
1331