package net.decix.jipfix.detector;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class GroupMissingSequenceNumberChecker {
private final static Logger mLogger = Logger.getLogger(GroupMissingSequenceNumberChecker.class.getName());
private static int CHECK_LAST_SEQEUNCE_NUMBERS = 1024;
private static int DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER = 512;
private List<Long> mSequenceNumbers = Collections.synchronizedList(new ArrayList<Long>());
private IPObservationDomain currentIPObservationDomain;
public GroupMissingSequenceNumberChecker() {
this.currentIPObservationDomain = new IPObservationDomain();
}
public GroupMissingSequenceNumberChecker(IPObservationDomain currentIPObservationDomain) {
this.currentIPObservationDomain = currentIPObservationDomain;
}
public List<Long> getSequenceNumbers() {
return mSequenceNumbers;
}
public void addSequenceNumber(long sequenceNumber) {
mSequenceNumbers.add(sequenceNumber);
if (((sequenceNumber % DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER) == 0) && (sequenceNumber != 0)) {
mLogger.fine("Sequence: " + sequenceNumber);
checkSequenceNumbers(sequenceNumber);
}
}
public void removeSequenceNumber(long sequenceNumber) {
mSequenceNumbers.remove(mSequenceNumbers);
}
public void removeSequenceNumbers(List<Long> sequenceNumbers) {
mSequenceNumbers.removeAll(sequenceNumbers);
}
public synchronized void checkSequenceNumbers(long lastSequenceNumber) {
// sequence number overflow handling is needed -> done
// limit the space needed -> done
boolean missingSequenceNumber = false;
mLogger.fine(currentIPObservationDomain.getAddress().getHostAddress() + ":" + currentIPObservationDomain.getObservationDomain() + ": Start sequence number check in the range of: " + (lastSequenceNumber - CHECK_LAST_SEQEUNCE_NUMBERS) + " - " + (lastSequenceNumber - DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER));
int missingSequenceNumbers = 0;
for (long i = (lastSequenceNumber - CHECK_LAST_SEQEUNCE_NUMBERS); i < (lastSequenceNumber - DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER); i++) {
long j = i;
if (i < 0) {
j = Math.floorMod(i, (long) Math.pow(2, 32));
}
if (!mSequenceNumbers.contains(j)) {
missingSequenceNumber = true;
missingSequenceNumbers++;
System.out.println("Missing: " + j);
}
}
// if (lastSequenceNumber == mSequenceNumbers.get(mSequenceNumbers.size() - 1)) { // hack needed to handle ALU bug which results in equal sequence number in consecutive IPFIX packets
// missingSequenceNumber = false;
// }
if (!missingSequenceNumber) {
mLogger.info(currentIPObservationDomain.getAddress().getHostAddress() + ":" + currentIPObservationDomain.getObservationDomain() + ": No sequence number is missing in range: " + Math.floorMod((lastSequenceNumber - CHECK_LAST_SEQEUNCE_NUMBERS), (long) Math.pow(2, 32)) + " - " + Math.floorMod((lastSequenceNumber - DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER - 1), (long) Math.pow(2, 32)));
removeSequenceNumbers(lastSequenceNumber - CHECK_LAST_SEQEUNCE_NUMBERS, lastSequenceNumber - DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER - 1);
} else {
mLogger.info("LastSequenceNumber: " + lastSequenceNumber);
mLogger.info(currentIPObservationDomain.getAddress().getHostAddress() + ":" + currentIPObservationDomain.getObservationDomain() + ": Number of missing sequence numbers: " + missingSequenceNumbers + " in range: " + Math.floorMod((lastSequenceNumber - CHECK_LAST_SEQEUNCE_NUMBERS), (long) Math.pow(2, 32)) + " - " + Math.floorMod((lastSequenceNumber - DISTANCE_FROM_CURRENT_SEQUENCE_NUMBER - 1), (long) Math.pow(2, 32)));
}
shrinkList();
}
private void removeSequenceNumbers(long startRange, long endRange) {
List<Long> removeSequenceNumbers = new ArrayList<Long>();
for (long i = startRange; i <= endRange; i++) {
removeSequenceNumbers.add(Math.floorMod(i, (long) Math.pow(2, 32)));
}
removeSequenceNumbers(removeSequenceNumbers);
}
private void shrinkList() {
if (mSequenceNumbers.size() > ((CHECK_LAST_SEQEUNCE_NUMBERS * 2) + 1)) {
mLogger.fine(currentIPObservationDomain.getAddress().getHostAddress() + ":" + currentIPObservationDomain.getObservationDomain() + ": Shrink " + (mSequenceNumbers.size() - (2 * CHECK_LAST_SEQEUNCE_NUMBERS)) + " elements. Size: " + mSequenceNumbers.size());
int counter = (mSequenceNumbers.size() - (2 * CHECK_LAST_SEQEUNCE_NUMBERS));
for (int i = 0; i <= counter; i++) {
mSequenceNumbers.remove(0);
}
} else {
mLogger.fine(currentIPObservationDomain.getAddress().getHostAddress() + ":" + currentIPObservationDomain.getObservationDomain() + ": Nothing to shrink");
}
}
public static void main(String args[]) throws SecurityException, IOException {
FileHandler fh = new FileHandler("ipfix-muxer.log", 5 * 10485760, 20, true); // 20 x 50MByte
fh.setFormatter(new SimpleFormatter());
Logger l = Logger.getLogger("");
l.addHandler(fh);
l.setLevel(Level.FINEST);
System.setProperty("java.net.preferIPv4Stack" , "true");
mLogger.log(Level.INFO, "Program Start");
GroupMissingSequenceNumberChecker msnc = new GroupMissingSequenceNumberChecker();
for (long i = (((long) Math.pow(2, 32)) - 1000); i <= Math.pow(2, 32); i++) {
if (i != (Math.pow(2, 32) - 128)) msnc.addSequenceNumber(i);
// msnc.addSequenceNumber(i);
}
for (long i = 0; i <= Math.pow(2, 12); i++) {
if (i != 125) msnc.addSequenceNumber(i);
}
System.out.println(msnc.getSequenceNumbers().size());
}
}