Committed by
Gerrit Code Review
Added packet handling functions for PIM, Specifically
PIM Hello and PIM Join/Prune messages along with respective PIM encoded address types Change-Id: Iaef2e3581e27fa910ad355043bcb3e175238706a
Showing
9 changed files
with
1600 additions
and
0 deletions
| ... | @@ -35,6 +35,7 @@ public class IPv4 extends BasePacket { | ... | @@ -35,6 +35,7 @@ public class IPv4 extends BasePacket { |
| 35 | public static final byte PROTOCOL_IGMP = 0x2; | 35 | public static final byte PROTOCOL_IGMP = 0x2; |
| 36 | public static final byte PROTOCOL_TCP = 0x6; | 36 | public static final byte PROTOCOL_TCP = 0x6; |
| 37 | public static final byte PROTOCOL_UDP = 0x11; | 37 | public static final byte PROTOCOL_UDP = 0x11; |
| 38 | + public static final byte PROTOCOL_PIM = 0x67; | ||
| 38 | public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP = | 39 | public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP = |
| 39 | new HashMap<>(); | 40 | new HashMap<>(); |
| 40 | 41 | ||
| ... | @@ -43,6 +44,7 @@ public class IPv4 extends BasePacket { | ... | @@ -43,6 +44,7 @@ public class IPv4 extends BasePacket { |
| 43 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer()); | 44 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_IGMP, IGMP.deserializer()); |
| 44 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer()); | 45 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_TCP, TCP.deserializer()); |
| 45 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer()); | 46 | IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_UDP, UDP.deserializer()); |
| 47 | + IPv4.PROTOCOL_DESERIALIZER_MAP.put(IPv4.PROTOCOL_PIM, PIM.deserializer()); | ||
| 46 | } | 48 | } |
| 47 | 49 | ||
| 48 | private static final byte DSCP_MASK = 0x3f; | 50 | private static final byte DSCP_MASK = 0x3f; | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.pim.PIMHello; | ||
| 19 | +import org.onlab.packet.pim.PIMJoinPrune; | ||
| 20 | + | ||
| 21 | +import java.nio.ByteBuffer; | ||
| 22 | +import java.util.HashMap; | ||
| 23 | +import java.util.Map; | ||
| 24 | + | ||
| 25 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * Implements PIM control packet format. | ||
| 29 | + */ | ||
| 30 | +public class PIM extends BasePacket { | ||
| 31 | + | ||
| 32 | + public static final IpAddress PIM_ADDRESS = IpAddress.valueOf("224.0.0.13"); | ||
| 33 | + | ||
| 34 | + public static final byte TYPE_HELLO = 0x00; | ||
| 35 | + public static final byte TYPE_REGISTER = 0x01; | ||
| 36 | + public static final byte TYPE_REQUEST_STOP = 0x02; | ||
| 37 | + public static final byte TYPE_JOIN_PRUNE_REQUEST = 0x03; | ||
| 38 | + public static final byte TYPE_BOOTSTRAP = 0x04; | ||
| 39 | + public static final byte TYPE_ASSERT = 0x05; | ||
| 40 | + public static final byte TYPE_GRAFT = 0x06; | ||
| 41 | + public static final byte TYPE_GRAFT_ACK = 0x07; | ||
| 42 | + public static final byte TYPE_CANDIDATE_RP_ADV = 0x08; | ||
| 43 | + | ||
| 44 | + public static final int PIM_HEADER_LEN = 4; | ||
| 45 | + | ||
| 46 | + public static final Map<Byte, Deserializer<? extends IPacket>> PROTOCOL_DESERIALIZER_MAP = | ||
| 47 | + new HashMap<>(); | ||
| 48 | + | ||
| 49 | + static { | ||
| 50 | + PIM.PROTOCOL_DESERIALIZER_MAP.put(PIM.TYPE_HELLO, PIMHello.deserializer()); | ||
| 51 | + PIM.PROTOCOL_DESERIALIZER_MAP.put(PIM.TYPE_JOIN_PRUNE_REQUEST, PIMJoinPrune.deserializer()); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + /* | ||
| 55 | + * PIM Header fields | ||
| 56 | + */ | ||
| 57 | + protected byte version; | ||
| 58 | + protected byte type; | ||
| 59 | + protected byte reserved; | ||
| 60 | + protected short checksum; | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * Default constructor. | ||
| 64 | + */ | ||
| 65 | + public PIM() { | ||
| 66 | + super(); | ||
| 67 | + this.version = 2; | ||
| 68 | + this.reserved = 0; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Return the PIM message type. | ||
| 73 | + * | ||
| 74 | + * @return the pimMsgType | ||
| 75 | + */ | ||
| 76 | + public byte getPimMsgType() { | ||
| 77 | + return this.type; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * Set the PIM message type. Currently PIMJoinPrune and PIMHello are | ||
| 82 | + * supported. | ||
| 83 | + * | ||
| 84 | + * @param type PIM message type | ||
| 85 | + * @return PIM Header | ||
| 86 | + */ | ||
| 87 | + public PIM setPIMType(final byte type) { | ||
| 88 | + this.type = type; | ||
| 89 | + return this; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * Get the version of PIM. | ||
| 94 | + * | ||
| 95 | + * @return the PIM version. Must be 2. | ||
| 96 | + */ | ||
| 97 | + public byte getVersion() { | ||
| 98 | + return version; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Set the PIM version type. Should not change from 2. | ||
| 103 | + * | ||
| 104 | + * @param version | ||
| 105 | + */ | ||
| 106 | + public void setVersion(byte version) { | ||
| 107 | + this.version = version; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + /** | ||
| 111 | + * Get the reserved field. | ||
| 112 | + * | ||
| 113 | + * @return the reserved field. Must be ignored. | ||
| 114 | + */ | ||
| 115 | + public byte getReserved() { | ||
| 116 | + return reserved; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + /** | ||
| 120 | + * Set the reserved field. | ||
| 121 | + * | ||
| 122 | + * @param reserved should be 0 | ||
| 123 | + */ | ||
| 124 | + public void setReserved(byte reserved) { | ||
| 125 | + this.reserved = reserved; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * Get the checksum of this packet. | ||
| 130 | + * | ||
| 131 | + * @return the checksum | ||
| 132 | + */ | ||
| 133 | + public short getChecksum() { | ||
| 134 | + return checksum; | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + /** | ||
| 138 | + * Set the checksum. | ||
| 139 | + * | ||
| 140 | + * @param checksum the checksum | ||
| 141 | + */ | ||
| 142 | + public void setChecksum(short checksum) { | ||
| 143 | + this.checksum = checksum; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + /* | ||
| 147 | + * (non-Javadoc) | ||
| 148 | + * | ||
| 149 | + * @see java.lang.Object#hashCode() | ||
| 150 | + */ | ||
| 151 | + @Override | ||
| 152 | + public int hashCode() { | ||
| 153 | + final int prime = 5807; | ||
| 154 | + int result = super.hashCode(); | ||
| 155 | + result = prime * result + this.type; | ||
| 156 | + result = prime * result + this.version; | ||
| 157 | + result = prime * result + this.checksum; | ||
| 158 | + return result; | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + /* | ||
| 162 | + * (non-Javadoc) | ||
| 163 | + * | ||
| 164 | + * @see java.lang.Object#equals(java.lang.Object) | ||
| 165 | + */ | ||
| 166 | + @Override | ||
| 167 | + public boolean equals(final Object obj) { | ||
| 168 | + if (this == obj) { | ||
| 169 | + return true; | ||
| 170 | + } | ||
| 171 | + if (!super.equals(obj)) { | ||
| 172 | + return false; | ||
| 173 | + } | ||
| 174 | + if (!(obj instanceof PIM)) { | ||
| 175 | + return false; | ||
| 176 | + } | ||
| 177 | + final PIM other = (PIM) obj; | ||
| 178 | + if (this.type != other.type) { | ||
| 179 | + return false; | ||
| 180 | + } | ||
| 181 | + if (this.version != other.version) { | ||
| 182 | + return false; | ||
| 183 | + } | ||
| 184 | + if (this.checksum != other.checksum) { | ||
| 185 | + return false; | ||
| 186 | + } | ||
| 187 | + return true; | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + /** | ||
| 191 | + * Serializes the packet. Will compute and set the following fields if they | ||
| 192 | + * are set to specific values at the time serialize is called: -checksum : 0 | ||
| 193 | + * -length : 0 | ||
| 194 | + * | ||
| 195 | + * @return will return the serialized packet | ||
| 196 | + */ | ||
| 197 | + @Override | ||
| 198 | + public byte[] serialize() { | ||
| 199 | + int length = 4; | ||
| 200 | + byte[] payloadData = null; | ||
| 201 | + if (this.payload != null) { | ||
| 202 | + this.payload.setParent(this); | ||
| 203 | + payloadData = this.payload.serialize(); | ||
| 204 | + length += payloadData.length; | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + final byte[] data = new byte[length]; | ||
| 208 | + final ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 209 | + | ||
| 210 | + bb.put((byte) ((this.version & 0xf) << 4 | this.type & 0xf)); | ||
| 211 | + bb.put(this.reserved); | ||
| 212 | + bb.putShort(this.checksum); | ||
| 213 | + if (payloadData != null) { | ||
| 214 | + bb.put(payloadData); | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + if (this.parent != null && this.parent instanceof PIM) { | ||
| 218 | + ((PIM) this.parent).setPIMType(TYPE_JOIN_PRUNE_REQUEST); | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + // compute checksum if needed | ||
| 222 | + if (this.checksum == 0) { | ||
| 223 | + bb.rewind(); | ||
| 224 | + int accumulation = 0; | ||
| 225 | + | ||
| 226 | + for (int i = 0; i < length / 2; ++i) { | ||
| 227 | + accumulation += 0xffff & bb.getShort(); | ||
| 228 | + } | ||
| 229 | + // pad to an even number of shorts | ||
| 230 | + if (length % 2 > 0) { | ||
| 231 | + accumulation += (bb.get() & 0xff) << 8; | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + accumulation = (accumulation >> 16 & 0xffff) | ||
| 235 | + + (accumulation & 0xffff); | ||
| 236 | + this.checksum = (short) (~accumulation & 0xffff); | ||
| 237 | + bb.putShort(2, this.checksum); | ||
| 238 | + } | ||
| 239 | + return data; | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + /** | ||
| 243 | + * Deserialize the PIM packet. | ||
| 244 | + * | ||
| 245 | + * @param data bytes to deserialize. | ||
| 246 | + * @param offset offset to start deserializing from | ||
| 247 | + * @param length length of the data to deserialize | ||
| 248 | + * | ||
| 249 | + * @return the deserialized PIM packet. | ||
| 250 | + */ | ||
| 251 | + @Override | ||
| 252 | + public IPacket deserialize(final byte[] data, final int offset, | ||
| 253 | + final int length) { | ||
| 254 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 255 | + this.type = bb.get(); | ||
| 256 | + this.version = bb.get(); | ||
| 257 | + this.checksum = bb.getShort(); | ||
| 258 | + | ||
| 259 | + //this.payload = new Data(); | ||
| 260 | + this.payload = this.payload.deserialize(data, bb.position(), bb.limit() - bb.position()); | ||
| 261 | + this.payload.setParent(this); | ||
| 262 | + return this; | ||
| 263 | + } | ||
| 264 | + /** | ||
| 265 | + * Deserializer function for IPv4 packets. | ||
| 266 | + * | ||
| 267 | + * @return deserializer function | ||
| 268 | + */ | ||
| 269 | + public static Deserializer<PIM> deserializer() { | ||
| 270 | + return (data, offset, length) -> { | ||
| 271 | + checkInput(data, offset, length, PIM_HEADER_LEN); | ||
| 272 | + | ||
| 273 | + PIM pim = new PIM(); | ||
| 274 | + | ||
| 275 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 276 | + | ||
| 277 | + byte versionByte = bb.get(); | ||
| 278 | + pim.version = (byte) (versionByte >> 4 & 0xf); | ||
| 279 | + pim.setPIMType((byte) (versionByte & 0xf)); | ||
| 280 | + pim.reserved = bb.get(); | ||
| 281 | + pim.checksum = bb.getShort(); | ||
| 282 | + | ||
| 283 | + Deserializer<? extends IPacket> deserializer; | ||
| 284 | + if (PIM.PROTOCOL_DESERIALIZER_MAP.containsKey(pim.getPimMsgType())) { | ||
| 285 | + deserializer = PIM.PROTOCOL_DESERIALIZER_MAP.get(pim.getPimMsgType()); | ||
| 286 | + } else { | ||
| 287 | + deserializer = Data.deserializer(); | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + pim.payload = deserializer.deserialize(data, bb.position(), bb.limit() - bb.position()); | ||
| 291 | + pim.payload.setParent(pim); | ||
| 292 | + | ||
| 293 | + return pim; | ||
| 294 | + }; | ||
| 295 | + } | ||
| 296 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet.pim; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.DeserializationException; | ||
| 19 | +import org.onlab.packet.Ip4Address; | ||
| 20 | +import org.onlab.packet.IpAddress; | ||
| 21 | +import org.onlab.packet.IpPrefix; | ||
| 22 | +import org.onlab.packet.Ip6Address; | ||
| 23 | + | ||
| 24 | +import java.nio.ByteBuffer; | ||
| 25 | + | ||
| 26 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 27 | + | ||
| 28 | +public class PIMAddrGroup { | ||
| 29 | + private byte family; | ||
| 30 | + private byte encType; | ||
| 31 | + private byte reserved; | ||
| 32 | + private boolean bBit; | ||
| 33 | + private boolean zBit; | ||
| 34 | + private byte masklen; | ||
| 35 | + IpAddress addr; | ||
| 36 | + | ||
| 37 | + public static final int ENC_GROUP_IPV4_BYTE_LENGTH = 4 + Ip4Address.BYTE_LENGTH; | ||
| 38 | + public static final int ENC_GROUP_IPV6_BYTE_LENGTH = 4 + Ip6Address.BYTE_LENGTH; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * PIM Encoded Group Address. | ||
| 42 | + */ | ||
| 43 | + public PIMAddrGroup() { | ||
| 44 | + this.family = 4; | ||
| 45 | + this.encType = 0; | ||
| 46 | + this.reserved = 0; | ||
| 47 | + this.bBit = false; | ||
| 48 | + this.zBit = false; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * PIM Encoded Source Address. | ||
| 53 | + * | ||
| 54 | + * @param addr IPv4 or IPv6 | ||
| 55 | + */ | ||
| 56 | + public PIMAddrGroup(String addr) { | ||
| 57 | + this.setAddr(addr); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * PIM Encoded Group Address. | ||
| 62 | + * | ||
| 63 | + * @param gpfx PIM encoded group address. | ||
| 64 | + */ | ||
| 65 | + public PIMAddrGroup(IpPrefix gpfx) { | ||
| 66 | + this.setAddr(gpfx); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * PIM encoded source address. | ||
| 71 | + * | ||
| 72 | + * @param addr IPv4 or IPv6 | ||
| 73 | + */ | ||
| 74 | + public void setAddr(String addr) { | ||
| 75 | + setAddr(IpPrefix.valueOf(addr)); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * Set the encoded source address. | ||
| 80 | + * | ||
| 81 | + * @param pfx | ||
| 82 | + */ | ||
| 83 | + public void setAddr(IpPrefix pfx) { | ||
| 84 | + this.addr = pfx.address(); | ||
| 85 | + this.masklen = (byte) pfx.prefixLength(); | ||
| 86 | + this.family = (byte) ((this.addr.isIp4()) ? 4 : 6); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * Get the IP family of this address: 4 or 6. | ||
| 91 | + * | ||
| 92 | + * @return the IP address family | ||
| 93 | + */ | ||
| 94 | + public int getFamily() { | ||
| 95 | + return this.family; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * Get the address of this encoded address. | ||
| 100 | + * | ||
| 101 | + * @return source address | ||
| 102 | + */ | ||
| 103 | + public IpAddress getAddr() { | ||
| 104 | + return this.addr; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * Get the masklen of the group address. | ||
| 109 | + * | ||
| 110 | + * @return the masklen | ||
| 111 | + */ | ||
| 112 | + public int getMasklen() { | ||
| 113 | + return this.masklen; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * Return the z bit for admin scoping. Only used for the Bootstrap router. | ||
| 118 | + * | ||
| 119 | + * @return true or false | ||
| 120 | + */ | ||
| 121 | + public boolean getZBit() { | ||
| 122 | + return this.zBit; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + /** | ||
| 126 | + * Return the bBit. Used to indicate this is a bidir | ||
| 127 | + * | ||
| 128 | + * @return return true or false. | ||
| 129 | + */ | ||
| 130 | + public boolean getBBit() { | ||
| 131 | + return this.bBit; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + /** | ||
| 135 | + * The size in bytes of a serialized address. | ||
| 136 | + * | ||
| 137 | + * @return the number of bytes when serialized | ||
| 138 | + */ | ||
| 139 | + public int getByteSize() { | ||
| 140 | + int size = 4; | ||
| 141 | + size += addr.isIp4() ? 4 : 16; | ||
| 142 | + return size; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + /** | ||
| 146 | + * Serialize this group address. | ||
| 147 | + * | ||
| 148 | + * @return the serialized address in a buffer. | ||
| 149 | + */ | ||
| 150 | + public byte[] serialize() { | ||
| 151 | + int len = getByteSize(); | ||
| 152 | + | ||
| 153 | + final byte[] data = new byte[len]; | ||
| 154 | + final ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 155 | + | ||
| 156 | + bb.put(this.family); | ||
| 157 | + bb.put(this.encType); | ||
| 158 | + | ||
| 159 | + // Todo: technically we should be setting the B and Z bits, but we'll never use them. | ||
| 160 | + bb.put(reserved); | ||
| 161 | + | ||
| 162 | + bb.put(this.masklen); | ||
| 163 | + bb.put(this.addr.toOctets()); | ||
| 164 | + return data; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + /** | ||
| 168 | + * Deserialze from a ByteBuffer. | ||
| 169 | + * | ||
| 170 | + * @param bb the ByteBuffer | ||
| 171 | + * @return an encoded PIM group address. | ||
| 172 | + */ | ||
| 173 | + public PIMAddrGroup deserialize(ByteBuffer bb) throws DeserializationException { | ||
| 174 | + | ||
| 175 | + /* | ||
| 176 | + * We need to verify that we have enough buffer space. First we'll assume that | ||
| 177 | + * we are decoding an IPv4 address. After we read the first by (address family), | ||
| 178 | + * we'll determine if we actually need more buffer space for an IPv6 address. | ||
| 179 | + */ | ||
| 180 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV4_BYTE_LENGTH); | ||
| 181 | + | ||
| 182 | + this.family = bb.get(); | ||
| 183 | + if (family != 4 && family != 6) { | ||
| 184 | + throw new DeserializationException("Illegal IP version number: " + family + "\n"); | ||
| 185 | + } else if (family == 6) { | ||
| 186 | + | ||
| 187 | + // Check for one less by since we have already read the first byte of the packet. | ||
| 188 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV6_BYTE_LENGTH - 1); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + this.encType = bb.get(); | ||
| 192 | + this.reserved = bb.get(); | ||
| 193 | + if ((this.reserved & 0x80) != 0) { | ||
| 194 | + this.bBit = true; | ||
| 195 | + } | ||
| 196 | + if ((this.reserved & 0x01) != 0) { | ||
| 197 | + this.zBit = true; | ||
| 198 | + } | ||
| 199 | + // Remove the z and b bits from reserved | ||
| 200 | + this.reserved |= 0x7d; | ||
| 201 | + | ||
| 202 | + this.masklen = bb.get(); | ||
| 203 | + if (this.family == 4) { | ||
| 204 | + this.addr = IpAddress.valueOf(bb.getInt()); | ||
| 205 | + } else if (this.family == 6) { | ||
| 206 | + this.addr = Ip6Address.valueOf(bb.array(), 2); | ||
| 207 | + } | ||
| 208 | + return this; | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + /* | ||
| 212 | + * (non-Javadoc) | ||
| 213 | + * | ||
| 214 | + * @see java.lang.Object#hashCode() | ||
| 215 | + */ | ||
| 216 | + @Override | ||
| 217 | + public int hashCode() { | ||
| 218 | + final int prime = 2521; | ||
| 219 | + int result = super.hashCode(); | ||
| 220 | + result = prime * result + this.family; | ||
| 221 | + result = prime * result + this.encType; | ||
| 222 | + result = prime * result + this.reserved; | ||
| 223 | + result = prime * result + this.masklen; | ||
| 224 | + result = prime * result + this.addr.hashCode(); | ||
| 225 | + return result; | ||
| 226 | + } | ||
| 227 | + | ||
| 228 | + | ||
| 229 | + /* | ||
| 230 | + * (non-Javadoc) | ||
| 231 | + * | ||
| 232 | + * @see java.lang.Object#equals() | ||
| 233 | + */ | ||
| 234 | + @Override | ||
| 235 | + public boolean equals(final Object obj) { | ||
| 236 | + if (this == obj) { | ||
| 237 | + return true; | ||
| 238 | + } | ||
| 239 | + if (!(obj instanceof PIMAddrGroup)) { | ||
| 240 | + return false; | ||
| 241 | + } | ||
| 242 | + final PIMAddrGroup other = (PIMAddrGroup) obj; | ||
| 243 | + if (this.family != this.family) { | ||
| 244 | + return false; | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + if (this.encType != other.encType) { | ||
| 248 | + return false; | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + if (!this.addr.equals(other.addr)) { | ||
| 252 | + return false; | ||
| 253 | + } | ||
| 254 | + return true; | ||
| 255 | + } | ||
| 256 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet.pim; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.DeserializationException; | ||
| 19 | +import org.onlab.packet.Ip4Address; | ||
| 20 | +import org.onlab.packet.IpAddress; | ||
| 21 | +import org.onlab.packet.IpPrefix; | ||
| 22 | +import org.onlab.packet.Ip6Address; | ||
| 23 | + | ||
| 24 | +import java.nio.ByteBuffer; | ||
| 25 | + | ||
| 26 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 27 | + | ||
| 28 | +public class PIMAddrSource { | ||
| 29 | + private byte family; | ||
| 30 | + private byte encType; | ||
| 31 | + private byte reserved; | ||
| 32 | + private boolean sBit; | ||
| 33 | + private boolean wBit; | ||
| 34 | + private boolean rBit; | ||
| 35 | + private byte masklen; | ||
| 36 | + IpAddress addr; | ||
| 37 | + | ||
| 38 | + public static final int ENC_SOURCE_IPV4_BYTE_LENGTH = 4 + Ip4Address.BYTE_LENGTH; | ||
| 39 | + public static final int ENC_SOURCE_IPV6_BYTE_LENGTH = 4 + Ip6Address.BYTE_LENGTH; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * PIM Encoded Source Address. | ||
| 43 | + * | ||
| 44 | + * @param addr IPv4 or IPv6 | ||
| 45 | + */ | ||
| 46 | + public PIMAddrSource(String addr) { | ||
| 47 | + this.init(); | ||
| 48 | + this.setAddr(addr); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * PIM Encoded Source Address. | ||
| 53 | + * | ||
| 54 | + * @param spfx IPv4 or IPv6 | ||
| 55 | + */ | ||
| 56 | + public PIMAddrSource(IpPrefix spfx) { | ||
| 57 | + this.init(); | ||
| 58 | + this.setAddr(spfx); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * PIM Encoded Group Address. | ||
| 63 | + */ | ||
| 64 | + public PIMAddrSource() { | ||
| 65 | + this.init(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + private void init() { | ||
| 69 | + this.family = 4; | ||
| 70 | + this.encType = 0; | ||
| 71 | + this.reserved = 0; | ||
| 72 | + this.sBit = true; | ||
| 73 | + this.wBit = false; | ||
| 74 | + this.rBit = false; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * PIM Encoded Source Address. | ||
| 79 | + * | ||
| 80 | + * @param addr IPv4 or IPv6 | ||
| 81 | + */ | ||
| 82 | + public void setAddr(String addr) { | ||
| 83 | + IpPrefix spfx = IpPrefix.valueOf(addr); | ||
| 84 | + setAddr(spfx); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * PIM Encoded Source Address. | ||
| 89 | + * | ||
| 90 | + * @param spfx IPv4 or IPv6 address prefix | ||
| 91 | + */ | ||
| 92 | + public void setAddr(IpPrefix spfx) { | ||
| 93 | + this.addr = spfx.address(); | ||
| 94 | + this.masklen = (byte) spfx.prefixLength(); | ||
| 95 | + this.family = (byte) ((this.addr.isIp4()) ? 4 : 6); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * Get the IP family of this address: 4 or 6. | ||
| 100 | + * | ||
| 101 | + * @return the IP address family | ||
| 102 | + */ | ||
| 103 | + public byte getFamily() { | ||
| 104 | + return this.family; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * Get the address of this encoded address. | ||
| 109 | + * | ||
| 110 | + * @return source address | ||
| 111 | + */ | ||
| 112 | + public IpAddress getAddr() { | ||
| 113 | + return this.addr; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * Get the masklen of the group address. | ||
| 118 | + * | ||
| 119 | + * @return the masklen | ||
| 120 | + */ | ||
| 121 | + public int getMasklen() { | ||
| 122 | + return this.masklen; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + /** | ||
| 126 | + * Return the sparse bit. | ||
| 127 | + * | ||
| 128 | + * @return true or false | ||
| 129 | + */ | ||
| 130 | + public boolean getSBit() { | ||
| 131 | + return this.sBit; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + /** | ||
| 135 | + * Return the wBit, used in Join/Prune messages. | ||
| 136 | + * | ||
| 137 | + * @return return true or false. | ||
| 138 | + */ | ||
| 139 | + public boolean getWBit() { | ||
| 140 | + return this.wBit; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + /** | ||
| 144 | + * Return the rBit. Used by Rendezvous Point. | ||
| 145 | + * | ||
| 146 | + * @return the rBit. | ||
| 147 | + */ | ||
| 148 | + public boolean getRBit() { | ||
| 149 | + return this.rBit; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + /** | ||
| 153 | + * The size in bytes of a serialized address. | ||
| 154 | + * | ||
| 155 | + * @return the number of bytes when serialized | ||
| 156 | + */ | ||
| 157 | + public int getByteSize() { | ||
| 158 | + int size = 4; | ||
| 159 | + size += addr.isIp4() ? 4 : 16; | ||
| 160 | + return size; | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + public byte[] serialize() { | ||
| 164 | + int len = addr.isIp4() ? ENC_SOURCE_IPV4_BYTE_LENGTH : ENC_SOURCE_IPV6_BYTE_LENGTH; | ||
| 165 | + | ||
| 166 | + final byte[] data = new byte[len]; | ||
| 167 | + final ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 168 | + | ||
| 169 | + bb.put(this.family); | ||
| 170 | + bb.put(this.encType); | ||
| 171 | + | ||
| 172 | + // Todo: technically we should be setting the B and Z bits, but we'll never use them. | ||
| 173 | + byte mask = 0x0; | ||
| 174 | + if (this.sBit) { | ||
| 175 | + this.reserved |= 0x4; | ||
| 176 | + } | ||
| 177 | + if (this.wBit) { | ||
| 178 | + this.reserved |= 0x2; | ||
| 179 | + } | ||
| 180 | + if (this.rBit) { | ||
| 181 | + this.reserved |= 0x1; | ||
| 182 | + } | ||
| 183 | + bb.put(reserved); | ||
| 184 | + | ||
| 185 | + bb.put(this.masklen); | ||
| 186 | + bb.put(this.addr.toOctets()); | ||
| 187 | + return data; | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + public PIMAddrSource deserialize(byte[] data, int offset, int length) throws DeserializationException { | ||
| 191 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 192 | + return deserialize(bb); | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + public PIMAddrSource deserialize(ByteBuffer bb) throws DeserializationException { | ||
| 196 | + | ||
| 197 | + /* | ||
| 198 | + * We need to verify that we have enough buffer space. First we'll assume that | ||
| 199 | + * we are decoding an IPv4 address. After we read the first by (address family), | ||
| 200 | + * we'll determine if we actually need more buffer space for an IPv6 address. | ||
| 201 | + */ | ||
| 202 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV4_BYTE_LENGTH); | ||
| 203 | + | ||
| 204 | + this.family = bb.get(); | ||
| 205 | + if (family != 4 && family != 6) { | ||
| 206 | + throw new DeserializationException("Illegal IP version number: " + family + "\n"); | ||
| 207 | + } else if (family == 6) { | ||
| 208 | + | ||
| 209 | + // Check for one less by since we have already read the first byte of the packet. | ||
| 210 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_SOURCE_IPV6_BYTE_LENGTH - 1); | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + this.encType = bb.get(); | ||
| 214 | + this.reserved = bb.get(); | ||
| 215 | + if ((this.reserved & 0x01) != 0) { | ||
| 216 | + this.rBit = true; | ||
| 217 | + } | ||
| 218 | + if ((this.reserved & 0x02) != 0) { | ||
| 219 | + this.wBit = true; | ||
| 220 | + } | ||
| 221 | + if ((this.reserved & 0x4) != 0) { | ||
| 222 | + this.sBit = true; | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + // Remove the s, reserved | ||
| 226 | + this.reserved &= 0xf8; | ||
| 227 | + | ||
| 228 | + this.masklen = bb.get(); | ||
| 229 | + if (this.family == 4) { | ||
| 230 | + this.addr = IpAddress.valueOf(bb.getInt()); | ||
| 231 | + } else if (this.family == 6) { | ||
| 232 | + this.addr = Ip6Address.valueOf(bb.array(), 2); | ||
| 233 | + } | ||
| 234 | + return this; | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + /* | ||
| 238 | + * (non-Javadoc) | ||
| 239 | + * | ||
| 240 | + * @see java.lang.Object#hashCode() | ||
| 241 | + */ | ||
| 242 | + @Override | ||
| 243 | + public int hashCode() { | ||
| 244 | + final int prime = 2521; | ||
| 245 | + int result = super.hashCode(); | ||
| 246 | + result = prime * result + this.family; | ||
| 247 | + result = prime * result + this.encType; | ||
| 248 | + result = prime * result + this.reserved; | ||
| 249 | + result = prime * result + this.masklen; | ||
| 250 | + result = prime * result + this.addr.hashCode(); | ||
| 251 | + return result; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + /* | ||
| 255 | + * (non-Javadoc) | ||
| 256 | + * | ||
| 257 | + * @see java.lang.Object#hashCode() | ||
| 258 | + */ | ||
| 259 | + @Override | ||
| 260 | + public boolean equals(final Object obj) { | ||
| 261 | + if (this == obj) { | ||
| 262 | + return true; | ||
| 263 | + } | ||
| 264 | + if (!(obj instanceof PIMAddrSource)) { | ||
| 265 | + return false; | ||
| 266 | + } | ||
| 267 | + final PIMAddrSource other = (PIMAddrSource) obj; | ||
| 268 | + if (this.family != this.family) { | ||
| 269 | + return false; | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + if (this.encType != other.encType) { | ||
| 273 | + return false; | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + if (!this.addr.equals(other.addr)) { | ||
| 277 | + return false; | ||
| 278 | + } | ||
| 279 | + return true; | ||
| 280 | + } | ||
| 281 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet.pim; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.DeserializationException; | ||
| 19 | +import org.onlab.packet.Ip4Address; | ||
| 20 | +import org.onlab.packet.IpAddress; | ||
| 21 | +import org.onlab.packet.Ip6Address; | ||
| 22 | + | ||
| 23 | +import java.nio.ByteBuffer; | ||
| 24 | + | ||
| 25 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 26 | + | ||
| 27 | +public class PIMAddrUnicast { | ||
| 28 | + private byte family; | ||
| 29 | + private byte encType; | ||
| 30 | + IpAddress addr; | ||
| 31 | + | ||
| 32 | + public static final int ENC_UNICAST_IPV4_BYTE_LENGTH = 2 + Ip4Address.BYTE_LENGTH; | ||
| 33 | + public static final int ENC_UNICAST_IPV6_BYTE_LENGTH = 2 + Ip6Address.BYTE_LENGTH; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * PIM Encoded Source Address. | ||
| 37 | + */ | ||
| 38 | + public PIMAddrUnicast() { | ||
| 39 | + this.family = 4; | ||
| 40 | + this.encType = 0; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * PIM Encoded Source Address. | ||
| 45 | + * | ||
| 46 | + * @param addr IPv4 or IPv6 | ||
| 47 | + */ | ||
| 48 | + public PIMAddrUnicast(String addr) { | ||
| 49 | + this.addr = IpAddress.valueOf(addr); | ||
| 50 | + if (this.addr.isIp4()) { | ||
| 51 | + this.family = 4; | ||
| 52 | + } else { | ||
| 53 | + this.family = 6; | ||
| 54 | + } | ||
| 55 | + this.encType = 0; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * PIM Encoded Source Address. | ||
| 60 | + * | ||
| 61 | + * @param addr IPv4 or IPv6 | ||
| 62 | + */ | ||
| 63 | + public void setAddr(IpAddress addr) { | ||
| 64 | + this.addr = addr; | ||
| 65 | + if (this.addr.isIp4()) { | ||
| 66 | + this.family = 4; | ||
| 67 | + } else { | ||
| 68 | + this.family = 6; | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * Get the address of this encoded address. | ||
| 74 | + * | ||
| 75 | + * @return source address | ||
| 76 | + */ | ||
| 77 | + public IpAddress getAddr() { | ||
| 78 | + return this.addr; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * Get the IP family of this address: 4 or 6. | ||
| 83 | + * | ||
| 84 | + * @return the IP address family | ||
| 85 | + */ | ||
| 86 | + public int getFamily() { | ||
| 87 | + return this.family; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * The size in bytes of a serialized address. | ||
| 92 | + * | ||
| 93 | + * @return the number of bytes when serialized | ||
| 94 | + */ | ||
| 95 | + public int getByteSize() { | ||
| 96 | + int size = 2; | ||
| 97 | + if (addr != null) { | ||
| 98 | + size += addr.isIp4() ? 4 : 16; | ||
| 99 | + } else { | ||
| 100 | + size += 4; | ||
| 101 | + } | ||
| 102 | + return size; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + public byte[] serialize() { | ||
| 106 | + int len = getByteSize(); | ||
| 107 | + | ||
| 108 | + final byte[] data = new byte[len]; | ||
| 109 | + final ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 110 | + | ||
| 111 | + bb.put(family); | ||
| 112 | + bb.put(encType); | ||
| 113 | + bb.put(addr.toOctets()); | ||
| 114 | + return data; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + public PIMAddrUnicast deserialize(ByteBuffer bb) throws DeserializationException { | ||
| 118 | + | ||
| 119 | + // Assume IPv4 for check length until we read the encoded family. | ||
| 120 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_UNICAST_IPV4_BYTE_LENGTH); | ||
| 121 | + this.family = bb.get(); | ||
| 122 | + | ||
| 123 | + // If we have IPv6 we need to ensure we have adequate buffer space. | ||
| 124 | + if (this.family != 4 && this.family != 6) { | ||
| 125 | + throw new DeserializationException("Invalid address family: " + this.family); | ||
| 126 | + } else if (this.family == 6) { | ||
| 127 | + // Subtract -1 from ENC_UNICAST_IPv6 BYTE_LENGTH because we read one byte for family previously. | ||
| 128 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_UNICAST_IPV6_BYTE_LENGTH - 1); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + this.encType = bb.get(); | ||
| 132 | + if (this.family == 4) { | ||
| 133 | + this.addr = IpAddress.valueOf(bb.getInt()); | ||
| 134 | + } else if (this.family == 6) { | ||
| 135 | + this.addr = Ip6Address.valueOf(bb.array(), 2); | ||
| 136 | + } | ||
| 137 | + return this; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + /* | ||
| 141 | + * (non-Javadoc) | ||
| 142 | + * | ||
| 143 | + * @see java.lang.Object#hashCode() | ||
| 144 | + */ | ||
| 145 | + @Override | ||
| 146 | + public int hashCode() { | ||
| 147 | + final int prime = 2521; | ||
| 148 | + int result = super.hashCode(); | ||
| 149 | + result = prime * result + this.family; | ||
| 150 | + result = prime * result + this.encType; | ||
| 151 | + result = prime * result + this.addr.hashCode(); | ||
| 152 | + return result; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + /* | ||
| 156 | + * (non-Javadoc) | ||
| 157 | + * | ||
| 158 | + * @see java.lang.Object#hashCode() | ||
| 159 | + */ | ||
| 160 | + @Override | ||
| 161 | + public boolean equals(final Object obj) { | ||
| 162 | + if (this == obj) { | ||
| 163 | + return true; | ||
| 164 | + } | ||
| 165 | + if (!(obj instanceof PIMAddrUnicast)) { | ||
| 166 | + return false; | ||
| 167 | + } | ||
| 168 | + final PIMAddrUnicast other = (PIMAddrUnicast) obj; | ||
| 169 | + if (this.family != this.family) { | ||
| 170 | + return false; | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + if (this.encType != other.encType) { | ||
| 174 | + return false; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + if (!this.addr.equals(other.addr)) { | ||
| 178 | + return false; | ||
| 179 | + } | ||
| 180 | + return true; | ||
| 181 | + } | ||
| 182 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet.pim; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.BasePacket; | ||
| 19 | +import org.onlab.packet.Deserializer; | ||
| 20 | +import org.onlab.packet.IPacket; | ||
| 21 | +import org.onlab.packet.IpAddress; | ||
| 22 | + | ||
| 23 | +import java.nio.ByteBuffer; | ||
| 24 | +import java.util.Random; | ||
| 25 | + | ||
| 26 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 27 | + | ||
| 28 | +public class PIMHello extends BasePacket { | ||
| 29 | + | ||
| 30 | + private IpAddress nbrIpAddress; | ||
| 31 | + | ||
| 32 | + private int holdtime = 105; | ||
| 33 | + private int genid = 0; | ||
| 34 | + private int priority = 1; | ||
| 35 | + private boolean priorityPresent = false; | ||
| 36 | + | ||
| 37 | + public static final int MINIMUM_OPTION_LEN_BYTES = 4; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * PIM Option types. | ||
| 41 | + */ | ||
| 42 | + public enum Option { | ||
| 43 | + HOLDTIME (1, 2), | ||
| 44 | + PRUNEDELAY(2, 4), | ||
| 45 | + PRIORITY (19, 4), | ||
| 46 | + GENID (20, 4), | ||
| 47 | + ADDRLIST (24, 0); | ||
| 48 | + | ||
| 49 | + private final int optType; | ||
| 50 | + private final int optLen; | ||
| 51 | + | ||
| 52 | + Option(int ot, int ol) { | ||
| 53 | + this.optType = ot; | ||
| 54 | + this.optLen = ol; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + public int optType() { | ||
| 58 | + return this.optType; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public int optLen() { | ||
| 62 | + return this.optLen; | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * Add the holdtime to the packet. | ||
| 68 | + * | ||
| 69 | + * @param holdtime the holdtime in seconds | ||
| 70 | + */ | ||
| 71 | + public void addHoldtime(int holdtime) { | ||
| 72 | + this.holdtime = holdtime; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + /** | ||
| 76 | + * Add the hello priority. | ||
| 77 | + * | ||
| 78 | + * @param priority default is 1, the higher the better | ||
| 79 | + */ | ||
| 80 | + public void addPriority(int priority) { | ||
| 81 | + this.priority = priority; | ||
| 82 | + this.priorityPresent = true; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * Add a Gen ID. | ||
| 87 | + * | ||
| 88 | + * @param genid a random generated number, changes only after reset. | ||
| 89 | + */ | ||
| 90 | + public void addGenId(int genid) { | ||
| 91 | + if (genid == 0) { | ||
| 92 | + this.addGenId(); | ||
| 93 | + } else { | ||
| 94 | + this.genid = genid; | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * Add the genid. Let this function figure out the number. | ||
| 100 | + */ | ||
| 101 | + public void addGenId() { | ||
| 102 | + Random rand = new Random(); | ||
| 103 | + this.genid = rand.nextInt(); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * Sets all payloads parent packet if applicable, then serializes this | ||
| 108 | + * packet and all payloads. | ||
| 109 | + * | ||
| 110 | + * @return a byte[] containing this packet and payloads | ||
| 111 | + */ | ||
| 112 | + @Override | ||
| 113 | + public byte[] serialize() { | ||
| 114 | + | ||
| 115 | + // TODO: Figure out a better way to calculate buffer size | ||
| 116 | + int size = Option.PRIORITY.optLen() + 4 + | ||
| 117 | + Option.GENID.optLen() + 4 + | ||
| 118 | + Option.HOLDTIME.optLen() + 4; | ||
| 119 | + | ||
| 120 | + byte[] data = new byte[size]; // Come up with something better | ||
| 121 | + ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 122 | + | ||
| 123 | + // Add the priority | ||
| 124 | + bb.putShort((short) Option.PRIORITY.optType); | ||
| 125 | + bb.putShort((short) Option.PRIORITY.optLen); | ||
| 126 | + bb.putInt(this.priority); | ||
| 127 | + | ||
| 128 | + // Add the genid | ||
| 129 | + bb.putShort((short) Option.GENID.optType); | ||
| 130 | + bb.putShort((short) Option.GENID.optLen); | ||
| 131 | + bb.putInt(this.genid); | ||
| 132 | + | ||
| 133 | + // Add the holdtime | ||
| 134 | + bb.putShort((short) Option.HOLDTIME.optType); | ||
| 135 | + bb.putShort((short) Option.HOLDTIME.optLen); | ||
| 136 | + bb.putShort((short) this.holdtime); | ||
| 137 | + return data; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + /** | ||
| 141 | + * XXX: This is deprecated, DO NOT USE, use the deserializer() function instead. | ||
| 142 | + */ | ||
| 143 | + // @Override | ||
| 144 | + public IPacket deserialize(final byte[] data, final int offset, | ||
| 145 | + final int length) { | ||
| 146 | + // | ||
| 147 | + return null; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + /** | ||
| 151 | + * Deserialize this hello message. | ||
| 152 | + * | ||
| 153 | + * @return a deserialized hello message. | ||
| 154 | + */ | ||
| 155 | + public static Deserializer<PIMHello> deserializer() { | ||
| 156 | + return (data, offset, length) -> { | ||
| 157 | + checkInput(data, offset, length, MINIMUM_OPTION_LEN_BYTES); | ||
| 158 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 159 | + | ||
| 160 | + PIMHello hello = new PIMHello(); | ||
| 161 | + while (bb.hasRemaining()) { | ||
| 162 | + int optType = bb.getShort(); | ||
| 163 | + int optLen = bb.getShort(); | ||
| 164 | + | ||
| 165 | + // Check that we have enough buffer for the next option. | ||
| 166 | + checkInput(data, bb.position(), bb.limit() - bb.position(), optLen); | ||
| 167 | + if (optType == Option.GENID.optType) { | ||
| 168 | + hello.addGenId(bb.getInt()); | ||
| 169 | + } else if (optType == Option.PRIORITY.optType) { | ||
| 170 | + hello.addPriority(bb.getInt()); | ||
| 171 | + } else if (optType == Option.HOLDTIME.optType) { | ||
| 172 | + hello.addHoldtime((int) bb.getShort()); | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + return hello; | ||
| 177 | + }; | ||
| 178 | + } | ||
| 179 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet.pim; | ||
| 17 | + | ||
| 18 | +import org.onlab.packet.BasePacket; | ||
| 19 | +import org.onlab.packet.Deserializer; | ||
| 20 | +import org.onlab.packet.IPacket; | ||
| 21 | +import org.onlab.packet.IpPrefix; | ||
| 22 | + | ||
| 23 | +import java.nio.ByteBuffer; | ||
| 24 | +import java.util.HashMap; | ||
| 25 | + | ||
| 26 | +import static org.onlab.packet.PacketUtils.checkInput; | ||
| 27 | + | ||
| 28 | +public class PIMJoinPrune extends BasePacket { | ||
| 29 | + | ||
| 30 | + private PIMAddrUnicast upstreamAddr = new PIMAddrUnicast(); | ||
| 31 | + private short holdTime = (short) 0xffff; | ||
| 32 | + | ||
| 33 | + private class JoinPruneGroup { | ||
| 34 | + protected IpPrefix group; | ||
| 35 | + protected HashMap<IpPrefix, IpPrefix> joins = new HashMap<>(); | ||
| 36 | + protected HashMap<IpPrefix, IpPrefix> prunes = new HashMap<>(); | ||
| 37 | + | ||
| 38 | + public JoinPruneGroup(IpPrefix grp) { | ||
| 39 | + group = grp; | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + private HashMap<IpPrefix, JoinPruneGroup> joinPrunes = new HashMap<>(); | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * Get the J/P hold time. | ||
| 46 | + * | ||
| 47 | + * @return specified in seconds. | ||
| 48 | + */ | ||
| 49 | + public short getHoldTime() { | ||
| 50 | + return holdTime; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * Set the J/P holdtime in seconds. | ||
| 55 | + * | ||
| 56 | + * @param holdTime return the holdtime. | ||
| 57 | + */ | ||
| 58 | + public void setHoldTime(short holdTime) { | ||
| 59 | + this.holdTime = holdTime; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * Get the upstreamAddr for this J/P request. | ||
| 64 | + * | ||
| 65 | + * @return the upstream address. | ||
| 66 | + */ | ||
| 67 | + public PIMAddrUnicast getUpstreamAddr() { | ||
| 68 | + return upstreamAddr; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Set the upstream address of this PIM J/P request. | ||
| 73 | + * | ||
| 74 | + * @param upstr the PIM Upstream unicast address | ||
| 75 | + */ | ||
| 76 | + public void setUpstreamAddr(PIMAddrUnicast upstr) { | ||
| 77 | + this.upstreamAddr = upstr; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * Add the specified s,g to join field. | ||
| 82 | + * | ||
| 83 | + * @param saddr the source address of the route | ||
| 84 | + * @param gaddr the group address of the route | ||
| 85 | + * @param join true for a join, false for a prune. | ||
| 86 | + */ | ||
| 87 | + public void addJoinPrune(String saddr, String gaddr, boolean join) { | ||
| 88 | + IpPrefix gpfx = IpPrefix.valueOf(gaddr); | ||
| 89 | + IpPrefix spfx = IpPrefix.valueOf(saddr); | ||
| 90 | + addJoinPrune(spfx, gpfx, join); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * Add the specified S, G to the join field. | ||
| 95 | + * | ||
| 96 | + * @param spfx the source prefix of the route | ||
| 97 | + * @param gpfx the group prefix of the route | ||
| 98 | + * @param join true for join, false for prune | ||
| 99 | + */ | ||
| 100 | + public void addJoinPrune(IpPrefix spfx, IpPrefix gpfx, boolean join) { | ||
| 101 | + JoinPruneGroup jpg = joinPrunes.get(gpfx); | ||
| 102 | + if (jpg == null) { | ||
| 103 | + jpg = new JoinPruneGroup(gpfx); | ||
| 104 | + joinPrunes.put(gpfx, jpg); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + HashMap<IpPrefix, IpPrefix> members = (join) ? jpg.joins : jpg.prunes; | ||
| 108 | + if (members.get(spfx) == null) { | ||
| 109 | + members.put(spfx, spfx); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * Add a join given strings represending the source and group addresses. | ||
| 115 | + * | ||
| 116 | + * @param saddr source address | ||
| 117 | + * @param gaddr group address | ||
| 118 | + */ | ||
| 119 | + public void addJoin(String saddr, String gaddr) { | ||
| 120 | + this.addJoinPrune(saddr, gaddr, true); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * Add a prune given strings represending the source and group addresses. | ||
| 125 | + * | ||
| 126 | + * @param saddr source address | ||
| 127 | + * @param gaddr group address | ||
| 128 | + */ | ||
| 129 | + public void addPrune(String saddr, String gaddr) { | ||
| 130 | + this.addJoinPrune(saddr, gaddr, false); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * Sets all payloads parent packet if applicable, then serializes this | ||
| 135 | + * packet and all payloads. | ||
| 136 | + * | ||
| 137 | + * @return a byte[] containing this packet and payloads | ||
| 138 | + */ | ||
| 139 | + @Override | ||
| 140 | + public byte[] serialize() { | ||
| 141 | + | ||
| 142 | + byte[] data = new byte[8096]; // Come up with something better | ||
| 143 | + ByteBuffer bb = ByteBuffer.wrap(data); | ||
| 144 | + | ||
| 145 | + bb.put(upstreamAddr.serialize()); | ||
| 146 | + bb.put((byte) 0); // reserved | ||
| 147 | + | ||
| 148 | + int ngrps = joinPrunes.size(); | ||
| 149 | + bb.put((byte) ngrps); | ||
| 150 | + bb.putShort(this.holdTime); | ||
| 151 | + | ||
| 152 | + // Walk the group list and input all groups | ||
| 153 | + for (JoinPruneGroup jpg : joinPrunes.values()) { | ||
| 154 | + PIMAddrGroup grp = new PIMAddrGroup(jpg.group); | ||
| 155 | + bb.put(grp.serialize()); | ||
| 156 | + | ||
| 157 | + // put the number of joins and prunes | ||
| 158 | + bb.putShort((short) jpg.joins.size()); | ||
| 159 | + bb.putShort((short) jpg.prunes.size()); | ||
| 160 | + | ||
| 161 | + // Set all of the joins | ||
| 162 | + for (IpPrefix spfx : jpg.joins.values()) { | ||
| 163 | + PIMAddrSource src = new PIMAddrSource(spfx); | ||
| 164 | + bb.put(src.serialize()); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + // Set all of the prunes | ||
| 168 | + for (IpPrefix spfx : jpg.prunes.values()) { | ||
| 169 | + PIMAddrSource src = new PIMAddrSource(spfx); | ||
| 170 | + bb.put(src.serialize()); | ||
| 171 | + } | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + int len = bb.position(); | ||
| 175 | + byte[] data2 = new byte[len]; | ||
| 176 | + bb = ByteBuffer.wrap(data2, 0, len); | ||
| 177 | + bb.put(data, 0, len); | ||
| 178 | + return data2; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + // TODO: I suppose I really need to implement this? | ||
| 182 | + @Override | ||
| 183 | + public IPacket deserialize(final byte[] data, final int offset, | ||
| 184 | + final int length) { | ||
| 185 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 186 | + return this; | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + /** | ||
| 190 | + * Return the J/P deserializer function. | ||
| 191 | + * | ||
| 192 | + * @return a function that will deserialize a J/P message. | ||
| 193 | + */ | ||
| 194 | + public static Deserializer<PIMJoinPrune> deserializer() { | ||
| 195 | + return (data, offset, length) -> { | ||
| 196 | + | ||
| 197 | + /* | ||
| 198 | + * Delay buffer checks until we read enough of the packet to know how | ||
| 199 | + * much data we will require. Each encoded address deserializer function | ||
| 200 | + * will ensure there is enough data for that address. | ||
| 201 | + */ | ||
| 202 | + PIMJoinPrune jp = new PIMJoinPrune(); | ||
| 203 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
| 204 | + | ||
| 205 | + // We must get a PIM encoded unicast address | ||
| 206 | + PIMAddrUnicast upstream = new PIMAddrUnicast(); | ||
| 207 | + upstream.deserialize(bb); | ||
| 208 | + jp.setUpstreamAddr(upstream); | ||
| 209 | + | ||
| 210 | + // Use this boolean to determine the buffer space we need according to address sizes | ||
| 211 | + boolean ipv4 = upstream.getAddr().isIp4(); | ||
| 212 | + | ||
| 213 | + // We need at minimum 4 bytes for reserved(1), ngroups(1) & holdtime(2) | ||
| 214 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); | ||
| 215 | + | ||
| 216 | + // get and skip the reserved byte | ||
| 217 | + bb.get(); | ||
| 218 | + | ||
| 219 | + // Get the number of groups. | ||
| 220 | + int ngroups = bb.get(); | ||
| 221 | + | ||
| 222 | + // Save the holdtime. | ||
| 223 | + jp.setHoldTime(bb.getShort()); | ||
| 224 | + | ||
| 225 | + | ||
| 226 | + for (int i = 0; i < ngroups; i++) { | ||
| 227 | + PIMAddrGroup grp = new PIMAddrGroup(); | ||
| 228 | + | ||
| 229 | + /* | ||
| 230 | + * grp.deserialize will ensure the buffer has enough data to read the group address. | ||
| 231 | + */ | ||
| 232 | + grp.deserialize(bb); | ||
| 233 | + | ||
| 234 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); | ||
| 235 | + int njoins = bb.getShort(); | ||
| 236 | + int nprunes = bb.getShort(); | ||
| 237 | + | ||
| 238 | + /* | ||
| 239 | + * Now we'll verify we have enough buffer to read the next | ||
| 240 | + * group of join and prune addresses for this group. | ||
| 241 | + */ | ||
| 242 | + int required = (njoins + nprunes) * | ||
| 243 | + (ipv4 ? PIMAddrSource.ENC_SOURCE_IPV4_BYTE_LENGTH : PIMAddrSource.ENC_SOURCE_IPV6_BYTE_LENGTH); | ||
| 244 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), required); | ||
| 245 | + | ||
| 246 | + // Now iterate through the joins for this group | ||
| 247 | + for (; njoins > 0; njoins--) { | ||
| 248 | + | ||
| 249 | + PIMAddrSource src = new PIMAddrSource(); | ||
| 250 | + src.deserialize(bb); | ||
| 251 | + | ||
| 252 | + jp.addJoinPrune( | ||
| 253 | + src.getAddr().toIpPrefix(), | ||
| 254 | + grp.getAddr().toIpPrefix(), true); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + // Now iterate through the prunes for this group | ||
| 258 | + for (; nprunes > 0; nprunes--) { | ||
| 259 | + | ||
| 260 | + PIMAddrSource src = new PIMAddrSource(); | ||
| 261 | + src.deserialize(bb); | ||
| 262 | + jp.addJoinPrune( | ||
| 263 | + src.getAddr().toIpPrefix(), | ||
| 264 | + grp.getAddr().toIpPrefix(), false); | ||
| 265 | + } | ||
| 266 | + } | ||
| 267 | + | ||
| 268 | + return jp; | ||
| 269 | + }; | ||
| 270 | + } | ||
| 271 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Utilities for managing PIM packets. | ||
| 19 | + */ | ||
| 20 | +package org.onlab.packet.pim; | ||
| 21 | + |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onlab.packet; | ||
| 17 | + | ||
| 18 | +import org.junit.Before; | ||
| 19 | +import org.junit.Test; | ||
| 20 | +import org.onlab.packet.pim.PIMAddrUnicast; | ||
| 21 | +import org.onlab.packet.pim.PIMHello; | ||
| 22 | +import org.onlab.packet.pim.PIMJoinPrune; | ||
| 23 | + | ||
| 24 | +import static junit.framework.Assert.assertTrue; | ||
| 25 | + | ||
| 26 | +public final class PIMTest { | ||
| 27 | + | ||
| 28 | + public static final String SADDR = "10.2.1.2"; | ||
| 29 | + public static final String PIMADDR = "224.0.0.13"; | ||
| 30 | + public static final String PIMUADDR = "10.23.3.5"; | ||
| 31 | + | ||
| 32 | + public static final String SADDR1 = "10.1.1.1/32"; | ||
| 33 | + public static final String SADDR2 = "10.1.2.1/32"; | ||
| 34 | + public static final String GADDR1 = "232.1.1.1/32"; | ||
| 35 | + public static final String GADDR2 = "232.1.2.1/32"; | ||
| 36 | + | ||
| 37 | + public static final String CPSTR1 = "of:deadbeefball/8"; | ||
| 38 | + public static final String CPSTR2 = "of:deadbeefcafe/3"; | ||
| 39 | + public static final String CPSTR3 = "of:2badcafef00d/3"; | ||
| 40 | + | ||
| 41 | + private Deserializer<PIM> deserializer; | ||
| 42 | + | ||
| 43 | + private PIM pimHello; | ||
| 44 | + private PIMHello hello; | ||
| 45 | + | ||
| 46 | + private PIM pimJoinPrune; | ||
| 47 | + private PIMJoinPrune joinPrune; | ||
| 48 | + | ||
| 49 | + @Before | ||
| 50 | + public void setUp() throws Exception { | ||
| 51 | + | ||
| 52 | + // Create a PIM Hello | ||
| 53 | + pimHello = new PIM(); | ||
| 54 | + pimHello.setVersion((byte) 2); | ||
| 55 | + pimHello.setPIMType((byte) PIM.TYPE_HELLO); | ||
| 56 | + pimHello.setChecksum((short) 0); | ||
| 57 | + | ||
| 58 | + hello = new PIMHello(); | ||
| 59 | + hello.addHoldtime(0xd2); | ||
| 60 | + hello.addPriority(44); | ||
| 61 | + hello.addGenId(0xf00d); | ||
| 62 | + pimHello.setPayload(hello); | ||
| 63 | + hello.setParent(pimHello); | ||
| 64 | + | ||
| 65 | + // Create PIM Join Prune | ||
| 66 | + pimJoinPrune = new PIM(); | ||
| 67 | + pimJoinPrune.setVersion((byte) 2); | ||
| 68 | + pimJoinPrune.setPIMType((byte) PIM.TYPE_JOIN_PRUNE_REQUEST); | ||
| 69 | + pimJoinPrune.setChecksum((short) 0); | ||
| 70 | + | ||
| 71 | + joinPrune = new PIMJoinPrune(); | ||
| 72 | + joinPrune.setUpstreamAddr(new PIMAddrUnicast(SADDR)); | ||
| 73 | + joinPrune.addJoin(GADDR1, SADDR1); | ||
| 74 | + joinPrune.addJoin(GADDR2, SADDR2); | ||
| 75 | + joinPrune.addPrune(GADDR1, SADDR2); | ||
| 76 | + joinPrune.addPrune(GADDR2, SADDR1); | ||
| 77 | + | ||
| 78 | + pimJoinPrune.setPayload(joinPrune); | ||
| 79 | + joinPrune.setParent(pimJoinPrune); | ||
| 80 | + | ||
| 81 | + deserializer = PIM.deserializer(); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @Test | ||
| 85 | + public void testDerserializeBadInput() throws Exception { | ||
| 86 | + PacketTestUtils.testDeserializeBadInput(deserializer); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @Test | ||
| 90 | + public void testDeserializeTruncated() throws Exception { | ||
| 91 | + //byte [] bits = pimHello.serialize(); | ||
| 92 | + //PacketTestUtils.testDeserializeTruncated(deserializer, bits); | ||
| 93 | + | ||
| 94 | + byte [] bits = pimJoinPrune.serialize(); | ||
| 95 | + PacketTestUtils.testDeserializeTruncated(deserializer, bits); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + @Test | ||
| 99 | + public void testDeserializeHello() throws Exception { | ||
| 100 | + byte [] data = pimHello.serialize(); | ||
| 101 | + PIM pim = deserializer.deserialize(data, 0, data.length); | ||
| 102 | + assertTrue(pim.equals(pimHello)); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @Test | ||
| 106 | + public void testDeserializeJoinPrune() throws Exception { | ||
| 107 | + byte [] data = pimJoinPrune.serialize(); | ||
| 108 | + PIM pim = deserializer.deserialize(data, 0, data.length); | ||
| 109 | + assertTrue(pim.equals(pimJoinPrune)); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment