blob: bd0f8a062240bb4cd9175a084c277f99c591273a [file] [log] [blame]
Charles M.C. Chanea5aa472015-01-03 13:40:39 +08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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 +080020
21import java.nio.ByteBuffer;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080022import java.util.List;
Charles M.C. Chanea5aa472015-01-03 13:40:39 +080023
Jian Li5fc14292015-12-04 11:30:46 -080024import static com.google.common.base.MoreObjects.toStringHelper;
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
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800212
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800213
214 /*
215 * (non-Javadoc)
216 *
217 * @see java.lang.Object#hashCode()
218 */
219 @Override
220 public int hashCode() {
221 final int prime = 5807;
222 int result = super.hashCode();
223 result = prime * result + this.currentHopLimit;
224 result = prime * result + this.mFlag;
225 result = prime * result + this.oFlag;
226 result = prime * result + this.routerLifetime;
227 result = prime * result + this.reachableTime;
228 result = prime * result + this.retransmitTimer;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800229 result = prime * result + this.options.hashCode();
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800230 return result;
231 }
232
233 /*
234 * (non-Javadoc)
235 *
236 * @see java.lang.Object#equals(java.lang.Object)
237 */
238 @Override
239 public boolean equals(final Object obj) {
240 if (this == obj) {
241 return true;
242 }
243 if (!super.equals(obj)) {
244 return false;
245 }
246 if (!(obj instanceof RouterAdvertisement)) {
247 return false;
248 }
249 final RouterAdvertisement other = (RouterAdvertisement) obj;
250 if (this.currentHopLimit != other.currentHopLimit) {
251 return false;
252 }
253 if (this.mFlag != other.mFlag) {
254 return false;
255 }
256 if (this.oFlag != other.oFlag) {
257 return false;
258 }
259 if (this.routerLifetime != other.routerLifetime) {
260 return false;
261 }
262 if (this.reachableTime != other.reachableTime) {
263 return false;
264 }
265 if (this.retransmitTimer != other.retransmitTimer) {
266 return false;
267 }
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800268 if (!this.options.equals(other.options)) {
269 return false;
270 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800271 return true;
272 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700273
274 /**
275 * Deserializer function for router advertisement packets.
276 *
277 * @return deserializer function
278 */
279 public static Deserializer<RouterAdvertisement> deserializer() {
280 return (data, offset, length) -> {
281 checkInput(data, offset, length, HEADER_LENGTH);
282
283 RouterAdvertisement routerAdvertisement = new RouterAdvertisement();
284
285 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
286 int bscratch;
287
288 routerAdvertisement.currentHopLimit = bb.get();
289 bscratch = bb.get();
290 routerAdvertisement.mFlag = (byte) ((bscratch >> 7) & 0x1);
291 routerAdvertisement.oFlag = (byte) ((bscratch >> 6) & 0x1);
292 routerAdvertisement.routerLifetime = bb.getShort();
293 routerAdvertisement.reachableTime = bb.getInt();
294 routerAdvertisement.retransmitTimer = bb.getInt();
295
Charles Chan3599d632015-09-05 14:47:51 +0800296 if (bb.limit() - bb.position() > 0) {
297 NeighborDiscoveryOptions options = NeighborDiscoveryOptions.deserializer()
298 .deserialize(data, bb.position(), bb.limit() - bb.position());
Jonathan Hart2a655752015-04-07 16:46:33 -0700299
Charles Chan3599d632015-09-05 14:47:51 +0800300 for (NeighborDiscoveryOptions.Option option : options.options()) {
301 routerAdvertisement.addOption(option.type(), option.data());
302 }
Jonathan Hart2a655752015-04-07 16:46:33 -0700303 }
304
305 return routerAdvertisement;
306 };
307 }
Jian Li5fc14292015-12-04 11:30:46 -0800308
309 @Override
310 public String toString() {
311 return toStringHelper(getClass())
312 .add("currentHopLimit", Byte.toString(currentHopLimit))
313 .add("mFlag", Byte.toString(mFlag))
314 .add("oFlag", Byte.toString(oFlag))
315 .add("routerLifetime", Short.toString(routerLifetime))
316 .add("reachableTime", Integer.toString(reachableTime))
317 .add("retransmitTimer", Integer.toString(retransmitTimer))
318 .toString();
319 // TODO: need to handle optionis
320 }
Charles M.C. Chanea5aa472015-01-03 13:40:39 +0800321}