Testing with tighter bounds (without epsilon) for signatures that are 2 packets.
authorrtrimana <rtrimana@uci.edu>
Wed, 13 Mar 2019 18:48:51 +0000 (11:48 -0700)
committerrtrimana <rtrimana@uci.edu>
Wed, 13 Mar 2019 18:48:51 +0000 (11:48 -0700)
Code/Projects/PacketLevelSignatureExtractor/execute_layer3_smarthome_all_detection.sh
Code/Projects/PacketLevelSignatureExtractor/execute_layer3_unb_all_detection.sh
Code/Projects/PacketLevelSignatureExtractor/execute_layer3_unsw_all_detection.sh
Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/SignatureGenerator.java
Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer2/Layer2SignatureDetector.java
Code/Projects/PacketLevelSignatureExtractor/src/main/java/edu/uci/iotproject/detection/layer3/Layer3SignatureDetector.java

index 8f4465f..e5a84de 100755 (executable)
@@ -25,10 +25,10 @@ PCAP_FILE="$PCAPS_BASE_DIR/arlo-camera/eth0/arlo-camera.eth0.detection.pcap"
 # PHONE SIDE (TODO: may possibly be the .incomplete signatures)
 ON_ANALYSIS="$SIGNATURES_BASE_DIR/arlo-camera/analysis/arlo-camera-onClusters-phone-side.cls"
 OFF_ANALYSIS="$SIGNATURES_BASE_DIR/arlo-camera/analysis/arlo-camera-offClusters-phone-side.cls"
-ON_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-onSignature-phone-side.sig"
-OFF_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-offSignature-phone-side.sig"
+ON_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-onSignature-phone-side.complete.sig"
+OFF_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-offSignature-phone-side.complete.sig"
 RESULTS_FILE="$OUTPUT_DIR/arlo-camera/arlo-camera.eth0.detection.pcap___phone-side.detectionresults"
-SIGNATURE_DURATION="213"
+SIGNATURE_DURATION="548"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
 #./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
@@ -48,7 +48,7 @@ RESULTS_FILE="$OUTPUT_DIR/blossom-sprinkler/blossom-sprinkler.eth0.detection.pca
 SIGNATURE_DURATION="9274"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 
 # PHONE SIDE
 ON_ANALYSIS="$SIGNATURES_BASE_DIR/blossom-sprinkler/analysis/blossom-sprinkler-onClusters-phone-side.cls"
@@ -59,7 +59,7 @@ RESULTS_FILE="$OUTPUT_DIR/blossom-sprinkler/blossom-sprinkler.wlan1.detection.pc
 SIGNATURE_DURATION="3670"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 # ======================================================================================================================
 
 
@@ -76,7 +76,7 @@ RESULTS_FILE="$OUTPUT_DIR/dlink-plug/dlink-plug.eth0.detection.pcap___device-sid
 SIGNATURE_DURATION="8866"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 
 # PHONE SIDE
 ON_ANALYSIS="$SIGNATURES_BASE_DIR/dlink-plug/analysis/dlink-plug-onClusters-phone-side.cls"
@@ -87,7 +87,7 @@ RESULTS_FILE="$OUTPUT_DIR/dlink-plug/dlink-plug.eth0.detection.pcap___phone-side
 SIGNATURE_DURATION="193"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 # ======================================================================================================================
 
 
@@ -104,7 +104,7 @@ RESULTS_FILE="$OUTPUT_DIR/dlink-siren/dlink-siren.eth0.detection.pcap___phone-si
 SIGNATURE_DURATION="71"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 # ======================================================================================================================
 
 
@@ -142,7 +142,7 @@ RESULTS_FILE="$OUTPUT_DIR/kwikset-doorlock/kwikset-doorlock.eth0.detection.pcap_
 SIGNATURE_DURATION="3161"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 # ======================================================================================================================
 
 
@@ -180,7 +180,7 @@ RESULTS_FILE="$OUTPUT_DIR/st-plug/st-plug.wlan1.detection.pcap___phone-side.dete
 SIGNATURE_DURATION="2445"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 # ======================================================================================================================
 
 
@@ -216,7 +216,7 @@ RESULTS_FILE="$OUTPUT_DIR/tplink-plug/tplink-plug.wlan1.wan-detection.pcap___dev
 SIGNATURE_DURATION="3660"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 
 # DEVICE SIDE OUTBOUND (contains only those packets that go through the WAN port, i.e., only the 556, 1293 sequence)
 ON_ANALYSIS="$SIGNATURES_BASE_DIR/tplink-plug/analysis/tplink-plug-onClusters.cls"
@@ -227,7 +227,7 @@ RESULTS_FILE="$OUTPUT_DIR/tplink-plug/tplink-plug.wlan1.wan-detection.pcap___dev
 SIGNATURE_DURATION="224"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
-./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
+#./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
 
 # Phone side does not make sense as it is merely a subset of the device side and does not differentiate ONs from OFFs.
 # ======================================================================================================================
index 3bd5229..101f7eb 100755 (executable)
@@ -31,7 +31,7 @@ OFF_ANALYSIS="$SIGNATURES_BASE_DIR/arlo-camera/analysis/arlo-camera-offClusters-
 ON_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-onSignature-phone-side.sig"
 OFF_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-offSignature-phone-side.sig"
 RESULTS_FILE="$OUTPUT_DIR/arlo-camera/arlo-camera.eth0.detection.pcap___phone-side$i.detectionresults"
-SIGNATURE_DURATION="213"
+SIGNATURE_DURATION="548"
 
 PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
 ./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
index e4b1301..8a26715 100755 (executable)
@@ -59,7 +59,7 @@ do
        ON_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-onSignature-phone-side.sig"
        OFF_SIGNATURE="$SIGNATURES_BASE_DIR/arlo-camera/signatures/arlo-camera-offSignature-phone-side.sig"
        RESULTS_FILE="$OUTPUT_DIR/arlo-camera/arlo-camera.eth0.detection.pcap___phone-side$i.detectionresults"
-       SIGNATURE_DURATION="213"
+       SIGNATURE_DURATION="548"
 
        PROGRAM_ARGS="'$PCAP_FILE' '$ON_ANALYSIS' '$OFF_ANALYSIS' '$ON_SIGNATURE' '$OFF_SIGNATURE' '$RESULTS_FILE' '$SIGNATURE_DURATION'"
        ./gradlew run -DmainClass=edu.uci.iotproject.detection.layer3.Layer3SignatureDetector --args="$PROGRAM_ARGS"
index d342508..c00f8ff 100644 (file)
@@ -57,11 +57,11 @@ public class SignatureGenerator {
 //        final String triggerTimesFile = path + "/2018-10/dlink-plug/dlink-plug-oct-17-2018.timestamps";
 //        final String deviceIp = "192.168.1.199"; // .246 == phone; .199 == dlink plug?
         // TODO: EXPERIMENT - November 7, 2018
-//        final String inputPcapFile = path + "/experimental_result/standalone/dlink-plug/wlan1/dlink-plug.wlan1.local.pcap";
-//        final String outputPcapFile = path + "/experimental_result/standalone/dlink-plug/wlan1/dlink-plug-processed.pcap";
-//        final String triggerTimesFile = path + "/experimental_result/standalone/dlink-plug/timestamps/dlink-plug-nov-7-2018.timestamps";
-////        final String deviceIp = "192.168.1.199"; // .246 == phone; .199 == dlink plug?
-//        final String deviceIp = "192.168.1.246"; // .246 == phone; .199 == dlink plug?
+        final String inputPcapFile = path + "/experimental_result/standalone/dlink-plug/wlan1/dlink-plug.wlan1.local.pcap";
+        final String outputPcapFile = path + "/experimental_result/standalone/dlink-plug/wlan1/dlink-plug-processed.pcap";
+        final String triggerTimesFile = path + "/experimental_result/standalone/dlink-plug/timestamps/dlink-plug-nov-7-2018.timestamps";
+//        final String deviceIp = "192.168.1.199"; // .246 == phone; .199 == dlink plug?
+        final String deviceIp = "192.168.1.246"; // .246 == phone; .199 == dlink plug?
 
         // 2) TODO: TP-LINK PLUG July 25 experiment
 //        final String inputPcapFile = path + "/2018-07/tplink/tplink.wlan1.local.pcap";
@@ -125,11 +125,11 @@ public class SignatureGenerator {
 //        final String triggerTimesFile = path + "/2018-07/wemoinsight/wemo-insight-july-31-2018.timestamps";
 //        final String deviceIp = "192.168.1.135";
         // TODO: EXPERIMENT - November 21, 2018
-        final String inputPcapFile = path + "/experimental_result/standalone/wemo-insight-plug/wlan1/wemo-insight-plug.wlan1.local.pcap";
-        final String outputPcapFile = path + "/experimental_result/standalone/wemo-insight-plug/wlan1/wemo-insight-plug-processed.pcap";
-        final String triggerTimesFile = path + "/experimental_result/standalone/wemo-insight-plug/timestamps/wemo-insight-plug-nov-21-2018.timestamps";
-//        final String deviceIp = "192.168.1.145"; // .246 == phone; .135 == WeMo Insight
-        final String deviceIp = "192.168.1.246"; // .246 == phone; .135 == WeMo Insight
+//        final String inputPcapFile = path + "/experimental_result/standalone/wemo-insight-plug/wlan1/wemo-insight-plug.wlan1.local.pcap";
+//        final String outputPcapFile = path + "/experimental_result/standalone/wemo-insight-plug/wlan1/wemo-insight-plug-processed.pcap";
+//        final String triggerTimesFile = path + "/experimental_result/standalone/wemo-insight-plug/timestamps/wemo-insight-plug-nov-21-2018.timestamps";
+////        final String deviceIp = "192.168.1.145"; // .246 == phone; .135 == WeMo Insight
+//        final String deviceIp = "192.168.1.246"; // .246 == phone; .135 == WeMo Insight
 
         // 6) TODO: TP-LINK BULB August 1 experiment
 //        final String inputPcapFile = path + "/2018-08/tplink-bulb/tplinkbulb.wlan1.local.pcap";
@@ -327,8 +327,8 @@ public class SignatureGenerator {
 //        final String offSignatureFile = path + "/experimental_result/standalone/st-plug/signatures/st-plug-offSignature-phone-side.sig";
         // Arlo Q
 //        final String triggerTimesFile = path + "/experimental_result/standalone/arlo-camera/timestamps/arlo-camera-nov-13-2018.timestamps";
-//        final String onSignatureFile = path + "/experimental_result/standalone/arlo-camera/signatures/arlo-camera-onSignature-phone-side.sig";
-//        final String offSignatureFile = path + "/experimental_result/standalone/arlo-camera/signatures/arlo-camera-offSignature-phone-side.sig";
+//        final String onSignatureFile = path + "/experimental_result/standalone/arlo-camera/signatures/arlo-camera-onSignature-phone-side.complete.sig";
+//        final String offSignatureFile = path + "/experimental_result/standalone/arlo-camera/signatures/arlo-camera-offSignature-phone-side.complete.sig";
         // Nest thermostat
 //        final String triggerTimesFile = path + "/experimental_result/standalone/nest-thermostat/timestamps/nest-thermostat-nov-15-2018.timestamps";
 //        final String onSignatureFile = path + "/experimental_result/standalone/nest-thermostat/signatures/nest-thermostat-onSignature-phone-side.sig";
@@ -363,8 +363,8 @@ public class SignatureGenerator {
 //        System.out.println("ON signature file in use is " + onSignatureFile);
 //        System.out.println("OFF signature file in use is " + offSignatureFile);
 //
-//        List<List<List<PcapPacket>>> onSignature = PrintUtils.deserializeSignatureFromFile(onSignatureFile);
-//        List<List<List<PcapPacket>>> offSignature = PrintUtils.deserializeSignatureFromFile(offSignatureFile);
+//        List<List<List<PcapPacket>>> onSignature = PrintUtils.deserializeFromFile(onSignatureFile);
+//        List<List<List<PcapPacket>>> offSignature = PrintUtils.deserializeFromFile(offSignatureFile);
 //
 //        List<Instant> signatureTimestamps = new ArrayList<>();
 //        // Load ON signature last packet's timestamp
@@ -924,51 +924,8 @@ public class SignatureGenerator {
         }
 
         return isRange;
-//        if (!isRangeBased(signatureRanges) && !isRangeBased(otherSignatureRanges)) {
-//            // Conservative checking when there is no range
-//            return true;
-//        } else if(signatureRanges.size() != otherSignatureRanges.size()) {
-//            // The two signatures have different numbers of packets/packet lengths
-//            return false;
-//        } else {
-//            // There is range; check if there is overlap
-//            return checkOverlap(signatureRanges, otherSignatureRanges);
-//        }
     }
 
-    /*
-     * Check for overlap since we have range in at least one of the signatures.
-     * Overlap is only true when all ranges overlap. We need to check in order.
-     */
-//    private boolean checkOverlap(List<List<List<PcapPacket>>> signatureRanges,
-//                                 List<List<List<PcapPacket>>> otherSignatureRanges) {
-//
-//        for(List<List<PcapPacket>> listListPcapPacket : signatureRanges) {
-//            // Lower bound of the range is in index 0
-//            // Upper bound of the range is in index 1
-//            int sequenceSetIndex = signatureRanges.indexOf(listListPcapPacket);
-//            List<PcapPacket> minSequenceSignature = listListPcapPacket.get(0);
-//            List<PcapPacket> maxSequenceSignature = listListPcapPacket.get(1);
-//            for(PcapPacket pcapPacket : minSequenceSignature) {
-//                // Get the lower and upper bounds of the current signature
-//                int packetIndex = minSequenceSignature.indexOf(pcapPacket);
-//                int lowerBound = pcapPacket.length();
-//                int upperBound = maxSequenceSignature.get(packetIndex).length();
-//                // Check for range overlap in the other signature!
-//                // Check the packet/packet length at the same position
-//                List<PcapPacket> minSequenceSignatureOther = otherSignatureRanges.get(sequenceSetIndex).get(0);
-//                List<PcapPacket> maxSequenceSignatureOther = otherSignatureRanges.get(sequenceSetIndex).get(1);
-//                int lowerBoundOther = minSequenceSignatureOther.get(packetIndex).length();
-//                int upperBoundOther = maxSequenceSignatureOther.get(packetIndex).length();
-//                if (!(lowerBoundOther <= lowerBound && lowerBound <= upperBoundOther) &&
-//                    !(lowerBoundOther <= upperBound && upperBound <= upperBoundOther)) {
-//                    return false;
-//                }
-//            }
-//        }
-//
-//        return true;
-//    }
 
     /*
      * Check and see if there is any range in the signatures
@@ -992,40 +949,6 @@ public class SignatureGenerator {
 
         return false;
     }
-
-//    /* Find the sequence with the minimum packet lengths.
-//     * The second-layer list should contain the minimum sequence for element 0 and maximum sequence for element 1.
-//     */
-//    private List<List<List<PcapPacket>>> getSequenceRanges(List<List<List<PcapPacket>>> signature) {
-//
-//        // Start from the first index
-//        List<List<List<PcapPacket>>> rangeBasedSequence = new ArrayList<>();
-//        for (List<List<PcapPacket>> listListPcapPacket : signature) {
-//            List<List<PcapPacket>> minMaxSequence = new ArrayList<>();
-//            // Both searches start from index 0
-//            List<PcapPacket> minSequence = new ArrayList<>(listListPcapPacket.get(0));
-//            List<PcapPacket> maxSequence = new ArrayList<>(listListPcapPacket.get(0));
-//            for (List<PcapPacket> listPcapPacket : listListPcapPacket) {
-//                for (PcapPacket pcapPacket : listPcapPacket) {
-//                    int index = listPcapPacket.indexOf(pcapPacket);
-//                    // Set the new minimum if length at the index is minimum
-//                    if (pcapPacket.length() < minSequence.get(index).length()) {
-//                        minSequence.set(index, pcapPacket);
-//                    }
-//                    // Set the new maximum if length at the index is maximum
-//                    if (pcapPacket.length() > maxSequence.get(index).length()) {
-//                        maxSequence.set(index, pcapPacket);
-//                    }
-//                }
-//            }
-//            // minSequence as element 0 and maxSequence as element 1
-//            minMaxSequence.add(minSequence);
-//            minMaxSequence.add(maxSequence);
-//            rangeBasedSequence.add(minMaxSequence);
-//        }
-//
-//        return rangeBasedSequence;
-//    }
 }
 
 
index 2fc1d7a..c133b8e 100644 (file)
@@ -78,6 +78,7 @@ public class Layer2SignatureDetector implements PacketListener, ClusterMatcherOb
             System.out.println(optParamsExplained);
             return;
         }
+        // TODO: We could take 7 inputs if we decided to use the cluster analyses.
 //        final String pcapFile = args[0];
 //        final String onClusterAnalysisFile = args[1];
 //        final String offClusterAnalysisFile = args[2];
index 92d2bd9..4a5ecb9 100644 (file)
@@ -46,7 +46,7 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
     private static String ROUTER_WAN_IP = "128.195.205.105";
 
     public static void main(String[] args) throws PcapNativeException, NotOpenException, IOException {
-        if (args.length < 7) {
+        if (args.length < 8) {
             String errMsg = String.format("Usage: %s inputPcapFile onAnalysisFile offAnalysisFile onSignatureFile offSignatureFile resultsFile" +
                             "\n  inputPcapFile: the target of the detection" +
                             "\n  onAnalysisFile: the file that contains the ON clusters analysis" +
@@ -54,7 +54,8 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
                             "\n  onSignatureFile: the file that contains the ON signature to search for" +
                             "\n  offSignatureFile: the file that contains the OFF signature to search for" +
                             "\n  resultsFile: where to write the results of the detection" +
-                            "\n  signatureDuration: the maximum duration of signature detection",
+                            "\n  signatureDuration: the maximum duration of signature detection" +
+                            "\n  epsilon: the epsilon value for the DBSCAN algorithm",
                     Layer3SignatureDetector.class.getSimpleName());
             System.out.println(errMsg);
             return;
@@ -66,6 +67,7 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
         final String offSignatureFile = args[4];
         final String resultsFile = args[5];
         final int signatureDuration = Integer.parseInt(args[6]);
+        final double eps = Double.parseDouble(args[7]);
 
         // Prepare file outputter.
         File outputFile = new File(resultsFile);
@@ -80,9 +82,6 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
         PrintWriterUtils.println("# - offSignatureFile: " + offSignatureFile, resultsWriter, DUPLICATE_OUTPUT_TO_STD_OUT);
         resultsWriter.flush();
 
-        // Specify epsilon
-        // TODO: This would be specified through command line option
-        double eps = 10.0;
         // Load signatures
         List<List<List<PcapPacket>>> onSignature = PrintUtils.deserializeFromFile(onSignatureFile);
         List<List<List<PcapPacket>>> offSignature = PrintUtils.deserializeFromFile(offSignatureFile);
@@ -96,17 +95,27 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
         // Check if we should use range-based matching
         boolean isRangeBasedForOn = PcapPacketUtils.isRangeBasedMatching(onSignature, eps, offSignature);
         boolean isRangeBasedForOff = PcapPacketUtils.isRangeBasedMatching(offSignature, eps, onSignature);
+//        boolean isRangeBasedForOn = false;
+//        boolean isRangeBasedForOff = false;
         // Update the signature with ranges if it is range-based
         if (isRangeBasedForOn && isRangeBasedForOff) {
             onSignature = PcapPacketUtils.useRangeBasedMatching(onSignature, onClusterAnalysis);
             offSignature = PcapPacketUtils.useRangeBasedMatching(offSignature, offClusterAnalysis);
         }
-
         // WAN
+        double onEps = eps;
+        double offEps = eps;
+        // IFF the signature is just one pair of packets then we set EPS to 0 to make it tighter
+        if (onSignature.get(0).size() == 1 && onSignature.get(0).get(0).size() == 2) {
+            onEps = 0;
+        }
+        if (offSignature.get(0).size() == 1 && offSignature.get(0).get(0).size() == 2) {
+            offEps = 0;
+        }
         Layer3SignatureDetector onDetector = new Layer3SignatureDetector(onSignature, ROUTER_WAN_IP,
-                signatureDuration, isRangeBasedForOn, eps);
+                signatureDuration, isRangeBasedForOn, onEps);
         Layer3SignatureDetector offDetector = new Layer3SignatureDetector(offSignature, ROUTER_WAN_IP,
-                signatureDuration, isRangeBasedForOff, eps);
+                signatureDuration, isRangeBasedForOff, offEps);
 
         final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).
                 withLocale(Locale.US).withZone(ZoneId.of("America/Los_Angeles"));
@@ -128,6 +137,7 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
             // String output = String.format("%s",
             // dateTimeFormatter.format(ua.getTimestamp()));
             // System.out.println(output);
+            PrintWriterUtils.println(ua, resultsWriter, DUPLICATE_OUTPUT_TO_STD_OUT);
         };
 
         // Let's create observers that construct a UserAction representing the detected event.
@@ -135,13 +145,12 @@ public class Layer3SignatureDetector implements PacketListener, ClusterMatcherOb
         onDetector.addObserver((searched, match) -> {
             PcapPacket firstPkt = match.get(0).get(0);
             UserAction event = new UserAction(UserAction.Type.TOGGLE_ON, firstPkt.getTimestamp());
-            PrintWriterUtils.println(event, resultsWriter, DUPLICATE_OUTPUT_TO_STD_OUT);
             detectedEvents.add(event);
         });
         offDetector.addObserver((searched, match) -> {
             PcapPacket firstPkt = match.get(0).get(0);
             UserAction event = new UserAction(UserAction.Type.TOGGLE_OFF, firstPkt.getTimestamp());
-            PrintWriterUtils.println(event, resultsWriter, DUPLICATE_OUTPUT_TO_STD_OUT);
+            //PrintWriterUtils.println(event, resultsWriter, DUPLICATE_OUTPUT_TO_STD_OUT);
             detectedEvents.add(event);
         });