/* * This file is part of jsFlow. * * Copyright (c) 2009 DE-CIX Management GmbH <http://www.de-cix.net> - All rights * reserved. * * Author: Thomas King <thomas.king@de-cix.net> * * This software is licensed under the Apache License, version 2.0. A copy of * the license agreement is included in this distribution. */ package net.decix.jsflow.header; import java.util.Vector; import net.decix.util.HeaderBytesException; import net.decix.util.HeaderParseException; import net.decix.util.Utility; public class ExpandedFlowSampleHeader { // enterprise 0, format 3 private long seqNumber; private long sourceIDType; // 0 = ifindex, 1 = smonVlanDataSource, 2 = entPhysicalEntry private long sourceIDIndex; private long samplingRate; private long samplePool; // total number of packets that could have been sampled private long drops; // packets dropped due a lack of resources private long inputInterfaceFormat; private long inputInterfaceValue; private long outputInterfaceFormat; private long outputInterfaceValue; private long numberFlowRecords; private Vector<FlowRecordHeader> flowRecords; public ExpandedFlowSampleHeader() { flowRecords = new Vector<FlowRecordHeader>(); } public long getSequenceNumber() { return seqNumber; } public long getSourceIDType() { return sourceIDType; } public long getSourceIDIndex() { return sourceIDIndex; } public long getSamplingRate() { return samplingRate; } public long getSamplePool() { return samplePool; } public long getDrops() { return drops; } public long getInputInterfaceFormat() { return inputInterfaceFormat; } public long getInputInterfaceValue() { return inputInterfaceValue; } public long getOutputInterfaceFormat() { return outputInterfaceFormat; } public long getOutputInterfaceValue() { return outputInterfaceValue; } public long getNumberFlowRecords() { return numberFlowRecords; } public void setSequenceNumber(long seqNumber) { this.seqNumber = seqNumber; } public void setSourceIDType(long sourceIDType) { this.sourceIDType = sourceIDType; } public void setSourceIDIndex(long sourceIDIndex) { this.sourceIDIndex = sourceIDIndex; } public void setSamplingRate(long samplingRate) { this.samplingRate = samplingRate; } public void setSamplePool(long samplePool) { this.samplePool = samplePool; } public void setDrops(long drops) { this.drops = drops; } public void setInputInterfaceFormat(long inputInterfaceFormat) { this.inputInterfaceFormat = inputInterfaceFormat; } public void setInputInterfaceValue(long inputInterfaceValue) { this.inputInterfaceValue = inputInterfaceValue; } public void setOutputInterfaceFormat(long outputInterfaceFormat) { this.outputInterfaceFormat = outputInterfaceFormat; } public void setOutputInterfaceValue(long outputInterfaceValue) { this.outputInterfaceValue = outputInterfaceValue; } public void setNumberFlowRecords(long numberFlowRecords) { this.numberFlowRecords = numberFlowRecords; } public void addFlowRecord(FlowRecordHeader flowRecord) { flowRecords.add(flowRecord); } public Vector<FlowRecordHeader> getFlowRecords() { return flowRecords; } public static ExpandedFlowSampleHeader parse(byte[] data) throws HeaderParseException { try { if (data.length < 44) throw new HeaderParseException("Data array too short."); ExpandedFlowSampleHeader efsh = new ExpandedFlowSampleHeader(); // sample sequence number byte[] seqNumber = new byte[4]; System.arraycopy(data, 0, seqNumber, 0, 4); efsh.setSequenceNumber(Utility.fourBytesToLong(seqNumber)); // source id type byte[] sourceIDType = new byte[4]; System.arraycopy(data, 4, sourceIDType, 0, 4); efsh.setSourceIDType(Utility.fourBytesToLong(sourceIDType)); // source id index byte[] sourceIDIndex = new byte[4]; System.arraycopy(data, 8, sourceIDIndex, 0, 4); efsh.setSourceIDIndex(Utility.fourBytesToLong(sourceIDIndex)); // sampling rate byte[] samplingRate = new byte[4]; System.arraycopy(data, 12, samplingRate, 0, 4); efsh.setSamplingRate(Utility.fourBytesToLong(samplingRate)); // sample pool byte[] samplePool = new byte[4]; System.arraycopy(data, 16, samplePool, 0, 4); efsh.setSamplePool(Utility.fourBytesToLong(samplePool)); // drops byte[] drops = new byte[4]; System.arraycopy(data, 20, drops, 0, 4); efsh.setDrops(Utility.fourBytesToLong(drops)); // input interface format byte[] inputInterfaceFormat = new byte[4]; System.arraycopy(data, 24, inputInterfaceFormat, 0, 4); efsh.setInputInterfaceFormat(Utility.fourBytesToLong(inputInterfaceFormat)); // input interface value byte[] inputInterfaceValue = new byte[4]; System.arraycopy(data, 28, inputInterfaceValue, 0, 4); efsh.setInputInterfaceValue(Utility.fourBytesToLong(inputInterfaceValue)); // output interface format byte[] outputInterfaceFormat = new byte[4]; System.arraycopy(data, 32, outputInterfaceFormat, 0, 4); efsh.setOutputInterfaceFormat(Utility.fourBytesToLong(outputInterfaceFormat)); // output interface value byte[] outputInterfaceValue = new byte[4]; System.arraycopy(data, 36, outputInterfaceValue, 0, 4); efsh.setOutputInterfaceValue(Utility.fourBytesToLong(outputInterfaceValue)); // number flow records byte[] numberFlowRecords = new byte[4]; System.arraycopy(data, 40, numberFlowRecords, 0, 4); efsh.setNumberFlowRecords(Utility.fourBytesToLong(numberFlowRecords)); // flow records int offset = 44; for (int i = 0; i < efsh.getNumberFlowRecords(); i++) { byte[] subData = new byte[data.length - offset]; System.arraycopy(data, offset, subData, 0, data.length - offset); FlowRecordHeader fr = FlowRecordHeader.parse(subData); efsh.addFlowRecord(fr); offset += (fr.getFlowDataLength() + 8); } return efsh; } catch (Exception e) { throw new HeaderParseException("Parse error: " + e.getMessage()); } } public byte[] getBytes() throws HeaderBytesException { try { int lengthFlowRecords = 0; for (FlowRecordHeader fr : flowRecords) { lengthFlowRecords += (fr.getFlowDataLength() + 8); } byte[] data = new byte[44 + lengthFlowRecords]; // sequence number System.arraycopy(Utility.longToFourBytes(seqNumber), 0, data, 0, 4); // source id type System.arraycopy(Utility.longToFourBytes(sourceIDType), 0, data, 4, 4); // source id index System.arraycopy(Utility.longToFourBytes(sourceIDIndex), 0, data, 8, 4); // sampling rate System.arraycopy(Utility.longToFourBytes(samplingRate), 0, data, 12, 4); // sample pool System.arraycopy(Utility.longToFourBytes(samplePool), 0, data, 16, 4); // drops System.arraycopy(Utility.longToFourBytes(drops), 0, data, 20, 4); // input interface format System.arraycopy(Utility.longToFourBytes(inputInterfaceFormat), 0, data, 24, 4); // input interface value System.arraycopy(Utility.longToFourBytes(inputInterfaceValue), 0, data, 28, 4); // output interface format System.arraycopy(Utility.longToFourBytes(outputInterfaceFormat), 0, data, 32, 4); // output interface value System.arraycopy(Utility.longToFourBytes(outputInterfaceValue), 0, data, 36, 4); // number flow records System.arraycopy(Utility.longToFourBytes(numberFlowRecords), 0, data, 40, 4); int offset = 0; for (FlowRecordHeader fr : flowRecords) { byte[] temp = fr.getBytes(); System.arraycopy(temp, 0, data, 44 + offset, temp.length); offset += (fr.getFlowDataLength() + 8); } return data; } catch (Exception e) { throw new HeaderBytesException("Error while generating the bytes: " + e.getMessage()); } } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[ExpandedFlowSampleHeader]: "); sb.append("SequenceNumber: "); sb.append(getSequenceNumber()); sb.append(", SourceIDtype: "); sb.append(getSourceIDType()); sb.append(", SourceIDindex: "); sb.append(getSourceIDIndex()); sb.append(", SamplingRate: "); sb.append(getSamplingRate()); sb.append(", SamplePool: "); sb.append(getSamplePool()); sb.append(", Drops: "); sb.append(getDrops()); sb.append(", InputInterfaceFormat: "); sb.append(getInputInterfaceFormat()); sb.append(", InputInterfaceValue: "); sb.append(getInputInterfaceValue()); sb.append(", OutputInterfaceFormat: "); sb.append(getOutputInterfaceFormat()); sb.append(", OutputInterfaceValue: "); sb.append(getOutputInterfaceValue()); sb.append(", FlowRecords: "); sb.append(getNumberFlowRecords()); for (FlowRecordHeader frh : flowRecords) { sb.append(frh); sb.append(" "); } return sb.toString(); } }