blob: af18b2ca43372b61fd150f4d561c2ce561905fdb [file] [log] [blame]
/*
* Copyright 2015 Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.ipfix.packet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
/**
* IPFIX Message Header.
*/
public class MessageHeader extends AbstractIpfixPacketEntity implements AbstractIpfixPacketInterface {
private static final Logger LOGGER = Logger.getLogger(SetHeader.class.getName());
private static final int HEADER_LENGTH = 16;
private static final int IPFIX_VERSION = 10;
private int versionNumber;
private int length;
private Date exportTime;
private long sequenceNumber;
private long observationDomainID;
private List<SetHeader> setHeaders = new ArrayList<SetHeader>();
/**
* Message Header format.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version Number | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Export Time |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Observation Domain ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
public int getVersionNumber() {
return IPFIX_VERSION;
}
public void setVersionNumber(int versionNumber) {
this.versionNumber = versionNumber;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Date getExportTime() {
return exportTime;
}
public void setExportTime(Date exportTime) {
this.exportTime = exportTime;
}
public long getSequenceNumber() {
return sequenceNumber;
}
public void setSequenceNumber(long sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
public long getObservationDomainID() {
return observationDomainID;
}
public void setObservationDomainID(long observationDomainID) {
this.observationDomainID = observationDomainID;
}
public List<SetHeader> getSetHeaders() {
return setHeaders;
}
public void setSetHeaders(List<SetHeader> setHeaders) {
this.setHeaders = setHeaders;
int length = HEADER_LENGTH;
for (SetHeader header : setHeaders) {
length += header.getLength();
}
setLength(length);
}
public static MessageHeader parse(byte[] data) throws HeaderException {
try {
if (data.length < HEADER_LENGTH) {
throw new HeaderException("Data array too short.");
}
MessageHeader mh = new MessageHeader();
// version number
byte[] versionNumber = new byte[2];
System.arraycopy(data, 0, versionNumber, 0, 2);
mh.setVersionNumber(Ints.fromByteArray(versionNumber));
// length
byte[] length = new byte[2];
System.arraycopy(data, 2, length, 0, 2);
mh.setLength(Ints.fromByteArray(length));
// export time
byte[] exportTime = new byte[4];
System.arraycopy(data, 4, exportTime, 0, 4);
long secondsSinceEpoche = Longs.fromByteArray(exportTime);
long milliSecondsSinceEpoche = secondsSinceEpoche * 1000;
mh.setExportTime(new Date(milliSecondsSinceEpoche));
// sequence number
byte[] sequenceNumber = new byte[4];
System.arraycopy(data, 8, sequenceNumber, 0, 4);
mh.setSequenceNumber(Longs.fromByteArray(sequenceNumber));
// observation domain id
byte[] observationDomainID = new byte[4];
System.arraycopy(data, 12, observationDomainID, 0, 4);
mh.setObservationDomainID(Longs.fromByteArray(observationDomainID));
// set header
int offset = HEADER_LENGTH;
while ((mh.getLength() - offset) > 0) {
byte[] subData = new byte[mh.getLength() - offset];
System.arraycopy(data, offset, subData, 0, subData.length);
SetHeader sh = SetHeader.parse(subData);
mh.getSetHeaders().add(sh);
offset += sh.getLength();
}
if ((mh.getLength() - offset) != 0) {
LOGGER.log(Level.INFO, "Unused bytes: " + (mh.getLength() - offset));
}
return mh;
} catch (Exception e) {
throw new HeaderException("Parse error: " + e.getMessage());
}
}
public byte[] getBytes() throws HeaderException {
try {
byte[] data = new byte[length];
// version number
System.arraycopy(Shorts.toByteArray((short) versionNumber), 0, data, 0, 2);
// length
System.arraycopy(Shorts.toByteArray((short) length), 0, data, 2, 2);
// export time
System.arraycopy(Ints.toByteArray((int) exportTime.getTime() / 1000), 0, data, 4, 4);
// sequence number
System.arraycopy(Ints.toByteArray((int) sequenceNumber), 0, data, 8, 4);
// observation domain id
System.arraycopy(Ints.toByteArray((int) observationDomainID), 0, data, 12, 4);
// set header
int offset = HEADER_LENGTH;
for (SetHeader sh : setHeaders) {
byte[] temp = sh.getBytes();
System.arraycopy(temp, 0, data, offset, temp.length);
offset += temp.length;
}
return data;
} catch (Exception e) {
e.printStackTrace();
throw new HeaderException("Error while generating the bytes: " + e.getMessage());
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[MessageHeader]: ");
sb.append("Version Number: ");
sb.append(versionNumber);
sb.append(", ");
sb.append("Length: ");
sb.append(length);
sb.append(", ");
sb.append("Export time: ");
sb.append(exportTime);
sb.append(", ");
sb.append("Sequence number: ");
sb.append(sequenceNumber);
sb.append(", ");
sb.append("Observation Domain ID: ");
sb.append(observationDomainID);
sb.append(", ");
sb.append("SetHeaders: ");
sb.append(setHeaders.size());
sb.append(", ");
for (SetHeader sh : setHeaders) {
sb.append(sh);
sb.append(", ");
}
return sb.toString();
}
}