blob: e4ef2c6ad75a7c3f2b2bad638af94f53c4de5b03 [file] [log] [blame]
Charles M.C. Chanea5aa472015-01-03 13:40:39 +08001/*
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -08002 * Copyright 2014-2015 Open Networking Laboratory
Charles M.C. Chanea5aa472015-01-03 13:40:39 +08003 *
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 */
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080016package org.onlab.packet.ndp;
17
18import org.onlab.packet.BasePacket;
Jonathan Hart2a655752015-04-07 16:46:33 -070019import org.onlab.packet.Deserializer;
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080020import org.onlab.packet.IPacket;
21
22import java.nio.ByteBuffer;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080023import java.util.List;
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080024
Jonathan Hart2a655752015-04-07 16:46:33 -070025import static org.onlab.packet.PacketUtils.checkInput;
26
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080027/**
28 * Implements ICMPv6 Router Advertisement packet format. (RFC 4861)
29 */
30public class RouterAdvertisement extends BasePacket {
31 public static final byte HEADER_LENGTH = 12; // bytes
32
33 protected byte currentHopLimit;
34 protected byte mFlag;
35 protected byte oFlag;
36 protected short routerLifetime;
37 protected int reachableTime;
38 protected int retransmitTimer;
39
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080040 private final NeighborDiscoveryOptions options =
41 new NeighborDiscoveryOptions();
42
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080043 /**
44 * Gets current hop limit.
45 *
46 * @return the current hop limit
47 */
48 public byte getCurrentHopLimit() {
49 return this.currentHopLimit;
50 }
51
52 /**
53 * Sets current hop limit.
54 *
55 * @param currentHopLimit the current hop limit to set
56 * @return this
57 */
58 public RouterAdvertisement setCurrentHopLimit(final byte currentHopLimit) {
59 this.currentHopLimit = currentHopLimit;
60 return this;
61 }
62
63 /**
64 * Gets managed address configuration flag.
65 *
66 * @return the managed address configuration flag
67 */
68 public byte getMFlag() {
69 return this.mFlag;
70 }
71
72 /**
73 * Sets managed address configuration flag.
74 *
75 * @param mFlag the managed address configuration flag to set
76 * @return this
77 */
78 public RouterAdvertisement setMFlag(final byte mFlag) {
79 this.mFlag = mFlag;
80 return this;
81 }
82
83 /**
84 * Gets other configuration flag.
85 *
86 * @return the other configuration flag
87 */
88 public byte getOFlag() {
89 return this.oFlag;
90 }
91
92 /**
93 * Sets other configuration flag.
94 *
95 * @param oFlag the other configuration flag to set
96 * @return this
97 */
98 public RouterAdvertisement setOFlag(final byte oFlag) {
99 this.oFlag = oFlag;
100 return this;
101 }
102
103 /**
104 * Gets router lifetime.
105 *
106 * @return the router lifetime
107 */
108 public short getRouterLifetime() {
109 return this.routerLifetime;
110 }
111
112 /**
113 * Sets router lifetime.
114 *
115 * @param routerLifetime the router lifetime to set
116 * @return this
117 */
118 public RouterAdvertisement setRouterLifetime(final short routerLifetime) {
119 this.routerLifetime = routerLifetime;
120 return this;
121 }
122
123 /**
124 * Gets reachable time.
125 *
126 * @return the reachable time
127 */
128 public int getReachableTime() {
129 return this.reachableTime;
130 }
131
132 /**
133 * Sets reachable time.
134 *
135 * @param reachableTime the reachable time to set
136 * @return this
137 */
138 public RouterAdvertisement setReachableTime(final int reachableTime) {
139 this.reachableTime = reachableTime;
140 return this;
141 }
142
143 /**
144 * Gets retransmission timer.
145 *
146 * @return the retransmission timer
147 */
148 public int getRetransmitTimer() {
149 return this.retransmitTimer;
150 }
151
152 /**
153 * Sets retransmission timer.
154 *
155 * @param retransmitTimer the retransmission timer to set
156 * @return this
157 */
158 public RouterAdvertisement setRetransmitTimer(final int retransmitTimer) {
159 this.retransmitTimer = retransmitTimer;
160 return this;
161 }
162
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800163 /**
164 * Gets the Neighbor Discovery Protocol packet options.
165 *
166 * @return the Neighbor Discovery Protocol packet options
167 */
168 public List<NeighborDiscoveryOptions.Option> getOptions() {
169 return this.options.options();
170 }
171
172 /**
173 * Adds a Neighbor Discovery Protocol packet option.
174 *
175 * @param type the option type
176 * @param data the option data
177 * @return this
178 */
179 public RouterAdvertisement addOption(final byte type, final byte[] data) {
180 this.options.addOption(type, data);
181 return this;
182 }
183
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800184 @Override
185 public byte[] serialize() {
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800186 byte[] optionsData = null;
187 if (this.options.hasOptions()) {
188 optionsData = this.options.serialize();
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800189 }
190
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800191 int optionsLength = 0;
192 if (optionsData != null) {
193 optionsLength = optionsData.length;
Charles M.C. Chan5c0b4762015-01-10 18:38:37 +0800194 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800195
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800196 final byte[] data = new byte[HEADER_LENGTH + optionsLength];
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800197 final ByteBuffer bb = ByteBuffer.wrap(data);
198
199 bb.put(this.currentHopLimit);
200 bb.put((byte) ((this.mFlag & 0x1) << 7 | (this.oFlag & 0x1) << 6));
201 bb.putShort(routerLifetime);
202 bb.putInt(reachableTime);
203 bb.putInt(retransmitTimer);
204
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800205 if (optionsData != null) {
206 bb.put(optionsData);
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800207 }
208
209 return data;
210 }
211
212 @Override
213 public IPacket deserialize(byte[] data, int offset, int length) {
214 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
215 int bscratch;
216
217 this.currentHopLimit = bb.get();
218 bscratch = bb.get();
219 this.mFlag = (byte) ((bscratch >> 7) & 0x1);
220 this.oFlag = (byte) ((bscratch >> 6) & 0x1);
221 this.routerLifetime = bb.getShort();
222 this.reachableTime = bb.getInt();
223 this.retransmitTimer = bb.getInt();
224
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800225 this.options.deserialize(data, bb.position(),
226 bb.limit() - bb.position());
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800227
228 return this;
229 }
230
231 /*
232 * (non-Javadoc)
233 *
234 * @see java.lang.Object#hashCode()
235 */
236 @Override
237 public int hashCode() {
238 final int prime = 5807;
239 int result = super.hashCode();
240 result = prime * result + this.currentHopLimit;
241 result = prime * result + this.mFlag;
242 result = prime * result + this.oFlag;
243 result = prime * result + this.routerLifetime;
244 result = prime * result + this.reachableTime;
245 result = prime * result + this.retransmitTimer;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800246 result = prime * result + this.options.hashCode();
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800247 return result;
248 }
249
250 /*
251 * (non-Javadoc)
252 *
253 * @see java.lang.Object#equals(java.lang.Object)
254 */
255 @Override
256 public boolean equals(final Object obj) {
257 if (this == obj) {
258 return true;
259 }
260 if (!super.equals(obj)) {
261 return false;
262 }
263 if (!(obj instanceof RouterAdvertisement)) {
264 return false;
265 }
266 final RouterAdvertisement other = (RouterAdvertisement) obj;
267 if (this.currentHopLimit != other.currentHopLimit) {
268 return false;
269 }
270 if (this.mFlag != other.mFlag) {
271 return false;
272 }
273 if (this.oFlag != other.oFlag) {
274 return false;
275 }
276 if (this.routerLifetime != other.routerLifetime) {
277 return false;
278 }
279 if (this.reachableTime != other.reachableTime) {
280 return false;
281 }
282 if (this.retransmitTimer != other.retransmitTimer) {
283 return false;
284 }
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800285 if (!this.options.equals(other.options)) {
286 return false;
287 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800288 return true;
289 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700290
291 /**
292 * Deserializer function for router advertisement packets.
293 *
294 * @return deserializer function
295 */
296 public static Deserializer<RouterAdvertisement> deserializer() {
297 return (data, offset, length) -> {
298 checkInput(data, offset, length, HEADER_LENGTH);
299
300 RouterAdvertisement routerAdvertisement = new RouterAdvertisement();
301
302 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
303 int bscratch;
304
305 routerAdvertisement.currentHopLimit = bb.get();
306 bscratch = bb.get();
307 routerAdvertisement.mFlag = (byte) ((bscratch >> 7) & 0x1);
308 routerAdvertisement.oFlag = (byte) ((bscratch >> 6) & 0x1);
309 routerAdvertisement.routerLifetime = bb.getShort();
310 routerAdvertisement.reachableTime = bb.getInt();
311 routerAdvertisement.retransmitTimer = bb.getInt();
312
313 NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
314 .deserialize(data, bb.position(), bb.limit() - bb.position());
315
316 for (NeighborDiscoveryOptions.Option option : options.options()) {
317 routerAdvertisement.addOption(option.type(), option.data());
318 }
319
320 return routerAdvertisement;
321 };
322 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800323}