Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b144e6d authored by Bernie Innocenti's avatar Bernie Innocenti Committed by Android (Google) Code Review
Browse files

Merge "Teach ApfGenerator about the new opcodes for accessing data memory" into pi-dev

parents ba199f56 408dbda4
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -522,7 +522,7 @@ public class ApfFilter {
                    ICMP6_4_BYTE_LIFETIME_OFFSET, ICMP6_4_BYTE_LIFETIME_LEN);
        }

        // Note that this parses RA and may throw IllegalArgumentException (from
        // Note that this parses RA and may throw InvalidRaException (from
        // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
        // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
        // specifications.
@@ -986,9 +986,8 @@ public class ApfFilter {
     */
    @GuardedBy("this")
    private ApfGenerator beginProgramLocked() throws IllegalInstructionException {
        ApfGenerator gen = new ApfGenerator();
        // This is guaranteed to return true because of the check in maybeCreate.
        gen.setApfVersion(mApfCapabilities.apfVersionSupported);
        // This is guaranteed to succeed because of the check in maybeCreate.
        ApfGenerator gen = new ApfGenerator(mApfCapabilities.apfVersionSupported);

        // Here's a basic summary of what the initial program does:
        //
@@ -1216,7 +1215,7 @@ public class ApfFilter {
        //   1. the program generator will need its offsets adjusted.
        //   2. the packet filter attached to our packet socket will need its offset adjusted.
        if (apfCapabilities.apfPacketFormat != ARPHRD_ETHER) return null;
        if (!new ApfGenerator().setApfVersion(apfCapabilities.apfVersionSupported)) {
        if (!ApfGenerator.supportsVersion(apfCapabilities.apfVersionSupported)) {
            Log.e(TAG, "Unsupported APF version: " + apfCapabilities.apfVersionSupported);
            return null;
        }
+57 −6
Original line number Diff line number Diff line
@@ -58,7 +58,9 @@ public class ApfGenerator {
        JLT(18),   // Compare less than and branch, e.g. "jlt R0,5,label"
        JSET(19),  // Compare any bits set and branch, e.g. "jset R0,5,label"
        JNEBS(20), // Compare not equal byte sequence, e.g. "jnebs R0,5,label,0x1122334455"
        EXT(21);   // Followed by immediate indicating ExtendedOpcodes.
        EXT(21),   // Followed by immediate indicating ExtendedOpcodes.
        LDDW(22),  // Load 4 bytes from data memory address (register + immediate): "lddw R0, [5]R1"
        STDW(23);  // Store 4 bytes to data memory address (register + immediate): "stdw R0, [5]R1"

        final int value;

@@ -355,19 +357,38 @@ public class ApfGenerator {
     */
    public static final int LAST_PREFILLED_MEMORY_SLOT = FILTER_AGE_MEMORY_SLOT;

    // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
    private static final int MIN_APF_VERSION = 2;

    private final ArrayList<Instruction> mInstructions = new ArrayList<Instruction>();
    private final HashMap<String, Instruction> mLabels = new HashMap<String, Instruction>();
    private final Instruction mDropLabel = new Instruction(Opcodes.LABEL);
    private final Instruction mPassLabel = new Instruction(Opcodes.LABEL);
    private final int mVersion;
    private boolean mGenerated;

    /**
     * Set version of APF instruction set to generate instructions for. Returns {@code true}
     * if generating for this version is supported, {@code false} otherwise.
     * Creates an ApfGenerator instance which is able to emit instructions for the specified
     * {@code version} of the APF interpreter. Throws {@code IllegalInstructionException} if
     * the requested version is unsupported.
     */
    public boolean setApfVersion(int version) {
        // This version number syncs up with APF_VERSION in hardware/google/apf/apf_interpreter.h
        return version >= 2;
    ApfGenerator(int version) throws IllegalInstructionException {
        mVersion = version;
        requireApfVersion(MIN_APF_VERSION);
    }

    /**
     * Returns true if the specified {@code version} is supported by the ApfGenerator, otherwise
     * false.
     */
    public static boolean supportsVersion(int version) {
        return version >= MIN_APF_VERSION;
    }

    private void requireApfVersion(int minimumVersion) throws IllegalInstructionException {
        if (mVersion < minimumVersion) {
            throw new IllegalInstructionException("Requires APF >= " + minimumVersion);
        }
    }

    private void addInstruction(Instruction instruction) {
@@ -818,6 +839,36 @@ public class ApfGenerator {
        return this;
    }

    /**
     * Add an instruction to the end of the program to load 32 bits from the data memory into
     * {@code register}. The source address is computed by adding @{code offset} to the other
     * register.
     * Requires APF v3 or greater.
     */
    public ApfGenerator addLoadData(Register destinationRegister, int offset)
            throws IllegalInstructionException {
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
        instruction.setUnsignedImm(offset);
        addInstruction(instruction);
        return this;
    }

    /**
     * Add an instruction to the end of the program to store 32 bits from {@code register} into the
     * data memory. The destination address is computed by adding @{code offset} to the other
     * register.
     * Requires APF v3 or greater.
     */
    public ApfGenerator addStoreData(Register sourceRegister, int offset)
            throws IllegalInstructionException {
        requireApfVersion(3);
        Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
        instruction.setUnsignedImm(offset);
        addInstruction(instruction);
        return this;
    }

    /**
     * Updates instruction offset fields using latest instruction sizes.
     * @return current program length in bytes.
+223 −84

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ public class Bpf2Apf {
     * program and return it.
     */
    public static byte[] convert(String bpf) throws IllegalInstructionException {
        ApfGenerator gen = new ApfGenerator();
        ApfGenerator gen = new ApfGenerator(3);
        for (String line : bpf.split("\\n")) convertLine(line, gen);
        return gen.generate();
    }
@@ -320,7 +320,7 @@ public class Bpf2Apf {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        StringBuilder responseData = new StringBuilder();
        ApfGenerator gen = new ApfGenerator();
        ApfGenerator gen = new ApfGenerator(3);
        while ((line = in.readLine()) != null) convertLine(line, gen);
        System.out.write(gen.generate());
    }
+18 −11
Original line number Diff line number Diff line
/*
 * Copyright 2016, The Android Open Source Project
 * Copyright 2018, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -28,15 +28,22 @@

// JNI function acting as simply call-through to native APF interpreter.
static jint com_android_server_ApfTest_apfSimulate(
        JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jint filter_age) {
    return accept_packet(
            (uint8_t*)env->GetByteArrayElements(program, NULL),
            env->GetArrayLength(program),
            (uint8_t*)env->GetByteArrayElements(packet, NULL),
            env->GetArrayLength(packet),
            nullptr,
            0,
            filter_age);
        JNIEnv* env, jclass, jbyteArray program, jbyteArray packet,
        jbyteArray data, jint filter_age) {
    uint8_t* program_raw = (uint8_t*)env->GetByteArrayElements(program, nullptr);
    uint8_t* packet_raw = (uint8_t*)env->GetByteArrayElements(packet, nullptr);
    uint8_t* data_raw = (uint8_t*)(data ? env->GetByteArrayElements(data, nullptr) : nullptr);
    uint32_t program_len = env->GetArrayLength(program);
    uint32_t packet_len = env->GetArrayLength(packet);
    uint32_t data_len = data ? env->GetArrayLength(data) : 0;
    jint result = accept_packet(program_raw, program_len, packet_raw,
                                packet_len, data_raw, data_len, filter_age);
    if (data) {
        env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */);
    }
    env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT);
    env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT);
    return result;
}

class ScopedPcap {
@@ -170,7 +177,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
    }

    static JNINativeMethod gMethods[] = {
            { "apfSimulate", "([B[BI)I",
            { "apfSimulate", "([B[B[BI)I",
                    (void*)com_android_server_ApfTest_apfSimulate },
            { "compileToBpf", "(Ljava/lang/String;)Ljava/lang/String;",
                    (void*)com_android_server_ApfTest_compileToBpf },