From e10a7a7c54f61c74db4f95b0360fade0b2b5b2c2 Mon Sep 17 00:00:00 2001 From: Shigeru Yasuda Date: Sat, 17 Oct 2015 02:12:02 +0900 Subject: [PATCH] Import AD-SAL packet parser/generator. Although packet parser is located in manager bundle, it is only for VTN internal use. Change-Id: I31d239d032fdc04d73e3288ca1e22f96c588dc8b Signed-off-by: Shigeru Yasuda --- manager/api/pom.xml | 14 + .../opendaylight/vtn/manager/packet/ARP.java | 331 +++++++ .../vtn/manager/packet/Ethernet.java | 207 ++++ .../opendaylight/vtn/manager/packet/ICMP.java | 272 ++++++ .../vtn/manager/packet/IEEE8021Q.java | 209 ++++ .../opendaylight/vtn/manager/packet/IPv4.java | 766 +++++++++++++++ .../vtn/manager/packet/Packet.java | 811 ++++++++++++++++ .../vtn/manager/packet/PacketException.java | 49 + .../opendaylight/vtn/manager/packet/TCP.java | 352 +++++++ .../opendaylight/vtn/manager/packet/UDP.java | 177 ++++ .../vtn/manager/util/ByteUtils.java | 246 ++++- .../vtn/manager/util/EtherTypes.java | 45 +- .../vtn/manager/util/InetProtocols.java | 49 +- .../vtn/manager/util/NumberUtils.java | 73 +- .../vtn/manager/VTNExceptionTest.java | 4 +- .../vtn/manager/packet/ARPTest.java | 385 ++++++++ .../vtn/manager/packet/EthernetTest.java | 214 +++++ .../vtn/manager/packet/ICMPTest.java | 273 ++++++ .../vtn/manager/packet/IEEE8021QTest.java | 415 ++++++++ .../vtn/manager/packet/IPv4Test.java | 908 ++++++++++++++++++ .../manager/packet/PacketExceptionTest.java | 70 ++ .../vtn/manager/packet/PacketTest.java | 171 ++++ .../vtn/manager/packet/TCPTest.java | 445 +++++++++ .../vtn/manager/packet/UDPTest.java | 246 +++++ .../vtn/manager/util/ByteUtilsTest.java | 355 +++++++ .../vtn/manager/util/EtherTypesTest.java | 21 + .../vtn/manager/util/InetProtocolsTest.java | 20 + .../vtn/manager/util/NumberUtilsTest.java | 54 ++ .../vtn/manager/internal/PacketContext.java | 29 +- .../vtn/manager/internal/VTNManagerImpl.java | 2 +- .../manager/internal/VTNManagerProvider.java | 3 +- .../manager/internal/cluster/MacMapImpl.java | 2 +- .../manager/internal/cluster/PortBridge.java | 2 +- .../internal/cluster/PortInterface.java | 2 +- .../manager/internal/cluster/VlanMapImpl.java | 2 +- .../internal/packet/PacketInEvent.java | 23 +- .../internal/packet/VTNPacketService.java | 3 +- .../internal/packet/cache/CachedPacket.java | 3 +- .../internal/packet/cache/EtherPacket.java | 7 +- .../internal/packet/cache/IcmpPacket.java | 10 +- .../internal/packet/cache/Inet4Packet.java | 26 +- .../internal/packet/cache/L4Packet.java | 5 +- .../packet/cache/PortProtoPacket.java | 32 +- .../internal/packet/cache/TcpPacket.java | 10 +- .../internal/packet/cache/UdpPacket.java | 10 +- .../provider/VTNManagerProviderImpl.java | 3 +- .../vtn/manager/internal/util/MiscUtils.java | 24 - .../util/packet/ArpPacketBuilder.java | 9 +- .../vtn/manager/internal/TestBase.java | 91 +- .../cluster/SetDlDstActionImplTest.java | 2 +- .../cluster/SetDlSrcActionImplTest.java | 2 +- .../cluster/SetDscpActionImplTest.java | 2 +- .../cluster/SetIcmpCodeActionImplTest.java | 6 +- .../cluster/SetIcmpTypeActionImplTest.java | 6 +- .../cluster/SetInet4DstActionImplTest.java | 2 +- .../cluster/SetInet4SrcActionImplTest.java | 2 +- .../cluster/SetTpDstActionImplTest.java | 6 +- .../cluster/SetTpSrcActionImplTest.java | 6 +- .../cluster/SetVlanPcpActionImplTest.java | 2 +- .../packet/cache/EtherPacketTest.java | 8 +- .../internal/packet/cache/IcmpPacketTest.java | 7 +- .../packet/cache/Inet4PacketTest.java | 13 +- .../internal/packet/cache/TcpPacketTest.java | 18 +- .../internal/packet/cache/UdpPacketTest.java | 19 +- .../manager/internal/util/MiscUtilsTest.java | 448 --------- .../util/packet/ArpPacketBuilderTest.java | 9 +- .../vtn/manager/it/core/VTNManagerIT.java | 7 +- .../vtn/manager/it/util/TestHost.java | 14 +- .../it/util/action/SetInet4DstVerifier.java | 27 +- .../it/util/action/SetInet4SrcVerifier.java | 27 +- .../manager/it/util/packet/ArpFactory.java | 4 +- .../it/util/packet/EthernetFactory.java | 21 +- .../manager/it/util/packet/Icmp4Factory.java | 5 +- .../manager/it/util/packet/Inet4Factory.java | 69 +- .../manager/it/util/packet/PacketFactory.java | 3 +- .../manager/it/util/packet/TcpFactory.java | 5 +- .../manager/it/util/packet/UdpFactory.java | 5 +- 77 files changed, 7386 insertions(+), 839 deletions(-) create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ARP.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Ethernet.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ICMP.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IEEE8021Q.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IPv4.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Packet.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/PacketException.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/TCP.java create mode 100644 manager/api/src/main/java/org/opendaylight/vtn/manager/packet/UDP.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ARPTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/EthernetTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ICMPTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IEEE8021QTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IPv4Test.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketExceptionTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/TCPTest.java create mode 100644 manager/api/src/test/java/org/opendaylight/vtn/manager/packet/UDPTest.java diff --git a/manager/api/pom.xml b/manager/api/pom.xml index f750b56f..71815ebd 100644 --- a/manager/api/pom.xml +++ b/manager/api/pom.xml @@ -77,6 +77,8 @@ org.opendaylight.controller.sal.packet.address, org.opendaylight.controller.sal.utils, org.opendaylight.yang.gen.v1.*, + org.slf4j, + com.google.common.*, com.fasterxml.jackson.databind.annotation, javax.xml.bind.annotation, javax.xml.bind.annotation.adapters @@ -124,6 +126,12 @@ hosttracker + + + com.google.guava + guava + + com.fasterxml.jackson.core @@ -136,5 +144,11 @@ jackson-module-jaxb-annotations test + + + + org.slf4j + slf4j-api + diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ARP.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ARP.java new file mode 100644 index 00000000..36fb574f --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ARP.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; + +import java.util.Map; + +import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.util.Ip4Network; + +/** + * {@code ARP} describes an ARP packet. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class ARP extends Packet { + /** + * The number of bits in the ARP header. + */ + private static final int HEADER_SIZE = 224; + + /** + * The field name that indicates the hardware type. + */ + private static final String HWTYPE = "HardwareType"; + + /** + * The field name that indicates the protocol type. + */ + private static final String PTYPE = "ProtocolType"; + + /** + * The field name that indicates the hardware address length. + */ + private static final String HWADDRLENGTH = "HardwareAddressLength"; + + /** + * The field name that indicates the protocol address length. + */ + private static final String PADDRLENGTH = "ProtocolAddressLength"; + + /** + * The field name that indicates the operation code. + */ + private static final String OPCODE = "OpCode"; + + /** + * The field name that indicates the sender hardware address. + */ + private static final String SENDERHWADDR = "SenderHardwareAddress"; + + /** + * The field name that indicates the sender protocol address. + */ + private static final String SENDERPADDR = "SenderProtocolAddress"; + + /** + * The field name that indicates the target hardware address. + */ + private static final String TARGETHWADDR = "TargetHardwareAddress"; + + /** + * The field name that indicates the target protocol address. + */ + private static final String TARGETPADDR = "TargetProtocolAddress"; + + /** + * The hardware tyep value that indicates Ethernet. + */ + public static final short HW_TYPE_ETHERNET = 0x1; + + /** + * The ARP operation code that indicates ARP request. + */ + public static final short REQUEST = 0x1; + + /** + * The ARP operation code that indicates ARP reply. + */ + public static final short REPLY = 0x2; + + /** + * A map that determines the ARP packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * Initialize static fields. + */ + static { + int etherBits = EtherAddress.SIZE * Byte.SIZE; + int ipv4Bits = Ip4Network.SIZE * Byte.SIZE; + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(HWTYPE, Short.SIZE). + addNumber(PTYPE, Short.SIZE). + addNumber(HWADDRLENGTH, Byte.SIZE). + addNumber(PADDRLENGTH, Byte.SIZE). + addNumber(OPCODE, Short.SIZE). + addByte(SENDERHWADDR, etherBits). + addByte(SENDERPADDR, ipv4Bits). + addByte(TARGETHWADDR, etherBits). + addByte(TARGETPADDR, ipv4Bits). + build(); + } + + /** + * Gets the hardware type from the stored ARP header. + * + * @return The hardware type. + */ + public short getHardwareType() { + return getShort(HWTYPE); + } + + /** + * Gets the protocol type from the stored ARP header. + * + * @return The protocol type. + */ + public short getProtocolType() { + return getShort(PTYPE); + } + + /** + * Gets the hardware address length from the stored ARP header. + * + * @return The length of the hardware address. + */ + public byte getHardwareAddressLength() { + return getByte(HWADDRLENGTH); + } + + /** + * Get the protocol address length from Protocol header. + * + * @return The length of the protocol address. + */ + public byte getProtocolAddressLength() { + return getByte(PADDRLENGTH); + } + + /** + * Gets the opCode from stored ARP header. + * + * @return The operation code. + */ + public short getOpCode() { + return getShort(OPCODE); + } + + /** + * Gets the sender hardware address from the stored ARP header. + * + * @return The sender hardware address. + * {@code null} if not configured. + */ + public byte[] getSenderHardwareAddress() { + return getBytes(SENDERHWADDR); + } + + /** + * Gets the IP address from the stored ARP header. + * + * @return The sender protocol address. + * {@code null} if not configured. + */ + public byte[] getSenderProtocolAddress() { + return getBytes(SENDERPADDR); + } + + /** + * Gets the hardware address from the stored ARP header. + * + * @return The target hardware address. + * {@code null} if not configured. + */ + public byte[] getTargetHardwareAddress() { + return getBytes(TARGETHWADDR); + } + + /** + * Gets the target protocol address. + * + * @return The target protocol address. + * {@code null} if not configured. + */ + public byte[] getTargetProtocolAddress() { + return getBytes(TARGETPADDR); + } + + /** + * Sets the hardware Type for the current ARP object instance. + * + * @param hwtype The hardwareType to set. + * @return This instance. + */ + public ARP setHardwareType(short hwtype) { + getHeaderFieldMap().put(HWTYPE, toBytes(hwtype)); + return this; + } + + /** + * Sets the protocol Type for the current ARP object instance. + * + * @param ptype The protocol type to set. + * @return This instance. + */ + public ARP setProtocolType(short ptype) { + getHeaderFieldMap().put(PTYPE, toBytes(ptype)); + return this; + } + + /** + * Sets the hardware address length for the current ARP object instance. + * + * @param len The length of the hardware address. + * @return This instance. + */ + public ARP setHardwareAddressLength(byte len) { + getHeaderFieldMap().put(HWADDRLENGTH, new byte[]{len}); + return this; + } + + /** + * Sets the Protocol address for the current ARP object instance. + * + * @param len The length of the protocol address. + * @return This instance. + */ + public ARP setProtocolAddressLength(byte len) { + getHeaderFieldMap().put(PADDRLENGTH, new byte[]{len}); + return this; + } + + /** + * Sets the opCode for the current ARP object instance. + * + * @param op The operation code. + * @return This instance. + */ + public ARP setOpCode(short op) { + getHeaderFieldMap().put(OPCODE, toBytes(op)); + return this; + } + + /** + * Sets the sender hardware address for the current ARP object instance. + * + * @param addr The sender hardware address. + * @return This instance. + */ + public ARP setSenderHardwareAddress(byte[] addr) { + getHeaderFieldMap().put(SENDERHWADDR, addr.clone()); + return this; + } + + /** + * Sets the target hardware address for the current ARP object instance. + * + * @param addr The target hardware address. + * @return This instance. + */ + public ARP setTargetHardwareAddress(byte[] addr) { + getHeaderFieldMap().put(TARGETHWADDR, addr.clone()); + return this; + } + + /** + * Sets the sender protocol address for the current ARP object instance. + * + * @param addr The sender protocol address. + * @return This instance. + */ + public ARP setSenderProtocolAddress(byte[] addr) { + getHeaderFieldMap().put(SENDERPADDR, addr.clone()); + return this; + } + + /** + * Sets the target protocol address for the current ARP object instance. + * + * @param addr The target protocol address. + * @return This instance. + */ + public ARP setTargetProtocolAddress(byte[] addr) { + getHeaderFieldMap().put(TARGETPADDR, addr.clone()); + return this; + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The ARP header size in bits. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public ARP clone() { + return (ARP)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Ethernet.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Ethernet.java new file mode 100644 index 00000000..dd4febf9 --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Ethernet.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; +import static org.opendaylight.vtn.manager.util.NumberUtils.toShort; + +import java.util.EnumMap; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.util.EtherTypes; + +/** + * {@code Ethernet} describes an Ethernet frame. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public class Ethernet extends Packet { + /** + * The number of bits in the Ethernet header. + */ + private static final int HEADER_SIZE = 112; + + /** + * The field name that indicates the destination MAC address. + */ + private static final String DMAC = "DestinationMACAddress"; + + /** + * The field name that indicates the source MAC address. + */ + private static final String SMAC = "SourceMACAddress"; + + /** + * The field name that indicates the Ethernet type. + */ + static final String ETHT = "EtherType"; + + /** + * A map that determines the IPv4 packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * A set of supported payload types. + */ + private static final Map> PAYLOAD_TYPES; + + /** + * Initialize static fields. + */ + static { + // Initialize the Ethernet header format. + int addrSize = EtherAddress.SIZE * Byte.SIZE; + HEADER_FORMAT = new HeaderMapBuilder(). + addByte(DMAC, addrSize). + addByte(SMAC, addrSize). + addNumber(ETHT, Short.SIZE). + build(); + + // Initialize the payload types. + EnumMap> typeMap = + new EnumMap(EtherTypes.class); + typeMap.put(EtherTypes.IPV4, IPv4.class); + typeMap.put(EtherTypes.ARP, ARP.class); + typeMap.put(EtherTypes.VLAN, IEEE8021Q.class); + PAYLOAD_TYPES = ImmutableMap.copyOf(typeMap); + } + + /** + * Determine the payload type for the given Ethernet type. + * + * @param type The Ethernet type value. + * @return A class for the payload type. + * {@code null} if no payload type is defined for the given + * Ethernet type. + */ + static Class getPayloadClass(short type) { + EtherTypes etype = EtherTypes.forValue(type); + return (etype == null) ? null : PAYLOAD_TYPES.get(etype); + } + + /** + * Gets the destination MAC address stored. + * + * @return The destination MAC address. + * {@code null} if not configured. + */ + public byte[] getDestinationMACAddress() { + return getHeaderFieldMap().get(DMAC); + } + + /** + * Gets the source MAC address stored. + * + * @return The source MAC address. + * {@code null} if not configured. + */ + public byte[] getSourceMACAddress() { + return getHeaderFieldMap().get(SMAC); + } + + /** + * Gets the etherType stored. + * + * @return The Ethernet type. + */ + public short getEtherType() { + return getShort(ETHT); + } + + /** + * Sets the destination MAC address for the current Ethernet object. + * + * @param mac The destination MAC address. + * {@code null} cannot be specified. + * @return This instance. + */ + public Ethernet setDestinationMACAddress(byte[] mac) { + getHeaderFieldMap().put(DMAC, mac.clone()); + return this; + } + + /** + * Sets the source MAC address for the current Ethernet object. + * + * @param mac The source MAC address. + * {@code null} cannot be specified. + * @return This instance. + */ + public Ethernet setSourceMACAddress(byte[] mac) { + getHeaderFieldMap().put(SMAC, mac.clone()); + return this; + } + + /** + * Sets the etherType for the current Ethernet object. + * + * @param type The Ethernet type. + * @return This instance. + */ + public Ethernet setEtherType(short type) { + getHeaderFieldMap().put(ETHT, toBytes(type)); + return this; + } + + // Packet + + /** + * Return the number of bits in the Ethernet header. + * + * @return The number of bits in the Ethernet header. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + /** + * Stores the value of fields read from data stream. + * + * @param name The name of the header field. + * @param value The value to be associated with the specified header + * field. {@code null} cannot be specified. + */ + @Override + protected void setHeaderField(String name, byte[] value) { + if (name.equals(ETHT)) { + short etype = toShort(value); + setPayloadClass(getPayloadClass(etype)); + } + + super.setHeaderField(name, value); + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public Ethernet clone() { + return (Ethernet)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ICMP.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ICMP.java new file mode 100644 index 00000000..3ac63916 --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/ICMP.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.packet.IPv4.CKSUM_BYTES; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_BYTE; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_SHORT; +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; + +import java.util.Map; + +import org.opendaylight.vtn.manager.util.ByteUtils; + +/** + * {@code ICMP} describes an ICMP packet. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class ICMP extends Packet { + /** + * The number of bits in the ICMP header. + */ + private static final int HEADER_SIZE = 64; + + /** + * The field name that indicates the ICMP type. + */ + private static final String TYPE = "Type"; + + /** + * The field name that indicates the ICMP code. + */ + private static final String CODE = "Code"; + + /** + * The field name that indicates the checksum. + */ + private static final String CHECKSUM = "Checksum"; + + /** + * The field name that indicates the ICMP identifier. + */ + private static final String IDENTIFIER = "Identifier"; + + /** + * The field name that indicates the sequence number. + */ + private static final String SEQNUMBER = "SequenceNumber"; + + /** + * A map that determines the ICMP packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * Initialize static fields. + */ + static { + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(TYPE, Byte.SIZE). + addNumber(CODE, Byte.SIZE). + addNumber(CHECKSUM, Short.SIZE). + addNumber(IDENTIFIER, Short.SIZE). + addNumber(SEQNUMBER, Short.SIZE). + build(); + } + + /** + * Sets the type for the current ICMP message. + * + * @param type The ICMP message type + * @return This ICMP object + */ + public ICMP setType(byte type) { + getHeaderFieldMap().put(TYPE, new byte[]{type}); + return this; + } + + /** + * Returns the type field of the current ICMP packet. + * + * @return The type code of the current ICMP packet + */ + public byte getType() { + return getByte(TYPE); + } + + /** + * Sets the ICMP code (type subtype) for the current ICMP object instance. + * + * @param code The ICMP message type subtype + * @return This ICMP object + */ + public ICMP setCode(byte code) { + getHeaderFieldMap().put(CODE, new byte[]{code}); + return this; + } + + /** + * Gets the ICMP code (type subtype) for the current ICMP object instance. + * + * @return The ICMP message type subtype + */ + public byte getCode() { + return getByte(CODE); + } + + /** + * Sets the ICMP checksum for the current ICMP object instance. + * + * @param cksum The checksum value to be set. + * @return This instance. + */ + public ICMP setChecksum(short cksum) { + getHeaderFieldMap().put(CHECKSUM, toBytes(cksum)); + return this; + } + + /** + * Return the ICMP checksum in this packet. + * + * @return The ICMP checksum value. + */ + public short getChecksum() { + return getShort(CHECKSUM); + } + + /** + * Sets the ICMP identifier for the current ICMP object instance. + * @param id The ICMP identifier to be set. + * @return This instance. + */ + public ICMP setIdentifier(short id) { + getHeaderFieldMap().put(IDENTIFIER, toBytes(id)); + return this; + } + + /** + * Gets the ICMP identifier of the current ICMP object instance. + * + * @return The ICMP identifier. + */ + public short getIdentifier() { + return getShort(IDENTIFIER); + } + + /** + * Sets the ICMP sequence number for the current ICMP object instance. + * + * @param seq The ICMP sequence number to be set. + * @return This instance. + */ + public ICMP setSequenceNumber(short seq) { + getHeaderFieldMap().put(SEQNUMBER, toBytes(seq)); + return this; + } + + /** + * Gets the ICMP sequence number of the current ICMP object instance. + * + * @return The ICMP sequence number. + */ + public short getSequenceNumber() { + return getShort(SEQNUMBER); + } + + /** + * Computes the ICMP checksum on the serialized ICMP message. + * + * @param data The data stream. + * @param start The byte index on the data stream from which the ICMP + * packet starts. + * @return The checksum value. + */ + private short computeChecksum(byte[] data, int start) { + int sum = 0; + int wordData; + int end = (start + HEADER_SIZE / Byte.SIZE) + getRawPayloadSize(); + int checksumStartByte = start + getFieldOffset(CHECKSUM) / Byte.SIZE; + int even = end & ~1; + + for (int i = start; i < even; i += CKSUM_BYTES) { + // Skip, if the current bytes are checkSum bytes + if (i != checksumStartByte) { + wordData = ((data[i] & MASK_BYTE) << Byte.SIZE) | + (data[i + 1] & MASK_BYTE); + sum = sum + wordData; + } + } + if (even < end) { + // Add the last octet with zero padding. + wordData = (data[even] & MASK_BYTE) << Byte.SIZE; + sum = sum + wordData; + } + + int carry = sum >>> Short.SIZE; + int finalSum = (sum & MASK_SHORT) + carry; + return (short)~((short)finalSum & MASK_SHORT); + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The ICMP header size in bits. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + /** + * {@inheritDoc} + */ + @Override + protected void postSerializeCustomOperation(byte[] myBytes) + throws PacketException { + String field = CHECKSUM; + try { + HeaderField entry = HEADER_FORMAT.get(field); + int off = getFieldOffset(field, entry); + int nbits = getFieldNumBits(field, entry); + byte[] cksum = toBytes(computeChecksum(myBytes, 0)); + ByteUtils.setBits(myBytes, cksum, off, nbits); + getHeaderFieldMap().put(CHECKSUM, cksum); + } catch (RuntimeException e) { + throw new PacketException("Failed to update checksum.", e); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void postDeserializeCustomOperation(byte[] data, int offset) { + short computed = computeChecksum(data, offset / Byte.SIZE); + short actual = getChecksum(); + if (computed != actual) { + setCorrupted(true); + } + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public ICMP clone() { + return (ICMP)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IEEE8021Q.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IEEE8021Q.java new file mode 100644 index 00000000..39a2cb51 --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IEEE8021Q.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.packet.Ethernet.ETHT; +import static org.opendaylight.vtn.manager.packet.Ethernet.getPayloadClass; +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; +import static org.opendaylight.vtn.manager.util.NumberUtils.toShort; + +import java.util.Map; + +/** + * {@code IEEE8021Q} describes an IEEE 802.1Q VLAN tag. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class IEEE8021Q extends Packet { + /** + * The number of bits in the VLAN tag. + */ + private static final int HEADER_SIZE = 32; + + /** + * The field name that indicates the priority code point. + */ + private static final String PCP = "PriorityCodePoint"; + + /** + * The field name that indicates the canonical format indicator. + */ + private static final String CFI = "CanonicalFormatIndicator"; + + /** + * The field name that indicates the VLAN ID. + */ + private static final String VID = "VlanIdentifier"; + + /** + * The number of bits in the prioriy code point field. + */ + private static final int BITS_PCP = 3; + + /** + * The number of bits in the canonical format indicator field. + */ + private static final int BITS_CFI = 1; + + /** + * The number of bits in the VLAN ID field. + */ + private static final int BITS_VID = 12; + + /** + * A map that determines the IEEE 802.1Q header format. + */ + private static final Map HEADER_FORMAT; + + /** + * Initialize static fields. + */ + static { + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(PCP, BITS_PCP). + addNumber(CFI, BITS_CFI). + addNumber(VID, BITS_VID). + addNumber(ETHT, Short.SIZE). + build(); + } + + /** + * Gets the priority code point(PCP) stored. + * + * @return The priority code point value. + */ + public byte getPcp() { + return getByte(PCP); + } + + /** + * Gets the canonical format indicator(CFI) stored. + * + * @return The canonical format indicator value. + */ + public byte getCfi() { + return getByte(CFI); + } + + /** + * Gets the VLAN identifier(VID) stored. + * + * @return The VLAN ID. + */ + public short getVid() { + return getShort(VID); + } + + /** + * Gets the Ethernet type stored. + * + * @return The Ethernet type. + */ + public short getEtherType() { + return getShort(ETHT); + } + + /** + * Sets the priority code point(PCP) for the current IEEE 802.1Q object + * instance. + * + * @param pcp The priority code point value. + * @return This instance. + */ + public IEEE8021Q setPcp(byte pcp) { + getHeaderFieldMap().put(PCP, new byte[]{pcp}); + return this; + } + + /** + * Sets the canonical format indicator(CFI) for the current IEEE 802.1Q + * object instance. + * + * @param cfi The canonical format indicator value. + * @return This instance. + */ + public IEEE8021Q setCfi(byte cfi) { + getHeaderFieldMap().put(CFI, new byte[]{cfi}); + return this; + } + + /** + * Sets the VLAN identifier(VID) for the current IEEE 802.1Q instance. + * + * @param vid The VLAN ID. + * @return This instance. + */ + public IEEE8021Q setVid(short vid) { + getHeaderFieldMap().put(VID, toBytes(vid)); + return this; + } + + /** + * Sets the etherType for the current IEEE 802.1Q object instance. + * + * @param type The Ethernet type. + * @return This instance. + */ + public IEEE8021Q setEtherType(short type) { + getHeaderFieldMap().put(ETHT, toBytes(type)); + return this; + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The IEEE 802.1Q header size in bits. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + /** + * Stores the value of fields read from data stream. + * + * @param name The name of the header field. + * @param value The value to be associated with the specified header + * field. {@code null} cannot be specified. + */ + @Override + protected void setHeaderField(String name, byte[] value) { + if (name.equals(ETHT)) { + short etype = toShort(value); + setPayloadClass(getPayloadClass(etype)); + } + + super.setHeaderField(name, value); + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public IEEE8021Q clone() { + return (IEEE8021Q)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IPv4.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IPv4.java new file mode 100644 index 00000000..50bc843e --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/IPv4.java @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_BYTE; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_SHORT; +import static org.opendaylight.vtn.manager.util.NumberUtils.NUM_OCTETS_SHORT; +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +import org.opendaylight.vtn.manager.util.ByteUtils; +import org.opendaylight.vtn.manager.util.InetProtocols; +import org.opendaylight.vtn.manager.util.Ip4Network; + +/** + * {@code IPv4} describes an IP version 4 packet. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class IPv4 extends Packet { + /** + * The IPv4 version number. + */ + public static final byte IPV4_VERSION = 4; + + /** + * The number of octets in IP checksum. + */ + public static final int CKSUM_BYTES = NUM_OCTETS_SHORT; + + /** + * The field name that indicates the Inetnet Protocol version. + */ + private static final String VERSION = "Version"; + + /** + * The field name that indicates the IP header length. + */ + private static final String HEADERLENGTH = "HeaderLength"; + + /** + * The field name that indicates the IP differential service. + */ + private static final String DIFFSERV = "DiffServ"; + + /** + * The field name that indicates the ECN bits. + */ + private static final String ECN = "ECN"; + + /** + * The field name that indicates the total length. + */ + private static final String TOTLENGTH = "TotalLength"; + + /** + * The field name that indicates the IPv4 identification. + */ + private static final String IDENTIFICATION = "Identification"; + + /** + * The field name that indicates the IPv4 flags. + */ + private static final String FLAGS = "Flags"; + + /** + * The field name that indicates the IPv4 fragment offset. + */ + private static final String FRAGOFFSET = "FragmentOffset"; + + /** + * The field name that indicates the IPv4 Time-To-Live. + */ + private static final String TTL = "TTL"; + + /** + * The field name that indicates the IP protocol number. + */ + private static final String PROTOCOL = "Protocol"; + + /** + * The field name that indicates the IP checksum. + */ + private static final String CHECKSUM = "Checksum"; + + /** + * The field name that indicates the source IP address. + */ + private static final String SIP = "SourceIPAddress"; + + /** + * The field name that indicates the destination IP address. + */ + private static final String DIP = "DestinationIPAddress"; + + /** + * The field name that indicates the IPv4 options. + */ + private static final String OPTIONS = "Options"; + + /** + * The number of bits in the IP protocol version field. + */ + private static final int BITS_VERSION = 4; + + /** + * The number of bits in the IP header length field. + */ + private static final int BITS_HEADERLENGTH = 4; + + /** + * The number of bits in the IP differential service field. + */ + private static final int BITS_DIFFSERV = 6; + + /** + * The number of bits in the ECN field. + */ + private static final int BITS_ECN = 2; + + /** + * The number of bits in the IPv4 flags field. + */ + private static final int BITS_FLAGS = 3; + + /** + * The number of bits in the IPv4 fragment offset field. + */ + private static final int BITS_FRAGOFFSET = 13; + + /** + * The number of bits to calculate IPv4 unit size. + */ + private static final int UNIT_SIZE_SHIFT = 2; + + /** + * The number of bytes in an IPv4 unit value. + */ + private static final int UNIT_SIZE = (1 << UNIT_SIZE_SHIFT); + + /** + * The minimum size of the IPv4 header in bytes. + */ + private static final int MIN_HEADER_SIZE = 20; + + /** + * The default value of the header length field. + */ + private static final byte DEFAULT_HEADER_LENGTH = + (byte)(MIN_HEADER_SIZE >>> UNIT_SIZE_SHIFT); + + /** + * The default value of the IPv4 flags. + */ + private static final byte DEFAULT_FLAGS = 2; + + /** + * A map that determines the IPv4 packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * A set of supported payload types. + */ + private static final Map> PAYLOAD_TYPES; + + /** + * Initialize static fields. + */ + static { + // Initialize the IPv4 header format. + int addrSize = Ip4Network.SIZE * Byte.SIZE; + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(VERSION, BITS_VERSION). + addNumber(HEADERLENGTH, BITS_HEADERLENGTH). + addNumber(DIFFSERV, BITS_DIFFSERV). + addNumber(ECN, BITS_ECN). + addNumber(TOTLENGTH, Short.SIZE). + addNumber(IDENTIFICATION, Short.SIZE). + addNumber(FLAGS, BITS_FLAGS). + addNumber(FRAGOFFSET, BITS_FRAGOFFSET). + addNumber(TTL, Byte.SIZE). + addNumber(PROTOCOL, Byte.SIZE). + addNumber(CHECKSUM, Short.SIZE). + addByte(SIP, addrSize). + addByte(DIP, addrSize). + addByte(OPTIONS, 0). + build(); + + // Initialize the payload types. + EnumMap> typeMap = + new EnumMap(InetProtocols.class); + typeMap.put(InetProtocols.ICMP, ICMP.class); + typeMap.put(InetProtocols.TCP, TCP.class); + typeMap.put(InetProtocols.UDP, UDP.class); + PAYLOAD_TYPES = ImmutableMap.copyOf(typeMap); + } + + /** + * Determine the payload type for the given IP protocol number. + * + * @param proto The IP protocol number. + * @return A class for the payload type. + * {@code null} if no payload type is defined for the given + * IP protocol number. + */ + static Class getPayloadClass(byte proto) { + InetProtocols ipproto = InetProtocols.forValue(proto); + return (ipproto == null) ? null : PAYLOAD_TYPES.get(ipproto); + } + + /** + * Construct a new instance. + * + *

+ * This constructor sets the version to 4, headerLength to 5, + * and flags to 2. + *

+ */ + public IPv4() { + setVersion(IPV4_VERSION); + setHeaderLength(DEFAULT_HEADER_LENGTH); + setFlags(DEFAULT_FLAGS); + } + + /** + * Gets the IP version stored. + * + * @return The IP version. + */ + public byte getVersion() { + return getByte(VERSION); + } + + /** + * Gets the IP header length stored. + * + * @return The IP header length in bytes. + */ + public int getHeaderLen() { + return (getByte(HEADERLENGTH) << UNIT_SIZE_SHIFT); + } + + /** + * Gets the differential services value stored. + * + * @return The differential services value. + */ + public byte getDiffServ() { + return getByte(DIFFSERV); + } + + /** + * Gets the ECN bits stored. + * + * @return The ECN bits. + */ + public byte getECN() { + return getByte(ECN); + } + + /** + * Gets the total length of the IPv4 packe in bytes. + * + * @return The total length of the IPv4 packet. + */ + public short getTotalLength() { + return getShort(TOTLENGTH); + } + + /** + * Gets the identification value stored. + * + * @return The IP identification value. + */ + public short getIdentification() { + return getShort(IDENTIFICATION); + } + + /** + * Gets the flag values stored. + * + * @return The IPv4 flags. + */ + public byte getFlags() { + return getByte(FLAGS); + } + + /** + * Gets the TTL value stored. + * + * @return The TTL value. + */ + public byte getTtl() { + return getByte(TTL); + } + + /** + * Gets the protocol value stored. + * + * @return The IP protocol number. + */ + public byte getProtocol() { + return getByte(PROTOCOL); + } + + /** + * Gets the checksum value stored. + * + * @return The IP header checksum. + */ + public short getChecksum() { + return getShort(CHECKSUM); + } + + /** + * Gets the fragment offset stored. + * + * @return The IP fragment offset. + */ + public short getFragmentOffset() { + return getShort(FRAGOFFSET); + } + + /** + * Gets the source IP address stored. + * + * @return An {@link Ip4Network} instance that represents the source + * IP address. + */ + public Ip4Network getSourceAddress() { + return getIp4Network(SIP); + } + + /** + * Gets the destination IP address stored. + * + * @return An {@link Ip4Network} instance that represents the destination + * IP address. + */ + public Ip4Network getDestinationAddress() { + return getIp4Network(DIP); + } + + /** + * Gets the Options stored. + * + * @return The IPv4 options. {@code null} if no option is present. + */ + public byte[] getOptions() { + byte[] opts = getHeaderFieldMap().get(OPTIONS); + return (opts == null || opts.length == 0) ? null : opts.clone(); + } + + /** + * Stores the IP version from the header. + * + * @param version The version to set + * @return This instance. + */ + public IPv4 setVersion(byte version) { + getHeaderFieldMap().put(VERSION, new byte[]{version}); + return this; + } + + /** + * Stores the length of IP header in words (4 bytes). + * + * @param len The headerLength to set. + * @return This instance. + */ + public IPv4 setHeaderLength(byte len) { + getHeaderFieldMap().put(HEADERLENGTH, new byte[]{len}); + return this; + } + + /** + * Stores the differential services value from the IP header. + * + * @param dserv The differential services value. + * @return This instance. + */ + public IPv4 setDiffServ(byte dserv) { + getHeaderFieldMap().put(DIFFSERV, new byte[]{dserv}); + return this; + } + + /** + * Stores the ECN bits from the header. + * + * @param ecn The ECN bits to set. + * @return This instance. + */ + public IPv4 setECN(byte ecn) { + getHeaderFieldMap().put(ECN, new byte[]{ecn}); + return this; + } + + /** + * Stores the total length of IPv4 packet in bytes. + * + * @param len The total length of the IPv4 packet. + * @return This instance. + */ + public IPv4 setTotalLength(short len) { + getHeaderFieldMap().put(TOTLENGTH, toBytes(len)); + return this; + } + + /** + * Stores the identification number from the header. + * + * @param id The identification to set. + * @return This instance. + */ + public IPv4 setIdentification(short id) { + getHeaderFieldMap().put(IDENTIFICATION, toBytes(id)); + return this; + } + + /** + * Stores the IP flags value. + * + * @param flags The flags to set. + * @return This instance. + */ + public IPv4 setFlags(byte flags) { + getHeaderFieldMap().put(FLAGS, new byte[]{flags}); + return this; + } + + /** + * Stores the IP fragmentation offset value. + * + * @param off The fragmentation offset. + * @return This instance. + */ + public IPv4 setFragmentOffset(short off) { + getHeaderFieldMap().put(FRAGOFFSET, toBytes(off)); + return this; + } + + /** + * Stores the TTL value. + * + * @param ttl The ttl to set. + * @return This instance. + */ + public IPv4 setTtl(byte ttl) { + getHeaderFieldMap().put(TTL, new byte[]{ttl}); + return this; + } + + /** + * Stores the protocol value of the IP payload. + * + * @param proto The protocol to set. + * @return This instance. + */ + public IPv4 setProtocol(byte proto) { + getHeaderFieldMap().put(PROTOCOL, new byte[]{proto}); + return this; + } + + /** + * Set the IP checksum value. + * + *

+ * This method is only for testing. + * IP checksum will be updated on serialization. + *

+ * + * @param cksum The IP checksum. + * @return This instance. + */ + public IPv4 setChecksum(short cksum) { + getHeaderFieldMap().put(CHECKSUM, toBytes(cksum)); + return this; + } + + /** + * Stores the IP source address from the header. + * + *

+ * The network prefix in the given paramter is always ignored. + *

+ * + * @param addr The source IP address. + * @return This instance. + */ + public IPv4 setSourceAddress(Ip4Network addr) { + getHeaderFieldMap().put(SIP, addr.getBytes()); + return this; + } + + /** + * Stores the IP destination address from the header. + * + *

+ * The network prefix in the given paramter is always ignored. + *

+ * + * @param addr The destination IP address. + * @return This instance. + */ + public IPv4 setDestinationAddress(Ip4Network addr) { + getHeaderFieldMap().put(DIP, addr.getBytes()); + return this; + } + + /** + * Store the options from IP header. + * + * @param options The IP options. + * @return This instance. + */ + public IPv4 setOptions(byte[] options) { + Map map = getHeaderFieldMap(); + byte newIHL = DEFAULT_HEADER_LENGTH; + if (options == null || options.length == 0) { + map.remove(OPTIONS); + } else { + int len = options.length; + int mask = UNIT_SIZE - 1; + int rlen = (len + mask) & ~mask; + byte[] newopt; + if (rlen > len) { + // Padding is required. + newopt = new byte[rlen]; + System.arraycopy(options, 0, newopt, 0, len); + len = rlen; + } else { + newopt = options.clone(); + } + map.put(OPTIONS, newopt); + newIHL += ((len & MASK_BYTE) >>> UNIT_SIZE_SHIFT); + } + + map.put(HEADERLENGTH, new byte[]{newIHL}); + return this; + } + + /** + * Computes the IPv4 header checksum on the passed stream of bytes + * representing the packet. + * + * @param data The byte stream. + * @param start The byte offset from where the IPv4 packet starts. + * @return The computed checksum + */ + short computeChecksum(byte[] data, int start) { + int end = start + getHeaderLen() - 1; + int sum = 0; + int wordData; + int checksumStart = start + (getFieldOffset(CHECKSUM) / Byte.SIZE); + + for (int i = start; i <= end; i += CKSUM_BYTES) { + // Skip, if the current bytes are checkSum bytes + if (i != checksumStart) { + wordData = ((data[i] & MASK_BYTE) << Byte.SIZE) | + (data[i + 1] & MASK_BYTE); + sum = sum + wordData; + } + } + + int carry = sum >>> Short.SIZE; + int finalSum = (sum & MASK_SHORT) + carry; + return (short)~((short)finalSum & MASK_SHORT); + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The number of bits constituting the header. + */ + @Override + public int getHeaderSize() { + int len = getHeaderLen(); + if (len == 0) { + len = MIN_HEADER_SIZE; + } + + return len * Byte.SIZE; + } + + /** + * Gets the number of bits for the specified field. + * + *

+ * If the fieldname has variable length like "Options", then this value + * is computed using the header length. + *

+ * + * @param name The name of the header field. + * @param entry The header field entry associated with {@code name}. + * @return The number of bits of the requested field. + */ + @Override + protected int getFieldNumBits(String name, HeaderField entry) { + return (name.equals(OPTIONS)) + ? (getHeaderLen() - MIN_HEADER_SIZE) * Byte.SIZE + : entry.getNumBits(); + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + /** + * Stores the value of fields read from data stream. + * + *

+ * Variable header value like payload protocol, is stored here. + *

+ * + * @param name The name of the header field. + * @param value The value to be associated with the specified header + * field. {@code null} cannot be specified. + */ + @Override + protected void setHeaderField(String name, byte[] value) { + Map map = getHeaderFieldMap(); + if (name.equals(PROTOCOL)) { + // Don't set payloadClass if framgment offset is not zero. + byte[] fragoff = map.get(FRAGOFFSET); + if (isZeroShort(fragoff)) { + setPayloadClass(getPayloadClass(value[0])); + } + } else if (name.equals(FRAGOFFSET)) { + if (!isZeroShort(value)) { + // Clear payloadClass because protocol header is not present + // in this packet. + setPayloadClass(null); + } + } else if (name.equals(OPTIONS) && + (value == null || value.length == 0)) { + map.remove(name); + return; + } + map.put(name, value); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean equalsField(String name, byte[] value1, byte[] value2) { + return (name.equals(OPTIONS)) + ? Arrays.equals(value1, value2) + : super.equalsField(name, value1, value2); + } + + /** + * Set the packet encapsulated by this IPv4 packet. + * + *

+ * This method updates the total length of the IPv4 packet. + *

+ * + * @param p The packet encapsulated by this IPv4 packet. + */ + @Override + public void setPayload(Packet p) { + super.setPayload(p); + + if (p != null) { + // Determine the total length. + int plen; + try { + plen = p.serialize().length; + } catch (PacketException e) { + throw new IllegalStateException( + "Failed to serialize the specified payload.", e); + } + + setTotalLength((short)(getHeaderLen() + plen)); + } + } + + /** + * This method gets called at the end of the serialization process. + * + *

+ * This method computes the IP checksum and stores it into the IP header. + *

+ * + * @param myBytes Serialized bytes. + * @throws PacketException An error occurred. + */ + @Override + protected void postSerializeCustomOperation(byte[] myBytes) + throws PacketException { + try { + Map map = getHeaderFieldMap(); + String field = TOTLENGTH; + HeaderField entry = HEADER_FORMAT.get(field); + int off = getFieldOffset(field, entry); + int nbits = getFieldNumBits(field, entry); + + // Recompute the total length field here. + byte[] total = toBytes((short)myBytes.length); + ByteUtils.setBits(myBytes, total, off, nbits); + map.put(TOTLENGTH, total); + + // Compute the header checksum. + field = CHECKSUM; + entry = HEADER_FORMAT.get(field); + off = getFieldOffset(field, entry); + nbits = getFieldNumBits(field, entry); + byte[] cksum = toBytes(computeChecksum(myBytes, 0)); + ByteUtils.setBits(myBytes, cksum, off, nbits); + map.put(CHECKSUM, cksum); + } catch (RuntimeException e) { + throw new PacketException("Failed to update checksum.", e); + } + } + + /** + * This method re-computes the checksum of the bits received on the wire + * and validates it with the checksum in the bits received. + * + * @param data The byte stream representing the Ethernet frame. + * @param offset The bit offset from where the byte array corresponding to + * this Packet starts in the frame + */ + @Override + protected void postDeserializeCustomOperation(byte[] data, int offset) { + short computed = computeChecksum(data, offset / Byte.SIZE); + short actual = getChecksum(); + if (computed != actual) { + setCorrupted(true); + } + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public IPv4 clone() { + return (IPv4)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Packet.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Packet.java new file mode 100644 index 00000000..6938c37c --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/Packet.java @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.HASH_PRIME; +import static org.opendaylight.vtn.manager.util.NumberUtils.toInteger; +import static org.opendaylight.vtn.manager.util.NumberUtils.toShort; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableMap; + +import org.opendaylight.vtn.manager.util.ByteUtils; +import org.opendaylight.vtn.manager.util.Ip4Network; + +/** + * {@code Packet} is an abstract class which represents the generic network + * packet object. + * + *

+ * It provides the basic methods which are common for all the packets, + * like serialize and deserialize. + *

+ *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public abstract class Packet implements Cloneable { + /** + * Logger instance. + */ + private static final Logger LOG = LoggerFactory.getLogger(Packet.class); + + /** + * Determine whether this packet is corrupted or not. + */ + private boolean corrupted; + + /** + * The packet encapsulated by this packet. + */ + private Packet payload; + + /** + * The unparsed raw payload carried by this packet. + */ + private byte[] rawPayload; + + /** + * Header fields values. + */ + private Map hdrFieldsMap = new HashMap<>(); + + /** + * The class of the encapsulated packet object. + */ + private Class payloadClass; + + /** + * {@code HeaderField} describes the location of the header field in the + * packet header. + */ + static final class HeaderField { + /** + * The start bit offset for the header field. + */ + private final int offset; + + /** + * The number of bits in the header field. + */ + private final int numBits; + + /** + * The number of bytes in the buffer used to keep the value. + */ + private final int size; + + /** + * Construct a new instance. + * + * @param off The start bit offset for the header field. + * @param nbits The number of bits in the header field. + * @param nbytes The number of bytes in the buffer used to keep + * the value. + */ + private HeaderField(int off, int nbits, int nbytes) { + offset = off; + numBits = nbits; + size = nbytes; + } + + /** + * Return the start bit offset for the header field. + * + * @return The start offset bit for the header field. + */ + int getOffset() { + return offset; + } + + /** + * Return the number of bits in the header field. + * + * @return The number of bits in the header field. + */ + int getNumBits() { + return numBits; + } + + /** + * Return the size of the buffer for the header field. + * + * @return The number of bytes in the buffer used to keep the value. + */ + int getSize() { + return size; + } + + /** + * Return the hash code of the given value. + * + * @param value A value associated with this header field. + * @return The hash code of the given value. + */ + int hash(byte[] value) { + byte[] v = value; + assert v == null || v.length == size; + + if (v == null && size != 0) { + // Compute the hash code of the default value. + v = new byte[size]; + } + + return Arrays.hashCode(v); + } + } + + /** + * Internal utility class to generate header format map. + * + *

+ * The order of the header fields iteration is the order in which its + * entries were added. + *

+ */ + static final class HeaderMapBuilder { + /** + * A immutable map builder. + */ + private final ImmutableMap.Builder builder = + ImmutableMap.builder(); + + /** + * The bit offset fot the next field. + */ + private int offset; + + /** + * Add a new header field that keeps a byte array. + * + * @param name The name of the header field. + * @param nbits The number of bits in the header field. + * @return This instance. + */ + HeaderMapBuilder addByte(String name, int nbits) { + int size = (nbits + Byte.SIZE - 1) / Byte.SIZE; + return add(name, nbits, size); + } + + /** + * Add a new header field that keeps a number. + * + * @param name The name of the header field. + * @param nbits The number of bits in the header field. + * @return This instance. + */ + HeaderMapBuilder addNumber(String name, int nbits) { + int size = (nbits + Byte.SIZE - 1) / Byte.SIZE; + if (size != 0) { + // Round up the size to a power of 2. + int leading = Integer.numberOfLeadingZeros(size); + int trailing = Integer.numberOfTrailingZeros(size); + if (leading + trailing < Integer.SIZE - 1) { + size = 1 << (Integer.SIZE - leading); + } + } + + return add(name, nbits, size); + } + + /** + * Add a new header field. + * + * @param name The name of the header field. + * @param nbits The number of bits in the header field. + * @param size The number of bytes in the buffer used to keep the + * value. + * @return This instance. + */ + private HeaderMapBuilder add(String name, int nbits, int size) { + HeaderField field = new HeaderField(offset, nbits, size); + builder.put(name, field); + offset += nbits; + return this; + } + + /** + * Create a new header field map. + * + * @return A map that determines the format of the header fields. + */ + Map build() { + return builder.build(); + } + } + + /** + * Construct a new instance. + */ + Packet() { + } + + /** + * Return the packet encapsulated by this packet. + * + * @return The packet encapsulated by this packet if present. + * {@code null} if not present. + */ + public final Packet getPayload() { + return payload; + } + + /** + * Set the packet encapsulated by this packet. + * + * @param p The packet encapsulated by this packet. + */ + public void setPayload(Packet p) { + payload = p; + } + + /** + * This method deserializes the data bits obtained from the wire into the + * respective header and payload which are of type Packet. + * + * @param data Data from wire to deserialize. + * @param bitOffset Bit position where packet header starts in data array. + * @param size Size of packet in bits. + * @return This instance. + * @throws PacketException An error occurred. + */ + public Packet deserialize(byte[] data, int bitOffset, int size) + throws PacketException { + // Deserialize the header fields one by one. + int startOffset = 0; + int numBits = 0; + payloadClass = null; + Map fmtMap = getHeaderFormat(); + for (Entry entry: fmtMap.entrySet()) { + String hdrField = entry.getKey(); + HeaderField hent = entry.getValue(); + startOffset = bitOffset + getFieldOffset(hdrField, hent); + numBits = getFieldNumBits(hdrField, hent); + + byte[] hdrFieldBytes; + try { + hdrFieldBytes = ByteUtils.getBits(data, startOffset, numBits); + } catch (RuntimeException e) { + String msg = "Failed to deserialize field: " + hdrField + + ": off=" + startOffset + ", size=" + numBits + + ", total=" + size; + throw new PacketException(msg, e); + } + + /* + * Store the raw read value, checks the payload type and set the + * payloadClass accordingly + */ + setHeaderField(hdrField, hdrFieldBytes); + + if (LOG.isTraceEnabled()) { + LOG.trace("Deserializing: {}: {}: {} (offset {} bitsize {})", + getClass().getSimpleName(), hdrField, + ByteUtils.toHexString(hdrFieldBytes), + startOffset, numBits); + } + } + + // Deserialize the payload now + int payloadStart = startOffset + numBits; + int payloadSize = data.length * Byte.SIZE - payloadStart; + + if (payloadClass != null) { + try { + payload = payloadClass.newInstance(); + } catch (Exception e) { + throw new PacketException( + "Error parsing payload for Ethernet packet", e); + } + payload.deserialize(data, payloadStart, payloadSize); + } else if (payloadSize > 0) { + /* + * The payload class was not set, it means no class for parsing + * this payload is present. Let's store the raw payload if any. + */ + int start = payloadStart / Byte.SIZE; + int stop = start + payloadSize / Byte.SIZE; + rawPayload = Arrays.copyOfRange(data, start, stop); + } + + // Take care of computation that can be done only after deserialization + postDeserializeCustomOperation(data, payloadStart - getHeaderSize()); + + return this; + } + + /** + * This method serializes the header and payload from the respective + * packet class, into a single stream of bytes to be sent on the wire. + * + * @return The byte array representing the serialized Packet. + * @throws PacketException An error occurred. + */ + public byte[] serialize() throws PacketException { + // Acquire or compute the serialized payload + byte[] payloadBytes = null; + if (payload != null) { + payloadBytes = payload.serialize(); + } else if (rawPayload != null) { + payloadBytes = rawPayload; + } + + int payloadSize = (payloadBytes == null) ? 0 : payloadBytes.length; + + // Allocate the buffer to contain the full (header + payload) packet + int headerSize = getHeaderSize() / Byte.SIZE; + byte[] packetBytes = new byte[headerSize + payloadSize]; + if (payloadSize != 0) { + System.arraycopy(payloadBytes, 0, packetBytes, headerSize, + payloadSize); + } + + // Serialize this packet header, field by field + Map fmtMap = getHeaderFormat(); + for (Entry entry: fmtMap.entrySet()) { + String field = entry.getKey(); + HeaderField hent = entry.getValue(); + byte[] fieldBytes = hdrFieldsMap.get(field); + // Let's skip optional fields when not set + if (fieldBytes != null) { + int off = getFieldOffset(field, hent); + int nbits = getFieldNumBits(field, hent); + try { + ByteUtils.setBits(packetBytes, fieldBytes, off, nbits); + } catch (RuntimeException e) { + String msg = "Failed to serialize field: " + field + + ": off=" + off + ", size=" + nbits + + ", total=" + fieldBytes.length; + throw new PacketException(msg, e); + } + } + } + + // Perform post serialize operations (like checksum computation) + postSerializeCustomOperation(packetBytes); + + if (LOG.isTraceEnabled()) { + LOG.trace("Serialized: {}: {}", getClass().getSimpleName(), + ByteUtils.toHexString(packetBytes)); + } + + return packetBytes; + } + + /** + * This method gets called at the end of the serialization process. + * + * It is intended for the child packets to insert some custom data into the + * output byte stream which cannot be done or cannot be done efficiently + * during the normal Packet.serialize() path. An example is the checksum + * computation for IPv4. + * + * @param myBytes Serialized bytes. + * @throws PacketException An error occurred. + */ + protected void postSerializeCustomOperation(byte[] myBytes) + throws PacketException { + } + + /** + * This method re-computes the checksum of the bits received on the wire + * and validates it with the checksum in the bits received. + * + * Since the computation of checksum varies based on the protocol, + * this method is overridden. Currently only IPv4 and ICMP do checksum + * computation and validation. TCP and UDP need to implement these if + * required. + * + * @param data The byte stream representing the Ethernet frame. + * @param offset The bit offset from where the byte array corresponding to + * this Packet starts in the frame + * @throws PacketException An error occurred. + */ + protected void postDeserializeCustomOperation(byte[] data, int offset) + throws PacketException { + } + + /** + * Set a class that specifies the type of packets encapsulated by this + * packet. + * + * @param cls A class that specifies the type of the payload packet. + */ + protected final void setPayloadClass(Class cls) { + payloadClass = cls; + } + + /** + * Associate the specified value with the specified header field. + * + * @param name The name of the header field. + * @param value The value to be associated with the specified header + * field. {@code null} cannot be specified. + */ + protected void setHeaderField(String name, byte[] value) { + hdrFieldsMap.put(name, value); + } + + /** + * Return a map that keeps packet header fields. + * + * @return A map that keeps packet header fields. + */ + protected final Map getHeaderFieldMap() { + return hdrFieldsMap; + } + + /** + * Gets the header length in bits. + * + * @return The header length in bits. + */ + public int getHeaderSize() { + int size = 0; + + /* + * We need to iterate over the fields that were read in the frame + * (hdrFieldsMap) not all the possible ones described in the map + * returned by getHeaderFormat(). + * For ex, 802.1Q may or may not be there + */ + Map fmtMap = getHeaderFormat(); + for (Entry fieldEntry: hdrFieldsMap.entrySet()) { + if (fieldEntry.getValue() != null) { + String field = fieldEntry.getKey(); + size += getFieldNumBits(field, fmtMap.get(field)); + } + } + return size; + } + + /** + * This method fetches the start bit offset for header field specified by + * {@code name}. + * + * @param name The name of the header field. + * @return The offset of the requested field. + */ + public final int getFieldOffset(String name) { + return getFieldOffset(name, getHeaderFormat().get(name)); + } + + /** + * This method fetches the number of bits for header field specified by + * {@code name}. + * + * @param name The name of the header field. + * @return The number of bits of the requested field. + */ + public final int getFieldNumBits(String name) { + return getFieldNumBits(name, getHeaderFormat().get(name)); + } + + /** + * Returns the raw payload carried by this packet in case payload was not + * parsed. Caller can call this function in case the getPaylod() returns + * {@code null}. + * + * @return The raw payload if not parsable as an array of bytes. + * {@code null} otherwise + */ + public byte[] getRawPayload() { + return (rawPayload == null) ? null : rawPayload.clone(); + } + + /** + * Set a raw payload in the packet class. + * + * @param bytes The raw payload as byte array. + */ + public void setRawPayload(byte[] bytes) { + rawPayload = (bytes == null || bytes.length == 0) + ? null : bytes.clone(); + } + + /** + * Return whether the deserialized packet is to be considered corrupted. + * This is the case when the checksum computed after reconstructing the + * packet received from wire is not equal to the checksum read from the + * stream. For the Packet class which do not have a checksum field, this + * function will always return false. + * + * @return true if the deserialized packet's recomputed checksum is not + * equal to the packet carried checksum + */ + public final boolean isCorrupted() { + return corrupted; + } + + /** + * Set a boolean value which determines whether this packet is corrupted + * or not. + * + * @param c {@code true} indicates that this packet is corrupted. + */ + protected final void setCorrupted(boolean c) { + corrupted = c; + } + + /** + * Return the size of the raw payload in this packet. + * + * @return The number of bytes in the raw payload. + */ + protected final int getRawPayloadSize() { + return (rawPayload == null) ? 0 : rawPayload.length; + } + + /** + * Return the offset of the header field configured in the given instance. + * + * @param name The name of the header field. + * @param entry The header field entry associated with {@code name}. + * @return The offset of the requested field. + */ + protected int getFieldOffset(String name, HeaderField entry) { + return entry.getOffset(); + } + + /** + * Return the number of bits in the header field configured in the given + * instance. + * + * @param name The name of the header field. + * @param entry The header field entry associated with {@code name}. + * @return The number of bits of the requested field. + */ + protected int getFieldNumBits(String name, HeaderField entry) { + return entry.getNumBits(); + } + + /** + * Compare the given header field values. + * + * @param name The name of the header field. + * @param value1 The first header field value to be compared. + * @param value2 The second header field value to be compared. + * @return {@code true} only if the given two header field values are + * identical. + */ + protected boolean equalsField(String name, byte[] value1, byte[] value2) { + boolean ret = (value1 == value2); + if (!ret) { + // null is identical to zero. + byte[] v1 = value1; + byte[] v2 = value2; + if (v1 == null) { + v1 = new byte[v2.length]; + } else if (v2 == null) { + v2 = new byte[v1.length]; + } + ret = Arrays.equals(v1, v2); + } + + return ret; + } + + /** + * Return the value of the specified field as a byte array. + * + * @param name The name of the field. + * @return A byte array. + */ + protected final byte[] getBytes(String name) { + byte[] value = hdrFieldsMap.get(name); + return (value == null) ? null : value.clone(); + } + + /** + * Return the value of the specified field as a byte. + * + * @param name The name of the field. + * @return A byte value. + */ + protected final byte getByte(String name) { + byte[] value = hdrFieldsMap.get(name); + return (value == null) ? 0 : value[0]; + } + + /** + * Return the value of the specified field as an integer. + * + * @param name The name of the field. + * @return An integer value. + */ + protected final int getInt(String name) { + byte[] value = hdrFieldsMap.get(name); + return (value == null) ? 0 : toInteger(value); + } + + /** + * Return the value of the specified field as a short integer. + * + * @param name The name of the field. + * @return A short integer value. + */ + protected final short getShort(String name) { + byte[] value = hdrFieldsMap.get(name); + return (value == null) ? 0 : toShort(value); + } + + /** + * Return the value of the specified field as an IPv4 address. + * + * @param name The name of the field. + * @return An {@link Ip4Network} instance. + */ + protected final Ip4Network getIp4Network(String name) { + byte[] value = hdrFieldsMap.get(name); + return (value == null) ? new Ip4Network(0) : new Ip4Network(value); + } + + /** + * Determine whether the given value represents a zero short value or not. + * + * @param value A byte array that contains a short integer. + * @return {@code true} only if the given value represents a zero. + */ + protected final boolean isZeroShort(byte[] value) { + return (value == null || toShort(value) == 0); + } + + /** + * Return a map that determines the format of the packet. + * + * @return A map that determines the format of the packet. + */ + protected abstract Map getHeaderFormat(); + + /** + * Compute the hash code of the header field map. + * + * @return The hash code of the header field map. + */ + private int headerHashCode() { + int h = 0; + Map fmtMap = getHeaderFormat(); + for (Entry entry: fmtMap.entrySet()) { + String field = entry.getKey(); + HeaderField hf = entry.getValue(); + h += (field.hashCode() ^ hf.hash(hdrFieldsMap.get(field))); + } + + return h; + } + + /** + * Determine whether the given header field map is equal to the map + * configured in this instance or not. + * + * @param map The header field map to be compared. + * Specifying {@code null} results in undefined behavior. + * @return {@code true} only if the given map is equal to the header + * field map in this instance. + */ + private boolean headerEquals(Map map) { + for (String field: getHeaderFormat().keySet()) { + byte[] myData = hdrFieldsMap.get(field); + byte[] data = map.get(field); + if (!equalsField(field, myData, data)) { + return false; + } + } + + return true; + } + + /** + * Create a deep copy of the header field map in this packet. + * + * @return A deep copy of the header field map in this packet. + */ + private Map headerClone() { + Map copy = new HashMap<>(); + for (Entry entry: hdrFieldsMap.entrySet()) { + String field = entry.getKey(); + byte[] data = entry.getValue(); + copy.put(field, data.clone()); + } + + return copy; + } + + // Object + + /** + * Return the hash code of this object. + * + *

+ * Note that this method never uses the payload to compute the hash code. + *

+ * + * @return The hash code. + */ + @Override + public final int hashCode() { + return getClass().hashCode() * HASH_PRIME + headerHashCode(); + } + + /** + * Determine whether the given object is identical to this object. + * + *

+ * Note that this method never compares the payload encapsulated by + * the packet. + *

+ * + * @param o An object to be compared. + * @return {@code true} if identical. Otherwise {@code false}. + */ + @Override + public final boolean equals(Object o) { + boolean ret = (o == this); + if (!ret && o != null && getClass().equals(o.getClass())) { + Packet pkt = (Packet)o; + ret = headerEquals(pkt.hdrFieldsMap); + } + + return ret; + } + + /** + * Return a string representation of this object. + * + * @return A string representation of this object. + */ + @Override + public final String toString() { + StringBuilder builder = new StringBuilder(). + append(getClass().getSimpleName()).append('{'); + String sep = ""; + for (String field: getHeaderFormat().keySet()) { + byte[] value = hdrFieldsMap.get(field); + builder.append(sep).append(field).append('='). + append(ByteUtils.toHexString(value)); + sep = ", "; + } + + return builder.append('}').toString(); + } + + /** + * Return a deep copy of this packet. + * + * @return A deep copy of this packet. + */ + @Override + public Packet clone() { + try { + Packet copy = (Packet)super.clone(); + copy.hdrFieldsMap = headerClone(); + + // Copy the payload. + // Note that we don't need to copy raw payload because it is + // never modified. + if (payload != null) { + copy.payload = payload.clone(); + } + + return copy; + } catch (CloneNotSupportedException e) { + throw new IllegalStateException("clone() failed", e); + } + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/PacketException.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/PacketException.java new file mode 100644 index 00000000..2e465c63 --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/PacketException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.opendaylight.vtn.manager.VTNException; + +/** + * {@code VTNException} is an exception raised when the packet serialization + * or deserialization fails. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class PacketException extends VTNException { + /** + * Version number for serialization. + */ + private static final long serialVersionUID = -257294779623090915L; + + /** + * Construct a new exception. + * + * @param msg The detailed message. + */ + public PacketException(String msg) { + super(msg); + } + + /** + * Construct a new exception with specifying the cause of error. + * + * @param msg The detailed message. + * @param cause The {@link Throwable} object which indicates the cause + * of error. + */ + public PacketException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/TCP.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/TCP.java new file mode 100644 index 00000000..565174f4 --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/TCP.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; + +import java.util.Map; + +/** + * {@code TCP} describes an TCP packet. + * + *

+ * TCP option is not supported. TCP option is treated as a part of TCP + * payload.e + *

+ *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class TCP extends Packet { + /** + * The number of bits in the TCP header, excluding options. + */ + private static final int HEADER_SIZE = 160; + + /** + * The field name that indicates the source port number. + */ + private static final String SRCPORT = "SourcePort"; + + /** + * The field name that indicates the destination port number. + */ + private static final String DESTPORT = "DestinationPort"; + + /** + * The field name that indicates the TCP sequence number. + */ + private static final String SEQNUMBER = "SequenceNumber"; + + /** + * The field name that indicates the TCP acknowledgement number. + */ + private static final String ACKNUMBER = "AcknowledgementNumber"; + + /** + * The field name that indicates the data offset. + */ + private static final String DATAOFFSET = "DataOffset"; + + /** + * The field name that indicates the reserved field. + */ + private static final String RESERVED = "Reserved"; + + /** + * The field name that indicates the header length and TCP flags. + */ + private static final String HEADERLENFLAGS = "HeaderLenFlags"; + + /** + * The field name that indicates the TCP window size. + */ + private static final String WINDOWSIZE = "WindowSize"; + + /** + * The field name that indicates the TCP checksum. + */ + private static final String CHECKSUM = "Checksum"; + + /** + * The field name that indicates the urgent pointer. + */ + private static final String URGENTPOINTER = "UrgentPointer"; + + /** + * The number of bits in the data offset field. + */ + private static final int BITS_DATAOFFSET = 4; + + /** + * The number of bits in the reserved field. + */ + private static final int BITS_RESERVED = 3; + + /** + * The number of bits in the header length and TCP flags field. + */ + private static final int BITS_HEADERLENFLAGS = 9; + + /** + * A map that determines the TCP packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * Initialize static fields. + */ + static { + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(SRCPORT, Short.SIZE). + addNumber(DESTPORT, Short.SIZE). + addNumber(SEQNUMBER, Integer.SIZE). + addNumber(ACKNUMBER, Integer.SIZE). + addNumber(DATAOFFSET, BITS_DATAOFFSET). + addNumber(RESERVED, BITS_RESERVED). + addNumber(HEADERLENFLAGS, BITS_HEADERLENFLAGS). + addNumber(WINDOWSIZE, Short.SIZE). + addNumber(CHECKSUM, Short.SIZE). + addNumber(URGENTPOINTER, Short.SIZE). + build(); + } + + /** + * Sets the TCP source port for the current TCP object instance. + * + * @param port The source port number. + * @return This instance. + */ + public TCP setSourcePort(short port) { + getHeaderFieldMap().put(SRCPORT, toBytes(port)); + return this; + } + + /** + * Sets the TCP destination port for the current TCP object instance. + * + * @param port The destination port number. + * @return This instance. + */ + public TCP setDestinationPort(short port) { + getHeaderFieldMap().put(DESTPORT, toBytes(port)); + return this; + } + + /** + * Sets the TCP sequence number for the current TCP object instance. + * + * @param seq The TCP sequence number. + * @return This instance. + */ + public TCP setSequenceNumber(int seq) { + getHeaderFieldMap().put(SEQNUMBER, toBytes(seq)); + return this; + } + + /** + * Sets the TCP data offset for the current TCP object instance. + * + * @param off The TCP data offset. + * @return This instance. + */ + public TCP setDataOffset(byte off) { + getHeaderFieldMap().put(DATAOFFSET, new byte[]{off}); + return this; + } + + /** + * Sets the TCP reserved bits for the current TCP object instance. + * + * @param resv The reserved field value. + * @return This instance. + */ + public TCP setReserved(byte resv) { + getHeaderFieldMap().put(RESERVED, new byte[]{resv}); + return this; + } + + /** + * Sets the TCP Ack number for the current TCP object instance. + * + * @param acq The TCP acknowledgement number. + * @return This instance. + */ + public TCP setAckNumber(int acq) { + getHeaderFieldMap().put(ACKNUMBER, toBytes(acq)); + return this; + } + + /** + * Sets the TCP flags for the current TCP object instance. + * + * @param flags The TCP flags. + * @return This instance. + */ + public TCP setHeaderLenFlags(short flags) { + getHeaderFieldMap().put(HEADERLENFLAGS, toBytes(flags)); + return this; + } + + /** + * Sets the TCP window size for the current TCP object instance. + * + * @param wsize The TCP window size. + * @return This instance. + */ + public TCP setWindowSize(short wsize) { + getHeaderFieldMap().put(WINDOWSIZE, toBytes(wsize)); + return this; + } + + /** + * Sets the TCP checksum for the current TCP object instance. + * + * @param cksum The TCP checksum. + * @return This instance. + */ + public TCP setChecksum(short cksum) { + getHeaderFieldMap().put(CHECKSUM, toBytes(cksum)); + return this; + } + + /** + * Sets the TCP Urgent Pointer for the current TCP object instance. + * + * @param urg The TCP urgent pointer. + * @return This instance. + */ + public TCP setUrgentPointer(short urg) { + getHeaderFieldMap().put(URGENTPOINTER, toBytes(urg)); + return this; + } + + /** + * Gets the stored source port value of TCP header. + * + * @return The source port number. + */ + public short getSourcePort() { + return getShort(SRCPORT); + } + + /** + * Gets the stored destination port value of TCP header. + * + * @return The destination port number. + */ + public short getDestinationPort() { + return getShort(DESTPORT); + } + + /** + * Return the TCP sequence number. + * + * @return The TCP sequence number. + */ + public int getSequenceNumber() { + return getInt(SEQNUMBER); + } + + /** + * Return the TCP data offset. + * + * @return The TCP data offset. + */ + public byte getDataOffset() { + return getByte(DATAOFFSET); + } + + /** + * Return the reserved field value. + * + * @return The value configured in the reserved field. + */ + public byte getReserved() { + return getByte(RESERVED); + } + + /** + * Return the TCP acknowledgement number. + * + * @return The TCP acknowledgement number. + */ + public int getAckNumber() { + return getInt(ACKNUMBER); + } + + /** + * Return the TCP header length and flags. + * + * @return The value of TCP header length and flags. + */ + public short getHeaderLenFlags() { + return getShort(HEADERLENFLAGS); + } + + /** + * Return the TCP window size. + * + * @return The TCP window size. + */ + public short getWindowSize() { + return getShort(WINDOWSIZE); + } + + /** + * Get the stored checksum value of the TCP header. + * + * @return The TCP checksum. + */ + public short getChecksum() { + return getShort(CHECKSUM); + } + + /** + * Return the TCP urgent pointer. + * + * @return The TCP urgent pointer. + */ + public short getUrgentPointer() { + return getShort(URGENTPOINTER); + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The TCP header size in bits. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public TCP clone() { + return (TCP)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/UDP.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/UDP.java new file mode 100644 index 00000000..9fdaa83f --- /dev/null +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/packet/UDP.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.toBytes; + +import java.util.Map; + +/** + * {@code UDP} describes an UDP packet. + * + *

+ * This class is provided only for VTN internal use. + * This class may be changed without any notice. + *

+ * + * @since Beryllium + */ +public final class UDP extends Packet { + /** + * The number of bits in the UDP header. + */ + private static final int HEADER_SIZE = 64; + + /** + * The field name that indicates the source port number. + */ + private static final String SRCPORT = "SourcePort"; + + /** + * The field name that indicates the destination port number. + */ + private static final String DESTPORT = "DestinationPort"; + + /** + * The field name that indicates the packet length. + */ + private static final String LENGTH = "Length"; + + /** + * The field name that indicates the UDP checksum. + */ + private static final String CHECKSUM = "Checksum"; + + /** + * A map that determines the UDP packet header format. + */ + private static final Map HEADER_FORMAT; + + /** + * Initialize static fields. + */ + static { + HEADER_FORMAT = new HeaderMapBuilder(). + addNumber(SRCPORT, Short.SIZE). + addNumber(DESTPORT, Short.SIZE). + addNumber(LENGTH, Short.SIZE). + addNumber(CHECKSUM, Short.SIZE). + build(); + } + + /** + * Get the stored source port. + * + * @return The source port number. + */ + public short getSourcePort() { + return getShort(SRCPORT); + } + + /** + * Get the stored destination port. + * + * @return The destination port number. + */ + public short getDestinationPort() { + return getShort(DESTPORT); + } + + /** + * Gets the stored length of UDP packet. + * + * @return The number of bytes in the UDP datagram. + */ + public short getLength() { + return getShort(LENGTH); + } + + /** + * Get the stored checksum value of the UDP packet. + * + * @return The UDP checksum. + */ + public short getChecksum() { + return getShort(CHECKSUM); + } + + /** + * Sets the sourcePort value for the current UDP object instance. + * + * @param port The source port number. + * @return This instance. + */ + public UDP setSourcePort(short port) { + getHeaderFieldMap().put(SRCPORT, toBytes(port)); + return this; + } + + /** + * Sets the destinationPort value for the current UDP object instance. + * + * @param port The destination port number. + * @return This instance. + */ + public UDP setDestinationPort(short port) { + getHeaderFieldMap().put(DESTPORT, toBytes(port)); + return this; + } + + /** + * Set the UDP header length value for the current UDP object instance. + * + * @param len The number of bytes in the UDP datagram. + * @return This instance. + */ + public UDP setLength(short len) { + getHeaderFieldMap().put(LENGTH, toBytes(len)); + return this; + } + + /** + * Set the checksum for the current UDP object instance. + * + * @param cksum The UDP checksum. + * @return This instance. + */ + public UDP setChecksum(short cksum) { + getHeaderFieldMap().put(CHECKSUM, toBytes(cksum)); + return this; + } + + // Packet + + /** + * Gets the header size in bits. + * + * @return The UDP header size in bits. + */ + @Override + public int getHeaderSize() { + return HEADER_SIZE; + } + + /** + * {@inheritDoc} + */ + @Override + protected Map getHeaderFormat() { + return HEADER_FORMAT; + } + + // Object + + /** + * {@inheritDoc} + */ + @Override + public UDP clone() { + return (UDP)super.clone(); + } +} diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/ByteUtils.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/ByteUtils.java index 2d280b44..e65616fa 100644 --- a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/ByteUtils.java +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/ByteUtils.java @@ -8,6 +8,8 @@ package org.opendaylight.vtn.manager.util; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_BYTE; + /** * {@code ByteUtils} class is a collection of utility class fields and methods * for byte array handling. @@ -31,6 +33,126 @@ public final class ByteUtils { */ public static final int HEX_RADIX = 16; + /** + * A private class to convert bit stream into the specified byte array. + */ + private static final class BitStream { + /** + * The byte array to store result. + */ + private final byte[] result; + + /** + * The current byte. + */ + private byte current; + + /** + * The byte offset to store the next byte. + */ + private int resultOff; + + /** + * The bit offset to store the next bits into the current byte. + */ + private int bitOff; + + /** + * Construct a new instance that sets LSB aligned bits into the + * specified byte array. + * + * @param array A byte array to store result. + * @param nbits The total number of bits to be added. + */ + private BitStream(byte[] array, int nbits) { + result = array; + int mod = nbits % Byte.SIZE; + bitOff = (mod == 0) ? 0 : Byte.SIZE - mod; + } + + /** + * Construct a new instance that sets bits into the specified byte + * array with specifying the start position. + * + * @param array A byte array to store result. + * @param start Starting byte offset in the given array. + * @param boff Starting bit offset in the first byte of the specified + * byte array. + */ + private BitStream(byte[] array, int start, int boff) { + result = array; + bitOff = boff; + resultOff = start; + if (boff != 0) { + byte b = result[start]; + current = (byte)(b & (MASK_BYTE << (Byte.SIZE - boff))); + } + } + + /** + * Add all the bits in the given byte to the bit stream. + * + * @param value A byte value. + */ + private void add(byte value) { + byte b = (byte)((value & MASK_BYTE) >>> bitOff); + current |= b; + result[resultOff++] = current; + current = (byte)(value << (Byte.SIZE - bitOff)); + } + + /** + * Add LSB aligned bits in the given byte to the bit stream. + * + * @param value A byte value. + * @param start The start bit offset. + * @param nbits The number of bits to be added. + */ + private void add(byte value, int start, int nbits) { + byte v = (byte)(value << start); + byte b = (byte)((v & MASK_BYTE) >>> bitOff); + int off = bitOff + nbits; + if (off < Byte.SIZE) { + int nshift = Byte.SIZE - off; + b = (byte)(b & (MASK_BYTE << nshift)); + current |= b; + bitOff = off; + } else { + current |= b; + result[resultOff++] = current; + bitOff = off - Byte.SIZE; + if (bitOff > 0) { + int nright = Byte.SIZE - nbits; + int nleft = Byte.SIZE - bitOff; + current = (byte)(((v & MASK_BYTE) >>> nright) << nleft); + } else { + current = 0; + } + } + } + + /** + * Write unwritten bits into the target array. + * + * @return {@code true} if at least one bit is written. + * {@code false} if all added bits are already written. + */ + private boolean flush() { + boolean ret = (bitOff != 0); + if (ret) { + // Merge with a byte at the output byte. + byte cur = (byte)(result[resultOff] << bitOff); + cur = (byte)((cur & MASK_BYTE) >>> bitOff); + + int nshift = Byte.SIZE - bitOff; + byte b = (byte)(((current & MASK_BYTE) >>> nshift) << nshift); + result[resultOff] = (byte)(cur | b); + } + + return ret; + } + } + /** * Private constructor that protects this class from instantiating. */ @@ -55,7 +177,7 @@ public final class ByteUtils { StringBuilder builder = new StringBuilder(); for (byte b: bytes) { builder.append(sep). - append(String.format("%02x", b & NumberUtils.MASK_BYTE)); + append(String.format("%02x", b & MASK_BYTE)); sep = HEX_SEPARATOR; } return builder.toString(); @@ -100,10 +222,130 @@ public final class ByteUtils { */ public static int parseHexOctet(String hex) { int octet = Integer.valueOf(hex, HEX_RADIX).intValue(); - if (octet < 0 || octet > NumberUtils.MASK_BYTE) { + if (octet < 0 || octet > MASK_BYTE) { throw new NumberFormatException("Octet out of range: " + hex); } return octet; } + + /** + * Read the specified number of bits from the given byte array. + * + * @param data A byte array. + * Specifying {@code null} results in undefined behavior. + * @param off The bit offset to start fetching bits. + * @param nbits The number of bits to be fetched. + * @return A byte array that contains fetched bits (LSB aligned). + * @since Beryllium + */ + public static byte[] getBits(byte[] data, int off, int nbits) { + int round = Byte.SIZE - 1; + int nbytes = (nbits + round) / Byte.SIZE; + byte[] result = new byte[nbytes]; + if (nbytes != 0) { + // Byte offset to the first byte to be read. + int start = off / Byte.SIZE; + + // Start bit offset in the first byte. + int firstBit = off - (start * Byte.SIZE); + + // The last bit offset (exclusive). + int lastoff = off + nbits; + + // End bit offset (exclusive) in the last byte. + int lastBit = lastoff % Byte.SIZE; + + if (firstBit == 0 && lastBit == 0) { + // No need to shift bits. + System.arraycopy(data, start, result, 0, nbytes); + } else { + BitStream bst = new BitStream(result, nbits); + + // Add bits in the first byte. + boolean moreBytes = ((firstBit + nbits) > Byte.SIZE); + int nb = (moreBytes) ? Byte.SIZE - firstBit : nbits; + bst.add(data[start], firstBit, nb); + + if (moreBytes) { + // Determine the number of bytes to be read from the + // source byte array. + int nread = (lastoff + round) / Byte.SIZE; + if (lastBit != 0) { + nread--; + } + + // Add bits except for the last byte. + int index; + for (index = start + 1; index < nread; index++) { + bst.add(data[index]); + } + + if (lastBit != 0) { + // Add bits in the last byte. + bst.add(data[index], 0, lastBit); + } + } + + assert !bst.flush(); + } + } + + return result; + } + + /** + * Copy bits in the specified input byte array into the specified output + * array. + * + * @param output A byte array to store bits. + * Specifying {@code null} results in undefined behavior. + * @param input A byte array to be copied. + * Bits in this array are expected to be aligned to LSB. + * Specifying {@code null} results in undefined behavior. + * @param off The bit offset of {@code output} to start inserting bits + * from {@code input}. + * @param nbits The number of bits to be copied. + * @since Beryllium + */ + public static void setBits(byte[] output, byte[] input, int off, + int nbits) { + int round = Byte.SIZE - 1; + int nbytes = (nbits + round) / Byte.SIZE; + if (nbytes != 0) { + // Output byte offset to the first byte to store. + int start = off / Byte.SIZE; + + // Output start bit offset in the first byte. + int firstBit = off - (start * Byte.SIZE); + + // The number of bits (from LSB) in the first input byte to be + // copied. + int inputBits = nbits % Byte.SIZE; + + if (firstBit == 0 && inputBits == 0) { + // No need to shift bits. + System.arraycopy(input, 0, output, start, nbytes); + } else { + BitStream bst = new BitStream(output, start, firstBit); + + int index; + if (inputBits == 0) { + index = 0; + } else { + // Copy bits in the first byte. + bst.add(input[0], Byte.SIZE - inputBits, inputBits); + index = 1; + } + + // Copy the rest of bits. + for (; index < nbytes; index++) { + bst.add(input[index]); + } + + // Flush unwritten bits. + bst.flush(); + } + } + } } diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/EtherTypes.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/EtherTypes.java index 5f0afab5..df8d6b51 100644 --- a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/EtherTypes.java +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/EtherTypes.java @@ -8,8 +8,14 @@ package org.opendaylight.vtn.manager.util; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + /** * {@code EtherTypes} contains the common Ethernet types. + * + * @since Beryllium */ public enum EtherTypes { /** @@ -37,10 +43,41 @@ public enum EtherTypes { */ LLDP(0x88cc); + /** + * A map which keeps pairs of Ethernet types and {@link EtherTypes} + * instances. + */ + private static final Map TYPE_MAP; + /** * The Ethernet type value. */ - private final int value; + private final short value; + + /** + * Initialize static fields. + */ + static { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (EtherTypes type: EtherTypes.values()) { + builder.put(type.value, type); + } + + TYPE_MAP = builder.build(); + } + + /** + * Convert the given Ethernet type vlaue into a {@link EtherTypes} + * instance. + * + * @param value An Ethernet type value. + * @return An {@link EtherTypes} instance if found. + * {@code null} if not found. + */ + public static EtherTypes forValue(short value) { + return TYPE_MAP.get(value); + } /** * Construct a new instance. @@ -48,7 +85,7 @@ public enum EtherTypes { * @param v The Ethernet type value. */ private EtherTypes(int v) { - value = v; + value = (short)v; } /** @@ -57,7 +94,7 @@ public enum EtherTypes { * @return An integer that represents the Ethernet type value. */ public int intValue() { - return value; + return (value & NumberUtils.MASK_SHORT); } /** @@ -66,6 +103,6 @@ public enum EtherTypes { * @return A short integer that represents the Ethernet type value. */ public short shortValue() { - return (short)value; + return value; } } diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/InetProtocols.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/InetProtocols.java index 6daf9255..568f14ff 100644 --- a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/InetProtocols.java +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/InetProtocols.java @@ -8,8 +8,16 @@ package org.opendaylight.vtn.manager.util; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_BYTE; + +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + /** * {@code InetProtocols} contains the common IP protocol numbers. + * + * @since Beryllium */ public enum InetProtocols { /** @@ -27,10 +35,41 @@ public enum InetProtocols { */ UDP(17); + /** + * A map which keeps pairs of IP protocol value and {@link InetProtocols} + * instances. + */ + private static final Map PROTO_MAP; + /** * The IP protocol number. */ - private final int value; + private final byte value; + + /** + * Initialize static fields. + */ + static { + ImmutableMap.Builder builder = + ImmutableMap.builder(); + for (InetProtocols proto: InetProtocols.values()) { + builder.put(proto.value, proto); + } + + PROTO_MAP = builder.build(); + } + + /** + * Convert the given IP protocol number into a {@link InetProtocols} + * instance. + * + * @param proto An IP protocol number. + * @return An {@link InetProtocols} instance if found. + * {@code null} if not found. + */ + public static InetProtocols forValue(byte proto) { + return PROTO_MAP.get(proto); + } /** * Construct a new instance. @@ -38,7 +77,7 @@ public enum InetProtocols { * @param v The IP protocol number. */ private InetProtocols(int v) { - value = v; + value = (byte)v; } /** @@ -47,7 +86,7 @@ public enum InetProtocols { * @return An integer that represents the IP protocol number. */ public int intValue() { - return value; + return (int)(value & MASK_BYTE); } /** @@ -56,7 +95,7 @@ public enum InetProtocols { * @return A short integer that represents the IP protocol number. */ public short shortValue() { - return (short)value; + return (short)(value & MASK_BYTE); } /** @@ -65,6 +104,6 @@ public enum InetProtocols { * @return A byte that represents the IP protocol number. */ public byte byteValue() { - return (byte)value; + return value; } } diff --git a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/NumberUtils.java b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/NumberUtils.java index 2bf4a7ff..785d3a42 100644 --- a/manager/api/src/main/java/org/opendaylight/vtn/manager/util/NumberUtils.java +++ b/manager/api/src/main/java/org/opendaylight/vtn/manager/util/NumberUtils.java @@ -27,6 +27,20 @@ public final class NumberUtils { */ public static final int NUM_OCTETS_INTEGER = Integer.SIZE / Byte.SIZE; + /** + * The number of octets in a short integer value. + * + * @since Beryllium + */ + public static final int NUM_OCTETS_SHORT = Short.SIZE / Byte.SIZE; + + /** + * The number of octets in a byte value. + * + * @since Beryllium + */ + public static final int NUM_OCTETS_BYTE = 1; + /** * A mask value which represents all bits in a byte value. */ @@ -121,10 +135,7 @@ public final class NumberUtils { * The length of {@code b} is not 4. */ public static int toInteger(byte[] b) { - if (b.length != NUM_OCTETS_INTEGER) { - throw new IllegalArgumentException( - "Invalid byte array length: " + b.length); - } + checkLength(b, NUM_OCTETS_INTEGER); int index = 0; int value = (b[index++] & MASK_BYTE) << INT_SHIFT_OCTET1; @@ -133,15 +144,46 @@ public final class NumberUtils { return value | (b[index] & MASK_BYTE); } + /** + * Convert a 2 bytes array into a short integer number. + * + * @param b A 2 bytes array. + * @return A short integer number. + * @throws NullPointerException + * {@code b} is {@code null}. + * @throws IllegalArgumentException + * The length of {@code b} is not 2. + * @since Beryllium + */ + public static short toShort(byte[] b) { + checkLength(b, NUM_OCTETS_SHORT); + + int value = (b[0] & MASK_BYTE) << Byte.SIZE; + return (short)(value | (b[1] & MASK_BYTE)); + } + /** * Convert an integer value into an byte array. * - * @param i An integer value. + * @param v An integer value. * @return A converted byte array. */ - public static byte[] toBytes(int i) { + public static byte[] toBytes(int v) { byte[] b = new byte[NUM_OCTETS_INTEGER]; - setInt(b, 0, i); + setInt(b, 0, v); + return b; + } + + /** + * Convert a short integer value into an byte array. + * + * @param v A short integer value. + * @return A converted byte array. + * @since Beryllium + */ + public static byte[] toBytes(short v) { + byte[] b = new byte[NUM_OCTETS_SHORT]; + setShort(b, 0, v); return b; } @@ -251,4 +293,21 @@ public final class NumberUtils { public static boolean equalsDouble(double d1, double d2) { return (Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2)); } + + /** + * Check the length of the given byte array. + * + * @param b The byte array to be tested. + * @param len The expected length of the byte array. + * @throws NullPointerException + * {@code b} is {@code null}. + * @throws IllegalArgumentException + * The length of {@code b} is invalid. + */ + private static void checkLength(byte[] b, int len) { + if (b.length != len) { + throw new IllegalArgumentException( + "Invalid byte array length: " + b.length); + } + } } diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/VTNExceptionTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/VTNExceptionTest.java index 75bc3799..5f8eda1f 100644 --- a/manager/api/src/test/java/org/opendaylight/vtn/manager/VTNExceptionTest.java +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/VTNExceptionTest.java @@ -94,7 +94,7 @@ public class VTNExceptionTest extends TestBase { /** * Test case for - * {@link VTNException#VTNException(VtnErrorTag, String, Thowable)} and + * {@link VTNException#VTNException(VtnErrorTag, String, Throwable)} and * the followings. * *
    @@ -155,7 +155,7 @@ public class VTNExceptionTest extends TestBase { /** * Test case for - * {@link VTNException#VTNException(String, Thowable)} and + * {@link VTNException#VTNException(String, Throwable)} and * the followings. * *
      diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ARPTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ARPTest.java new file mode 100644 index 00000000..74e1f296 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ARPTest.java @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.util.Ip4Network; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link ARP}. + */ +public class ARPTest extends TestBase { + /** + * Test case for hardware type. + * + *
        + *
      • {@link ARP#getHardwareType()}
      • + *
      • {@link ARP#setHardwareType(short)}
      • + *
      + */ + @Test + public void testGetHardwareType() { + ARP arp = new ARP(); + assertEquals((short)0, arp.getHardwareType()); + + short[] types = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short hwtype: types) { + assertSame(arp, arp.setHardwareType(hwtype)); + assertEquals(hwtype, arp.getHardwareType()); + } + } + + /** + * Test case for protocol type. + * + *
        + *
      • {@link ARP#getProtocolType()}
      • + *
      • {@link ARP#setProtocolType(short)}
      • + *
      + */ + @Test + public void testGetProtocolType() { + ARP arp = new ARP(); + assertEquals((short)0, arp.getProtocolType()); + + short[] types = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short ptype: types) { + assertSame(arp, arp.setProtocolType(ptype)); + assertEquals(ptype, arp.getProtocolType()); + } + } + + /** + * Test case for the hardware address length. + * + *
        + *
      • {@link ARP#getHardwareAddressLength()}
      • + *
      • {@link ARP#setHardwareAddressLength(byte)}
      • + *
      + */ + @Test + public void testGetHardwareAddressLength() { + ARP arp = new ARP(); + assertEquals((byte)0, arp.getHardwareAddressLength()); + + byte[] lengths = {0, 1, 9, 57, 127, -128, -127, -15, -2, -1}; + for (byte len: lengths) { + assertSame(arp, arp.setHardwareAddressLength(len)); + assertEquals(len, arp.getHardwareAddressLength()); + } + } + + /** + * Test cast for the protocol address length. + * + *
        + *
      • {@link ARP#getProtocolAddressLength()}
      • + *
      • {@link ARP#setProtocolAddressLength(byte)}
      • + *
      + */ + @Test + public void testGetProtocolAddressLength() { + ARP arp = new ARP(); + assertEquals((byte)0, arp.getProtocolAddressLength()); + + byte[] lengths = {0, 1, 9, 57, 127, -128, -127, -15, -2, -1}; + for (byte len: lengths) { + assertSame(arp, arp.setProtocolAddressLength(len)); + assertEquals(len, arp.getProtocolAddressLength()); + } + } + + /** + * Test case for the operation code. + * + *
        + *
      • {@link ARP#getOpCode()}
      • + *
      • {@link ARP#setOpCode(short)}
      • + *
      + */ + @Test + public void testGetOpCode() { + ARP arp = new ARP(); + assertEquals((short)0, arp.getOpCode()); + + short[] codes = {0, 1, 2, 100, 127, 128, 30123, 32767, -30000, -2, -1}; + for (short op: codes) { + assertSame(arp, arp.setOpCode(op)); + assertEquals(op, arp.getOpCode()); + } + } + + /** + * Test case for the sender hardware address. + * + *
        + *
      • {@link ARP#getSenderHardwareAddress()}
      • + *
      • {@link ARP#setSenderHardwareAddress(byte[])}
      • + *
      + */ + @Test + public void testGetSenderHardwareAddress() { + ARP arp = new ARP(); + assertEquals(null, arp.getSenderHardwareAddress()); + + EtherAddress[] addrs = { + new EtherAddress(0x123456789abcL), + new EtherAddress(0x001122334455L), + new EtherAddress(0x182cf31fa341L), + }; + + for (EtherAddress eaddr: addrs) { + byte[] baddr = eaddr.getBytes(); + assertSame(arp, arp.setSenderHardwareAddress(baddr)); + + // The specified array should be copied. + baddr[0] = 0; + baddr[1] = 0; + assertArrayEquals(eaddr.getBytes(), + arp.getSenderHardwareAddress()); + } + } + + /** + * Test case for the sender protocol address. + * + *
        + *
      • {@link ARP#getSenderProtocolAddress()}
      • + *
      • {@link ARP#setSenderProtocolAddress(byte[])}
      • + *
      + */ + @Test + public void testGetSenderProtocolAddress() { + ARP arp = new ARP(); + assertEquals(null, arp.getSenderProtocolAddress()); + + Ip4Network[] addrs = { + new Ip4Network("192.168.123.234"), + new Ip4Network("10.20.30.40"), + new Ip4Network("220.39.195.254"), + }; + for (Ip4Network addr: addrs) { + byte[] baddr = addr.getBytes(); + assertSame(arp, arp.setSenderProtocolAddress(baddr)); + + // The specified array should be copied. + baddr[0] = 0; + baddr[1] = 0; + assertArrayEquals(addr.getBytes(), arp.getSenderProtocolAddress()); + } + } + + /** + * Test case for the target hardware address. + * + *
        + *
      • {@link ARP#getSenderHardwareAddress()}
      • + *
      • {@link ARP#setSenderHardwareAddress(byte[])}
      • + *
      + */ + @Test + public void testGetTargetHardwareAddress() { + ARP arp = new ARP(); + assertEquals(null, arp.getTargetHardwareAddress()); + + EtherAddress[] addrs = { + new EtherAddress(0x123456789abcL), + new EtherAddress(0x001122334455L), + new EtherAddress(0x182cf31fa341L), + }; + + for (EtherAddress eaddr: addrs) { + byte[] baddr = eaddr.getBytes(); + assertSame(arp, arp.setTargetHardwareAddress(baddr)); + + // The specified array should be copied. + baddr[0] = 0; + baddr[1] = 0; + assertArrayEquals(eaddr.getBytes(), + arp.getTargetHardwareAddress()); + } + } + + /** + * Test case for the target protocol address. + * + *
        + *
      • {@link ARP#getTargetProtocolAddress()}
      • + *
      • {@link ARP#setTargetProtocolAddress(byte[])}
      • + *
      + */ + @Test + public void testGetTargetProtocolAddress() { + ARP arp = new ARP(); + assertEquals(null, arp.getTargetProtocolAddress()); + + Ip4Network[] addrs = { + new Ip4Network("192.168.123.234"), + new Ip4Network("10.20.30.40"), + new Ip4Network("220.39.195.254"), + }; + for (Ip4Network addr: addrs) { + byte[] baddr = addr.getBytes(); + assertSame(arp, arp.setTargetProtocolAddress(baddr)); + + // The specified array should be copied. + baddr[0] = 0; + baddr[1] = 0; + assertArrayEquals(addr.getBytes(), arp.getTargetProtocolAddress()); + } + } + + /** + * Test case for {@link ARP#clone()}. + */ + @Test + public void testClone() { + short hwtype = 1; + short ptype = 123; + byte hlen = 6; + byte plen = 4; + short op = 7; + EtherAddress sha = new EtherAddress(0x001122334455L); + EtherAddress tha = new EtherAddress(0xa0b0c0d0e0f0L); + Ip4Network spa = new Ip4Network("1.2.3.4"); + Ip4Network tpa = new Ip4Network("192.168.34.56"); + ARP arp = new ARP(). + setHardwareType(hwtype). + setProtocolType(ptype). + setHardwareAddressLength(hlen). + setProtocolAddressLength(plen). + setOpCode(op). + setSenderHardwareAddress(sha.getBytes()). + setTargetHardwareAddress(tha.getBytes()). + setSenderProtocolAddress(spa.getBytes()). + setTargetProtocolAddress(tpa.getBytes()); + + ARP copy = arp.clone(); + assertNotSame(arp, copy); + assertEquals(arp, copy); + assertEquals(arp.hashCode(), copy.hashCode()); + + // Modifying the source packet should never affect a deep copy. + short hwtype1 = 3; + short ptype1 = 45; + byte hlen1 = 4; + byte plen1 = 8; + short op1 = 1; + EtherAddress sha1 = new EtherAddress(0xaabbccddeeffL); + EtherAddress tha1 = new EtherAddress(0x000011112222L); + Ip4Network spa1 = new Ip4Network("10.20.30.40"); + Ip4Network tpa1 = new Ip4Network("10.20.30.1"); + arp.setHardwareType(hwtype1). + setProtocolType(ptype1). + setHardwareAddressLength(hlen1). + setProtocolAddressLength(plen1). + setOpCode(op1). + setSenderHardwareAddress(sha1.getBytes()). + setTargetHardwareAddress(tha1.getBytes()). + setSenderProtocolAddress(spa1.getBytes()). + setTargetProtocolAddress(tpa1.getBytes()); + + assertEquals(hwtype, copy.getHardwareType()); + assertEquals(ptype, copy.getProtocolType()); + assertEquals(hlen, copy.getHardwareAddressLength()); + assertEquals(plen, copy.getProtocolAddressLength()); + assertEquals(op, copy.getOpCode()); + assertArrayEquals(sha.getBytes(), copy.getSenderHardwareAddress()); + assertArrayEquals(tha.getBytes(), copy.getTargetHardwareAddress()); + assertArrayEquals(spa.getBytes(), copy.getSenderProtocolAddress()); + assertArrayEquals(tpa.getBytes(), copy.getTargetProtocolAddress()); + + assertEquals(hwtype1, arp.getHardwareType()); + assertEquals(ptype1, arp.getProtocolType()); + assertEquals(hlen1, arp.getHardwareAddressLength()); + assertEquals(plen1, arp.getProtocolAddressLength()); + assertEquals(op1, arp.getOpCode()); + assertArrayEquals(sha1.getBytes(), arp.getSenderHardwareAddress()); + assertArrayEquals(tha1.getBytes(), arp.getTargetHardwareAddress()); + assertArrayEquals(spa1.getBytes(), arp.getSenderProtocolAddress()); + assertArrayEquals(tpa1.getBytes(), arp.getTargetProtocolAddress()); + } + + /** + * Test for serialization and deserialization. + * + *
        + *
      • {@link Packet#serialize()}
      • + *
      • {@link Packet#deserialize(byte[], int, int)}
      • + *
      + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialize() throws Exception { + byte[] raw = { + // Hardware type. + (byte)0x00, (byte)0x01, + + // Protocol type. + (byte)0x08, (byte)0x00, + + // Hardware address length. + (byte)0x06, + + // Protocol address length. + (byte)0x04, + + // Operation code. + (byte)0x00, 0x01, + + // Sender hardware address. + (byte)0x01, (byte)0x23, (byte)0x45, (byte)0x67, + (byte)0x89, (byte)0xab, + + // Sender protocol address. + (byte)10, (byte)20, (byte)30, (byte)40, + + // Target hardware address. + (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, + (byte)0xff, (byte)0xff, + + // Target protocol address. + (byte)192, (byte)168, (byte)123, (byte)254, + }; + + EtherAddress sha = new EtherAddress(0x0123456789abL); + EtherAddress tha = EtherAddress.BROADCAST; + Ip4Network spa = new Ip4Network("10.20.30.40"); + Ip4Network tpa = new Ip4Network("192.168.123.254"); + + // Deserialize raw packet. + ARP arp = new ARP(); + arp.deserialize(raw, 0, raw.length * Byte.SIZE); + assertEquals((short)1, arp.getHardwareType()); + assertEquals((short)0x800, arp.getProtocolType()); + assertEquals((byte)6, arp.getHardwareAddressLength()); + assertEquals((byte)4, arp.getProtocolAddressLength()); + assertEquals((short)1, arp.getOpCode()); + assertArrayEquals(sha.getBytes(), arp.getSenderHardwareAddress()); + assertArrayEquals(tha.getBytes(), arp.getTargetHardwareAddress()); + assertArrayEquals(spa.getBytes(), arp.getSenderProtocolAddress()); + assertArrayEquals(tpa.getBytes(), arp.getTargetProtocolAddress()); + assertEquals(null, arp.getPayload()); + assertEquals(null, arp.getRawPayload()); + assertEquals(false, arp.isCorrupted()); + + // Serialize packet. + assertArrayEquals(raw, arp.serialize()); + + // Serialize an empty packet. + arp = new ARP(); + byte[] expected = new byte[28]; + assertArrayEquals(expected, arp.serialize()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/EthernetTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/EthernetTest.java new file mode 100644 index 00000000..159d2069 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/EthernetTest.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.util.EtherTypes; +import org.opendaylight.vtn.manager.util.Ip4Network; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link Ethernet}. + */ +public class EthernetTest extends TestBase { + /** + * Test case for {@link Ethernet#getPayloadClass(short)}. + */ + @Test + public void testGetPayloadClass() { + short[] badTypes = { + (short)0x0000, (short)0x0011, (short)0x07ff, (short)0x0805, + (short)0x0899, (short)0x8001, (short)0x8101, (short)0x88a8, + (short)0x88cc, (short)0x9999, (short)0xabcd, (short)0xcdef, + (short)0xcef0, (short)0xf000, (short)0xfff0, (short)0xffff, + }; + + for (short type: badTypes) { + assertEquals(null, Ethernet.getPayloadClass(type)); + } + + assertEquals(IPv4.class, Ethernet.getPayloadClass((short)0x0800)); + assertEquals(ARP.class, Ethernet.getPayloadClass((short)0x0806)); + assertEquals(IEEE8021Q.class, Ethernet.getPayloadClass((short)0x8100)); + } + + /** + * Test case for the destination MAC address. + * + *
        + *
      • {@link Ethernet#getDestinationMACAddress()}
      • + *
      • {@link Ethernet#setDestinationMACAddress(byte[])}
      • + *
      + */ + @Test + public void testGetDestinationMACAddress() { + Ethernet eth = new Ethernet(); + assertEquals(null, eth.getDestinationMACAddress()); + + EtherAddress[] addrs = { + new EtherAddress(0x123456789abcL), + new EtherAddress(0), + EtherAddress.BROADCAST, + new EtherAddress(0x00abcdef1122L), + }; + for (EtherAddress eaddr: addrs) { + byte[] mac = eaddr.getBytes(); + assertSame(eth, eth.setDestinationMACAddress(mac)); + + // Ensure the specified byte array is copied. + mac[0] = (byte)0xae; + assertArrayEquals(eaddr.getBytes(), + eth.getDestinationMACAddress()); + } + } + + /** + * Test case for the source MAC address. + * + *
        + *
      • {@link Ethernet#getSourceMACAddress()}
      • + *
      • {@link Ethernet#setSourceMACAddress(byte[])}
      • + *
      + */ + @Test + public void testSourceMACAddress() { + Ethernet eth = new Ethernet(); + assertEquals(null, eth.getSourceMACAddress()); + + EtherAddress[] addrs = { + new EtherAddress(0x123456789abcL), + new EtherAddress(0), + EtherAddress.BROADCAST, + new EtherAddress(0x00abcdef1122L), + }; + for (EtherAddress eaddr: addrs) { + byte[] mac = eaddr.getBytes(); + assertSame(eth, eth.setSourceMACAddress(mac)); + + // Ensure the specified byte array is copied. + mac[0] = (byte)0xae; + assertArrayEquals(eaddr.getBytes(), + eth.getSourceMACAddress()); + } + } + + /** + * Test case for the Ethernet type. + * + *
        + *
      • {@link Ethernet#getEtherType()}
      • + *
      • {@link Ethernet#setEtherType(short)}
      • + *
      + */ + @Test + public void testGetEthertype() throws Exception { + Ethernet eth = new Ethernet(); + assertEquals((short)0, eth.getEtherType()); + + + short[] values = { + (short)0x0000, (short)0x0001, (short)0x0020, (short)0x03ff, + (short)0x07ff, (short)0x0800, (short)0x0999, (short)0x1abc, + (short)0x5678, (short)0x7fff, (short)0x8000, (short)0x8888, + (short)0xabcd, (short)0xcdef, (short)0xff00, (short)0xffff, + }; + for (short v: values) { + assertSame(eth, eth.setEtherType(v)); + assertEquals(v, eth.getEtherType()); + } + } + + /** + * Test case for {@link Ethernet#clone()}. + */ + @Test + public void testClone() { + EtherAddress src = new EtherAddress(0x001122334455L); + EtherAddress dst = new EtherAddress(0x0abbccddeeffL); + short etype = EtherTypes.VLAN.shortValue(); + Ethernet eth = new Ethernet(). + setSourceMACAddress(src.getBytes()). + setDestinationMACAddress(dst.getBytes()). + setEtherType(etype); + + byte pcp = 0; + byte cfi = 0; + short vid = 4095; + short vetype = EtherTypes.ARP.shortValue(); + IEEE8021Q vlan = new IEEE8021Q(). + setPcp(pcp). + setCfi(cfi). + setVid(vid). + setEtherType(vetype); + + short hwtype = 1; + short ptype = 0x800; + byte hlen = 6; + byte plen = 4; + short op = 7; + EtherAddress sha = new EtherAddress(0x010203040506L); + EtherAddress tha = new EtherAddress(0xa0b0c0d0e0f0L); + Ip4Network spa = new Ip4Network("1.2.3.4"); + Ip4Network tpa = new Ip4Network("192.168.34.56"); + ARP arp = new ARP(). + setHardwareType(hwtype). + setProtocolType(ptype). + setHardwareAddressLength(hlen). + setProtocolAddressLength(plen). + setOpCode(op). + setSenderHardwareAddress(sha.getBytes()). + setTargetHardwareAddress(tha.getBytes()). + setSenderProtocolAddress(spa.getBytes()). + setTargetProtocolAddress(tpa.getBytes()); + + vlan.setPayload(arp); + eth.setPayload(vlan); + + Ethernet copy = eth.clone(); + assertNotSame(eth, copy); + assertEquals(eth, copy); + assertEquals(eth.hashCode(), copy.hashCode()); + assertEquals(null, copy.getRawPayload()); + + Packet payload1 = copy.getPayload(); + assertNotSame(vlan, payload1); + assertEquals(vlan, payload1); + assertEquals(null, payload1.getRawPayload()); + + Packet payload2 = payload1.getPayload(); + assertNotSame(arp, payload2); + assertEquals(arp, payload2); + assertEquals(null, payload2.getPayload()); + assertEquals(null, payload2.getRawPayload()); + + // Modifying the source packet should never affect a deep copy. + EtherAddress src1 = new EtherAddress(0x0L); + EtherAddress dst1 = EtherAddress.BROADCAST; + short etype1 = 0x123; + eth.setSourceMACAddress(src1.getBytes()). + setDestinationMACAddress(dst1.getBytes()). + setEtherType(etype1); + eth.setPayload(null); + + assertArrayEquals(src.getBytes(), copy.getSourceMACAddress()); + assertArrayEquals(dst.getBytes(), copy.getDestinationMACAddress()); + assertEquals(etype, copy.getEtherType()); + assertEquals(payload1, copy.getPayload()); + assertEquals(payload2, payload1.getPayload()); + assertEquals(null, payload2.getPayload()); + + assertArrayEquals(src1.getBytes(), eth.getSourceMACAddress()); + assertArrayEquals(dst1.getBytes(), eth.getDestinationMACAddress()); + assertEquals(etype1, eth.getEtherType()); + assertEquals(null, eth.getPayload()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ICMPTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ICMPTest.java new file mode 100644 index 00000000..0828425c --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/ICMPTest.java @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import java.util.Arrays; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link ICMP}. + */ +public class ICMPTest extends TestBase { + /** + * Test case for ICMP type. + * + *
        + *
      • {@link ICMP#getType()}
      • + *
      • {@link ICMP#setType(byte)}
      • + *
      + */ + @Test + public void testSetType() { + ICMP icmp = new ICMP(); + assertEquals((byte)0, icmp.getType()); + + byte[] values = {0, 1, 9, 57, 94, 127, -128, -127, -15, -2, -1}; + for (byte type: values) { + assertSame(icmp, icmp.setType(type)); + assertEquals(type, icmp.getType()); + } + } + + /** + * Test case for ICMP code. + * + *
        + *
      • {@link ICMP#getCode()}
      • + *
      • {@link ICMP#setCode(byte)}
      • + *
      + */ + @Test + public void testSetCode() { + ICMP icmp = new ICMP(); + assertEquals((byte)0, icmp.getCode()); + + byte[] values = {0, 1, 9, 57, 94, 127, -128, -127, -15, -2, -1}; + for (byte code: values) { + assertSame(icmp, icmp.setCode(code)); + assertEquals(code, icmp.getCode()); + } + } + + /** + * Test case for ICMP checksum. + * + *
        + *
      • {@link ICMP#getChecksum()}
      • + *
      • {@link ICMP#setChecksum(short)}
      • + *
      + */ + @Test + public void testSetChecksum() { + ICMP icmp = new ICMP(); + assertEquals((short)0, icmp.getChecksum()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short cksum: values) { + assertSame(icmp, icmp.setChecksum(cksum)); + assertEquals(cksum, icmp.getChecksum()); + } + } + + /** + * Test case for ICMP identifier. + * + *
        + *
      • {@link ICMP#getIdentifier()}
      • + *
      • {@link ICMP#setIdentifier(short)}
      • + *
      + */ + @Test + public void testSetIdentifier() { + ICMP icmp = new ICMP(); + assertEquals((short)0, icmp.getChecksum()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short id: values) { + assertSame(icmp, icmp.setIdentifier(id)); + assertEquals(id, icmp.getIdentifier()); + } + } + + /** + * Test case for ICMP sequence number. + * + *
        + *
      • {@link ICMP#getSequenceNumber()}
      • + *
      • {@link ICMP#setSequenceNumber(short)}
      • + *
      + */ + @Test + public void testSetSequenceNumber() { + ICMP icmp = new ICMP(); + assertEquals((short)0, icmp.getSequenceNumber()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short seq: values) { + assertSame(icmp, icmp.setSequenceNumber(seq)); + assertEquals(seq, icmp.getSequenceNumber()); + } + } + + /** + * Test case for {@link ICMP#clone()}. + */ + @Test + public void testClone() { + byte type = 12; + byte code = 45; + short cksum = 18341; + short id = -29234; + short seq = 31721; + ICMP icmp = new ICMP(). + setType(type). + setCode(code). + setChecksum(cksum). + setIdentifier(id). + setSequenceNumber(seq); + + ICMP copy = icmp.clone(); + assertNotSame(icmp, copy); + assertEquals(icmp, copy); + assertEquals(icmp.hashCode(), copy.hashCode()); + + // Modifying the source packet should never affect a deep copy. + byte type1 = 0; + byte code1 = 23; + short cksum1 = -29216; + short id1 = 3445; + short seq1 = 9163; + icmp.setType(type1). + setCode(code1). + setChecksum(cksum1). + setIdentifier(id1). + setSequenceNumber(seq1); + + assertEquals(type, copy.getType()); + assertEquals(code, copy.getCode()); + assertEquals(cksum, copy.getChecksum()); + assertEquals(id, copy.getIdentifier()); + assertEquals(seq, copy.getSequenceNumber()); + + assertEquals(type1, icmp.getType()); + assertEquals(code1, icmp.getCode()); + assertEquals(cksum1, icmp.getChecksum()); + assertEquals(id1, icmp.getIdentifier()); + assertEquals(seq1, icmp.getSequenceNumber()); + } + + /** + * Test for serialization and deserialization. + * + *
        + *
      • {@link Packet#serialize()}
      • + *
      • {@link Packet#deserialize(byte[], int, int)}
      • + *
      + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialization() throws Exception { + byte[] icmpRawPayload = { + (byte)0x38, (byte)0x26, (byte)0x9e, (byte)0x51, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x2e, (byte)0x6a, (byte)0x08, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, + (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, + (byte)0x18, (byte)0x19, (byte)0x1a, (byte)0x1b, + (byte)0x1c, (byte)0x1d, (byte)0x1e, (byte)0x1f, + (byte)0x20, (byte)0x21, (byte)0x22, (byte)0x23, + (byte)0x24, (byte)0x25, (byte)0x26, (byte)0x27, + (byte)0x28, (byte)0x29, (byte)0x2a, (byte)0x2b, + (byte)0x2c, (byte)0x2d, (byte)0x2e, (byte)0x2f, + (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x33, + (byte)0x34, (byte)0x35, (byte)0x36, (byte)0x37, + }; + serializeTest(icmpRawPayload, (short)0xe553); + + serializeTest(null, (short)0xb108); + serializeTest(new byte[0], (short)0xb108); + + byte[] odd = { + (byte)0xba, (byte)0xd4, (byte)0xc7, (byte)0x53, + (byte)0xf8, (byte)0x59, (byte)0x68, (byte)0x77, + (byte)0xfd, (byte)0x27, (byte)0xe0, (byte)0x5b, + (byte)0xd0, (byte)0x2e, (byte)0x28, (byte)0x41, + (byte)0xa3, (byte)0x48, (byte)0x5d, (byte)0x2e, + (byte)0x7d, (byte)0x5b, (byte)0xd3, (byte)0x60, + (byte)0xb3, (byte)0x88, (byte)0x8d, (byte)0x0f, + (byte)0x1d, (byte)0x87, (byte)0x51, (byte)0x0f, + (byte)0x6a, (byte)0xff, (byte)0xf7, (byte)0xd4, + (byte)0x40, (byte)0x35, (byte)0x4e, (byte)0x01, + (byte)0x36, + }; + serializeTest(odd, (short)0xd0ad); + + // Large payload that causes 16-bit checksum overflow more than + // 255 times. + byte[] largeEven = new byte[1024]; + Arrays.fill(largeEven, (byte)0xff); + serializeTest(largeEven, (short)0xb108); + + byte[] largeOdd = new byte[1021]; + Arrays.fill(largeOdd, (byte)0xff); + serializeTest(largeOdd, (short)0xb207); + + // Serialize an empty packet. + ICMP icmp = new ICMP(); + byte[] expected = new byte[8]; + + // Checksum should be updated. + expected[2] = (byte)0xff; + expected[3] = (byte)0xff; + assertArrayEquals(expected, icmp.serialize()); + } + + /** + * Ensure that the ICMP packet is serializable and deserializable. + * + * @param payload The raw packet of the ICMP packet. + * @param checksum The expected ICMP checksum. + * @throws Exception An error occurred. + */ + private void serializeTest(byte[] payload, short checksum) + throws Exception { + ICMP icmp = new ICMP(); + icmp.setType((byte)8).setCode((byte)0). + setIdentifier((short)0x46f5).setSequenceNumber((short)2); + int payloadSize = 0; + if (payload != null) { + icmp.setRawPayload(payload); + payloadSize = payload.length; + } + + // Serialize + byte[] data = icmp.serialize(); + assertEquals(payloadSize + 8, data.length); + + // Deserialize + ICMP icmpDes = new ICMP(); + icmpDes.deserialize(data, 0, data.length); + + assertFalse(icmpDes.isCorrupted()); + assertEquals(checksum, icmpDes.getChecksum()); + assertEquals(icmp, icmpDes); + assertEquals(false, icmpDes.isCorrupted()); + + // Ensure that data corruption can be detected. + data[0] = (byte)~data[0]; + icmpDes = new ICMP(); + icmpDes.deserialize(data, 0, data.length); + assertEquals(true, icmpDes.isCorrupted()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IEEE8021QTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IEEE8021QTest.java new file mode 100644 index 00000000..15746026 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IEEE8021QTest.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.util.Ip4Network; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link IEEE8021Q}. + */ +public class IEEE8021QTest extends TestBase { + /** + * Test case for the priority code point. + * + *
        + *
      • {@link IEEE8021Q#getPcp()}
      • + *
      • {@link IEEE8021Q#setPcp(byte)}
      • + *
      + */ + @Test + public void testGetPcp() { + IEEE8021Q vlan = new IEEE8021Q(); + assertEquals((byte)0, vlan.getPcp()); + + for (byte v = 0; v <= 7; v++) { + assertSame(vlan, vlan.setPcp(v)); + assertEquals(v, vlan.getPcp()); + } + } + + /** + * Test case for the canonical format indicator. + * + *
        + *
      • {@link IEEE8021Q#getCfi()}
      • + *
      • {@link IEEE8021Q#setCfi(byte)}
      • + *
      + */ + @Test + public void testGetCfi() throws Exception { + IEEE8021Q vlan = new IEEE8021Q(); + assertEquals((byte)0, vlan.getCfi()); + + for (byte v = 0; v <= 1; v++) { + assertSame(vlan, vlan.setCfi(v)); + assertEquals(v, vlan.getCfi()); + } + } + + /** + * Test case for the VLAN ID. + * + *
        + *
      • {@link IEEE8021Q#getVid()}
      • + *
      • {@link IEEE8021Q#setVid(short)}
      • + *
      + */ + @Test + public void testGetVid() throws Exception { + IEEE8021Q vlan = new IEEE8021Q(); + assertEquals((short)0, vlan.getVid()); + + short[] values = { + 0, 1, 4, 21, 127, 128, 254, 255, 256, 257, 1023, 1024, 1025, + 2000, 3000, 4000, 4093, 4094, 4095, + }; + for (short v: values) { + assertSame(vlan, vlan.setVid(v)); + assertEquals(v, vlan.getVid()); + } + } + + /** + * Test case for the Ethernet type. + * + *
        + *
      • {@link IEEE8021Q#getEtherType()}
      • + *
      • {@link IEEE8021Q#setEtherType(short)}
      • + *
      + */ + @Test + public void testGetEthertype() throws Exception { + IEEE8021Q vlan = new IEEE8021Q(); + assertEquals((short)0, vlan.getVid()); + + short[] values = { + (short)0x0000, (short)0x0001, (short)0x0020, (short)0x03ff, + (short)0x07ff, (short)0x0800, (short)0x0999, (short)0x1abc, + (short)0x5678, (short)0x7fff, (short)0x8000, (short)0x8888, + (short)0xabcd, (short)0xcdef, (short)0xff00, (short)0xffff, + }; + for (short v: values) { + assertSame(vlan, vlan.setEtherType(v)); + assertEquals(v, vlan.getEtherType()); + } + } + + /** + * Ensure that the IEEE8021Q packet is deserializable. + * + * @throws Exception An error occurred. + */ + @Test + public void testDeserialize() throws Exception { + byte[] data = { + // Destination MAC address. + (byte)0x0a, (byte)0x0c, (byte)0x0e, (byte)0x14, + (byte)0x37, (byte)0x45, + + // Source MAC address. + (byte)0xa6, (byte)0xec, (byte)0x9c, (byte)0xae, + (byte)0xb2, (byte)0x9f, + + // Ether type. + (byte)0x81, (byte)0x00, + + // VLAN tag + // PCP, CFI, and VLAN ID. + (byte)0xaf, (byte)0xfe, + + // Ethernet type. + 0x08, 0x06, + + // ARP + + // Hardware type. + 0x00, 0x01, + + // Protocol type. + 0x08, 0x00, + + // Hardware address length. + 0x06, + + // Protocol address length. + 0x04, + + // ARP operation code. + 0x00, 0x01, + + // Sender hardware address. + (byte)0xa6, (byte)0xec, (byte)0x9c, (byte)0xae, + (byte)0xb2, (byte)0x9f, + + // Sender protocol address. + (byte)0x09, (byte)0x09, (byte)0x09, (byte)0x01, + + // Target hardware address. + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, + + // Target protocol address. + (byte)0x09, (byte)0x09, (byte)0x09, (byte)0xfe, + }; + + short startOffset = 0; + short numBits = (short)(data.length * 8); + Ethernet eth = new Ethernet(); + eth.deserialize(data, startOffset, numBits); + + assertEquals((short)0x8100, eth.getEtherType()); + + IEEE8021Q vlan = (IEEE8021Q)eth.getPayload(); + assertEquals((byte)0, vlan.getCfi()); + assertEquals((byte)5, vlan.getPcp()); + assertEquals((short)4094, vlan.getVid()); + assertEquals((short)0x0806, vlan.getEtherType()); + + ARP arp = (ARP)vlan.getPayload(); + assertEquals((short)0x1, arp.getHardwareType()); + assertEquals((short)0x0800, arp.getProtocolType()); + assertEquals((byte)0x06, arp.getHardwareAddressLength()); + assertEquals((byte)0x04, arp.getProtocolAddressLength()); + assertEquals((short)1, arp.getOpCode()); + + byte[] sha = { + (byte)0xa6, (byte)0xec, (byte)0x9c, (byte)0xae, + (byte)0xb2, (byte)0x9f, + }; + byte[] spa = { + (byte)0x09, (byte)0x09, (byte)0x09, (byte)0x01, + }; + byte[] tha = { + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, + }; + byte[] tpa = { + (byte)0x09, (byte)0x09, (byte)0x09, (byte)0xfe, + }; + assertArrayEquals(sha, arp.getSenderHardwareAddress()); + assertArrayEquals(spa, arp.getSenderProtocolAddress()); + assertArrayEquals(tha, arp.getTargetHardwareAddress()); + assertArrayEquals(tpa, arp.getTargetProtocolAddress()); + } + + /** + * Enshre that the IEEE8021Q packet is serializable. + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialize() throws Exception { + + byte[] dMac = { + (byte)0xa, (byte)0xc, (byte)0xe, (byte)0x14, + (byte)0x37, (byte)0x45, + }; + byte[] sMac = { + (byte)0xa6, (byte)0xec, (byte)0x9c, (byte)0xae, + (byte)0xb2, (byte)0x9f, + }; + + Ethernet eth = new Ethernet(). + setDestinationMACAddress(dMac). + setSourceMACAddress(sMac). + setEtherType((short)0x8100); + + IEEE8021Q vlan = new IEEE8021Q(). + setCfi((byte)0x0). + setPcp((byte)0x5). + setVid((short)4094). + setEtherType((short)0x806); + + eth.setPayload(vlan); + + ARP arp = new ARP(). + setHardwareType((short)1). + setProtocolType((short)0x800). + setHardwareAddressLength((byte)0x6). + setProtocolAddressLength((byte)0x4). + setOpCode((byte)0x1); + + byte[] sha = { + (byte)0xa6, (byte)0xec, (byte)0x9c, (byte)0xae, + (byte)0xb2, (byte)0x9f, + }; + byte[] tha = { + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, + }; + byte[] spa = {(byte)0x9, (byte)0x9, (byte)0x9, (byte)0x01}; + byte[] tpa = {(byte)0x9, (byte)0x9, (byte)0x9, (byte)0xfe}; + arp.setSenderHardwareAddress(sha); + arp.setSenderProtocolAddress(spa); + arp.setTargetHardwareAddress(tha); + arp.setTargetProtocolAddress(tpa); + + vlan.setPayload(arp); + + byte[] data = eth.serialize(); + + // Ethernet header + + // Destination MAC adress. + assertEquals((byte)0x0a, data[0]); + assertEquals((byte)0x0c, data[1]); + assertEquals((byte)0x0e, data[2]); + assertEquals((byte)0x14, data[3]); + assertEquals((byte)0x37, data[4]); + assertEquals((byte)0x45, data[5]); + + // Source MAC address. + assertEquals((byte)0xa6, data[6]); + assertEquals((byte)0xec, data[7]); + assertEquals((byte)0x9c, data[8]); + assertEquals((byte)0xae, data[9]); + assertEquals((byte)0xb2, data[10]); + assertEquals((byte)0x9f, data[11]); + + // Ethernet type. + assertEquals((byte)0x81, data[12]); + assertEquals((byte)0x00, data[13]); + + // VLAN Tag + + // PCP, CFI, VLAN ID + assertEquals((byte)0xaf, data[14]); + assertEquals((byte)0xfe, data[15]); + + // Ethernet type. + assertEquals((byte)0x08, data[16]); + assertEquals((byte)0x06, data[17]); + + // ARP + + // Hardware type. + assertEquals((byte)0x00, data[18]); + assertEquals((byte)0x01, data[19]); + + // Protocol type. + assertEquals((byte)0x08, data[20]); + assertEquals((byte)0x00, data[21]); + + // Hardware address length. + assertEquals((byte)0x06, data[22]); + + // Protocol address length. + assertEquals((byte)0x04, data[23]); + + // ARP operation code. + assertEquals((byte)0x00, data[24]); + assertEquals((byte)0x01, data[25]); + + // Sender hardware address. + assertEquals((byte)0xa6, data[26]); + assertEquals((byte)0xec, data[27]); + assertEquals((byte)0x9c, data[28]); + assertEquals((byte)0xae, data[29]); + assertEquals((byte)0xb2, data[30]); + assertEquals((byte)0x9f, data[31]); + + // Sender protocol address. + assertEquals((byte)0x09, data[32]); + assertEquals((byte)0x09, data[33]); + assertEquals((byte)0x09, data[34]); + assertEquals((byte)0x01, data[35]); + + // Target hardware address. + assertEquals((byte)0x00, data[36]); + assertEquals((byte)0x00, data[37]); + assertEquals((byte)0x00, data[38]); + assertEquals((byte)0x00, data[39]); + assertEquals((byte)0x00, data[40]); + assertEquals((byte)0x00, data[41]); + + // Target protocol address + assertEquals((byte)0x09, data[42]); + assertEquals((byte)0x09, data[43]); + assertEquals((byte)0x09, data[44]); + assertEquals((byte)0xfe, data[45]); + } + + /** + * Test case for {@link IEEE8021Q#clone()}. + */ + @Test + public void testClone() { + byte pcp = 5; + byte cfi = 0; + short vid = 104; + short etype = 0x806; + IEEE8021Q vlan = new IEEE8021Q(). + setPcp(pcp). + setCfi(cfi). + setVid(vid). + setEtherType(etype); + + short hwtype = 1; + short ptype = 123; + byte hlen = 6; + byte plen = 4; + short op = 7; + EtherAddress sha = new EtherAddress(0x001122334455L); + EtherAddress tha = new EtherAddress(0xa0b0c0d0e0f0L); + Ip4Network spa = new Ip4Network("1.2.3.4"); + Ip4Network tpa = new Ip4Network("192.168.34.56"); + ARP arp = new ARP(). + setHardwareType(hwtype). + setProtocolType(ptype). + setHardwareAddressLength(hlen). + setProtocolAddressLength(plen). + setOpCode(op). + setSenderHardwareAddress(sha.getBytes()). + setTargetHardwareAddress(tha.getBytes()). + setSenderProtocolAddress(spa.getBytes()). + setTargetProtocolAddress(tpa.getBytes()); + + vlan.setPayload(arp); + + IEEE8021Q copy = vlan.clone(); + assertNotSame(vlan, copy); + assertEquals(vlan, copy); + assertEquals(vlan.hashCode(), copy.hashCode()); + assertEquals(null, copy.getRawPayload()); + + Packet payload = copy.getPayload(); + assertNotSame(arp, payload); + assertEquals(arp, payload); + assertEquals(null, payload.getRawPayload()); + + // Modifying the source packet should never affect a deep copy. + byte pcp1 = 7; + byte cfi1 = 1; + short vid1 = 4095; + short etype1 = 0x811; + vlan.setPcp(pcp1). + setCfi(cfi1). + setVid(vid1). + setEtherType(etype1); + vlan.setPayload(null); + + assertEquals(cfi, copy.getCfi()); + assertEquals(pcp, copy.getPcp()); + assertEquals(vid, copy.getVid()); + assertEquals(etype, copy.getEtherType()); + + assertEquals(cfi1, vlan.getCfi()); + assertEquals(pcp1, vlan.getPcp()); + assertEquals(vid1, vlan.getVid()); + assertEquals(etype1, vlan.getEtherType()); + + assertEquals(null, vlan.getPayload()); + assertEquals(payload, copy.getPayload()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IPv4Test.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IPv4Test.java new file mode 100644 index 00000000..cee5ff41 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/IPv4Test.java @@ -0,0 +1,908 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import static org.opendaylight.vtn.manager.util.NumberUtils.getUnsigned; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.util.EtherTypes; +import org.opendaylight.vtn.manager.util.InetProtocols; +import org.opendaylight.vtn.manager.util.Ip4Network; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link IPv4}. + */ +public class IPv4Test extends TestBase { + /** + * Test case for {@link IPv4#getPayloadClass(byte)}. + */ + @Test + public void testGetPayloadClass() { + for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { + Class expected; + if (i == 1) { + expected = ICMP.class; + } else if (i == 6) { + expected = TCP.class; + } else if (i == 17) { + expected = UDP.class; + } else { + expected = null; + } + + assertEquals(expected, IPv4.getPayloadClass((byte)i)); + } + } + + /** + * Test case for IP version. + * + *
        + *
      • {@link IPv4#getVersion()}
      • + *
      • {@link IPv4#setVersion(byte)}
      • + *
      + */ + @Test + public void testGetVersion() { + IPv4 ip = new IPv4(); + assertEquals((byte)4, ip.getVersion()); + + for (byte v = 0; v <= 15; v++) { + assertSame(ip, ip.setVersion(v)); + assertEquals(v, ip.getVersion()); + } + } + + /** + * Test case for IP header length. + * + *
        + *
      • {@link IPv4#getHeaderLen()}
      • + *
      • {@link IPv4#setHeaderLength(byte)}
      • + *
      + */ + @Test + public void testGetHeaderLength() { + IPv4 ip = new IPv4(); + assertEquals(20, ip.getHeaderLen()); + + for (byte v = 0; v <= 15; v++) { + assertSame(ip, ip.setHeaderLength(v)); + assertEquals(v * 4, ip.getHeaderLen()); + } + } + + /** + * Test case for IP differential services. + * + *
        + *
      • {@link IPv4#getDiffServ()}
      • + *
      • {@link IPv4#setDiffServ(byte)}
      • + *
      + */ + @Test + public void testGetDiffServ() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getDiffServ()); + + for (byte v = 0; v <= 63; v++) { + assertSame(ip, ip.setDiffServ(v)); + assertEquals(v, ip.getDiffServ()); + } + } + + /** + * Test case for IP ECN bits. + * + *
        + *
      • {@link IPv4#getECN()}
      • + *
      • {@link IPv4#setECN(byte)}
      • + *
      + */ + @Test + public void testGetECN() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getECN()); + + for (byte v = 0; v <= 3; v++) { + assertSame(ip, ip.setECN(v)); + assertEquals(v, ip.getECN()); + } + } + + /** + * Test case for the IP total length. + * + *
        + *
      • {@link IPv4#getTotalLength()}
      • + *
      • {@link IPv4#setTotalLength(short)}
      • + *
      + */ + @Test + public void testGetTotalLength() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getTotalLength()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short v: values) { + assertSame(ip, ip.setTotalLength(v)); + assertEquals(v, ip.getTotalLength()); + } + } + + /** + * Test case for the IP identification. + * + *
        + *
      • {@link IPv4#getIdentification()}
      • + *
      • {@link IPv4#setIdentification(short)}
      • + *
      + */ + @Test + public void testGetIdentification() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getIdentification()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short v: values) { + assertSame(ip, ip.setIdentification(v)); + assertEquals(v, ip.getIdentification()); + } + } + + /** + * Test case for the IPv4 flags. + * + *
        + *
      • {@link IPv4#getFlags()}
      • + *
      • {@link IPv4#setFlags(byte)}
      • + *
      + */ + @Test + public void testGetFlags() { + IPv4 ip = new IPv4(); + assertEquals((byte)2, ip.getFlags()); + + byte[] values = {0, 1, 9, 57, 94, 127, -128, -127, -15, -2, -1}; + for (byte v: values) { + assertSame(ip, ip.setFlags(v)); + assertEquals(v, ip.getFlags()); + } + } + + /** + * Test case for TTL. + * + *
        + *
      • {@link IPv4#getTtl()}
      • + *
      • {@link IPv4#setTtl(byte)}
      • + *
      + */ + @Test + public void testGetTtl() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getTtl()); + + byte[] values = {0, 1, 9, 57, 94, 127, -128, -127, -15, -2, -1}; + for (byte v: values) { + assertSame(ip, ip.setTtl(v)); + assertEquals(v, ip.getTtl()); + } + } + + /** + * Test case for the IP protocol number. + * + *
        + *
      • {@link IPv4#getProtocol()}
      • + *
      • {@link IPv4#setProtocol(byte)}
      • + *
      + */ + @Test + public void testGetProtocol() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getProtocol()); + + byte[] values = {0, 1, 9, 57, 94, 127, -128, -127, -15, -2, -1}; + for (byte v: values) { + assertSame(ip, ip.setProtocol(v)); + assertEquals(v, ip.getProtocol()); + } + } + + /** + * Test case for the IPv4 checksum. + * + *
        + *
      • {@link IPv4#getChecksum()}
      • + *
      • {@link IPv4#setChecksum(short)}
      • + *
      + */ + @Test + public void testGetChecksum() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getChecksum()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short v: values) { + assertSame(ip, ip.setChecksum(v)); + assertEquals(v, ip.getChecksum()); + } + } + + /** + * Test case for the IP fragmentation offset. + * + *
        + *
      • {@link IPv4#getFragmentOffset()}
      • + *
      • {@link IPv4#setFragmentOffset(short)}
      • + *
      + */ + @Test + public void testGetFragmentOffset() { + IPv4 ip = new IPv4(); + assertEquals((byte)0, ip.getFragmentOffset()); + + short[] values = {0, 1, 19, 456, 719, 1024, 2491, 6182, 8190, 8191}; + for (short v: values) { + assertSame(ip, ip.setFragmentOffset(v)); + assertEquals(v, ip.getFragmentOffset()); + } + } + + /** + * Test case for the source IP address. + * + *
        + *
      • {@link IPv4#getSourceAddress()}
      • + *
      • {@link IPv4#setSourceAddress(Ip4Network)}
      • + *
      + */ + @Test + public void testGetSourceAddress() { + IPv4 ip = new IPv4(); + assertEquals(new Ip4Network(0), ip.getSourceAddress()); + + Ip4Network[] addrs = { + new Ip4Network("11.22.33.44"), + new Ip4Network("127.0.0.1"), + new Ip4Network("192.168.45.254"), + new Ip4Network("200.35.87.176"), + }; + for (Ip4Network addr: addrs) { + assertSame(ip, ip.setSourceAddress(addr)); + assertEquals(addr, ip.getSourceAddress()); + } + } + + /** + * Test case for the destination IP address. + * + *
        + *
      • {@link IPv4#getDestinationAddress()}
      • + *
      • {@link IPv4#setDestinationAddress(Ip4Network)}
      • + *
      + */ + @Test + public void testGetDestinationAddress() { + IPv4 ip = new IPv4(); + assertEquals(new Ip4Network(0), ip.getDestinationAddress()); + + Ip4Network[] addrs = { + new Ip4Network("11.22.33.44"), + new Ip4Network("127.0.0.1"), + new Ip4Network("192.168.45.254"), + new Ip4Network("200.35.87.176"), + }; + for (Ip4Network addr: addrs) { + assertSame(ip, ip.setDestinationAddress(addr)); + assertEquals(addr, ip.getDestinationAddress()); + } + } + + + /** + * Test case for the IPv4 options. + * + *
        + *
      • {@link IPv4#getOptions()}
      • + *
      • {@link IPv4#setOptions(byte[])}
      • + *
      + */ + @Test + public void testOptions() throws Exception { + IPv4 ip = new IPv4(); + assertEquals(20, ip.getHeaderLen()); + assertEquals(160, ip.getHeaderSize()); + assertEquals(0, ip.getFieldNumBits("Options")); + + byte[][] options = { + new byte[] { + (byte)0x01, + }, + new byte[] { + (byte)0x01, (byte)0x02, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + }, + null, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, (byte)0x07, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, + }, + new byte[0], + }; + + byte[][] expected = { + new byte[] { + (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x00, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + }, + null, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, (byte)0x00, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x00, + }, + new byte[] { + (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, + (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, + }, + null, + }; + + byte[] echo = { + (byte)0x11, (byte)0x22, (byte)0x33, (byte)0x44, + (byte)0x55, (byte)0x66, (byte)0x77, (byte)0x88, + (byte)0x99, (byte)0xaa, + }; + ICMP icmp = new ICMP(); + icmp.setType((byte)8); + icmp.setCode((byte)0); + icmp.setIdentifier((short)0xabcd); + icmp.setSequenceNumber((short)7777); + icmp.setRawPayload(echo); + + ip.setSourceAddress(new Ip4Network("192.168.10.20")); + ip.setDestinationAddress(new Ip4Network("192.168.30.40")); + ip.setProtocol(InetProtocols.ICMP.byteValue()); + + for (int i = 0; i < options.length; i++) { + byte[] opts = options[i]; + byte[] exp = expected[i]; + + // Set IPv4 options. + int hlen = 20; + int optlen; + if (exp != null) { + optlen = exp.length; + hlen += optlen; + } else { + optlen = 0; + } + ip.setOptions(opts); + assertArrayEquals(exp, ip.getOptions()); + assertEquals(hlen, ip.getHeaderLen()); + assertEquals(hlen * 8, ip.getHeaderSize()); + assertEquals(optlen * 8, ip.getFieldNumBits("Options")); + + // Serialize/Deserialize test. + ip.setPayload(icmp); + + byte[] raw = ip.serialize(); + IPv4 newip = new IPv4(); + newip.deserialize(raw, 0, raw.length * 8); + assertEquals(ip, newip); + assertEquals(icmp, newip.getPayload()); + assertArrayEquals(exp, newip.getOptions()); + } + } + + /** + * Test case for the IPv4 checksum computation. + */ + @Test + public void testChecksum() { + byte[] header = { + (byte)0x45, 00, 00, (byte)0x3c, (byte)0x1c, + (byte)0x46, (byte)0x40, 00, (byte)0x40, 06, (byte)0xb1, + (byte)0xe6, (byte)0xac, (byte)0x10, (byte)0x0a, + (byte)0x63, (byte)0xac, (byte)0x10, (byte)0x0a, (byte)0x0c + }; + byte[] header2 = { + (byte)0x45, 00, 00, (byte)0x73, 00, 00, + (byte)0x40, 00, (byte)0x40, (byte)0x11, (byte)0xb8, + (byte)0x61, (byte)0xc0, (byte)0xa8, 00, 01, (byte)0xc0, + (byte)0xa8, 00, (byte)0xc7 + }; + byte[] header3 = { + (byte)0x45, 00, 00, (byte)0x47, (byte)0x73, + (byte)0x88, (byte)0x40, 00, (byte)0x40, 06, (byte)0xA2, + (byte)0xC4, (byte)0x83, (byte)0x9F, (byte)0x0E, + (byte)0x85, (byte)0x83, (byte)0x9F, (byte)0x0E, (byte)0xA1 + }; + byte[] header4 = { + (byte)0x45, 00, 00, (byte)0x54, 00, 00, + (byte)0x40, 00, (byte)0x40, 01, (byte)0xf0, (byte)0x8e, + (byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x65, + (byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x64 + }; + byte[] header5 = { + (byte)0x45, 00, 00, (byte)0x54, 00, 00, + (byte)0x40, 00, (byte)0x40, 01, (byte)0xef, (byte)0x8d, + (byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x65, + (byte)0xc0, (byte)0xa8, (byte)0x65, (byte)0x65 + }; + byte[] header6 = { + (byte)0x45, 00, 00, (byte)0x54, 00, 00, + (byte)0x40, 00, (byte)0x40, 01, (byte)0x0b, (byte)0x92, + (byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x65, (byte)0x9, + (byte)0x9, (byte)0x1, (byte)0x1 + }; + byte[] header7 = { + (byte)0x45, 00, 00, (byte)0x54, 00, 00, + (byte)0x40, 00, (byte)0x40, 01, (byte)0, (byte)0, + (byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x65, (byte)0x9, + (byte)0x9, (byte)0x2, (byte)0x2 + }; + + IPv4 ip = new IPv4(); + assertEquals(0xb1e6, getUnsigned(ip.computeChecksum(header, 0))); + assertEquals(0xb861, getUnsigned(ip.computeChecksum(header2, 0))); + assertEquals(0xa2c4, getUnsigned(ip.computeChecksum(header3, 0))); + assertEquals(0xf08e, getUnsigned(ip.computeChecksum(header4, 0))); + assertEquals(0xef8d, getUnsigned(ip.computeChecksum(header5, 0))); + assertEquals(0x0b92, getUnsigned(ip.computeChecksum(header6, 0))); + assertEquals(0x0a91, getUnsigned(ip.computeChecksum(header7, 0))); + } + + /** + * Test case for serialization. + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialization() throws Exception { + byte[] icmpRawPayload = { + (byte)0x38, (byte)0x26, (byte)0x9e, (byte)0x51, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x2e, (byte)0x6a, (byte)0x08, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x10, (byte)0x11, (byte)0x12, (byte)0x13, + (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, + (byte)0x18, (byte)0x19, (byte)0x1a, (byte)0x1b, + (byte)0x1c, (byte)0x1d, (byte)0x1e, (byte)0x1f, + (byte)0x20, (byte)0x21, (byte)0x22, (byte)0x23, + (byte)0x24, (byte)0x25, (byte)0x26, (byte)0x27, + (byte)0x28, (byte)0x29, (byte)0x2a, (byte)0x2b, + (byte)0x2c, (byte)0x2d, (byte)0x2e, (byte)0x2f, + (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x33, + (byte)0x34, (byte)0x35, (byte)0x36, (byte)0x37, + }; + + ICMP icmp = new ICMP(); + icmp.setType((byte)8); + icmp.setCode((byte)0); + icmp.setIdentifier((short)0x46f5); + icmp.setSequenceNumber((short)2); + icmp.setRawPayload(icmpRawPayload); + + IPv4 ip = new IPv4(); + ip.setVersion((byte)4); + ip.setIdentification((short)5); + ip.setDiffServ((byte)0); + ip.setECN((byte)0); + ip.setTotalLength((short)84); + ip.setFlags((byte)2); + ip.setFragmentOffset((short)0); + ip.setTtl((byte)64); + ip.setProtocol(InetProtocols.ICMP.byteValue()); + ip.setDestinationAddress(new Ip4Network("192.168.100.100")); + ip.setSourceAddress(new Ip4Network("192.168.100.101")); + ip.setPayload(icmp); + + Ethernet eth = new Ethernet(); + byte[] dstMac = { + (byte)0x98, (byte)0xfc, (byte)0x11, (byte)0x93, + (byte)0x5c, (byte)0xb8, + }; + byte[] srcMac = { + (byte)0x00, (byte)0x24, (byte)0xd7, (byte)0xa9, + (byte)0xa3, (byte)0x50, + }; + eth.setDestinationMACAddress(dstMac); + eth.setSourceMACAddress(srcMac); + eth.setEtherType(EtherTypes.IPV4.shortValue()); + eth.setPayload(ip); + + byte[] stream = eth.serialize(); + Ethernet decEth = new Ethernet(); + decEth.deserialize(stream, 0, stream.length * Byte.SIZE); + + IPv4 decIp = (IPv4)decEth.getPayload(); + assertFalse(decIp.isCorrupted()); + assertTrue(ip.equals(decIp)); + + ICMP decIcmp = (ICMP)decIp.getPayload(); + assertFalse(decIcmp.isCorrupted()); + assertArrayEquals(icmpRawPayload, decIcmp.getRawPayload()); + } + + /** + * Test case for IPv4 header fragmentation. + * + * @throws Exception An error occurred. + */ + @Test + public void testFragment()throws Exception { + byte[] payload1 = new byte[0]; + byte[] payload2 = { + (byte)0x61, (byte)0xd1, (byte)0x3d, (byte)0x51, + (byte)0x1b, (byte)0x75, (byte)0xa7, (byte)0x83, + }; + byte[] payload3 = { + (byte)0xe7, (byte)0x0f, (byte)0x2d, (byte)0x7e, + (byte)0x15, (byte)0xba, (byte)0xe7, (byte)0x6d, + (byte)0xb5, (byte)0xc5, (byte)0xb5, (byte)0x37, + (byte)0x59, (byte)0xbc, (byte)0x91, (byte)0x43, + (byte)0xb5, (byte)0xb7, (byte)0xe4, (byte)0x28, + (byte)0xec, (byte)0x62, (byte)0x6b, (byte)0x6a, + (byte)0xd1, (byte)0xcb, (byte)0x79, (byte)0x1e, + (byte)0xfc, (byte)0x82, (byte)0xf5, (byte)0xb4, + }; + + // Ensure that the payload is not deserialized if the fragment offset + // is not zero. + byte proto = InetProtocols.TCP.byteValue(); + fragmentTest(payload1, proto, (short)0xf250); + fragmentTest(payload2, proto, (short)0xf248); + fragmentTest(payload3, proto, (short)0xf230); + + proto = InetProtocols.UDP.byteValue(); + fragmentTest(payload1, proto, (short)0xf245); + fragmentTest(payload2, proto, (short)0xf23d); + fragmentTest(payload3, proto, (short)0xf225); + + proto = InetProtocols.ICMP.byteValue(); + fragmentTest(payload1, proto, (short)0xf255); + fragmentTest(payload2, proto, (short)0xf24d); + fragmentTest(payload3, proto, (short)0xf235); + + // Ensure that the protocol header in the first fragment is + // deserialized. + proto = InetProtocols.TCP.byteValue(); + TCP tcp = new TCP(); + tcp.setSourcePort((short)1234).setDestinationPort((short)32000). + setSequenceNumber((int)0xd541f5f8).setAckNumber((int)0x58da787d). + setDataOffset((byte)5).setReserved((byte)0). + setHeaderLenFlags((short)0x18).setWindowSize((short)0x40e8). + setUrgentPointer((short)0x15f7).setChecksum((short)0x0d4e); + firstFragmentTest(tcp, payload1, proto, (short)0xdfe6); + tcp.setChecksum((short)0xab2a); + firstFragmentTest(tcp, payload2, proto, (short)0xdfde); + tcp.setChecksum((short)0x1c75); + firstFragmentTest(tcp, payload3, proto, (short)0xdfc6); + + proto = InetProtocols.UDP.byteValue(); + UDP udp = new UDP(); + udp.setSourcePort((short)53).setDestinationPort((short)45383). + setLength((short)(payload1.length + 8)).setChecksum((short)0); + firstFragmentTest(udp, payload1, proto, (short)0xdfe7); + udp.setLength((short)(payload2.length + 8)); + firstFragmentTest(udp, payload2, proto, (short)0xdfdf); + udp.setLength((short)(payload3.length + 8)); + firstFragmentTest(udp, payload3, proto, (short)0xdfc7); + + proto = InetProtocols.ICMP.byteValue(); + ICMP icmp = new ICMP(); + icmp.setType((byte)8).setCode((byte)0).setIdentifier((short)0x3d1e). + setSequenceNumber((short)1); + firstFragmentTest(icmp, payload1, proto, (short)0xdff7); + firstFragmentTest(icmp, payload2, proto, (short)0xdfef); + firstFragmentTest(icmp, payload3, proto, (short)0xdfd7); + } + + /** + * Test case for {@link IPv4#clone()}. + */ + @Test + public void testClone() { + byte dserv = 34; + byte ecn = 2; + short id = 4981; + byte flag = 5; + byte ttl = 116; + byte proto = InetProtocols.UDP.byteValue(); + short fragoff = 45; + short cksum = 12345; + Ip4Network src = new Ip4Network("10.20.30.40"); + Ip4Network dst = new Ip4Network("192.168.100.200"); + IPv4 ip = new IPv4(). + setDiffServ(dserv). + setECN(ecn). + setIdentification(id). + setFlags(flag). + setTtl(ttl). + setProtocol(proto). + setFragmentOffset(fragoff). + setChecksum(cksum). + setSourceAddress(src). + setDestinationAddress(dst); + + UDP udp = new UDP(). + setSourcePort((short)451). + setDestinationPort((short)17). + setLength((short)567). + setChecksum((short)0); + + byte[] raw = { + (byte)0x8b, (byte)0xc5, (byte)0x0b, (byte)0x3a, + (byte)0xc2, (byte)0x3d, (byte)0xb2, (byte)0x65, + }; + udp.setRawPayload(raw); + ip.setPayload(udp); + + IPv4 copy = ip.clone(); + assertNotSame(ip, copy); + assertEquals(ip, copy); + assertEquals(ip.hashCode(), copy.hashCode()); + assertEquals(null, copy.getRawPayload()); + + Packet payload = copy.getPayload(); + assertNotSame(udp, payload); + assertEquals(udp, payload); + assertArrayEquals(raw, payload.getRawPayload()); + + // Modifying the source packet should never affect a deep copy. + byte dserv1 = 3; + byte ecn1 = 0; + short id1 = -31984; + byte flag1 = 0; + byte ttl1 = 12; + short fragoff1 = 0; + short cksum1 = -32315; + Ip4Network src1 = new Ip4Network("11.22.33.44"); + Ip4Network dst1 = new Ip4Network("192.168.100.253"); + ip.setDiffServ(dserv1). + setECN(ecn1). + setIdentification(id1). + setFlags(flag1). + setTtl(ttl1). + setFragmentOffset(fragoff1). + setChecksum(cksum1). + setSourceAddress(src1). + setDestinationAddress(dst1); + + UDP udp1 = new UDP(). + setSourcePort((short)64120). + setDestinationPort((short)45). + setLength((short)333). + setChecksum((short)12345); + ip.setPayload(udp1); + + assertEquals(dserv, copy.getDiffServ()); + assertEquals(ecn, copy.getECN()); + assertEquals(id, copy.getIdentification()); + assertEquals(flag, copy.getFlags()); + assertEquals(ttl, copy.getTtl()); + assertEquals(fragoff, copy.getFragmentOffset()); + assertEquals(cksum, copy.getChecksum()); + assertEquals(src, copy.getSourceAddress()); + assertEquals(dst, copy.getDestinationAddress()); + + assertEquals(dserv1, ip.getDiffServ()); + assertEquals(ecn1, ip.getECN()); + assertEquals(id1, ip.getIdentification()); + assertEquals(flag1, ip.getFlags()); + assertEquals(ttl1, ip.getTtl()); + assertEquals(fragoff1, ip.getFragmentOffset()); + assertEquals(cksum1, ip.getChecksum()); + assertEquals(src1, ip.getSourceAddress()); + assertEquals(dst1, ip.getDestinationAddress()); + + assertEquals(udp, copy.getPayload()); + assertArrayEquals(raw, copy.getPayload().getRawPayload()); + assertEquals(udp1, ip.getPayload()); + assertEquals(null, ip.getPayload().getRawPayload()); + } + + /** + * Run the IPv4 fragmentation test. + * + * @param payload The payload of the IPv4 packet. + * @param proto The IP protocol number. + * @param checksum The expected IPv4 checksum value. + * @throws Exception An error occurred. + */ + private void fragmentTest(byte[] payload, byte proto, short checksum) + throws Exception { + // Construct a fragmented raw IPv4 packet. + int ipv4Len = 20; + byte[] rawIp = new byte[ipv4Len + payload.length]; + + byte ipVersion = 4; + byte dscp = 35; + byte ecn = 2; + byte tos = (byte)((dscp << 2) | ecn); + short totalLen = (short)rawIp.length; + short id = 22143; + short offset = 0xb9; + byte ttl = 64; + byte[] srcIp = {(byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x01}; + byte[] dstIp = {(byte)0xc0, (byte)0xa9, (byte)0x66, (byte)0x23}; + + rawIp[0] = (byte)((ipVersion << 4) | (ipv4Len >> 2)); + rawIp[1] = tos; + rawIp[2] = (byte)(totalLen >>> Byte.SIZE); + rawIp[3] = (byte)totalLen; + rawIp[4] = (byte)(id >>> Byte.SIZE); + rawIp[5] = (byte)id; + rawIp[6] = (byte)(offset >>> Byte.SIZE); + rawIp[7] = (byte)offset; + rawIp[8] = ttl; + rawIp[9] = proto; + rawIp[10] = (byte)(checksum >>> Byte.SIZE); + rawIp[11] = (byte)checksum; + System.arraycopy(srcIp, 0, rawIp, 12, srcIp.length); + System.arraycopy(dstIp, 0, rawIp, 16, srcIp.length); + System.arraycopy(payload, 0, rawIp, ipv4Len, payload.length); + + // Deserialize. + IPv4 ipv4 = new IPv4(); + ipv4.deserialize(rawIp, 0, rawIp.length * Byte.SIZE); + + assertEquals(ipVersion, ipv4.getVersion()); + assertEquals(ipv4Len, ipv4.getHeaderLen()); + assertEquals(dscp, ipv4.getDiffServ()); + assertEquals(ecn, ipv4.getECN()); + assertEquals(totalLen, ipv4.getTotalLength()); + assertEquals(id, ipv4.getIdentification()); + assertEquals((byte)0, ipv4.getFlags()); + assertEquals(offset, ipv4.getFragmentOffset()); + assertEquals(ttl, ipv4.getTtl()); + assertEquals(proto, ipv4.getProtocol()); + assertEquals(checksum, ipv4.getChecksum()); + assertArrayEquals(srcIp, ipv4.getSourceAddress().getBytes()); + assertArrayEquals(dstIp, ipv4.getDestinationAddress().getBytes()); + assertEquals(false, ipv4.isCorrupted()); + + // payloadClass should not be set if fragment offset is not zero. + assertEquals(null, ipv4.getPayload()); + checkRawPayload(payload, ipv4.getRawPayload()); + + // Ensure that data corruption can be detected. + rawIp[1] = (byte)~rawIp[1]; + ipv4 = new IPv4(); + ipv4.deserialize(rawIp, 0, rawIp.length * Byte.SIZE); + assertEquals(true, ipv4.isCorrupted()); + } + + /** + * Ensure that the protocol header in the first fragment is deserialized. + * + * @param payload The payload of the IPv4 packet. + * @param rawPayload The raw payload of the IPv4 packet. + * @param proto The IP protocol number. + * @param checksum The expected IPv4 checksum value. + * @throws Exception An error occurred. + */ + private void firstFragmentTest(Packet payload, byte[] rawPayload, + byte proto, short checksum) + throws Exception { + // Construct a raw IPv4 packet with MF flag. + int ipv4Len = 20; + payload.setRawPayload(rawPayload); + byte[] payloadBytes = payload.serialize(); + byte[] rawIp = new byte[ipv4Len + payloadBytes.length]; + + byte ipVersion = 4; + byte dscp = 13; + byte ecn = 1; + byte tos = (byte)((dscp << 2) | ecn); + short totalLen = (short)rawIp.length; + short id = 19834; + byte flags = 0x1; + short offset = 0; + short off = (short)(((short)flags << 13) | offset); + byte ttl = 64; + byte[] srcIp = {(byte)0xac, (byte)0x23, (byte)0x5b, (byte)0xfd}; + byte[] dstIp = {(byte)0xc0, (byte)0xa8, (byte)0x64, (byte)0x71}; + + rawIp[0] = (byte)((ipVersion << 4) | (ipv4Len >> 2)); + rawIp[1] = tos; + rawIp[2] = (byte)(totalLen >>> Byte.SIZE); + rawIp[3] = (byte)totalLen; + rawIp[4] = (byte)(id >>> Byte.SIZE); + rawIp[5] = (byte)id; + rawIp[6] = (byte)(off >>> Byte.SIZE); + rawIp[7] = (byte)off; + rawIp[8] = ttl; + rawIp[9] = proto; + rawIp[10] = (byte)(checksum >>> Byte.SIZE); + rawIp[11] = (byte)checksum; + System.arraycopy(srcIp, 0, rawIp, 12, srcIp.length); + System.arraycopy(dstIp, 0, rawIp, 16, srcIp.length); + System.arraycopy(payloadBytes, 0, rawIp, ipv4Len, payloadBytes.length); + + // Deserialize. + IPv4 ipv4 = new IPv4(); + ipv4.deserialize(rawIp, 0, rawIp.length * Byte.SIZE); + + assertEquals(ipVersion, ipv4.getVersion()); + assertEquals(ipv4Len, ipv4.getHeaderLen()); + assertEquals(dscp, ipv4.getDiffServ()); + assertEquals(ecn, ipv4.getECN()); + assertEquals(totalLen, ipv4.getTotalLength()); + assertEquals(id, ipv4.getIdentification()); + assertEquals(flags, ipv4.getFlags()); + assertEquals(offset, ipv4.getFragmentOffset()); + assertEquals(ttl, ipv4.getTtl()); + assertEquals(proto, ipv4.getProtocol()); + assertEquals(checksum, ipv4.getChecksum()); + assertArrayEquals(srcIp, ipv4.getSourceAddress().getBytes()); + assertArrayEquals(dstIp, ipv4.getDestinationAddress().getBytes()); + assertEquals(false, ipv4.isCorrupted()); + + // Protocol header in the first fragment should be deserialized. + assertEquals(null, ipv4.getRawPayload()); + + Packet desPayload = ipv4.getPayload(); + assertEquals(payload, desPayload); + assertEquals(false, desPayload.isCorrupted()); + checkRawPayload(rawPayload, desPayload.getRawPayload()); + } + + /** + * Compare the raw payload. + * + * @param expected The expected raw payload. + * @param payload The raw payload to be tested. + */ + private void checkRawPayload(byte[] expected, byte[] payload) { + if (expected == null || expected.length == 0) { + assertEquals(null, payload); + } else { + assertArrayEquals(expected, payload); + } + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketExceptionTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketExceptionTest.java new file mode 100644 index 00000000..5f77b9a8 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketExceptionTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.TestBase; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnErrorTag; + +/** + * JUnit test for {@link PacketException}. + */ +public class PacketExceptionTest extends TestBase { + /** + * Test case for {@link PacketException#PacketException(String)}. + */ + @Test + public void testDefault() { + String[] messages = { + null, + "message 1", + "message 2", + }; + + IllegalArgumentException cause = new IllegalArgumentException(); + for (String msg: messages) { + PacketException e = new PacketException(msg); + assertEquals(VtnErrorTag.INTERNALERROR, e.getVtnErrorTag()); + assertEquals(msg, e.getMessage()); + assertEquals(null, e.getCause()); + + // Ensure that no cause is configured. + e.initCause(cause); + assertEquals(cause, e.getCause()); + } + } + + /** + * Test case for {@link PacketException#PacketException(String, Throwable)}. + */ + @Test + public void testCause() { + String[] messages = { + null, + "message 1", + "message 2", + }; + Throwable[] causes = { + new IllegalArgumentException(), + new IllegalStateException(), + new NullPointerException(), + }; + + for (String msg: messages) { + for (Throwable cause: causes) { + PacketException e = new PacketException(msg, cause); + assertEquals(VtnErrorTag.INTERNALERROR, e.getVtnErrorTag()); + assertEquals(msg, e.getMessage()); + assertEquals(cause, e.getCause()); + } + } + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketTest.java new file mode 100644 index 00000000..b4883286 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/PacketTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import java.util.Map; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link Packet}. + */ +public class PacketTest extends TestBase { + /** + * Test case for {@link Packet#deserialize(byte[], int, int)}. + * + * @throws Exception An error occurred. + */ + @Test + public void testDeserialize() throws Exception { + Ethernet eth = new Ethernet(); + byte[] data = { + // Destination MAC address + 10, 12, 14, 20, 55, 69, + + // Source MAC address + -90, -20, -100, -82, -78, -97, + + // Ethernet type (ARP) + 0x08, 0x06, + + // ARP + + // Hardware type + 0, 1, + + // Protocol type (IPv4) + 0x08, 0x00, + + // Hardware address length + 6, + + // Protocol address length + 4, + + // ARP operation code + 0, 1, + + // Sender hardware address + -90, -20, -100, -82, -78, -97, + + // Sender protocol address + 10, 20, 30, 55, + + // Target hardware address + 0, 0, 0, 0, 0, 0, + + // Target protocol address + 10, 20, 30, -2, + }; + + eth.deserialize(data, 0, data.length * Byte.SIZE); + + byte[] dstMac = eth.getDestinationMACAddress(); + byte[] srcMac = eth.getSourceMACAddress(); + short etype = eth.getEtherType(); + + assertEquals(10, dstMac[0]); + assertEquals(12, dstMac[1]); + assertEquals(14, dstMac[2]); + assertEquals(20, dstMac[3]); + assertEquals(55, dstMac[4]); + assertEquals(69, dstMac[5]); + + assertEquals(-90, srcMac[0]); + assertEquals(-20, srcMac[1]); + assertEquals(-100, srcMac[2]); + assertEquals(-82, srcMac[3]); + assertEquals(-78, srcMac[4]); + assertEquals(-97, srcMac[5]); + + assertEquals(0x806, etype); + + ARP arp = (ARP)eth.getPayload(); + + assertEquals((byte)0x1, arp.getHardwareType()); + assertEquals(2048, arp.getProtocolType()); + assertEquals((byte)0x6, arp.getHardwareAddressLength()); + assertEquals((byte)0x4, arp.getProtocolAddressLength()); + assertEquals(1, arp.getOpCode()); + + byte[] sha = arp.getSenderHardwareAddress(); + byte[] spa = arp.getSenderProtocolAddress(); + byte[] tha = arp.getTargetHardwareAddress(); + byte[] tpa = arp.getTargetProtocolAddress(); + + assertEquals((byte)0xA6, sha[0]); + assertEquals((byte)0xEC, sha[1]); + assertEquals((byte)0x9C, sha[2]); + assertEquals((byte)0xAE, sha[3]); + assertEquals((byte)0xB2, sha[4]); + assertEquals((byte)0x9F, sha[5]); + + assertEquals((byte)10, spa[0]); + assertEquals((byte)20, spa[1]); + assertEquals((byte)30, spa[2]); + assertEquals((byte)55, spa[3]); + + assertEquals((byte)0x0, tha[0]); + assertEquals((byte)0x0, tha[1]); + assertEquals((byte)0x0, tha[2]); + assertEquals((byte)0x0, tha[3]); + assertEquals((byte)0x0, tha[4]); + assertEquals((byte)0x0, tha[5]); + + assertEquals((byte)10, tpa[0]); + assertEquals((byte)20, tpa[1]); + assertEquals((byte)30, tpa[2]); + assertEquals((byte)-2, tpa[3]); + } + + /** + * Test case for {@link Packet#serialize()}. + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialize() throws Exception { + Ethernet eth = new Ethernet(); + Map header = eth.getHeaderFieldMap(); + + byte[] dstMac = {10, 12, 14, 20, 55, 69}; + byte[] srcMac = {82, 97, 109, 117, 127, -50}; + short etype = 0x0806; + + eth.setDestinationMACAddress(dstMac); + eth.setSourceMACAddress(srcMac); + eth.setEtherType(etype); + + assertArrayEquals(dstMac, header.get("DestinationMACAddress")); + assertArrayEquals(srcMac, header.get("SourceMACAddress")); + + byte[] etypeData = {0x08, 0x06}; + assertArrayEquals(etypeData, header.get("EtherType")); + + byte[] data = eth.serialize(); + assertEquals(10, data[0]); + assertEquals(12, data[1]); + assertEquals(14, data[2]); + assertEquals(20, data[3]); + assertEquals(55, data[4]); + assertEquals(69, data[5]); + + assertEquals(82, data[6]); + assertEquals(97, data[7]); + assertEquals(109, data[8]); + assertEquals(117, data[9]); + assertEquals(127, data[10]); + assertEquals(-50, data[11]); + + assertEquals(8, data[12]); + assertEquals(6, data[13]); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/TCPTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/TCPTest.java new file mode 100644 index 00000000..83d425e2 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/TCPTest.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link TCP}. + */ +public class TCPTest extends TestBase { + /** + * Test case for TCP source port. + * + *
        + *
      • {@link TCP#getSourcePort()}
      • + *
      • {@link TCP#setSourcePort(short)}
      • + *
      + */ + @Test + public void testGetSourcePort() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getSourcePort()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short port: values) { + assertSame(tcp, tcp.setSourcePort(port)); + assertEquals(port, tcp.getSourcePort()); + } + } + + /** + * Test case for TCP destination port. + * + *
        + *
      • {@link TCP#getDestinationPort()}
      • + *
      • {@link TCP#setDestinationPort(short)}
      • + *
      + */ + @Test + public void testGetDestinationPort() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getDestinationPort()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short port: values) { + assertSame(tcp, tcp.setDestinationPort(port)); + assertEquals(port, tcp.getDestinationPort()); + } + } + + /** + * Test case for TCP sequence number. + * + *
        + *
      • {@link TCP#getSequenceNumber()}
      • + *
      • {@link TCP#setSequenceNumber(int)}
      • + *
      + */ + @Test + public void testGetSequenceNumber() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getSequenceNumber()); + + int[] values = { + 1, 123, 4678, 0x12345678, 0x7fffffff, + -1, -12934, -91287345, Integer.MIN_VALUE, + }; + for (int seq: values) { + assertSame(tcp, tcp.setSequenceNumber(seq)); + assertEquals(seq, tcp.getSequenceNumber()); + } + } + + /** + * Test case for TCP acknowledgement number. + * + *
        + *
      • {@link TCP#getAckNumber()}
      • + *
      • {@link TCP#setAckNumber(int)}
      • + *
      + */ + @Test + public void testGetAckNumber() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getAckNumber()); + + int[] values = { + 1, 123, 4678, 0x12345678, 0x7fffffff, + -1, -12934, -91287345, Integer.MIN_VALUE, + }; + for (int ack: values) { + assertSame(tcp, tcp.setAckNumber(ack)); + assertEquals(ack, tcp.getAckNumber()); + } + } + + /** + * Test case for TCP data offset. + * + *
        + *
      • {@link TCP#getDataOffset()}
      • + *
      • {@link TCP#setDataOffset(byte)}
      • + *
      + */ + @Test + public void testGetDataOffset() { + TCP tcp = new TCP(); + assertEquals((byte)0, tcp.getDataOffset()); + + for (byte off = 0; off <= 15; off++) { + assertSame(tcp, tcp.setDataOffset(off)); + assertEquals(off, tcp.getDataOffset()); + } + } + + /** + * Test case for reserved field. + * + *
        + *
      • {@link TCP#getReserved()}
      • + *
      • {@link TCP#setReserved(byte)}
      • + *
      + */ + @Test + public void testGetReserved() { + TCP tcp = new TCP(); + assertEquals((byte)0, tcp.getReserved()); + + for (byte resv = 0; resv <= 7; resv++) { + assertSame(tcp, tcp.setReserved(resv)); + assertEquals(resv, tcp.getReserved()); + } + } + + /** + * Test case for TCP header length and TCP flags. + * + *
        + *
      • {@link TCP#getHeaderLenFlags()}
      • + *
      • {@link TCP#setHeaderLenFlags(short)}
      • + *
      + */ + @Test + public void testHeaderLenFlags() { + TCP tcp = new TCP(); + assertEquals((byte)0, tcp.getHeaderLenFlags()); + + short[] values = {0, 1, 33, 123, 312, 456, 509, 510, 511}; + for (short flags: values) { + assertSame(tcp, tcp.setHeaderLenFlags(flags)); + assertEquals(flags, tcp.getHeaderLenFlags()); + } + } + + /** + * Test case for TCP window size. + * + *
        + *
      • {@link TCP#getWindowSize()}
      • + *
      • {@link TCP#setWindowSize(short)}
      • + *
      + */ + @Test + public void testGetWindowSize() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getWindowSize()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short wsize: values) { + assertSame(tcp, tcp.setWindowSize(wsize)); + assertEquals(wsize, tcp.getWindowSize()); + } + } + + /** + * Test case for TCP checksum. + * + *
        + *
      • {@link TCP#getChecksum()}
      • + *
      • {@link TCP#setChecksum(short)}
      • + *
      + */ + @Test + public void testGetChecksum() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getChecksum()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short cksum: values) { + assertSame(tcp, tcp.setChecksum(cksum)); + assertEquals(cksum, tcp.getChecksum()); + } + } + + /** + * Test case for TCP urgent pointer. + * + *
        + *
      • {@link TCP#getUrgentPointer()}
      • + *
      • {@link TCP#setUrgentPointer(short)}
      • + *
      + */ + @Test + public void testGetUrgentPointer() { + TCP tcp = new TCP(); + assertEquals((short)0, tcp.getUrgentPointer()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short urg: values) { + assertSame(tcp, tcp.setUrgentPointer(urg)); + assertEquals(urg, tcp.getUrgentPointer()); + } + } + + /** + * Test case for {@link TCP#clone()}. + */ + @Test + public void testClone() { + short src = 16721; + short dst = 999; + int seq = 0x761231da; + int ack = 0x7319efc1; + byte off = 12; + byte resv = 2; + short flags = 503; + short wsize = 31982; + short cksum = -30981; + short urg = 7788; + TCP tcp = new TCP(). + setSourcePort(src). + setDestinationPort(dst). + setSequenceNumber(seq). + setAckNumber(ack). + setDataOffset(off). + setReserved(resv). + setHeaderLenFlags(flags). + setWindowSize(wsize). + setChecksum(cksum). + setUrgentPointer(urg); + + TCP copy = tcp.clone(); + assertNotSame(tcp, copy); + assertEquals(tcp, copy); + assertEquals(tcp.hashCode(), copy.hashCode()); + assertEquals(null, copy.getRawPayload()); + + // Modifying the source packet should never affect a deep copy. + short src1 = 29871; + short dst1 = 17; + int seq1 = (int)0xabcdef00; + int ack1 = (int)0x891d4fcb; + byte off1 = 3; + byte resv1 = 0; + byte flags1 = 81; + short wsize1 = 3600; + short cksum1 = 19826; + short urg1 = 4; + tcp.setSourcePort(src1). + setDestinationPort(dst1). + setSequenceNumber(seq1). + setAckNumber(ack1). + setDataOffset(off1). + setReserved(resv1). + setHeaderLenFlags(flags1). + setWindowSize(wsize1). + setChecksum(cksum1). + setUrgentPointer(urg1); + byte[] payload = { + (byte)0x9b, (byte)0x6d, (byte)0x30, (byte)0x0e, + }; + + assertEquals(src, copy.getSourcePort()); + assertEquals(dst, copy.getDestinationPort()); + assertEquals(seq, copy.getSequenceNumber()); + assertEquals(ack, copy.getAckNumber()); + assertEquals(off, copy.getDataOffset()); + assertEquals(resv, copy.getReserved()); + assertEquals(flags, copy.getHeaderLenFlags()); + assertEquals(wsize, copy.getWindowSize()); + assertEquals(cksum, copy.getChecksum()); + assertEquals(urg, copy.getUrgentPointer()); + + assertEquals(src1, tcp.getSourcePort()); + assertEquals(dst1, tcp.getDestinationPort()); + assertEquals(seq1, tcp.getSequenceNumber()); + assertEquals(ack1, tcp.getAckNumber()); + assertEquals(off1, tcp.getDataOffset()); + assertEquals(resv1, tcp.getReserved()); + assertEquals(flags1, tcp.getHeaderLenFlags()); + assertEquals(wsize1, tcp.getWindowSize()); + assertEquals(cksum1, tcp.getChecksum()); + assertEquals(urg1, tcp.getUrgentPointer()); + } + + /** + * Test for serialization and deserialization. + * + *
        + *
      • {@link Packet#serialize()}
      • + *
      • {@link Packet#deserialize(byte[], int, int)}
      • + *
      + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialization() throws Exception { + byte[] raw = { + // Source port. + (byte)0x41, (byte)0x9c, + + // Destination port. + (byte)0x00, (byte)0x35, + + // Sequence number. + (byte)0x41, (byte)0xdb, (byte)0x3a, (byte)0x91, + + // Acknowledgement number. + (byte)0xb7, (byte)0x05, (byte)0xb1, (byte)0x9b, + + // Data offset, reserved, header length, and flags. + (byte)0x9c, (byte)0xc1, + + // Window size. + (byte)0x52, (byte)0xd2, + + // Checksum. + (byte)0xd9, (byte)0x04, + + // Urgent pointer. + (byte)0x68, (byte)0xde, + }; + + short src = (short)0x419c; + short dst = (short)0x0035; + int seq = (int)0x41db3a91; + int ack = (int)0xb705b19b; + byte off = 0x9; + byte resv = 6; + short flags = 193; + short wsize = (short)0x52d2; + short cksum = (short)0xd904; + short urg = (short)0x68de; + + // Deserialize raw packet. + TCP tcp = new TCP(); + tcp.deserialize(raw, 0, raw.length * Byte.SIZE); + assertEquals(src, tcp.getSourcePort()); + assertEquals(dst, tcp.getDestinationPort()); + assertEquals(seq, tcp.getSequenceNumber()); + assertEquals(ack, tcp.getAckNumber()); + assertEquals(off, tcp.getDataOffset()); + assertEquals(resv, tcp.getReserved()); + assertEquals(flags, tcp.getHeaderLenFlags()); + assertEquals(wsize, tcp.getWindowSize()); + assertEquals(cksum, tcp.getChecksum()); + assertEquals(urg, tcp.getUrgentPointer()); + assertEquals(null, tcp.getPayload()); + assertEquals(null, tcp.getRawPayload()); + assertEquals(false, tcp.isCorrupted()); + + // Serialize packet. + assertArrayEquals(raw, tcp.serialize()); + + // Deserialize packet with TCP payload. + raw = new byte[]{ + // Source port. + (byte)0xb0, (byte)0xd9, + + // Destination port. + (byte)0x2e, (byte)0x8c, + + // Sequence number. + (byte)0xe6, (byte)0x0d, (byte)0x2a, (byte)0xdb, + + // Acknowledgement number. + (byte)0x5f, (byte)0x9c, (byte)0x76, (byte)0xf6, + + // Data offset, reserved, header length, and flags. + (byte)0xc5, (byte)0x37, + + // Window size. + (byte)0x49, (byte)0x6c, + + // Checksum. + (byte)0x36, (byte)0xad, + + // Urgent pointer. + (byte)0xd7, (byte)0xbd, + + // Payload. + (byte)0x7d, (byte)0xc9, (byte)0x39, (byte)0xf2, + (byte)0xf1, (byte)0x4f, (byte)0xc4, (byte)0x73, + (byte)0x66, + }; + + src = (short)0xb0d9; + dst = (short)0x2e8c; + seq = (int)0xe60d2adb; + ack = (int)0x5f9c76f6; + off = 0xc; + resv = 2; + flags = 311; + wsize = (short)0x496c; + cksum = (short)0x36ad; + urg = (short)0xd7bd; + byte[] payload = { + (byte)0x7d, (byte)0xc9, (byte)0x39, (byte)0xf2, + (byte)0xf1, (byte)0x4f, (byte)0xc4, (byte)0x73, + (byte)0x66, + }; + + tcp = new TCP(); + tcp.deserialize(raw, 0, raw.length * Byte.SIZE); + assertEquals(src, tcp.getSourcePort()); + assertEquals(dst, tcp.getDestinationPort()); + assertEquals(seq, tcp.getSequenceNumber()); + assertEquals(ack, tcp.getAckNumber()); + assertEquals(off, tcp.getDataOffset()); + assertEquals(resv, tcp.getReserved()); + assertEquals(flags, tcp.getHeaderLenFlags()); + assertEquals(wsize, tcp.getWindowSize()); + assertEquals(cksum, tcp.getChecksum()); + assertEquals(urg, tcp.getUrgentPointer()); + assertEquals(null, tcp.getPayload()); + assertArrayEquals(payload, tcp.getRawPayload()); + assertEquals(false, tcp.isCorrupted()); + + // Serialize packet. + assertArrayEquals(raw, tcp.serialize()); + + // Serialize an empty packet. + tcp = new TCP(); + byte[] expected = new byte[20]; + assertArrayEquals(expected, tcp.serialize()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/UDPTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/UDPTest.java new file mode 100644 index 00000000..e82f4df0 --- /dev/null +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/packet/UDPTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015 NEC Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vtn.manager.packet; + +import org.junit.Test; + +import org.opendaylight.vtn.manager.TestBase; + +/** + * JUnit test for {@link UDP}. + */ +public class UDPTest extends TestBase { + /** + * Test case for UDP source port. + * + *
        + *
      • {@link UDP#getSourcePort()}
      • + *
      • {@link UDP#setSourcePort(short)}
      • + *
      + */ + @Test + public void testGetSourcePort() { + UDP udp = new UDP(); + assertEquals((short)0, udp.getSourcePort()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short port: values) { + assertSame(udp, udp.setSourcePort(port)); + assertEquals(port, udp.getSourcePort()); + } + } + + /** + * Test case for UDP destination port. + * + *
        + *
      • {@link UDP#getDestinationPort()}
      • + *
      • {@link UDP#setDestinationPort(short)}
      • + *
      + */ + @Test + public void testGetDestinationPort() { + UDP udp = new UDP(); + assertEquals((short)0, udp.getDestinationPort()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short port: values) { + assertSame(udp, udp.setDestinationPort(port)); + assertEquals(port, udp.getDestinationPort()); + } + } + + /** + * Test case for UDP datagram length. + * + *
        + *
      • {@link UDP#getLength()}
      • + *
      • {@link UDP#setLength(short)}
      • + *
      + */ + @Test + public void testGetLength() { + UDP udp = new UDP(); + assertEquals((short)0, udp.getLength()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short len: values) { + assertSame(udp, udp.setLength(len)); + assertEquals(len, udp.getLength()); + } + } + + /** + * Test case for UDP checksum. + * + *
        + *
      • {@link UDP#getChecksum()}
      • + *
      • {@link UDP#setChecksum(short)}
      • + *
      + */ + @Test + public void testGetChecksum() { + UDP udp = new UDP(); + assertEquals((short)0, udp.getLength()); + + short[] values = {1, 4, 99, 2054, 30000, 32767, -32768, -2, -1}; + for (short cksum: values) { + assertSame(udp, udp.setChecksum(cksum)); + assertEquals(cksum, udp.getChecksum()); + } + } + + /** + * Test case for {@link UDP#clone()}. + */ + @Test + public void testClone() { + short src = 32144; + short dst = 53; + short len = 3128; + short cksum = -28714; + byte[] payload = { + (byte)0x4e, (byte)0x99, (byte)0xe2, (byte)0x52, + (byte)0xc3, (byte)0x4f, (byte)0x3e, (byte)0xac, + }; + + UDP udp = new UDP(). + setSourcePort(src). + setDestinationPort(dst). + setLength(len). + setChecksum(cksum); + udp.setRawPayload(payload); + + UDP copy = udp.clone(); + assertNotSame(udp, copy); + assertEquals(udp, copy); + assertEquals(udp.hashCode(), copy.hashCode()); + assertArrayEquals(payload, copy.getRawPayload()); + + // Modifying the source packet should never affect a deep copy. + short src1 = 4567; + short dst1 = 80; + short len1 = 7811; + short cksum1 = 31985; + udp.setSourcePort(src1). + setDestinationPort(dst1). + setLength(len1). + setChecksum(cksum1); + udp.setRawPayload(null); + + assertEquals(src, copy.getSourcePort()); + assertEquals(dst, copy.getDestinationPort()); + assertEquals(len, copy.getLength()); + assertEquals(cksum, copy.getChecksum()); + assertArrayEquals(payload, copy.getRawPayload()); + + assertEquals(src1, udp.getSourcePort()); + assertEquals(dst1, udp.getDestinationPort()); + assertEquals(len1, udp.getLength()); + assertEquals(cksum1, udp.getChecksum()); + assertEquals(null, udp.getRawPayload()); + } + + /** + * Test for serialization and deserialization. + * + *
        + *
      • {@link Packet#serialize()}
      • + *
      • {@link Packet#deserialize(byte[], int, int)}
      • + *
      + * + * @throws Exception An error occurred. + */ + @Test + public void testSerialization() throws Exception { + byte[] raw = { + // Source port. + (byte)0x01, (byte)0x35, + + // Destination port. + (byte)0x31, (byte)0x9d, + + // Length + (byte)0x01, (byte)0x16, + + // Checksum + (byte)0xd4, (byte)0x41, + }; + + short src = (short)0x0135; + short dst = (short)0x319d; + short len = (short)0x0116; + short cksum = (short)0xd441; + + // Deserialize raw packet. + UDP udp = new UDP(); + udp.deserialize(raw, 0, raw.length * Byte.SIZE); + assertEquals(src, udp.getSourcePort()); + assertEquals(dst, udp.getDestinationPort()); + assertEquals(len, udp.getLength()); + assertEquals(cksum, udp.getChecksum()); + assertEquals(null, udp.getPayload()); + assertEquals(null, udp.getRawPayload()); + assertEquals(false, udp.isCorrupted()); + + // Serialize packet. + assertArrayEquals(raw, udp.serialize()); + + // Deserialize packet with UDP payload. + raw = new byte[]{ + // Source port. + (byte)0x74, (byte)0x1d, + + // Destination port. + (byte)0x00, (byte)0x31, + + // Length + (byte)0x12, (byte)0x34, + + // Checksum + (byte)0x91, (byte)0xdf, + + // Payload + (byte)0x26, (byte)0xa6, (byte)0xdf, (byte)0x80, + (byte)0x06, (byte)0xb5, (byte)0xd6, (byte)0xa0, + (byte)0x66, (byte)0xf2, (byte)0x38, (byte)0x6e, + (byte)0x36, (byte)0x19, (byte)0xa9, + }; + + src = (short)0x741d; + dst = (short)0x0031; + len = (short)0x1234; + cksum = (short)0x91df; + byte[] payload = { + (byte)0x26, (byte)0xa6, (byte)0xdf, (byte)0x80, + (byte)0x06, (byte)0xb5, (byte)0xd6, (byte)0xa0, + (byte)0x66, (byte)0xf2, (byte)0x38, (byte)0x6e, + (byte)0x36, (byte)0x19, (byte)0xa9, + }; + + // Deserialize raw packet. + udp = new UDP(); + udp.deserialize(raw, 0, raw.length * Byte.SIZE); + assertEquals(src, udp.getSourcePort()); + assertEquals(dst, udp.getDestinationPort()); + assertEquals(len, udp.getLength()); + assertEquals(cksum, udp.getChecksum()); + assertEquals(null, udp.getPayload()); + assertArrayEquals(payload, udp.getRawPayload()); + assertEquals(false, udp.isCorrupted()); + + // Serialize packet. + assertArrayEquals(raw, udp.serialize()); + + // Serialize an empty packet. + udp = new UDP(); + byte[] expected = new byte[8]; + assertArrayEquals(expected, udp.serialize()); + } +} diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/ByteUtilsTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/ByteUtilsTest.java index dbf2d12f..c9faf2da 100644 --- a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/ByteUtilsTest.java +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/ByteUtilsTest.java @@ -128,4 +128,359 @@ public class ByteUtilsTest extends TestBase { } } } + + /** + * Test case for {@link ByteUtils#getBits(byte[], int, int)}. + */ + @Test + public void testGetBits() { + byte[] data = {10, 12, 14, 20, 55, 69, 82, 97, 109, 117, 127, -50}; + byte[] bits; + + // Zero bits + bits = ByteUtils.getBits(data, 10, 0); + assertEquals(0, bits.length); + + // In case of simple byte copy + bits = ByteUtils.getBits(data, 88, 8); + assertEquals((byte)-50, bits[0]); + assertEquals(1, bits.length); + + bits = ByteUtils.getBits(data, 8, 16); + assertEquals((byte)12, bits[0]); + assertEquals((byte)14, bits[1]); + assertEquals(2, bits.length); + + bits = ByteUtils.getBits(data, 32, 32); + assertEquals((byte)55, bits[0]); + assertEquals((byte)69, bits[1]); + assertEquals((byte)82, bits[2]); + assertEquals((byte)97, bits[3]); + assertEquals(4, bits.length); + + bits = ByteUtils.getBits(data, 16, 48); + assertEquals((byte)14, bits[0]); + assertEquals((byte)20, bits[1]); + assertEquals((byte)55, bits[2]); + assertEquals((byte)69, bits[3]); + assertEquals((byte)82, bits[4]); + assertEquals((byte)97, bits[5]); + assertEquals(6, bits.length); + + // Partial bits + bits = ByteUtils.getBits(data, 40, 7); + assertEquals((byte)34, bits[0]); + assertEquals(1, bits.length); + + bits = ByteUtils.getBits(data, 8, 13); + assertEquals((byte)1, bits[0]); + assertEquals((byte)-127, bits[1]); + assertEquals(2, bits.length); + + bits = ByteUtils.getBits(data, 32, 28); + assertEquals((byte)3, bits[0]); + assertEquals((byte)116, bits[1]); + assertEquals((byte)85, bits[2]); + assertEquals((byte)38, bits[3]); + assertEquals(4, bits.length); + + bits = ByteUtils.getBits(data, 16, 41); + assertEquals((byte)0, bits[0]); + assertEquals((byte)28, bits[1]); + assertEquals((byte)40, bits[2]); + assertEquals((byte)110, bits[3]); + assertEquals((byte)-118, bits[4]); + assertEquals((byte)-92, bits[5]); + assertEquals(6, bits.length); + + // Unaligned + bits = ByteUtils.getBits(data, 3, 8); + assertEquals((byte)80, bits[0]); + assertEquals(1, bits.length); + + bits = ByteUtils.getBits(data, 13, 16); + assertEquals((byte)-127, bits[0]); + assertEquals((byte)-62, bits[1]); + assertEquals(2, bits.length); + + bits = ByteUtils.getBits(data, 5, 32); + assertEquals((byte)65, bits[0]); + assertEquals((byte)-127, bits[1]); + assertEquals((byte)-62, bits[2]); + assertEquals((byte)-122, bits[3]); + assertEquals(4, bits.length); + + bits = ByteUtils.getBits(data, 23, 48); + assertEquals((byte)10, bits[0]); + assertEquals((byte)27, bits[1]); + assertEquals((byte)-94, bits[2]); + assertEquals((byte)-87, bits[3]); + assertEquals((byte)48, bits[4]); + assertEquals((byte)-74, bits[5]); + assertEquals(6, bits.length); + + // Unaligned and partial bits + bits = ByteUtils.getBits(data, 66, 9); + assertEquals((byte)1, bits[0]); + assertEquals((byte)107, bits[1]); + assertEquals(2, bits.length); + + bits = ByteUtils.getBits(data, 13, 15); + assertEquals((byte)64, bits[0]); + assertEquals((byte)-31, bits[1]); + assertEquals(2, bits.length); + + bits = ByteUtils.getBits(data, 5, 29); + assertEquals((byte)8, bits[0]); + assertEquals((byte)48, bits[1]); + assertEquals((byte)56, bits[2]); + assertEquals((byte)80, bits[3]); + assertEquals(4, bits.length); + + bits = ByteUtils.getBits(data, 31, 43); + assertEquals((byte)0, bits[0]); + assertEquals((byte)-35, bits[1]); + assertEquals((byte)21, bits[2]); + assertEquals((byte)73, bits[3]); + assertEquals((byte)-123, bits[4]); + assertEquals((byte)-75, bits[5]); + assertEquals(6, bits.length); + + bits = ByteUtils.getBits(data, 4, 12); + assertEquals((byte)10, bits[0]); + assertEquals((byte)12, bits[1]); + assertEquals(2, bits.length); + + byte[] data1 = {0, 8}; + bits = ByteUtils.getBits(data1, 7, 9); + assertEquals((byte)0, bits[0]); + assertEquals((byte)8, bits[1]); + assertEquals(2, bits.length); + + byte[] data2 = {2, 8}; + bits = ByteUtils.getBits(data2, 0, 7); + assertEquals((byte)1, bits[0]); + assertEquals(1, bits.length); + + bits = ByteUtils.getBits(data2, 7, 9); + assertEquals((byte)0, bits[0]); + assertEquals((byte)8, bits[1]); + assertEquals(2, bits.length); + } + + /** + * Test case for {@link ByteUtils#setBits(byte[], byte[], int, int)}. + */ + @Test + public void testSetBits() { + byte[] data = { + 74, 79, 14, -110, 55, -3, 82, 97, + -63, 117, 127, -50, 127, 95, -31, 3, + }; + byte[] original = data.clone(); + byte[] expected = data.clone(); + + // Zero bits + byte[] input = {}; + ByteUtils.setBits(data, input, 3, 0); + assertArrayEquals(original, data); + + // In case of simple byte copy + int index = 1; + input = new byte[]{31}; + ByteUtils.setBits(data, input, index * 8, input.length * Byte.SIZE); + expected[index] = input[0]; + assertArrayEquals(expected, data); + + index = 3; + input = new byte[]{91, -116}; + ByteUtils.setBits(data, input, index * 8, input.length * Byte.SIZE); + for (int i = 0; i < input.length; i++) { + expected[index + i] = input[i]; + } + assertArrayEquals(expected, data); + + index = 7; + input = new byte[]{1, 93, -89, 73}; + ByteUtils.setBits(data, input, index * 8, input.length * Byte.SIZE); + for (int i = 0; i < input.length; i++) { + expected[index + i] = input[i]; + } + assertArrayEquals(expected, data); + + index = 8; + input = new byte[]{33, 81, 124, -47, 10, 43, 77, -93}; + ByteUtils.setBits(data, input, index * 8, input.length * Byte.SIZE); + for (int i = 0; i < input.length; i++) { + expected[index + i] = input[i]; + } + assertArrayEquals(expected, data); + + // Partial bits + data = original.clone(); + expected = original.clone(); + input = new byte[]{45}; + index = 15; + ByteUtils.setBits(data, input, index * 8, 6); + expected[index] = -73; + assertArrayEquals(expected, data); + + input = new byte[]{54, 77}; + index = 2; + ByteUtils.setBits(data, input, index * 8, 14); + expected[index] = -39; + expected[index + 1] = 54; + assertArrayEquals(expected, data); + + input = new byte[]{1, -36, 25, -121}; + index = 7; + ByteUtils.setBits(data, input, index * 8, 25); + expected[index] = -18; + expected[index + 1] = 12; + expected[index + 2] = -61; + expected[index + 3] = -1; + assertArrayEquals(expected, data); + + input = new byte[]{5, 57, 28, -66, 118, -13, -100, -75}; + index = 6; + ByteUtils.setBits(data, input, index * 8, 59); + expected[index] = -89; + expected[index + 1] = 35; + expected[index + 2] = -105; + expected[index + 3] = -50; + expected[index + 4] = -34; + expected[index + 5] = 115; + expected[index + 6] = -106; + expected[index + 7] = -65; + assertArrayEquals(expected, data); + + // Unaligned + data = original.clone(); + expected = original.clone(); + input = new byte[]{-74}; + index = 0; + int off = 3; + ByteUtils.setBits(data, input, index * 8 + off, + input.length * Byte.SIZE); + expected[index] = 86; + expected[index + 1] = -49; + assertArrayEquals(expected, data); + + input = new byte[]{106, -51}; + index = 13; + off = 7; + ByteUtils.setBits(data, input, index * 8 + off, + input.length * Byte.SIZE); + expected[index] = 94; + expected[index + 1] = -43; + expected[index + 2] = -101; + assertArrayEquals(expected, data); + + input = new byte[]{-121, 18, 58, -111}; + index = 3; + off = 1; + ByteUtils.setBits(data, input, index * 8 + off, + input.length * Byte.SIZE); + expected[index] = -61; + expected[index + 1] = -119; + expected[index + 2] = 29; + expected[index + 3] = 72; + expected[index + 4] = -31; + assertArrayEquals(expected, data); + + input = new byte[]{-77, 26, -104, 54, 51, 21, -20, -45}; + index = 7; + off = 6; + ByteUtils.setBits(data, input, index * 8 + off, + input.length * Byte.SIZE); + expected[index] = -30; + expected[index + 1] = -52; + expected[index + 2] = 106; + expected[index + 3] = 96; + expected[index + 4] = -40; + expected[index + 5] = -52; + expected[index + 6] = 87; + expected[index + 7] = -77; + expected[index + 8] = 79; + assertArrayEquals(expected, data); + + // Unaligned and partial bits + data = original.clone(); + expected = original.clone(); + input = new byte[]{9}; + index = 11; + off = 6; + ByteUtils.setBits(data, input, index * 8 + off, 5); + expected[index] = -51; + expected[index + 1] = 63; + assertArrayEquals(expected, data); + + input = new byte[]{29, 109}; + index = 8; + off = 1; + ByteUtils.setBits(data, input, index * 8 + off, 14); + expected[index] = -70; + expected[index + 1] = -37; + assertArrayEquals(expected, data); + + input = new byte[]{26, 53, -56, 59}; + index = 1; + off = 3; + ByteUtils.setBits(data, input, index * 8 + off, 29); + expected[index] = 90; + expected[index + 1] = 53; + expected[index + 2] = -56; + expected[index + 3] = 59; + assertArrayEquals(expected, data); + + input = new byte[]{40, -37, 78, -95, 53, 23, -52, 35}; + index = 7; + off = 7; + ByteUtils.setBits(data, input, index * 8 + off, 63); + expected[index] = 96; + expected[index + 1] = -93; + expected[index + 2] = 109; + expected[index + 3] = 58; + expected[index + 4] = -124; + expected[index + 5] = -44; + expected[index + 6] = 95; + expected[index + 7] = 48; + expected[index + 8] = -113; + assertArrayEquals(expected, data); + + input = new byte[]{0, 1}; + data = new byte[]{6, 0}; + ByteUtils.setBits(data, input, 7, 9); + assertEquals((byte)6, data[0]); + assertEquals((byte)1, data[1]); + + input = new byte[]{1}; + ByteUtils.setBits(data, input, 0, 1); + assertEquals((byte)-122, data[0]); + assertEquals((byte)1, data[1]); + + ByteUtils.setBits(data, input, 3, 1); + assertEquals((byte)-106, data[0]); + assertEquals((byte)1, data[1]); + + input = new byte[]{0x3}; + data = new byte[]{0, -88, 0, 0}; + ByteUtils.setBits(data, input, 14, 2); + assertEquals((byte)0, data[0]); + assertEquals((byte)-85, data[1]); + assertEquals((byte)0, data[2]); + assertEquals((byte)0, data[3]); + + input = new byte[1]; + for (int nbits = 1; nbits <= 8; nbits++) { + int mask = (1 << nbits) - 1; + input[0] = (byte)mask; + for (int boff = 0; boff <= 32 - nbits; boff++) { + data = new byte[]{0, 0, 0, 0}; + ByteUtils.setBits(data, input, boff, nbits); + int exmask = mask << (32 - nbits - boff); + assertEquals(exmask, NumberUtils.toInteger(data)); + } + } + } } diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/EtherTypesTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/EtherTypesTest.java index 429a83b5..785f4f69 100644 --- a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/EtherTypesTest.java +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/EtherTypesTest.java @@ -39,4 +39,25 @@ public class EtherTypesTest extends TestBase { assertEquals((short)0x88a8, EtherTypes.QINQ.shortValue()); assertEquals((short)0x88cc, EtherTypes.LLDP.shortValue()); } + + /** + * Test case for {@link EtherTypes#forValue(short)}. + */ + @Test + public void testForValue() { + short[] badTypes = { + (short)0x0000, (short)0x0011, (short)0x07ff, (short)0x0805, + (short)0x7fff, (short)0x8000, (short)0x8101, (short)0x8888, + (short)0x8999, (short)0x9999, (short)0xabcd, (short)0xcdef, + (short)0xcef0, (short)0xf000, (short)0xfff0, (short)0xffff, + }; + + for (short type: badTypes) { + assertEquals(null, EtherTypes.forValue(type)); + } + + for (EtherTypes etype: EtherTypes.values()) { + assertEquals(etype, EtherTypes.forValue(etype.shortValue())); + } + } } diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/InetProtocolsTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/InetProtocolsTest.java index e341f160..457d7b41 100644 --- a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/InetProtocolsTest.java +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/InetProtocolsTest.java @@ -45,4 +45,24 @@ public class InetProtocolsTest extends TestBase { assertEquals((byte)6, InetProtocols.TCP.byteValue()); assertEquals((byte)17, InetProtocols.UDP.byteValue()); } + + /** + * Test case for {@link InetProtocols#forValue(byte)}. + */ + @Test + public void testForValue() { + for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { + byte value = (byte)i; + InetProtocols proto = InetProtocols.forValue(value); + if (i == 1) { + assertEquals(InetProtocols.ICMP, proto); + } else if (i == 6) { + assertEquals(InetProtocols.TCP, proto); + } else if (i == 17) { + assertEquals(InetProtocols.UDP, proto); + } else { + assertEquals(null, proto); + } + } + } } diff --git a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/NumberUtilsTest.java b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/NumberUtilsTest.java index e5a2c9ce..b13ebd51 100644 --- a/manager/api/src/test/java/org/opendaylight/vtn/manager/util/NumberUtilsTest.java +++ b/manager/api/src/test/java/org/opendaylight/vtn/manager/util/NumberUtilsTest.java @@ -161,6 +161,60 @@ public class NumberUtilsTest extends TestBase { } } + /** + * Test case for {@link NumberUtils#toShort(byte[])} and + * {@link NumberUtils#toBytes(short)}. + */ + @Test + public void testToShortBytes() { + try { + NumberUtils.toShort((byte[])null); + unexpected(); + } catch (NullPointerException e) { + } + + for (int i = 0; i <= 10; i++) { + if (i == 2) { + continue; + } + + byte[] b = new byte[i]; + try { + NumberUtils.toShort(b); + unexpected(); + } catch (IllegalArgumentException e) { + assertEquals("Invalid byte array length: " + i, + e.getMessage()); + } + } + + HashMap cases = new HashMap<>(); + cases.put(new byte[]{0, 0}, (short)0); + cases.put(new byte[]{0, 1}, (short)1); + cases.put(new byte[]{0, 2}, (short)2); + cases.put(new byte[]{0, (byte)0xff}, (short)255); + cases.put(new byte[]{1, 0}, (short)256); + cases.put(new byte[]{(byte)0x10, (byte)0xff}, (short)4351); + cases.put(new byte[]{(byte)0x59, (byte)0x34}, (short)22836); + cases.put(new byte[]{(byte)0x7f, (byte)0xfe}, (short)32766); + cases.put(new byte[]{(byte)0x7f, (byte)0xff}, (short)32767); + cases.put(new byte[]{(byte)0x80, (byte)0x00}, (short)-32768); + cases.put(new byte[]{(byte)0x80, (byte)0x01}, (short)-32767); + cases.put(new byte[]{(byte)0x9a, (byte)0x1b}, (short)-26085); + cases.put(new byte[]{(byte)0xde, (byte)0xad}, (short)-8531); + cases.put(new byte[]{(byte)0xff, (byte)0xfc}, (short)-4); + cases.put(new byte[]{(byte)0xff, (byte)0xfd}, (short)-3); + cases.put(new byte[]{(byte)0xff, (byte)0xfe}, (short)-2); + cases.put(new byte[]{(byte)0xff, (byte)0xff}, (short)-1); + + for (Map.Entry entry: cases.entrySet()) { + byte[] b = entry.getKey(); + short v = entry.getValue(); + assertEquals(v, NumberUtils.toShort(b)); + assertArrayEquals(b, NumberUtils.toBytes(v)); + } + } + /** * Test case for {@link NumberUtils#getUnsigned(byte)}. */ diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/PacketContext.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/PacketContext.java index 9965a124..1b65815f 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/PacketContext.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/PacketContext.java @@ -23,6 +23,14 @@ import org.slf4j.LoggerFactory; import org.opendaylight.vtn.manager.VNodePath; import org.opendaylight.vtn.manager.VNodeRoute; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.IPv4; +import org.opendaylight.vtn.manager.packet.Packet; +import org.opendaylight.vtn.manager.packet.TCP; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.util.Ip4Network; @@ -57,15 +65,6 @@ import org.opendaylight.vtn.manager.internal.util.packet.Layer4Header; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.Packet; -import org.opendaylight.controller.sal.packet.RawPacket; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.rev150410.VirtualRouteReason; @@ -89,9 +88,9 @@ public class PacketContext implements Cloneable, FlowMatchContext { private static final int ETHER_TYPE_MASK = 0xffff; /** - * A received raw packet. + * A {@link SalPort} instance which specifies the ingress switch port. */ - private final RawPacket rawPacket; + private final SalPort ingressPort; /** * PACKET_IN event. @@ -218,7 +217,7 @@ public class PacketContext implements Cloneable, FlowMatchContext { * @param ev A {@link PacketInEvent} instance. */ PacketContext(PacketInEvent ev) { - rawPacket = ev.getPayload(); + ingressPort = ev.getIngressPort(); etherFrame = new EtherPacket(ev.getEthernet()); txContext = ev.getTxContext(); packetIn = ev; @@ -237,7 +236,7 @@ public class PacketContext implements Cloneable, FlowMatchContext { * @param ctx A MD-SAL datastore transaction only for read. */ PacketContext(Ethernet ether, SalPort out, TxContext ctx) { - rawPacket = null; + ingressPort = null; etherFrame = new EtherPacket(ether); txContext = ctx; egressPort = out; @@ -335,11 +334,11 @@ public class PacketContext implements Cloneable, FlowMatchContext { * the packet was received from. */ public PortVlan getIncomingNetwork() { - if (rawPacket == null) { + if (ingressPort == null) { return null; } - NodeConnector nc = rawPacket.getIncomingNodeConnector(); + NodeConnector nc = ingressPort.getAdNodeConnector(); return new PortVlan(nc, (short)etherFrame.getOriginalVlan()); } diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java index 44983f0f..148cdd1e 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java @@ -71,6 +71,7 @@ import org.opendaylight.vtn.manager.flow.cond.FlowCondition; import org.opendaylight.vtn.manager.flow.cond.FlowMatch; import org.opendaylight.vtn.manager.flow.filter.FlowFilter; import org.opendaylight.vtn.manager.flow.filter.FlowFilterId; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.util.VTNIdentifiableComparator; @@ -137,7 +138,6 @@ import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.UpdateType; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.address.DataLinkAddress; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.Status; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerProvider.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerProvider.java index 2169c9d2..6d72614f 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerProvider.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerProvider.java @@ -15,6 +15,7 @@ import java.util.concurrent.Future; import com.google.common.util.concurrent.FutureCallback; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.internal.util.concurrent.VTNFuture; import org.opendaylight.vtn.manager.internal.util.flow.VTNFlowBuilder; @@ -22,8 +23,6 @@ import org.opendaylight.vtn.manager.internal.util.inventory.SalPort; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.binding.RpcService; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/MacMapImpl.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/MacMapImpl.java index 12dfd44c..23fbb70b 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/MacMapImpl.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/MacMapImpl.java @@ -29,6 +29,7 @@ import org.opendaylight.vtn.manager.VBridgePath; import org.opendaylight.vtn.manager.VNodeRoute; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.util.EtherAddress; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.internal.IVTNResourceManager; import org.opendaylight.vtn.manager.internal.MacAddressTable; @@ -52,7 +53,6 @@ import org.opendaylight.vtn.manager.internal.util.inventory.SalPort; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.address.DataLinkAddress; import org.opendaylight.controller.sal.packet.address.EthernetAddress; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortBridge.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortBridge.java index be1076b6..79f0d212 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortBridge.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortBridge.java @@ -20,6 +20,7 @@ import org.opendaylight.vtn.manager.VInterfacePath; import org.opendaylight.vtn.manager.VNodePath; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.VTenantPath; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.internal.LockStack; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -36,7 +37,6 @@ import org.opendaylight.vtn.manager.internal.util.inventory.SalPort; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeState; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnUpdateType; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortInterface.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortInterface.java index dee60a5b..176d63e7 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortInterface.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/PortInterface.java @@ -24,6 +24,7 @@ import org.opendaylight.vtn.manager.VNodePath; import org.opendaylight.vtn.manager.VNodeRoute; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.VTenantPath; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.internal.IVTNResourceManager; @@ -49,7 +50,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.VTNFlowBuilder; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.UpdateType; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.rev150410.VirtualRouteReason; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.node.info.VtnPort; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/VlanMapImpl.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/VlanMapImpl.java index 720e962b..ff645c24 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/VlanMapImpl.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/cluster/VlanMapImpl.java @@ -21,6 +21,7 @@ import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.VTenantPath; import org.opendaylight.vtn.manager.VlanMap; import org.opendaylight.vtn.manager.VlanMapConfig; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.internal.IVTNResourceManager; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -40,7 +41,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev15020 import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.flow.rev150410.VirtualRouteReason; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeState; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/PacketInEvent.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/PacketInEvent.java index fb5cbee3..cf9c5aec 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/PacketInEvent.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/PacketInEvent.java @@ -9,14 +9,13 @@ package org.opendaylight.vtn.manager.internal.packet; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.PacketException; import org.opendaylight.vtn.manager.internal.util.inventory.SalPort; import org.opendaylight.vtn.manager.internal.util.tx.TxEvent; import org.opendaylight.controller.sal.core.ConstructionException; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.PacketException; -import org.opendaylight.controller.sal.packet.RawPacket; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived; @@ -35,11 +34,6 @@ public final class PacketInEvent extends TxEvent { */ private final SalPort ingressPort; - /** - * A {@link RawPacket} instance which represents the received packet. - */ - private final RawPacket payload; - /** * Decoded ethernet frame. */ @@ -66,8 +60,6 @@ public final class PacketInEvent extends TxEvent { ingressPort = ingress; byte[] bytes = rcv.getPayload(); - payload = new RawPacket(bytes); - payload.setIncomingNodeConnector(ingressPort.getAdNodeConnector()); ethernet = new Ethernet(); ethernet.deserialize(bytes, 0, bytes.length * Byte.SIZE); } @@ -81,7 +73,6 @@ public final class PacketInEvent extends TxEvent { public PacketInEvent(VTNPacketListener l, PacketInEvent ev) { listener = l; ingressPort = ev.ingressPort; - payload = ev.payload; ethernet = ev.ethernet; } @@ -95,16 +86,6 @@ public final class PacketInEvent extends TxEvent { return ingressPort; } - /** - * Return a {@link RawPacket} instance which represents the received - * packet. - * - * @return A {@link RawPacket} instance. - */ - public RawPacket getPayload() { - return payload; - } - /** * Return a {@link Ethernet} instance which represents the received * packet. diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/VTNPacketService.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/VTNPacketService.java index 1b4192fa..f989c844 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/VTNPacketService.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/VTNPacketService.java @@ -22,6 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.internal.VTNManagerProvider; @@ -45,8 +46,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Pa import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived; import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder; -import org.opendaylight.controller.sal.packet.Packet; - /** * Provider of internal packet services. */ diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/CachedPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/CachedPacket.java index b894da48..2968f63a 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/CachedPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/CachedPacket.java @@ -9,11 +9,10 @@ package org.opendaylight.vtn.manager.internal.packet.cache; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.internal.PacketContext; -import org.opendaylight.controller.sal.packet.Packet; - /** * {@code CachedPacket} defines interfaces that implements cache for a * {@link Packet} instance. diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacket.java index a0315da8..70748f5e 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacket.java @@ -10,6 +10,9 @@ package org.opendaylight.vtn.manager.internal.packet.cache; import java.util.Set; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.NumberUtils; @@ -22,10 +25,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNEtherMatch; import org.opendaylight.vtn.manager.internal.util.packet.EtherHeader; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.Packet; - /** * {@code EtherPacket} class implements a cache for a {@link Ethernet} * instance including VLAN tag. diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacket.java index c1172c70..d8533218 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacket.java @@ -12,10 +12,10 @@ import java.util.Set; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.ICMP; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.PacketContext; -import org.opendaylight.vtn.manager.internal.util.MiscUtils; import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetIcmpCodeAction; import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetIcmpTypeAction; import org.opendaylight.vtn.manager.internal.util.flow.match.FlowMatchType; @@ -23,8 +23,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNIcmpMatch; import org.opendaylight.vtn.manager.internal.util.packet.IcmpHeader; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; -import org.opendaylight.controller.sal.packet.ICMP; - /** * {@code IcmpPacket} class implements a cache for an {@link ICMP} instance. */ @@ -208,13 +206,11 @@ public final class IcmpPacket implements L4Packet, IcmpHeader { * Return an {@link ICMP} instance to set modified values. * * @return An {@link ICMP} instance. - * @throws VTNException - * Failed to copy the packet. */ - private ICMP getPacketForWrite() throws VTNException { + private ICMP getPacketForWrite() { if (cloned) { // Create a copy of the original packet. - packet = MiscUtils.copy(packet, new ICMP()); + packet = packet.clone(); cloned = false; } diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4Packet.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4Packet.java index 497e4131..ed3c28fb 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4Packet.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4Packet.java @@ -8,16 +8,15 @@ package org.opendaylight.vtn.manager.internal.packet.cache; -import java.net.InetAddress; import java.util.Set; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.util.IpNetwork; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.PacketContext; -import org.opendaylight.vtn.manager.internal.util.MiscUtils; import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetDscpAction; import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetDstAction; import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetSrcAction; @@ -26,8 +25,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNInet4Match; import org.opendaylight.vtn.manager.internal.util.packet.InetHeader; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; -import org.opendaylight.controller.sal.packet.IPv4; - /** * {@code Inet4Packet} class implements a cache for an {@link IPv4} instance. */ @@ -196,11 +193,10 @@ public final class Inet4Packet implements CachedPacket, InetHeader { */ private void fill(IPv4 ipv4) { if (sourceAddress == null) { - sourceAddress = new Ip4Network(ipv4.getSourceAddress()); + sourceAddress = ipv4.getSourceAddress(); } if (destinationAddress == null) { - destinationAddress = - new Ip4Network(ipv4.getDestinationAddress()); + destinationAddress = ipv4.getDestinationAddress(); } if (dscp == DSCP_NONE) { dscp = ipv4.getDiffServ(); @@ -337,13 +333,11 @@ public final class Inet4Packet implements CachedPacket, InetHeader { * Return an {@link IPv4} instance to set modified values. * * @return An {@link IPv4} instance. - * @throws VTNException - * Failed to copy the packet. */ - private IPv4 getPacketForWrite() throws VTNException { + private IPv4 getPacketForWrite() { if (cloned) { // Create a copy of the original packet. - packet = MiscUtils.copy(packet, new IPv4()); + packet = packet.clone(); cloned = false; } @@ -383,9 +377,8 @@ public final class Inet4Packet implements CachedPacket, InetHeader { Ip4Network newIp = modifiedValues.getSourceAddress(); if (oldIp.getAddress() != newIp.getAddress()) { // Source address was modified. - InetAddress iaddr = newIp.getInetAddress(); ipv4 = getPacketForWrite(); - ipv4.setSourceAddress(iaddr); + ipv4.setSourceAddress(newIp); mod = true; } else if (pctx.hasMatchField(FlowMatchType.IP_SRC)) { // Source IP address in the original packet is unchanged and @@ -398,11 +391,10 @@ public final class Inet4Packet implements CachedPacket, InetHeader { newIp = modifiedValues.getDestinationAddress(); if (oldIp.getAddress() != newIp.getAddress()) { // Destination address was modified. - InetAddress iaddr = newIp.getInetAddress(); if (ipv4 == null) { ipv4 = getPacketForWrite(); } - ipv4.setDestinationAddress(iaddr); + ipv4.setDestinationAddress(newIp); mod = true; } else if (pctx.hasMatchField(FlowMatchType.IP_DST)) { // Destination IP address in the original packet is unchanged @@ -463,7 +455,7 @@ public final class Inet4Packet implements CachedPacket, InetHeader { Values v = getValues(); Ip4Network ipn = v.getSourceAddress(); if (ipn == null) { - ipn = new Ip4Network(packet.getSourceAddress()); + ipn = packet.getSourceAddress(); v.setSourceAddress(ipn); } @@ -496,7 +488,7 @@ public final class Inet4Packet implements CachedPacket, InetHeader { Values v = getValues(); Ip4Network ipn = v.getDestinationAddress(); if (ipn == null) { - ipn = new Ip4Network(packet.getDestinationAddress()); + ipn = packet.getDestinationAddress(); v.setDestinationAddress(ipn); } diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/L4Packet.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/L4Packet.java index 4515ce6e..5a1c0535 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/L4Packet.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/L4Packet.java @@ -39,15 +39,14 @@ public interface L4Packet extends CachedPacket, Layer4Header { /** * Calculate the checksum of the packet, and set the computed checksum - * into a {@link org.opendaylight.controller.sal.packet.Packet} instance + * into a {@link org.opendaylight.vtn.manager.packet.Packet} instance * configured in this instance. * * @param ipv4 An {@link Inet4Packet} instance that contains this * packet. * @return {@code true} is returned if the checksum field was updated. * {@code false} is returned if the packet was not modified. - * @throws VTNException - * An error occurred. + * @throws VTNException An error occurred. */ boolean updateChecksum(Inet4Packet ipv4) throws VTNException; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/PortProtoPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/PortProtoPacket.java index 9d34bd45..97ff379f 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/PortProtoPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/PortProtoPacket.java @@ -8,9 +8,14 @@ package org.opendaylight.vtn.manager.internal.packet.cache; +import static org.opendaylight.vtn.manager.packet.IPv4.CKSUM_BYTES; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_BYTE; +import static org.opendaylight.vtn.manager.util.NumberUtils.MASK_SHORT; + import java.util.Set; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -22,8 +27,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNPortRange; import org.opendaylight.vtn.manager.internal.util.packet.Layer4PortHeader; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; -import org.opendaylight.controller.sal.packet.Packet; - /** * {@code PortProtoPacket} class implements a cache for layer 4 protocol * header, which identifies the service using 16-bit port number. @@ -42,11 +45,6 @@ public abstract class PortProtoPacket */ private static final int CKSUM_OK = 0xffff; - /** - * The number of octets in TCP/UDP checksum. - */ - private static final int CKSUM_BYTES = Short.SIZE / Byte.SIZE; - /** * A mask value used to clear LSB. */ @@ -199,25 +197,25 @@ public abstract class PortProtoPacket byte[] header = ipv4.getHeaderForChecksum(proto, (short)data.length); int sum = 0; for (int i = 0; i < header.length; i += CKSUM_BYTES) { - int v = ((header[i] & NumberUtils.MASK_BYTE) << Byte.SIZE) | - (header[i + 1] & NumberUtils.MASK_BYTE); + int v = ((header[i] & MASK_BYTE) << Byte.SIZE) | + (header[i + 1] & MASK_BYTE); sum += v; } int rsize = (data.length & MASK_CLEAR_LSB); for (int i = 0; i < rsize; i += CKSUM_BYTES) { - int v = ((data[i] & NumberUtils.MASK_BYTE) << Byte.SIZE) | - (data[i + 1] & NumberUtils.MASK_BYTE); + int v = ((data[i] & MASK_BYTE) << Byte.SIZE) | + (data[i + 1] & MASK_BYTE); sum += v; } if (rsize < data.length) { // Zero padding is needed. - int v = (data[rsize] & NumberUtils.MASK_BYTE) << Byte.SIZE; + int v = (data[rsize] & MASK_BYTE) << Byte.SIZE; sum += v; } int carry = (sum >>> Short.SIZE); - return (sum & NumberUtils.MASK_SHORT) + carry; + return (sum & MASK_SHORT) + carry; } /** @@ -287,10 +285,8 @@ public abstract class PortProtoPacket * Return a {@link Packet} instance to set modified values. * * @return A {@link Packet} instance. - * @throws VTNException - * Failed to copy the packet. */ - protected final T getPacketForWrite() throws VTNException { + protected final T getPacketForWrite() { T pkt = getPacketForWrite(cloned); cloned = false; return pkt; @@ -333,10 +329,8 @@ public abstract class PortProtoPacket * @param doCopy {@code true} is passed if the packet configured in this * instance needs to be copied. * @return A {@link Packet} instance. - * @throws VTNException - * Failed to copy the packet. */ - protected abstract T getPacketForWrite(boolean doCopy) throws VTNException; + protected abstract T getPacketForWrite(boolean doCopy); /** * Return the name of the protocol. diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacket.java index d13fa982..d85ddc8e 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacket.java @@ -9,15 +9,13 @@ package org.opendaylight.vtn.manager.internal.packet.cache; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.TCP; -import org.opendaylight.vtn.manager.internal.util.MiscUtils; import org.opendaylight.vtn.manager.internal.util.flow.match.FlowMatchType; import org.opendaylight.vtn.manager.internal.util.flow.match.VTNPortRange; import org.opendaylight.vtn.manager.internal.util.flow.match.VTNTcpMatch; import org.opendaylight.vtn.manager.internal.util.packet.TcpHeader; -import org.opendaylight.controller.sal.packet.TCP; - /** * {@code TcpPacket} class implements a cache for a {@link TCP} instance. */ @@ -93,14 +91,12 @@ public final class TcpPacket extends PortProtoPacket * @param doCopy {@code true} is passed if the packet configured in this * instance needs to be copied. * @return A {@link TCP} instance. - * @throws VTNException - * Failed to copy the packet. */ @Override - protected TCP getPacketForWrite(boolean doCopy) throws VTNException { + protected TCP getPacketForWrite(boolean doCopy) { TCP pkt; if (doCopy) { - pkt = MiscUtils.copy(packet, new TCP()); + pkt = packet.clone(); packet = pkt; } else { pkt = packet; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacket.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacket.java index 8454a2b9..47fa6ce7 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacket.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacket.java @@ -9,15 +9,13 @@ package org.opendaylight.vtn.manager.internal.packet.cache; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.UDP; -import org.opendaylight.vtn.manager.internal.util.MiscUtils; import org.opendaylight.vtn.manager.internal.util.flow.match.FlowMatchType; import org.opendaylight.vtn.manager.internal.util.flow.match.VTNPortRange; import org.opendaylight.vtn.manager.internal.util.flow.match.VTNUdpMatch; import org.opendaylight.vtn.manager.internal.util.packet.UdpHeader; -import org.opendaylight.controller.sal.packet.UDP; - /** * {@code UdpPacket} class implements a cache for a {@link UDP} instance. */ @@ -96,14 +94,12 @@ public final class UdpPacket extends PortProtoPacket * @param doCopy {@code true} is passed if the packet configured in this * instance needs to be copied. * @return A {@link UDP} instance. - * @throws VTNException - * Failed to copy the packet. */ @Override - protected UDP getPacketForWrite(boolean doCopy) throws VTNException { + protected UDP getPacketForWrite(boolean doCopy) { UDP pkt; if (doCopy) { - pkt = MiscUtils.copy(packet, new UDP()); + pkt = packet.clone(); packet = pkt; } else { pkt = packet; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/provider/VTNManagerProviderImpl.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/provider/VTNManagerProviderImpl.java index 702715d3..1d8229db 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/provider/VTNManagerProviderImpl.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/provider/VTNManagerProviderImpl.java @@ -26,6 +26,7 @@ import org.osgi.framework.FrameworkUtil; import org.osgi.framework.Version; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.internal.FlowRemover; import org.opendaylight.vtn.manager.internal.RouteResolver; @@ -61,8 +62,6 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.NotificationProviderService; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.binding.RpcService; import org.opendaylight.yangtools.yang.common.RpcResult; diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/MiscUtils.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/MiscUtils.java index ad0ff6f5..9321a9d2 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/MiscUtils.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/MiscUtils.java @@ -24,14 +24,12 @@ import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; import org.opendaylight.controller.sal.core.UpdateType; -import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnUpdateType; @@ -182,28 +180,6 @@ public final class MiscUtils { throw new IllegalStateException(builder.toString()); } - /** - * Copy the contents of the given packet. - * - * @param src The source {@link Packet} instance. - * @param dst The destination {@link Packet} instance. - * @param Type of packet. - * @return {@code dst}. - * @throws VTNException - * Failed to copy the packet. - */ - public static T copy(T src, T dst) throws VTNException { - try { - byte[] raw = src.serialize(); - int nbits = raw.length * Byte.SIZE; - dst.deserialize(raw, 0, nbits); - return dst; - } catch (Exception e) { - // This should never happen. - throw new VTNException("Failed to copy the packet.", e); - } - } - /** * Ensure that the given value is not null. * diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilder.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilder.java index 9c09c819..f8ef3137 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilder.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilder.java @@ -11,15 +11,14 @@ package org.opendaylight.vtn.manager.internal.util.packet; import java.net.Inet4Address; import java.net.InetAddress; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.util.Ip4Network; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.Packet; - /** * {@code ArpPacketBuilder} is a utility to build an ARP packet. */ diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/TestBase.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/TestBase.java index 2da0ae5a..c52bb63e 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/TestBase.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/TestBase.java @@ -59,8 +59,14 @@ import org.opendaylight.vtn.manager.flow.action.FlowAction; import org.opendaylight.vtn.manager.flow.action.SetTpSrcAction; import org.opendaylight.vtn.manager.flow.filter.FlowFilter; import org.opendaylight.vtn.manager.flow.filter.PassFilter; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.IPv4; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; +import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.cluster.MacMapPath; @@ -79,12 +85,6 @@ import org.opendaylight.controller.sal.core.Edge; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.Packet; -import org.opendaylight.controller.sal.packet.RawPacket; import org.opendaylight.controller.sal.packet.address.EthernetAddress; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.core.UpdateType; @@ -1120,6 +1120,21 @@ public abstract class TestBase extends Assert { */ protected static IPv4 createIPv4(InetAddress src, InetAddress dst, short proto, byte dscp) { + return createIPv4(new Ip4Network(src), new Ip4Network(dst), + proto, dscp); + } + + /** + * Create an {@link IPv4} instance. + * + * @param src Source IP address. + * @param dst Destination IP address. + * @param proto IP protocol number. + * @param dscp DSCP field value. + * @return An {@link IPv4} instance. + */ + protected static IPv4 createIPv4(Ip4Network src, Ip4Network dst, + short proto, byte dscp) { IPv4 pkt = new IPv4(); return pkt.setSourceAddress(src).setDestinationAddress(dst). setProtocol((byte)proto).setDiffServ(dscp). @@ -1195,24 +1210,6 @@ public abstract class TestBase extends Assert { return createIPv4(src, dst, proto, (byte)0, payload); } - /** - * create a {@link RawPacket} object. - * - * @param eth A {@link Ethernet} object. - * @param nc A incoming node connector. - * @return A {@link RawPacket} object. - */ - protected RawPacket createRawPacket(Ethernet eth, NodeConnector nc) { - RawPacket raw = null; - try { - raw = new RawPacket(eth.serialize()); - } catch (Exception e) { - unexpected(e); - } - raw.setIncomingNodeConnector(copy(nc)); - - return raw; - } /** * create a {@link Ethernet} object of IPv4 Packet. @@ -1237,8 +1234,8 @@ public abstract class TestBase extends Assert { setFragmentOffset((short)0). setTtl((byte)64); - ip.setDestinationAddress(createInetAddress(target)); - ip.setSourceAddress(createInetAddress(sender)); + ip.setDestinationAddress(new Ip4Network(target)); + ip.setSourceAddress(new Ip4Network(sender)); Ethernet eth = new Ethernet(); eth.setSourceMACAddress(src).setDestinationMACAddress(dst); @@ -1248,7 +1245,7 @@ public abstract class TestBase extends Assert { IEEE8021Q vlantag = new IEEE8021Q(); vlantag.setCfi((byte)0x0).setPcp((byte)0x0).setVid((short)vlan). - setEtherType(EtherTypes.IPV4.shortValue()).setParent(eth); + setEtherType(EtherTypes.IPV4.shortValue()); eth.setPayload(vlantag); vlantag.setPayload(ip); @@ -1288,8 +1285,8 @@ public abstract class TestBase extends Assert { eth.setEtherType(EtherTypes.VLAN.shortValue()); IEEE8021Q vlantag = new IEEE8021Q(); - vlantag.setCfi((byte)0x0).setPcp((byte)0x0).setVid(vlan) - .setEtherType(EtherTypes.ARP.shortValue()).setParent(eth); + vlantag.setCfi((byte)0x0).setPcp((byte)0x0).setVid(vlan). + setEtherType(EtherTypes.ARP.shortValue()); eth.setPayload(vlantag); vlantag.setPayload(arp); @@ -1336,42 +1333,6 @@ public abstract class TestBase extends Assert { createIPv4Packet(src, dst, sender, target, vlan), nc); } - /** - * create a {@link RawPacket} object of ARP Request. - * - * @param src A source MAC address - * @param dst A destination MAC address - * @param sender A sender address - * @param target A target address - * @param vlan specify val ID. if vlan < 0, vlan tag is not added. - * @param nc A node connector - * @param arptype ARP.REQUEST or ARP.REPLY. (ARP Reply is not implemented yet ) - * @return A {@link PacketContext} object. - */ - protected RawPacket createARPRawPacket(byte[] src, byte[] dst, - byte[] sender, byte[] target, short vlan, NodeConnector nc, - short arptype) { - return createRawPacket( - createARPPacket(src, dst, sender, target, vlan, arptype), nc); - } - - /** - * create a {@link RawPacket} object of IPv4 packet. - * - * @param src A source MAC address - * @param dst A destination MAC address - * @param sender A sender address - * @param target A target address - * @param vlan specify vlan ID. if vlan < 0, vlan tag is not added. - * @param nc A node connector - * @return A {@link PacketContext} object. - */ - protected RawPacket createIPv4RawPacket(byte[] src, byte[] dst, - byte[] sender, byte[] target, short vlan, NodeConnector nc) { - return createRawPacket( - createIPv4Packet(src, dst, sender, target, vlan), nc); - } - /** * Create a {@link EthernetHost} instance which represents the * specified MAC address and VLAN ID. diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlDstActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlDstActionImplTest.java index a5ec09cd..577eeef4 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlDstActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlDstActionImplTest.java @@ -19,6 +19,7 @@ import org.junit.Test; import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.util.ByteUtils; import org.opendaylight.vtn.manager.util.EtherAddress; @@ -30,7 +31,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetDlDstAction; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.address.EthernetAddress; import org.opendaylight.controller.sal.utils.StatusCode; diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlSrcActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlSrcActionImplTest.java index c7c86e94..3b817b8c 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlSrcActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDlSrcActionImplTest.java @@ -19,6 +19,7 @@ import org.junit.Test; import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.util.ByteUtils; import org.opendaylight.vtn.manager.util.EtherAddress; @@ -30,7 +31,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetDlSrcAction; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.address.EthernetAddress; import org.opendaylight.controller.sal.utils.StatusCode; diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDscpActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDscpActionImplTest.java index 17e75b66..6fdae916 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDscpActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetDscpActionImplTest.java @@ -16,6 +16,7 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetDscpAction; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -25,7 +26,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetDscpActi import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.IPv4; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpCodeActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpCodeActionImplTest.java index 9c26ad32..858b8cfe 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpCodeActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpCodeActionImplTest.java @@ -16,6 +16,9 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetIcmpCodeAction; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.TCP; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.internal.PacketContext; import org.opendaylight.vtn.manager.internal.packet.cache.IcmpPacket; @@ -26,9 +29,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetIcmpCodeActi import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpTypeActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpTypeActionImplTest.java index 9a67338b..2c71e836 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpTypeActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetIcmpTypeActionImplTest.java @@ -16,6 +16,9 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetIcmpTypeAction; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.TCP; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.internal.PacketContext; import org.opendaylight.vtn.manager.internal.packet.cache.IcmpPacket; @@ -26,9 +29,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetIcmpTypeActi import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4DstActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4DstActionImplTest.java index f3115520..368f3493 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4DstActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4DstActionImplTest.java @@ -20,6 +20,7 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetInet4DstAction; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.util.IpNetwork; @@ -30,7 +31,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetDstActio import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.IPv4; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4SrcActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4SrcActionImplTest.java index 92ecfe2f..25c29553 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4SrcActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetInet4SrcActionImplTest.java @@ -20,6 +20,7 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetInet4SrcAction; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.util.IpNetwork; @@ -30,7 +31,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetInetSrcActio import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.IPv4; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpDstActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpDstActionImplTest.java index dfc29c9f..cb96450b 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpDstActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpDstActionImplTest.java @@ -16,6 +16,9 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetTpDstAction; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.TCP; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.internal.PacketContext; import org.opendaylight.vtn.manager.internal.packet.cache.IcmpPacket; @@ -26,9 +29,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetPortDstActio import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpSrcActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpSrcActionImplTest.java index dcb9274b..f137db4e 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpSrcActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetTpSrcActionImplTest.java @@ -16,6 +16,9 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetTpSrcAction; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.TCP; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.internal.PacketContext; import org.opendaylight.vtn.manager.internal.packet.cache.IcmpPacket; @@ -26,9 +29,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetPortSrcActio import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetVlanPcpActionImplTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetVlanPcpActionImplTest.java index e6286708..af692304 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetVlanPcpActionImplTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/cluster/SetVlanPcpActionImplTest.java @@ -16,6 +16,7 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.flow.action.SetVlanPcpAction; +import org.opendaylight.vtn.manager.packet.Ethernet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -24,7 +25,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.action.VTNSetVlanPcpActio import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.utils.StatusCode; /** diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacketTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacketTest.java index 730111b5..492d210e 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacketTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/EtherPacketTest.java @@ -17,6 +17,10 @@ import java.util.Set; import org.junit.Test; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; @@ -33,10 +37,6 @@ import org.opendaylight.vtn.manager.internal.TestBase; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.NodeCreator; diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacketTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacketTest.java index b59cc5db..057757fe 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacketTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/IcmpPacketTest.java @@ -17,6 +17,9 @@ import java.util.Set; import org.junit.Test; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.internal.PacketContext; @@ -28,10 +31,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNIcmpMatch; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.IPv4; - /** * JUnit test for {@link IcmpPacket}. */ diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4PacketTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4PacketTest.java index 254364ae..8c02a698 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4PacketTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/Inet4PacketTest.java @@ -18,6 +18,8 @@ import java.util.Set; import org.junit.Test; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IPv4; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.util.NumberUtils; @@ -31,9 +33,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNInet4Match; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IPv4; - /** * JUnit test for {@link Inet4Packet}. */ @@ -185,8 +184,8 @@ public class Inet4PacketTest extends TestBase { assertEquals(true, ip.commit(pctx)); IPv4 newPkt = ip.getPacket(); assertNotSame(pkt, newPkt); - assertEquals(src.getAddress(), newPkt.getSourceAddress()); - assertEquals(dst.getAddress(), newPkt.getDestinationAddress()); + assertEquals(src, newPkt.getSourceAddress()); + assertEquals(dst, newPkt.getDestinationAddress()); assertEquals((byte)proto, newPkt.getProtocol()); assertEquals((byte)dscp, newPkt.getDiffServ()); @@ -228,8 +227,8 @@ public class Inet4PacketTest extends TestBase { assertEquals(dscp0, ipv4.getDscp()); assertSame(pkt, ipv4.getPacket()); - assertEquals(src0.getAddress(), pkt.getSourceAddress()); - assertEquals(dst0.getAddress(), pkt.getDestinationAddress()); + assertEquals(src0, pkt.getSourceAddress()); + assertEquals(dst0, pkt.getDestinationAddress()); assertEquals((byte)proto, pkt.getProtocol()); assertEquals((byte)dscp0, pkt.getDiffServ()); diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacketTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacketTest.java index bf95219a..ee9fe0ed 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacketTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/TcpPacketTest.java @@ -19,6 +19,11 @@ import java.util.Set; import org.junit.Test; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IPv4; +import org.opendaylight.vtn.manager.packet.Packet; +import org.opendaylight.vtn.manager.packet.PacketException; +import org.opendaylight.vtn.manager.packet.TCP; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.util.Ip4Network; @@ -32,11 +37,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNTcpMatch; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.PacketException; -import org.opendaylight.controller.sal.packet.TCP; - /** * JUnit test for {@link TcpPacket}. */ @@ -295,11 +295,17 @@ public class TcpPacketTest extends TestBase { */ @Test public void testUpdateChecksum() throws Exception { + // Create a broken TCP packet. + TCP pkt = new TCP(); + Map header = getFieldValue( + pkt, Packet.class, Map.class, "hdrFieldsMap"); + header.put("WindowSize", new byte[]{0}); + // Ensure that an exception is wrapped by a VTNException. IPv4 ipv4 = new IPv4(); Inet4Packet inet4 = new Inet4Packet(ipv4); - TCP pkt = new TCP(); TcpPacket tcp = new TcpPacket(pkt); + try { tcp.updateChecksum(inet4); unexpected(); diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacketTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacketTest.java index 5979e6de..a6b99568 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacketTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/packet/cache/UdpPacketTest.java @@ -19,6 +19,11 @@ import java.util.Set; import org.junit.Test; import org.opendaylight.vtn.manager.VTNException; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IPv4; +import org.opendaylight.vtn.manager.packet.Packet; +import org.opendaylight.vtn.manager.packet.PacketException; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.util.Ip4Network; @@ -32,11 +37,6 @@ import org.opendaylight.vtn.manager.internal.util.flow.match.VTNUdpMatch; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.PacketException; -import org.opendaylight.controller.sal.packet.UDP; - /** * JUnit test for {@link UdpPacket}. */ @@ -260,11 +260,16 @@ public class UdpPacketTest extends TestBase { */ @Test public void testUpdateChecksum() throws Exception { + // Create a broken UDP packet. + UDP pkt = new UDP(); + Map header = getFieldValue( + pkt, Packet.class, Map.class, "hdrFieldsMap"); + header.put("Length", new byte[]{0}); + pkt.setChecksum((short)1); + // Ensure that an exception is wrapped by a VTNException. IPv4 ipv4 = new IPv4(); Inet4Packet inet4 = new Inet4Packet(ipv4); - UDP pkt = new UDP(); - pkt.setHeaderField("Checksum", new byte[]{1}); UdpPacket udp = new UdpPacket(pkt); try { udp.updateChecksum(inet4); diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/MiscUtilsTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/MiscUtilsTest.java index f2d7db3e..bd201956 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/MiscUtilsTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/MiscUtilsTest.java @@ -30,8 +30,6 @@ import org.mockito.Mockito; import org.opendaylight.vtn.manager.VTNException; import org.opendaylight.vtn.manager.util.EtherAddress; -import org.opendaylight.vtn.manager.util.EtherTypes; -import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.util.NumberUtils; import org.opendaylight.vtn.manager.internal.util.rpc.RpcErrorTag; @@ -39,15 +37,6 @@ import org.opendaylight.vtn.manager.internal.util.rpc.RpcException; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.Packet; -import org.opendaylight.controller.sal.packet.TCP; -import org.opendaylight.controller.sal.packet.UDP; - import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VnodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnErrorTag; @@ -235,274 +224,6 @@ public class MiscUtilsTest extends TestBase { } } - /** - * Test case for {@link MiscUtils#copy(Packet, Packet)}. - * - * @throws Exception An error occurred. - */ - @Test - public void testCopyPacket() throws Exception { - // Specifying null. - try { - MiscUtils.copy((Packet)null, (Packet)null); - unexpected(); - } catch (VTNException e) { - checkException(e, "Failed to copy the packet.", - VtnErrorTag.INTERNALERROR); - assertTrue(e.getCause() instanceof NullPointerException); - } - - byte[] raw = { - (byte)0x7c, (byte)0xe8, (byte)0x07, (byte)0xde, - (byte)0xc5, (byte)0x1b, (byte)0x40, (byte)0x86, - (byte)0xc0, (byte)0xa1, (byte)0xe3, (byte)0xe0, - (byte)0x90, (byte)0xdd, (byte)0x0c, (byte)0xe6, - }; - - // Ensure that Ethernet instance with raw payload can be copied. - byte[] srcMac = { - (byte)0x00, (byte)0x11, (byte)0x22, - (byte)0x33, (byte)0x44, (byte)0x55, - }; - byte[] dstMac = { - (byte)0xf0, (byte)0xfa, (byte)0xfb, - (byte)0xfc, (byte)0xfd, (byte)0xfe, - }; - short etype = 0xa00; - short vid = MatchType.DL_VLAN_NONE; - byte pcp = 1; - for (int loop = 0; loop < 5; loop++) { - Ethernet org = createEthernet(srcMac, dstMac, etype, vid, pcp, raw); - Ethernet copy = new Ethernet(); - assertSame(copy, MiscUtils.copy(org, copy)); - checkCopy(org, copy, srcMac, dstMac, etype, vid, pcp, raw); - etype++; - vid++; - srcMac[3]++; - dstMac[4]++; - } - - // Ensure that IPv4 instance with raw payload can be copied. - int srcIp = (int)0x0a010203; - int dstIp = (int)0xc0a864c8; - short ipproto = 30; - byte dscp = 0; - for (int loop = 0; loop < 5; loop++) { - IPv4 org = createIPv4(srcIp, dstIp, ipproto, dscp); - org.setRawPayload(raw); - - // Copy the original in order to fix up header fields, such as - // checksum. - org = MiscUtils.copy(org, new IPv4()); - - IPv4 copy = new IPv4(); - assertSame(copy, MiscUtils.copy(org, copy)); - checkCopy(org, copy, srcIp, dstIp, ipproto, dscp, raw); - srcIp++; - dstIp++; - ipproto++; - dscp++; - } - - // Ensure that TCP instance with raw payload can be copied. - int seq = 0x3333; - int ack = 0x4567; - byte dataOff = 0; - byte resv = 0; - short win = (short)0xfc00; - short urp = (short)0x5678; - short cksum = (short)0x1234; - short flags = 0x18; - short srcPort = 17; - short dstPort = 30000; - for (int loop = 0; loop < 5; loop++) { - TCP org = new TCP(); - org.setSourcePort(srcPort).setDestinationPort(dstPort). - setSequenceNumber(seq).setAckNumber(ack). - setDataOffset(dataOff).setHeaderLenFlags(flags). - setReserved(resv).setWindowSize(win).setChecksum(cksum). - setUrgentPointer(urp).setRawPayload(raw); - TCP copy = new TCP(); - assertSame(copy, MiscUtils.copy(org, copy)); - checkCopy(org, copy, srcPort, dstPort, cksum, raw); - - seq++; - ack++; - dataOff = (byte)((dataOff + 1) & 0xf); - cksum += 7; - srcPort++; - dstPort++; - } - - // Ensure that UDP instance with raw payload can be copied. - srcPort = (short)45678; - dstPort = 133; - cksum = (short)0xf1a0; - short udpLen = (short)(raw.length + 8); - for (int loop = 0; loop < 5; loop++) { - UDP org = new UDP(); - org.setSourcePort(srcPort).setDestinationPort(dstPort). - setLength(udpLen).setChecksum(cksum).setRawPayload(raw); - UDP copy = new UDP(); - assertSame(copy, MiscUtils.copy(org, copy)); - checkCopy(org, copy, srcPort, dstPort, cksum, raw); - - srcPort++; - dstPort++; - cksum++; - } - - // Ensure that ICMP instance with raw payload can be copied. - short icmpSeq = 0x13a9; - short icmpId = 0x7c; - byte icmpType = 0; - byte icmpCode = 6; - for (int loop = 0; loop < 5; loop++) { - ICMP org = new ICMP(); - org.setType(icmpType).setCode(icmpCode).setIdentifier(icmpId). - setSequenceNumber(icmpSeq).setRawPayload(raw); - - // Copy the original in order to fix up header fields, such as - // checksum. - org = MiscUtils.copy(org, new ICMP()); - - ICMP copy = new ICMP(); - assertSame(copy, MiscUtils.copy(org, copy)); - checkCopy(org, copy, icmpType, icmpCode, icmpId, icmpSeq, raw); - - icmpSeq++; - icmpId++; - icmpType++; - icmpCode++; - } - - // Ensure that nested Etherner frame can be copied. - InetProtocols[] protos = { - InetProtocols.TCP, - InetProtocols.UDP, - InetProtocols.ICMP, - }; - int protoIndex = 0; - vid = MatchType.DL_VLAN_NONE; - etype = EtherTypes.IPV4.shortValue(); - pcp = 0; - dscp = 0; - srcPort = 128; - dstPort = 12345; - cksum = (short)0xed03; - for (int loop = 0; loop < protos.length * 5; loop++) { - InetProtocols proto = protos[protoIndex]; - protoIndex++; - if (protoIndex >= protos.length) { - protoIndex = 0; - } - - Packet l4 = null; - switch (proto) { - case TCP: - l4 = new TCP().setSourcePort(srcPort). - setDestinationPort(dstPort).setSequenceNumber(seq). - setAckNumber(ack).setDataOffset(dataOff). - setHeaderLenFlags(flags).setReserved(resv). - setWindowSize(win).setChecksum(cksum). - setUrgentPointer(urp); - break; - - case UDP: - l4 = new UDP().setSourcePort(srcPort). - setDestinationPort(dstPort).setLength(udpLen). - setChecksum(cksum); - break; - - case ICMP: - l4 = new ICMP().setType(icmpType).setCode(icmpCode). - setIdentifier(icmpId).setSequenceNumber(icmpSeq); - break; - - default: - unexpected(); - break; - } - - l4.setRawPayload(raw); - - ipproto = proto.byteValue(); - IPv4 ipv4 = createIPv4(srcIp, dstIp, ipproto, dscp); - ipv4.setPayload(l4); - Ethernet ether = createEthernet(srcMac, dstMac, etype, vid, pcp, - ipv4); - - // Copy the original in order to fix up header fields, such as - // IP checksum. - ether = MiscUtils.copy(ether, new Ethernet()); - - Ethernet copy = new Ethernet(); - assertSame(copy, MiscUtils.copy(ether, copy)); - checkCopy(ether, copy, srcMac, dstMac, etype, vid, pcp, null); - - IPv4 ipCopy; - if (vid == MatchType.DL_VLAN_NONE) { - ipv4 = (IPv4)ether.getPayload(); - ipCopy = (IPv4)copy.getPayload(); - } else { - Packet pkt = ether.getPayload(); - ipv4 = (IPv4)pkt.getPayload(); - pkt = copy.getPayload(); - ipCopy = (IPv4)pkt.getPayload(); - } - vid = (short)((vid + 1) & 0xfff); - srcMac[5]++; - dstMac[2]++; - - // Check IPv4 packet. - checkCopy(ipv4, ipCopy, srcIp, dstIp, ipproto, dscp, null); - srcIp++; - dstIp++; - dscp = (byte)((dscp + 1) & 0x3f); - - switch (proto) { - case TCP: - // Check TCP packet. - TCP tcp = (TCP)ipv4.getPayload(); - TCP tcpCopy = (TCP)ipCopy.getPayload(); - checkCopy(tcp, tcpCopy, srcPort, dstPort, cksum, raw); - seq++; - ack++; - dataOff = (byte)((dataOff + 1) & 0xf); - cksum += 13; - srcPort++; - dstPort++; - break; - - case UDP: - // Check UDP packet. - UDP udp = (UDP)ipv4.getPayload(); - UDP udpCopy = (UDP)ipCopy.getPayload(); - checkCopy(udp, udpCopy, srcPort, dstPort, cksum, raw); - srcPort++; - dstPort++; - cksum += 23; - break; - - case ICMP: - // Check ICMP packet. - ICMP icmp = (ICMP)ipv4.getPayload(); - ICMP icmpCopy = (ICMP)ipCopy.getPayload(); - checkCopy(icmp, icmpCopy, icmpType, icmpCode, icmpId, icmpSeq, - raw); - icmpSeq++; - icmpId++; - icmpType++; - icmpCode++; - break; - - default: - unexpected(); - break; - } - } - } - /** * Test case for {@link MiscUtils#checkNotNull(Object, Logger, String)}. */ @@ -883,173 +604,4 @@ public class MiscUtilsTest extends TestBase { assertEquals(desc, e.getMessage()); assertEquals(vtag, e.getVtnErrorTag()); } - - /** - * Ensure that the raw payload of the packet was copied successfully. - * - * @param org Original{@link Packet} instance. - * @param copy A copy of {@code org}. - * @param raw Expected raw payload. - */ - private void checkRawPayloadCopy(Packet org, Packet copy, byte[] raw) { - byte[] rawPayload = copy.getRawPayload(); - byte[] orgPayload = org.getRawPayload(); - if (raw == null) { - assertEquals(null, rawPayload); - assertEquals(null, orgPayload); - } else { - assertEquals(null, org.getPayload()); - assertEquals(null, copy.getPayload()); - assertNotSame(raw, rawPayload); - assertNotSame(orgPayload, rawPayload); - assertArrayEquals(raw, rawPayload); - assertArrayEquals(raw, orgPayload); - } - } - - /** - * Ensure that an {@link Ethernet} instance was copied successfully. - * - * @param org Original {@link Ethernet} instance. - * @param copy A copy of {@code org}. - * @param src Expected source MAC address. - * @param dst Expected destination MAC address. - * @param etype Expected ethernet type. - * @param vid Expected VLAN ID. - * @param pcp Expected VLAN priority. - * @param raw Expected raw payload. - */ - private void checkCopy(Ethernet org, Ethernet copy, byte[] src, byte[] dst, - short etype, short vid, byte pcp, byte[] raw) { - assertNotSame(copy, org); - assertEquals(copy, org); - assertArrayEquals(src, org.getSourceMACAddress()); - assertArrayEquals(dst, org.getDestinationMACAddress()); - assertArrayEquals(src, copy.getSourceMACAddress()); - assertArrayEquals(dst, copy.getDestinationMACAddress()); - Packet parent; - Packet orgParent; - if (vid == MatchType.DL_VLAN_NONE) { - assertEquals(etype, org.getEtherType()); - assertEquals(etype, copy.getEtherType()); - parent = copy; - orgParent = org; - } else { - assertEquals(EtherTypes.VLAN.shortValue(), org.getEtherType()); - assertEquals(EtherTypes.VLAN.shortValue(), copy.getEtherType()); - IEEE8021Q orgTag = (IEEE8021Q)org.getPayload(); - IEEE8021Q vlanTag = (IEEE8021Q)copy.getPayload(); - assertNotNull(vlanTag); - assertNotSame(orgTag, vlanTag); - assertEquals(orgTag, vlanTag); - assertEquals(etype, orgTag.getEtherType()); - assertEquals(vid, orgTag.getVid()); - assertEquals(pcp, orgTag.getPcp()); - assertEquals((byte)0, orgTag.getCfi()); - assertEquals(etype, vlanTag.getEtherType()); - assertEquals(vid, vlanTag.getVid()); - assertEquals(pcp, vlanTag.getPcp()); - assertEquals((byte)0, vlanTag.getCfi()); - parent = vlanTag; - orgParent = orgTag; - } - - checkRawPayloadCopy(parent, orgParent, raw); - } - - /** - * Ensure that an {@link IPv4} instance was copied successfully. - * - * @param org Original {@link IPv4} instance. - * @param copy A copy of {@code org}. - * @param src Expected source IP address. - * @param dst Expected destination IP address. - * @param proto Expected IP protocol number. - * @param dscp Expected DSCP field value. - * @param raw Expected raw payload. - */ - private void checkCopy(IPv4 org, IPv4 copy, int src, int dst, short proto, - byte dscp, byte[] raw) { - assertNotSame(copy, org); - assertEquals(copy, org); - for (IPv4 ipv4: new IPv4[]{org, copy}) { - assertEquals(src, ipv4.getSourceAddress()); - assertEquals(dst, ipv4.getDestinationAddress()); - assertEquals((byte)proto, ipv4.getProtocol()); - assertEquals(dscp, ipv4.getDiffServ()); - } - - checkRawPayloadCopy(org, copy, raw); - } - - /** - * Ensure that an {@link TCP} instance was copied successfully. - * - * @param org Original {@link TCP} instance. - * @param copy A copy of {@code org}. - * @param src Expected source port number. - * @param dst Expected destination port number. - * @param cksum Expected TCP checksum. - * @param raw Expected raw payload. - */ - private void checkCopy(TCP org, TCP copy, short src, short dst, - short cksum, byte[] raw) { - assertNotSame(copy, org); - assertEquals(copy, org); - for (TCP tcp: new TCP[]{org, copy}) { - assertEquals(src, tcp.getSourcePort()); - assertEquals(dst, tcp.getDestinationPort()); - assertEquals(cksum, tcp.getChecksum()); - } - - checkRawPayloadCopy(org, copy, raw); - } - - /** - * Ensure that an {@link UDP} instance was copied successfully. - * - * @param org Original {@link UDP} instance. - * @param copy A copy of {@code org}. - * @param src Expected source port number. - * @param dst Expected destination port number. - * @param cksum Expected UDP checksum. - * @param raw Expected raw payload. - */ - private void checkCopy(UDP org, UDP copy, short src, short dst, - short cksum, byte[] raw) { - assertNotSame(copy, org); - assertEquals(copy, org); - for (UDP udp: new UDP[]{org, copy}) { - assertEquals(src, udp.getSourcePort()); - assertEquals(dst, udp.getDestinationPort()); - assertEquals(cksum, udp.getChecksum()); - } - - checkRawPayloadCopy(org, copy, raw); - } - - /** - * Ensure that an {@link ICMP} instance was copied successfully. - * - * @param org Original {@link UDP} instance. - * @param copy A copy of {@code org}. - * @param type Expected ICMP type. - * @param code Expected ICMP code. - * @param id Expected identifier. - * @param seq Expected sequence number. - * @param raw Expected raw payload. - */ - private void checkCopy(ICMP org, ICMP copy, byte type, byte code, - short id, short seq, byte[] raw) { - assertNotSame(copy, org); - assertEquals(copy, org); - for (ICMP icmp: new ICMP[]{org, copy}) { - assertEquals(type, icmp.getType()); - assertEquals(code, icmp.getCode()); - assertEquals(id, icmp.getIdentifier()); - assertEquals(seq, icmp.getSequenceNumber()); - } - - checkRawPayloadCopy(org, copy, raw); - } } diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilderTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilderTest.java index 0a152824..74abc125 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilderTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/util/packet/ArpPacketBuilderTest.java @@ -12,17 +12,16 @@ import java.net.InetAddress; import org.junit.Test; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.util.Ip4Network; import org.opendaylight.vtn.manager.internal.TestBase; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.Packet; - /** * JUnit test for {@link ArpPacketBuilder}. */ diff --git a/manager/it/core/src/test/java/org/opendaylight/vtn/manager/it/core/VTNManagerIT.java b/manager/it/core/src/test/java/org/opendaylight/vtn/manager/it/core/VTNManagerIT.java index 736b4f2c..9740b9a5 100644 --- a/manager/it/core/src/test/java/org/opendaylight/vtn/manager/it/core/VTNManagerIT.java +++ b/manager/it/core/src/test/java/org/opendaylight/vtn/manager/it/core/VTNManagerIT.java @@ -95,6 +95,7 @@ import org.opendaylight.vtn.manager.flow.cond.UdpMatch; import org.opendaylight.vtn.manager.util.EtherAddress; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.util.InetProtocols; +import org.opendaylight.vtn.manager.util.IpNetwork; import org.opendaylight.vtn.manager.it.ofmock.OfMockFlow; import org.opendaylight.vtn.manager.it.ofmock.OfMockLink; @@ -3700,7 +3701,7 @@ public final class VTNManagerIT extends ModelDrivenTestBase { // Send ICMP packet from moved hosts. // This invalidates old MAC address table entries. - InetAddress dstIp = InetAddress.getByName("192.168.100.255"); + IpNetwork dstIp = IpNetwork.create("192.168.100.255"); for (Map.Entry entry: oldHosts0.entrySet()) { TestHost oldHost = entry.getKey(); TestHost newHost = entry.getValue(); @@ -3775,12 +3776,12 @@ public final class VTNManagerIT extends ModelDrivenTestBase { * A set of VLAN IDs mapped to the given vBridge must be * associated with the key. */ - private void sendBroadcastIcmp(TestHost host, InetAddress dstIp, + private void sendBroadcastIcmp(TestHost host, IpNetwork dstIp, Map> allPorts) throws Exception { String pid = host.getPortIdentifier(); byte[] src = host.getMacAddress(); - InetAddress srcIp = host.getInetAddress(); + IpNetwork srcIp = host.getInetAddress(); short vlan = host.getVlan(); byte type = 8; byte code = 0; diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/TestHost.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/TestHost.java index 37e9f719..5486dcd4 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/TestHost.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/TestHost.java @@ -15,6 +15,8 @@ import java.util.Set; import org.opendaylight.vtn.manager.EthernetHost; import org.opendaylight.vtn.manager.MacAddressEntry; +import org.opendaylight.vtn.manager.util.Ip4Network; +import org.opendaylight.vtn.manager.util.IpNetwork; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.packet.address.EthernetAddress; @@ -46,7 +48,7 @@ public final class TestHost { /** * IP address. */ - private final InetAddress inetAddress; + private final IpNetwork inetAddress; /** * MD-SAL node connector identifier which specifies the switch port @@ -74,7 +76,7 @@ public final class TestHost { byte[] addr = IPV4_ADDRESS_BASE.clone(); addr[addr.length - 1] = (byte)index; - inetAddress = InetAddress.getByAddress(addr); + inetAddress = new Ip4Network(addr); portIdentifier = pid; vlan = vid; } @@ -114,9 +116,9 @@ public final class TestHost { /** * Return IP address of this host. * - * @return An {@link InetAddress} instance. + * @return An {@link IpNetwork} instance. */ - public InetAddress getInetAddress() { + public IpNetwork getInetAddress() { return inetAddress; } @@ -126,7 +128,7 @@ public final class TestHost { * @return A byte array which represents the IP address of this host. */ public byte[] getRawInetAddress() { - return inetAddress.getAddress(); + return inetAddress.getBytes(); } /** @@ -176,7 +178,7 @@ public final class TestHost { public MacAddressEntry getMacAddressEntry(boolean useIp) { NodeConnector nc = TestBase.toAdNodeConnector(portIdentifier); Set ipaddrs = (useIp) - ? Collections.singleton(inetAddress) + ? Collections.singleton(inetAddress.getInetAddress()) : null; return new MacAddressEntry(macAddress, vlan, nc, ipaddrs); } diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4DstVerifier.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4DstVerifier.java index abbab246..e2c2942f 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4DstVerifier.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4DstVerifier.java @@ -9,23 +9,19 @@ package org.opendaylight.vtn.manager.it.util.action; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.net.Inet4Address; -import java.net.InetAddress; import java.util.ListIterator; +import org.opendaylight.vtn.manager.util.Ip4Network; +import org.opendaylight.vtn.manager.util.IpNetwork; + import org.opendaylight.vtn.manager.it.util.packet.EthernetFactory; import org.opendaylight.vtn.manager.it.util.packet.Inet4Factory; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwDstActionCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4; - -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; /** * {@code SetDscpVerifier} is a utility class used to verify a SET_NW_DST @@ -35,7 +31,7 @@ public final class SetInet4DstVerifier extends ActionVerifier { /** * The destination IP address to be set. */ - private final InetAddress address; + private final IpNetwork address; /** * Ensure that the specified action is an expected SET_NW_DST action. @@ -43,15 +39,10 @@ public final class SetInet4DstVerifier extends ActionVerifier { * @param it Action list iterator. * @param ip Expected destination IP address. */ - public static void verify(ListIterator it, InetAddress ip) { + public static void verify(ListIterator it, IpNetwork ip) { SetNwDstActionCase act = verify(it, SetNwDstActionCase.class); SetNwDstAction snda = act.getSetNwDstAction(); - Address addr = snda.getAddress(); - assertTrue(addr instanceof Ipv4); - Ipv4 v4 = (Ipv4)addr; - Ipv4Prefix v4p = v4.getIpv4Address(); - assertNotNull(v4p); - assertEquals(ip.getHostAddress(), v4p.getValue()); + assertEquals(ip.getMdAddress(), snda.getAddress()); } /** @@ -59,8 +50,8 @@ public final class SetInet4DstVerifier extends ActionVerifier { * * @param ip The destination IP address to be set. */ - public SetInet4DstVerifier(InetAddress ip) { - assertTrue(ip instanceof Inet4Address); + public SetInet4DstVerifier(IpNetwork ip) { + assertTrue(ip instanceof Ip4Network); address = ip; } @@ -69,7 +60,7 @@ public final class SetInet4DstVerifier extends ActionVerifier { * * @return The destination IP address to be set. */ - public InetAddress getAddress() { + public IpNetwork getAddress() { return address; } diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4SrcVerifier.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4SrcVerifier.java index 74364b49..00a0e786 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4SrcVerifier.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/action/SetInet4SrcVerifier.java @@ -9,23 +9,19 @@ package org.opendaylight.vtn.manager.it.util.action; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.net.Inet4Address; -import java.net.InetAddress; import java.util.ListIterator; +import org.opendaylight.vtn.manager.util.Ip4Network; +import org.opendaylight.vtn.manager.util.IpNetwork; + import org.opendaylight.vtn.manager.it.util.packet.EthernetFactory; import org.opendaylight.vtn.manager.it.util.packet.Inet4Factory; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetNwSrcActionCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4; - -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; /** * {@code SetDscpVerifier} is a utility class used to verify a SET_NW_SRC @@ -35,7 +31,7 @@ public final class SetInet4SrcVerifier extends ActionVerifier { /** * The source IP address to be set. */ - private final InetAddress address; + private final IpNetwork address; /** * Ensure that the specified action is an expected SET_NW_SRC action. @@ -43,15 +39,10 @@ public final class SetInet4SrcVerifier extends ActionVerifier { * @param it Action list iterator. * @param ip Expected source IP address. */ - public static void verify(ListIterator it, InetAddress ip) { + public static void verify(ListIterator it, IpNetwork ip) { SetNwSrcActionCase act = verify(it, SetNwSrcActionCase.class); SetNwSrcAction snsa = act.getSetNwSrcAction(); - Address addr = snsa.getAddress(); - assertTrue(addr instanceof Ipv4); - Ipv4 v4 = (Ipv4)addr; - Ipv4Prefix v4p = v4.getIpv4Address(); - assertNotNull(v4p); - assertEquals(ip.getHostAddress(), v4p.getValue()); + assertEquals(ip.getMdAddress(), snsa.getAddress()); } /** @@ -59,8 +50,8 @@ public final class SetInet4SrcVerifier extends ActionVerifier { * * @param ip The source IP address to be set. */ - public SetInet4SrcVerifier(InetAddress ip) { - assertTrue(ip instanceof Inet4Address); + public SetInet4SrcVerifier(IpNetwork ip) { + assertTrue(ip instanceof Ip4Network); address = ip; } @@ -69,7 +60,7 @@ public final class SetInet4SrcVerifier extends ActionVerifier { * * @return The source IP address to be set. */ - public InetAddress getAddress() { + public IpNetwork getAddress() { return address; } diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/ArpFactory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/ArpFactory.java index 8ead1882..8e280260 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/ArpFactory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/ArpFactory.java @@ -14,12 +14,12 @@ import static org.junit.Assert.assertTrue; import java.util.Set; +import org.opendaylight.vtn.manager.packet.ARP; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherTypes; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.ARP; -import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.controller.sal.packet.address.EthernetAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/EthernetFactory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/EthernetFactory.java index d0baf499..cc55f9dc 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/EthernetFactory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/EthernetFactory.java @@ -13,22 +13,21 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.net.InetAddress; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import org.opendaylight.vtn.manager.packet.Ethernet; +import org.opendaylight.vtn.manager.packet.IEEE8021Q; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherTypes; +import org.opendaylight.vtn.manager.util.IpNetwork; import org.opendaylight.vtn.manager.it.ofmock.OfMockService; import org.opendaylight.vtn.manager.it.util.ModelDrivenTestBase; import org.opendaylight.vtn.manager.it.util.TestBase; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.Ethernet; -import org.opendaylight.controller.sal.packet.IEEE8021Q; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; @@ -66,7 +65,7 @@ public final class EthernetFactory extends PacketFactory { /** * IP address to be probed. */ - private InetAddress probeAddress; + private IpNetwork probeAddress; /** * VLAN ID used for IP address probe. @@ -139,9 +138,9 @@ public final class EthernetFactory extends PacketFactory { /** * Return an IP address to be probed. * - * @return An {@link InetAddress} instance or {@code null}. + * @return An {@link IpNetwork} instance or {@code null}. */ - public InetAddress getProbeAddress() { + public IpNetwork getProbeAddress() { return probeAddress; } @@ -212,11 +211,11 @@ public final class EthernetFactory extends PacketFactory { /** * Set a pair of IP address and VLAN ID for IP address probe. * - * @param ip An {@link InetAddress} instance. + * @param ip An {@link IpNetwork} instance. * @param vid VLAN ID used for IP address probe. * @return This instance. */ - public EthernetFactory setProbe(InetAddress ip, short vid) { + public EthernetFactory setProbe(IpNetwork ip, short vid) { probeAddress = ip; probeVlan = vid; return this; @@ -283,7 +282,7 @@ public final class EthernetFactory extends PacketFactory { afc.setSenderHardwareAddress(ctlrMac). setTargetHardwareAddress(sourceAddress). setSenderProtocolAddress(TestBase.IPV4_ZERO). - setTargetProtocolAddress(probeAddress.getAddress()); + setTargetProtocolAddress(probeAddress.getBytes()); return efc.verify(ofmock, bytes, vlanIds); } diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Icmp4Factory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Icmp4Factory.java index d83d7b32..557354ca 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Icmp4Factory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Icmp4Factory.java @@ -13,13 +13,12 @@ import static org.junit.Assert.assertTrue; import java.util.Set; +import org.opendaylight.vtn.manager.packet.ICMP; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.ICMP; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder; diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Inet4Factory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Inet4Factory.java index 0ae3ffd7..22cc836b 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Inet4Factory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/Inet4Factory.java @@ -11,20 +11,16 @@ package org.opendaylight.vtn.manager.it.util.packet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.opendaylight.vtn.manager.it.util.ModelDrivenTestBase.toIpv4Prefix; - -import java.net.Inet4Address; -import java.net.InetAddress; import java.util.Set; +import org.opendaylight.vtn.manager.packet.IPv4; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.EtherTypes; -import org.opendaylight.vtn.manager.util.NumberUtils; +import org.opendaylight.vtn.manager.util.Ip4Network; +import org.opendaylight.vtn.manager.util.IpNetwork; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; @@ -44,12 +40,12 @@ public final class Inet4Factory extends PacketFactory { /** * The source IP address. */ - private InetAddress sourceAddress; + private Ip4Network sourceAddress; /** * The target IP address. */ - private InetAddress destinationAddress; + private Ip4Network destinationAddress; /** * IP protocl number. @@ -88,7 +84,7 @@ public final class Inet4Factory extends PacketFactory { * @return An {@link Inet4Factory} instance. */ public static Inet4Factory newInstance(EthernetFactory efc, - InetAddress src, InetAddress dst) { + IpNetwork src, IpNetwork dst) { Inet4Factory i4fc = new Inet4Factory(src, dst); efc.setEtherType(EtherTypes.IPV4.shortValue()).setNextFactory(i4fc); @@ -106,7 +102,7 @@ public final class Inet4Factory extends PacketFactory { * @param src The source IP address. * @param dst The destination IP address. */ - Inet4Factory(InetAddress src, InetAddress dst) { + Inet4Factory(IpNetwork src, IpNetwork dst) { setSourceAddress(src); setDestinationAddress(dst); } @@ -114,18 +110,18 @@ public final class Inet4Factory extends PacketFactory { /** * Return the source IP address. * - * @return An {@link InetAddress} or {@code null}. + * @return An {@link Ip4Network} or {@code null}. */ - public InetAddress getSourceAddress() { + public Ip4Network getSourceAddress() { return sourceAddress; } /** * Return the destination IP address. * - * @return An {@link InetAddress} or {@code null}. + * @return An {@link Ip4Network} or {@code null}. */ - public InetAddress getDestinationAddress() { + public Ip4Network getDestinationAddress() { return destinationAddress; } @@ -159,28 +155,24 @@ public final class Inet4Factory extends PacketFactory { /** * Set the source IP address. * - * @param ip An {@link InetAddress}. + * @param ip An {@link IpNetwork}. * @return This instance. */ - public Inet4Factory setSourceAddress(InetAddress ip) { - if (ip != null) { - assertTrue(ip instanceof Inet4Address); - } - sourceAddress = ip; + public Inet4Factory setSourceAddress(IpNetwork ip) { + assertEquals(Ip4Network.class, ip.getClass()); + sourceAddress = (Ip4Network)ip; return this; } /** * Set the destination IP address. * - * @param ip An {@link InetAddress}. + * @param ip An {@link IpNetwork}. * @return This instance. */ - public Inet4Factory setDestinationAddress(InetAddress ip) { - if (ip != null) { - assertTrue(ip instanceof Inet4Address); - } - destinationAddress = ip; + public Inet4Factory setDestinationAddress(IpNetwork ip) { + assertEquals(Ip4Network.class, ip.getClass()); + destinationAddress = (Ip4Network)ip; return this; } @@ -238,10 +230,8 @@ public final class Inet4Factory extends PacketFactory { assertTrue(packet instanceof IPv4); IPv4 ip = (IPv4)packet; - int srcInet = toInteger(sourceAddress); - int dstInet = toInteger(destinationAddress); - assertEquals(srcInet, ip.getSourceAddress()); - assertEquals(dstInet, ip.getDestinationAddress()); + assertEquals(sourceAddress, ip.getSourceAddress()); + assertEquals(destinationAddress, ip.getDestinationAddress()); assertEquals(protocol, ip.getProtocol()); assertEquals(timeToLive, ip.getTtl()); assertEquals(dscp, ip.getDiffServ()); @@ -258,11 +248,12 @@ public final class Inet4Factory extends PacketFactory { Ipv4MatchBuilder i4mb = new Ipv4MatchBuilder(); if (types.contains(FlowMatchType.IP_SRC)) { - i4mb.setIpv4Source(toIpv4Prefix(sourceAddress)); + i4mb.setIpv4Source(sourceAddress.getIpPrefix().getIpv4Prefix()); v4Count++; } if (types.contains(FlowMatchType.IP_DST)) { - i4mb.setIpv4Destination(toIpv4Prefix(destinationAddress)); + i4mb.setIpv4Destination(destinationAddress.getIpPrefix(). + getIpv4Prefix()); v4Count++; } if (types.contains(FlowMatchType.IP_PROTO)) { @@ -284,16 +275,6 @@ public final class Inet4Factory extends PacketFactory { return ipCount + v4Count; } - /** - * Convert an IPv4 address into an integer value. - * - * @param ip An {@link InetAddress} instance. - * @return An integer value. - */ - private int toInteger(InetAddress ip) { - return NumberUtils.toInteger(ip.getAddress()); - } - // Object /** diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/PacketFactory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/PacketFactory.java index 37898882..cc861cd6 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/PacketFactory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/PacketFactory.java @@ -13,13 +13,12 @@ import static org.junit.Assert.fail; import java.util.Set; +import org.opendaylight.vtn.manager.packet.Packet; import org.opendaylight.vtn.manager.util.ByteUtils; import org.opendaylight.vtn.manager.it.ofmock.OfMockUtils; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.Packet; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/TcpFactory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/TcpFactory.java index 635c8da5..30463b79 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/TcpFactory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/TcpFactory.java @@ -15,13 +15,12 @@ import static org.opendaylight.vtn.manager.it.util.ModelDrivenTestBase.toPortNum import java.util.Set; +import org.opendaylight.vtn.manager.packet.Packet; +import org.opendaylight.vtn.manager.packet.TCP; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.Packet; -import org.opendaylight.controller.sal.packet.TCP; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; diff --git a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/UdpFactory.java b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/UdpFactory.java index c841901a..7acfc80d 100644 --- a/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/UdpFactory.java +++ b/manager/it/util/src/main/java/org/opendaylight/vtn/manager/it/util/packet/UdpFactory.java @@ -15,13 +15,12 @@ import static org.opendaylight.vtn.manager.it.util.ModelDrivenTestBase.toPortNum import java.util.Set; +import org.opendaylight.vtn.manager.packet.Packet; +import org.opendaylight.vtn.manager.packet.UDP; import org.opendaylight.vtn.manager.util.InetProtocols; import org.opendaylight.vtn.manager.it.util.match.FlowMatchType; -import org.opendaylight.controller.sal.packet.Packet; -import org.opendaylight.controller.sal.packet.UDP; - import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; -- 2.36.6