Rusty Eddy
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
...@@ -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