X-Git-Url: http://plrg.eecs.uci.edu/git/?p=pingpong.git;a=blobdiff_plain;f=Code%2FProjects%2FPacketLevelSignatureExtractor%2Fsrc%2Fmain%2Fjava%2Fedu%2Fuci%2Fiotproject%2Fdetection%2Flayer2%2FLayer2ClusterMatcher.java;h=7b576be3d79debd87329944a8a6b2884e5e8c400;hp=ab5f148f46d2809c6bba80ae1e89ae200f2b6585;hb=987ea910fed24a1f3f51ded41b6aa98c4e2618ae;hpb=2faef4940976a927c5983a51a7824a3e01d5354a diff --git a/Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java b/Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java index ab5f148..7b576be 100644 --- a/Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java +++ b/Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer2/Layer2ClusterMatcher.java @@ -6,6 +6,7 @@ import edu.uci.iotproject.trafficreassembly.layer2.Layer2Flow; import edu.uci.iotproject.trafficreassembly.layer2.Layer2FlowReassemblerObserver; import edu.uci.iotproject.detection.AbstractClusterMatcher; import edu.uci.iotproject.trafficreassembly.layer2.Layer2FlowObserver; +import org.jetbrains.annotations.NotNull; import org.pcap4j.core.*; import java.util.ArrayList; @@ -46,6 +47,12 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye private int mInclusionTimeMillis; + /** + * Keeping track of maximum number of skipped packets + */ + //private int mMaxSkippedPackets; + private List mMaxSkippedPackets; + /** * Create a new {@link Layer2ClusterMatcher} that attempts to find occurrences of {@code cluster}'s members. * @param cluster The sequence mutations that the new {@link Layer2ClusterMatcher} should search for. @@ -77,6 +84,8 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye mEps = eps; mInclusionTimeMillis = inclusionTimeMillis == 0 ? TriggerTrafficExtractor.INCLUSION_WINDOW_MILLIS : inclusionTimeMillis; + //mMaxSkippedPackets = 0; + mMaxSkippedPackets = new ArrayList<>(); } @Override @@ -119,6 +128,8 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye boolean matched = sm.matchPacket(newPacket); if (matched) { if (sm.getMatchedPacketsCount() == sm.getTargetSequencePacketCount()) { + // Update maximum skipped packets + updateMaxSkippedPackets(flow.getPackets(), sm.getMatchedPackets()); // Sequence matcher has a match. Report it to observers. mObservers.forEach(o -> o.onMatch(this, sm.getMatchedPackets())); // Remove the now terminated sequence matcher. @@ -145,6 +156,21 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye } } + // Update the maximum number of skipped packets + private void updateMaxSkippedPackets(List flowPackets, List matchedPackets) { + // Count number of skipped packets by looking into + // the difference of indices of two matched packets + for(int i = 1; i < matchedPackets.size(); ++i) { + int currIndex = flowPackets.indexOf(matchedPackets.get(i-1)); + int nextIndex = flowPackets.indexOf(matchedPackets.get(i)); + int skippedPackets = nextIndex - currIndex; +// if (mMaxSkippedPackets < skippedPackets) { +// mMaxSkippedPackets = skippedPackets; +// } + mMaxSkippedPackets.add(skippedPackets); + } + } + private void rangeBasedMatching(Layer2Flow flow, PcapPacket newPacket) { // TODO: For range-based matching, we need to create a new matcher every time we see the first element of // the sequence (between lower and upper bounds). @@ -175,7 +201,8 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye listMatchers.add(newMatcher); } // Present packet to the sequence matchers. - // Make a shallow copy of the list so that we can clean up the actual list when a matcher is terminated + // Make a shallow copy of the list so that we can clean up the actual list when a matcher is terminated. + // Otherwise, we would get an exception for changing the list while iterating on it. List listMatchersCopy = new ArrayList<>(listMatchers); for(Layer2RangeMatcher matcher : listMatchersCopy) { Layer2RangeMatcher sm = matcher; @@ -190,6 +217,8 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye boolean matched = sm.matchPacket(newPacket); if (matched) { if (sm.getMatchedPacketsCount() == sm.getTargetSequencePacketCount()) { + // Update maximum skipped packets + updateMaxSkippedPackets(flow.getPackets(), sm.getMatchedPackets()); // Sequence matcher has a match. Report it to observers. mObservers.forEach(o -> o.onMatch(this, sm.getMatchedPackets())); // Terminate sequence matcher since matching is complete. @@ -200,79 +229,6 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye } } -// private void rangeBasedMatching(Layer2Flow flow, PcapPacket newPacket) { -// // TODO: For range-based matching, we only care about matching a range; therefore it is a matcher array. -// if (mPerFlowRangeMatcher.get(flow) == null) { -// // If this is the first time we encounter this flow, we need to set up a sequence matcher. -// // All sequences of the cluster have the same length, so we only need to compute the length of the -// // arrays once. We want to make room for a cluster matcher in each state, including the initial empty state -// // but excluding the final "full match" state (as there is no point in keeping a terminated sequence matcher -// // around), so the length of the array is simply the sequence length. -// Layer2RangeMatcher[] matcher = new Layer2RangeMatcher[mCluster.get(0).size()]; -// // Prepare a "state 0" sequence matcher. -// matcher[0] = new Layer2RangeMatcher(mCluster.get(0), mCluster.get(1), mInclusionTimeMillis, mEps); -// // Associate the new sequence matcher table with the new flow. -// mPerFlowRangeMatcher.put(flow, matcher); -// } -// // Fetch table that contains sequence matchers for this flow. -// Layer2RangeMatcher[] matcher = mPerFlowRangeMatcher.get(flow); -// // Present packet to the sequence matcher. -// for (int j = matcher.length - 1; j >= 0; j--) { -// Layer2RangeMatcher sm = matcher[j]; -// if (sm == null) { -// // There is currently no sequence matcher that has managed to match j packets. -// continue; -// } -// boolean matched = sm.matchPacket(newPacket); -// -// // TODO: DEBUGGING -// long timeStamp = newPacket.getTimestamp().getEpochSecond(); -// if (339 == newPacket.length() && timeStamp == 1542297773) { -// System.out.println("Timestamp of length 339: " + newPacket.getTimestamp().getEpochSecond()); -// int length = matcher.length; -// } -// if (329 == newPacket.length() && timeStamp == 1542297773) { -// System.out.println("Timestamp of length 329: " + newPacket.getTimestamp().getEpochSecond()); -// } -// if (364 <= newPacket.length() && newPacket.length() <= 365 && timeStamp == 1542297773) { -// System.out.println("Timestamp of length 364-365: " + newPacket.getTimestamp().getEpochSecond()); -// } -// if (1061 <= newPacket.length() && newPacket.length() <= 1070 && timeStamp == 1542297773) { -// System.out.println("Timestamp of length 1061-1070: " + newPacket.getTimestamp().getEpochSecond()); -// } -// // TODO: DEBUGGING -// -// if (matched) { -// if (sm.getMatchedPacketsCount() == sm.getTargetSequencePacketCount()) { -// // Sequence matcher has a match. Report it to observers. -// mObservers.forEach(o -> o.onMatch(this, sm.getMatchedPackets())); -// // Remove the now terminated sequence matcher. -// matcher[j] = null; -// } else { -// // Sequence matcher advanced one step, so move it to its corresponding new position iff the -// // packet that advanced it has a later timestamp than that of the last matched packet of the -// // sequence matcher at the new index, if any. In most traces, a small amount of the packets -// // appear out of order (with regards to their timestamp), which is why this check is required. -// // Obviously it would not be needed if packets where guaranteed to be processed in timestamp -// // order here. -// if (matcher[j+1] == null || -// newPacket.getTimestamp().isAfter(matcher[j+1].getLastPacket().getTimestamp())) { -// matcher[j+1] = sm; -// if (matcher[j+1].getTargetUpperBound().size() == 4 && matcher[j+1].mMatchedPackets.size() > 1) { -// System.out.println("Got here"); -// } -// } -// } -// // We always want to have a sequence matcher in state 0, regardless of if the one that advanced -// // from state zero completed its matching or if it replaced a different one in state 1 or not. -// if (sm.getMatchedPacketsCount() == 1) { -// matcher[j] = new Layer2RangeMatcher(sm.getTargetLowerBound(), sm.getTargetUpperBound(), -// mInclusionTimeMillis, mEps); -// } -// } -// } -// } - @Override protected List> pruneCluster(List> cluster) { // Note: we assume that all sequences in the input cluster are of the same length and that their packet @@ -310,4 +266,14 @@ public class Layer2ClusterMatcher extends AbstractClusterMatcher implements Laye System.out.println(">>> IGNORING FLOW: " + newFlow + " <<<"); } } + + /** + * Return the maximum number of skipped packets. + */ +// public int getMaxSkippedPackets() { +// return mMaxSkippedPackets; +// } + public List getMaxSkippedPackets() { + return mMaxSkippedPackets; + } }