diff options
author | Samuel Tan <samueltan@google.com> | 2016-04-20 16:55:34 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-04-20 16:55:34 +0000 |
commit | af8c59a9cb6b9cd0151b3cfa5d4ea2c698fd7eda (patch) | |
tree | 58c60405b20b7e85f444cdb53df44f5d8bc4d5f4 | |
parent | 985df17909a5703a86f3e665abc9dd964d9623d9 (diff) | |
parent | 590f3fc2045389d5ef274c4b3bd6162d93b1a0ac (diff) |
Merge changes Id4cc9c3c,Ice7dad5a into nyc-dev
* changes:
Log summarized packet fate reports
Add FrameParser
7 files changed, 1062 insertions, 218 deletions
diff --git a/service/java/com/android/server/wifi/WifiLogger.java b/service/java/com/android/server/wifi/WifiLogger.java index 6d7b608a8..047794f98 100644 --- a/service/java/com/android/server/wifi/WifiLogger.java +++ b/service/java/com/android/server/wifi/WifiLogger.java @@ -29,6 +29,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.lang.StringBuilder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Calendar; @@ -137,7 +138,7 @@ class WifiLogger extends BaseWifiLogger { startLoggingAllExceptPerPacketBuffers(); } - if (verboseEnabled && !mWifiNative.startPktFateMonitoring()) { + if (!mWifiNative.startPktFateMonitoring()) { Log.e(TAG, "Failed to start packet fate monitoring"); } } @@ -178,10 +179,6 @@ class WifiLogger extends BaseWifiLogger { @Override synchronized void reportConnectionFailure() { - if (!isVerboseLoggingEnabled()) { - return; - } - mPacketFatesForLastFailure = fetchPacketFates(); } @@ -631,14 +628,16 @@ class WifiLogger extends BaseWifiLogger { } private void dumpPacketFates(PrintWriter pw) { - dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure); + dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure, + isVerboseLoggingEnabled()); if (DBG) { - dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates()); + dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates(), + isVerboseLoggingEnabled()); } } - private static void dumpPacketFatesInternal( - PrintWriter pw, String description, ArrayList<WifiNative.FateReport> fates) { + private static void dumpPacketFatesInternal(PrintWriter pw, String description, + ArrayList<WifiNative.FateReport> fates, boolean verbose) { if (fates == null) { pw.format("No fates fetched for \"%s\"\n", description); return; @@ -649,14 +648,25 @@ class WifiLogger extends BaseWifiLogger { return; } - int i = 0; pw.format("--------------------- %s ----------------------\n", description); + + StringBuilder verboseOutput = new StringBuilder(); + pw.print(WifiNative.FateReport.getTableHeader()); for (WifiNative.FateReport fate : fates) { - pw.format("Frame number: %d\n", i + 1); - pw.print(fate); - pw.print("\n"); - ++i; + pw.print(fate.toTableRowString()); + if (verbose) { + // Important: only print Personally Identifiable Information (PII) if verbose + // logging is turned on. + verboseOutput.append(fate.toVerboseStringWithPiiAllowed()); + verboseOutput.append("\n"); + } + } + + if (verbose) { + pw.format("\n>>> VERBOSE PACKET FATE DUMP <<<\n\n"); + pw.print(verboseOutput.toString()); } + pw.println("--------------------------------------------------------------------"); } } diff --git a/service/java/com/android/server/wifi/WifiLoggerHal.java b/service/java/com/android/server/wifi/WifiLoggerHal.java index 1d542b87d..ce3640182 100644 --- a/service/java/com/android/server/wifi/WifiLoggerHal.java +++ b/service/java/com/android/server/wifi/WifiLoggerHal.java @@ -16,34 +16,34 @@ package com.android.server.wifi; -class WifiLoggerHal { +public class WifiLoggerHal { // Must match wifi_logger.h - static final int MAX_FATE_LOG_LEN = 32; + public static final int MAX_FATE_LOG_LEN = 32; - static final byte FRAME_TYPE_UNKNOWN = 0; - static final byte FRAME_TYPE_ETHERNET_II = 1; - static final byte FRAME_TYPE_80211_MGMT = 2; + public static final byte FRAME_TYPE_UNKNOWN = 0; + public static final byte FRAME_TYPE_ETHERNET_II = 1; + public static final byte FRAME_TYPE_80211_MGMT = 2; - static final byte TX_PKT_FATE_ACKED = 0; - static final byte TX_PKT_FATE_SENT = 1; - static final byte TX_PKT_FATE_FW_QUEUED = 2; - static final byte TX_PKT_FATE_FW_DROP_INVALID = 3; - static final byte TX_PKT_FATE_FW_DROP_NOBUFS = 4; - static final byte TX_PKT_FATE_FW_DROP_OTHER = 5; - static final byte TX_PKT_FATE_DRV_QUEUED = 6; - static final byte TX_PKT_FATE_DRV_DROP_INVALID = 7; - static final byte TX_PKT_FATE_DRV_DROP_NOBUFS = 9; - static final byte TX_PKT_FATE_DRV_DROP_OTHER = 10; + public static final byte TX_PKT_FATE_ACKED = 0; + public static final byte TX_PKT_FATE_SENT = 1; + public static final byte TX_PKT_FATE_FW_QUEUED = 2; + public static final byte TX_PKT_FATE_FW_DROP_INVALID = 3; + public static final byte TX_PKT_FATE_FW_DROP_NOBUFS = 4; + public static final byte TX_PKT_FATE_FW_DROP_OTHER = 5; + public static final byte TX_PKT_FATE_DRV_QUEUED = 6; + public static final byte TX_PKT_FATE_DRV_DROP_INVALID = 7; + public static final byte TX_PKT_FATE_DRV_DROP_NOBUFS = 9; + public static final byte TX_PKT_FATE_DRV_DROP_OTHER = 10; - static final byte RX_PKT_FATE_SUCCESS = 0; - static final byte RX_PKT_FATE_FW_QUEUED = 1; - static final byte RX_PKT_FATE_FW_DROP_FILTER = 2; - static final byte RX_PKT_FATE_FW_DROP_INVALID = 3; - static final byte RX_PKT_FATE_FW_DROP_NOBUFS = 4; - static final byte RX_PKT_FATE_FW_DROP_OTHER = 5; - static final byte RX_PKT_FATE_DRV_QUEUED = 6; - static final byte RX_PKT_FATE_DRV_DROP_FILTER = 7; - static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8; - static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9; - static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10; + public static final byte RX_PKT_FATE_SUCCESS = 0; + public static final byte RX_PKT_FATE_FW_QUEUED = 1; + public static final byte RX_PKT_FATE_FW_DROP_FILTER = 2; + public static final byte RX_PKT_FATE_FW_DROP_INVALID = 3; + public static final byte RX_PKT_FATE_FW_DROP_NOBUFS = 4; + public static final byte RX_PKT_FATE_FW_DROP_OTHER = 5; + public static final byte RX_PKT_FATE_DRV_QUEUED = 6; + public static final byte RX_PKT_FATE_DRV_DROP_FILTER = 7; + public static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8; + public static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9; + public static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10; } diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index f6381b929..c07350d2f 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -50,6 +50,7 @@ import com.android.server.connectivity.KeepalivePacketData; import com.android.server.wifi.hotspot2.NetworkDetail; import com.android.server.wifi.hotspot2.SupplicantBridge; import com.android.server.wifi.hotspot2.Utils; +import com.android.server.wifi.util.FrameParser; import com.android.server.wifi.util.InformationElementUtil; import libcore.util.HexEncoding; @@ -2638,21 +2639,44 @@ public class WifiNative { mFrameBytes = frameBytes; } - @Override - public String toString() { + public String toTableRowString() { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + FrameParser parser = new FrameParser(mFrameType, mFrameBytes); + pw.format("%-15s %-9s %-32s %-12s %s\n", + mDriverTimestampUSec, directionToString(), fateToString(), + parser.mMostSpecificProtocolString, parser.mTypeString); + return sw.toString(); + } + + public String toVerboseStringWithPiiAllowed() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); + FrameParser parser = new FrameParser(mFrameType, mFrameBytes); pw.format("Frame direction: %s\n", directionToString()); pw.format("Frame timestamp: %d\n", mDriverTimestampUSec); pw.format("Frame fate: %s\n", fateToString()); pw.format("Frame type: %s\n", frameTypeToString(mFrameType)); + pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString); + pw.format("Frame protocol type: %s\n", parser.mTypeString); pw.format("Frame length: %d\n", mFrameBytes.length); pw.append("Frame bytes"); - pw.append(HexDump.dumpHexString(mFrameBytes)); + pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII pw.append("\n"); return sw.toString(); } + /* Returns a header to match the output of toTableRowString(). */ + public static String getTableHeader() { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.format("\n%-15s %-9s %-32s %-12s %s\n", + "Timestamp", "Direction", "Fate", "Protocol", "Type"); + pw.format("%-15s %-9s %-32s %-12s %s\n", + "---------", "---------", "----", "--------", "----"); + return sw.toString(); + } + protected abstract String directionToString(); protected abstract String fateToString(); diff --git a/service/java/com/android/server/wifi/util/FrameParser.java b/service/java/com/android/server/wifi/util/FrameParser.java new file mode 100644 index 000000000..165ebbb89 --- /dev/null +++ b/service/java/com/android/server/wifi/util/FrameParser.java @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.wifi.util; + +import android.util.Log; + +import com.android.server.wifi.WifiLoggerHal; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.HashSet; +import java.util.Set; + +/** + * This class parses the raw bytes of a network frame, and stores the parsed information in its + * public fields. + */ +public class FrameParser { + /** + * Note: When adding constants derived from network protocol specifications, please encode + * these constants the same way as the relevant specification, for ease of comparison. + */ + + private static final String TAG = "FrameParser"; + + /* These fields hold the information parsed from this frame. */ + public String mMostSpecificProtocolString = "N/A"; + public String mTypeString = "N/A"; + + /** + * Parses the contents of a given network frame. + * + * @param frameType The type of the frame, as defined in + * {@link com.android.server.wifi.WifiLoggerHal}. + * @param frameBytes The raw bytes of the frame to be parsed. + */ + public FrameParser(byte frameType, byte[] frameBytes) { + try { + ByteBuffer frameBuffer = ByteBuffer.wrap(frameBytes); + frameBuffer.order(ByteOrder.BIG_ENDIAN); + if (frameType == WifiLoggerHal.FRAME_TYPE_ETHERNET_II) { + parseEthernetFrame(frameBuffer); + } else if (frameType == WifiLoggerHal.FRAME_TYPE_80211_MGMT) { + parseManagementFrame(frameBuffer); + } + } catch (BufferUnderflowException | IllegalArgumentException e) { + Log.e(TAG, "Dissection aborted mid-frame: " + e); + } + } + + /** + * Read one byte into a form that can easily be compared against, or output as, an integer + * in the range (0, 255). + */ + private static short getUnsignedByte(ByteBuffer data) { + return (short) (data.get() & 0x00ff); + } + /** + * Read two bytes into a form that can easily be compared against, or output as, an integer + * in the range (0, 65535). + */ + private static int getUnsignedShort(ByteBuffer data) { + return (data.getShort() & 0xffff); + } + + private static final int ETHERNET_SRC_MAC_ADDR_LEN = 6; + private static final int ETHERNET_DST_MAC_ADDR_LEN = 6; + private static final short ETHERTYPE_IP_V4 = (short) 0x0800; + private static final short ETHERTYPE_ARP = (short) 0x0806; + private static final short ETHERTYPE_IP_V6 = (short) 0x86dd; + private static final short ETHERTYPE_EAPOL = (short) 0x888e; + + private void parseEthernetFrame(ByteBuffer data) { + mMostSpecificProtocolString = "Ethernet"; + data.position(data.position() + ETHERNET_SRC_MAC_ADDR_LEN + ETHERNET_DST_MAC_ADDR_LEN); + short etherType = data.getShort(); + switch (etherType) { + case ETHERTYPE_IP_V4: + parseIpv4Packet(data); + return; + case ETHERTYPE_ARP: + parseArpPacket(data); + return; + case ETHERTYPE_IP_V6: + parseIpv6Packet(data); + return; + case ETHERTYPE_EAPOL: + parseEapolPacket(data); + return; + default: + return; + } + } + + private static final byte IP_V4_VERSION_BYTE_MASK = (byte) 0b11110000; + private static final byte IP_V4_IHL_BYTE_MASK = (byte) 0b00001111; + private static final byte IP_V4_ADDR_LEN = 4; + private static final byte IP_V4_DSCP_AND_ECN_LEN = 1; + private static final byte IP_V4_TOTAL_LEN_LEN = 2; + private static final byte IP_V4_ID_LEN = 2; + private static final byte IP_V4_FLAGS_AND_FRAG_OFFSET_LEN = 2; + private static final byte IP_V4_TTL_LEN = 1; + private static final byte IP_V4_HEADER_CHECKSUM_LEN = 2; + private static final byte IP_V4_SRC_ADDR_LEN = 4; + private static final byte IP_V4_DST_ADDR_LEN = 4; + private static final byte IP_PROTO_ICMP = 1; + private static final byte IP_PROTO_TCP = 6; + private static final byte IP_PROTO_UDP = 17; + private static final byte BYTES_PER_QUAD = 4; + + private void parseIpv4Packet(ByteBuffer data) { + mMostSpecificProtocolString = "IPv4"; + data.mark(); + byte versionAndHeaderLen = data.get(); + int version = (versionAndHeaderLen & IP_V4_VERSION_BYTE_MASK) >> 4; + if (version != 4) { + Log.e(TAG, "IPv4 header: Unrecognized protocol version " + version); + return; + } + + data.position(data.position() + IP_V4_DSCP_AND_ECN_LEN + IP_V4_TOTAL_LEN_LEN + + IP_V4_ID_LEN + IP_V4_FLAGS_AND_FRAG_OFFSET_LEN + IP_V4_TTL_LEN); + short protocolNumber = getUnsignedByte(data); + data.position(data.position() + IP_V4_HEADER_CHECKSUM_LEN + IP_V4_SRC_ADDR_LEN + + IP_V4_DST_ADDR_LEN); + + int headerLen = (versionAndHeaderLen & IP_V4_IHL_BYTE_MASK) * BYTES_PER_QUAD; + data.reset(); // back to start of IPv4 header + data.position(data.position() + headerLen); + + switch (protocolNumber) { + case IP_PROTO_ICMP: + parseIcmpPacket(data); + break; + case IP_PROTO_TCP: + parseTcpPacket(data); + break; + case IP_PROTO_UDP: + parseUdpPacket(data); + break; + default: + break; + } + } + + private static final byte TCP_SRC_PORT_LEN = 2; + private static final int HTTPS_PORT = 443; + private static final Set<Integer> HTTP_PORTS = new HashSet<>(); + static { + HTTP_PORTS.add(80); + HTTP_PORTS.add(3128); + HTTP_PORTS.add(3132); + HTTP_PORTS.add(5985); + HTTP_PORTS.add(8080); + HTTP_PORTS.add(8088); + HTTP_PORTS.add(11371); + HTTP_PORTS.add(1900); + HTTP_PORTS.add(2869); + HTTP_PORTS.add(2710); + } + + private void parseTcpPacket(ByteBuffer data) { + mMostSpecificProtocolString = "TCP"; + data.position(data.position() + TCP_SRC_PORT_LEN); + int dstPort = getUnsignedShort(data); + + if (dstPort == HTTPS_PORT) { + mTypeString = "HTTPS"; + } else if (HTTP_PORTS.contains(dstPort)) { + mTypeString = "HTTP"; + } + } + + private static final byte UDP_PORT_BOOTPS = 67; + private static final byte UDP_PORT_BOOTPC = 68; + private static final byte UDP_PORT_NTP = 123; + private static final byte UDP_CHECKSUM_LEN = 2; + + private void parseUdpPacket(ByteBuffer data) { + mMostSpecificProtocolString = "UDP"; + int srcPort = getUnsignedShort(data); + int dstPort = getUnsignedShort(data); + int length = getUnsignedShort(data); + + data.position(data.position() + UDP_CHECKSUM_LEN); + if ((srcPort == UDP_PORT_BOOTPC && dstPort == UDP_PORT_BOOTPS) + || (srcPort == UDP_PORT_BOOTPS && dstPort == UDP_PORT_BOOTPC)) { + parseDhcpPacket(data); + return; + } + if (srcPort == UDP_PORT_NTP || dstPort == UDP_PORT_NTP) { + mMostSpecificProtocolString = "NTP"; + return; + } + } + + private static final byte BOOTP_OPCODE_LEN = 1; + private static final byte BOOTP_HWTYPE_LEN = 1; + private static final byte BOOTP_HWADDR_LEN_LEN = 1; + private static final byte BOOTP_HOPCOUNT_LEN = 1; + private static final byte BOOTP_TRANSACTION_ID_LEN = 4; + private static final byte BOOTP_ELAPSED_SECONDS_LEN = 2; + private static final byte BOOTP_FLAGS_LEN = 2; + private static final byte BOOTP_CLIENT_HWADDR_LEN = 16; + private static final byte BOOTP_SERVER_HOSTNAME_LEN = 64; + private static final short BOOTP_BOOT_FILENAME_LEN = 128; + private static final byte BOOTP_MAGIC_COOKIE_LEN = 4; + private static final short DHCP_OPTION_TAG_PAD = 0; + private static final short DHCP_OPTION_TAG_MESSAGE_TYPE = 53; + private static final short DHCP_OPTION_TAG_END = 255; + + private void parseDhcpPacket(ByteBuffer data) { + mMostSpecificProtocolString = "DHCP"; + data.position(data.position() + BOOTP_OPCODE_LEN + BOOTP_HWTYPE_LEN + BOOTP_HWADDR_LEN_LEN + + BOOTP_HOPCOUNT_LEN + BOOTP_TRANSACTION_ID_LEN + BOOTP_ELAPSED_SECONDS_LEN + + BOOTP_FLAGS_LEN + IP_V4_ADDR_LEN * 4 + BOOTP_CLIENT_HWADDR_LEN + + BOOTP_SERVER_HOSTNAME_LEN + BOOTP_BOOT_FILENAME_LEN + BOOTP_MAGIC_COOKIE_LEN); + while (data.remaining() > 0) { + short dhcpOptionTag = getUnsignedByte(data); + if (dhcpOptionTag == DHCP_OPTION_TAG_PAD) { + continue; + } + if (dhcpOptionTag == DHCP_OPTION_TAG_END) { + break; + } + short dhcpOptionLen = getUnsignedByte(data); + switch (dhcpOptionTag) { + case DHCP_OPTION_TAG_MESSAGE_TYPE: + if (dhcpOptionLen != 1) { + Log.e(TAG, "DHCP option len: " + dhcpOptionLen + " (expected |1|)"); + return; + } + mTypeString = decodeDhcpMessageType(getUnsignedByte(data)); + return; + default: + data.position(data.position() + dhcpOptionLen); + } + } + } + + private static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; + private static final byte DHCP_MESSAGE_TYPE_OFFER = 2; + private static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; + private static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; + private static final byte DHCP_MESSAGE_TYPE_ACK = 5; + private static final byte DHCP_MESSAGE_TYPE_NAK = 6; + private static final byte DHCP_MESSAGE_TYPE_RELEASE = 7; + private static final byte DHCP_MESSAGE_TYPE_INFORM = 8; + + private static String decodeDhcpMessageType(short messageType) { + switch (messageType) { + case DHCP_MESSAGE_TYPE_DISCOVER: + return "Discover"; + case DHCP_MESSAGE_TYPE_OFFER: + return "Offer"; + case DHCP_MESSAGE_TYPE_REQUEST: + return "Request"; + case DHCP_MESSAGE_TYPE_DECLINE: + return "Decline"; + case DHCP_MESSAGE_TYPE_ACK: + return "Ack"; + case DHCP_MESSAGE_TYPE_NAK: + return "Nak"; + case DHCP_MESSAGE_TYPE_RELEASE: + return "Release"; + case DHCP_MESSAGE_TYPE_INFORM: + return "Inform"; + default: + return "Unknown type " + messageType; + } + } + + private static final byte ICMP_TYPE_ECHO_REPLY = 0; + private static final byte ICMP_TYPE_DEST_UNREACHABLE = 3; + private static final byte ICMP_TYPE_REDIRECT = 5; + private static final byte ICMP_TYPE_ECHO_REQUEST = 8; + + private void parseIcmpPacket(ByteBuffer data) { + mMostSpecificProtocolString = "ICMP"; + short messageType = getUnsignedByte(data); + switch (messageType) { + case ICMP_TYPE_ECHO_REPLY: + mTypeString = "Echo Reply"; + return; + case ICMP_TYPE_DEST_UNREACHABLE: + mTypeString = "Destination Unreachable"; + return; + case ICMP_TYPE_REDIRECT: + mTypeString = "Redirect"; + return; + case ICMP_TYPE_ECHO_REQUEST: + mTypeString = "Echo Request"; + return; + default: + mTypeString = "Type " + messageType; + return; + } + } + + private static final byte ARP_HWTYPE_LEN = 2; + private static final byte ARP_PROTOTYPE_LEN = 2; + private static final byte ARP_HWADDR_LEN_LEN = 1; + private static final byte ARP_PROTOADDR_LEN_LEN = 1; + private static final byte ARP_OPCODE_REQUEST = 1; + private static final byte ARP_OPCODE_REPLY = 2; + + private void parseArpPacket(ByteBuffer data) { + mMostSpecificProtocolString = "ARP"; + data.position(data.position() + ARP_HWTYPE_LEN + ARP_PROTOTYPE_LEN + ARP_HWADDR_LEN_LEN + + ARP_PROTOADDR_LEN_LEN); + int opCode = getUnsignedShort(data); + switch (opCode) { + case ARP_OPCODE_REQUEST: + mTypeString = "Request"; + break; + case ARP_OPCODE_REPLY: + mTypeString = "Reply"; + break; + default: + mTypeString = "Operation " + opCode; + } + } + + private static final byte IP_V6_PAYLOAD_LENGTH_LEN = 2; + private static final byte IP_V6_HOP_LIMIT_LEN = 1; + private static final byte IP_V6_ADDR_LEN = 16; + private static final byte IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION = 0; + private static final byte IP_V6_HEADER_TYPE_ICMP_V6 = 58; + private static final byte BYTES_PER_OCT = 8; + + private void parseIpv6Packet(ByteBuffer data) { + mMostSpecificProtocolString = "IPv6"; + int versionClassAndLabel = data.getInt(); + int version = (versionClassAndLabel & 0xf0000000) >> 28; + if (version != 6) { + Log.e(TAG, "IPv6 header: invalid IP version " + version); + return; + } + data.position(data.position() + IP_V6_PAYLOAD_LENGTH_LEN); + + short nextHeaderType = getUnsignedByte(data); + data.position(data.position() + IP_V6_HOP_LIMIT_LEN + IP_V6_ADDR_LEN * 2); + while (nextHeaderType == IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION) { + int thisHeaderLen; + data.mark(); + nextHeaderType = getUnsignedByte(data); + thisHeaderLen = (getUnsignedByte(data) + 1) * BYTES_PER_OCT; + data.reset(); // back to start of this header + data.position(data.position() + thisHeaderLen); + } + switch (nextHeaderType) { + case IP_V6_HEADER_TYPE_ICMP_V6: + parseIcmpV6Packet(data); + return; + default: + mTypeString = "Option/Protocol " + nextHeaderType; + return; + } + } + + private static final short ICMP_V6_TYPE_ECHO_REQUEST = 128; + private static final short ICMP_V6_TYPE_ECHO_REPLY = 129; + private static final short ICMP_V6_TYPE_ROUTER_SOLICITATION = 133; + private static final short ICMP_V6_TYPE_ROUTER_ADVERTISEMENT = 134; + private static final short ICMP_V6_TYPE_NEIGHBOR_SOLICITATION = 135; + private static final short ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT = 136; + private static final short ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY = 143; + + private void parseIcmpV6Packet(ByteBuffer data) { + mMostSpecificProtocolString = "ICMPv6"; + short icmpV6Type = getUnsignedByte(data); + switch (icmpV6Type) { + case ICMP_V6_TYPE_ECHO_REQUEST: + mTypeString = "Echo Request"; + return; + case ICMP_V6_TYPE_ECHO_REPLY: + mTypeString = "Echo Reply"; + return; + case ICMP_V6_TYPE_ROUTER_SOLICITATION: + mTypeString = "Router Solicitation"; + return; + case ICMP_V6_TYPE_ROUTER_ADVERTISEMENT: + mTypeString = "Router Advertisement"; + return; + case ICMP_V6_TYPE_NEIGHBOR_SOLICITATION: + mTypeString = "Neighbor Solicitation"; + return; + case ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT: + mTypeString = "Neighbor Advertisement"; + return; + case ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY: + mTypeString = "MLDv2 report"; + return; + default: + mTypeString = "Type " + icmpV6Type; + return; + } + } + + private static final byte EAPOL_TYPE_KEY = 3; + private static final byte EAPOL_KEY_DESCRIPTOR_RSN_KEY = 2; + private static final byte EAPOL_LENGTH_LEN = 2; + private static final short WPA_KEY_INFO_FLAG_PAIRWISE = (short) 1 << 3; // bit 4 + private static final short WPA_KEY_INFO_FLAG_INSTALL = (short) 1 << 6; // bit 7 + private static final short WPA_KEY_INFO_FLAG_MIC = (short) 1 << 8; // bit 9 + private static final byte WPA_KEYLEN_LEN = 2; + private static final byte WPA_REPLAY_COUNTER_LEN = 8; + private static final byte WPA_KEY_NONCE_LEN = 32; + private static final byte WPA_KEY_IV_LEN = 16; + private static final byte WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN = 8; + private static final byte WPA_KEY_IDENTIFIER_LEN = 8; + private static final byte WPA_KEY_MIC_LEN = 16; + + private void parseEapolPacket(ByteBuffer data) { + mMostSpecificProtocolString = "EAPOL"; + short eapolVersion = getUnsignedByte(data); + if (eapolVersion < 1 || eapolVersion > 2) { + Log.e(TAG, "Unrecognized EAPOL version " + eapolVersion); + return; + } + + short eapolType = getUnsignedByte(data); + if (eapolType != EAPOL_TYPE_KEY) { + Log.e(TAG, "Unrecognized EAPOL type " + eapolType); + return; + } + + data.position(data.position() + EAPOL_LENGTH_LEN); + short eapolKeyDescriptorType = getUnsignedByte(data); + if (eapolKeyDescriptorType != EAPOL_KEY_DESCRIPTOR_RSN_KEY) { + Log.e(TAG, "Unrecognized key descriptor " + eapolKeyDescriptorType); + return; + } + + short wpaKeyInfo = data.getShort(); + if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_PAIRWISE) == 0) { + mTypeString = "Group Key"; + } else { + mTypeString = "Pairwise Key"; + } + + // See goo.gl/tu8AQC for details. + if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_MIC) == 0) { + mTypeString += " message 1/4"; + return; + } + + if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_INSTALL) != 0) { + mTypeString += " message 3/4"; + return; + } + + data.position(data.position() + WPA_KEYLEN_LEN + WPA_REPLAY_COUNTER_LEN + + WPA_KEY_NONCE_LEN + WPA_KEY_IV_LEN + WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN + + WPA_KEY_IDENTIFIER_LEN + WPA_KEY_MIC_LEN); + int wpaKeyDataLen = getUnsignedShort(data); + if (wpaKeyDataLen > 0) { + mTypeString += " message 2/4"; + } else { + mTypeString += " message 4/4"; + } + } + + private static final byte IEEE_80211_FRAME_CTRL_TYPE_MGMT = 0x00; + private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ = 0x00; + private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP = 0x01; + private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ = 0x04; + private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP = 0x05; + private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH = 0x0b; + + private static byte parseIeee80211FrameCtrlVersion(byte b) { + return (byte) (b & 0b00000011); + } + private static byte parseIeee80211FrameCtrlType(byte b) { + return (byte) ((b & 0b00001100) >> 2); + } + private static byte parseIeee80211FrameCtrlSubtype(byte b) { + return (byte) ((b & 0b11110000) >> 4); + } + private void parseManagementFrame(ByteBuffer data) { + mMostSpecificProtocolString = "802.11 Mgmt"; + byte frameControlField = data.get(); + byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlField); + if (ieee80211Version != 0) { + Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version); + return; + } + + byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlField); + if (ieee80211FrameType != IEEE_80211_FRAME_CTRL_TYPE_MGMT) { + Log.e(TAG, "Unexpected frame type " + ieee80211FrameType); + return; + } + + byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlField); + switch (ieee80211FrameSubtype) { + case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ: + mTypeString = "Association Request"; + return; + case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP: + mTypeString = "Association Response"; + return; + case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ: + mTypeString = "Probe Request"; + return; + case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP: + mTypeString = "Probe Response"; + return; + case IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH: + mTypeString = "Authentication"; + return; + default: + mTypeString = "Unexpected subtype " + ieee80211FrameSubtype; + return; + } + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java index 6f68187a9..64bb880fe 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java @@ -80,6 +80,7 @@ public class WifiLoggerTest { when(mWifiNative.readKernelLog()).thenReturn(""); mWifiLogger = new WifiLogger(mWsm, mWifiNative); + mWifiNative.enableVerboseLogging(0); } /** @@ -138,14 +139,14 @@ public class WifiLoggerTest { } /** - * Verifies that, when verbose mode is not enabled, startLogging() does not + * Verifies that, when verbose mode is not enabled, startLogging() calls * startPktFateMonitoring(). */ @Test - public void startLoggingIgnoresPacketFateWithoutVerboseMode() { + public void startLoggingStartsPacketFateWithoutVerboseMode() { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); - verify(mWifiNative, never()).startPktFateMonitoring(); + verify(mWifiNative).startPktFateMonitoring(); } /** @@ -160,16 +161,16 @@ public class WifiLoggerTest { } /** - * Verifies that, when verbose mode is not enabled, reportConnectionFailure() does not - * fetch packet fates. + * Verifies that, when verbose mode is not enabled, reportConnectionFailure() still + * fetches packet fates. */ @Test public void reportConnectionFailureIsIgnoredWithoutVerboseMode() { final boolean verbosityToggle = false; mWifiLogger.startLogging(verbosityToggle); mWifiLogger.reportConnectionFailure(); - verify(mWifiNative, never()).getTxPktFates(anyObject()); - verify(mWifiNative, never()).getRxPktFates(anyObject()); + verify(mWifiNative).getTxPktFates(anyObject()); + verify(mWifiNative).getRxPktFates(anyObject()); } /** @@ -266,16 +267,16 @@ public class WifiLoggerTest { "--------------------------------------------------------------------")); } - /** - * Verifies that dump() shows both TX, and RX, fates. - */ - @Test - public void dumpShowsTxAndRxFates() { - final boolean verbosityToggle = true; - mWifiLogger.startLogging(verbosityToggle); + private String getDumpString(boolean verbose) { + mWifiLogger.startLogging(verbose); + mWifiNative.enableVerboseLogging(verbose ? 1 : 0); when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { public boolean answer(WifiNative.TxFateReport[] fates) { fates[0] = new WifiNative.TxFateReport( + WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, + new byte[0] + ); + fates[1] = new WifiNative.TxFateReport( WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, new byte[0] ); @@ -285,6 +286,10 @@ public class WifiLoggerTest { when(mWifiNative.getRxPktFates(anyObject())).then(new AnswerWithArguments() { public boolean answer(WifiNative.RxFateReport[] fates) { fates[0] = new WifiNative.RxFateReport( + WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, + new byte[0] + ); + fates[1] = new WifiNative.RxFateReport( WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, new byte[0] ); @@ -296,10 +301,41 @@ public class WifiLoggerTest { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); + return sw.toString(); + } - String fateDumpString = sw.toString(); - assertTrue(fateDumpString.contains("Frame direction: TX")); - assertTrue(fateDumpString.contains("Frame direction: RX")); + /** + * Verifies that dump() shows both TX, and RX fates in only table form, when verbose + * logging is not enabled. + */ + @Test + public void dumpShowsTxAndRxFates() { + final boolean verbosityToggle = false; + String dumpString = getDumpString(verbosityToggle); + assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); + assertTrue(dumpString.contains("0 TX")); + assertTrue(dumpString.contains("1 RX")); + assertTrue(dumpString.contains("2 TX")); + assertTrue(dumpString.contains("3 RX")); + assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP")); + assertFalse(dumpString.contains("Frame bytes")); + } + + /** + * Verifies that dump() shows both TX, and RX fates in table and verbose forms, when verbose + * logging is enabled. + */ + @Test + public void dumpShowsTxAndRxFatesVerbose() { + final boolean verbosityToggle = true; + String dumpString = getDumpString(verbosityToggle); + assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); + assertTrue(dumpString.contains("0 TX")); + assertTrue(dumpString.contains("1 RX")); + assertTrue(dumpString.contains("2 TX")); + assertTrue(dumpString.contains("3 RX")); + assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP")); + assertTrue(dumpString.contains("Frame bytes")); } /** @@ -309,53 +345,40 @@ public class WifiLoggerTest { @Test public void dumpIsSortedByTimestamp() { final boolean verbosityToggle = true; - mWifiLogger.startLogging(verbosityToggle); - when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() { - public boolean answer(WifiNative.TxFateReport[] fates) { - fates[0] = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - fates[1] = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - when(mWifiNative.getRxPktFates(anyObject())).then(new AnswerWithArguments() { - public boolean answer(WifiNative.RxFateReport[] fates) { - fates[0] = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - fates[1] = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - new byte[0] - ); - return true; - } - }); - mWifiLogger.reportConnectionFailure(); - - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); - - String fateDumpString = sw.toString(); - assertTrue(fateDumpString.contains( - "Frame number: 1\nFrame direction: TX\nFrame timestamp: 0\n")); - assertTrue(fateDumpString.contains( - "Frame number: 2\nFrame direction: RX\nFrame timestamp: 1\n")); - assertTrue(fateDumpString.contains( - "Frame number: 3\nFrame direction: TX\nFrame timestamp: 2\n")); - assertTrue(fateDumpString.contains( - "Frame number: 4\nFrame direction: RX\nFrame timestamp: 3\n")); + String dumpString = getDumpString(verbosityToggle); + assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader())); + int expected_index_of_frame_0 = dumpString.indexOf("0 TX"); + int expected_index_of_frame_1 = dumpString.indexOf("1 RX"); + int expected_index_of_frame_2 = dumpString.indexOf("2 TX"); + int expected_index_of_frame_3 = dumpString.indexOf("3 RX"); + assertFalse(-1 == expected_index_of_frame_0); + assertFalse(-1 == expected_index_of_frame_1); + assertFalse(-1 == expected_index_of_frame_2); + assertFalse(-1 == expected_index_of_frame_3); + assertTrue(expected_index_of_frame_0 < expected_index_of_frame_1); + assertTrue(expected_index_of_frame_1 < expected_index_of_frame_2); + assertTrue(expected_index_of_frame_2 < expected_index_of_frame_3); + + int expected_index_of_verbose_frame_0 = dumpString.indexOf( + "Frame direction: TX\nFrame timestamp: 0\n"); + int expected_index_of_verbose_frame_1 = dumpString.indexOf( + "Frame direction: RX\nFrame timestamp: 1\n"); + int expected_index_of_verbose_frame_2 = dumpString.indexOf( + "Frame direction: TX\nFrame timestamp: 2\n"); + int expected_index_of_verbose_frame_3 = dumpString.indexOf( + "Frame direction: RX\nFrame timestamp: 3\n"); + assertFalse(-1 == expected_index_of_verbose_frame_0); + assertFalse(-1 == expected_index_of_verbose_frame_1); + assertFalse(-1 == expected_index_of_verbose_frame_2); + assertFalse(-1 == expected_index_of_verbose_frame_3); + assertTrue(expected_index_of_verbose_frame_0 < expected_index_of_verbose_frame_1); + assertTrue(expected_index_of_verbose_frame_1 < expected_index_of_verbose_frame_2); + assertTrue(expected_index_of_verbose_frame_2 < expected_index_of_verbose_frame_3); } /** * Verifies that, if verbose is disabled after fetching fates, the dump does not include - * fates. + * verbose fate logs. */ @Test public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() { @@ -391,8 +414,8 @@ public class WifiLoggerTest { mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"}); String fateDumpString = sw.toString(); - assertFalse(fateDumpString.contains("Frame direction: TX")); - assertFalse(fateDumpString.contains("Frame direction: RX")); + assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP")); + assertFalse(fateDumpString.contains("Frame bytes")); } /** Verifies that the default size of our ring buffers is small. */ diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java index 29cb3e5b5..5fa20d05c 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java @@ -50,6 +50,68 @@ public class WifiNativeTest { private static final String NETWORK_EXTRAS_SERIALIZED = "\"%7B%22key2%22%3A%22value2%22%2C%22key1%22%3A%22value1%22%7D\""; + private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345; + private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7}; + private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport( + WifiLoggerHal.TX_PKT_FATE_SENT, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, + WifiLoggerHal.FRAME_TYPE_ETHERNET_II, + FATE_REPORT_FRAME_BYTES + ); + private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport( + WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, + WifiLoggerHal.FRAME_TYPE_ETHERNET_II, + FATE_REPORT_FRAME_BYTES + ); + private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] { + new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"), + new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"), + new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management", + "802.11 Mgmt"), + new FrameTypeMapping((byte) 42, "42", "N/A") + }; + private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] { + new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID, + "firmware dropped (invalid frame)"), + new FateMapping( + WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), + new FateMapping( + WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID, + "driver dropped (invalid frame)"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS, + "driver dropped (no bufs)"), + new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), + new FateMapping((byte) 42, "42") + }; + private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] { + new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"), + new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"), + new FateMapping( + WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"), + new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, + "firmware dropped (invalid frame)"), + new FateMapping( + WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), + new FateMapping( + WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), + new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"), + new FateMapping( + WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"), + new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID, + "driver dropped (invalid frame)"), + new FateMapping( + WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"), + new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), + new FateMapping((byte) 42, "42") + }; + private WifiNative mWifiNative; @Before @@ -89,18 +151,16 @@ public class WifiNativeTest { */ @Test public void testTxFateReportCtorSetsFields() { - long driverTimestampUSec = 12345; - byte[] frameBytes = new byte[] {'a', 'b', 0, 'c'}; WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport( WifiLoggerHal.TX_PKT_FATE_SENT, // non-zero value - driverTimestampUSec, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value - frameBytes + FATE_REPORT_FRAME_BYTES ); assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate); - assertEquals(driverTimestampUSec, fateReport.mDriverTimestampUSec); + assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec); assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType); - assertArrayEquals(frameBytes, fateReport.mFrameBytes); + assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes); } /** @@ -108,27 +168,27 @@ public class WifiNativeTest { */ @Test public void testRxFateReportCtorSetsFields() { - long driverTimestampUSec = 12345; - byte[] frameBytes = new byte[] {'a', 'b', 0, 'c'}; WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport( WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, // non-zero value - driverTimestampUSec, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value - frameBytes + FATE_REPORT_FRAME_BYTES ); assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate); - assertEquals(driverTimestampUSec, fateReport.mDriverTimestampUSec); + assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec); assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType); - assertArrayEquals(frameBytes, fateReport.mFrameBytes); + assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes); } // Support classes for test{Tx,Rx}FateReportToString. private static class FrameTypeMapping { byte mTypeNumber; - String mExpectedText; - FrameTypeMapping(byte typeNumber, String expectedText) { + String mExpectedTypeText; + String mExpectedProtocolText; + FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) { this.mTypeNumber = typeNumber; - this.mExpectedText = expectedText; + this.mExpectedTypeText = expectedTypeText; + this.mExpectedProtocolText = expectedProtocolText; } } private static class FateMapping { @@ -141,138 +201,174 @@ public class WifiNativeTest { } /** - * Verifies that TxFateReport.toString() includes the information we care about. + * Verifies that FateReport.getTableHeader() prints the right header. */ @Test - public void testTxFateReportToString() { - long driverTimestampUSec = 12345; - byte[] frameBytes = new byte[] { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7}; - WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport( - WifiLoggerHal.TX_PKT_FATE_SENT, - driverTimestampUSec, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - frameBytes - ); + public void testFateReportTableHeader() { + String header = WifiNative.FateReport.getTableHeader(); + assertTrue(header.contains( + "Timestamp Direction Fate Protocol Type\n")); + assertTrue(header.contains( + "--------- --------- ---- -------- ----\n")); + } + + /** + * Verifies that TxFateReport.toTableRowString() includes the information we care about. + */ + @Test + public void testTxFateReportToTableRowString() { + WifiNative.TxFateReport fateReport = TX_FATE_REPORT; + + String tableRowFateString = fateReport.toTableRowString(); + assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC)); + assertTrue(tableRowFateString.contains("TX")); + assertTrue(tableRowFateString.contains("sent")); + assertTrue(tableRowFateString.contains("Ethernet")); + assertTrue(tableRowFateString.contains("N/A")); + + for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) { + fateReport = new WifiNative.TxFateReport( + WifiLoggerHal.TX_PKT_FATE_SENT, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, + frameTypeMapping.mTypeNumber, + FATE_REPORT_FRAME_BYTES + ); + tableRowFateString = fateReport.toTableRowString(); + assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC)); + assertTrue(tableRowFateString.contains("TX")); + assertTrue(tableRowFateString.contains("sent")); + assertTrue(tableRowFateString.contains(frameTypeMapping.mExpectedProtocolText)); + assertTrue(tableRowFateString.contains("N/A")); + } + + for (FateMapping fateMapping : TX_FATE_MAPPINGS) { + fateReport = new WifiNative.TxFateReport( + fateMapping.mFateNumber, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, + WifiLoggerHal.FRAME_TYPE_80211_MGMT, + FATE_REPORT_FRAME_BYTES + ); + tableRowFateString = fateReport.toTableRowString(); + assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC)); + assertTrue(tableRowFateString.contains("TX")); + assertTrue(tableRowFateString.contains(fateMapping.mExpectedText)); + assertTrue(tableRowFateString.contains("802.11 Mgmt")); + assertTrue(tableRowFateString.contains("N/A")); + } + } + + /** + * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care + * about. + */ + @Test + public void testTxFateReportToVerboseStringWithPiiAllowed() { + WifiNative.TxFateReport fateReport = TX_FATE_REPORT; - String fateString = fateReport.toString(); - assertTrue(fateString.contains("Frame direction: TX")); - assertTrue(fateString.contains("Frame timestamp: 12345")); - assertTrue(fateString.contains("Frame fate: sent")); - assertTrue(fateString.contains("Frame type: data")); - assertTrue(fateString.contains("Frame length: 16")); - assertTrue(fateString.contains( + String verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); + assertTrue(verboseFateString.contains("Frame direction: TX")); + assertTrue(verboseFateString.contains("Frame timestamp: 12345")); + assertTrue(verboseFateString.contains("Frame fate: sent")); + assertTrue(verboseFateString.contains("Frame type: data")); + assertTrue(verboseFateString.contains("Frame protocol: Ethernet")); + assertTrue(verboseFateString.contains("Frame protocol type: N/A")); + assertTrue(verboseFateString.contains("Frame length: 16")); + assertTrue(verboseFateString.contains( "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump // TODO(quiche): uncomment this, once b/27975149 is fixed. - // assertTrue(fateString.contains("abcdefgh........")); // hex dump - - FrameTypeMapping[] frameTypeMappings = new FrameTypeMapping[] { - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown"), - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data"), - new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management"), - new FrameTypeMapping((byte) 42, "42") - }; - for (FrameTypeMapping frameTypeMapping : frameTypeMappings) { + // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump + + for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) { fateReport = new WifiNative.TxFateReport( WifiLoggerHal.TX_PKT_FATE_SENT, - driverTimestampUSec, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, frameTypeMapping.mTypeNumber, - frameBytes + FATE_REPORT_FRAME_BYTES ); - assertTrue(fateReport.toString().contains( - "Frame type: " + frameTypeMapping.mExpectedText)); + verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); + assertTrue(verboseFateString.contains("Frame type: " + + frameTypeMapping.mExpectedTypeText)); } - FateMapping[] fateMappings = new FateMapping[] { - new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID, - "firmware dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), - new FateMapping( - WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID, - "driver dropped (invalid frame)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS, - "driver dropped (no bufs)"), - new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), - new FateMapping((byte) 42, "42") - }; - for (FateMapping fateMapping : fateMappings) { + for (FateMapping fateMapping : TX_FATE_MAPPINGS) { fateReport = new WifiNative.TxFateReport( fateMapping.mFateNumber, - driverTimestampUSec, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, WifiLoggerHal.FRAME_TYPE_80211_MGMT, - frameBytes + FATE_REPORT_FRAME_BYTES ); - assertTrue(fateReport.toString().contains("Frame fate: " + fateMapping.mExpectedText)); + verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); + assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText)); } } /** - * Verifies that RxFateReport.toString() includes the information we care about. + * Verifies that RxFateReport.toTableRowString() includes the information we care about. */ @Test - public void testRxFateReportToString() { - long driverTimestampUSec = 67890; - byte[] frameBytes = new byte[] { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7}; - WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, - driverTimestampUSec, - WifiLoggerHal.FRAME_TYPE_ETHERNET_II, - frameBytes - ); + public void testRxFateReportToTableRowString() { + WifiNative.RxFateReport fateReport = RX_FATE_REPORT; + + String tableRowFateString = fateReport.toTableRowString(); + assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC)); + assertTrue(tableRowFateString.contains("RX")); + assertTrue(tableRowFateString.contains("firmware dropped (invalid frame)")); + assertTrue(tableRowFateString.contains("Ethernet")); + assertTrue(tableRowFateString.contains("N/A")); - String fateString = fateReport.toString(); - assertTrue(fateString.contains("Frame direction: RX")); - assertTrue(fateString.contains("Frame timestamp: 67890")); - assertTrue(fateString.contains("Frame fate: firmware dropped (invalid frame)")); - assertTrue(fateString.contains("Frame type: data")); - assertTrue(fateString.contains("Frame length: 16")); - assertTrue(fateString.contains( + // FrameTypeMappings omitted, as they're the same as for TX. + + for (FateMapping fateMapping : RX_FATE_MAPPINGS) { + fateReport = new WifiNative.RxFateReport( + fateMapping.mFateNumber, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, + WifiLoggerHal.FRAME_TYPE_80211_MGMT, + FATE_REPORT_FRAME_BYTES + ); + tableRowFateString = fateReport.toTableRowString(); + assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC)); + assertTrue(tableRowFateString.contains("RX")); + assertTrue(tableRowFateString.contains(fateMapping.mExpectedText)); + assertTrue(tableRowFateString.contains("802.11 Mgmt")); + assertTrue(tableRowFateString.contains("N/A")); + } + } + + /** + * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care + * about. + */ + @Test + public void testRxFateReportToVerboseStringWithPiiAllowed() { + WifiNative.RxFateReport fateReport = RX_FATE_REPORT; + + String verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); + assertTrue(verboseFateString.contains("Frame direction: RX")); + assertTrue(verboseFateString.contains("Frame timestamp: 12345")); + assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)")); + assertTrue(verboseFateString.contains("Frame type: data")); + assertTrue(verboseFateString.contains("Frame protocol: Ethernet")); + assertTrue(verboseFateString.contains("Frame protocol type: N/A")); + assertTrue(verboseFateString.contains("Frame length: 16")); + assertTrue(verboseFateString.contains( "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump // TODO(quiche): uncomment this, once b/27975149 is fixed. - // assertTrue(fateString.contains("abcdefgh........")); // hex dump + // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump // FrameTypeMappings omitted, as they're the same as for TX. - FateMapping[] fateMappings = new FateMapping[] { - new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, - "firmware dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID, - "driver dropped (invalid frame)"), - new FateMapping( - WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"), - new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"), - new FateMapping((byte) 42, "42") - }; - for (FateMapping fateMapping : fateMappings) { + for (FateMapping fateMapping : RX_FATE_MAPPINGS) { fateReport = new WifiNative.RxFateReport( fateMapping.mFateNumber, - driverTimestampUSec, + FATE_REPORT_DRIVER_TIMESTAMP_USEC, WifiLoggerHal.FRAME_TYPE_80211_MGMT, - frameBytes + FATE_REPORT_FRAME_BYTES ); - assertTrue(fateReport.toString().contains("Frame fate: " + fateMapping.mExpectedText)); + verboseFateString = fateReport.toVerboseStringWithPiiAllowed(); + assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText)); } } - /** * Verifies that startPktFateMonitoring returns false when HAL is not started. */ diff --git a/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java b/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java new file mode 100644 index 000000000..e8e921be4 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi.util; + +import static org.junit.Assert.assertEquals; + +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.server.wifi.WifiLoggerHal; + +import org.junit.Test; + +/** + * Unit tests for {@link com.android.server.wifi.util.FrameParser}. + */ +@SmallTest +public class FrameParserTest { + + private static final byte[] TEST_EAPOL_1_OF_4_FRAME_BYTES = new byte[] { + (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC, + (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB, + (byte) 0x88, (byte) 0x8E, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x5F, + (byte) 0x02, (byte) 0x00, (byte) 0x8A, (byte) 0x00, (byte) 0x10, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0xF2, (byte) 0x0D, (byte) 0xFA, (byte) 0x35, (byte) 0x89, + (byte) 0x9C, (byte) 0xA8, (byte) 0x8C, (byte) 0x14, (byte) 0xD9, (byte) 0x3F, + (byte) 0xC9, (byte) 0x62, (byte) 0x11, (byte) 0x39, (byte) 0xC3, (byte) 0x34, + (byte) 0xE1, (byte) 0x00, (byte) 0x09, (byte) 0xE3, (byte) 0x9C, (byte) 0x0C, + (byte) 0x32, (byte) 0xFE, (byte) 0x7F, (byte) 0x79, (byte) 0x29, (byte) 0x3E, + (byte) 0x6C, (byte) 0xF2, (byte) 0x57, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; + private static final byte TEST_EAPOL_1_OF_4_FRAME_TYPE = + WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + private static final String TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING = "EAPOL"; + private static final String TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 1/4"; + + private static final byte[] TEST_EAPOL_2_OF_4_FRAME_BYTES = new byte[] { + (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB, + (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC, + (byte) 0x88, (byte) 0x8E, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x75, + (byte) 0x02, (byte) 0x01, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0x42, (byte) 0xAE, (byte) 0x33, (byte) 0x61, (byte) 0xF8, + (byte) 0x38, (byte) 0x28, (byte) 0x81, (byte) 0x70, (byte) 0xD8, (byte) 0xA5, + (byte) 0xDD, (byte) 0x90, (byte) 0xB1, (byte) 0x8E, (byte) 0xEB, (byte) 0x58, + (byte) 0xF1, (byte) 0x0A, (byte) 0xE4, (byte) 0xA1, (byte) 0x93, (byte) 0x34, + (byte) 0xE1, (byte) 0x4F, (byte) 0x90, (byte) 0x85, (byte) 0xA0, (byte) 0x21, + (byte) 0x95, (byte) 0xC8, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x53, + (byte) 0x12, (byte) 0xE4, (byte) 0x97, (byte) 0xBC, (byte) 0xFF, (byte) 0x15, + (byte) 0x45, (byte) 0xCF, (byte) 0x4C, (byte) 0xC0, (byte) 0xB8, (byte) 0xBA, + (byte) 0x30, (byte) 0x5F, (byte) 0x6C, (byte) 0x00, (byte) 0x16, (byte) 0x30, + (byte) 0x14, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, + (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, + (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, + (byte) 0x02, (byte) 0x80, (byte) 0x00}; + private static final byte TEST_EAPOL_2_OF_4_FRAME_TYPE = + WifiLoggerHal.FRAME_TYPE_ETHERNET_II; + private static final String TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING = "EAPOL"; + private static final String TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 2/4"; + + private static final byte[] TEST_PROBE_RESPONSE_FRAME_BYTES = new byte[] { + (byte) 0x50, (byte) 0x08, (byte) 0x3a, (byte) 0x01, (byte) 0x54, (byte) 0x27, + (byte) 0x1e, (byte) 0xf2, (byte) 0xcd, (byte) 0x0f, (byte) 0x10, (byte) 0x6f, + (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x10, (byte) 0x6f, + (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x60, (byte) 0xc4, + (byte) 0x4a, (byte) 0xaa, (byte) 0x2a, (byte) 0x0d, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x11, (byte) 0x04, + (byte) 0x00, (byte) 0x16, (byte) 0x77, (byte) 0x7a, (byte) 0x72, (byte) 0x5f, + (byte) 0x68, (byte) 0x70, (byte) 0x5f, (byte) 0x67, (byte) 0x34, (byte) 0x35, + (byte) 0x30, (byte) 0x68, (byte) 0x5f, (byte) 0x67, (byte) 0x5f, (byte) 0x63, + (byte) 0x68, (byte) 0x35, (byte) 0x5f, (byte) 0x77, (byte) 0x70, (byte) 0x61, + (byte) 0x01, (byte) 0x08, (byte) 0x82, (byte) 0x84, (byte) 0x8b, (byte) 0x96, + (byte) 0x0c, (byte) 0x12, (byte) 0x18, (byte) 0x24, (byte) 0x03, (byte) 0x01, + (byte) 0x05, (byte) 0x2a, (byte) 0x01, (byte) 0x04, (byte) 0x32, (byte) 0x04, + (byte) 0x30, (byte) 0x48, (byte) 0x60, (byte) 0x6c, (byte) 0x30, (byte) 0x18, + (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, + (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x04, + (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x01, (byte) 0x00, + (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x0c, (byte) 0x00, + (byte) 0xdd, (byte) 0x18, (byte) 0x00, (byte) 0x50, (byte) 0xf2, (byte) 0x02, + (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0xa4, + (byte) 0x00, (byte) 0x00, (byte) 0x27, (byte) 0xa4, (byte) 0x00, (byte) 0x00, + (byte) 0x42, (byte) 0x43, (byte) 0x5e, (byte) 0x00, (byte) 0x62, (byte) 0x32, + (byte) 0x2f, (byte) 0x00, (byte) 0xdd, (byte) 0x70, (byte) 0x00, (byte) 0x50, + (byte) 0xf2, (byte) 0x04, (byte) 0x10, (byte) 0x4a, (byte) 0x00, (byte) 0x01, + (byte) 0x10, (byte) 0x10, (byte) 0x44, (byte) 0x00, (byte) 0x01, (byte) 0x02, + (byte) 0x10, (byte) 0x3b, (byte) 0x00, (byte) 0x01, (byte) 0x03, (byte) 0x10, + (byte) 0x47, (byte) 0x00, (byte) 0x10, (byte) 0xf3, (byte) 0x1b, (byte) 0x31, + (byte) 0x7f, (byte) 0x8c, (byte) 0x25, (byte) 0x56, (byte) 0x46, (byte) 0xb5, + (byte) 0xc9, (byte) 0x5f, (byte) 0x2f, (byte) 0x0b, (byte) 0xcf, (byte) 0x6a, + (byte) 0x14, (byte) 0x10, (byte) 0x21, (byte) 0x00, (byte) 0x06, (byte) 0x44, + (byte) 0x44, (byte) 0x2d, (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10, + (byte) 0x23, (byte) 0x00, (byte) 0x0c, (byte) 0x57, (byte) 0x5a, (byte) 0x52, + (byte) 0x2d, (byte) 0x48, (byte) 0x50, (byte) 0x2d, (byte) 0x47, (byte) 0x34, + (byte) 0x35, (byte) 0x30, (byte) 0x48, (byte) 0x10, (byte) 0x24, (byte) 0x00, + (byte) 0x01, (byte) 0x30, (byte) 0x10, (byte) 0x42, (byte) 0x00, (byte) 0x05, + (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x10, + (byte) 0x54, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x06, (byte) 0x00, + (byte) 0x50, (byte) 0xf2, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x10, + (byte) 0x11, (byte) 0x00, (byte) 0x06, (byte) 0x44, (byte) 0x44, (byte) 0x2d, + (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10, (byte) 0x08, (byte) 0x00, + (byte) 0x02, (byte) 0x01, (byte) 0x04, (byte) 0x10, (byte) 0x3c, (byte) 0x00, + (byte) 0x01, (byte) 0x01, (byte) 0x8a, (byte) 0x0e, (byte) 0x06, (byte) 0xcf}; + private static final byte TEST_PROBE_RESPONSE_FRAME_TYPE = WifiLoggerHal.FRAME_TYPE_80211_MGMT; + private static final String TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING = "802.11 Mgmt"; + private static final String TEST_PROBE_RESPONSE_FRAME_TYPE_STRING = "Probe Response"; + + /** + * Test that a probe response frame is parsed correctly. + */ + @Test + public void parseProbeResponseFrame() { + FrameParser parser = new FrameParser( + TEST_PROBE_RESPONSE_FRAME_TYPE, TEST_PROBE_RESPONSE_FRAME_BYTES); + assertEquals(TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING, parser.mMostSpecificProtocolString); + assertEquals(TEST_PROBE_RESPONSE_FRAME_TYPE_STRING, parser.mTypeString); + } + + /** + * Test that pairwise EAPOL 1/4 and 2/4 frames are parsed correctly. + */ + @Test + public void parseEapolFrames() { + FrameParser parser1 = new FrameParser( + TEST_EAPOL_1_OF_4_FRAME_TYPE, TEST_EAPOL_1_OF_4_FRAME_BYTES); + assertEquals(TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING, parser1.mMostSpecificProtocolString); + assertEquals(TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING, parser1.mTypeString); + + FrameParser parser2 = new FrameParser( + TEST_EAPOL_2_OF_4_FRAME_TYPE, TEST_EAPOL_2_OF_4_FRAME_BYTES); + assertEquals(TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING, parser2.mMostSpecificProtocolString); + assertEquals(TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING, parser2.mTypeString); + } +} |