Implemented a mechanism to easily add and access Neighbor Discovery protocol
packet options. Fixes ONOS-1011 Change-Id: I94daa3f3c1297fb9a7b44901927738a29aff030a
Showing
12 changed files
with
628 additions
and
217 deletions
... | @@ -25,7 +25,6 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -25,7 +25,6 @@ import org.apache.felix.scr.annotations.Reference; |
25 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 25 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | import org.apache.felix.scr.annotations.Service; | 26 | import org.apache.felix.scr.annotations.Service; |
27 | import org.onlab.packet.ARP; | 27 | import org.onlab.packet.ARP; |
28 | -import org.onlab.packet.Data; | ||
29 | import org.onlab.packet.Ethernet; | 28 | import org.onlab.packet.Ethernet; |
30 | import org.onlab.packet.ICMP6; | 29 | import org.onlab.packet.ICMP6; |
31 | import org.onlab.packet.IPv6; | 30 | import org.onlab.packet.IPv6; |
... | @@ -35,6 +34,7 @@ import org.onlab.packet.IpAddress; | ... | @@ -35,6 +34,7 @@ import org.onlab.packet.IpAddress; |
35 | import org.onlab.packet.MacAddress; | 34 | import org.onlab.packet.MacAddress; |
36 | import org.onlab.packet.VlanId; | 35 | import org.onlab.packet.VlanId; |
37 | import org.onlab.packet.ndp.NeighborAdvertisement; | 36 | import org.onlab.packet.ndp.NeighborAdvertisement; |
37 | +import org.onlab.packet.ndp.NeighborDiscoveryOptions; | ||
38 | import org.onlab.packet.ndp.NeighborSolicitation; | 38 | import org.onlab.packet.ndp.NeighborSolicitation; |
39 | import org.onosproject.net.ConnectPoint; | 39 | import org.onosproject.net.ConnectPoint; |
40 | import org.onosproject.net.Device; | 40 | import org.onosproject.net.Device; |
... | @@ -548,21 +548,10 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -548,21 +548,10 @@ public class ProxyArpManager implements ProxyArpService { |
548 | nadv.setTargetAddress(srcIp.toOctets()); | 548 | nadv.setTargetAddress(srcIp.toOctets()); |
549 | nadv.setSolicitedFlag((byte) 1); | 549 | nadv.setSolicitedFlag((byte) 1); |
550 | nadv.setOverrideFlag((byte) 1); | 550 | nadv.setOverrideFlag((byte) 1); |
551 | - byte[] nadvData = | 551 | + nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
552 | - new byte[NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS]; | 552 | + srcMac.toBytes()); |
553 | - ByteBuffer bbNadv = ByteBuffer.wrap(nadvData); | ||
554 | - byte nadvOptionType = | ||
555 | - NeighborAdvertisement.OPTION_TYPE_TARGET_LL_ADDRESS; | ||
556 | - // The Option length in 8-octets units | ||
557 | - byte nadvOptionLength = | ||
558 | - (NeighborAdvertisement.OPTION_LENGTH_IEEE802_ADDRESS + 7) / 8; | ||
559 | - bbNadv.put(nadvOptionType); | ||
560 | - bbNadv.put(nadvOptionLength); | ||
561 | - bbNadv.put(srcMac.toBytes()); | ||
562 | - Data nadvPayload = new Data(); | ||
563 | - nadv.setPayload(nadvPayload.deserialize(nadvData, 0, nadvData.length)); | ||
564 | - icmp6.setPayload(nadv); | ||
565 | 553 | ||
554 | + icmp6.setPayload(nadv); | ||
566 | ipv6.setPayload(icmp6); | 555 | ipv6.setPayload(icmp6); |
567 | eth.setPayload(ipv6); | 556 | eth.setPayload(ipv6); |
568 | return eth; | 557 | return eth; | ... | ... |
... | @@ -16,30 +16,27 @@ | ... | @@ -16,30 +16,27 @@ |
16 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
17 | 17 | ||
18 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
19 | -import org.onlab.packet.Data; | ||
20 | import org.onlab.packet.IPacket; | 19 | import org.onlab.packet.IPacket; |
21 | import org.onlab.packet.Ip6Address; | 20 | import org.onlab.packet.Ip6Address; |
22 | 21 | ||
23 | import java.nio.ByteBuffer; | 22 | import java.nio.ByteBuffer; |
24 | import java.util.Arrays; | 23 | import java.util.Arrays; |
24 | +import java.util.List; | ||
25 | 25 | ||
26 | /** | 26 | /** |
27 | * Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861). | 27 | * Implements ICMPv6 Neighbor Advertisement packet format (RFC 4861). |
28 | */ | 28 | */ |
29 | public class NeighborAdvertisement extends BasePacket { | 29 | public class NeighborAdvertisement extends BasePacket { |
30 | public static final byte HEADER_LENGTH = 20; // bytes | 30 | public static final byte HEADER_LENGTH = 20; // bytes |
31 | - public static final byte OPTION_TYPE_SOURCE_LL_ADDRESS = 1; | ||
32 | - public static final byte OPTION_TYPE_TARGET_LL_ADDRESS = 2; | ||
33 | - public static final byte OPTION_TYPE_PREFIX_INFORMATION = 3; | ||
34 | - public static final byte OPTION_TYPE_REDIRECTED_HEADER = 4; | ||
35 | - public static final byte OPTION_TYPE_MTU = 5; | ||
36 | - public static final byte OPTION_LENGTH_IEEE802_ADDRESS = 8; | ||
37 | 31 | ||
38 | protected byte routerFlag; | 32 | protected byte routerFlag; |
39 | protected byte solicitedFlag; | 33 | protected byte solicitedFlag; |
40 | protected byte overrideFlag; | 34 | protected byte overrideFlag; |
41 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; | 35 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; |
42 | 36 | ||
37 | + private final NeighborDiscoveryOptions options = | ||
38 | + new NeighborDiscoveryOptions(); | ||
39 | + | ||
43 | /** | 40 | /** |
44 | * Gets router flag. | 41 | * Gets router flag. |
45 | * | 42 | * |
... | @@ -116,30 +113,54 @@ public class NeighborAdvertisement extends BasePacket { | ... | @@ -116,30 +113,54 @@ public class NeighborAdvertisement extends BasePacket { |
116 | * @return this | 113 | * @return this |
117 | */ | 114 | */ |
118 | public NeighborAdvertisement setTargetAddress(final byte[] targetAddress) { | 115 | public NeighborAdvertisement setTargetAddress(final byte[] targetAddress) { |
119 | - this.targetAddress = Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | 116 | + this.targetAddress = |
117 | + Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | ||
118 | + return this; | ||
119 | + } | ||
120 | + | ||
121 | + /** | ||
122 | + * Gets the Neighbor Discovery Protocol packet options. | ||
123 | + * | ||
124 | + * @return the Neighbor Discovery Protocol packet options | ||
125 | + */ | ||
126 | + public List<NeighborDiscoveryOptions.Option> getOptions() { | ||
127 | + return this.options.options(); | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * Adds a Neighbor Discovery Protocol packet option. | ||
132 | + * | ||
133 | + * @param type the option type | ||
134 | + * @param data the option data | ||
135 | + * @return this | ||
136 | + */ | ||
137 | + public NeighborAdvertisement addOption(final byte type, | ||
138 | + final byte[] data) { | ||
139 | + this.options.addOption(type, data); | ||
120 | return this; | 140 | return this; |
121 | } | 141 | } |
122 | 142 | ||
123 | @Override | 143 | @Override |
124 | public byte[] serialize() { | 144 | public byte[] serialize() { |
125 | - byte[] payloadData = null; | 145 | + byte[] optionsData = null; |
126 | - if (this.payload != null) { | 146 | + if (this.options.hasOptions()) { |
127 | - this.payload.setParent(this); | 147 | + optionsData = this.options.serialize(); |
128 | - payloadData = this.payload.serialize(); | ||
129 | } | 148 | } |
130 | 149 | ||
131 | - int payloadLength = 0; | 150 | + int optionsLength = 0; |
132 | - if (payloadData != null) { | 151 | + if (optionsData != null) { |
133 | - payloadLength = payloadData.length; | 152 | + optionsLength = optionsData.length; |
134 | } | 153 | } |
135 | 154 | ||
136 | - final byte[] data = new byte[HEADER_LENGTH + payloadLength]; | 155 | + final byte[] data = new byte[HEADER_LENGTH + optionsLength]; |
137 | final ByteBuffer bb = ByteBuffer.wrap(data); | 156 | final ByteBuffer bb = ByteBuffer.wrap(data); |
138 | 157 | ||
139 | - bb.putInt((this.routerFlag & 0x1) << 31 | (this.solicitedFlag & 0x1) << 30 | (this.overrideFlag & 0x1) << 29); | 158 | + bb.putInt((this.routerFlag & 0x1) << 31 | |
159 | + (this.solicitedFlag & 0x1) << 30 | | ||
160 | + (this.overrideFlag & 0x1) << 29); | ||
140 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 161 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
141 | - if (payloadData != null) { | 162 | + if (optionsData != null) { |
142 | - bb.put(payloadData); | 163 | + bb.put(optionsData); |
143 | } | 164 | } |
144 | 165 | ||
145 | return data; | 166 | return data; |
... | @@ -156,10 +177,8 @@ public class NeighborAdvertisement extends BasePacket { | ... | @@ -156,10 +177,8 @@ public class NeighborAdvertisement extends BasePacket { |
156 | this.overrideFlag = (byte) (iscratch >> 29 & 0x1); | 177 | this.overrideFlag = (byte) (iscratch >> 29 & 0x1); |
157 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 178 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
158 | 179 | ||
159 | - this.payload = new Data(); | 180 | + this.options.deserialize(data, bb.position(), |
160 | - this.payload = this.payload.deserialize(data, bb.position(), bb.limit() | 181 | + bb.limit() - bb.position()); |
161 | - - bb.position()); | ||
162 | - this.payload.setParent(this); | ||
163 | 182 | ||
164 | return this; | 183 | return this; |
165 | } | 184 | } |
... | @@ -178,9 +197,10 @@ public class NeighborAdvertisement extends BasePacket { | ... | @@ -178,9 +197,10 @@ public class NeighborAdvertisement extends BasePacket { |
178 | result = prime * result + this.solicitedFlag; | 197 | result = prime * result + this.solicitedFlag; |
179 | result = prime * result + this.overrideFlag; | 198 | result = prime * result + this.overrideFlag; |
180 | bb = ByteBuffer.wrap(this.targetAddress); | 199 | bb = ByteBuffer.wrap(this.targetAddress); |
181 | - for (int i = 0; i < 4; i++) { | 200 | + for (int i = 0; i < this.targetAddress.length / 4; i++) { |
182 | result = prime * result + bb.getInt(); | 201 | result = prime * result + bb.getInt(); |
183 | } | 202 | } |
203 | + result = prime * result + this.options.hashCode(); | ||
184 | return result; | 204 | return result; |
185 | } | 205 | } |
186 | 206 | ||
... | @@ -213,6 +233,9 @@ public class NeighborAdvertisement extends BasePacket { | ... | @@ -213,6 +233,9 @@ public class NeighborAdvertisement extends BasePacket { |
213 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { | 233 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { |
214 | return false; | 234 | return false; |
215 | } | 235 | } |
236 | + if (!this.options.equals(other.options)) { | ||
237 | + return false; | ||
238 | + } | ||
216 | return true; | 239 | return true; |
217 | } | 240 | } |
218 | } | 241 | } | ... | ... |
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.ndp; | ||
17 | + | ||
18 | +import java.nio.ByteBuffer; | ||
19 | +import java.util.ArrayList; | ||
20 | +import java.util.Arrays; | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +import org.onlab.packet.BasePacket; | ||
24 | +import org.onlab.packet.IPacket; | ||
25 | + | ||
26 | +/** | ||
27 | + * Neighbor Discovery Protocol packet options. | ||
28 | + */ | ||
29 | +public class NeighborDiscoveryOptions extends BasePacket { | ||
30 | + public static final byte TYPE_SOURCE_LL_ADDRESS = 1; | ||
31 | + public static final byte TYPE_TARGET_LL_ADDRESS = 2; | ||
32 | + public static final byte TYPE_PREFIX_INFORMATION = 3; | ||
33 | + public static final byte TYPE_REDIRECTED_HEADER = 4; | ||
34 | + public static final byte TYPE_MTU = 5; | ||
35 | + | ||
36 | + private final List<Option> options = new ArrayList<>(); | ||
37 | + | ||
38 | + /** | ||
39 | + * Packet option. | ||
40 | + */ | ||
41 | + public final class Option { | ||
42 | + private final byte type; | ||
43 | + private final byte[] data; | ||
44 | + | ||
45 | + /** | ||
46 | + * Constructor. | ||
47 | + * | ||
48 | + * @param type the option type | ||
49 | + * @param data the option data | ||
50 | + */ | ||
51 | + private Option(byte type, byte[] data) { | ||
52 | + this.type = type; | ||
53 | + this.data = Arrays.copyOfRange(data, 0, data.length); | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * Gets the option type. | ||
58 | + * | ||
59 | + * @return the option type | ||
60 | + */ | ||
61 | + public byte type() { | ||
62 | + return this.type; | ||
63 | + } | ||
64 | + | ||
65 | + /** | ||
66 | + * Gets the option data. | ||
67 | + * | ||
68 | + * @return the option data | ||
69 | + */ | ||
70 | + public byte[] data() { | ||
71 | + return this.data; | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * Gets the option data length (in number of octets). | ||
76 | + * | ||
77 | + * @return the option data length (in number of octets) | ||
78 | + */ | ||
79 | + public int dataLength() { | ||
80 | + return data.length; | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Gets the option length (in number of octets), including the type and | ||
85 | + * length fields (one octet each). | ||
86 | + * | ||
87 | + * @return the option length (in number of octets), including the type | ||
88 | + * and length fields | ||
89 | + */ | ||
90 | + private int optionLength() { | ||
91 | + return 2 + dataLength(); | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * Gets the option length field value (in units of 8 octets). | ||
96 | + * | ||
97 | + * @return the option length field value (in units of 8 octets) | ||
98 | + */ | ||
99 | + private byte optionLengthField() { | ||
100 | + return (byte) ((optionLength() + 7) / 8); | ||
101 | + } | ||
102 | + | ||
103 | + /** | ||
104 | + * Gets the option length on the wire (in number of octets). | ||
105 | + * | ||
106 | + * @return the option length on the wire (in number of octets) | ||
107 | + */ | ||
108 | + private int optionWireLength() { | ||
109 | + return 8 * optionLengthField(); | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * Adds a Neighbor Discovery Protocol packet option. | ||
115 | + * | ||
116 | + * @param type the option type | ||
117 | + * @param data the option data | ||
118 | + * @return this | ||
119 | + */ | ||
120 | + public NeighborDiscoveryOptions addOption(byte type, byte[] data) { | ||
121 | + options.add(new Option(type, data)); | ||
122 | + return this; | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * Gets the Neighbor Discovery Protocol packet options. | ||
127 | + * | ||
128 | + * @return the Neighbor Discovery Protocol packet options | ||
129 | + */ | ||
130 | + public List<NeighborDiscoveryOptions.Option> options() { | ||
131 | + return this.options; | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * Checks whether any options are included. | ||
136 | + * | ||
137 | + * @return true if options are included, otherwise false | ||
138 | + */ | ||
139 | + public boolean hasOptions() { | ||
140 | + return !this.options.isEmpty(); | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
144 | + public byte[] serialize() { | ||
145 | + // Compute first the total length on the wire for all options | ||
146 | + | ||
147 | + int wireLength = 0; | ||
148 | + | ||
149 | + for (Option option : this.options) { | ||
150 | + wireLength += option.optionWireLength(); | ||
151 | + } | ||
152 | + | ||
153 | + final byte[] data = new byte[wireLength]; | ||
154 | + final ByteBuffer bb = ByteBuffer.wrap(data); | ||
155 | + | ||
156 | + // | ||
157 | + // Serialize all options | ||
158 | + // | ||
159 | + for (Option option : this.options) { | ||
160 | + bb.put(option.type()); | ||
161 | + bb.put(option.optionLengthField()); | ||
162 | + bb.put(option.data()); | ||
163 | + // Add the padding | ||
164 | + int paddingLength = | ||
165 | + option.optionWireLength() - option.optionLength(); | ||
166 | + for (int i = 0; i < paddingLength; i++) { | ||
167 | + bb.put((byte) 0); | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + return data; | ||
172 | + } | ||
173 | + | ||
174 | + @Override | ||
175 | + public IPacket deserialize(byte[] data, int offset, int length) { | ||
176 | + final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); | ||
177 | + | ||
178 | + options.clear(); | ||
179 | + | ||
180 | + // | ||
181 | + // Deserialize all options | ||
182 | + // | ||
183 | + while (bb.hasRemaining()) { | ||
184 | + byte type = bb.get(); | ||
185 | + if (!bb.hasRemaining()) { | ||
186 | + break; | ||
187 | + } | ||
188 | + byte lengthField = bb.get(); | ||
189 | + int dataLength = lengthField * 8; // The data length field is in | ||
190 | + // unit of 8 octets | ||
191 | + | ||
192 | + // Exclude the type and length fields | ||
193 | + if (dataLength < 2) { | ||
194 | + break; | ||
195 | + } | ||
196 | + dataLength -= 2; | ||
197 | + | ||
198 | + if (bb.remaining() < dataLength) { | ||
199 | + break; | ||
200 | + } | ||
201 | + byte[] optionData = new byte[dataLength]; | ||
202 | + bb.get(optionData, 0, optionData.length); | ||
203 | + addOption(type, optionData); | ||
204 | + } | ||
205 | + | ||
206 | + return this; | ||
207 | + } | ||
208 | + | ||
209 | + @Override | ||
210 | + public int hashCode() { | ||
211 | + final int prime = 31; | ||
212 | + int result = 1; | ||
213 | + | ||
214 | + for (Option option : this.options) { | ||
215 | + result = prime * result + option.type(); | ||
216 | + result = prime * result + Arrays.hashCode(option.data()); | ||
217 | + } | ||
218 | + return result; | ||
219 | + } | ||
220 | + | ||
221 | + @Override | ||
222 | + public boolean equals(final Object obj) { | ||
223 | + if (this == obj) { | ||
224 | + return true; | ||
225 | + } | ||
226 | + if (obj instanceof NeighborDiscoveryOptions) { | ||
227 | + NeighborDiscoveryOptions other = (NeighborDiscoveryOptions) obj; | ||
228 | + return this.options.equals(other.options); | ||
229 | + } | ||
230 | + return false; | ||
231 | + } | ||
232 | +} |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,18 +13,15 @@ | ... | @@ -13,18 +13,15 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
22 | -import org.onlab.packet.Data; | ||
23 | import org.onlab.packet.IPacket; | 19 | import org.onlab.packet.IPacket; |
24 | import org.onlab.packet.Ip6Address; | 20 | import org.onlab.packet.Ip6Address; |
25 | 21 | ||
26 | import java.nio.ByteBuffer; | 22 | import java.nio.ByteBuffer; |
27 | import java.util.Arrays; | 23 | import java.util.Arrays; |
24 | +import java.util.List; | ||
28 | 25 | ||
29 | /** | 26 | /** |
30 | * Implements ICMPv6 Neighbor Solicitation packet format. (RFC 4861) | 27 | * Implements ICMPv6 Neighbor Solicitation packet format. (RFC 4861) |
... | @@ -34,6 +31,9 @@ public class NeighborSolicitation extends BasePacket { | ... | @@ -34,6 +31,9 @@ public class NeighborSolicitation extends BasePacket { |
34 | 31 | ||
35 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; | 32 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; |
36 | 33 | ||
34 | + private final NeighborDiscoveryOptions options = | ||
35 | + new NeighborDiscoveryOptions(); | ||
36 | + | ||
37 | /** | 37 | /** |
38 | * Gets target address. | 38 | * Gets target address. |
39 | * | 39 | * |
... | @@ -50,30 +50,52 @@ public class NeighborSolicitation extends BasePacket { | ... | @@ -50,30 +50,52 @@ public class NeighborSolicitation extends BasePacket { |
50 | * @return this | 50 | * @return this |
51 | */ | 51 | */ |
52 | public NeighborSolicitation setTargetAddress(final byte[] targetAddress) { | 52 | public NeighborSolicitation setTargetAddress(final byte[] targetAddress) { |
53 | - this.targetAddress = Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | 53 | + this.targetAddress = |
54 | + Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | ||
55 | + return this; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * Gets the Neighbor Discovery Protocol packet options. | ||
60 | + * | ||
61 | + * @return the Neighbor Discovery Protocol packet options | ||
62 | + */ | ||
63 | + public List<NeighborDiscoveryOptions.Option> getOptions() { | ||
64 | + return this.options.options(); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * Adds a Neighbor Discovery Protocol packet option. | ||
69 | + * | ||
70 | + * @param type the option type | ||
71 | + * @param data the option data | ||
72 | + * @return this | ||
73 | + */ | ||
74 | + public NeighborSolicitation addOption(final byte type, | ||
75 | + final byte[] data) { | ||
76 | + this.options.addOption(type, data); | ||
54 | return this; | 77 | return this; |
55 | } | 78 | } |
56 | 79 | ||
57 | @Override | 80 | @Override |
58 | public byte[] serialize() { | 81 | public byte[] serialize() { |
59 | - byte[] payloadData = null; | 82 | + byte[] optionsData = null; |
60 | - if (this.payload != null) { | 83 | + if (this.options.hasOptions()) { |
61 | - this.payload.setParent(this); | 84 | + optionsData = this.options.serialize(); |
62 | - payloadData = this.payload.serialize(); | ||
63 | } | 85 | } |
64 | 86 | ||
65 | - int payloadLength = 0; | 87 | + int optionsLength = 0; |
66 | - if (payloadData != null) { | 88 | + if (optionsData != null) { |
67 | - payloadLength = payloadData.length; | 89 | + optionsLength = optionsData.length; |
68 | } | 90 | } |
69 | 91 | ||
70 | - final byte[] data = new byte[HEADER_LENGTH + payloadLength]; | 92 | + final byte[] data = new byte[HEADER_LENGTH + optionsLength]; |
71 | final ByteBuffer bb = ByteBuffer.wrap(data); | 93 | final ByteBuffer bb = ByteBuffer.wrap(data); |
72 | 94 | ||
73 | bb.putInt(0); | 95 | bb.putInt(0); |
74 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 96 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
75 | - if (payloadData != null) { | 97 | + if (optionsData != null) { |
76 | - bb.put(payloadData); | 98 | + bb.put(optionsData); |
77 | } | 99 | } |
78 | 100 | ||
79 | return data; | 101 | return data; |
... | @@ -86,10 +108,8 @@ public class NeighborSolicitation extends BasePacket { | ... | @@ -86,10 +108,8 @@ public class NeighborSolicitation extends BasePacket { |
86 | bb.getInt(); | 108 | bb.getInt(); |
87 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 109 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
88 | 110 | ||
89 | - this.payload = new Data(); | 111 | + this.options.deserialize(data, bb.position(), |
90 | - this.payload = this.payload.deserialize(data, bb.position(), bb.limit() | 112 | + bb.limit() - bb.position()); |
91 | - - bb.position()); | ||
92 | - this.payload.setParent(this); | ||
93 | 113 | ||
94 | return this; | 114 | return this; |
95 | } | 115 | } |
... | @@ -105,9 +125,10 @@ public class NeighborSolicitation extends BasePacket { | ... | @@ -105,9 +125,10 @@ public class NeighborSolicitation extends BasePacket { |
105 | int result = super.hashCode(); | 125 | int result = super.hashCode(); |
106 | ByteBuffer bb; | 126 | ByteBuffer bb; |
107 | bb = ByteBuffer.wrap(this.targetAddress); | 127 | bb = ByteBuffer.wrap(this.targetAddress); |
108 | - for (int i = 0; i < 4; i++) { | 128 | + for (int i = 0; i < this.targetAddress.length / 4; i++) { |
109 | result = prime * result + bb.getInt(); | 129 | result = prime * result + bb.getInt(); |
110 | } | 130 | } |
131 | + result = prime * result + this.options.hashCode(); | ||
111 | return result; | 132 | return result; |
112 | } | 133 | } |
113 | 134 | ||
... | @@ -131,6 +152,9 @@ public class NeighborSolicitation extends BasePacket { | ... | @@ -131,6 +152,9 @@ public class NeighborSolicitation extends BasePacket { |
131 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { | 152 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { |
132 | return false; | 153 | return false; |
133 | } | 154 | } |
155 | + if (!this.options.equals(other.options)) { | ||
156 | + return false; | ||
157 | + } | ||
134 | return true; | 158 | return true; |
135 | } | 159 | } |
136 | } | 160 | } | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,18 +13,15 @@ | ... | @@ -13,18 +13,15 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
22 | -import org.onlab.packet.Data; | ||
23 | import org.onlab.packet.IPacket; | 19 | import org.onlab.packet.IPacket; |
24 | import org.onlab.packet.Ip6Address; | 20 | import org.onlab.packet.Ip6Address; |
25 | 21 | ||
26 | import java.nio.ByteBuffer; | 22 | import java.nio.ByteBuffer; |
27 | import java.util.Arrays; | 23 | import java.util.Arrays; |
24 | +import java.util.List; | ||
28 | 25 | ||
29 | /** | 26 | /** |
30 | * Implements ICMPv6 Redirect packet format. (RFC 4861) | 27 | * Implements ICMPv6 Redirect packet format. (RFC 4861) |
... | @@ -35,6 +32,9 @@ public class Redirect extends BasePacket { | ... | @@ -35,6 +32,9 @@ public class Redirect extends BasePacket { |
35 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; | 32 | protected byte[] targetAddress = new byte[Ip6Address.BYTE_LENGTH]; |
36 | protected byte[] destinationAddress = new byte[Ip6Address.BYTE_LENGTH]; | 33 | protected byte[] destinationAddress = new byte[Ip6Address.BYTE_LENGTH]; |
37 | 34 | ||
35 | + private final NeighborDiscoveryOptions options = | ||
36 | + new NeighborDiscoveryOptions(); | ||
37 | + | ||
38 | /** | 38 | /** |
39 | * Gets target address. | 39 | * Gets target address. |
40 | * | 40 | * |
... | @@ -51,7 +51,8 @@ public class Redirect extends BasePacket { | ... | @@ -51,7 +51,8 @@ public class Redirect extends BasePacket { |
51 | * @return this | 51 | * @return this |
52 | */ | 52 | */ |
53 | public Redirect setTargetAddress(final byte[] targetAddress) { | 53 | public Redirect setTargetAddress(final byte[] targetAddress) { |
54 | - this.targetAddress = Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | 54 | + this.targetAddress = |
55 | + Arrays.copyOfRange(targetAddress, 0, Ip6Address.BYTE_LENGTH); | ||
55 | return this; | 56 | return this; |
56 | } | 57 | } |
57 | 58 | ||
... | @@ -71,32 +72,52 @@ public class Redirect extends BasePacket { | ... | @@ -71,32 +72,52 @@ public class Redirect extends BasePacket { |
71 | * @return this | 72 | * @return this |
72 | */ | 73 | */ |
73 | public Redirect setDestinationAddress(final byte[] destinationAddress) { | 74 | public Redirect setDestinationAddress(final byte[] destinationAddress) { |
74 | - this.destinationAddress = Arrays.copyOfRange(destinationAddress, 0, Ip6Address.BYTE_LENGTH); | 75 | + this.destinationAddress = |
76 | + Arrays.copyOfRange(destinationAddress, 0, Ip6Address.BYTE_LENGTH); | ||
77 | + return this; | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * Gets the Neighbor Discovery Protocol packet options. | ||
82 | + * | ||
83 | + * @return the Neighbor Discovery Protocol packet options | ||
84 | + */ | ||
85 | + public List<NeighborDiscoveryOptions.Option> getOptions() { | ||
86 | + return this.options.options(); | ||
87 | + } | ||
88 | + | ||
89 | + /** | ||
90 | + * Adds a Neighbor Discovery Protocol packet option. | ||
91 | + * | ||
92 | + * @param type the option type | ||
93 | + * @param data the option data | ||
94 | + * @return this | ||
95 | + */ | ||
96 | + public Redirect addOption(final byte type, final byte[] data) { | ||
97 | + this.options.addOption(type, data); | ||
75 | return this; | 98 | return this; |
76 | } | 99 | } |
77 | 100 | ||
78 | @Override | 101 | @Override |
79 | public byte[] serialize() { | 102 | public byte[] serialize() { |
80 | - byte[] payloadData = null; | 103 | + byte[] optionsData = null; |
81 | - if (this.payload != null) { | 104 | + if (this.options.hasOptions()) { |
82 | - this.payload.setParent(this); | 105 | + optionsData = this.options.serialize(); |
83 | - payloadData = this.payload.serialize(); | ||
84 | } | 106 | } |
85 | 107 | ||
86 | - int payloadLength = 0; | 108 | + int optionsLength = 0; |
87 | - if (payloadData != null) { | 109 | + if (optionsData != null) { |
88 | - payloadLength = payloadData.length; | 110 | + optionsLength = optionsData.length; |
89 | } | 111 | } |
90 | 112 | ||
91 | - final byte[] data = new byte[HEADER_LENGTH + payloadLength]; | 113 | + final byte[] data = new byte[HEADER_LENGTH + optionsLength]; |
92 | final ByteBuffer bb = ByteBuffer.wrap(data); | 114 | final ByteBuffer bb = ByteBuffer.wrap(data); |
93 | 115 | ||
94 | bb.putInt(0); | 116 | bb.putInt(0); |
95 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 117 | bb.put(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
96 | bb.put(this.destinationAddress, 0, Ip6Address.BYTE_LENGTH); | 118 | bb.put(this.destinationAddress, 0, Ip6Address.BYTE_LENGTH); |
97 | - | 119 | + if (optionsData != null) { |
98 | - if (payloadData != null) { | 120 | + bb.put(optionsData); |
99 | - bb.put(payloadData); | ||
100 | } | 121 | } |
101 | 122 | ||
102 | return data; | 123 | return data; |
... | @@ -110,10 +131,8 @@ public class Redirect extends BasePacket { | ... | @@ -110,10 +131,8 @@ public class Redirect extends BasePacket { |
110 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); | 131 | bb.get(this.targetAddress, 0, Ip6Address.BYTE_LENGTH); |
111 | bb.get(this.destinationAddress, 0, Ip6Address.BYTE_LENGTH); | 132 | bb.get(this.destinationAddress, 0, Ip6Address.BYTE_LENGTH); |
112 | 133 | ||
113 | - this.payload = new Data(); | 134 | + this.options.deserialize(data, bb.position(), |
114 | - this.payload = this.payload.deserialize(data, bb.position(), bb.limit() | 135 | + bb.limit() - bb.position()); |
115 | - - bb.position()); | ||
116 | - this.payload.setParent(this); | ||
117 | 136 | ||
118 | return this; | 137 | return this; |
119 | } | 138 | } |
... | @@ -129,13 +148,14 @@ public class Redirect extends BasePacket { | ... | @@ -129,13 +148,14 @@ public class Redirect extends BasePacket { |
129 | int result = super.hashCode(); | 148 | int result = super.hashCode(); |
130 | ByteBuffer bb; | 149 | ByteBuffer bb; |
131 | bb = ByteBuffer.wrap(this.targetAddress); | 150 | bb = ByteBuffer.wrap(this.targetAddress); |
132 | - for (int i = 0; i < 4; i++) { | 151 | + for (int i = 0; i < this.targetAddress.length / 4; i++) { |
133 | result = prime * result + bb.getInt(); | 152 | result = prime * result + bb.getInt(); |
134 | } | 153 | } |
135 | bb = ByteBuffer.wrap(this.destinationAddress); | 154 | bb = ByteBuffer.wrap(this.destinationAddress); |
136 | - for (int i = 0; i < 4; i++) { | 155 | + for (int i = 0; i < this.destinationAddress.length / 4; i++) { |
137 | result = prime * result + bb.getInt(); | 156 | result = prime * result + bb.getInt(); |
138 | } | 157 | } |
158 | + result = prime * result + this.options.hashCode(); | ||
139 | return result; | 159 | return result; |
140 | } | 160 | } |
141 | 161 | ||
... | @@ -159,7 +179,11 @@ public class Redirect extends BasePacket { | ... | @@ -159,7 +179,11 @@ public class Redirect extends BasePacket { |
159 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { | 179 | if (!Arrays.equals(this.targetAddress, other.targetAddress)) { |
160 | return false; | 180 | return false; |
161 | } | 181 | } |
162 | - if (!Arrays.equals(this.destinationAddress, other.destinationAddress)) { | 182 | + if (!Arrays.equals(this.destinationAddress, |
183 | + other.destinationAddress)) { | ||
184 | + return false; | ||
185 | + } | ||
186 | + if (!this.options.equals(other.options)) { | ||
163 | return false; | 187 | return false; |
164 | } | 188 | } |
165 | return true; | 189 | return true; | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,16 +13,13 @@ | ... | @@ -13,16 +13,13 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
22 | -import org.onlab.packet.Data; | ||
23 | import org.onlab.packet.IPacket; | 19 | import org.onlab.packet.IPacket; |
24 | 20 | ||
25 | import java.nio.ByteBuffer; | 21 | import java.nio.ByteBuffer; |
22 | +import java.util.List; | ||
26 | 23 | ||
27 | /** | 24 | /** |
28 | * Implements ICMPv6 Router Advertisement packet format. (RFC 4861) | 25 | * Implements ICMPv6 Router Advertisement packet format. (RFC 4861) |
... | @@ -37,6 +34,9 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -37,6 +34,9 @@ public class RouterAdvertisement extends BasePacket { |
37 | protected int reachableTime; | 34 | protected int reachableTime; |
38 | protected int retransmitTimer; | 35 | protected int retransmitTimer; |
39 | 36 | ||
37 | + private final NeighborDiscoveryOptions options = | ||
38 | + new NeighborDiscoveryOptions(); | ||
39 | + | ||
40 | /** | 40 | /** |
41 | * Gets current hop limit. | 41 | * Gets current hop limit. |
42 | * | 42 | * |
... | @@ -157,20 +157,40 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -157,20 +157,40 @@ public class RouterAdvertisement extends BasePacket { |
157 | return this; | 157 | return this; |
158 | } | 158 | } |
159 | 159 | ||
160 | + /** | ||
161 | + * Gets the Neighbor Discovery Protocol packet options. | ||
162 | + * | ||
163 | + * @return the Neighbor Discovery Protocol packet options | ||
164 | + */ | ||
165 | + public List<NeighborDiscoveryOptions.Option> getOptions() { | ||
166 | + return this.options.options(); | ||
167 | + } | ||
168 | + | ||
169 | + /** | ||
170 | + * Adds a Neighbor Discovery Protocol packet option. | ||
171 | + * | ||
172 | + * @param type the option type | ||
173 | + * @param data the option data | ||
174 | + * @return this | ||
175 | + */ | ||
176 | + public RouterAdvertisement addOption(final byte type, final byte[] data) { | ||
177 | + this.options.addOption(type, data); | ||
178 | + return this; | ||
179 | + } | ||
180 | + | ||
160 | @Override | 181 | @Override |
161 | public byte[] serialize() { | 182 | public byte[] serialize() { |
162 | - byte[] payloadData = null; | 183 | + byte[] optionsData = null; |
163 | - if (this.payload != null) { | 184 | + if (this.options.hasOptions()) { |
164 | - this.payload.setParent(this); | 185 | + optionsData = this.options.serialize(); |
165 | - payloadData = this.payload.serialize(); | ||
166 | } | 186 | } |
167 | 187 | ||
168 | - int payloadLength = 0; | 188 | + int optionsLength = 0; |
169 | - if (payloadData != null) { | 189 | + if (optionsData != null) { |
170 | - payloadLength = payloadData.length; | 190 | + optionsLength = optionsData.length; |
171 | } | 191 | } |
172 | 192 | ||
173 | - final byte[] data = new byte[HEADER_LENGTH + payloadLength]; | 193 | + final byte[] data = new byte[HEADER_LENGTH + optionsLength]; |
174 | final ByteBuffer bb = ByteBuffer.wrap(data); | 194 | final ByteBuffer bb = ByteBuffer.wrap(data); |
175 | 195 | ||
176 | bb.put(this.currentHopLimit); | 196 | bb.put(this.currentHopLimit); |
... | @@ -179,8 +199,8 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -179,8 +199,8 @@ public class RouterAdvertisement extends BasePacket { |
179 | bb.putInt(reachableTime); | 199 | bb.putInt(reachableTime); |
180 | bb.putInt(retransmitTimer); | 200 | bb.putInt(retransmitTimer); |
181 | 201 | ||
182 | - if (payloadData != null) { | 202 | + if (optionsData != null) { |
183 | - bb.put(payloadData); | 203 | + bb.put(optionsData); |
184 | } | 204 | } |
185 | 205 | ||
186 | return data; | 206 | return data; |
... | @@ -199,10 +219,8 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -199,10 +219,8 @@ public class RouterAdvertisement extends BasePacket { |
199 | this.reachableTime = bb.getInt(); | 219 | this.reachableTime = bb.getInt(); |
200 | this.retransmitTimer = bb.getInt(); | 220 | this.retransmitTimer = bb.getInt(); |
201 | 221 | ||
202 | - this.payload = new Data(); | 222 | + this.options.deserialize(data, bb.position(), |
203 | - this.payload = this.payload.deserialize(data, bb.position(), bb.limit() | 223 | + bb.limit() - bb.position()); |
204 | - - bb.position()); | ||
205 | - this.payload.setParent(this); | ||
206 | 224 | ||
207 | return this; | 225 | return this; |
208 | } | 226 | } |
... | @@ -222,6 +240,7 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -222,6 +240,7 @@ public class RouterAdvertisement extends BasePacket { |
222 | result = prime * result + this.routerLifetime; | 240 | result = prime * result + this.routerLifetime; |
223 | result = prime * result + this.reachableTime; | 241 | result = prime * result + this.reachableTime; |
224 | result = prime * result + this.retransmitTimer; | 242 | result = prime * result + this.retransmitTimer; |
243 | + result = prime * result + this.options.hashCode(); | ||
225 | return result; | 244 | return result; |
226 | } | 245 | } |
227 | 246 | ||
... | @@ -260,6 +279,9 @@ public class RouterAdvertisement extends BasePacket { | ... | @@ -260,6 +279,9 @@ public class RouterAdvertisement extends BasePacket { |
260 | if (this.retransmitTimer != other.retransmitTimer) { | 279 | if (this.retransmitTimer != other.retransmitTimer) { |
261 | return false; | 280 | return false; |
262 | } | 281 | } |
282 | + if (!this.options.equals(other.options)) { | ||
283 | + return false; | ||
284 | + } | ||
263 | return true; | 285 | return true; |
264 | } | 286 | } |
265 | } | 287 | } | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,16 +13,13 @@ | ... | @@ -13,16 +13,13 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.onlab.packet.BasePacket; | 18 | import org.onlab.packet.BasePacket; |
22 | -import org.onlab.packet.Data; | ||
23 | import org.onlab.packet.IPacket; | 19 | import org.onlab.packet.IPacket; |
24 | 20 | ||
25 | import java.nio.ByteBuffer; | 21 | import java.nio.ByteBuffer; |
22 | +import java.util.List; | ||
26 | 23 | ||
27 | /** | 24 | /** |
28 | * Implements ICMPv6 Router Solicitation packet format. (RFC 4861) | 25 | * Implements ICMPv6 Router Solicitation packet format. (RFC 4861) |
... | @@ -30,26 +27,49 @@ import java.nio.ByteBuffer; | ... | @@ -30,26 +27,49 @@ import java.nio.ByteBuffer; |
30 | public class RouterSolicitation extends BasePacket { | 27 | public class RouterSolicitation extends BasePacket { |
31 | public static final byte HEADER_LENGTH = 4; // bytes | 28 | public static final byte HEADER_LENGTH = 4; // bytes |
32 | 29 | ||
30 | + private final NeighborDiscoveryOptions options = | ||
31 | + new NeighborDiscoveryOptions(); | ||
32 | + | ||
33 | + /** | ||
34 | + * Gets the Neighbor Discovery Protocol packet options. | ||
35 | + * | ||
36 | + * @return the Neighbor Discovery Protocol packet options | ||
37 | + */ | ||
38 | + public List<NeighborDiscoveryOptions.Option> getOptions() { | ||
39 | + return this.options.options(); | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * Adds a Neighbor Discovery Protocol packet option. | ||
44 | + * | ||
45 | + * @param type the option type | ||
46 | + * @param data the option data | ||
47 | + * @return this | ||
48 | + */ | ||
49 | + public RouterSolicitation addOption(final byte type, final byte[] data) { | ||
50 | + this.options.addOption(type, data); | ||
51 | + return this; | ||
52 | + } | ||
53 | + | ||
33 | @Override | 54 | @Override |
34 | public byte[] serialize() { | 55 | public byte[] serialize() { |
35 | - byte[] payloadData = null; | 56 | + byte[] optionsData = null; |
36 | - if (this.payload != null) { | 57 | + if (this.options.hasOptions()) { |
37 | - this.payload.setParent(this); | 58 | + optionsData = this.options.serialize(); |
38 | - payloadData = this.payload.serialize(); | ||
39 | } | 59 | } |
40 | 60 | ||
41 | - int payloadLength = 0; | 61 | + int optionsLength = 0; |
42 | - if (payloadData != null) { | 62 | + if (optionsData != null) { |
43 | - payloadLength = payloadData.length; | 63 | + optionsLength = optionsData.length; |
44 | } | 64 | } |
45 | 65 | ||
46 | - final byte[] data = new byte[HEADER_LENGTH + payloadLength]; | 66 | + final byte[] data = new byte[HEADER_LENGTH + optionsLength]; |
47 | final ByteBuffer bb = ByteBuffer.wrap(data); | 67 | final ByteBuffer bb = ByteBuffer.wrap(data); |
48 | 68 | ||
49 | bb.putInt(0); | 69 | bb.putInt(0); |
50 | 70 | ||
51 | - if (payloadData != null) { | 71 | + if (optionsData != null) { |
52 | - bb.put(payloadData); | 72 | + bb.put(optionsData); |
53 | } | 73 | } |
54 | 74 | ||
55 | return data; | 75 | return data; |
... | @@ -61,10 +81,8 @@ public class RouterSolicitation extends BasePacket { | ... | @@ -61,10 +81,8 @@ public class RouterSolicitation extends BasePacket { |
61 | 81 | ||
62 | bb.getInt(); | 82 | bb.getInt(); |
63 | 83 | ||
64 | - this.payload = new Data(); | 84 | + this.options.deserialize(data, bb.position(), |
65 | - this.payload = this.payload.deserialize(data, bb.position(), bb.limit() | 85 | + bb.limit() - bb.position()); |
66 | - - bb.position()); | ||
67 | - this.payload.setParent(this); | ||
68 | 86 | ||
69 | return this; | 87 | return this; |
70 | } | 88 | } |
... | @@ -76,7 +94,10 @@ public class RouterSolicitation extends BasePacket { | ... | @@ -76,7 +94,10 @@ public class RouterSolicitation extends BasePacket { |
76 | */ | 94 | */ |
77 | @Override | 95 | @Override |
78 | public int hashCode() { | 96 | public int hashCode() { |
79 | - return super.hashCode(); | 97 | + final int prime = 5807; |
98 | + int result = super.hashCode(); | ||
99 | + result = prime * result + this.options.hashCode(); | ||
100 | + return result; | ||
80 | } | 101 | } |
81 | 102 | ||
82 | /* | 103 | /* |
... | @@ -95,6 +116,10 @@ public class RouterSolicitation extends BasePacket { | ... | @@ -95,6 +116,10 @@ public class RouterSolicitation extends BasePacket { |
95 | if (!(obj instanceof RouterSolicitation)) { | 116 | if (!(obj instanceof RouterSolicitation)) { |
96 | return false; | 117 | return false; |
97 | } | 118 | } |
119 | + final RouterSolicitation other = (RouterSolicitation) obj; | ||
120 | + if (!this.options.equals(other.options)) { | ||
121 | + return false; | ||
122 | + } | ||
98 | return true; | 123 | return true; |
99 | } | 124 | } |
100 | } | 125 | } | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,46 +13,46 @@ | ... | @@ -13,46 +13,46 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.junit.BeforeClass; | 18 | import org.junit.BeforeClass; |
22 | import org.junit.Test; | 19 | import org.junit.Test; |
23 | -import org.onlab.packet.Data; | 20 | +import org.onlab.packet.MacAddress; |
24 | 21 | ||
25 | import static org.hamcrest.Matchers.is; | 22 | import static org.hamcrest.Matchers.is; |
26 | import static org.junit.Assert.assertArrayEquals; | 23 | import static org.junit.Assert.assertArrayEquals; |
27 | -import static org.junit.Assert.assertTrue; | ||
28 | import static org.junit.Assert.assertFalse; | 24 | import static org.junit.Assert.assertFalse; |
29 | import static org.junit.Assert.assertThat; | 25 | import static org.junit.Assert.assertThat; |
26 | +import static org.junit.Assert.assertTrue; | ||
30 | 27 | ||
31 | /** | 28 | /** |
32 | * Tests for class {@link NeighborAdvertisement}. | 29 | * Tests for class {@link NeighborAdvertisement}. |
33 | */ | 30 | */ |
34 | public class NeighborAdvertisementTest { | 31 | public class NeighborAdvertisementTest { |
35 | private static final byte[] TARGET_ADDRESS = { | 32 | private static final byte[] TARGET_ADDRESS = { |
36 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 33 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
37 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 34 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
35 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
36 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | ||
38 | }; | 37 | }; |
39 | - private static Data data; | 38 | + private static final MacAddress MAC_ADDRESS = |
39 | + MacAddress.valueOf("11:22:33:44:55:66"); | ||
40 | + | ||
40 | private static byte[] bytePacket; | 41 | private static byte[] bytePacket; |
41 | 42 | ||
42 | @BeforeClass | 43 | @BeforeClass |
43 | public static void setUpBeforeClass() throws Exception { | 44 | public static void setUpBeforeClass() throws Exception { |
44 | - data = new Data(); | ||
45 | - data.setData("".getBytes()); | ||
46 | - | ||
47 | - byte[] bytePayload = data.serialize(); | ||
48 | byte[] byteHeader = { | 45 | byte[] byteHeader = { |
49 | (byte) 0xe0, (byte) 0x00, (byte) 0x00, (byte) 0x00, | 46 | (byte) 0xe0, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
50 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 47 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
51 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 48 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
49 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
50 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce, | ||
51 | + (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22, | ||
52 | + (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 | ||
52 | }; | 53 | }; |
53 | - bytePacket = new byte[byteHeader.length + bytePayload.length]; | 54 | + bytePacket = new byte[byteHeader.length]; |
54 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); | 55 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); |
55 | - System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length); | ||
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
... | @@ -65,7 +65,8 @@ public class NeighborAdvertisementTest { | ... | @@ -65,7 +65,8 @@ public class NeighborAdvertisementTest { |
65 | na.setSolicitedFlag((byte) 1); | 65 | na.setSolicitedFlag((byte) 1); |
66 | na.setOverrideFlag((byte) 1); | 66 | na.setOverrideFlag((byte) 1); |
67 | na.setTargetAddress(TARGET_ADDRESS); | 67 | na.setTargetAddress(TARGET_ADDRESS); |
68 | - na.setPayload(data); | 68 | + na.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
69 | + MAC_ADDRESS.toBytes()); | ||
69 | 70 | ||
70 | assertArrayEquals(na.serialize(), bytePacket); | 71 | assertArrayEquals(na.serialize(), bytePacket); |
71 | } | 72 | } |
... | @@ -82,6 +83,13 @@ public class NeighborAdvertisementTest { | ... | @@ -82,6 +83,13 @@ public class NeighborAdvertisementTest { |
82 | assertThat(na.getSolicitedFlag(), is((byte) 1)); | 83 | assertThat(na.getSolicitedFlag(), is((byte) 1)); |
83 | assertThat(na.getOverrideFlag(), is((byte) 1)); | 84 | assertThat(na.getOverrideFlag(), is((byte) 1)); |
84 | assertArrayEquals(na.getTargetAddress(), TARGET_ADDRESS); | 85 | assertArrayEquals(na.getTargetAddress(), TARGET_ADDRESS); |
86 | + | ||
87 | + // Check the option(s) | ||
88 | + assertThat(na.getOptions().size(), is(1)); | ||
89 | + NeighborDiscoveryOptions.Option option = na.getOptions().get(0); | ||
90 | + assertThat(option.type(), | ||
91 | + is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS)); | ||
92 | + assertArrayEquals(option.data(), MAC_ADDRESS.toBytes()); | ||
85 | } | 93 | } |
86 | 94 | ||
87 | /** | 95 | /** |
... | @@ -94,12 +102,16 @@ public class NeighborAdvertisementTest { | ... | @@ -94,12 +102,16 @@ public class NeighborAdvertisementTest { |
94 | na1.setSolicitedFlag((byte) 1); | 102 | na1.setSolicitedFlag((byte) 1); |
95 | na1.setOverrideFlag((byte) 1); | 103 | na1.setOverrideFlag((byte) 1); |
96 | na1.setTargetAddress(TARGET_ADDRESS); | 104 | na1.setTargetAddress(TARGET_ADDRESS); |
105 | + na1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
106 | + MAC_ADDRESS.toBytes()); | ||
97 | 107 | ||
98 | NeighborAdvertisement na2 = new NeighborAdvertisement(); | 108 | NeighborAdvertisement na2 = new NeighborAdvertisement(); |
99 | na2.setRouterFlag((byte) 1); | 109 | na2.setRouterFlag((byte) 1); |
100 | na2.setSolicitedFlag((byte) 1); | 110 | na2.setSolicitedFlag((byte) 1); |
101 | na2.setOverrideFlag((byte) 0); | 111 | na2.setOverrideFlag((byte) 0); |
102 | na2.setTargetAddress(TARGET_ADDRESS); | 112 | na2.setTargetAddress(TARGET_ADDRESS); |
113 | + na2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
114 | + MAC_ADDRESS.toBytes()); | ||
103 | 115 | ||
104 | assertTrue(na1.equals(na1)); | 116 | assertTrue(na1.equals(na1)); |
105 | assertFalse(na1.equals(na2)); | 117 | assertFalse(na1.equals(na2)); | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,47 +13,52 @@ | ... | @@ -13,47 +13,52 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.junit.BeforeClass; | 18 | import org.junit.BeforeClass; |
22 | import org.junit.Test; | 19 | import org.junit.Test; |
23 | -import org.onlab.packet.Data; | 20 | +import org.onlab.packet.MacAddress; |
24 | 21 | ||
22 | +import static org.hamcrest.Matchers.is; | ||
25 | import static org.junit.Assert.assertArrayEquals; | 23 | import static org.junit.Assert.assertArrayEquals; |
26 | -import static org.junit.Assert.assertTrue; | ||
27 | import static org.junit.Assert.assertFalse; | 24 | import static org.junit.Assert.assertFalse; |
25 | +import static org.junit.Assert.assertThat; | ||
26 | +import static org.junit.Assert.assertTrue; | ||
27 | + | ||
28 | /** | 28 | /** |
29 | * Tests for class {@link NeighborSolicitation}. | 29 | * Tests for class {@link NeighborSolicitation}. |
30 | */ | 30 | */ |
31 | public class NeighborSolicitationTest { | 31 | public class NeighborSolicitationTest { |
32 | private static final byte[] TARGET_ADDRESS = { | 32 | private static final byte[] TARGET_ADDRESS = { |
33 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 33 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
34 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 34 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
35 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
36 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | ||
35 | }; | 37 | }; |
36 | private static final byte[] TARGET_ADDRESS2 = { | 38 | private static final byte[] TARGET_ADDRESS2 = { |
37 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 39 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
38 | - (byte) 0xe6, (byte) 0xce, (byte) 0x8f, (byte) 0xff, (byte) 0xfe, (byte) 0x54, (byte) 0x37, (byte) 0xc8 | 40 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
41 | + (byte) 0xe6, (byte) 0xce, (byte) 0x8f, (byte) 0xff, | ||
42 | + (byte) 0xfe, (byte) 0x54, (byte) 0x37, (byte) 0xc8 | ||
39 | }; | 43 | }; |
40 | - private static Data data; | 44 | + private static final MacAddress MAC_ADDRESS = |
45 | + MacAddress.valueOf("11:22:33:44:55:66"); | ||
46 | + | ||
41 | private static byte[] bytePacket; | 47 | private static byte[] bytePacket; |
42 | 48 | ||
43 | @BeforeClass | 49 | @BeforeClass |
44 | public static void setUpBeforeClass() throws Exception { | 50 | public static void setUpBeforeClass() throws Exception { |
45 | - data = new Data(); | ||
46 | - data.setData("".getBytes()); | ||
47 | - | ||
48 | - byte[] bytePayload = data.serialize(); | ||
49 | byte[] byteHeader = { | 51 | byte[] byteHeader = { |
50 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, | 52 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
51 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 53 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
52 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 54 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
55 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
56 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce, | ||
57 | + (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22, | ||
58 | + (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 | ||
53 | }; | 59 | }; |
54 | - bytePacket = new byte[byteHeader.length + bytePayload.length]; | 60 | + bytePacket = new byte[byteHeader.length]; |
55 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); | 61 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); |
56 | - System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length); | ||
57 | } | 62 | } |
58 | 63 | ||
59 | /** | 64 | /** |
... | @@ -63,7 +68,8 @@ public class NeighborSolicitationTest { | ... | @@ -63,7 +68,8 @@ public class NeighborSolicitationTest { |
63 | public void testSerialize() { | 68 | public void testSerialize() { |
64 | NeighborSolicitation ns = new NeighborSolicitation(); | 69 | NeighborSolicitation ns = new NeighborSolicitation(); |
65 | ns.setTargetAddress(TARGET_ADDRESS); | 70 | ns.setTargetAddress(TARGET_ADDRESS); |
66 | - ns.setPayload(data); | 71 | + ns.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
72 | + MAC_ADDRESS.toBytes()); | ||
67 | 73 | ||
68 | assertArrayEquals(ns.serialize(), bytePacket); | 74 | assertArrayEquals(ns.serialize(), bytePacket); |
69 | } | 75 | } |
... | @@ -77,6 +83,13 @@ public class NeighborSolicitationTest { | ... | @@ -77,6 +83,13 @@ public class NeighborSolicitationTest { |
77 | ns.deserialize(bytePacket, 0, bytePacket.length); | 83 | ns.deserialize(bytePacket, 0, bytePacket.length); |
78 | 84 | ||
79 | assertArrayEquals(ns.getTargetAddress(), TARGET_ADDRESS); | 85 | assertArrayEquals(ns.getTargetAddress(), TARGET_ADDRESS); |
86 | + | ||
87 | + // Check the option(s) | ||
88 | + assertThat(ns.getOptions().size(), is(1)); | ||
89 | + NeighborDiscoveryOptions.Option option = ns.getOptions().get(0); | ||
90 | + assertThat(option.type(), | ||
91 | + is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS)); | ||
92 | + assertArrayEquals(option.data(), MAC_ADDRESS.toBytes()); | ||
80 | } | 93 | } |
81 | 94 | ||
82 | /** | 95 | /** |
... | @@ -86,9 +99,13 @@ public class NeighborSolicitationTest { | ... | @@ -86,9 +99,13 @@ public class NeighborSolicitationTest { |
86 | public void testEqual() { | 99 | public void testEqual() { |
87 | NeighborSolicitation ns1 = new NeighborSolicitation(); | 100 | NeighborSolicitation ns1 = new NeighborSolicitation(); |
88 | ns1.setTargetAddress(TARGET_ADDRESS); | 101 | ns1.setTargetAddress(TARGET_ADDRESS); |
102 | + ns1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
103 | + MAC_ADDRESS.toBytes()); | ||
89 | 104 | ||
90 | NeighborSolicitation ns2 = new NeighborSolicitation(); | 105 | NeighborSolicitation ns2 = new NeighborSolicitation(); |
91 | ns2.setTargetAddress(TARGET_ADDRESS2); | 106 | ns2.setTargetAddress(TARGET_ADDRESS2); |
107 | + ns2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
108 | + MAC_ADDRESS.toBytes()); | ||
92 | 109 | ||
93 | assertTrue(ns1.equals(ns1)); | 110 | assertTrue(ns1.equals(ns1)); |
94 | assertFalse(ns1.equals(ns2)); | 111 | assertFalse(ns1.equals(ns2)); | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,54 +13,62 @@ | ... | @@ -13,54 +13,62 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.junit.BeforeClass; | 18 | import org.junit.BeforeClass; |
22 | import org.junit.Test; | 19 | import org.junit.Test; |
23 | -import org.onlab.packet.Data; | 20 | +import org.onlab.packet.MacAddress; |
24 | 21 | ||
22 | +import static org.hamcrest.Matchers.is; | ||
25 | import static org.junit.Assert.assertArrayEquals; | 23 | import static org.junit.Assert.assertArrayEquals; |
26 | -import static org.junit.Assert.assertTrue; | ||
27 | import static org.junit.Assert.assertFalse; | 24 | import static org.junit.Assert.assertFalse; |
25 | +import static org.junit.Assert.assertThat; | ||
26 | +import static org.junit.Assert.assertTrue; | ||
28 | 27 | ||
29 | /** | 28 | /** |
30 | * Tests for class {@link Redirect}. | 29 | * Tests for class {@link Redirect}. |
31 | */ | 30 | */ |
32 | public class RedirectTest { | 31 | public class RedirectTest { |
33 | private static final byte[] TARGET_ADDRESS = { | 32 | private static final byte[] TARGET_ADDRESS = { |
34 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 33 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
35 | - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 | 34 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
35 | + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, | ||
36 | + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 | ||
36 | }; | 37 | }; |
37 | private static final byte[] DESTINATION_ADDRESS = { | 38 | private static final byte[] DESTINATION_ADDRESS = { |
38 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 39 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
39 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 40 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
41 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
42 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | ||
40 | }; | 43 | }; |
41 | private static final byte[] DESTINATION_ADDRESS2 = { | 44 | private static final byte[] DESTINATION_ADDRESS2 = { |
42 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 45 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
43 | - (byte) 0xe6, (byte) 0xce, (byte) 0x8f, (byte) 0xff, (byte) 0xfe, (byte) 0x54, (byte) 0x37, (byte) 0xc8 | 46 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
47 | + (byte) 0xe6, (byte) 0xce, (byte) 0x8f, (byte) 0xff, | ||
48 | + (byte) 0xfe, (byte) 0x54, (byte) 0x37, (byte) 0xc8 | ||
44 | }; | 49 | }; |
45 | - private static Data data; | 50 | + private static final MacAddress MAC_ADDRESS = |
51 | + MacAddress.valueOf("11:22:33:44:55:66"); | ||
52 | + | ||
46 | private static byte[] bytePacket; | 53 | private static byte[] bytePacket; |
47 | 54 | ||
48 | @BeforeClass | 55 | @BeforeClass |
49 | public static void setUpBeforeClass() throws Exception { | 56 | public static void setUpBeforeClass() throws Exception { |
50 | - data = new Data(); | ||
51 | - data.setData("".getBytes()); | ||
52 | - | ||
53 | - byte[] bytePayload = data.serialize(); | ||
54 | byte[] byteHeader = { | 57 | byte[] byteHeader = { |
55 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, | 58 | (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
56 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 59 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, |
57 | - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, | 60 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, |
58 | - (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | 61 | + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
59 | - (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce | 62 | + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
63 | + (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18, | ||
64 | + (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15, | ||
65 | + (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff, | ||
66 | + (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce, | ||
67 | + (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22, | ||
68 | + (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 | ||
60 | }; | 69 | }; |
61 | - bytePacket = new byte[byteHeader.length + bytePayload.length]; | 70 | + bytePacket = new byte[byteHeader.length]; |
62 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); | 71 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); |
63 | - System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length); | ||
64 | } | 72 | } |
65 | 73 | ||
66 | /** | 74 | /** |
... | @@ -71,7 +79,8 @@ public class RedirectTest { | ... | @@ -71,7 +79,8 @@ public class RedirectTest { |
71 | Redirect rd = new Redirect(); | 79 | Redirect rd = new Redirect(); |
72 | rd.setTargetAddress(TARGET_ADDRESS); | 80 | rd.setTargetAddress(TARGET_ADDRESS); |
73 | rd.setDestinationAddress(DESTINATION_ADDRESS); | 81 | rd.setDestinationAddress(DESTINATION_ADDRESS); |
74 | - rd.setPayload(data); | 82 | + rd.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
83 | + MAC_ADDRESS.toBytes()); | ||
75 | 84 | ||
76 | assertArrayEquals(rd.serialize(), bytePacket); | 85 | assertArrayEquals(rd.serialize(), bytePacket); |
77 | } | 86 | } |
... | @@ -86,6 +95,13 @@ public class RedirectTest { | ... | @@ -86,6 +95,13 @@ public class RedirectTest { |
86 | 95 | ||
87 | assertArrayEquals(rd.getTargetAddress(), TARGET_ADDRESS); | 96 | assertArrayEquals(rd.getTargetAddress(), TARGET_ADDRESS); |
88 | assertArrayEquals(rd.getDestinationAddress(), DESTINATION_ADDRESS); | 97 | assertArrayEquals(rd.getDestinationAddress(), DESTINATION_ADDRESS); |
98 | + | ||
99 | + // Check the option(s) | ||
100 | + assertThat(rd.getOptions().size(), is(1)); | ||
101 | + NeighborDiscoveryOptions.Option option = rd.getOptions().get(0); | ||
102 | + assertThat(option.type(), | ||
103 | + is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS)); | ||
104 | + assertArrayEquals(option.data(), MAC_ADDRESS.toBytes()); | ||
89 | } | 105 | } |
90 | 106 | ||
91 | /** | 107 | /** |
... | @@ -96,10 +112,14 @@ public class RedirectTest { | ... | @@ -96,10 +112,14 @@ public class RedirectTest { |
96 | Redirect rd1 = new Redirect(); | 112 | Redirect rd1 = new Redirect(); |
97 | rd1.setTargetAddress(TARGET_ADDRESS); | 113 | rd1.setTargetAddress(TARGET_ADDRESS); |
98 | rd1.setDestinationAddress(DESTINATION_ADDRESS); | 114 | rd1.setDestinationAddress(DESTINATION_ADDRESS); |
115 | + rd1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
116 | + MAC_ADDRESS.toBytes()); | ||
99 | 117 | ||
100 | Redirect rd2 = new Redirect(); | 118 | Redirect rd2 = new Redirect(); |
101 | rd2.setTargetAddress(TARGET_ADDRESS); | 119 | rd2.setTargetAddress(TARGET_ADDRESS); |
102 | rd2.setDestinationAddress(DESTINATION_ADDRESS2); | 120 | rd2.setDestinationAddress(DESTINATION_ADDRESS2); |
121 | + rd2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
122 | + MAC_ADDRESS.toBytes()); | ||
103 | 123 | ||
104 | assertTrue(rd1.equals(rd1)); | 124 | assertTrue(rd1.equals(rd1)); |
105 | assertFalse(rd1.equals(rd2)); | 125 | assertFalse(rd1.equals(rd2)); | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,14 +13,11 @@ | ... | @@ -13,14 +13,11 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.junit.BeforeClass; | 18 | import org.junit.BeforeClass; |
22 | import org.junit.Test; | 19 | import org.junit.Test; |
23 | -import org.onlab.packet.Data; | 20 | +import org.onlab.packet.MacAddress; |
24 | 21 | ||
25 | import static org.hamcrest.Matchers.is; | 22 | import static org.hamcrest.Matchers.is; |
26 | import static org.junit.Assert.assertArrayEquals; | 23 | import static org.junit.Assert.assertArrayEquals; |
... | @@ -32,23 +29,22 @@ import static org.junit.Assert.assertTrue; | ... | @@ -32,23 +29,22 @@ import static org.junit.Assert.assertTrue; |
32 | * Tests for class {@link RouterAdvertisement}. | 29 | * Tests for class {@link RouterAdvertisement}. |
33 | */ | 30 | */ |
34 | public class RouterAdvertisementTest { | 31 | public class RouterAdvertisementTest { |
35 | - private static Data data; | 32 | + private static final MacAddress MAC_ADDRESS = |
33 | + MacAddress.valueOf("11:22:33:44:55:66"); | ||
34 | + | ||
36 | private static byte[] bytePacket; | 35 | private static byte[] bytePacket; |
37 | 36 | ||
38 | @BeforeClass | 37 | @BeforeClass |
39 | public static void setUpBeforeClass() throws Exception { | 38 | public static void setUpBeforeClass() throws Exception { |
40 | - data = new Data(); | ||
41 | - data.setData("".getBytes()); | ||
42 | - | ||
43 | - byte[] bytePayload = data.serialize(); | ||
44 | byte[] byteHeader = { | 39 | byte[] byteHeader = { |
45 | (byte) 0x03, (byte) 0xc0, (byte) 0x02, (byte) 0x58, | 40 | (byte) 0x03, (byte) 0xc0, (byte) 0x02, (byte) 0x58, |
46 | (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0xe8, | 41 | (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0xe8, |
47 | - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xf4 | 42 | + (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0xf4, |
43 | + (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22, | ||
44 | + (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 | ||
48 | }; | 45 | }; |
49 | - bytePacket = new byte[byteHeader.length + bytePayload.length]; | 46 | + bytePacket = new byte[byteHeader.length]; |
50 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); | 47 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); |
51 | - System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length); | ||
52 | } | 48 | } |
53 | 49 | ||
54 | /** | 50 | /** |
... | @@ -63,7 +59,8 @@ public class RouterAdvertisementTest { | ... | @@ -63,7 +59,8 @@ public class RouterAdvertisementTest { |
63 | ra.setRouterLifetime((short) 0x258); | 59 | ra.setRouterLifetime((short) 0x258); |
64 | ra.setReachableTime(0x3e8); | 60 | ra.setReachableTime(0x3e8); |
65 | ra.setRetransmitTimer(0x1f4); | 61 | ra.setRetransmitTimer(0x1f4); |
66 | - ra.setPayload(data); | 62 | + ra.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
63 | + MAC_ADDRESS.toBytes()); | ||
67 | 64 | ||
68 | assertArrayEquals(ra.serialize(), bytePacket); | 65 | assertArrayEquals(ra.serialize(), bytePacket); |
69 | } | 66 | } |
... | @@ -82,6 +79,13 @@ public class RouterAdvertisementTest { | ... | @@ -82,6 +79,13 @@ public class RouterAdvertisementTest { |
82 | assertThat(ra.getRouterLifetime(), is((short) 0x258)); | 79 | assertThat(ra.getRouterLifetime(), is((short) 0x258)); |
83 | assertThat(ra.getReachableTime(), is(0x3e8)); | 80 | assertThat(ra.getReachableTime(), is(0x3e8)); |
84 | assertThat(ra.getRetransmitTimer(), is(0x1f4)); | 81 | assertThat(ra.getRetransmitTimer(), is(0x1f4)); |
82 | + | ||
83 | + // Check the option(s) | ||
84 | + assertThat(ra.getOptions().size(), is(1)); | ||
85 | + NeighborDiscoveryOptions.Option option = ra.getOptions().get(0); | ||
86 | + assertThat(option.type(), | ||
87 | + is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS)); | ||
88 | + assertArrayEquals(option.data(), MAC_ADDRESS.toBytes()); | ||
85 | } | 89 | } |
86 | 90 | ||
87 | /** | 91 | /** |
... | @@ -96,6 +100,8 @@ public class RouterAdvertisementTest { | ... | @@ -96,6 +100,8 @@ public class RouterAdvertisementTest { |
96 | ra1.setRouterLifetime((short) 0x258); | 100 | ra1.setRouterLifetime((short) 0x258); |
97 | ra1.setReachableTime(0x3e8); | 101 | ra1.setReachableTime(0x3e8); |
98 | ra1.setRetransmitTimer(0x1f4); | 102 | ra1.setRetransmitTimer(0x1f4); |
103 | + ra1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
104 | + MAC_ADDRESS.toBytes()); | ||
99 | 105 | ||
100 | RouterAdvertisement ra2 = new RouterAdvertisement(); | 106 | RouterAdvertisement ra2 = new RouterAdvertisement(); |
101 | ra2.setCurrentHopLimit((byte) 3); | 107 | ra2.setCurrentHopLimit((byte) 3); |
... | @@ -104,6 +110,8 @@ public class RouterAdvertisementTest { | ... | @@ -104,6 +110,8 @@ public class RouterAdvertisementTest { |
104 | ra2.setRouterLifetime((short) 0x1f4); | 110 | ra2.setRouterLifetime((short) 0x1f4); |
105 | ra2.setReachableTime(0x3e8); | 111 | ra2.setReachableTime(0x3e8); |
106 | ra2.setRetransmitTimer(0x1f4); | 112 | ra2.setRetransmitTimer(0x1f4); |
113 | + ra2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
114 | + MAC_ADDRESS.toBytes()); | ||
107 | 115 | ||
108 | assertTrue(ra1.equals(ra1)); | 116 | assertTrue(ra1.equals(ra1)); |
109 | assertFalse(ra1.equals(ra2)); | 117 | assertFalse(ra1.equals(ra2)); | ... | ... |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2014-2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -13,38 +13,38 @@ | ... | @@ -13,38 +13,38 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | - | ||
17 | - | ||
18 | - | ||
19 | package org.onlab.packet.ndp; | 16 | package org.onlab.packet.ndp; |
20 | 17 | ||
21 | import org.junit.BeforeClass; | 18 | import org.junit.BeforeClass; |
22 | import org.junit.Test; | 19 | import org.junit.Test; |
23 | -import org.onlab.packet.Data; | 20 | +import org.onlab.packet.MacAddress; |
24 | 21 | ||
22 | +import static org.hamcrest.Matchers.is; | ||
25 | import static org.junit.Assert.assertArrayEquals; | 23 | import static org.junit.Assert.assertArrayEquals; |
24 | +import static org.junit.Assert.assertFalse; | ||
25 | +import static org.junit.Assert.assertThat; | ||
26 | import static org.junit.Assert.assertTrue; | 26 | import static org.junit.Assert.assertTrue; |
27 | 27 | ||
28 | /** | 28 | /** |
29 | * Tests for class {@link RouterSolicitation}. | 29 | * Tests for class {@link RouterSolicitation}. |
30 | */ | 30 | */ |
31 | public class RouterSolicitationTest { | 31 | public class RouterSolicitationTest { |
32 | - private static final byte[] OPTION = { | 32 | + private static final MacAddress MAC_ADDRESS1 = |
33 | - (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01 | 33 | + MacAddress.valueOf("11:22:33:44:55:66"); |
34 | - }; | 34 | + private static final MacAddress MAC_ADDRESS2 = |
35 | - private static Data data; | 35 | + MacAddress.valueOf("11:22:33:44:55:00"); |
36 | + | ||
36 | private static byte[] bytePacket; | 37 | private static byte[] bytePacket; |
37 | 38 | ||
38 | @BeforeClass | 39 | @BeforeClass |
39 | public static void setUpBeforeClass() throws Exception { | 40 | public static void setUpBeforeClass() throws Exception { |
40 | - data = new Data(); | 41 | + byte[] byteHeader = { |
41 | - data.setData(OPTION); | 42 | + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, |
42 | - | 43 | + (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22, |
43 | - byte[] bytePayload = data.serialize(); | 44 | + (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 |
44 | - byte[] byteHeader = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; | 45 | + }; |
45 | - bytePacket = new byte[byteHeader.length + bytePayload.length]; | 46 | + bytePacket = new byte[byteHeader.length]; |
46 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); | 47 | System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length); |
47 | - System.arraycopy(bytePayload, 0, bytePacket, byteHeader.length, bytePayload.length); | ||
48 | } | 48 | } |
49 | 49 | ||
50 | /** | 50 | /** |
... | @@ -53,7 +53,8 @@ public class RouterSolicitationTest { | ... | @@ -53,7 +53,8 @@ public class RouterSolicitationTest { |
53 | @Test | 53 | @Test |
54 | public void testSerialize() { | 54 | public void testSerialize() { |
55 | RouterSolicitation rs = new RouterSolicitation(); | 55 | RouterSolicitation rs = new RouterSolicitation(); |
56 | - rs.setPayload(data); | 56 | + rs.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, |
57 | + MAC_ADDRESS1.toBytes()); | ||
57 | 58 | ||
58 | assertArrayEquals(rs.serialize(), bytePacket); | 59 | assertArrayEquals(rs.serialize(), bytePacket); |
59 | } | 60 | } |
... | @@ -65,6 +66,13 @@ public class RouterSolicitationTest { | ... | @@ -65,6 +66,13 @@ public class RouterSolicitationTest { |
65 | public void testDeserialize() { | 66 | public void testDeserialize() { |
66 | RouterSolicitation rs = new RouterSolicitation(); | 67 | RouterSolicitation rs = new RouterSolicitation(); |
67 | rs.deserialize(bytePacket, 0, bytePacket.length); | 68 | rs.deserialize(bytePacket, 0, bytePacket.length); |
69 | + | ||
70 | + // Check the option(s) | ||
71 | + assertThat(rs.getOptions().size(), is(1)); | ||
72 | + NeighborDiscoveryOptions.Option option = rs.getOptions().get(0); | ||
73 | + assertThat(option.type(), | ||
74 | + is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS)); | ||
75 | + assertArrayEquals(option.data(), MAC_ADDRESS1.toBytes()); | ||
68 | } | 76 | } |
69 | 77 | ||
70 | /** | 78 | /** |
... | @@ -73,7 +81,14 @@ public class RouterSolicitationTest { | ... | @@ -73,7 +81,14 @@ public class RouterSolicitationTest { |
73 | @Test | 81 | @Test |
74 | public void testEqual() { | 82 | public void testEqual() { |
75 | RouterSolicitation rs1 = new RouterSolicitation(); | 83 | RouterSolicitation rs1 = new RouterSolicitation(); |
84 | + rs1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
85 | + MAC_ADDRESS1.toBytes()); | ||
86 | + | ||
87 | + RouterSolicitation rs2 = new RouterSolicitation(); | ||
88 | + rs2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, | ||
89 | + MAC_ADDRESS2.toBytes()); | ||
76 | 90 | ||
77 | assertTrue(rs1.equals(rs1)); | 91 | assertTrue(rs1.equals(rs1)); |
92 | + assertFalse(rs1.equals(rs2)); | ||
78 | } | 93 | } |
79 | } | 94 | } | ... | ... |
-
Please register or login to post a comment