diff options
Diffstat (limited to 'framework/src/onos/utils/misc')
15 files changed, 1756 insertions, 2 deletions
diff --git a/framework/src/onos/utils/misc/pom.xml b/framework/src/onos/utils/misc/pom.xml index 17951215..2e721135 100644 --- a/framework/src/onos/utils/misc/pom.xml +++ b/framework/src/onos/utils/misc/pom.xml @@ -22,7 +22,7 @@ <parent> <groupId>org.onosproject</groupId> <artifactId>onlab-utils</artifactId> - <version>1.3.0-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java index 230609f8..a0e0570d 100644 --- a/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAOrganism.java @@ -1,3 +1,18 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.onlab.graph; /** diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java index ae7f182e..c5fa9b45 100644 --- a/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/graph/GAPopulation.java @@ -1,3 +1,18 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.onlab.graph; import java.util.ArrayList; diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IPv4.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IPv4.java index d75b50a2..a5c5f4f1 100644 --- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IPv4.java +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IPv4.java @@ -35,6 +35,7 @@ public class IPv4 extends BasePacket { public static final byte PROTOCOL_IGMP = 0x2; public static final byte PROTOCOL_TCP = 0x6; public static final byte PROTOCOL_UDP = 0x11; + public static final byte PROTOCOL_PIM = 0x67; public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP = new HashMap<>(); @@ -43,6 +44,7 @@ public class IPv4 extends BasePacket { IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer()); IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer()); IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer()); + IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_PIM, PIM.deserializer()); } private static final byte DSCP_MASK = 0x3f; diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MPLS.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MPLS.java index 47dbeed2..71c5803e 100644 --- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MPLS.java +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/MPLS.java @@ -1,3 +1,18 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.onlab.packet; import java.nio.ByteBuffer; diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java new file mode 100755 index 00000000..d9a5e83f --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/PIM.java @@ -0,0 +1,296 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet; + +import org.onlab.packet.pim.PIMHello; +import org.onlab.packet.pim.PIMJoinPrune; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import static org.onlab.packet.PacketUtils.checkInput; + +/** + * Implements PIM control packet format. + */ +public class PIM extends BasePacket { + + public static final IpAddress PIM_ADDRESS = IpAddress.valueOf("224.0.0.13"); + + public static final byte TYPE_HELLO = 0x00; + public static final byte TYPE_REGISTER = 0x01; + public static final byte TYPE_REGISTER_STOP = 0x02; + public static final byte TYPE_JOIN_PRUNE_REQUEST = 0x03; + public static final byte TYPE_BOOTSTRAP = 0x04; + public static final byte TYPE_ASSERT = 0x05; + public static final byte TYPE_GRAFT = 0x06; + public static final byte TYPE_GRAFT_ACK = 0x07; + public static final byte TYPE_CANDIDATE_RP_ADV = 0x08; + + public static final int PIM_HEADER_LEN = 4; + + public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP = + new HashMap<>(); + + static { + PIM.PROTOCOL_DESERIALIZER_MAP.put(PIM.TYPE_HELLO, PIMHello.deserializer()); + PIM.PROTOCOL_DESERIALIZER_MAP.put(PIM.TYPE_JOIN_PRUNE_REQUEST, PIMJoinPrune.deserializer()); + } + + /* + * PIM Header fields + */ + protected byte version; + protected byte type; + protected byte reserved; + protected short checksum; + + /** + * Default constructor. + */ + public PIM() { + super(); + this.version = 2; + this.reserved = 0; + } + + /** + * Return the PIM message type. + * + * @return the pimMsgType + */ + public byte getPimMsgType() { + return this.type; + } + + /** + * Set the PIM message type. Currently PIMJoinPrune and PIMHello are + * supported. + * + * @param type PIM message type + * @return PIM Header + */ + public PIM setPIMType(final byte type) { + this.type = type; + return this; + } + + /** + * Get the version of PIM. + * + * @return the PIM version. Must be 2. + */ + public byte getVersion() { + return version; + } + + /** + * Set the PIM version type. Should not change from 2. + * + * @param version PIM version + */ + public void setVersion(byte version) { + this.version = version; + } + + /** + * Get the reserved field. + * + * @return the reserved field. Must be ignored. + */ + public byte getReserved() { + return reserved; + } + + /** + * Set the reserved field. + * + * @param reserved should be 0 + */ + public void setReserved(byte reserved) { + this.reserved = reserved; + } + + /** + * Get the checksum of this packet. + * + * @return the checksum + */ + public short getChecksum() { + return checksum; + } + + /** + * Set the checksum. + * + * @param checksum the checksum + */ + public void setChecksum(short checksum) { + this.checksum = checksum; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 5807; + int result = super.hashCode(); + result = prime * result + this.type; + result = prime * result + this.version; + result = prime * result + this.checksum; + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof PIM)) { + return false; + } + final PIM other = (PIM) obj; + if (this.type != other.type) { + return false; + } + if (this.version != other.version) { + return false; + } + if (this.checksum != other.checksum) { + return false; + } + return true; + } + + /** + * Serializes the packet. Will compute and set the following fields if they + * are set to specific values at the time serialize is called: -checksum : 0 + * -length : 0 + * + * @return will return the serialized packet + */ + @Override + public byte[] serialize() { + int length = 4; + byte[] payloadData = null; + if (this.payload != null) { + this.payload.setParent(this); + payloadData = this.payload.serialize(); + length += payloadData.length; + } + + final byte[] data = new byte[length]; + final ByteBuffer bb = ByteBuffer.wrap(data); + + bb.put((byte) ((this.version & 0xf) << 4 | this.type & 0xf)); + bb.put(this.reserved); + bb.putShort(this.checksum); + if (payloadData != null) { + bb.put(payloadData); + } + + if (this.parent != null && this.parent instanceof PIM) { + ((PIM) this.parent).setPIMType(TYPE_JOIN_PRUNE_REQUEST); + } + + // compute checksum if needed + if (this.checksum == 0) { + bb.rewind(); + int accumulation = 0; + + for (int i = 0; i < length / 2; ++i) { + accumulation += 0xffff & bb.getShort(); + } + // pad to an even number of shorts + if (length % 2 > 0) { + accumulation += (bb.get() & 0xff) << 8; + } + + accumulation = (accumulation >> 16 & 0xffff) + + (accumulation & 0xffff); + this.checksum = (short) (~accumulation & 0xffff); + bb.putShort(2, this.checksum); + } + return data; + } + + /** + * Deserialize the PIM packet. + * + * @param data bytes to deserialize. + * @param offset offset to start deserializing from + * @param length length of the data to deserialize + * + * @return the deserialized PIM packet. + */ + @Override + public IPacket deserialize(final byte[] data, final int offset, + final int length) { + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + this.type = bb.get(); + this.version = bb.get(); + this.checksum = bb.getShort(); + + //this.payload = new Data(); + this.payload = this.payload.deserialize(data, bb.position(), bb.limit() - bb.position()); + this.payload.setParent(this); + return this; + } + /** + * Deserializer function for IPv4 packets. + * + * @return deserializer function + */ + public static Deserializer<PIM> deserializer() { + return (data, offset, length) -> { + checkInput(data, offset, length, PIM_HEADER_LEN); + + PIM pim = new PIM(); + + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + + byte versionByte = bb.get(); + pim.version = (byte) (versionByte >> 4 & 0xf); + pim.setPIMType((byte) (versionByte & 0xf)); + pim.reserved = bb.get(); + pim.checksum = bb.getShort(); + + Deserializer<? extends IPacket> deserializer; + if (PIM.PROTOCOL_DESERIALIZER_MAP.containsKey(pim.getPimMsgType())) { + deserializer = PIM.PROTOCOL_DESERIALIZER_MAP.get(pim.getPimMsgType()); + } else { + deserializer = Data.deserializer(); + } + + pim.payload = deserializer.deserialize(data, bb.position(), bb.limit() - bb.position()); + pim.payload.setParent(pim); + + return pim; + }; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java new file mode 100644 index 00000000..891a0193 --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrGroup.java @@ -0,0 +1,257 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.DeserializationException; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onlab.packet.Ip6Address; + +import java.nio.ByteBuffer; + +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMAddrGroup { + private byte family; + private byte encType; + private byte reserved; + private boolean bBit; + private boolean zBit; + private byte masklen; + IpAddress addr; + + public static final int ENC_GROUP_IPV4_BYTE_LENGTH = 4 + Ip4Address.BYTE_LENGTH; + public static final int ENC_GROUP_IPV6_BYTE_LENGTH = 4 + Ip6Address.BYTE_LENGTH; + + /** + * PIM Encoded Group Address. + */ + public PIMAddrGroup() { + this.family = 4; + this.encType = 0; + this.reserved = 0; + this.bBit = false; + this.zBit = false; + } + + /** + * PIM Encoded Source Address. + * + * @param addr IPv4 or IPv6 + */ + public PIMAddrGroup(String addr) { + this.setAddr(addr); + } + + /** + * PIM Encoded Group Address. + * + * @param gpfx PIM encoded group address. + */ + public PIMAddrGroup(IpPrefix gpfx) { + this.setAddr(gpfx); + } + + /** + * PIM encoded source address. + * + * @param addr IPv4 or IPv6 + */ + public void setAddr(String addr) { + setAddr(IpPrefix.valueOf(addr)); + } + + /** + * Set the encoded source address. + * + * @param pfx address prefix + */ + public void setAddr(IpPrefix pfx) { + this.addr = pfx.address(); + this.masklen = (byte) pfx.prefixLength(); + this.family = (byte) ((this.addr.isIp4()) ? 4 : 6); + } + + /** + * Get the IP family of this address: 4 or 6. + * + * @return the IP address family + */ + public int getFamily() { + return this.family; + } + + /** + * Get the address of this encoded address. + * + * @return source address + */ + public IpAddress getAddr() { + return this.addr; + } + + /** + * Get the masklen of the group address. + * + * @return the masklen + */ + public int getMasklen() { + return this.masklen; + } + + /** + * Return the z bit for admin scoping. Only used for the Bootstrap router. + * + * @return true or false + */ + public boolean getZBit() { + return this.zBit; + } + + /** + * Return the bBit. Used to indicate this is a bidir + * + * @return return true or false. + */ + public boolean getBBit() { + return this.bBit; + } + + /** + * The size in bytes of a serialized address. + * + * @return the number of bytes when serialized + */ + public int getByteSize() { + int size = 4; + size += addr.isIp4() ? 4 : 16; + return size; + } + + /** + * Serialize this group address. + * + * @return the serialized address in a buffer + */ + public byte[] serialize() { + int len = getByteSize(); + + final byte[] data = new byte[len]; + final ByteBuffer bb = ByteBuffer.wrap(data); + + bb.put(this.family); + bb.put(this.encType); + + // Todo: technically we should be setting the B and Z bits, but we'll never use them. + bb.put(reserved); + + bb.put(this.masklen); + bb.put(this.addr.toOctets()); + return data; + } + + /** + * Deserialze from a ByteBuffer. + * + * @param bb the ByteBuffer + * @return an encoded PIM group address + * @throws DeserializationException if unable to deserialize the packet data + */ + public PIMAddrGroup deserialize(ByteBuffer bb) throws DeserializationException { + + /* + * We need to verify that we have enough buffer space. First we'll assume that + * we are decoding an IPv4 address. After we read the first by (address family), + * we'll determine if we actually need more buffer space for an IPv6 address. + */ + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV4_BYTE_LENGTH); + + this.family = bb.get(); + if (family != 4 && family != 6) { + throw new DeserializationException("Illegal IP version number: " + family + "\n"); + } else if (family == 6) { + + // Check for one less by since we have already read the first byte of the packet. + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV6_BYTE_LENGTH - 1); + } + + this.encType = bb.get(); + this.reserved = bb.get(); + if ((this.reserved & 0x80) != 0) { + this.bBit = true; + } + if ((this.reserved & 0x01) != 0) { + this.zBit = true; + } + // Remove the z and b bits from reserved + this.reserved |= 0x7d; + + this.masklen = bb.get(); + if (this.family == 4) { + this.addr = IpAddress.valueOf(bb.getInt()); + } else if (this.family == 6) { + this.addr = Ip6Address.valueOf(bb.array(), 2); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 2521; + int result = super.hashCode(); + result = prime * result + this.family; + result = prime * result + this.encType; + result = prime * result + this.reserved; + result = prime * result + this.masklen; + result = prime * result + this.addr.hashCode(); + return result; + } + + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals() + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PIMAddrGroup)) { + return false; + } + final PIMAddrGroup other = (PIMAddrGroup) obj; + if (this.family != this.family) { + return false; + } + + if (this.encType != other.encType) { + return false; + } + + if (!this.addr.equals(other.addr)) { + return false; + } + return true; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java new file mode 100644 index 00000000..2d4a7816 --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrSource.java @@ -0,0 +1,281 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.DeserializationException; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onlab.packet.IpPrefix; +import org.onlab.packet.Ip6Address; + +import java.nio.ByteBuffer; + +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMAddrSource { + private byte family; + private byte encType; + private byte reserved; + private boolean sBit; + private boolean wBit; + private boolean rBit; + private byte masklen; + IpAddress addr; + + public static final int ENC_SOURCE_IPV4_BYTE_LENGTH = 4 + Ip4Address.BYTE_LENGTH; + public static final int ENC_SOURCE_IPV6_BYTE_LENGTH = 4 + Ip6Address.BYTE_LENGTH; + + /** + * PIM Encoded Source Address. + * + * @param addr IPv4 or IPv6 + */ + public PIMAddrSource(String addr) { + this.init(); + this.setAddr(addr); + } + + /** + * PIM Encoded Source Address. + * + * @param spfx IPv4 or IPv6 + */ + public PIMAddrSource(IpPrefix spfx) { + this.init(); + this.setAddr(spfx); + } + + /** + * PIM Encoded Group Address. + */ + public PIMAddrSource() { + this.init(); + } + + private void init() { + this.family = 4; + this.encType = 0; + this.reserved = 0; + this.sBit = true; + this.wBit = false; + this.rBit = false; + } + + /** + * PIM Encoded Source Address. + * + * @param addr IPv4 or IPv6 + */ + public void setAddr(String addr) { + IpPrefix spfx = IpPrefix.valueOf(addr); + setAddr(spfx); + } + + /** + * PIM Encoded Source Address. + * + * @param spfx IPv4 or IPv6 address prefix + */ + public void setAddr(IpPrefix spfx) { + this.addr = spfx.address(); + this.masklen = (byte) spfx.prefixLength(); + this.family = (byte) ((this.addr.isIp4()) ? 4 : 6); + } + + /** + * Get the IP family of this address: 4 or 6. + * + * @return the IP address family + */ + public byte getFamily() { + return this.family; + } + + /** + * Get the address of this encoded address. + * + * @return source address + */ + public IpAddress getAddr() { + return this.addr; + } + + /** + * Get the masklen of the group address. + * + * @return the masklen + */ + public int getMasklen() { + return this.masklen; + } + + /** + * Return the sparse bit. + * + * @return true or false + */ + public boolean getSBit() { + return this.sBit; + } + + /** + * Return the wBit, used in Join/Prune messages. + * + * @return return true or false. + */ + public boolean getWBit() { + return this.wBit; + } + + /** + * Return the rBit. Used by Rendezvous Point. + * + * @return the rBit. + */ + public boolean getRBit() { + return this.rBit; + } + + /** + * The size in bytes of a serialized address. + * + * @return the number of bytes when serialized + */ + public int getByteSize() { + int size = 4; + size += addr.isIp4() ? 4 : 16; + return size; + } + + public byte[] serialize() { + int len = addr.isIp4() ? ENC_SOURCE_IPV4_BYTE_LENGTH : ENC_SOURCE_IPV6_BYTE_LENGTH; + + final byte[] data = new byte[len]; + final ByteBuffer bb = ByteBuffer.wrap(data); + + bb.put(this.family); + bb.put(this.encType); + + // Todo: technically we should be setting the B and Z bits, but we'll never use them. + byte mask = 0x0; + if (this.sBit) { + this.reserved |= 0x4; + } + if (this.wBit) { + this.reserved |= 0x2; + } + if (this.rBit) { + this.reserved |= 0x1; + } + bb.put(reserved); + + bb.put(this.masklen); + bb.put(this.addr.toOctets()); + return data; + } + + public PIMAddrSource deserialize(byte[] data, int offset, int length) throws DeserializationException { + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + return deserialize(bb); + } + + public PIMAddrSource deserialize(ByteBuffer bb) throws DeserializationException { + + /* + * We need to verify that we have enough buffer space. First we'll assume that + * we are decoding an IPv4 address. After we read the first by (address family), + * we'll determine if we actually need more buffer space for an IPv6 address. + */ + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV4_BYTE_LENGTH); + + this.family = bb.get(); + if (family != 4 && family != 6) { + throw new DeserializationException("Illegal IP version number: " + family + "\n"); + } else if (family == 6) { + + // Check for one less by since we have already read the first byte of the packet. + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV6_BYTE_LENGTH - 1); + } + + this.encType = bb.get(); + this.reserved = bb.get(); + if ((this.reserved & 0x01) != 0) { + this.rBit = true; + } + if ((this.reserved & 0x02) != 0) { + this.wBit = true; + } + if ((this.reserved & 0x4) != 0) { + this.sBit = true; + } + + // Remove the s, reserved + this.reserved &= 0xf8; + + this.masklen = bb.get(); + if (this.family == 4) { + this.addr = IpAddress.valueOf(bb.getInt()); + } else if (this.family == 6) { + this.addr = Ip6Address.valueOf(bb.array(), 2); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 2521; + int result = super.hashCode(); + result = prime * result + this.family; + result = prime * result + this.encType; + result = prime * result + this.reserved; + result = prime * result + this.masklen; + result = prime * result + this.addr.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PIMAddrSource)) { + return false; + } + final PIMAddrSource other = (PIMAddrSource) obj; + if (this.family != this.family) { + return false; + } + + if (this.encType != other.encType) { + return false; + } + + if (!this.addr.equals(other.addr)) { + return false; + } + return true; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java new file mode 100644 index 00000000..0c2d676b --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMAddrUnicast.java @@ -0,0 +1,182 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.DeserializationException; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onlab.packet.Ip6Address; + +import java.nio.ByteBuffer; + +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMAddrUnicast { + private byte family; + private byte encType; + IpAddress addr; + + public static final int ENC_UNICAST_IPV4_BYTE_LENGTH = 2 + Ip4Address.BYTE_LENGTH; + public static final int ENC_UNICAST_IPV6_BYTE_LENGTH = 2 + Ip6Address.BYTE_LENGTH; + + /** + * PIM Encoded Source Address. + */ + public PIMAddrUnicast() { + this.family = 4; + this.encType = 0; + } + + /** + * PIM Encoded Source Address. + * + * @param addr IPv4 or IPv6 + */ + public PIMAddrUnicast(String addr) { + this.addr = IpAddress.valueOf(addr); + if (this.addr.isIp4()) { + this.family = 4; + } else { + this.family = 6; + } + this.encType = 0; + } + + /** + * PIM Encoded Source Address. + * + * @param addr IPv4 or IPv6 + */ + public void setAddr(IpAddress addr) { + this.addr = addr; + if (this.addr.isIp4()) { + this.family = 4; + } else { + this.family = 6; + } + } + + /** + * Get the address of this encoded address. + * + * @return source address + */ + public IpAddress getAddr() { + return this.addr; + } + + /** + * Get the IP family of this address: 4 or 6. + * + * @return the IP address family + */ + public int getFamily() { + return this.family; + } + + /** + * The size in bytes of a serialized address. + * + * @return the number of bytes when serialized + */ + public int getByteSize() { + int size = 2; + if (addr != null) { + size += addr.isIp4() ? 4 : 16; + } else { + size += 4; + } + return size; + } + + public byte[] serialize() { + int len = getByteSize(); + + final byte[] data = new byte[len]; + final ByteBuffer bb = ByteBuffer.wrap(data); + + bb.put(family); + bb.put(encType); + bb.put(addr.toOctets()); + return data; + } + + public PIMAddrUnicast deserialize(ByteBuffer bb) throws DeserializationException { + + // Assume IPv4 for check length until we read the encoded family. + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_UNICAST_IPV4_BYTE_LENGTH); + this.family = bb.get(); + + // If we have IPv6 we need to ensure we have adequate buffer space. + if (this.family != 4 && this.family != 6) { + throw new DeserializationException("Invalid address family: " + this.family); + } else if (this.family == 6) { + // Subtract -1 from ENC_UNICAST_IPv6 BYTE_LENGTH because we read one byte for family previously. + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_UNICAST_IPV6_BYTE_LENGTH - 1); + } + + this.encType = bb.get(); + if (this.family == 4) { + this.addr = IpAddress.valueOf(bb.getInt()); + } else if (this.family == 6) { + this.addr = Ip6Address.valueOf(bb.array(), 2); + } + return this; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 2521; + int result = super.hashCode(); + result = prime * result + this.family; + result = prime * result + this.encType; + result = prime * result + this.addr.hashCode(); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof PIMAddrUnicast)) { + return false; + } + final PIMAddrUnicast other = (PIMAddrUnicast) obj; + if (this.family != this.family) { + return false; + } + + if (this.encType != other.encType) { + return false; + } + + if (!this.addr.equals(other.addr)) { + return false; + } + return true; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java new file mode 100644 index 00000000..9ad3fdbd --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHello.java @@ -0,0 +1,118 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.BasePacket; +import org.onlab.packet.Deserializer; +import org.onlab.packet.IPacket; +import org.onlab.packet.IpAddress; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMHello extends BasePacket { + + private IpAddress nbrIpAddress; + private boolean priorityPresent = false; + + private Map<Short, PIMHelloOption> options = new HashMap<>(); + + /** + * Create a PIM Hello packet with the most common hello options and default + * values. The values of any options can be easily changed by modifying the value of + * the option with the desired change. + */ + public void createDefaultOptions() { + options.put(PIMHelloOption.OPT_HOLDTIME, new PIMHelloOption(PIMHelloOption.OPT_HOLDTIME)); + options.put(PIMHelloOption.OPT_PRIORITY, new PIMHelloOption(PIMHelloOption.OPT_PRIORITY)); + options.put(PIMHelloOption.OPT_GENID, new PIMHelloOption(PIMHelloOption.OPT_GENID)); + } + + /** + * Add a PIM Hello option to this hello message. Note + * + * @param opt the PIM Hello option we are adding + */ + public void addOption(PIMHelloOption opt) { + this.options.put(opt.getOptType(), opt); + } + + public Map<Short, PIMHelloOption> getOptions() { + return this.options; + } + + /** + * Sets all payloads parent packet if applicable, then serializes this + * packet and all payloads. + * + * @return a byte[] containing this packet and payloads + */ + @Override + public byte[] serialize() { + int totalLen = 0; + + + // Since we are likely to only have 3-4 options, go head and walk the + // hashmap twice, once to calculate the space needed to allocate a + // buffer, the second time serialize the options into the buffer. This + // saves us from allocating an over sized buffer the re-allocating and + // copying. + for (Short optType : options.keySet()) { + PIMHelloOption opt = options.get(optType); + totalLen += PIMHelloOption.MINIMUM_OPTION_LEN_BYTES + opt.getOptLength(); + } + + byte[] data = new byte[totalLen]; + ByteBuffer bb = ByteBuffer.wrap(data); + + // Now serialize the data. + for (Short optType : options.keySet()) { + PIMHelloOption opt = options.get(optType); + bb.put(opt.serialize()); + } + return data; + } + + /** + * XXX: This is deprecated, DO NOT USE, use the deserializer() function instead. + */ + public IPacket deserialize(final byte[] data, final int offset, + final int length) { + // TODO: throw an expection? + return null; + } + + /** + * Deserialize this hello message. + * + * @return a deserialized hello message + */ + public static Deserializer<PIMHello> deserializer() { + return (data, offset, length) -> { + checkInput(data, offset, length, PIMHelloOption.MINIMUM_OPTION_LEN_BYTES); + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + + PIMHello hello = new PIMHello(); + while (bb.hasRemaining()) { + PIMHelloOption opt = PIMHelloOption.deserialize(bb); + hello.addOption(opt); + } + return hello; + }; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java new file mode 100644 index 00000000..bf021fbd --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMHelloOption.java @@ -0,0 +1,147 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.DeserializationException; + +import java.nio.ByteBuffer; +import java.text.MessageFormat; + +import static org.onlab.packet.PacketUtils.checkBufferLength; +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMHelloOption { + + /** + * PIM Option types. + */ + public static final short OPT_HOLDTIME = 1; + public static final short OPT_PRUNEDELAY = 2; + public static final short OPT_PRIORITY = 19; + public static final short OPT_GENID = 20; + public static final short OPT_ADDRLIST = 24; + + public static final short DEFAULT_HOLDTIME = 105; + public static final int DEFAULT_PRUNEDELAY = 2000; // 2,000 ms + public static final int DEFAULT_PRIORITY = 1; + public static final int DEFAULT_GENID = 0; + + public static final int MINIMUM_OPTION_LEN_BYTES = 4; + + // Values for this particular hello option. + private short optType; + private short optLength; + private byte[] optValue; + + public PIMHelloOption() { + } + + /** + * Set a PIM Hello option by type. The length and default value of the + * type will be auto filled in by default. + * + * @param type hello option type + */ + public PIMHelloOption(short type) { + this.optType = type; + switch (type) { + case OPT_HOLDTIME: + this.optLength = 2; + this.optValue = new byte[optLength]; + ByteBuffer.wrap(this.optValue).putShort(PIMHelloOption.DEFAULT_HOLDTIME); + break; + + case OPT_PRUNEDELAY: + this.optLength = 4; + this.optValue = new byte[this.optLength]; + ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRUNEDELAY); + break; + + case OPT_PRIORITY: + this.optLength = 4; + this.optValue = new byte[this.optLength]; + ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRIORITY); + break; + + case OPT_GENID: + this.optLength = 4; + this.optValue = new byte[this.optLength]; + ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_GENID); + break; + + case OPT_ADDRLIST: + this.optLength = 0; // We don't know what the length will be yet. + this.optValue = null; + + default: + //log.error("Unkown option type: " + type + "\n" ); + return; + } + } + + public void setOptType(short type) { + this.optType = type; + } + + public short getOptType() { + return this.optType; + } + + public void setOptLength(short len) { + this.optLength = len; + } + + public short getOptLength() { + return this.optLength; + } + + public void setValue(ByteBuffer bb) throws DeserializationException { + this.optValue = new byte[this.optLength]; + bb.get(this.optValue, 0, this.optLength); + } + + public byte[] getValue() { + return this.optValue; + } + + public static PIMHelloOption deserialize(ByteBuffer bb) throws DeserializationException { + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); + + PIMHelloOption opt = new PIMHelloOption(); + opt.setOptType(bb.getShort()); + opt.setOptLength(bb.getShort()); + + checkBufferLength(bb.limit(), bb.position(), opt.getOptLength()); + opt.setValue(bb); + + return opt; + } + + public byte [] serialize() { + int len = 4 + this.optLength; + ByteBuffer bb = ByteBuffer.allocate(len); + bb.putShort(this.optType); + bb.putShort(this.optLength); + bb.put(this.optValue); + return bb.array(); + } + + public String toString() { + return MessageFormat.format("Type: {0}, len: {1} value: {2}", this.optType, this.optLength, + (this.optValue == null) ? "null" : this.optValue.toString()); + } + +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java new file mode 100644 index 00000000..9653115b --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java @@ -0,0 +1,271 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet.pim; + +import org.onlab.packet.BasePacket; +import org.onlab.packet.Deserializer; +import org.onlab.packet.IPacket; +import org.onlab.packet.IpPrefix; + +import java.nio.ByteBuffer; +import java.util.HashMap; + +import static org.onlab.packet.PacketUtils.checkInput; + +public class PIMJoinPrune extends BasePacket { + + private PIMAddrUnicast upstreamAddr = new PIMAddrUnicast(); + private short holdTime = (short) 0xffff; + + private class JoinPruneGroup { + protected IpPrefix group; + protected HashMap<IpPrefix, IpPrefix> joins = new HashMap<>(); + protected HashMap<IpPrefix, IpPrefix> prunes = new HashMap<>(); + + public JoinPruneGroup(IpPrefix grp) { + group = grp; + } + } + private HashMap<IpPrefix, JoinPruneGroup> joinPrunes = new HashMap<>(); + + /** + * Get the J/P hold time. + * + * @return specified in seconds. + */ + public short getHoldTime() { + return holdTime; + } + + /** + * Set the J/P holdtime in seconds. + * + * @param holdTime return the holdtime. + */ + public void setHoldTime(short holdTime) { + this.holdTime = holdTime; + } + + /** + * Get the upstreamAddr for this J/P request. + * + * @return the upstream address. + */ + public PIMAddrUnicast getUpstreamAddr() { + return upstreamAddr; + } + + /** + * Set the upstream address of this PIM J/P request. + * + * @param upstr the PIM Upstream unicast address + */ + public void setUpstreamAddr(PIMAddrUnicast upstr) { + this.upstreamAddr = upstr; + } + + /** + * Add the specified s,g to join field. + * + * @param saddr the source address of the route + * @param gaddr the group address of the route + * @param join true for a join, false for a prune. + */ + public void addJoinPrune(String saddr, String gaddr, boolean join) { + IpPrefix gpfx = IpPrefix.valueOf(gaddr); + IpPrefix spfx = IpPrefix.valueOf(saddr); + addJoinPrune(spfx, gpfx, join); + } + + /** + * Add the specified S, G to the join field. + * + * @param spfx the source prefix of the route + * @param gpfx the group prefix of the route + * @param join true for join, false for prune + */ + public void addJoinPrune(IpPrefix spfx, IpPrefix gpfx, boolean join) { + JoinPruneGroup jpg = joinPrunes.get(gpfx); + if (jpg == null) { + jpg = new JoinPruneGroup(gpfx); + joinPrunes.put(gpfx, jpg); + } + + HashMap<IpPrefix, IpPrefix> members = (join) ? jpg.joins : jpg.prunes; + if (members.get(spfx) == null) { + members.put(spfx, spfx); + } + } + + /** + * Add a join given strings represending the source and group addresses. + * + * @param saddr source address + * @param gaddr group address + */ + public void addJoin(String saddr, String gaddr) { + this.addJoinPrune(saddr, gaddr, true); + } + + /** + * Add a prune given strings represending the source and group addresses. + * + * @param saddr source address + * @param gaddr group address + */ + public void addPrune(String saddr, String gaddr) { + this.addJoinPrune(saddr, gaddr, false); + } + + /** + * Sets all payloads parent packet if applicable, then serializes this + * packet and all payloads. + * + * @return a byte[] containing this packet and payloads + */ + @Override + public byte[] serialize() { + + byte[] data = new byte[8096]; // Come up with something better + ByteBuffer bb = ByteBuffer.wrap(data); + + bb.put(upstreamAddr.serialize()); + bb.put((byte) 0); // reserved + + int ngrps = joinPrunes.size(); + bb.put((byte) ngrps); + bb.putShort(this.holdTime); + + // Walk the group list and input all groups + for (JoinPruneGroup jpg : joinPrunes.values()) { + PIMAddrGroup grp = new PIMAddrGroup(jpg.group); + bb.put(grp.serialize()); + + // put the number of joins and prunes + bb.putShort((short) jpg.joins.size()); + bb.putShort((short) jpg.prunes.size()); + + // Set all of the joins + for (IpPrefix spfx : jpg.joins.values()) { + PIMAddrSource src = new PIMAddrSource(spfx); + bb.put(src.serialize()); + } + + // Set all of the prunes + for (IpPrefix spfx : jpg.prunes.values()) { + PIMAddrSource src = new PIMAddrSource(spfx); + bb.put(src.serialize()); + } + } + + int len = bb.position(); + byte[] data2 = new byte[len]; + bb = ByteBuffer.wrap(data2, 0, len); + bb.put(data, 0, len); + return data2; + } + + // TODO: I suppose I really need to implement this? + @Override + public IPacket deserialize(final byte[] data, final int offset, + final int length) { + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + return this; + } + + /** + * Return the J/P deserializer function. + * + * @return a function that will deserialize a J/P message. + */ + public static Deserializer<PIMJoinPrune> deserializer() { + return (data, offset, length) -> { + + /* + * Delay buffer checks until we read enough of the packet to know how + * much data we will require. Each encoded address deserializer function + * will ensure there is enough data for that address. + */ + PIMJoinPrune jp = new PIMJoinPrune(); + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); + + // We must get a PIM encoded unicast address + PIMAddrUnicast upstream = new PIMAddrUnicast(); + upstream.deserialize(bb); + jp.setUpstreamAddr(upstream); + + // Use this boolean to determine the buffer space we need according to address sizes + boolean ipv4 = upstream.getAddr().isIp4(); + + // We need at minimum 4 bytes for reserved(1), ngroups(1) & holdtime(2) + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); + + // get and skip the reserved byte + bb.get(); + + // Get the number of groups. + int ngroups = bb.get(); + + // Save the holdtime. + jp.setHoldTime(bb.getShort()); + + + for (int i = 0; i < ngroups; i++) { + PIMAddrGroup grp = new PIMAddrGroup(); + + /* + * grp.deserialize will ensure the buffer has enough data to read the group address. + */ + grp.deserialize(bb); + + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); + int njoins = bb.getShort(); + int nprunes = bb.getShort(); + + /* + * Now we'll verify we have enough buffer to read the next + * group of join and prune addresses for this group. + */ + int required = (njoins + nprunes) * + (ipv4 ? PIMAddrSource.ENC_SOURCE_IPV4_BYTE_LENGTH : PIMAddrSource.ENC_SOURCE_IPV6_BYTE_LENGTH); + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), required); + + // Now iterate through the joins for this group + for (; njoins > 0; njoins--) { + + PIMAddrSource src = new PIMAddrSource(); + src.deserialize(bb); + + jp.addJoinPrune( + src.getAddr().toIpPrefix(), + grp.getAddr().toIpPrefix(), true); + } + + // Now iterate through the prunes for this group + for (; nprunes > 0; nprunes--) { + + PIMAddrSource src = new PIMAddrSource(); + src.deserialize(bb); + jp.addJoinPrune( + src.getAddr().toIpPrefix(), + grp.getAddr().toIpPrefix(), false); + } + } + + return jp; + }; + } +} diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/package-info.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/package-info.java new file mode 100755 index 00000000..88a1ad5d --- /dev/null +++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Utilities for managing PIM packets. + */ +package org.onlab.packet.pim; + diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/packet/PIMTest.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/packet/PIMTest.java new file mode 100644 index 00000000..7fba3cd7 --- /dev/null +++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/packet/PIMTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onlab.packet; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.pim.PIMAddrUnicast; +import org.onlab.packet.pim.PIMHello; +import org.onlab.packet.pim.PIMJoinPrune; + +import static junit.framework.Assert.assertTrue; + +public final class PIMTest { + + public static final String SADDR = "10.2.1.2"; + public static final String PIMADDR = "224.0.0.13"; + public static final String PIMUADDR = "10.23.3.5"; + + public static final String SADDR1 = "10.1.1.1/32"; + public static final String SADDR2 = "10.1.2.1/32"; + public static final String GADDR1 = "232.1.1.1/32"; + public static final String GADDR2 = "232.1.2.1/32"; + + public static final String CPSTR1 = "of:deadbeefball/8"; + public static final String CPSTR2 = "of:deadbeefcafe/3"; + public static final String CPSTR3 = "of:2badcafef00d/3"; + + private Deserializer<PIM> deserializer; + + private PIM pimHello; + private PIMHello hello; + + private PIM pimJoinPrune; + private PIMJoinPrune joinPrune; + + /** + * Create PIM Hello and Join/Prune packets to be used in testing. + * + * @throws Exception if packet creation fails + */ + @Before + public void setUp() throws Exception { + + // Create a PIM Hello + pimHello = new PIM(); + pimHello.setVersion((byte) 2); + pimHello.setPIMType((byte) PIM.TYPE_HELLO); + pimHello.setChecksum((short) 0); + + hello = new PIMHello(); + hello.createDefaultOptions(); + pimHello.setPayload(hello); + hello.setParent(pimHello); + + // Create PIM Join Prune + pimJoinPrune = new PIM(); + pimJoinPrune.setVersion((byte) 2); + pimJoinPrune.setPIMType((byte) PIM.TYPE_JOIN_PRUNE_REQUEST); + pimJoinPrune.setChecksum((short) 0); + + joinPrune = new PIMJoinPrune(); + joinPrune.setUpstreamAddr(new PIMAddrUnicast(SADDR)); + joinPrune.addJoin(GADDR1, SADDR1); + joinPrune.addJoin(GADDR2, SADDR2); + joinPrune.addPrune(GADDR1, SADDR2); + joinPrune.addPrune(GADDR2, SADDR1); + + pimJoinPrune.setPayload(joinPrune); + joinPrune.setParent(pimJoinPrune); + + deserializer = PIM.deserializer(); + } + + /** + * Make sure our deserializer throws an exception if we recieve bad input. + * + * @throws Exception if we are given bad input. + */ + @Test + public void testDeserializeBadInput() throws Exception { + PacketTestUtils.testDeserializeBadInput(deserializer); + } + + /** + * Verify we throw an exception if we receive a truncated Join/Prune message. + * + * @throws Exception if we receive a truncated Join/Prune message. + */ + @Test + public void testDeserializeTruncated() throws Exception { + byte [] bits = pimJoinPrune.serialize(); + PacketTestUtils.testDeserializeTruncated(deserializer, bits); + } + + /** + * Verify that we correctly deserialize hello messages. + * + * @throws Exception if our input is bad or truncated. + */ + @Test + public void testDeserializeHello() throws Exception { + byte [] data = pimHello.serialize(); + PIM pim = deserializer.deserialize(data, 0, data.length); + assertTrue(pim.equals(pimHello)); + } + + /** + * Verify that we correctly deserialize Join/Prune messages. + * + * @throws Exception if our input is bad or truncated. + */ + @Test + public void testDeserializeJoinPrune() throws Exception { + byte [] data = pimJoinPrune.serialize(); + PIM pim = deserializer.deserialize(data, 0, data.length); + assertTrue(pim.equals(pimJoinPrune)); + } + +}
\ No newline at end of file diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/HexStringTest.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/HexStringTest.java index 27652123..e04e29a2 100644 --- a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/HexStringTest.java +++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/HexStringTest.java @@ -21,12 +21,14 @@ import com.esotericsoftware.minlog.Log; import junit.framework.TestCase; +import static org.junit.Assert.fail; + /** * Test of the Hexstring. * */ -public class HexStringTest extends TestCase { +public class HexStringTest { @Test public void testMarshalling() throws Exception { |