ApfTest.java revision 7d21eaedade0e01bed665dd2e4ba15e0c217237c
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
199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport static android.system.OsConstants.*;
209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport com.android.frameworks.servicestests.R;
229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
237d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkAddress;
247d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.LinkProperties;
257d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichiimport android.net.NetworkUtils;
269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfCapabilities;
279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfFilter;
289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator;
299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.IllegalInstructionException;
309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.apf.ApfGenerator.Register;
319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.net.ip.IpManager;
326ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.IpConnectivityLog;
336ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.net.metrics.RaEvent;
349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.os.ConditionVariable;
356ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport android.os.Parcelable;
369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.ErrnoException;
379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.system.Os;
389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.test.AndroidTestCase;
399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport android.test.suitebuilder.annotation.LargeTest;
409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
416ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.ArgumentCaptor;
426ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.Mock;
436ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport org.mockito.MockitoAnnotations;
446ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.atLeastOnce;
456ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport static org.mockito.Mockito.verify;
466ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.File;
489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileDescriptor;
499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.FileOutputStream;
509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.IOException;
519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.InputStream;
529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.io.OutputStream;
539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.InetAddress;
549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.net.NetworkInterface;
559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport java.nio.ByteBuffer;
566ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichiimport java.util.List;
579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.IoUtils;
599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenimport libcore.io.Streams;
609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen/**
629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Tests for APF program generator and interpreter.
639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen *
649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen * Build, install and run with:
65961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi *  runtest frameworks-services -c android.net.apf.ApfTest
669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen */
679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensenpublic class ApfTest extends AndroidTestCase {
689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int TIMEOUT_MS = 500;
699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
706ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    @Mock IpConnectivityLog mLog;
716ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @Override
739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void setUp() throws Exception {
749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        super.setUp();
756ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        MockitoAnnotations.initMocks(this);
769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Load up native shared library containing APF interpreter exposed via JNI.
779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        System.loadLibrary("servicestestsjni");
789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Expected return codes from APF interpreter.
819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int PASS = 1;
829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int DROP = 0;
839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Interpreter will just accept packets without link layer headers, so pad fake packet to at
849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // least the minimum packet size.
859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private final static int MIN_PKT_SIZE = 15;
869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
876ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private final static boolean DROP_MULTICAST = true;
886ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private final static boolean ALLOW_MULTICAST = false;
896ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
90961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static String label(int code) {
91961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        switch (code) {
92961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            case PASS: return "PASS";
93961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            case DROP: return "DROP";
94961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            default:   return "UNKNOWN";
95961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        }
96961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
97961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
98961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static void assertReturnCodesEqual(int expected, int got) {
99961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertEquals(label(expected), label(got));
100961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
101961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
103961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(program, packet, filterAge));
104961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
105961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
106961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertVerdict(int expected, byte[] program, byte[] packet) {
107961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(program, packet, 0));
1089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(byte[] program, byte[] packet, int filterAge) {
1119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, program, packet, filterAge);
1129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
114961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertPass(byte[] program, byte[] packet) {
115961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(PASS, program, packet);
116961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
117961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(byte[] program, byte[] packet, int filterAge) {
1199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, program, packet, filterAge);
1209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
122961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private void assertDrop(byte[] program, byte[] packet) {
123961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(DROP, program, packet);
124961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
125961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
1269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertVerdict(int expected, ApfGenerator gen, byte[] packet, int filterAge)
1279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
128961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertReturnCodesEqual(expected, apfSimulate(gen.generate(), packet, filterAge));
1299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(ApfGenerator gen, byte[] packet, int filterAge)
1329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, gen, packet, filterAge);
1349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(ApfGenerator gen, byte[] packet, int filterAge)
1379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, gen, packet, filterAge);
1399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertPass(ApfGenerator gen)
1429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(PASS, gen, new byte[MIN_PKT_SIZE], 0);
1449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void assertDrop(ApfGenerator gen)
1479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            throws IllegalInstructionException {
1489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertVerdict(DROP, gen, new byte[MIN_PKT_SIZE], 0);
1499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
1509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
1529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Test each instruction by generating a program containing the instruction,
1539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * generating bytecode for that program and running it through the
1549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * interpreter to verify it functions correctly.
1559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
1569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
1579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfInstructions() throws IllegalInstructionException {
1589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Empty program should pass because having the program counter reach the
1599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // location immediately after the program indicates the packet should be
1609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // passed to the AP.
1619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ApfGenerator gen = new ApfGenerator();
1629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
1639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping to pass label.
1659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.PASS_LABEL);
1679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = gen.generate();
1689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program.length);
1699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
1709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(program, new byte[MIN_PKT_SIZE], 0);
1719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping to drop label.
1739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
1759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = gen.generate();
1769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(2, program.length);
1779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
1789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[1]);
1799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(program, new byte[15], 15);
1809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if equal to 0.
1829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
1849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
1859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if not equal to 0.
1879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
1899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
1909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
1929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
1939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
1949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if registers equal.
1969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
1979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
1989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
1999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if registers not equal.
2019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
2039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
2049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
2069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
2079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test load immediate.
2109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test add.
2169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAdd(1234567890);
2189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test subtract.
2229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAdd(-1234567890);
2249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
2259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test or.
2289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addOr(1234567890);
2309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test and.
2349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAnd(123456789);
2379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
2389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test left shift.
2419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLeftShift(1);
2449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
2459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test right shift.
2489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addRightShift(1);
2519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
2529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test multiply.
2559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMul(2);
2589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
2599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide.
2629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDiv(2);
2659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
2669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide by zero.
2699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDiv(0);
2719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
2729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
2739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test add.
2759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
2779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAddR1();
2789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test subtract.
2829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, -1234567890);
2849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAddR1();
2859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
2869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test or.
2899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
2919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addOrR1();
2929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
2939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
2949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
2959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test and.
2969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
2979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
2989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 123456789);
2999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addAndR1();
3009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
3019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test left shift.
3049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLeftShiftR1();
3089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
3099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test right 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 multiply.
3209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 2);
3239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMulR1();
3249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
3259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide.
3289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
3309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 2);
3319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDivR1();
3329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
3339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
3349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test divide by zero.
3369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addDivR1();
3389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJump(gen.DROP_LABEL);
3399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
3409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test byte load.
3429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8(Register.R0, 1);
3449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
3459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test out of bounds load.
3489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8(Register.R0, 16);
3509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
3519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test half-word load.
3549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad16(Register.R0, 1);
3569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
3579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test word load.
3609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad32(Register.R0, 1);
3629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
3639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
3649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test byte indexed load.
3669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8Indexed(Register.R0, 0);
3699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
3709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test out of bounds indexed load.
3739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 8);
3759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad8Indexed(Register.R0, 8);
3769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
3779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test half-word indexed load.
3809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad16Indexed(Register.R0, 0);
3839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
3849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
3859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test word indexed load.
3879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
3899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoad32Indexed(Register.R0, 0);
3909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
3919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
3929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
3939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if greater than.
3949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
3969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
3979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
3989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
3999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
4009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if less than.
4039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
4059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
4089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if any bits set.
4119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
4169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 3);
4209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
4219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if register greater than.
4249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
4269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 2);
4299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
4309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
4319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if register less than.
4349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
4369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1);
4399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
4409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jumping if any bits set in register.
4439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen);
4479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
4509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 3);
4549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 3);
4559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
4569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test load from memory.
4599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, 0);
4619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
4629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test store to memory.
4659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
4679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addStoreToMemory(Register.R1, 12);
4689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, 12);
4699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
4709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test filter age pre-filled memory.
4739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
4759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
4769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
4779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test packet size pre-filled memory.
4799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
4819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
4829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test IPv4 header size pre-filled memory.
4859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
4879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
4889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
4899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test not.
4919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
4939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addNot(Register.R0);
4949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
4959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
4969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
4979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test negate.
4989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
4999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addNeg(Register.R0);
5019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
5029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test move.
5059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
5079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMove(Register.R0);
5089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addMove(Register.R1);
5139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test swap.
5179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R1, 1234567890);
5199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addSwap();
5209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
5219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1234567890);
5249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addSwap();
5259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
5269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen);
5279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Test jump if bytes not equal.
5299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
5329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = gen.generate();
5339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(6, program.length);
5349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
5359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[1]);
5369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
5379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[3]);
5389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(1, program[4]);
5399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertEquals(123, program[5]);
5409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(program, new byte[MIN_PKT_SIZE], 0);
5419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
544961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
5459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, packet123, 0);
5469132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
5489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, packet123, 0);
5499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
552961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
5539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(gen, packet12345, 0);
5549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen = new ApfGenerator();
5559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addLoadImmediate(Register.R0, 1);
5569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
5579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(gen, packet12345, 0);
5589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
5599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
5619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Generate some BPF programs, translate them to APF, then run APF and BPF programs
5629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * over packet traces and verify both programs filter out the same packets.
5639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
5649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
5659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfAgainstBpf() throws Exception {
5669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        String[] tcpdump_filters = new String[]{ "udp", "tcp", "icmp", "icmp6", "udp port 53",
5679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "arp", "dst 239.255.255.250", "arp or tcp or udp port 53", "net 192.168.1.0/24",
5689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "arp or icmp6 or portrange 53-54", "portrange 53-54 or portrange 100-50000",
5699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                "tcp[tcpflags] & (tcp-ack|tcp-fin) != 0 and (ip[2:2] > 57 or icmp)" };
5709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        String pcap_filename = stageFile(R.raw.apf);
5719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        for (String tcpdump_filter : tcpdump_filters) {
5729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            byte[] apf_program = Bpf2Apf.convert(compileToBpf(tcpdump_filter));
5739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            assertTrue("Failed to match for filter: " + tcpdump_filter,
5749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                    compareBpfApf(tcpdump_filter, pcap_filename, apf_program));
5759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
5779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private class MockIpManagerCallback extends IpManager.Callback {
5799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private final ConditionVariable mGotApfProgram = new ConditionVariable();
5809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private byte[] mLastApfProgram;
5819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
5839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void installPacketFilter(byte[] filter) {
5849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mLastApfProgram = filter;
5859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mGotApfProgram.open();
5869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void resetApfProgramWait() {
5899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mGotApfProgram.close();
5909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
5929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public byte[] getApfProgram() {
5939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            assertTrue(mGotApfProgram.block(TIMEOUT_MS));
5949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            return mLastApfProgram;
5959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
5968995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
5978995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        public void assertNoProgramUpdate() {
5988995d85b9432387520c9f04a69251536754b996bLorenzo Colitti            assertFalse(mGotApfProgram.block(TIMEOUT_MS));
5998995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        }
6009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
6019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static class TestApfFilter extends ApfFilter {
603961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
6049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        private FileDescriptor mWriteSocket;
6059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6066ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
6076ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                IpConnectivityLog log) throws Exception {
6080dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi            super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
6096ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                    ipManagerCallback, multicastFilter, log);
6109132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Pretend an RA packet has been received and show it to ApfFilter.
6139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void pretendPacketReceived(byte[] packet) throws IOException, ErrnoException {
6149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // ApfFilter's ReceiveThread will be waiting to read this.
6159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            Os.write(mWriteSocket, packet, 0, packet.length);
6169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
6199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        void maybeStartFilter() {
6209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mHardwareAddress = MOCK_MAC_ADDR;
6219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            installNewProgramLocked();
6229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // Create two sockets, "readSocket" and "mWriteSocket" and connect them together.
6249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            FileDescriptor readSocket = new FileDescriptor();
6259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mWriteSocket = new FileDescriptor();
6269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            try {
6279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mWriteSocket, readSocket);
6289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            } catch (ErrnoException e) {
6299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                fail();
6309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                return;
6319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            }
6329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // Now pass readSocket to ReceiveThread as if it was setup to read raw RAs.
6339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            // This allows us to pretend RA packets have been recieved via pretendPacketReceived().
6349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mReceiveThread = new ReceiveThread(readSocket);
6359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            mReceiveThread.start();
6369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        @Override
6399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        public void shutdown() {
6409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            super.shutdown();
6419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            IoUtils.closeQuietly(mWriteSocket);
6429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
6439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
6449132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6459132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ETH_HEADER_LEN = 14;
64638db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static final int ETH_DEST_ADDR_OFFSET = 0;
6479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ETH_ETHERTYPE_OFFSET = 12;
648961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
649961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
6509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_VERSION_IHL_OFFSET = ETH_HEADER_LEN + 0;
6529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
6539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
654961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] IPV4_BROADCAST_ADDRESS =
655961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            {(byte) 255, (byte) 255, (byte) 255, (byte) 255};
6569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
6589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_HEADER_LEN = 40;
6599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
6609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // The IPv6 all nodes address ff02::1
6619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final byte[] IPV6_ALL_NODES_ADDRESS =
662961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi            { (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
6639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_TYPE_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN;
6659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_ROUTER_ADVERTISEMENT = 134;
6669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_NEIGHBOR_ANNOUNCEMENT = 136;
6679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_HEADER_LEN = 16;
6699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
6709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
6719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_CHECKSUM_OFFSET =
6729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
6739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RA_OPTION_OFFSET =
6749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
6759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
6779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_LEN = 32;
6789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
6799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
6809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC6106: Recursive DNS Server option
6829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
6839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC6106: DNS Search List option
6849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
6859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // From RFC4191: Route Information option
6879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
6889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Above three options all have the same format:
6899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_OPTION_LEN = 8;
6909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
6919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
6929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int UDP_HEADER_LEN = 8;
6949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int UDP_DESTINATION_PORT_OFFSET = ETH_HEADER_LEN + 22;
6959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int DHCP_CLIENT_PORT = 68;
6979132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 48;
6989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
6994fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi    private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
700961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ARP_IPV4_REQUEST_HEADER = {
7019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            0, 1, // Hardware type: Ethernet (1)
7029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            8, 0, // Protocol type: IP (0x0800)
7039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            6,    // Hardware size: 6
7049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            4,    // Protocol size: 4
7059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            0, 1  // Opcode: request (1)
7069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    };
707961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ARP_IPV4_REPLY_HEADER = {
70838db976514ff2ad12d207a927219762eab179882Hugo Benichi            0, 1, // Hardware type: Ethernet (1)
70938db976514ff2ad12d207a927219762eab179882Hugo Benichi            8, 0, // Protocol type: IP (0x0800)
71038db976514ff2ad12d207a927219762eab179882Hugo Benichi            6,    // Hardware size: 6
71138db976514ff2ad12d207a927219762eab179882Hugo Benichi            4,    // Protocol size: 4
71238db976514ff2ad12d207a927219762eab179882Hugo Benichi            0, 2  // Opcode: reply (2)
71338db976514ff2ad12d207a927219762eab179882Hugo Benichi    };
7144fc3ee5be223122792ebc0ee8a05c93d93e26a52Hugo Benichi    private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
7159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
716961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] MOCK_IPV4_ADDR           = {10, 0, 0, 1};
7177d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
718961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
719961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] ANOTHER_IPV4_ADDR        = {10, 0, 0, 2};
720961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static final byte[] IPV4_ANY_HOST_ADDR       = {0, 0, 0, 0};
7219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
7239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterIPv4() throws Exception {
7249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
7257d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
7267d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkProperties lp = new LinkProperties();
7277d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        lp.addLinkAddress(link);
7280dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi
7296ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
7307d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
7310dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi
7329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
7339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty packet of 100 zero bytes is passed
7359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
736961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify unicast IPv4 packet is passed
739961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
7409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
741961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
742961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
743961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
7440dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi        // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
745961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
7460dc1d314709d579ccdc3fc59a5f66557f6cd319dHugo Benichi        assertDrop(program, packet.array());
747961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
7487d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, packet.array());
749961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
750961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Verify multicast/broadcast IPv4, not DHCP to us, is dropped
751961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
752961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV4_VERSION_IHL_OFFSET, (byte)0x45);
754961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV4_PROTOCOL_OFFSET, (byte)IPPROTO_UDP);
756961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(UDP_DESTINATION_PORT_OFFSET, (short)DHCP_CLIENT_PORT);
758961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
759961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_MULTICAST_IPV4_ADDR);
760961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
761961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
762961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
763961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
764961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify broadcast IPv4 DHCP to us is passed
767961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, DHCP_CLIENT_MAC_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
768961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
769961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
770961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Verify unicast IPv4 DHCP to us is passed
771961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, TestApfFilter.MOCK_MAC_ADDR);
772961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
7759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
7769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
7789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterIPv6() throws Exception {
7799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
7806ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
7819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
7829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty IPv6 packet is passed
7849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
7859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
786961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty ICMPv6 packet is passed
7899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
790961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify empty ICMPv6 NA packet is passed
7939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_NEIGHBOR_ANNOUNCEMENT);
794961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
7959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
7969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify ICMPv6 NA to ff02::1 is dropped
797961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
798961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
7999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
8019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
8029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
80411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti    public void testApfFilterMulticast() throws Exception {
805961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] unicastIpv4Addr   = {(byte)192,0,2,63};
8067d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
807961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
808961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
809961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
8107d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
8117d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
8127d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        LinkProperties lp = new LinkProperties();
8137d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        lp.addLinkAddress(link);
8147d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
8157d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
8167d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
8177d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
8187d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        byte[] program = ipManagerCallback.getApfProgram();
8197d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
82011e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        // Construct IPv4 and IPv6 multicast packets.
821f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
822f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
823961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(mcastv4packet, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
824f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen
825f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        ByteBuffer mcastv6packet = ByteBuffer.wrap(new byte[100]);
826f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
827f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_UDP);
828961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(mcastv6packet, IPV6_DEST_ADDR_OFFSET, multicastIpv6Addr);
829f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen
830f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        // Construct IPv4 broadcast packet.
831961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4packet1 = ByteBuffer.wrap(new byte[100]);
832961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet1.put(ETH_BROADCAST_MAC_ADDRESS);
833961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet1.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
834961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4packet1, IPV4_DEST_ADDR_OFFSET, multicastIpv4Addr);
835961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
836961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4packet2 = ByteBuffer.wrap(new byte[100]);
837961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet2.put(ETH_BROADCAST_MAC_ADDRESS);
838961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4packet2.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
839961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4packet2, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
840961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
841961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        // Construct IPv4 broadcast with L2 unicast address packet (b/30231088).
842961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        ByteBuffer bcastv4unicastl2packet = ByteBuffer.wrap(new byte[100]);
843961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4unicastl2packet.put(TestApfFilter.MOCK_MAC_ADDR);
844961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        bcastv4unicastl2packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
845961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(bcastv4unicastl2packet, IPV4_DEST_ADDR_OFFSET, broadcastIpv4Addr);
84611e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti
8479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify initially disabled multicast filter is off
848961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv4packet.array());
849961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
850961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet1.array());
851961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet2.array());
852961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4unicastl2packet.array());
8539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Turn on multicast filter and verify it works
8559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
8569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.setMulticastFilter(true);
8579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
858961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv4packet.array());
859961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv6packet.array());
860961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet1.array());
861961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet2.array());
8627d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, bcastv4unicastl2packet.array());
8639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Turn off multicast filter and verify it's off
8659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
8669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.setMulticastFilter(false);
8679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
868961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv4packet.array());
869961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
870961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet1.array());
871961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4packet2.array());
872961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, bcastv4unicastl2packet.array());
8739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify it can be initialized to on
8759132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
8769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
8776ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
8787d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        apfFilter.setLinkProperties(lp);
8799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        program = ipManagerCallback.getApfProgram();
880961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv4packet.array());
881961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, mcastv6packet.array());
882961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, bcastv4packet1.array());
8837d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertDrop(program, bcastv4unicastl2packet.array());
88411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti
88511e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        // Verify that ICMPv6 multicast is not dropped.
886f8a01e84317fcb9d27a294e95603b846143c7fcbPaul Jensen        mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
887961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, mcastv6packet.array());
8889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
8899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
8909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
8919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
89238db976514ff2ad12d207a927219762eab179882Hugo Benichi    private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
89338db976514ff2ad12d207a927219762eab179882Hugo Benichi        cb.resetApfProgramWait();
89438db976514ff2ad12d207a927219762eab179882Hugo Benichi        filter.setLinkProperties(lp);
89538db976514ff2ad12d207a927219762eab179882Hugo Benichi        return cb.getApfProgram();
89638db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
89738db976514ff2ad12d207a927219762eab179882Hugo Benichi
89838db976514ff2ad12d207a927219762eab179882Hugo Benichi    private void verifyArpFilter(byte[] program, int filterResult) {
89938db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify ARP request packet
900961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR));
901961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
902961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
90338db976514ff2ad12d207a927219762eab179882Hugo Benichi
90438db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify unicast ARP reply packet is always accepted.
905961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
906961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
907961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
90838db976514ff2ad12d207a927219762eab179882Hugo Benichi
90938db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify GARP reply packets are always filtered
910961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, garpReply());
9119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
9149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterArp() throws Exception {
9159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
9166ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
9179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
91838db976514ff2ad12d207a927219762eab179882Hugo Benichi        // Verify initially ARP request filter is off, and GARP filter is on.
91938db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
9209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Inform ApfFilter of our address and verify ARP filtering is on
92238db976514ff2ad12d207a927219762eab179882Hugo Benichi        LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
9239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        LinkProperties lp = new LinkProperties();
92438db976514ff2ad12d207a927219762eab179882Hugo Benichi        assertTrue(lp.addLinkAddress(linkAddress));
92538db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP);
9269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Inform ApfFilter of loss of IP and verify ARP filtering is off
92838db976514ff2ad12d207a927219762eab179882Hugo Benichi        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS);
9299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
9319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
93338db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] arpRequestBroadcast(byte[] tip) {
93438db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
93538db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
936961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
937961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
938961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
93938db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
94038db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
94138db976514ff2ad12d207a927219762eab179882Hugo Benichi
94238db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] arpReplyUnicast(byte[] tip) {
94338db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
94438db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
945961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
946961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
94738db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
94838db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
94938db976514ff2ad12d207a927219762eab179882Hugo Benichi
95038db976514ff2ad12d207a927219762eab179882Hugo Benichi    private static byte[] garpReply() {
95138db976514ff2ad12d207a927219762eab179882Hugo Benichi        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
95238db976514ff2ad12d207a927219762eab179882Hugo Benichi        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
953961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
954961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
955961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, IPV4_ANY_HOST_ADDR);
95638db976514ff2ad12d207a927219762eab179882Hugo Benichi        return packet.array();
95738db976514ff2ad12d207a927219762eab179882Hugo Benichi    }
95838db976514ff2ad12d207a927219762eab179882Hugo Benichi
9599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Verify that the last program pushed to the IpManager.Callback properly filters the
9609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // given packet for the given lifetime.
9619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void verifyRaLifetime(MockIpManagerCallback ipManagerCallback, ByteBuffer packet,
9629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            int lifetime) {
9639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
9649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify new program should drop RA for 1/6th its lifetime
966961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
9679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertDrop(program, packet.array(), lifetime/6);
9689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(program, packet.array(), lifetime/6 + 1);
9699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        assertPass(program, packet.array(), lifetime);
9709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify RA checksum is ignored
9729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
973961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
9749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
975961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
9769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify other changes to RA make it not match filter
9789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(0, (byte)-1);
979961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, packet.array());
9809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        packet.put(0, (byte)0);
981961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertDrop(program, packet.array());
9829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // Test that when ApfFilter is shown the given packet, it generates a program to filter it
9859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    // for the given lifetime.
9869132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private void testRaLifetime(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
9879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            ByteBuffer packet, int lifetime) throws IOException, ErrnoException {
9889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify new program generated if ApfFilter witnesses RA
9899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.resetApfProgramWait();
9909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.pretendPacketReceived(packet.array());
9919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ipManagerCallback.getApfProgram();
9929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, packet, lifetime);
9949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
9959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
9966ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private void verifyRaEvent(RaEvent expected) {
9976ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        ArgumentCaptor<Parcelable> captor = ArgumentCaptor.forClass(Parcelable.class);
9986ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verify(mLog, atLeastOnce()).log(captor.capture());
9996ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        RaEvent got = lastRaEvent(captor.getAllValues());
10006ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        if (!raEventEquals(expected, got)) {
10016ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            assertEquals(expected, got);  // fail for printing an assertion error message.
10026ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        }
10036ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
10046ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
10056ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private RaEvent lastRaEvent(List<Parcelable> events) {
10066ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        RaEvent got = null;
10076ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        for (Parcelable ev : events) {
10086ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            if (ev instanceof RaEvent) {
10096ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                got = (RaEvent) ev;
10106ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi            }
10116ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        }
10126ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        return got;
10136ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
10146ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
10156ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    private boolean raEventEquals(RaEvent ev1, RaEvent ev2) {
10166ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        return (ev1 != null) && (ev2 != null)
10176ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.routerLifetime == ev2.routerLifetime)
10186ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.prefixValidLifetime == ev2.prefixValidLifetime)
10196ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.prefixPreferredLifetime == ev2.prefixPreferredLifetime)
10206ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.routeInfoLifetime == ev2.routeInfoLifetime)
10216ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.rdnssLifetime == ev2.rdnssLifetime)
10226ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi                && (ev1.dnsslLifetime == ev2.dnsslLifetime);
10236ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi    }
10246ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi
10258995d85b9432387520c9f04a69251536754b996bLorenzo Colitti    private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
10268995d85b9432387520c9f04a69251536754b996bLorenzo Colitti            ByteBuffer packet) throws IOException, ErrnoException {
10278995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ipManagerCallback.resetApfProgramWait();
10288995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        apfFilter.pretendPacketReceived(packet.array());
10298995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ipManagerCallback.assertNoProgramUpdate();
10308995d85b9432387520c9f04a69251536754b996bLorenzo Colitti    }
10318995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
10329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    @LargeTest
10339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    public void testApfFilterRa() throws Exception {
10349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
10356ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
10369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        byte[] program = ipManagerCallback.getApfProgram();
10379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify RA is passed the first time
10399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
10409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
10419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
10429132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
10439132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)1000);
104411e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        basePacket.position(IPV6_DEST_ADDR_OFFSET);
104511e13e2175674389ed18c2b1e1af69c5ad931e8fLorenzo Colitti        basePacket.put(IPV6_ALL_NODES_ADDRESS);
1046961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        assertPass(program, basePacket.array());
10479132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10489132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
10496ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, -1));
10509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10518995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        // Ensure zero-length options cause the packet to be silently skipped.
10528995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        // Do this before we test other packets. http://b/29586253
10538995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
10548995d85b9432387520c9f04a69251536754b996bLorenzo Colitti                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
10558995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        basePacket.clear();
10568995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put(basePacket);
10578995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
10588995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        zeroLengthOptionPacket.put((byte)0);
10598995d85b9432387520c9f04a69251536754b996bLorenzo Colitti        assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket);
10608995d85b9432387520c9f04a69251536754b996bLorenzo Colitti
10619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Generate several RAs with different options and lifetimes, and verify when
10629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // ApfFilter is shown these packets, it generates programs to filter them for the
10639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // appropriate lifetime.
10649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer prefixOptionPacket = ByteBuffer.wrap(
10659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
10669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
10679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put(basePacket);
10689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
10699132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
10709132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.putInt(
10719132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, 100);
10729132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        prefixOptionPacket.putInt(
10739132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 200);
10749132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, 100);
10756ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verifyRaEvent(new RaEvent(1000, 200, 100, -1, -1, -1));
10769132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10779132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
10789132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
10799132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
10809132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put(basePacket);
10819132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
10829132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
10839132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        rdnssOptionPacket.putInt(
10849132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 300);
10859132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, 300);
10866ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verifyRaEvent(new RaEvent(1000, -1, -1, -1, 300, -1));
10879132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10889132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
10899132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
10909132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
10919132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put(basePacket);
10929132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
10939132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
10949132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        routeInfoOptionPacket.putInt(
10959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 400);
10969132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, 400);
10976ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verifyRaEvent(new RaEvent(1000, -1, -1, 400, -1, -1));
10989132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
10999132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
11009132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
11019132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        basePacket.clear();
11029132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put(basePacket);
11039132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
11049132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
11059132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        dnsslOptionPacket.putInt(
11069132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 2000);
11079132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Note that lifetime of 2000 will be ignored in favor of shorter
11089132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // route lifetime of 1000.
11099132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, 1000);
11106ccd51a338fed39217cb3a5c0f229ed547918634Hugo Benichi        verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, 2000));
11119132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11129132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        // Verify that current program filters all five RAs:
11139132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, basePacket, 1000);
11149132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, prefixOptionPacket, 100);
11159132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, rdnssOptionPacket, 300);
11169132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, routeInfoOptionPacket, 400);
11179132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        verifyRaLifetime(ipManagerCallback, dnsslOptionPacket, 1000);
11189132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11199132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        apfFilter.shutdown();
11209132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
11219132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11229132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
11239132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Stage a file for testing, i.e. make it native accessible. Given a resource ID,
11249132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * copy that resource into the app's data directory and return the path to it.
11259132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
11269132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private String stageFile(int rawId) throws Exception {
11279132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        File file = new File(getContext().getFilesDir(), "staged_file");
11289132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        new File(file.getParent()).mkdirs();
11299132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        InputStream in = null;
11309132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        OutputStream out = null;
11319132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        try {
11329132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            in = getContext().getResources().openRawResource(rawId);
11339132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            out = new FileOutputStream(file);
11349132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            Streams.copy(in, out);
11359132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        } finally {
11369132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            if (in != null) in.close();
11379132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            if (out != null) out.close();
11389132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        }
11399132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen        return file.getAbsolutePath();
11409132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    }
11419132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
1142961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    private static void put(ByteBuffer buffer, int position, byte[] bytes) {
1143961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        final int original = buffer.position();
1144961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.position(position);
1145961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.put(bytes);
1146961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi        buffer.position(original);
1147961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi    }
1148961ca49fd67b39d8076ea49d12d2fda73f581399Hugo Benichi
11499132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
11509132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Call the APF interpreter the run {@code program} on {@code packet} pretending the
11519132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * filter was installed {@code filter_age} seconds ago.
11529132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
11539132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static int apfSimulate(byte[] program, byte[] packet, int filter_age);
11549132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11559132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
11569132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Compile a tcpdump human-readable filter (e.g. "icmp" or "tcp port 54") into a BPF
11579132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * prorgam and return a human-readable dump of the BPF program identical to "tcpdump -d".
11589132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
11599132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static String compileToBpf(String filter);
11609132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen
11619132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    /**
11629132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * Open packet capture file {@code pcap_filename} and filter the packets using tcpdump
11639132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * human-readable filter (e.g. "icmp" or "tcp port 54") compiled to a BPF program and
11649132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * at the same time using APF program {@code apf_program}.  Return {@code true} if
11659132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     * both APF and BPF programs filter out exactly the same packets.
11669132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen     */
11679132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen    private native static boolean compareBpfApf(String filter, String pcap_filename,
11689132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen            byte[] apf_program);
11697d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
11707d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    public void testBytesToInt() {
11717d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0x00000000, ApfFilter.bytesToInt(IPV4_ANY_HOST_ADDR));
11727d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0xffffffff, ApfFilter.bytesToInt(IPV4_BROADCAST_ADDRESS));
11737d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0x0a000001, ApfFilter.bytesToInt(MOCK_IPV4_ADDR));
11747d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0x0a000002, ApfFilter.bytesToInt(ANOTHER_IPV4_ADDR));
11757d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0x0a001fff, ApfFilter.bytesToInt(MOCK_BROADCAST_IPV4_ADDR));
11767d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(0xe0000001, ApfFilter.bytesToInt(MOCK_MULTICAST_IPV4_ADDR));
11777d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    }
11787d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
11797d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    public void testBroadcastAddress() throws Exception {
11807d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
11817d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
11827d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
11837d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
11847d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
11857d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
11867d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
11877d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
11887d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
11897d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    }
11907d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi
11917d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    public void assertEqualsIp(String expected, int got) throws Exception {
11927d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        int want = ApfFilter.bytesToInt(InetAddress.getByName(expected).getAddress());
11937d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi        assertEquals(want, got);
11947d21eaedade0e01bed665dd2e4ba15e0c217237cHugo Benichi    }
11959132f34976f16a626c2ec1d3d90624d71e054346Paul Jensen}
1196