public OFMatch loadFromPacket(byte[] packetData, short inputPort) {
        short scratch;
        int transportOffset = 34;
        ByteBuffer packetDataBB = ByteBuffer.wrap(packetData);
        int limit = packetDataBB.limit();

        this.wildcards = 0; // all fields have explicit entries

        this.inputPort = inputPort;

        if (inputPort == OFPort.OFPP_ALL.getValue())
            this.wildcards |= OFPFW_IN_PORT;

        assert (limit >= 14);
        // dl dst
        this.dataLayerDestination = new byte[6];
        packetDataBB.get(this.dataLayerDestination);
        // dl src
        this.dataLayerSource = new byte[6];
        packetDataBB.get(this.dataLayerSource);
        // dl type
        this.dataLayerType = packetDataBB.getShort();

        if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed
            // bug
            setDataLayerVirtualLan((short) 0xffff);
            setDataLayerVirtualLanPriorityCodePoint((byte) 0);
        } else {
            // has vlan tag
            scratch = packetDataBB.getShort();
            setDataLayerVirtualLan((short) (0xfff & scratch));
            setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13));
            this.dataLayerType = packetDataBB.getShort();
        }

        switch (getDataLayerType()) {
        case 0x0800:
            // ipv4
            // check packet length
            scratch = packetDataBB.get();
            scratch = (short) (0xf & scratch);
            transportOffset = (packetDataBB.position() - 1) + (scratch * 4);
            // nw tos (dscp)
            scratch = packetDataBB.get();
            setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2));
            // nw protocol
            packetDataBB.position(packetDataBB.position() + 7);
            this.networkProtocol = packetDataBB.get();
            // nw src
            packetDataBB.position(packetDataBB.position() + 2);
            this.networkSource = packetDataBB.getInt();
            // nw dst
            this.networkDestination = packetDataBB.getInt();
            packetDataBB.position(transportOffset);
            break;
        case 0x0806:
            // arp
            int arpPos = packetDataBB.position();
            // opcode
            scratch = packetDataBB.getShort(arpPos + 6);
            setNetworkProtocol((byte) (0xff & scratch));

            scratch = packetDataBB.getShort(arpPos + 2);
            // if ipv4 and addr len is 4
            if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) {
                // nw src
                this.networkSource = packetDataBB.getInt(arpPos + 14);
                // nw dst
                this.networkDestination = packetDataBB.getInt(arpPos + 24);
            } else {
                setNetworkSource(0);
                setNetworkDestination(0);
            }
            break;
        default:
            setNetworkTypeOfService((byte) 0);
            setNetworkProtocol((byte) 0);
            setNetworkSource(0);
            setNetworkDestination(0);
            break;
        }

        switch (getNetworkProtocol()) {
        case 0x01:
            // icmp
            // type
            this.transportSource = U8.f(packetDataBB.get());
            // code
            this.transportDestination = U8.f(packetDataBB.get());
            break;
        case 0x06:
            // tcp
            // tcp src
            this.transportSource = packetDataBB.getShort();
            // tcp dest
            this.transportDestination = packetDataBB.getShort();
            break;
        case 0x11:
            // udp
            // udp src
            this.transportSource = packetDataBB.getShort();
            // udp dest
            this.transportDestination = packetDataBB.getShort();
            break;
        default:
            setTransportDestination((short) 0);
            setTransportSource((short) 0);
            break;
        }
        return this;
    }