mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-17 02:11:38 +02:00
Improve the resiliency of the packet deserialization code.
Packet deserializers now check for malformed input while reading the byte stream. Deserializers are re-implemented as functions that take a byte array and return a packet object. The old IPacket.deserialize(...) methods have been deprecated with the goal of eventually moving to immutable packet objects. Unit tests have been implemented for all Deserializer functions. ONOS-1589 Change-Id: I9073d5e6e7991e15d43830cfd810989256b71c56
This commit is contained in:
parent
08e457ab8b
commit
2a65575cf8
@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.onosproject.bgprouter;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.ICMP;
|
||||
import org.onlab.packet.IPv4;
|
||||
@ -36,6 +34,8 @@ import org.onosproject.routing.config.RoutingConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class IcmpHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IcmpHandler.class);
|
||||
@ -100,7 +100,7 @@ public class IcmpHandler {
|
||||
icmpReplyIpv4.setTtl((byte) 64);
|
||||
icmpReplyIpv4.setChecksum((short) 0);
|
||||
|
||||
ICMP icmpReply = (ICMP) icmpRequestIpv4.getPayload().clone();
|
||||
ICMP icmpReply = new ICMP();
|
||||
icmpReply.setIcmpType(ICMP.TYPE_ECHO_REPLY);
|
||||
icmpReply.setIcmpCode(ICMP.SUBTYPE_ECHO_REPLY);
|
||||
icmpReply.setChecksum((short) 0);
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.onosproject.segmentrouting;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onlab.packet.ICMP;
|
||||
import org.onlab.packet.IPv4;
|
||||
@ -33,6 +31,9 @@ import org.onosproject.net.packet.OutboundPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class IcmpHandler {
|
||||
@ -109,7 +110,7 @@ public class IcmpHandler {
|
||||
icmpReplyIpv4.setTtl((byte) 64);
|
||||
icmpReplyIpv4.setChecksum((short) 0);
|
||||
|
||||
ICMP icmpReply = (ICMP) icmpRequestIpv4.getPayload().clone();
|
||||
ICMP icmpReply = new ICMP();
|
||||
icmpReply.setIcmpType(ICMP.TYPE_ECHO_REPLY);
|
||||
icmpReply.setIcmpCode(ICMP.SUBTYPE_ECHO_REPLY);
|
||||
icmpReply.setChecksum((short) 0);
|
||||
|
@ -49,8 +49,14 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.expectLastCall;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class HostMonitorTest {
|
||||
|
||||
@ -151,10 +157,9 @@ public class HostMonitorTest {
|
||||
assertEquals(portNum, oi.port());
|
||||
|
||||
// Check the output packet is correct (well the important bits anyway)
|
||||
Ethernet eth = new Ethernet();
|
||||
final byte[] pktData = new byte[packet.data().remaining()];
|
||||
packet.data().get(pktData);
|
||||
eth.deserialize(pktData, 0, pktData.length);
|
||||
Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
|
||||
assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID());
|
||||
ARP arp = (ARP) eth.getPayload();
|
||||
assertArrayEquals(SOURCE_ADDR.toOctets(),
|
||||
@ -220,10 +225,9 @@ public class HostMonitorTest {
|
||||
assertEquals(portNum, oi.port());
|
||||
|
||||
// Check the output packet is correct (well the important bits anyway)
|
||||
Ethernet eth = new Ethernet();
|
||||
final byte[] pktData = new byte[packet.data().remaining()];
|
||||
packet.data().get(pktData);
|
||||
eth.deserialize(pktData, 0, pktData.length);
|
||||
Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length);
|
||||
assertEquals(vlan, eth.getVlanID());
|
||||
ARP arp = (ARP) eth.getPayload();
|
||||
assertArrayEquals(SOURCE_ADDR.toOctets(),
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.onosproject.openflow.controller;
|
||||
|
||||
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onosproject.core.Permission;
|
||||
import org.projectfloodlight.openflow.protocol.OFPacketIn;
|
||||
@ -26,6 +26,8 @@ import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
|
||||
import org.projectfloodlight.openflow.protocol.match.MatchField;
|
||||
import org.projectfloodlight.openflow.types.OFBufferId;
|
||||
import org.projectfloodlight.openflow.types.OFPort;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.Collections;
|
||||
@ -97,11 +99,12 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
|
||||
public Ethernet parsed() {
|
||||
checkPermission(Permission.PACKET_READ);
|
||||
|
||||
Ethernet eth = new Ethernet();
|
||||
try {
|
||||
eth.deserialize(pktin.getData(), 0, pktin.getData().length);
|
||||
return eth;
|
||||
} catch (BufferUnderflowException | NullPointerException e) {
|
||||
return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
|
||||
} catch (BufferUnderflowException | NullPointerException |
|
||||
DeserializationException e) {
|
||||
Logger log = LoggerFactory.getLogger(getClass());
|
||||
log.warn("packet deserialization problem");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.onosproject.provider.of.packet.impl;
|
||||
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.flow.instructions.Instruction;
|
||||
import org.onosproject.net.flow.instructions.Instruction.Type;
|
||||
@ -23,8 +25,9 @@ import org.onosproject.net.packet.DefaultPacketContext;
|
||||
import org.onosproject.net.packet.InboundPacket;
|
||||
import org.onosproject.net.packet.OutboundPacket;
|
||||
import org.onosproject.openflow.controller.OpenFlowPacketContext;
|
||||
import org.onlab.packet.Ethernet;
|
||||
import org.projectfloodlight.openflow.types.OFPort;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -33,6 +36,8 @@ import java.util.List;
|
||||
*/
|
||||
public class OpenFlowCorePacketContext extends DefaultPacketContext {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(OpenFlowCorePacketContext.class);
|
||||
|
||||
private final OpenFlowPacketContext ofPktCtx;
|
||||
|
||||
/**
|
||||
@ -57,12 +62,15 @@ public class OpenFlowCorePacketContext extends DefaultPacketContext {
|
||||
if (outPacket() == null) {
|
||||
sendPacket(null);
|
||||
} else {
|
||||
Ethernet eth = new Ethernet();
|
||||
eth.deserialize(outPacket().data().array(), 0,
|
||||
outPacket().data().array().length);
|
||||
sendPacket(eth);
|
||||
try {
|
||||
Ethernet eth = Ethernet.deserializer()
|
||||
.deserialize(outPacket().data().array(), 0,
|
||||
outPacket().data().array().length);
|
||||
sendPacket(eth);
|
||||
} catch (DeserializationException e) {
|
||||
log.warn("Unable to deserialize packet");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,11 @@
|
||||
<artifactId>onlab-junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty</artifactId>
|
||||
|
@ -21,6 +21,8 @@ package org.onlab.packet;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
@ -35,6 +37,8 @@ public class ARP extends BasePacket {
|
||||
public static final short OP_RARP_REQUEST = 0x3;
|
||||
public static final short OP_RARP_REPLY = 0x4;
|
||||
|
||||
public static final short INITIAL_HEADER_LENGTH = 8;
|
||||
|
||||
protected short hardwareType;
|
||||
protected short protocolType;
|
||||
protected byte hardwareAddressLength;
|
||||
@ -247,7 +251,7 @@ public class ARP extends BasePacket {
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.hardwareType = bb.getShort();
|
||||
this.protocolType = bb.getShort();
|
||||
@ -386,10 +390,50 @@ public class ARP extends BasePacket {
|
||||
arp.setTargetHardwareAddress(request.getSourceMACAddress());
|
||||
|
||||
arp.setTargetProtocolAddress(((ARP) request.getPayload())
|
||||
.getSenderProtocolAddress());
|
||||
.getSenderProtocolAddress());
|
||||
arp.setSenderProtocolAddress(srcIp.toInt());
|
||||
|
||||
eth.setPayload(arp);
|
||||
return eth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for ARP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<ARP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, INITIAL_HEADER_LENGTH);
|
||||
|
||||
ARP arp = new ARP();
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
arp.setHardwareType(bb.getShort());
|
||||
arp.setProtocolType(bb.getShort());
|
||||
|
||||
byte hwAddressLength = bb.get();
|
||||
arp.setHardwareAddressLength(hwAddressLength);
|
||||
|
||||
byte protocolAddressLength = bb.get();
|
||||
arp.setProtocolAddressLength(protocolAddressLength);
|
||||
arp.setOpCode(bb.getShort());
|
||||
|
||||
// Check we have enough space for the addresses
|
||||
checkHeaderLength(length, INITIAL_HEADER_LENGTH +
|
||||
2 * hwAddressLength +
|
||||
2 * protocolAddressLength);
|
||||
|
||||
arp.senderHardwareAddress = new byte[0xff & hwAddressLength];
|
||||
bb.get(arp.senderHardwareAddress, 0, arp.senderHardwareAddress.length);
|
||||
arp.senderProtocolAddress = new byte[0xff & protocolAddressLength];
|
||||
bb.get(arp.senderProtocolAddress, 0, arp.senderProtocolAddress.length);
|
||||
arp.targetHardwareAddress = new byte[0xff & hwAddressLength];
|
||||
bb.get(arp.targetHardwareAddress, 0, arp.targetHardwareAddress.length);
|
||||
arp.targetProtocolAddress = new byte[0xff & protocolAddressLength];
|
||||
bb.get(arp.targetProtocolAddress, 0, arp.targetProtocolAddress.length);
|
||||
|
||||
return arp;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -429,33 +431,9 @@ public class DHCP extends BasePacket {
|
||||
return data;
|
||||
}
|
||||
|
||||
protected void writeString(final String string, final ByteBuffer bb,
|
||||
final int maxLength) {
|
||||
if (string == null) {
|
||||
for (int i = 0; i < maxLength; ++i) {
|
||||
bb.put((byte) 0x0);
|
||||
}
|
||||
} else {
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
bytes = string.getBytes("ascii");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Failure encoding server name", e);
|
||||
}
|
||||
int writeLength = bytes.length;
|
||||
if (writeLength > maxLength) {
|
||||
writeLength = maxLength;
|
||||
}
|
||||
bb.put(bytes, 0, writeLength);
|
||||
for (int i = writeLength; i < maxLength; ++i) {
|
||||
bb.put((byte) 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
if (bb.remaining() < DHCP.MIN_HEADER_LENGTH) {
|
||||
return this;
|
||||
@ -529,7 +507,31 @@ public class DHCP extends BasePacket {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected String readString(final ByteBuffer bb, final int maxLength) {
|
||||
protected void writeString(final String string, final ByteBuffer bb,
|
||||
final int maxLength) {
|
||||
if (string == null) {
|
||||
for (int i = 0; i < maxLength; ++i) {
|
||||
bb.put((byte) 0x0);
|
||||
}
|
||||
} else {
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
bytes = string.getBytes("ascii");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Failure encoding server name", e);
|
||||
}
|
||||
int writeLength = bytes.length;
|
||||
if (writeLength > maxLength) {
|
||||
writeLength = maxLength;
|
||||
}
|
||||
bb.put(bytes, 0, writeLength);
|
||||
for (int i = writeLength; i < maxLength; ++i) {
|
||||
bb.put((byte) 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String readString(final ByteBuffer bb, final int maxLength) {
|
||||
final byte[] bytes = new byte[maxLength];
|
||||
bb.get(bytes);
|
||||
String result = null;
|
||||
@ -540,4 +542,84 @@ public class DHCP extends BasePacket {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for DHCP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<DHCP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, MIN_HEADER_LENGTH);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
DHCP dhcp = new DHCP();
|
||||
|
||||
dhcp.opCode = bb.get();
|
||||
dhcp.hardwareType = bb.get();
|
||||
dhcp.hardwareAddressLength = bb.get();
|
||||
dhcp.hops = bb.get();
|
||||
dhcp.transactionId = bb.getInt();
|
||||
dhcp.seconds = bb.getShort();
|
||||
dhcp.flags = bb.getShort();
|
||||
dhcp.clientIPAddress = bb.getInt();
|
||||
dhcp.yourIPAddress = bb.getInt();
|
||||
dhcp.serverIPAddress = bb.getInt();
|
||||
dhcp.gatewayIPAddress = bb.getInt();
|
||||
final int hardwareAddressLength = 0xff & dhcp.hardwareAddressLength;
|
||||
dhcp.clientHardwareAddress = new byte[hardwareAddressLength];
|
||||
|
||||
bb.get(dhcp.clientHardwareAddress);
|
||||
for (int i = hardwareAddressLength; i < 16; ++i) {
|
||||
bb.get();
|
||||
}
|
||||
dhcp.serverName = readString(bb, 64);
|
||||
dhcp.bootFileName = readString(bb, 128);
|
||||
// read the magic cookie
|
||||
// magic cookie
|
||||
bb.get();
|
||||
bb.get();
|
||||
bb.get();
|
||||
bb.get();
|
||||
|
||||
// read options
|
||||
boolean foundEndOptionsMarker = false;
|
||||
while (bb.hasRemaining()) {
|
||||
final DHCPOption option = new DHCPOption();
|
||||
int code = 0xff & bb.get(); // convert signed byte to int in range
|
||||
// [0,255]
|
||||
option.setCode((byte) code);
|
||||
if (code == 0) {
|
||||
// skip these
|
||||
continue;
|
||||
} else if (code != 255) {
|
||||
if (bb.hasRemaining()) {
|
||||
final int l = 0xff & bb.get(); // convert signed byte to
|
||||
// int in range [0,255]
|
||||
option.setLength((byte) l);
|
||||
if (bb.remaining() >= l) {
|
||||
final byte[] optionData = new byte[l];
|
||||
bb.get(optionData);
|
||||
option.setData(optionData);
|
||||
dhcp.options.add(option);
|
||||
} else {
|
||||
throw new DeserializationException(
|
||||
"Buffer underflow while reading DHCP option");
|
||||
}
|
||||
}
|
||||
} else if (code == 255) {
|
||||
// remaining bytes are supposed to be 0, but ignore them just in
|
||||
// case
|
||||
foundEndOptionsMarker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundEndOptionsMarker) {
|
||||
throw new DeserializationException("DHCP End options marker was missing");
|
||||
}
|
||||
|
||||
return dhcp;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ package org.onlab.packet;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -30,6 +32,7 @@ public class Data extends BasePacket {
|
||||
*
|
||||
*/
|
||||
public Data() {
|
||||
data = new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,7 +66,7 @@ public class Data extends BasePacket {
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
this.data = Arrays.copyOfRange(data, offset, data.length);
|
||||
return this;
|
||||
}
|
||||
@ -103,4 +106,27 @@ public class Data extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for generic payload data.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Data> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
// Allow zero-length data for now
|
||||
if (length == 0) {
|
||||
return new Data();
|
||||
}
|
||||
|
||||
checkInput(data, offset, length, 1);
|
||||
|
||||
Data dataObject = new Data();
|
||||
|
||||
dataObject.data = Arrays.copyOfRange(data, offset, data.length);
|
||||
|
||||
return dataObject;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
/**
|
||||
* Signals that an error occurred during deserialization of a packet.
|
||||
*/
|
||||
public class DeserializationException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new deserialization exception with the given message.
|
||||
*
|
||||
* @param message exception message
|
||||
*/
|
||||
public DeserializationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
36
utils/misc/src/main/java/org/onlab/packet/Deserializer.java
Normal file
36
utils/misc/src/main/java/org/onlab/packet/Deserializer.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
/**
|
||||
* Function to deserialize a packet from a byte-based input stream.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Deserializer<U extends IPacket> {
|
||||
|
||||
/**
|
||||
* Deserialize a packet object from a byte array.
|
||||
*
|
||||
* @param data input array to take packet bytes from
|
||||
* @param offset index where this packet header begins in the byte array
|
||||
* @param length length of the packet header
|
||||
* @return a deserialized packet object
|
||||
* @throws DeserializationException if the packet cannot be deserialized
|
||||
* from the input
|
||||
*/
|
||||
U deserialize(byte[] data, int offset, int length) throws DeserializationException;
|
||||
}
|
@ -93,25 +93,27 @@ public class EthType {
|
||||
|
||||
public static enum EtherType {
|
||||
|
||||
ARP(0x806, "arp", ARP.class),
|
||||
RARP(0x8035, "rarp", null),
|
||||
IPV4(0x800, "ipv4", IPv4.class),
|
||||
IPV6(0x86dd, "ipv6", IPv6.class),
|
||||
LLDP(0x88cc, "lldp", LLDP.class),
|
||||
VLAN(0x8100, "vlan", null),
|
||||
BDDP(0x8942, "bddp", LLDP.class),
|
||||
MPLS_UNICAST(0x8847, "mpls_unicast", null),
|
||||
MPLS_MULTICAST(0x8848, "mpls_unicast", null);
|
||||
ARP(0x806, "arp", ARP.class, org.onlab.packet.ARP.deserializer()),
|
||||
RARP(0x8035, "rarp", null, org.onlab.packet.ARP.deserializer()),
|
||||
IPV4(0x800, "ipv4", IPv4.class, org.onlab.packet.IPv4.deserializer()),
|
||||
IPV6(0x86dd, "ipv6", IPv6.class, org.onlab.packet.IPv6.deserializer()),
|
||||
LLDP(0x88cc, "lldp", LLDP.class, org.onlab.packet.LLDP.deserializer()),
|
||||
VLAN(0x8100, "vlan", null, null),
|
||||
BDDP(0x8942, "bddp", LLDP.class, org.onlab.packet.LLDP.deserializer()),
|
||||
MPLS_UNICAST(0x8847, "mpls_unicast", null, org.onlab.packet.MPLS.deserializer()),
|
||||
MPLS_MULTICAST(0x8848, "mpls_unicast", null, org.onlab.packet.MPLS.deserializer());
|
||||
|
||||
|
||||
private final Class clazz;
|
||||
private EthType ethType;
|
||||
private String type;
|
||||
private Deserializer<?> deserializer;
|
||||
|
||||
EtherType(int ethType, String type, Class clazz) {
|
||||
EtherType(int ethType, String type, Class clazz, Deserializer deserializer) {
|
||||
this.ethType = new EthType(ethType);
|
||||
this.type = type;
|
||||
this.clazz = clazz;
|
||||
this.deserializer = deserializer;
|
||||
}
|
||||
|
||||
public EthType ethType() {
|
||||
@ -127,6 +129,8 @@ public class EthType {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
public Deserializer<?> deserializer() {
|
||||
return deserializer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,14 @@
|
||||
|
||||
package org.onlab.packet;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onlab.packet.PacketUtils.checkHeaderLength;
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -42,15 +43,21 @@ public class Ethernet extends BasePacket {
|
||||
public static final short MPLS_UNICAST = EthType.MPLS_UNICAST;
|
||||
public static final short MPLS_MULTICAST = EthType.MPLS_MULTICAST;
|
||||
|
||||
|
||||
public static final short VLAN_UNTAGGED = (short) 0xffff;
|
||||
|
||||
public static final short ETHERNET_HEADER_LENGTH = 14; // bytes
|
||||
public static final short VLAN_HEADER_LENGTH = 4; // bytes
|
||||
|
||||
public static final short DATALAYER_ADDRESS_LENGTH = 6; // bytes
|
||||
public static final Map<Short, Class<? extends IPacket>> ETHER_TYPE_CLASS_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
private static final Map<Short, Deserializer<? extends IPacket>> ETHERTYPE_DESERIALIZER_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EthType.EtherType ethType : EthType.EtherType.values()) {
|
||||
if (ethType.clazz() != null) {
|
||||
ETHER_TYPE_CLASS_MAP.put(ethType.ethType().toShort(), ethType.clazz());
|
||||
ETHERTYPE_DESERIALIZER_MAP.put(ethType.ethType().toShort(), ethType.deserializer());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -300,7 +307,7 @@ public class Ethernet extends BasePacket {
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
if (length <= 0) {
|
||||
return null;
|
||||
}
|
||||
@ -331,21 +338,19 @@ public class Ethernet extends BasePacket {
|
||||
this.etherType = ethType;
|
||||
|
||||
IPacket payload;
|
||||
if (Ethernet.ETHER_TYPE_CLASS_MAP.containsKey(this.etherType)) {
|
||||
final Class<? extends IPacket> clazz = Ethernet.ETHER_TYPE_CLASS_MAP
|
||||
.get(this.etherType);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for Ethernet packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (Ethernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
|
||||
deserializer = Ethernet.ETHERTYPE_DESERIALIZER_MAP.get(ethType);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -567,4 +572,53 @@ public class Ethernet extends BasePacket {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for Ethernet packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Ethernet> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, ETHERNET_HEADER_LENGTH);
|
||||
|
||||
byte[] addressBuffer = new byte[DATALAYER_ADDRESS_LENGTH];
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
Ethernet eth = new Ethernet();
|
||||
// Read destination MAC address into buffer
|
||||
bb.get(addressBuffer);
|
||||
eth.setDestinationMACAddress(addressBuffer);
|
||||
|
||||
// Read source MAC address into buffer
|
||||
bb.get(addressBuffer);
|
||||
eth.setSourceMACAddress(addressBuffer);
|
||||
|
||||
short ethType = bb.getShort();
|
||||
if (ethType == TYPE_VLAN) {
|
||||
checkHeaderLength(length, ETHERNET_HEADER_LENGTH + VLAN_HEADER_LENGTH);
|
||||
final short tci = bb.getShort();
|
||||
eth.setPriorityCode((byte) (tci >> 13 & 0x07));
|
||||
eth.setVlanID((short) (tci & 0x0fff));
|
||||
ethType = bb.getShort();
|
||||
} else {
|
||||
eth.setVlanID(Ethernet.VLAN_UNTAGGED);
|
||||
}
|
||||
eth.setEtherType(ethType);
|
||||
|
||||
IPacket payload;
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (Ethernet.ETHERTYPE_DESERIALIZER_MAP.containsKey(ethType)) {
|
||||
deserializer = Ethernet.ETHERTYPE_DESERIALIZER_MAP.get(ethType);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
payload.setParent(eth);
|
||||
eth.setPayload(payload);
|
||||
|
||||
return eth;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ package org.onlab.packet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
* Implements ICMP packet format.
|
||||
*
|
||||
@ -33,6 +35,8 @@ public class ICMP extends BasePacket {
|
||||
public static final byte TYPE_ECHO_REPLY = 0x00;
|
||||
public static final byte SUBTYPE_ECHO_REPLY = 0x00;
|
||||
|
||||
public static final short ICMP_HEADER_LENGTH = 4;
|
||||
|
||||
/**
|
||||
* @return the icmpType
|
||||
*/
|
||||
@ -134,6 +138,21 @@ public class ICMP extends BasePacket {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.icmpType = bb.get();
|
||||
this.icmpCode = bb.get();
|
||||
this.checksum = bb.getShort();
|
||||
|
||||
this.payload = new Data();
|
||||
this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@ -178,18 +197,27 @@ public class ICMP extends BasePacket {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.icmpType = bb.get();
|
||||
this.icmpCode = bb.get();
|
||||
this.checksum = bb.getShort();
|
||||
/**
|
||||
* Deserializer function for ICMP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<ICMP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, ICMP_HEADER_LENGTH);
|
||||
|
||||
this.payload = new Data();
|
||||
this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
ICMP icmp = new ICMP();
|
||||
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
icmp.icmpType = bb.get();
|
||||
icmp.icmpCode = bb.get();
|
||||
icmp.checksum = bb.getShort();
|
||||
|
||||
icmp.payload = Data.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
icmp.payload.setParent(icmp);
|
||||
return icmp;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,13 @@ import org.onlab.packet.ndp.NeighborSolicitation;
|
||||
import org.onlab.packet.ndp.Redirect;
|
||||
import org.onlab.packet.ndp.RouterAdvertisement;
|
||||
import org.onlab.packet.ndp.RouterSolicitation;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 packet format. (RFC 4443)
|
||||
*/
|
||||
@ -96,15 +99,15 @@ public class ICMP6 extends BasePacket {
|
||||
/** Unrecognized IPv6 option encountered. */
|
||||
public static final byte IPV6_OPT_ERR = (byte) 0x01;
|
||||
|
||||
public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP =
|
||||
public static final Map<Byte, Deserializer<? extends IPacket>> TYPE_DESERIALIZER_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
static {
|
||||
ICMP6.PROTOCOL_CLASS_MAP.put(ICMP6.ROUTER_SOLICITATION, RouterSolicitation.class);
|
||||
ICMP6.PROTOCOL_CLASS_MAP.put(ICMP6.ROUTER_ADVERTISEMENT, RouterAdvertisement.class);
|
||||
ICMP6.PROTOCOL_CLASS_MAP.put(ICMP6.NEIGHBOR_SOLICITATION, NeighborSolicitation.class);
|
||||
ICMP6.PROTOCOL_CLASS_MAP.put(ICMP6.NEIGHBOR_ADVERTISEMENT, NeighborAdvertisement.class);
|
||||
ICMP6.PROTOCOL_CLASS_MAP.put(ICMP6.REDIRECT, Redirect.class);
|
||||
ICMP6.TYPE_DESERIALIZER_MAP.put(ICMP6.ROUTER_SOLICITATION, RouterSolicitation.deserializer());
|
||||
ICMP6.TYPE_DESERIALIZER_MAP.put(ICMP6.ROUTER_ADVERTISEMENT, RouterAdvertisement.deserializer());
|
||||
ICMP6.TYPE_DESERIALIZER_MAP.put(ICMP6.NEIGHBOR_SOLICITATION, NeighborSolicitation.deserializer());
|
||||
ICMP6.TYPE_DESERIALIZER_MAP.put(ICMP6.NEIGHBOR_ADVERTISEMENT, NeighborAdvertisement.deserializer());
|
||||
ICMP6.TYPE_DESERIALIZER_MAP.put(ICMP6.REDIRECT, Redirect.deserializer());
|
||||
}
|
||||
|
||||
protected byte icmpType;
|
||||
@ -261,6 +264,31 @@ public class ICMP6 extends BasePacket {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.icmpType = bb.get();
|
||||
this.icmpCode = bb.get();
|
||||
this.checksum = bb.getShort();
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (ICMP6.TYPE_DESERIALIZER_MAP.containsKey(icmpType)) {
|
||||
deserializer = TYPE_DESERIALIZER_MAP.get(icmpType);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@ -305,31 +333,34 @@ public class ICMP6 extends BasePacket {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.icmpType = bb.get();
|
||||
this.icmpCode = bb.get();
|
||||
this.checksum = bb.getShort();
|
||||
/**
|
||||
* Deserializer function for ICMPv6 packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<ICMP6> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
IPacket payload;
|
||||
if (ICMP6.PROTOCOL_CLASS_MAP.containsKey(this.icmpType)) {
|
||||
final Class<? extends IPacket> clazz = ICMP6.PROTOCOL_CLASS_MAP
|
||||
.get(this.icmpType);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for ICMP6 packet", e);
|
||||
ICMP6 icmp6 = new ICMP6();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
icmp6.icmpType = bb.get();
|
||||
icmp6.icmpCode = bb.get();
|
||||
icmp6.checksum = bb.getShort();
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (ICMP6.TYPE_DESERIALIZER_MAP.containsKey(icmp6.icmpType)) {
|
||||
deserializer = TYPE_DESERIALIZER_MAP.get(icmp6.icmpType);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
} else {
|
||||
payload = new Data();
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
icmp6.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
icmp6.payload.setParent(icmp6);
|
||||
|
||||
return this;
|
||||
return icmp6;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,11 @@ public interface IPacket {
|
||||
/**
|
||||
* Deserializes this packet layer and all possible payloads.
|
||||
*
|
||||
* NOTE: This method has been deprecated and will be removed in a future
|
||||
* release. It is now recommended to use the Deserializer function provided
|
||||
* by the deserialize() method on each packet to deserialize them. The
|
||||
* Deserializer functions are robust to malformed input.
|
||||
*
|
||||
* @param data bytes to deserialize
|
||||
* @param offset
|
||||
* offset to start deserializing from
|
||||
@ -71,6 +76,7 @@ public interface IPacket {
|
||||
* length of the data to deserialize
|
||||
* @return the deserialized data
|
||||
*/
|
||||
@Deprecated
|
||||
IPacket deserialize(byte[] data, int offset, int length);
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,8 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -32,19 +34,21 @@ public class IPv4 extends BasePacket {
|
||||
public static final byte PROTOCOL_ICMP = 0x1;
|
||||
public static final byte PROTOCOL_TCP = 0x6;
|
||||
public static final byte PROTOCOL_UDP = 0x11;
|
||||
public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP =
|
||||
public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
static {
|
||||
IPv4.PROTOCOL_CLASS_MAP.put(IPv4.PROTOCOL_ICMP, ICMP.class);
|
||||
IPv4.PROTOCOL_CLASS_MAP.put(IPv4.PROTOCOL_TCP, TCP.class);
|
||||
IPv4.PROTOCOL_CLASS_MAP.put(IPv4.PROTOCOL_UDP, UDP.class);
|
||||
IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_ICMP, ICMP.deserializer());
|
||||
IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer());
|
||||
IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer());
|
||||
}
|
||||
|
||||
private static final byte DSCP_MASK = 0x3f;
|
||||
private static final byte DSCP_OFFSET = 2;
|
||||
private static final byte ECN_MASK = 0x3;
|
||||
|
||||
private static final short HEADER_LENGTH = 20;
|
||||
|
||||
protected byte version;
|
||||
protected byte headerLength;
|
||||
protected byte diffServ;
|
||||
@ -414,7 +418,7 @@ s */
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
short sscratch;
|
||||
|
||||
@ -439,29 +443,26 @@ s */
|
||||
bb.get(this.options);
|
||||
}
|
||||
|
||||
IPacket payload;
|
||||
if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
|
||||
final Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP
|
||||
.get(this.protocol);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for IPv4 packet", e);
|
||||
}
|
||||
} else {
|
||||
payload = new Data();
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
if (this.totalLength != length) {
|
||||
this.isTruncated = true;
|
||||
} else {
|
||||
this.isTruncated = false;
|
||||
}
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(this.protocol)) {
|
||||
deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(this.protocol);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -669,4 +670,60 @@ s */
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for IPv4 packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<IPv4> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
IPv4 ipv4 = new IPv4();
|
||||
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
byte versionByte = bb.get();
|
||||
ipv4.headerLength = (byte) (versionByte & 0xf);
|
||||
ipv4.setVersion((byte) (versionByte >> 4 & 0xf));
|
||||
ipv4.setDiffServ(bb.get());
|
||||
ipv4.totalLength = bb.getShort();
|
||||
ipv4.identification = bb.getShort();
|
||||
short flagsFragment = bb.getShort();
|
||||
ipv4.flags = (byte) (flagsFragment >> 13 & 0x7);
|
||||
ipv4.fragmentOffset = (short) (flagsFragment & 0x1fff);
|
||||
ipv4.ttl = bb.get();
|
||||
ipv4.protocol = bb.get();
|
||||
ipv4.checksum = bb.getShort();
|
||||
ipv4.sourceAddress = bb.getInt();
|
||||
ipv4.destinationAddress = bb.getInt();
|
||||
|
||||
if (ipv4.headerLength > 5) {
|
||||
checkHeaderLength(length, ipv4.headerLength * 4);
|
||||
|
||||
int optionsLength = (ipv4.headerLength - 5) * 4;
|
||||
ipv4.options = new byte[optionsLength];
|
||||
bb.get(ipv4.options);
|
||||
}
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv4.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv4.protocol)) {
|
||||
deserializer = IPv4.PROTOCOL_DESERIALIZER_MAP.get(ipv4.protocol);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
ipv4.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
ipv4.payload.setParent(ipv4);
|
||||
|
||||
if (ipv4.totalLength != length) {
|
||||
ipv4.isTruncated = true;
|
||||
} else {
|
||||
ipv4.isTruncated = false;
|
||||
}
|
||||
|
||||
return ipv4;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,17 @@ import org.onlab.packet.ipv6.Authentication;
|
||||
import org.onlab.packet.ipv6.DestinationOptions;
|
||||
import org.onlab.packet.ipv6.EncapSecurityPayload;
|
||||
import org.onlab.packet.ipv6.Fragment;
|
||||
import org.onlab.packet.ipv6.IExtensionHeader;
|
||||
import org.onlab.packet.ipv6.HopByHopOptions;
|
||||
import org.onlab.packet.ipv6.IExtensionHeader;
|
||||
import org.onlab.packet.ipv6.Routing;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements IPv6 packet format. (RFC 2460)
|
||||
*/
|
||||
@ -47,19 +50,19 @@ public class IPv6 extends BasePacket implements IExtensionHeader {
|
||||
public static final byte PROTOCOL_DSTOPT = 0x3C;
|
||||
|
||||
|
||||
public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP =
|
||||
public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP =
|
||||
new HashMap<>();
|
||||
|
||||
static {
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_ICMP6, ICMP6.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_TCP, TCP.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_UDP, UDP.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_HOPOPT, HopByHopOptions.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_ROUTING, Routing.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_FRAG, Fragment.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_ESP, EncapSecurityPayload.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_AH, Authentication.class);
|
||||
IPv6.PROTOCOL_CLASS_MAP.put(IPv6.PROTOCOL_DSTOPT, DestinationOptions.class);
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_ICMP6, ICMP6.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_TCP, TCP.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_UDP, UDP.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_HOPOPT, HopByHopOptions.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_ROUTING, Routing.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_FRAG, Fragment.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_ESP, EncapSecurityPayload.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_AH, Authentication.deserializer());
|
||||
IPv6.PROTOCOL_DESERIALIZER_MAP.put(IPv6.PROTOCOL_DSTOPT, DestinationOptions.deserializer());
|
||||
}
|
||||
|
||||
protected byte version;
|
||||
@ -256,22 +259,19 @@ public class IPv6 extends BasePacket implements IExtensionHeader {
|
||||
bb.get(this.sourceAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
bb.get(this.destinationAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
|
||||
IPacket payload;
|
||||
if (IPv6.PROTOCOL_CLASS_MAP.containsKey(this.nextHeader)) {
|
||||
final Class<? extends IPacket> clazz = IPv6.PROTOCOL_CLASS_MAP
|
||||
.get(this.nextHeader);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for IPv6 packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(this.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(this.nextHeader);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -343,4 +343,42 @@ public class IPv6 extends BasePacket implements IExtensionHeader {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for IPv6 packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<IPv6> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, FIXED_HEADER_LENGTH);
|
||||
|
||||
IPv6 ipv6 = new IPv6();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
int iscratch = bb.getInt();
|
||||
|
||||
ipv6.version = (byte) (iscratch >> 28 & 0xf);
|
||||
ipv6.trafficClass = (byte) (iscratch >> 20 & 0xff);
|
||||
ipv6.flowLabel = iscratch & 0xfffff;
|
||||
ipv6.payloadLength = bb.getShort();
|
||||
ipv6.nextHeader = bb.get();
|
||||
ipv6.hopLimit = bb.get();
|
||||
bb.get(ipv6.sourceAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
bb.get(ipv6.destinationAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(ipv6.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(ipv6.nextHeader);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
ipv6.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
ipv6.payload.setParent(ipv6);
|
||||
|
||||
return ipv6;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ package org.onlab.packet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
* This class represents an Link Local Control header that is used in Ethernet
|
||||
* 802.3.
|
||||
@ -27,6 +29,9 @@ import java.nio.ByteBuffer;
|
||||
*
|
||||
*/
|
||||
public class LLC extends BasePacket {
|
||||
|
||||
public static final byte LLC_HEADER_LENGTH = 3;
|
||||
|
||||
private byte dsap = 0;
|
||||
private byte ssap = 0;
|
||||
private byte ctrl = 0;
|
||||
@ -67,11 +72,31 @@ public class LLC extends BasePacket {
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.dsap = bb.get();
|
||||
this.ssap = bb.get();
|
||||
this.ctrl = bb.get();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for LLC packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<LLC> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, LLC_HEADER_LENGTH);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
LLC llc = new LLC();
|
||||
|
||||
llc.dsap = bb.get();
|
||||
llc.ssap = bb.get();
|
||||
llc.ctrl = bb.get();
|
||||
|
||||
return llc;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,26 @@
|
||||
package org.onlab.packet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LLDP extends BasePacket {
|
||||
public static final byte CHASSIS_TLV_TYPE = 1;
|
||||
public static final short CHASSIS_TLV_SIZE = 7;
|
||||
public static final byte CHASSIS_TLV_SUBTYPE = 4;
|
||||
|
||||
public static final byte PORT_TLV_TYPE = 2;
|
||||
public static final short PORT_TLV_SIZE = 5;
|
||||
public static final byte PORT_TLV_SUBTYPE = 2;
|
||||
|
||||
public static final byte TTL_TLV_TYPE = 3;
|
||||
public static final short TTL_TLV_SIZE = 2;
|
||||
|
||||
protected LLDPTLV chassisId;
|
||||
protected LLDPTLV portId;
|
||||
protected LLDPTLV ttl;
|
||||
@ -34,7 +47,7 @@ public class LLDP extends BasePacket {
|
||||
protected short ethType;
|
||||
|
||||
public LLDP() {
|
||||
this.optionalTLVList = new ArrayList<LLDPTLV>();
|
||||
this.optionalTLVList = new LinkedList<>();
|
||||
this.ethType = Ethernet.TYPE_LLDP;
|
||||
}
|
||||
|
||||
@ -134,11 +147,15 @@ public class LLDP extends BasePacket {
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
LLDPTLV tlv;
|
||||
do {
|
||||
tlv = new LLDPOrganizationalTLV().deserialize(bb);
|
||||
try {
|
||||
tlv = new LLDPOrganizationalTLV().deserialize(bb);
|
||||
} catch (DeserializationException e) {
|
||||
break;
|
||||
}
|
||||
|
||||
// if there was a failure to deserialize stop processing TLVs
|
||||
if (tlv == null) {
|
||||
@ -227,4 +244,57 @@ public class LLDP extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for LLDP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<LLDP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, 0);
|
||||
|
||||
LLDP lldp = new LLDP();
|
||||
|
||||
int currentIndex = 0;
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
LLDPTLV tlv;
|
||||
do {
|
||||
// Each new TLV must be a minimum of 2 bytes
|
||||
// (containing the type and length fields).
|
||||
currentIndex += 2;
|
||||
checkHeaderLength(length, currentIndex);
|
||||
|
||||
tlv = new LLDPOrganizationalTLV().deserialize(bb);
|
||||
|
||||
// if there was a failure to deserialize stop processing TLVs
|
||||
if (tlv == null) {
|
||||
break;
|
||||
}
|
||||
switch (tlv.getType()) {
|
||||
case 0x0:
|
||||
// can throw this one away, it's just an end delimiter
|
||||
break;
|
||||
case 0x1:
|
||||
lldp.chassisId = tlv;
|
||||
break;
|
||||
case 0x2:
|
||||
lldp.portId = tlv;
|
||||
break;
|
||||
case 0x3:
|
||||
lldp.ttl = tlv;
|
||||
break;
|
||||
default:
|
||||
lldp.optionalTLVList.add(tlv);
|
||||
break;
|
||||
}
|
||||
|
||||
currentIndex += tlv.getLength();
|
||||
} while (tlv.getType() != 0);
|
||||
|
||||
return lldp;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -154,10 +154,15 @@ public class LLDPOrganizationalTLV extends LLDPTLV {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LLDPTLV deserialize(final ByteBuffer bb) {
|
||||
LLDPTLV tlv = super.deserialize(bb);
|
||||
if (tlv.getType() != LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
|
||||
return tlv;
|
||||
public LLDPTLV deserialize(final ByteBuffer bb) throws DeserializationException {
|
||||
super.deserialize(bb);
|
||||
if (this.getType() != LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.getLength() <= OUI_LENGTH + SUBTYPE_LENGTH) {
|
||||
throw new DeserializationException(
|
||||
"TLV length is less than required for organizational TLV");
|
||||
}
|
||||
|
||||
final ByteBuffer optionalField = ByteBuffer.wrap(this.value);
|
||||
|
@ -95,18 +95,23 @@ public class LLDPTLV {
|
||||
return data;
|
||||
}
|
||||
|
||||
public LLDPTLV deserialize(final ByteBuffer bb) {
|
||||
short sscratch;
|
||||
sscratch = bb.getShort();
|
||||
this.type = (byte) (sscratch >> 9 & 0x7f);
|
||||
this.length = (short) (sscratch & 0x1ff);
|
||||
public LLDPTLV deserialize(final ByteBuffer bb) throws DeserializationException {
|
||||
if (bb.remaining() < 2) {
|
||||
throw new DeserializationException(
|
||||
"Not enough bytes to deserialize TLV type and length");
|
||||
}
|
||||
short typeLength;
|
||||
typeLength = bb.getShort();
|
||||
this.type = (byte) (typeLength >> 9 & 0x7f);
|
||||
this.length = (short) (typeLength & 0x1ff);
|
||||
|
||||
if (this.length > 0) {
|
||||
this.value = new byte[this.length];
|
||||
|
||||
// if there is an underrun just toss the TLV
|
||||
if (bb.remaining() < this.length) {
|
||||
return null;
|
||||
throw new DeserializationException(
|
||||
"Remaining bytes are less then the length of the TLV");
|
||||
}
|
||||
bb.get(this.value);
|
||||
}
|
||||
|
@ -4,16 +4,19 @@ import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
public class MPLS extends BasePacket {
|
||||
public static final int ADDRESS_LENGTH = 4;
|
||||
public static final int HEADER_LENGTH = 4;
|
||||
|
||||
public static final byte PROTOCOL_IPV4 = 0x1;
|
||||
public static final byte PROTOCOL_MPLS = 0x6;
|
||||
public static final Map<Byte, Class<? extends IPacket>> PROTOCOL_CLASS_MAP;
|
||||
static Map<Byte, Deserializer<? extends IPacket>> protocolDeserializerMap
|
||||
= new HashMap<>();
|
||||
|
||||
static {
|
||||
PROTOCOL_CLASS_MAP = new HashMap<Byte, Class<? extends IPacket>>();
|
||||
PROTOCOL_CLASS_MAP.put(PROTOCOL_IPV4, IPv4.class);
|
||||
PROTOCOL_CLASS_MAP.put(PROTOCOL_MPLS, MPLS.class);
|
||||
protocolDeserializerMap.put(PROTOCOL_IPV4, IPv4.deserializer());
|
||||
protocolDeserializerMap.put(PROTOCOL_MPLS, MPLS.deserializer());
|
||||
}
|
||||
|
||||
protected int label; //20bits
|
||||
@ -59,19 +62,18 @@ public class MPLS extends BasePacket {
|
||||
this.bos = (byte) (mplsheader & 0x000000ff);
|
||||
this.protocol = (this.bos == 1) ? PROTOCOL_IPV4 : PROTOCOL_MPLS;
|
||||
|
||||
IPacket payload;
|
||||
if (IPv4.PROTOCOL_CLASS_MAP.containsKey(this.protocol)) {
|
||||
Class<? extends IPacket> clazz = IPv4.PROTOCOL_CLASS_MAP.get(this.protocol);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error parsing payload for MPLS packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (protocolDeserializerMap.containsKey(this.protocol)) {
|
||||
deserializer = protocolDeserializerMap.get(this.protocol);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -112,4 +114,34 @@ public class MPLS extends BasePacket {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for MPLS packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<MPLS> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
MPLS mpls = new MPLS();
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
int mplsheader = bb.getInt();
|
||||
mpls.label = ((mplsheader & 0xfffff000) >>> 12);
|
||||
mpls.bos = (byte) ((mplsheader & 0x00000100) >> 8);
|
||||
mpls.ttl = (byte) (mplsheader & 0x000000ff);
|
||||
mpls.protocol = (mpls.bos == 1) ? PROTOCOL_IPV4 : PROTOCOL_MPLS;
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (protocolDeserializerMap.containsKey(mpls.protocol)) {
|
||||
deserializer = protocolDeserializerMap.get(mpls.protocol);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
mpls.payload = deserializer.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
mpls.payload.setParent(mpls);
|
||||
|
||||
return mpls;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
84
utils/misc/src/main/java/org/onlab/packet/PacketUtils.java
Normal file
84
utils/misc/src/main/java/org/onlab/packet/PacketUtils.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Utilities for working with packet headers.
|
||||
*/
|
||||
public final class PacketUtils {
|
||||
|
||||
private PacketUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the length of the input buffer is appropriate given the offset and
|
||||
* length parameters.
|
||||
*
|
||||
* @param byteLength length of the input buffer array
|
||||
* @param offset offset given to begin reading bytes from
|
||||
* @param length length given to read up until
|
||||
* @throws DeserializationException if the input parameters don't match up (i.e
|
||||
* we can't read that many bytes from the buffer at the given offest)
|
||||
*/
|
||||
public static void checkBufferLength(int byteLength, int offset, int length)
|
||||
throws DeserializationException {
|
||||
boolean ok = (offset >= 0 && offset < byteLength);
|
||||
ok = ok & (length >= 0 && offset + length <= byteLength);
|
||||
|
||||
if (!ok) {
|
||||
throw new DeserializationException("Unable to read " + length + " bytes from a "
|
||||
+ byteLength + " byte array starting at offset " + offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that there are enough bytes in the buffer to read some number of
|
||||
* bytes that we need to read a full header.
|
||||
*
|
||||
* @param givenLength given size of the buffer
|
||||
* @param requiredLength number of bytes we need to read some header fully
|
||||
* @throws DeserializationException if there aren't enough bytes
|
||||
*/
|
||||
public static void checkHeaderLength(int givenLength, int requiredLength)
|
||||
throws DeserializationException {
|
||||
if (requiredLength > givenLength) {
|
||||
throw new DeserializationException(requiredLength
|
||||
+ " bytes are needed to continue deserialization, however only "
|
||||
+ givenLength + " remain in buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the input parameters are sane and there's enough bytes to read
|
||||
* the required length.
|
||||
*
|
||||
* @param data input byte buffer
|
||||
* @param offset offset of the start of the header
|
||||
* @param length length given to deserialize the header
|
||||
* @param requiredLength length needed to deserialize header
|
||||
* @throws DeserializationException if we're unable to deserialize the
|
||||
* packet based on the input parameters
|
||||
*/
|
||||
public static void checkInput(byte[] data, int offset, int length, int requiredLength)
|
||||
throws DeserializationException {
|
||||
checkNotNull(data);
|
||||
checkBufferLength(data.length, offset, length);
|
||||
checkHeaderLength(length, requiredLength);
|
||||
}
|
||||
}
|
@ -20,11 +20,16 @@ package org.onlab.packet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
* Implements TCP packet format.
|
||||
*/
|
||||
|
||||
public class TCP extends BasePacket {
|
||||
|
||||
private static final short TCP_HEADER_LENGTH = 20;
|
||||
|
||||
protected short sourcePort;
|
||||
protected short destinationPort;
|
||||
protected int sequence;
|
||||
@ -339,6 +344,40 @@ public class TCP extends BasePacket {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.sourcePort = bb.getShort();
|
||||
this.destinationPort = bb.getShort();
|
||||
this.sequence = bb.getInt();
|
||||
this.acknowledge = bb.getInt();
|
||||
this.flags = bb.getShort();
|
||||
this.dataOffset = (byte) (this.flags >> 12 & 0xf);
|
||||
this.flags = (short) (this.flags & 0x1ff);
|
||||
this.windowSize = bb.getShort();
|
||||
this.checksum = bb.getShort();
|
||||
this.urgentPointer = bb.getShort();
|
||||
if (this.dataOffset > 5) {
|
||||
int optLength = (this.dataOffset << 2) - 20;
|
||||
if (bb.limit() < bb.position() + optLength) {
|
||||
optLength = bb.limit() - bb.position();
|
||||
}
|
||||
try {
|
||||
this.options = new byte[optLength];
|
||||
bb.get(this.options, 0, optLength);
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.payload = new Data();
|
||||
this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@ -384,37 +423,39 @@ public class TCP extends BasePacket {
|
||||
&& (this.dataOffset == 5 || this.options.equals(other.options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.sourcePort = bb.getShort();
|
||||
this.destinationPort = bb.getShort();
|
||||
this.sequence = bb.getInt();
|
||||
this.acknowledge = bb.getInt();
|
||||
this.flags = bb.getShort();
|
||||
this.dataOffset = (byte) (this.flags >> 12 & 0xf);
|
||||
this.flags = (short) (this.flags & 0x1ff);
|
||||
this.windowSize = bb.getShort();
|
||||
this.checksum = bb.getShort();
|
||||
this.urgentPointer = bb.getShort();
|
||||
if (this.dataOffset > 5) {
|
||||
int optLength = (this.dataOffset << 2) - 20;
|
||||
if (bb.limit() < bb.position() + optLength) {
|
||||
optLength = bb.limit() - bb.position();
|
||||
}
|
||||
try {
|
||||
this.options = new byte[optLength];
|
||||
bb.get(this.options, 0, optLength);
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Deserializer function for TCP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<TCP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, TCP_HEADER_LENGTH);
|
||||
|
||||
this.payload = new Data();
|
||||
this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
TCP tcp = new TCP();
|
||||
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
tcp.sourcePort = bb.getShort();
|
||||
tcp.destinationPort = bb.getShort();
|
||||
tcp.sequence = bb.getInt();
|
||||
tcp.acknowledge = bb.getInt();
|
||||
tcp.flags = bb.getShort();
|
||||
tcp.dataOffset = (byte) (tcp.flags >> 12 & 0xf);
|
||||
tcp.flags = (short) (tcp.flags & 0x1ff);
|
||||
tcp.windowSize = bb.getShort();
|
||||
tcp.checksum = bb.getShort();
|
||||
tcp.urgentPointer = bb.getShort();
|
||||
if (tcp.dataOffset > 5) {
|
||||
int optLength = (tcp.dataOffset << 2) - 20;
|
||||
checkHeaderLength(length, TCP_HEADER_LENGTH + tcp.dataOffset);
|
||||
tcp.options = new byte[optLength];
|
||||
bb.get(tcp.options, 0, optLength);
|
||||
}
|
||||
|
||||
tcp.payload = Data.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
tcp.payload.setParent(tcp);
|
||||
return tcp;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -22,23 +22,27 @@ import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
public class UDP extends BasePacket {
|
||||
public static final Map<Short, Class<? extends IPacket>> DECODE_MAP =
|
||||
public static final Map<Short, Deserializer<? extends IPacket>> PORT_DESERIALIZER_MAP =
|
||||
new HashMap<>();
|
||||
public static final short DHCP_SERVER_PORT = (short) 67;
|
||||
public static final short DHCP_CLIENT_PORT = (short) 68;
|
||||
|
||||
private static final short UDP_HEADER_LENGTH = 8;
|
||||
|
||||
static {
|
||||
/*
|
||||
* Disable DHCP until the deserialize code is hardened to deal with
|
||||
* garbage input
|
||||
*/
|
||||
UDP.DECODE_MAP.put(UDP.DHCP_SERVER_PORT, DHCP.class);
|
||||
UDP.DECODE_MAP.put(UDP.DHCP_CLIENT_PORT, DHCP.class);
|
||||
UDP.PORT_DESERIALIZER_MAP.put(UDP.DHCP_SERVER_PORT, DHCP.deserializer());
|
||||
UDP.PORT_DESERIALIZER_MAP.put(UDP.DHCP_CLIENT_PORT, DHCP.deserializer());
|
||||
|
||||
}
|
||||
|
||||
@ -192,6 +196,34 @@ public class UDP extends BasePacket {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.sourcePort = bb.getShort();
|
||||
this.destinationPort = bb.getShort();
|
||||
this.length = bb.getShort();
|
||||
this.checksum = bb.getShort();
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (UDP.PORT_DESERIALIZER_MAP.containsKey(this.destinationPort)) {
|
||||
deserializer = UDP.PORT_DESERIALIZER_MAP.get(this.destinationPort);
|
||||
} else if (UDP.PORT_DESERIALIZER_MAP.containsKey(this.sourcePort)) {
|
||||
deserializer = UDP.PORT_DESERIALIZER_MAP.get(this.sourcePort);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
@ -240,35 +272,36 @@ public class UDP extends BasePacket {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket deserialize(final byte[] data, final int offset,
|
||||
final int length) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
this.sourcePort = bb.getShort();
|
||||
this.destinationPort = bb.getShort();
|
||||
this.length = bb.getShort();
|
||||
this.checksum = bb.getShort();
|
||||
/**
|
||||
* Deserializer function for UDP packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<UDP> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, UDP_HEADER_LENGTH);
|
||||
|
||||
if (UDP.DECODE_MAP.containsKey(this.destinationPort)) {
|
||||
try {
|
||||
this.payload = UDP.DECODE_MAP.get(this.destinationPort)
|
||||
.getConstructor().newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Failure instantiating class", e);
|
||||
UDP udp = new UDP();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
udp.sourcePort = bb.getShort();
|
||||
udp.destinationPort = bb.getShort();
|
||||
udp.length = bb.getShort();
|
||||
udp.checksum = bb.getShort();
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (UDP.PORT_DESERIALIZER_MAP.containsKey(udp.destinationPort)) {
|
||||
deserializer = UDP.PORT_DESERIALIZER_MAP.get(udp.destinationPort);
|
||||
} else if (UDP.PORT_DESERIALIZER_MAP.containsKey(udp.sourcePort)) {
|
||||
deserializer = UDP.PORT_DESERIALIZER_MAP.get(udp.sourcePort);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
} else if (UDP.DECODE_MAP.containsKey(this.sourcePort)) {
|
||||
try {
|
||||
this.payload = UDP.DECODE_MAP.get(this.sourcePort)
|
||||
.getConstructor().newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Failure instantiating class", e);
|
||||
}
|
||||
} else {
|
||||
this.payload = new Data();
|
||||
}
|
||||
this.payload = this.payload.deserialize(data, bb.position(), bb.limit()
|
||||
- bb.position());
|
||||
this.payload.setParent(this);
|
||||
return this;
|
||||
|
||||
udp.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
udp.payload.setParent(udp);
|
||||
return udp;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,16 @@ package org.onlab.packet.ipv6;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.IPv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements IPv6 authentication extension header format. (RFC 4302)
|
||||
*/
|
||||
@ -186,22 +191,20 @@ public class Authentication extends BasePacket implements IExtensionHeader {
|
||||
this.integrityCheck = new byte[icvLength];
|
||||
bb.get(this.integrityCheck, 0, icvLength);
|
||||
|
||||
IPacket payload;
|
||||
if (IPv6.PROTOCOL_CLASS_MAP.containsKey(this.nextHeader)) {
|
||||
final Class<? extends IPacket> clazz = IPv6.PROTOCOL_CLASS_MAP
|
||||
.get(this.nextHeader);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for Authentication packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(this.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(this.nextHeader);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -259,4 +262,39 @@ public class Authentication extends BasePacket implements IExtensionHeader {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for authentication headers.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Authentication> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, FIXED_HEADER_LENGTH);
|
||||
|
||||
Authentication authentication = new Authentication();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
authentication.nextHeader = bb.get();
|
||||
authentication.payloadLength = bb.get();
|
||||
bb.getShort();
|
||||
authentication.securityParamIndex = bb.getInt();
|
||||
authentication.sequence = bb.getInt();
|
||||
int icvLength = (authentication.payloadLength + MINUS) * LENGTH_UNIT - FIXED_HEADER_LENGTH;
|
||||
authentication.integrityCheck = new byte[icvLength];
|
||||
bb.get(authentication.integrityCheck, 0, icvLength);
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(authentication.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(authentication.nextHeader);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
authentication.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
authentication.payload.setParent(authentication);
|
||||
|
||||
return authentication;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,17 @@ package org.onlab.packet.ipv6;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.IPv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkHeaderLength;
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Base class for hop-by-hop options and destination options.
|
||||
*/
|
||||
@ -151,22 +156,19 @@ public class BaseOptions extends BasePacket implements IExtensionHeader {
|
||||
this.options = new byte[optionLength];
|
||||
bb.get(this.options, 0, optionLength);
|
||||
|
||||
IPacket payload;
|
||||
if (IPv6.PROTOCOL_CLASS_MAP.containsKey(this.nextHeader)) {
|
||||
final Class<? extends IPacket> clazz = IPv6.PROTOCOL_CLASS_MAP
|
||||
.get(this.nextHeader);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for BaseOptions packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(this.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(this.nextHeader);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -219,4 +221,40 @@ public class BaseOptions extends BasePacket implements IExtensionHeader {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for IPv6 base options.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<BaseOptions> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, FIXED_HEADER_LENGTH);
|
||||
|
||||
BaseOptions baseOptions = new BaseOptions();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
baseOptions.nextHeader = bb.get();
|
||||
baseOptions.headerExtLength = bb.get();
|
||||
int optionLength =
|
||||
FIXED_OPTIONS_LENGTH + LENGTH_UNIT * baseOptions.headerExtLength;
|
||||
|
||||
checkHeaderLength(bb.remaining(), optionLength);
|
||||
|
||||
baseOptions.options = new byte[optionLength];
|
||||
bb.get(baseOptions.options, 0, optionLength);
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(baseOptions.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(baseOptions.nextHeader);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
baseOptions.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
baseOptions.payload.setParent(baseOptions);
|
||||
|
||||
return baseOptions;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,14 @@ package org.onlab.packet.ipv6;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.IPv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements IPv6 Encapsulating Security Payload (ESP) extension header format.
|
||||
* (RFC 4303)
|
||||
@ -113,7 +117,7 @@ public class EncapSecurityPayload extends BasePacket {
|
||||
|
||||
this.payload = new Data();
|
||||
this.payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
@ -158,4 +162,27 @@ public class EncapSecurityPayload extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for encapsulated security payload headers.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<EncapSecurityPayload> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
EncapSecurityPayload encapSecurityPayload = new EncapSecurityPayload();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
encapSecurityPayload.securityParamIndex = bb.getInt();
|
||||
encapSecurityPayload.sequence = bb.getInt();
|
||||
|
||||
encapSecurityPayload.payload = Data.deserializer().deserialize(
|
||||
data, bb.position(), bb.limit() - bb.position());
|
||||
encapSecurityPayload.payload.setParent(encapSecurityPayload);
|
||||
|
||||
return encapSecurityPayload;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,15 @@ package org.onlab.packet.ipv6;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.IPv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements IPv6 fragment extension header format. (RFC 2460)
|
||||
*/
|
||||
@ -149,22 +153,19 @@ public class Fragment extends BasePacket implements IExtensionHeader {
|
||||
this.moreFragment = (byte) (sscratch & 0x1);
|
||||
this.identification = bb.getInt();
|
||||
|
||||
IPacket payload;
|
||||
if (IPv6.PROTOCOL_CLASS_MAP.containsKey(this.nextHeader)) {
|
||||
final Class<? extends IPacket> clazz = IPv6.PROTOCOL_CLASS_MAP
|
||||
.get(this.nextHeader);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for Fragment packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(this.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(this.nextHeader);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -216,4 +217,37 @@ public class Fragment extends BasePacket implements IExtensionHeader {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for fragment headers.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Fragment> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
Fragment fragment = new Fragment();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
fragment.nextHeader = bb.get();
|
||||
bb.get();
|
||||
short sscratch = bb.getShort();
|
||||
fragment.fragmentOffset = (short) (sscratch >> 3 & 0x1fff);
|
||||
fragment.moreFragment = (byte) (sscratch & 0x1);
|
||||
fragment.identification = bb.getInt();
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(fragment.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(fragment.nextHeader);
|
||||
} else {
|
||||
deserializer = Data.deserializer();
|
||||
}
|
||||
fragment.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
fragment.payload.setParent(fragment);
|
||||
|
||||
return fragment;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,17 @@ package org.onlab.packet.ipv6;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.IPv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkHeaderLength;
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements IPv6 routing extension header format. (RFC 2460)
|
||||
*/
|
||||
@ -175,22 +180,19 @@ public class Routing extends BasePacket implements IExtensionHeader {
|
||||
this.routingData = new byte[dataLength];
|
||||
bb.get(this.routingData, 0, dataLength);
|
||||
|
||||
IPacket payload;
|
||||
if (IPv6.PROTOCOL_CLASS_MAP.containsKey(this.nextHeader)) {
|
||||
final Class<? extends IPacket> clazz = IPv6.PROTOCOL_CLASS_MAP
|
||||
.get(this.nextHeader);
|
||||
try {
|
||||
payload = clazz.newInstance();
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Error parsing payload for Routing packet", e);
|
||||
}
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(this.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(this.nextHeader);
|
||||
} else {
|
||||
payload = new Data();
|
||||
deserializer = new Data().deserializer();
|
||||
}
|
||||
try {
|
||||
this.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
} catch (DeserializationException e) {
|
||||
return this;
|
||||
}
|
||||
this.payload = payload.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
this.payload.setParent(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -248,4 +250,42 @@ public class Routing extends BasePacket implements IExtensionHeader {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for routing headers.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Routing> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, FIXED_HEADER_LENGTH);
|
||||
|
||||
Routing routing = new Routing();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
routing.nextHeader = bb.get();
|
||||
routing.headerExtLength = bb.get();
|
||||
routing.routingType = bb.get();
|
||||
routing.segmentsLeft = bb.get();
|
||||
int dataLength =
|
||||
FIXED_ROUTING_DATA_LENGTH + LENGTH_UNIT * routing.headerExtLength;
|
||||
|
||||
checkHeaderLength(bb.remaining(), dataLength);
|
||||
|
||||
routing.routingData = new byte[dataLength];
|
||||
bb.get(routing.routingData, 0, dataLength);
|
||||
|
||||
Deserializer<? extends IPacket> deserializer;
|
||||
if (IPv6.PROTOCOL_DESERIALIZER_MAP.containsKey(routing.nextHeader)) {
|
||||
deserializer = IPv6.PROTOCOL_DESERIALIZER_MAP.get(routing.nextHeader);
|
||||
} else {
|
||||
deserializer = new Data().deserializer();
|
||||
}
|
||||
routing.payload = deserializer.deserialize(data, bb.position(),
|
||||
bb.limit() - bb.position());
|
||||
routing.payload.setParent(routing);
|
||||
|
||||
return routing;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.Ip6Address;
|
||||
|
||||
@ -23,6 +24,8 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861).
|
||||
*/
|
||||
@ -238,4 +241,36 @@ public class NeighborAdvertisement extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for neighbor advertisement packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<NeighborAdvertisement> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
NeighborAdvertisement neighborAdvertisement = new NeighborAdvertisement();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
int iscratch;
|
||||
|
||||
iscratch = bb.getInt();
|
||||
neighborAdvertisement.routerFlag = (byte) (iscratch >> 31 & 0x1);
|
||||
neighborAdvertisement.solicitedFlag = (byte) (iscratch >> 30 & 0x1);
|
||||
neighborAdvertisement.overrideFlag = (byte) (iscratch >> 29 & 0x1);
|
||||
bb.get(neighborAdvertisement.targetAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
|
||||
NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
|
||||
for (NeighborDiscoveryOptions.Option option : options.options()) {
|
||||
neighborAdvertisement.addOption(option.type(), option.data());
|
||||
}
|
||||
|
||||
return neighborAdvertisement;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,17 @@
|
||||
*/
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.IPacket;
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Neighbor Discovery Protocol packet options.
|
||||
@ -33,6 +37,11 @@ public class NeighborDiscoveryOptions extends BasePacket {
|
||||
public static final byte TYPE_REDIRECTED_HEADER = 4;
|
||||
public static final byte TYPE_MTU = 5;
|
||||
|
||||
public static final byte INITIAL_HEADER_REQUIRED = 2;
|
||||
|
||||
private static final String BUFFER_UNDERFLOW_ERROR =
|
||||
"Not enough bytes in buffer to read option";
|
||||
|
||||
private final List<Option> options = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@ -187,7 +196,7 @@ public class NeighborDiscoveryOptions extends BasePacket {
|
||||
}
|
||||
byte lengthField = bb.get();
|
||||
int dataLength = lengthField * 8; // The data length field is in
|
||||
// unit of 8 octets
|
||||
// unit of 8 octets
|
||||
|
||||
// Exclude the type and length fields
|
||||
if (dataLength < 2) {
|
||||
@ -229,4 +238,44 @@ public class NeighborDiscoveryOptions extends BasePacket {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Deserializer<NeighborDiscoveryOptions> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, INITIAL_HEADER_REQUIRED);
|
||||
|
||||
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
NeighborDiscoveryOptions ndo = new NeighborDiscoveryOptions();
|
||||
|
||||
ndo.options.clear();
|
||||
|
||||
//
|
||||
// Deserialize all options
|
||||
//
|
||||
while (bb.hasRemaining()) {
|
||||
byte type = bb.get();
|
||||
if (!bb.hasRemaining()) {
|
||||
throw new DeserializationException(BUFFER_UNDERFLOW_ERROR);
|
||||
}
|
||||
byte lengthField = bb.get();
|
||||
int dataLength = lengthField * 8; // The data length field is in
|
||||
// unit of 8 octets
|
||||
|
||||
// Exclude the type and length fields
|
||||
if (dataLength < 2) {
|
||||
break;
|
||||
}
|
||||
dataLength -= 2;
|
||||
|
||||
if (bb.remaining() < dataLength) {
|
||||
throw new DeserializationException(BUFFER_UNDERFLOW_ERROR);
|
||||
}
|
||||
byte[] optionData = new byte[dataLength];
|
||||
bb.get(optionData, 0, optionData.length);
|
||||
ndo.addOption(type, optionData);
|
||||
}
|
||||
|
||||
return ndo;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.Ip6Address;
|
||||
|
||||
@ -23,6 +24,8 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Neighbor Solicitation packet format. (RFC 4861)
|
||||
*/
|
||||
@ -157,4 +160,31 @@ public class NeighborSolicitation extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for neighbor solicitation packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<NeighborSolicitation> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
NeighborSolicitation neighborSolicitation = new NeighborSolicitation();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
bb.getInt();
|
||||
bb.get(neighborSolicitation.targetAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
|
||||
NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
|
||||
for (NeighborDiscoveryOptions.Option option : options.options()) {
|
||||
neighborSolicitation.addOption(option.type(), option.data());
|
||||
}
|
||||
|
||||
return neighborSolicitation;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
import org.onlab.packet.Ip6Address;
|
||||
|
||||
@ -23,6 +24,8 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Redirect packet format. (RFC 4861)
|
||||
*/
|
||||
@ -188,4 +191,33 @@ public class Redirect extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for redirect packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<Redirect> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
Redirect redirect = new Redirect();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
bb.getInt();
|
||||
|
||||
bb.get(redirect.targetAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
bb.get(redirect.destinationAddress, 0, Ip6Address.BYTE_LENGTH);
|
||||
|
||||
NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
|
||||
for (NeighborDiscoveryOptions.Option option : options.options()) {
|
||||
redirect.addOption(option.type(), option.data());
|
||||
}
|
||||
|
||||
return redirect;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,14 @@
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Router Advertisement packet format. (RFC 4861)
|
||||
*/
|
||||
@ -284,4 +287,37 @@ public class RouterAdvertisement extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for router advertisement packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<RouterAdvertisement> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
RouterAdvertisement routerAdvertisement = new RouterAdvertisement();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
int bscratch;
|
||||
|
||||
routerAdvertisement.currentHopLimit = bb.get();
|
||||
bscratch = bb.get();
|
||||
routerAdvertisement.mFlag = (byte) ((bscratch >> 7) & 0x1);
|
||||
routerAdvertisement.oFlag = (byte) ((bscratch >> 6) & 0x1);
|
||||
routerAdvertisement.routerLifetime = bb.getShort();
|
||||
routerAdvertisement.reachableTime = bb.getInt();
|
||||
routerAdvertisement.retransmitTimer = bb.getInt();
|
||||
|
||||
NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
|
||||
for (NeighborDiscoveryOptions.Option option : options.options()) {
|
||||
routerAdvertisement.addOption(option.type(), option.data());
|
||||
}
|
||||
|
||||
return routerAdvertisement;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,19 +16,21 @@
|
||||
package org.onlab.packet.ndp;
|
||||
|
||||
import org.onlab.packet.BasePacket;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static org.onlab.packet.PacketUtils.checkInput;
|
||||
|
||||
/**
|
||||
* Implements ICMPv6 Router Solicitation packet format. (RFC 4861)
|
||||
*/
|
||||
public class RouterSolicitation extends BasePacket {
|
||||
public static final byte HEADER_LENGTH = 4; // bytes
|
||||
|
||||
private final NeighborDiscoveryOptions options =
|
||||
new NeighborDiscoveryOptions();
|
||||
private final NeighborDiscoveryOptions options = new NeighborDiscoveryOptions();
|
||||
|
||||
/**
|
||||
* Gets the Neighbor Discovery Protocol packet options.
|
||||
@ -122,4 +124,30 @@ public class RouterSolicitation extends BasePacket {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializer function for router solicitation packets.
|
||||
*
|
||||
* @return deserializer function
|
||||
*/
|
||||
public static Deserializer<RouterSolicitation> deserializer() {
|
||||
return (data, offset, length) -> {
|
||||
checkInput(data, offset, length, HEADER_LENGTH);
|
||||
|
||||
RouterSolicitation routerSolicitation = new RouterSolicitation();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
|
||||
|
||||
bb.getInt();
|
||||
|
||||
NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
|
||||
.deserialize(data, bb.position(), bb.limit() - bb.position());
|
||||
|
||||
for (NeighborDiscoveryOptions.Option option : options.options()) {
|
||||
routerSolicitation.addOption(option.type(), option.data());
|
||||
}
|
||||
|
||||
return routerSolicitation;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
88
utils/misc/src/test/java/org/onlab/packet/ArpTest.java
Normal file
88
utils/misc/src/test/java/org/onlab/packet/ArpTest.java
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for the ARP class.
|
||||
*/
|
||||
public class ArpTest {
|
||||
|
||||
private Deserializer<ARP> deserializer = ARP.deserializer();
|
||||
|
||||
private final byte hwAddressLength = 6;
|
||||
private final byte protoAddressLength = 4;
|
||||
|
||||
private MacAddress srcMac = MacAddress.valueOf(1);
|
||||
private MacAddress targetMac = MacAddress.valueOf(2);
|
||||
private Ip4Address srcIp = Ip4Address.valueOf(1);
|
||||
private Ip4Address targetIp = Ip4Address.valueOf(2);
|
||||
|
||||
private byte[] byteHeader;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(ARP.INITIAL_HEADER_LENGTH +
|
||||
2 * hwAddressLength + 2 * protoAddressLength);
|
||||
bb.putShort(ARP.HW_TYPE_ETHERNET);
|
||||
bb.putShort(ARP.PROTO_TYPE_IP);
|
||||
bb.put(hwAddressLength);
|
||||
bb.put(protoAddressLength);
|
||||
bb.putShort(ARP.OP_REPLY);
|
||||
|
||||
bb.put(srcMac.toBytes());
|
||||
bb.put(srcIp.toOctets());
|
||||
bb.put(targetMac.toBytes());
|
||||
bb.put(targetIp.toOctets());
|
||||
|
||||
byteHeader = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, byteHeader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
ARP arp = deserializer.deserialize(byteHeader, 0, byteHeader.length);
|
||||
|
||||
assertEquals(ARP.HW_TYPE_ETHERNET, arp.getHardwareType());
|
||||
assertEquals(ARP.PROTO_TYPE_IP, arp.getProtocolType());
|
||||
assertEquals(hwAddressLength, arp.getHardwareAddressLength());
|
||||
assertEquals(protoAddressLength, arp.getProtocolAddressLength());
|
||||
assertEquals(ARP.OP_REPLY, arp.getOpCode());
|
||||
|
||||
assertTrue(Arrays.equals(srcMac.toBytes(), arp.getSenderHardwareAddress()));
|
||||
assertTrue(Arrays.equals(srcIp.toOctets(), arp.getSenderProtocolAddress()));
|
||||
assertTrue(Arrays.equals(targetMac.toBytes(), arp.getTargetHardwareAddress()));
|
||||
assertTrue(Arrays.equals(targetIp.toOctets(), arp.getTargetProtocolAddress()));
|
||||
}
|
||||
}
|
137
utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
Normal file
137
utils/misc/src/test/java/org/onlab/packet/DhcpTest.java
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for DHCP class.
|
||||
*/
|
||||
public class DhcpTest {
|
||||
|
||||
private Deserializer<DHCP> deserializer = DHCP.deserializer();
|
||||
|
||||
private byte opCode = 1;
|
||||
private byte hardwareType = 1;
|
||||
private byte hardwareAddressLength = Ethernet.DATALAYER_ADDRESS_LENGTH;
|
||||
private byte hops = 0;
|
||||
private int transactionId = 0x2ed4eb50;
|
||||
private short seconds = 0;
|
||||
private short flags = 0;
|
||||
private int clientIpAddress = 1;
|
||||
private int yourIpAddress = 2;
|
||||
private int serverIpAddress = 3;
|
||||
private int gatewayIpAddress = 4;
|
||||
private byte[] clientHardwareAddress = MacAddress.valueOf(500).toBytes();
|
||||
private String serverName = "test-server";
|
||||
private String bootFileName = "test-file";
|
||||
|
||||
private String hostName = "test-host";
|
||||
private DHCPOption hostNameOption = new DHCPOption();
|
||||
|
||||
private byte[] byteHeader;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
hostNameOption.setCode((byte) 55);
|
||||
hostNameOption.setLength((byte) hostName.length());
|
||||
hostNameOption.setData(hostName.getBytes(Charsets.US_ASCII));
|
||||
|
||||
// Packet length is the fixed DHCP header plus option length plus an
|
||||
// extra byte to indicate 'end of options'.
|
||||
ByteBuffer bb = ByteBuffer.allocate(DHCP.MIN_HEADER_LENGTH +
|
||||
2 + hostNameOption.getLength() + 1);
|
||||
|
||||
bb.put(opCode);
|
||||
bb.put(hardwareType);
|
||||
bb.put(hardwareAddressLength);
|
||||
bb.put(hops);
|
||||
bb.putInt(transactionId);
|
||||
bb.putShort(seconds);
|
||||
bb.putShort(flags);
|
||||
bb.putInt(clientIpAddress);
|
||||
bb.putInt(yourIpAddress);
|
||||
bb.putInt(serverIpAddress);
|
||||
bb.putInt(gatewayIpAddress);
|
||||
bb.put(clientHardwareAddress);
|
||||
|
||||
// need 16 bytes of zeros to pad out the client hardware address field
|
||||
bb.put(new byte[16 - hardwareAddressLength]);
|
||||
|
||||
// Put server name and pad out to 64 bytes
|
||||
bb.put(serverName.getBytes(Charsets.US_ASCII));
|
||||
bb.put(new byte[64 - serverName.length()]);
|
||||
|
||||
// Put boot file name and pad out to 128 bytes
|
||||
bb.put(bootFileName.getBytes(Charsets.US_ASCII));
|
||||
bb.put(new byte[128 - bootFileName.length()]);
|
||||
|
||||
// Magic cookie
|
||||
bb.put("DHCP".getBytes(Charsets.US_ASCII));
|
||||
|
||||
bb.put(hostNameOption.getCode());
|
||||
bb.put(hostNameOption.getLength());
|
||||
bb.put(hostNameOption.getData());
|
||||
|
||||
// End of options marker
|
||||
bb.put((byte) (0xff & 255));
|
||||
|
||||
byteHeader = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, byteHeader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
DHCP dhcp = deserializer.deserialize(byteHeader, 0, byteHeader.length);
|
||||
|
||||
assertEquals(opCode, dhcp.opCode);
|
||||
assertEquals(hardwareType, dhcp.hardwareType);
|
||||
assertEquals(hardwareAddressLength, dhcp.hardwareAddressLength);
|
||||
assertEquals(hops, dhcp.hops);
|
||||
assertEquals(transactionId, dhcp.transactionId);
|
||||
assertEquals(seconds, dhcp.seconds);
|
||||
assertEquals(flags, dhcp.flags);
|
||||
assertEquals(clientIpAddress, dhcp.clientIPAddress);
|
||||
assertEquals(yourIpAddress, dhcp.yourIPAddress);
|
||||
assertEquals(serverIpAddress, dhcp.serverIPAddress);
|
||||
assertEquals(gatewayIpAddress, dhcp.gatewayIPAddress);
|
||||
assertTrue(Arrays.equals(clientHardwareAddress, dhcp.clientHardwareAddress));
|
||||
|
||||
assertEquals(serverName, dhcp.serverName);
|
||||
assertEquals(bootFileName, dhcp.bootFileName);
|
||||
assertEquals(1, dhcp.options.size());
|
||||
assertEquals(hostNameOption, dhcp.options.get(0));
|
||||
}
|
||||
|
||||
}
|
103
utils/misc/src/test/java/org/onlab/packet/EthernetTest.java
Normal file
103
utils/misc/src/test/java/org/onlab/packet/EthernetTest.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for the Ethernet class.
|
||||
*/
|
||||
public class EthernetTest {
|
||||
|
||||
private MacAddress dstMac;
|
||||
private MacAddress srcMac;
|
||||
private short ethertype = 6;
|
||||
private short vlan = 5;
|
||||
|
||||
private Deserializer<Ethernet> deserializer;
|
||||
|
||||
private byte[] byteHeader;
|
||||
private byte[] vlanByteHeader;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = Ethernet.deserializer();
|
||||
|
||||
byte[] dstMacBytes = {
|
||||
(byte) 0x88, (byte) 0x88, (byte) 0x88, (byte) 0x88, (byte) 0x88,
|
||||
(byte) 0x88 };
|
||||
dstMac = MacAddress.valueOf(dstMacBytes);
|
||||
byte[] srcMacBytes = {
|
||||
(byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa, (byte) 0xaa,
|
||||
(byte) 0xaa };
|
||||
srcMac = MacAddress.valueOf(srcMacBytes);
|
||||
|
||||
// Create Ethernet byte array with no VLAN header
|
||||
ByteBuffer bb = ByteBuffer.allocate(Ethernet.ETHERNET_HEADER_LENGTH);
|
||||
bb.put(dstMacBytes);
|
||||
bb.put(srcMacBytes);
|
||||
bb.putShort(ethertype);
|
||||
|
||||
byteHeader = bb.array();
|
||||
|
||||
// Create Ethernet byte array with a VLAN header
|
||||
bb = ByteBuffer.allocate(Ethernet.ETHERNET_HEADER_LENGTH + Ethernet.VLAN_HEADER_LENGTH);
|
||||
bb.put(dstMacBytes);
|
||||
bb.put(srcMacBytes);
|
||||
bb.putShort(Ethernet.TYPE_VLAN);
|
||||
bb.putShort(vlan);
|
||||
bb.putShort(ethertype);
|
||||
|
||||
vlanByteHeader = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws DeserializationException {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, vlanByteHeader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeNoVlan() throws Exception {
|
||||
Ethernet eth = deserializer.deserialize(byteHeader, 0, byteHeader.length);
|
||||
|
||||
assertEquals(dstMac, eth.getDestinationMAC());
|
||||
assertEquals(srcMac, eth.getSourceMAC());
|
||||
assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID());
|
||||
assertEquals(ethertype, eth.getEtherType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeWithVlan() throws Exception {
|
||||
Ethernet eth = deserializer.deserialize(vlanByteHeader, 0, vlanByteHeader.length);
|
||||
|
||||
assertEquals(dstMac, eth.getDestinationMAC());
|
||||
assertEquals(srcMac, eth.getSourceMAC());
|
||||
assertEquals(vlan, eth.getVlanID());
|
||||
assertEquals(ethertype, eth.getEtherType());
|
||||
}
|
||||
|
||||
}
|
@ -67,13 +67,22 @@ public class ICMP6Test {
|
||||
assertArrayEquals(bytePacket, icmp6.serialize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(ICMP6.deserializer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(ICMP6.deserializer(), bytePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
ICMP6 icmp6 = new ICMP6();
|
||||
icmp6.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
ICMP6 icmp6 = ICMP6.deserializer().deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(icmp6.getIcmpType(), is(ICMP6.ECHO_REQUEST));
|
||||
assertThat(icmp6.getIcmpCode(), is((byte) 0x00));
|
||||
|
70
utils/misc/src/test/java/org/onlab/packet/ICMPTest.java
Normal file
70
utils/misc/src/test/java/org/onlab/packet/ICMPTest.java
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for the ICMP class.
|
||||
*/
|
||||
public class ICMPTest {
|
||||
|
||||
private Deserializer<ICMP> deserializer;
|
||||
|
||||
private byte icmpType = ICMP.TYPE_ECHO_REQUEST;
|
||||
private byte icmpCode = 4;
|
||||
private short checksum = 870;
|
||||
|
||||
private byte[] headerBytes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
deserializer = ICMP.deserializer();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(ICMP.ICMP_HEADER_LENGTH);
|
||||
|
||||
bb.put(icmpType);
|
||||
bb.put(icmpCode);
|
||||
bb.putShort(checksum);
|
||||
|
||||
headerBytes = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, headerBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
ICMP icmp = deserializer.deserialize(headerBytes, 0, headerBytes.length);
|
||||
|
||||
assertEquals(icmpType, icmp.getIcmpType());
|
||||
assertEquals(icmpCode, icmp.getIcmpCode());
|
||||
assertEquals(checksum, icmp.getChecksum());
|
||||
}
|
||||
}
|
99
utils/misc/src/test/java/org/onlab/packet/IPv4Test.java
Normal file
99
utils/misc/src/test/java/org/onlab/packet/IPv4Test.java
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for IPv4 class.
|
||||
*/
|
||||
public class IPv4Test {
|
||||
|
||||
private Deserializer<IPv4> deserializer;
|
||||
|
||||
private byte version = 4;
|
||||
private byte headerLength = 6;
|
||||
private byte diffServ = 2;
|
||||
private short totalLength = 20;
|
||||
private short identification = 1;
|
||||
private byte flags = 1;
|
||||
private short fragmentOffset = 1;
|
||||
private byte ttl = 60;
|
||||
private byte protocol = 4;
|
||||
private short checksum = 4;
|
||||
private int sourceAddress = 1;
|
||||
private int destinationAddress = 2;
|
||||
private byte[] options = new byte[] {0x1, 0x2, 0x3, 0x4};
|
||||
|
||||
private byte[] headerBytes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
deserializer = IPv4.deserializer();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(headerLength * 4);
|
||||
|
||||
bb.put((byte) ((version & 0xf) << 4 | headerLength & 0xf));
|
||||
bb.put(diffServ);
|
||||
bb.putShort(totalLength);
|
||||
bb.putShort(identification);
|
||||
bb.putShort((short) ((flags & 0x7) << 13 | fragmentOffset & 0x1fff));
|
||||
bb.put(ttl);
|
||||
bb.put(protocol);
|
||||
bb.putShort(checksum);
|
||||
bb.putInt(sourceAddress);
|
||||
bb.putInt(destinationAddress);
|
||||
bb.put(options);
|
||||
|
||||
headerBytes = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, headerBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
IPv4 ipv4 = deserializer.deserialize(headerBytes, 0, headerBytes.length);
|
||||
|
||||
assertEquals(version, ipv4.getVersion());
|
||||
assertEquals(headerLength, ipv4.getHeaderLength());
|
||||
assertEquals(diffServ, ipv4.getDiffServ());
|
||||
assertEquals(totalLength, ipv4.getTotalLength());
|
||||
assertEquals(identification, ipv4.getIdentification());
|
||||
assertEquals(flags, ipv4.getFlags());
|
||||
assertEquals(fragmentOffset, ipv4.getFragmentOffset());
|
||||
assertEquals(ttl, ipv4.getTtl());
|
||||
assertEquals(protocol, ipv4.getProtocol());
|
||||
assertEquals(checksum, ipv4.getChecksum());
|
||||
assertEquals(sourceAddress, ipv4.getSourceAddress());
|
||||
assertEquals(destinationAddress, ipv4.getDestinationAddress());
|
||||
assertTrue(ipv4.isTruncated());
|
||||
}
|
||||
}
|
@ -18,14 +18,17 @@
|
||||
|
||||
package org.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for class {@link IPv6}.
|
||||
@ -43,6 +46,8 @@ public class IPv6Test {
|
||||
private static UDP udp;
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<IPv6> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
data = new Data();
|
||||
@ -65,6 +70,11 @@ public class IPv6Test {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = IPv6.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -83,13 +93,26 @@ public class IPv6Test {
|
||||
assertArrayEquals(ipv6.serialize(), bytePacket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
// Run the truncation test only on the IPv6 header
|
||||
byte[] ipv6Header = new byte[IPv6.FIXED_HEADER_LENGTH];
|
||||
ByteBuffer.wrap(bytePacket).get(ipv6Header);
|
||||
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, ipv6Header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
IPv6 ipv6 = new IPv6();
|
||||
ipv6.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
IPv6 ipv6 = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(ipv6.getVersion(), is((byte) 6));
|
||||
assertThat(ipv6.getTrafficClass(), is((byte) 0x93));
|
||||
|
70
utils/misc/src/test/java/org/onlab/packet/LLCTest.java
Normal file
70
utils/misc/src/test/java/org/onlab/packet/LLCTest.java
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for LLC class.
|
||||
*/
|
||||
public class LLCTest {
|
||||
|
||||
private Deserializer<LLC> deserializer;
|
||||
|
||||
private byte dsap = 10;
|
||||
private byte ssap = 20;
|
||||
private byte ctrl = 30;
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
deserializer = LLC.deserializer();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(LLC.LLC_HEADER_LENGTH);
|
||||
|
||||
bb.put(dsap);
|
||||
bb.put(ssap);
|
||||
bb.put(ctrl);
|
||||
|
||||
bytes = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
LLC llc = deserializer.deserialize(bytes, 0, bytes.length);
|
||||
|
||||
assertEquals(dsap, llc.getDsap());
|
||||
assertEquals(ssap, llc.getSsap());
|
||||
assertEquals(ctrl, llc.getCtrl());
|
||||
}
|
||||
}
|
115
utils/misc/src/test/java/org/onlab/packet/LLDPTest.java
Normal file
115
utils/misc/src/test/java/org/onlab/packet/LLDPTest.java
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for the LLDP class.
|
||||
*/
|
||||
public class LLDPTest {
|
||||
|
||||
private Deserializer<LLDP> deserializer;
|
||||
|
||||
private byte[] chassisValue = new byte[] {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
|
||||
private byte[] portValue = new byte[] {0x1, 0x2, 0x3, 0x4, 0x5};
|
||||
private byte[] ttlValue = new byte[] {0x0, 0x20};
|
||||
|
||||
private short optionalTlvSize = 6;
|
||||
private byte[] optionalTlvValue = new byte[] {0x6, 0x5, 0x4, 0x3, 0x2, 0x1};
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
deserializer = LLDP.deserializer();
|
||||
|
||||
// Each TLV is 2 bytes for the type+length, plus the size of the value
|
||||
// There are 2 zero-bytes at the end
|
||||
ByteBuffer bb = ByteBuffer.allocate(2 + LLDP.CHASSIS_TLV_SIZE +
|
||||
2 + LLDP.PORT_TLV_SIZE +
|
||||
2 + LLDP.TTL_TLV_SIZE +
|
||||
2 + optionalTlvSize +
|
||||
2);
|
||||
|
||||
// Chassis TLV
|
||||
bb.putShort(getTypeLength(LLDP.CHASSIS_TLV_TYPE, LLDP.CHASSIS_TLV_SIZE));
|
||||
bb.put(chassisValue);
|
||||
|
||||
// Port TLV
|
||||
bb.putShort(getTypeLength(LLDP.PORT_TLV_TYPE, LLDP.PORT_TLV_SIZE));
|
||||
bb.put(portValue);
|
||||
|
||||
// TTL TLV
|
||||
bb.putShort(getTypeLength(LLDP.TTL_TLV_TYPE, LLDP.TTL_TLV_SIZE));
|
||||
bb.put(ttlValue);
|
||||
|
||||
// Optional TLV
|
||||
bb.putShort(getTypeLength(LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE, optionalTlvSize));
|
||||
bb.put(optionalTlvValue);
|
||||
|
||||
bb.putShort((short) 0);
|
||||
|
||||
bytes = bb.array();
|
||||
|
||||
}
|
||||
|
||||
private short getTypeLength(byte type, short length) {
|
||||
return (short) ((0x7f & type) << 9 | 0x1ff & length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
LLDP lldp = deserializer.deserialize(bytes, 0, bytes.length);
|
||||
|
||||
assertEquals(LLDP.CHASSIS_TLV_TYPE, lldp.getChassisId().getType());
|
||||
assertEquals(LLDP.CHASSIS_TLV_SIZE, lldp.getChassisId().getLength());
|
||||
assertTrue(Arrays.equals(chassisValue, lldp.getChassisId().getValue()));
|
||||
|
||||
assertEquals(LLDP.PORT_TLV_TYPE, lldp.getPortId().getType());
|
||||
assertEquals(LLDP.PORT_TLV_SIZE, lldp.getPortId().getLength());
|
||||
assertTrue(Arrays.equals(portValue, lldp.getPortId().getValue()));
|
||||
|
||||
assertEquals(LLDP.TTL_TLV_TYPE, lldp.getTtl().getType());
|
||||
assertEquals(LLDP.TTL_TLV_SIZE, lldp.getTtl().getLength());
|
||||
assertTrue(Arrays.equals(ttlValue, lldp.getTtl().getValue()));
|
||||
|
||||
assertEquals(1, lldp.getOptionalTLVList().size());
|
||||
LLDPTLV optionalTlv = lldp.getOptionalTLVList().get(0);
|
||||
|
||||
assertEquals(LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE, optionalTlv.getType());
|
||||
assertEquals(optionalTlvSize, optionalTlv.getLength());
|
||||
assertTrue(Arrays.equals(optionalTlvValue, optionalTlv.getValue()));
|
||||
}
|
||||
}
|
74
utils/misc/src/test/java/org/onlab/packet/MplsTest.java
Normal file
74
utils/misc/src/test/java/org/onlab/packet/MplsTest.java
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit tests for MPLS class.
|
||||
*/
|
||||
public class MplsTest {
|
||||
|
||||
private Deserializer<MPLS> deserializer;
|
||||
|
||||
private int label = 1048575;
|
||||
private byte bos = 1;
|
||||
private byte ttl = 20;
|
||||
private byte protocol = MPLS.PROTOCOL_IPV4;
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// Replace normal deserializer map with an empty map. This will cause
|
||||
// the DataDeserializer to be used which will silently handle 0-byte input.
|
||||
MPLS.protocolDeserializerMap = new HashMap<>();
|
||||
|
||||
deserializer = MPLS.deserializer();
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(MPLS.HEADER_LENGTH);
|
||||
bb.putInt(((label & 0x000fffff) << 12) | ((bos & 0x1) << 8 | (ttl & 0xff)));
|
||||
|
||||
bytes = bb.array();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws Exception {
|
||||
MPLS mpls = deserializer.deserialize(bytes, 0, bytes.length);
|
||||
|
||||
assertEquals(label, mpls.label);
|
||||
assertEquals(bos, mpls.bos);
|
||||
assertEquals(ttl, mpls.ttl);
|
||||
assertEquals(protocol, mpls.protocol);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* 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.onlab.packet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static junit.framework.TestCase.fail;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Utilities for testing packet methods.
|
||||
*/
|
||||
public final class PacketTestUtils {
|
||||
|
||||
private PacketTestUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the Deserializer function is resilient to bad input parameters
|
||||
* such as null input, negative offset and length, etc.
|
||||
*
|
||||
* @param deserializer deserializer function to test
|
||||
*/
|
||||
public static void testDeserializeBadInput(Deserializer deserializer) {
|
||||
byte[] bytes = ByteBuffer.allocate(4).array();
|
||||
|
||||
try {
|
||||
deserializer.deserialize(null, 0, 4);
|
||||
fail("NullPointerException was not thrown");
|
||||
} catch (NullPointerException e) {
|
||||
assertTrue(true);
|
||||
} catch (DeserializationException e) {
|
||||
fail("NullPointerException was not thrown");
|
||||
}
|
||||
|
||||
// input byte array length, offset and length don't make sense
|
||||
expectDeserializationException(deserializer, bytes, -1, 0);
|
||||
expectDeserializationException(deserializer, bytes, 0, -1);
|
||||
expectDeserializationException(deserializer, bytes, 0, 5);
|
||||
expectDeserializationException(deserializer, bytes, 2, 3);
|
||||
expectDeserializationException(deserializer, bytes, 5, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the Deserializer function is resilient to truncated input, or
|
||||
* cases where the input byte array does not contain enough bytes to
|
||||
* deserialize the packet.
|
||||
*
|
||||
* @param deserializer deserializer function to test
|
||||
* @param header byte array of a full-size packet
|
||||
*/
|
||||
public static void testDeserializeTruncated(Deserializer deserializer,
|
||||
byte[] header) {
|
||||
byte[] truncated;
|
||||
|
||||
for (int i = 0; i < header.length; i++) {
|
||||
truncated = new byte[i];
|
||||
|
||||
ByteBuffer.wrap(header).get(truncated);
|
||||
|
||||
expectDeserializationException(deserializer, truncated, 0, truncated.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given deserializer function against the given inputs and verify
|
||||
* that a DeserializationException is thrown. The the test will fail if a
|
||||
* DeserializationException is not thrown by the deserializer function.
|
||||
*
|
||||
* @param deserializer deserializer function to test
|
||||
* @param bytes input byte array
|
||||
* @param offset input offset
|
||||
* @param length input length
|
||||
*/
|
||||
public static void expectDeserializationException(Deserializer deserializer,
|
||||
byte[] bytes, int offset, int length) {
|
||||
try {
|
||||
deserializer.deserialize(bytes, offset, length);
|
||||
fail("DeserializationException was not thrown");
|
||||
} catch (DeserializationException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -67,8 +67,12 @@ public class TCPTest {
|
||||
(byte) 0x00, (byte) 0x01 // urgent
|
||||
};
|
||||
|
||||
private static Deserializer<TCP> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
deserializer = TCP.deserializer();
|
||||
|
||||
ipv4.setSourceAddress(IPv4.toIPv4Address(IPV4_SOURCE_ADDRESS));
|
||||
ipv4.setDestinationAddress(IPv4.toIPv4Address(IPV4_DESTINATION_ADDRESS));
|
||||
ipv4.setProtocol(IPv4.PROTOCOL_TCP);
|
||||
@ -100,13 +104,22 @@ public class TCPTest {
|
||||
assertArrayEquals(bytePacketTCP6, tcp.serialize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, bytePacketTCP4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
TCP tcp = new TCP();
|
||||
tcp.deserialize(bytePacketTCP4, 0, bytePacketTCP4.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
TCP tcp = deserializer.deserialize(bytePacketTCP4, 0, bytePacketTCP4.length);
|
||||
|
||||
assertThat(tcp.getSourcePort(), is((short) 0x50));
|
||||
assertThat(tcp.getDestinationPort(), is((short) 0x60));
|
||||
|
@ -61,8 +61,12 @@ public class UDPTest {
|
||||
(byte) 0x02, (byte) 0x2a, // checksum
|
||||
};
|
||||
|
||||
private static Deserializer<UDP> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
deserializer = UDP.deserializer();
|
||||
|
||||
ipv4.setSourceAddress(IPv4.toIPv4Address(IPV4_SOURCE_ADDRESS));
|
||||
ipv4.setDestinationAddress(IPv4.toIPv4Address(IPV4_DESTINATION_ADDRESS));
|
||||
ipv4.setProtocol(IPv4.PROTOCOL_UDP);
|
||||
@ -88,13 +92,22 @@ public class UDPTest {
|
||||
assertArrayEquals(bytePacketUDP6, udp.serialize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(deserializer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(deserializer, bytePacketUDP4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
UDP udp = new UDP();
|
||||
udp.deserialize(bytePacketUDP4, 0, bytePacketUDP4.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
UDP udp = deserializer.deserialize(bytePacketUDP4, 0, bytePacketUDP4.length);
|
||||
|
||||
assertThat(udp.getSourcePort(), is((short) 0x50));
|
||||
assertThat(udp.getDestinationPort(), is((short) 0x60));
|
||||
|
@ -16,9 +16,11 @@
|
||||
|
||||
package org.onlab.packet.ipv6;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.UDP;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -38,6 +40,8 @@ public class AuthenticationTest {
|
||||
};
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<Authentication> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
data = new Data();
|
||||
@ -57,6 +61,11 @@ public class AuthenticationTest {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = Authentication.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -77,9 +86,8 @@ public class AuthenticationTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
Authentication auth = new Authentication();
|
||||
auth.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
Authentication auth = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(auth.getNextHeader(), is((byte) 0x11));
|
||||
assertThat(auth.getPayloadLength(), is((byte) 0x02));
|
||||
|
@ -16,9 +16,11 @@
|
||||
|
||||
package org.onlab.packet.ipv6;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.IPv6;
|
||||
import org.onlab.packet.UDP;
|
||||
|
||||
@ -40,6 +42,8 @@ public class BaseOptionsTest {
|
||||
};
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<BaseOptions> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
data = new Data();
|
||||
@ -57,6 +61,11 @@ public class BaseOptionsTest {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = BaseOptions.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -75,9 +84,8 @@ public class BaseOptionsTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
BaseOptions baseopt = new BaseOptions();
|
||||
baseopt.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
BaseOptions baseopt = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(baseopt.getNextHeader(), is((byte) 0x11));
|
||||
assertThat(baseopt.getHeaderExtLength(), is((byte) 0x00));
|
||||
|
@ -16,9 +16,13 @@
|
||||
|
||||
package org.onlab.packet.ipv6;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -35,6 +39,8 @@ public class EncapSecurityPayloadTest {
|
||||
private static byte[] dataByte = new byte[32];
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<EncapSecurityPayload> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
Arrays.fill(dataByte, (byte) 0xff);
|
||||
@ -50,6 +56,11 @@ public class EncapSecurityPayloadTest {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = EncapSecurityPayload.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -67,9 +78,8 @@ public class EncapSecurityPayloadTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
EncapSecurityPayload esp = new EncapSecurityPayload();
|
||||
esp.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
EncapSecurityPayload esp = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(esp.getSecurityParamIndex(), is(0x13572468));
|
||||
assertThat(esp.getSequence(), is(0xffff00));
|
||||
|
@ -16,9 +16,12 @@
|
||||
|
||||
package org.onlab.packet.ipv6;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.UDP;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -35,6 +38,8 @@ public class FragmentTest {
|
||||
private static UDP udp;
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<Fragment> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
data = new Data();
|
||||
@ -52,6 +57,11 @@ public class FragmentTest {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = Fragment.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -71,9 +81,8 @@ public class FragmentTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
Fragment frag = new Fragment();
|
||||
frag.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
Fragment frag = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(frag.getNextHeader(), is((byte) 0x11));
|
||||
assertThat(frag.getFragmentOffset(), is((short) 0x1f));
|
||||
|
@ -16,9 +16,12 @@
|
||||
|
||||
package org.onlab.packet.ipv6;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Data;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.UDP;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -42,6 +45,8 @@ public class RoutingTest {
|
||||
};
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<Routing> deserializer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
data = new Data();
|
||||
@ -63,6 +68,11 @@ public class RoutingTest {
|
||||
System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deserializer = Routing.deserializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests serialize and setters.
|
||||
*/
|
||||
@ -83,9 +93,8 @@ public class RoutingTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
Routing routing = new Routing();
|
||||
routing.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
Routing routing = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(routing.getNextHeader(), is((byte) 0x11));
|
||||
assertThat(routing.getHeaderExtLength(), is((byte) 0x02));
|
||||
|
@ -17,6 +17,8 @@ package org.onlab.packet.ndp;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -40,6 +42,9 @@ public class NeighborAdvertisementTest {
|
||||
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<NeighborAdvertisement> deserializer
|
||||
= NeighborAdvertisement.deserializer();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
byte[] byteHeader = {
|
||||
@ -75,9 +80,8 @@ public class NeighborAdvertisementTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
NeighborAdvertisement na = new NeighborAdvertisement();
|
||||
na.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
NeighborAdvertisement na = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(na.getRouterFlag(), is((byte) 1));
|
||||
assertThat(na.getSolicitedFlag(), is((byte) 1));
|
||||
|
@ -17,6 +17,8 @@ package org.onlab.packet.ndp;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -46,6 +48,9 @@ public class NeighborSolicitationTest {
|
||||
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<NeighborSolicitation> deserializer
|
||||
= NeighborSolicitation.deserializer();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
byte[] byteHeader = {
|
||||
@ -78,9 +83,8 @@ public class NeighborSolicitationTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
NeighborSolicitation ns = new NeighborSolicitation();
|
||||
ns.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
NeighborSolicitation ns = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertArrayEquals(ns.getTargetAddress(), TARGET_ADDRESS);
|
||||
|
||||
|
@ -17,6 +17,8 @@ package org.onlab.packet.ndp;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -52,6 +54,8 @@ public class RedirectTest {
|
||||
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<Redirect> deserializer = Redirect.deserializer();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
byte[] byteHeader = {
|
||||
@ -89,9 +93,8 @@ public class RedirectTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
Redirect rd = new Redirect();
|
||||
rd.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
Redirect rd = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertArrayEquals(rd.getTargetAddress(), TARGET_ADDRESS);
|
||||
assertArrayEquals(rd.getDestinationAddress(), DESTINATION_ADDRESS);
|
||||
|
@ -17,6 +17,8 @@ package org.onlab.packet.ndp;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.DeserializationException;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -34,6 +36,9 @@ public class RouterAdvertisementTest {
|
||||
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<RouterAdvertisement> deserializer
|
||||
= RouterAdvertisement.deserializer();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
byte[] byteHeader = {
|
||||
@ -69,9 +74,8 @@ public class RouterAdvertisementTest {
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
RouterAdvertisement ra = new RouterAdvertisement();
|
||||
ra.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws DeserializationException {
|
||||
RouterAdvertisement ra = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
assertThat(ra.getCurrentHopLimit(), is((byte) 3));
|
||||
assertThat(ra.getMFlag(), is((byte) 1));
|
||||
|
@ -17,7 +17,9 @@ package org.onlab.packet.ndp;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.Deserializer;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.packet.PacketTestUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
@ -36,6 +38,9 @@ public class RouterSolicitationTest {
|
||||
|
||||
private static byte[] bytePacket;
|
||||
|
||||
private Deserializer<RouterSolicitation> deserializer
|
||||
= RouterSolicitation.deserializer();
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
byte[] byteHeader = {
|
||||
@ -59,13 +64,22 @@ public class RouterSolicitationTest {
|
||||
assertArrayEquals(rs.serialize(), bytePacket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeBadInput() throws Exception {
|
||||
PacketTestUtils.testDeserializeBadInput(RouterSolicitation.deserializer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeTruncated() throws Exception {
|
||||
PacketTestUtils.testDeserializeTruncated(RouterSolicitation.deserializer(), bytePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests deserialize and getters.
|
||||
*/
|
||||
@Test
|
||||
public void testDeserialize() {
|
||||
RouterSolicitation rs = new RouterSolicitation();
|
||||
rs.deserialize(bytePacket, 0, bytePacket.length);
|
||||
public void testDeserialize() throws Exception {
|
||||
RouterSolicitation rs = deserializer.deserialize(bytePacket, 0, bytePacket.length);
|
||||
|
||||
// Check the option(s)
|
||||
assertThat(rs.getOptions().size(), is(1));
|
||||
|
Loading…
x
Reference in New Issue
Block a user