blob: 891a0193972eb7ad4bee0966e6d1e78802e33ca4 [file] [log] [blame]
Rusty Eddy80f12522015-09-03 22:42:02 +00001/*
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 */
16package org.onlab.packet.pim;
17
18import org.onlab.packet.DeserializationException;
19import org.onlab.packet.Ip4Address;
20import org.onlab.packet.IpAddress;
21import org.onlab.packet.IpPrefix;
22import org.onlab.packet.Ip6Address;
23
24import java.nio.ByteBuffer;
25
26import static org.onlab.packet.PacketUtils.checkInput;
27
28public 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 *
Thomas Vachuskab9c7ea62015-09-10 15:17:02 -070081 * @param pfx address prefix
Rusty Eddy80f12522015-09-03 22:42:02 +000082 */
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 *
Thomas Vachuskab9c7ea62015-09-10 15:17:02 -0700148 * @return the serialized address in a buffer
Rusty Eddy80f12522015-09-03 22:42:02 +0000149 */
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
Thomas Vachuskab9c7ea62015-09-10 15:17:02 -0700171 * @return an encoded PIM group address
172 * @throws DeserializationException if unable to deserialize the packet data
Rusty Eddy80f12522015-09-03 22:42:02 +0000173 */
174 public PIMAddrGroup deserialize(ByteBuffer bb) throws DeserializationException {
175
176 /*
177 * We need to verify that we have enough buffer space. First we'll assume that
178 * we are decoding an IPv4 address. After we read the first by (address family),
179 * we'll determine if we actually need more buffer space for an IPv6 address.
180 */
181 checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV4_BYTE_LENGTH);
182
183 this.family = bb.get();
184 if (family != 4 && family != 6) {
185 throw new DeserializationException("Illegal IP version number: " + family + "\n");
186 } else if (family == 6) {
187
188 // Check for one less by since we have already read the first byte of the packet.
189 checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), ENC_GROUP_IPV6_BYTE_LENGTH - 1);
190 }
191
192 this.encType = bb.get();
193 this.reserved = bb.get();
194 if ((this.reserved & 0x80) != 0) {
195 this.bBit = true;
196 }
197 if ((this.reserved & 0x01) != 0) {
198 this.zBit = true;
199 }
200 // Remove the z and b bits from reserved
201 this.reserved |= 0x7d;
202
203 this.masklen = bb.get();
204 if (this.family == 4) {
205 this.addr = IpAddress.valueOf(bb.getInt());
206 } else if (this.family == 6) {
207 this.addr = Ip6Address.valueOf(bb.array(), 2);
208 }
209 return this;
210 }
211
212 /*
213 * (non-Javadoc)
214 *
215 * @see java.lang.Object#hashCode()
216 */
217 @Override
218 public int hashCode() {
219 final int prime = 2521;
220 int result = super.hashCode();
221 result = prime * result + this.family;
222 result = prime * result + this.encType;
223 result = prime * result + this.reserved;
224 result = prime * result + this.masklen;
225 result = prime * result + this.addr.hashCode();
226 return result;
227 }
228
229
230 /*
231 * (non-Javadoc)
232 *
233 * @see java.lang.Object#equals()
234 */
235 @Override
236 public boolean equals(final Object obj) {
237 if (this == obj) {
238 return true;
239 }
240 if (!(obj instanceof PIMAddrGroup)) {
241 return false;
242 }
243 final PIMAddrGroup other = (PIMAddrGroup) obj;
244 if (this.family != this.family) {
245 return false;
246 }
247
248 if (this.encType != other.encType) {
249 return false;
250 }
251
252 if (!this.addr.equals(other.addr)) {
253 return false;
254 }
255 return true;
256 }
257}