blob: 43f4f3821c6a48f7eb638d6412ba14cf46c57283 [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
Jian Li5fc14292015-12-04 11:30:46 -080025import static com.google.common.base.MoreObjects.toStringHelper;
Jonathan Hart2a655752015-04-07 16:46:33 -070026import static org.onlab.packet.PacketUtils.checkInput;
27
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080028/**
29 * Implements ICMPv6 Router Advertisement packet format. (RFC 4861)
30 */
31public class RouterAdvertisement extends BasePacket {
32 public static final byte HEADER_LENGTH = 12; // bytes
33
34 protected byte currentHopLimit;
35 protected byte mFlag;
36 protected byte oFlag;
37 protected short routerLifetime;
38 protected int reachableTime;
39 protected int retransmitTimer;
40
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080041 private final NeighborDiscoveryOptions options =
42 new NeighborDiscoveryOptions();
43
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080044 /**
45 * Gets current hop limit.
46 *
47 * @return the current hop limit
48 */
49 public byte getCurrentHopLimit() {
50 return this.currentHopLimit;
51 }
52
53 /**
54 * Sets current hop limit.
55 *
56 * @param currentHopLimit the current hop limit to set
57 * @return this
58 */
59 public RouterAdvertisement setCurrentHopLimit(final byte currentHopLimit) {
60 this.currentHopLimit = currentHopLimit;
61 return this;
62 }
63
64 /**
65 * Gets managed address configuration flag.
66 *
67 * @return the managed address configuration flag
68 */
69 public byte getMFlag() {
70 return this.mFlag;
71 }
72
73 /**
74 * Sets managed address configuration flag.
75 *
76 * @param mFlag the managed address configuration flag to set
77 * @return this
78 */
79 public RouterAdvertisement setMFlag(final byte mFlag) {
80 this.mFlag = mFlag;
81 return this;
82 }
83
84 /**
85 * Gets other configuration flag.
86 *
87 * @return the other configuration flag
88 */
89 public byte getOFlag() {
90 return this.oFlag;
91 }
92
93 /**
94 * Sets other configuration flag.
95 *
96 * @param oFlag the other configuration flag to set
97 * @return this
98 */
99 public RouterAdvertisement setOFlag(final byte oFlag) {
100 this.oFlag = oFlag;
101 return this;
102 }
103
104 /**
105 * Gets router lifetime.
106 *
107 * @return the router lifetime
108 */
109 public short getRouterLifetime() {
110 return this.routerLifetime;
111 }
112
113 /**
114 * Sets router lifetime.
115 *
116 * @param routerLifetime the router lifetime to set
117 * @return this
118 */
119 public RouterAdvertisement setRouterLifetime(final short routerLifetime) {
120 this.routerLifetime = routerLifetime;
121 return this;
122 }
123
124 /**
125 * Gets reachable time.
126 *
127 * @return the reachable time
128 */
129 public int getReachableTime() {
130 return this.reachableTime;
131 }
132
133 /**
134 * Sets reachable time.
135 *
136 * @param reachableTime the reachable time to set
137 * @return this
138 */
139 public RouterAdvertisement setReachableTime(final int reachableTime) {
140 this.reachableTime = reachableTime;
141 return this;
142 }
143
144 /**
145 * Gets retransmission timer.
146 *
147 * @return the retransmission timer
148 */
149 public int getRetransmitTimer() {
150 return this.retransmitTimer;
151 }
152
153 /**
154 * Sets retransmission timer.
155 *
156 * @param retransmitTimer the retransmission timer to set
157 * @return this
158 */
159 public RouterAdvertisement setRetransmitTimer(final int retransmitTimer) {
160 this.retransmitTimer = retransmitTimer;
161 return this;
162 }
163
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800164 /**
165 * Gets the Neighbor Discovery Protocol packet options.
166 *
167 * @return the Neighbor Discovery Protocol packet options
168 */
169 public List<NeighborDiscoveryOptions.Option> getOptions() {
170 return this.options.options();
171 }
172
173 /**
174 * Adds a Neighbor Discovery Protocol packet option.
175 *
176 * @param type the option type
177 * @param data the option data
178 * @return this
179 */
180 public RouterAdvertisement addOption(final byte type, final byte[] data) {
181 this.options.addOption(type, data);
182 return this;
183 }
184
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800185 @Override
186 public byte[] serialize() {
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800187 byte[] optionsData = null;
188 if (this.options.hasOptions()) {
189 optionsData = this.options.serialize();
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800190 }
191
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800192 int optionsLength = 0;
193 if (optionsData != null) {
194 optionsLength = optionsData.length;
Charles M.C. Chan5c0b4762015-01-10 18:38:37 +0800195 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800196
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800197 final byte[] data = new byte[HEADER_LENGTH + optionsLength];
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800198 final ByteBuffer bb = ByteBuffer.wrap(data);
199
200 bb.put(this.currentHopLimit);
201 bb.put((byte) ((this.mFlag & 0x1) << 7 | (this.oFlag & 0x1) << 6));
202 bb.putShort(routerLifetime);
203 bb.putInt(reachableTime);
204 bb.putInt(retransmitTimer);
205
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800206 if (optionsData != null) {
207 bb.put(optionsData);
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800208 }
209
210 return data;
211 }
212
213 @Override
214 public IPacket deserialize(byte[] data, int offset, int length) {
215 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
216 int bscratch;
217
218 this.currentHopLimit = bb.get();
219 bscratch = bb.get();
220 this.mFlag = (byte) ((bscratch >> 7) & 0x1);
221 this.oFlag = (byte) ((bscratch >> 6) & 0x1);
222 this.routerLifetime = bb.getShort();
223 this.reachableTime = bb.getInt();
224 this.retransmitTimer = bb.getInt();
225
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800226 this.options.deserialize(data, bb.position(),
227 bb.limit() - bb.position());
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800228
229 return this;
230 }
231
232 /*
233 * (non-Javadoc)
234 *
235 * @see java.lang.Object#hashCode()
236 */
237 @Override
238 public int hashCode() {
239 final int prime = 5807;
240 int result = super.hashCode();
241 result = prime * result + this.currentHopLimit;
242 result = prime * result + this.mFlag;
243 result = prime * result + this.oFlag;
244 result = prime * result + this.routerLifetime;
245 result = prime * result + this.reachableTime;
246 result = prime * result + this.retransmitTimer;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800247 result = prime * result + this.options.hashCode();
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800248 return result;
249 }
250
251 /*
252 * (non-Javadoc)
253 *
254 * @see java.lang.Object#equals(java.lang.Object)
255 */
256 @Override
257 public boolean equals(final Object obj) {
258 if (this == obj) {
259 return true;
260 }
261 if (!super.equals(obj)) {
262 return false;
263 }
264 if (!(obj instanceof RouterAdvertisement)) {
265 return false;
266 }
267 final RouterAdvertisement other = (RouterAdvertisement) obj;
268 if (this.currentHopLimit != other.currentHopLimit) {
269 return false;
270 }
271 if (this.mFlag != other.mFlag) {
272 return false;
273 }
274 if (this.oFlag != other.oFlag) {
275 return false;
276 }
277 if (this.routerLifetime != other.routerLifetime) {
278 return false;
279 }
280 if (this.reachableTime != other.reachableTime) {
281 return false;
282 }
283 if (this.retransmitTimer != other.retransmitTimer) {
284 return false;
285 }
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800286 if (!this.options.equals(other.options)) {
287 return false;
288 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800289 return true;
290 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700291
292 /**
293 * Deserializer function for router advertisement packets.
294 *
295 * @return deserializer function
296 */
297 public static Deserializer<RouterAdvertisement> deserializer() {
298 return (data, offset, length) -> {
299 checkInput(data, offset, length, HEADER_LENGTH);
300
301 RouterAdvertisement routerAdvertisement = new RouterAdvertisement();
302
303 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
304 int bscratch;
305
306 routerAdvertisement.currentHopLimit = bb.get();
307 bscratch = bb.get();
308 routerAdvertisement.mFlag = (byte) ((bscratch >> 7) & 0x1);
309 routerAdvertisement.oFlag = (byte) ((bscratch >> 6) & 0x1);
310 routerAdvertisement.routerLifetime = bb.getShort();
311 routerAdvertisement.reachableTime = bb.getInt();
312 routerAdvertisement.retransmitTimer = bb.getInt();
313
Charles Chan3599d632015-09-05 14:47:51 +0800314 if (bb.limit() - bb.position() > 0) {
315 NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
316 .deserialize(data, bb.position(), bb.limit() - bb.position());
Jonathan Hart2a655752015-04-07 16:46:33 -0700317
Charles Chan3599d632015-09-05 14:47:51 +0800318 for (NeighborDiscoveryOptions.Option option : options.options()) {
319 routerAdvertisement.addOption(option.type(), option.data());
320 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700321 }
322
323 return routerAdvertisement;
324 };
325 }
Jian Li5fc14292015-12-04 11:30:46 -0800326
327 @Override
328 public String toString() {
329 return toStringHelper(getClass())
330 .add("currentHopLimit", Byte.toString(currentHopLimit))
331 .add("mFlag", Byte.toString(mFlag))
332 .add("oFlag", Byte.toString(oFlag))
333 .add("routerLifetime", Short.toString(routerLifetime))
334 .add("reachableTime", Integer.toString(reachableTime))
335 .add("retransmitTimer", Integer.toString(retransmitTimer))
336 .toString();
337 // TODO: need to handle optionis
338 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800339}