aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Perot2014-08-04 16:53:05 (EDT)
committerMatthew Khouzam2014-08-07 15:25:11 (EDT)
commit7b88510c20eb2a6bffdbf4d4abf32a20a40c2de8 (patch)
tree900831a9a7abd5eb072b381893bfb694ead815da
parent5daf19f6a9c2ff082d085e435fc633e8e35b10fa (diff)
downloadorg.eclipse.linuxtools-7b88510c20eb2a6bffdbf4d4abf32a20a40c2de8.zip
org.eclipse.linuxtools-7b88510c20eb2a6bffdbf4d4abf32a20a40c2de8.tar.gz
org.eclipse.linuxtools-7b88510c20eb2a6bffdbf4d4abf32a20a40c2de8.tar.bz2
pcap: make PacketStream compute useful informationrefs/changes/98/30998/8
The PacketStream now computes Nb of packets/bytes, duration of the conversation, Bytes per seconds, etc. Also, it now does not store indexes to packet, since it makes the size of PacketStream proportional to the size of the trace. This is unwanted since we have to be able to open traces that are bigger than memory. Change-Id: I8f6bde99ceabc20c4a66786a2dbd25d49251cc9e Signed-off-by: Vincent Perot <vincent.perot@ericsson.com> Reviewed-on: https://git.eclipse.org/r/30998 Tested-by: Hudson CI Reviewed-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im> Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
-rw-r--r--lttng/org.eclipse.linuxtools.pcap.core.tests/src/org/eclipse/linuxtools/pcap/core/tests/stream/StreamBuildTest.java82
-rw-r--r--lttng/org.eclipse.linuxtools.pcap.core/META-INF/MANIFEST.MF3
-rw-r--r--lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/packet/PacketUniqueID.java93
-rw-r--r--lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/stream/PacketStream.java192
4 files changed, 193 insertions, 177 deletions
diff --git a/lttng/org.eclipse.linuxtools.pcap.core.tests/src/org/eclipse/linuxtools/pcap/core/tests/stream/StreamBuildTest.java b/lttng/org.eclipse.linuxtools.pcap.core.tests/src/org/eclipse/linuxtools/pcap/core/tests/stream/StreamBuildTest.java
index 90c8e6b..41dd1fd 100644
--- a/lttng/org.eclipse.linuxtools.pcap.core.tests/src/org/eclipse/linuxtools/pcap/core/tests/stream/StreamBuildTest.java
+++ b/lttng/org.eclipse.linuxtools.pcap.core.tests/src/org/eclipse/linuxtools/pcap/core/tests/stream/StreamBuildTest.java
@@ -13,13 +13,10 @@
package org.eclipse.linuxtools.pcap.core.tests.stream;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import java.io.IOException;
-import java.util.Set;
-import java.util.TreeSet;
import org.eclipse.linuxtools.pcap.core.protocol.Protocol;
import org.eclipse.linuxtools.pcap.core.stream.PacketStream;
@@ -28,8 +25,6 @@ import org.eclipse.linuxtools.pcap.core.tests.shared.PcapTestTrace;
import org.eclipse.linuxtools.pcap.core.trace.BadPcapFileException;
import org.junit.Test;
-import com.google.common.collect.ImmutableSet;
-
/**
* JUnit Class that tests whether packet streams are built correctly.
*
@@ -37,27 +32,7 @@ import com.google.common.collect.ImmutableSet;
*/
public class StreamBuildTest {
- // Values taken from wireshark
- private static final Set<Long> TCP_INDEX_SET_STREAM_7_PACKETS = ImmutableSet.of(
- // This stream contains 7 packets.
- 17L,
- 23L,
- 25L,
- 26L,
- 27L,
- 35L,
- 36L
- );
-
- private static final Set<Long> TCP_INDEX_SET_STREAM_34_PACKETS = new TreeSet<>();
- static {
- // This stream contains many packet (34). Some packets doesn't
- // belong to it like the 17 or the 23.
- for (Long i = new Long(0); i < 43; i++) {
- TCP_INDEX_SET_STREAM_34_PACKETS.add(i);
- }
- TCP_INDEX_SET_STREAM_34_PACKETS.removeAll(TCP_INDEX_SET_STREAM_7_PACKETS);
- }
+ private static final double DELTA = 0.001;
/**
* Test that verify that stream building is done correctly.
@@ -75,13 +50,18 @@ public class StreamBuildTest {
assertEquals(Protocol.ETHERNET_II, builder.getProtocol());
// Should do one loop only, so hardcoded values are okay.
for (PacketStream stream : builder.getStreams()) {
- assertTrue(stream.toString().contains("Stream eth.0, Number of Packets: 43"));
- for (int i = 0; i < stream.size(); i++) {
- Long id = stream.get(i).getIndex();
- String path = stream.get(i).getPath();
- assertTrue(id >= 0 && id < 43);
- assertEquals(file, path);
- }
+ assertEquals("Stream eth.0, Number of Packets: 43\n", stream.toString());
+ assertEquals(43, stream.getNbPackets());
+ assertEquals(25091, stream.getNbBytes());
+ assertEquals(20, stream.getNbPacketsAtoB());
+ assertEquals(2323, stream.getNbBytesAtoB());
+ assertEquals(23, stream.getNbPacketsBtoA());
+ assertEquals(22768, stream.getNbBytesBtoA());
+ assertEquals(1084443427311224000L, stream.getStartTime());
+ assertEquals(1084443457704928000L, stream.getStopTime());
+ assertEquals(30.393704, stream.getDuration(), DELTA);
+ assertEquals(76.43030280218561, stream.getBPSAtoB(), DELTA);
+ assertEquals(749.1025114938278, stream.getBPSBtoA(), DELTA);
}
// Test TCP streams and other constructor
@@ -97,13 +77,17 @@ public class StreamBuildTest {
assertEquals(Protocol.TCP, stream.getProtocol());
assertEquals(0, stream.getID());
assertEquals("tcp.0", stream.getUniqueID());
- assertEquals(34, stream.size());
- for (int i = 0; i < stream.size(); i++) {
- Long id = stream.get(i).getIndex();
- String path = stream.get(i).getPath();
- assertTrue(TCP_INDEX_SET_STREAM_34_PACKETS.contains(id));
- assertEquals(file, path);
- }
+ assertEquals(34, stream.getNbPackets());
+ assertEquals(20695, stream.getNbBytes());
+ assertEquals(16, stream.getNbPacketsAtoB());
+ assertEquals(1351, stream.getNbBytesAtoB());
+ assertEquals(18, stream.getNbPacketsBtoA());
+ assertEquals(19344, stream.getNbBytesBtoA());
+ assertEquals(1084443427311224000L, stream.getStartTime());
+ assertEquals(1084443457704928000L, stream.getStopTime());
+ assertEquals(30.393704, stream.getDuration(), DELTA);
+ assertEquals(44.449995301658525, stream.getBPSAtoB(), DELTA);
+ assertEquals(636.4476011216008, stream.getBPSBtoA(), DELTA);
stream = builder.getStream(1);
if (stream == null) {
@@ -113,13 +97,17 @@ public class StreamBuildTest {
assertEquals(Protocol.TCP, stream.getProtocol());
assertEquals(1, stream.getID());
assertEquals("tcp.1", stream.getUniqueID());
- assertEquals(7, stream.size());
- for (int i = 0; i < stream.size(); i++) {
- Long id = stream.get(i).getIndex();
- String path = stream.get(i).getPath();
- assertTrue(TCP_INDEX_SET_STREAM_7_PACKETS.contains(id));
- assertEquals(file, path);
- }
+ assertEquals(7, stream.getNbPackets());
+ assertEquals(4119, stream.getNbBytes());
+ assertEquals(3, stream.getNbPacketsAtoB());
+ assertEquals(883, stream.getNbBytesAtoB());
+ assertEquals(4, stream.getNbPacketsBtoA());
+ assertEquals(3236, stream.getNbBytesBtoA());
+ assertEquals(1084443430295515000L, stream.getStartTime());
+ assertEquals(1084443432088092000L, stream.getStopTime());
+ assertEquals(1.792577, stream.getDuration(), DELTA);
+ assertEquals(492.58692932019096, stream.getBPSAtoB(), DELTA);
+ assertEquals(1805.2223140205413, stream.getBPSBtoA(), DELTA);
builder.clear();
assertEquals(0, builder.getNbStreams());
diff --git a/lttng/org.eclipse.linuxtools.pcap.core/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.pcap.core/META-INF/MANIFEST.MF
index c28b84b..dce6f70 100644
--- a/lttng/org.eclipse.linuxtools.pcap.core/META-INF/MANIFEST.MF
+++ b/lttng/org.eclipse.linuxtools.pcap.core/META-INF/MANIFEST.MF
@@ -24,4 +24,5 @@ Export-Package: org.eclipse.linuxtools.internal.pcap.core;x-friends:="org.eclips
org.eclipse.linuxtools.pcap.core.stream,
org.eclipse.linuxtools.pcap.core.trace,
org.eclipse.linuxtools.pcap.core.util
-Import-Package: com.google.common.collect
+Import-Package: com.google.common.collect,
+ com.google.common.math
diff --git a/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/packet/PacketUniqueID.java b/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/packet/PacketUniqueID.java
deleted file mode 100644
index 5ce9f45..0000000
--- a/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/packet/PacketUniqueID.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2014 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Vincent Perot - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.linuxtools.pcap.core.packet;
-
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.linuxtools.pcap.core.packet.Packet;
-import org.eclipse.linuxtools.pcap.core.protocol.Protocol;
-import org.eclipse.linuxtools.pcap.core.protocol.pcap.PcapPacket;
-
-/**
- * Class that represents a Packet ID. Using the information contained in this
- * class, it is possible to retrieve a packet. This allows to tremendously
- * reduce memory usage of packet streams while keeping good performance.
- *
- * @author Vincent Perot
- */
-public class PacketUniqueID {
-
- private final String fPath;
- private final long fIndex;
-
- /**
- * Constructor. It builds the packet ID from a packet.
- *
- * @param packet
- * The packet to build the ID from.
- */
- public PacketUniqueID(Packet packet) {
- fPath = packet.getPcapFile().getPath();
- PcapPacket pcapPacket = (PcapPacket) packet.getPacket(Protocol.PCAP);
- fIndex = (pcapPacket == null ? -1 : pcapPacket.getIndex());
- }
-
- /**
- * Getter method that returns the file path of the packet.
- *
- * @return The file path.
- */
- public String getPath() {
- return fPath;
- }
-
- /**
- * Getter method that returns the index within the file of the packet.
- *
- * @return The packet index.
- */
- public long getIndex() {
- return fIndex;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (int) (fIndex ^ (fIndex >>> 32));
- result = prime * result + fPath.hashCode();
- return result;
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
-
- PacketUniqueID other = (PacketUniqueID) obj;
- if (fIndex != other.fIndex) {
- return false;
- }
- if (fPath != other.fPath) {
- return false;
- }
- return true;
- }
-
-}
diff --git a/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/stream/PacketStream.java b/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/stream/PacketStream.java
index fb7c251..c6492ea 100644
--- a/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/stream/PacketStream.java
+++ b/lttng/org.eclipse.linuxtools.pcap.core/src/org/eclipse/linuxtools/pcap/core/stream/PacketStream.java
@@ -12,14 +12,14 @@
package org.eclipse.linuxtools.pcap.core.stream;
-import java.util.ArrayList;
-import java.util.List;
-
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.linuxtools.pcap.core.endpoint.ProtocolEndpointPair;
-import org.eclipse.linuxtools.pcap.core.packet.PacketUniqueID;
+import org.eclipse.linuxtools.pcap.core.packet.Packet;
import org.eclipse.linuxtools.pcap.core.protocol.Protocol;
import org.eclipse.linuxtools.pcap.core.protocol.pcap.PcapPacket;
+import com.google.common.math.DoubleMath;
+
// TODO decide if default modifier a good idea. This allows only the
// stream builder to call that method (and any class that is added to this
// package). This effectively makes the stream read-only.
@@ -34,12 +34,19 @@ import org.eclipse.linuxtools.pcap.core.protocol.pcap.PcapPacket;
*/
public class PacketStream {
- private static final String EMPTY_STRING = ""; //$NON-NLS-1$
- private final List<PacketUniqueID> fListIndex;
+ private static final double SECOND_TO_NANOSECOND = 1000000000.0;
+ private static final double DELTA = 0.000000001;
private final Protocol fProtocol;
private final int fId;
private final ProtocolEndpointPair fEndpointPair;
+ private long fNbPacketsAtoB;
+ private long fNbPacketsBtoA;
+ private long fNbBytesAtoB;
+ private long fNbBytesBtoA;
+ private long fStartTime;
+ private long fEndTime;
+
/**
* Constructor of a packet stream.
*
@@ -53,34 +60,57 @@ public class PacketStream {
*/
PacketStream(Protocol protocol, int id, ProtocolEndpointPair endpointPair) {
fProtocol = protocol;
- fListIndex = new ArrayList<>();
fId = id;
fEndpointPair = endpointPair;
+ fNbPacketsAtoB = 0;
+ fNbPacketsBtoA = 0;
+ fNbBytesAtoB = 0;
+ fNbBytesBtoA = 0;
+ fStartTime = Long.MAX_VALUE;
+ fEndTime = Long.MIN_VALUE;
}
/**
- * Add a packet unique ID to the stream.
+ * Add a packet to the stream.
*
* @param packet
- * The packet unique ID that must be added.
+ * The packet that must be added.
*/
synchronized void add(PcapPacket packet) {
- fListIndex.add(new PacketUniqueID(packet));
- }
- /**
- * Get a packet unique ID in file from the stream.
- *
- * @param index
- * The index in the stream of the packet to be retrieved.
- * @return The retrieved packet unique ID.
- */
- public synchronized PacketUniqueID get(int index) {
- PacketUniqueID id = fListIndex.get(index);
- if (id == null) {
- throw new IllegalStateException("PacketUniqueID is null!"); //$NON-NLS-1$
+ Packet newPacket = packet.getPacket(fProtocol);
+ if (newPacket == null) {
+ return;
+ }
+
+ // Update packet and byte number
+ if (fEndpointPair.getFirstEndpoint().equals(newPacket.getSourceEndpoint()) &&
+ fEndpointPair.getSecondEndpoint().equals(newPacket.getDestinationEndpoint())) {
+ fNbPacketsAtoB++;
+ fNbBytesAtoB += packet.getOriginalLength();
+ } else if (fEndpointPair.getFirstEndpoint().equals(newPacket.getDestinationEndpoint()) &&
+ fEndpointPair.getSecondEndpoint().equals(newPacket.getSourceEndpoint())) {
+ fNbPacketsBtoA++;
+ fNbBytesBtoA += packet.getOriginalLength();
+ } else {
+ throw new IllegalStateException();
}
- return id;
+
+ // Update start and stop time
+ // Stream timestamp is ALWAYS in nanoseconds.
+ long timestamp;
+ switch (packet.getTimestampScale()) {
+ case MICROSECOND:
+ timestamp = packet.getTimestamp() * 1000;
+ break;
+ case NANOSECOND:
+ timestamp = packet.getTimestamp();
+ break;
+ default:
+ throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$
+ }
+ fStartTime = Math.min(fStartTime, timestamp);
+ fEndTime = Math.max(fEndTime, timestamp);
}
/**
@@ -123,27 +153,117 @@ public class PacketStream {
@Override
public synchronized String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("Stream " + getUniqueID() + ", Number of Packets: " + fListIndex.size() + "\n"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
-
- for (int i = 0; i < fListIndex.size(); i++) {
- sb.append(fListIndex.get(i) + ", "); //$NON-NLS-1$
- }
+ sb.append("Stream " + getUniqueID() + ", Number of Packets: " + getNbPackets() + "\n"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
- String string = sb.toString();
- if (string == null) {
- return EMPTY_STRING;
- }
+ @SuppressWarnings("null")
+ @NonNull String string = sb.toString();
return string;
}
/**
- * Method that returns the number of packets in the stream.
+ * Get the number of packets going from the first endpoint to the second.
+ *
+ * @return The number of packets from A to B.
+ */
+ public synchronized long getNbPacketsAtoB() {
+ return fNbPacketsAtoB;
+ }
+
+ /**
+ * Get the number of packets going from the second endpoint to the first.
+ *
+ * @return The number of packets from B to A.
+ */
+ public synchronized long getNbPacketsBtoA() {
+ return fNbPacketsBtoA;
+ }
+
+ /**
+ * Get the total number of packets in this stream.
+ *
+ * @return The total number of packets.
+ */
+ public synchronized long getNbPackets() {
+ return fNbPacketsAtoB + fNbPacketsBtoA;
+ }
+
+ /**
+ * Get the number of bytes going from the first endpoint to the second.
+ *
+ * @return The number of bytes from A to B.
+ */
+ public synchronized long getNbBytesAtoB() {
+ return fNbBytesAtoB;
+ }
+
+ /**
+ * Get the number of bytes going from the second endpoint to the first.
+ *
+ * @return The number of bytes from B to A.
+ */
+ public synchronized long getNbBytesBtoA() {
+ return fNbBytesBtoA;
+ }
+
+ /**
+ * Get the total number of bytes in this stream.
*
- * @return The number of packets in the stream.
+ * @return The total number of bytes.
*/
- public synchronized int size() {
- return fListIndex.size();
+ public synchronized long getNbBytes() {
+ return fNbBytesAtoB + fNbBytesBtoA;
+ }
+
+ /**
+ * Get the start time of this stream, in nanoseconds relative to epoch.
+ *
+ * @return The start time.
+ */
+ public synchronized long getStartTime() {
+ return fStartTime;
+ }
+
+ /**
+ * Get the stop time of this stream, in nanoseconds relative to epoch.
+ *
+ * @return The stop time.
+ */
+ public synchronized long getStopTime() {
+ return fEndTime;
+ }
+
+ /**
+ * Get the duration of this stream, in seconds
+ *
+ * @return The duration of this stream.
+ */
+ public synchronized double getDuration() {
+ return (fEndTime - fStartTime) / SECOND_TO_NANOSECOND;
+ }
+
+ /**
+ * Get the the average byte per second from A to B.
+ *
+ * @return the average byte per second from A to B.
+ */
+ public synchronized double getBPSAtoB() {
+ if (DoubleMath.fuzzyEquals(getDuration(), 0, DELTA)) {
+ return 0;
+ }
+ return fNbBytesAtoB / getDuration();
+ }
+
+ /**
+ * Get the the average byte per second from B to A.
+ *
+ * @return the average byte per second from B to A.
+ */
+ public synchronized double getBPSBtoA() {
+ if (DoubleMath.fuzzyEquals(getDuration(), 0, DELTA)) {
+ return 0;
+ }
+ return fNbBytesBtoA / getDuration();
}
}