blob: db345149e92abe38aa8cd8b6634f88248d356e9b [file] [log] [blame]
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +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;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080017
Jian Li5fc14292015-12-04 11:30:46 -080018import org.apache.commons.lang3.StringUtils;
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +020019import org.hamcrest.Description;
20import org.hamcrest.TypeSafeMatcher;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080021import org.junit.BeforeClass;
22import org.junit.Test;
Jonathan Hart2a655752015-04-07 16:46:33 -070023import org.onlab.packet.DeserializationException;
24import org.onlab.packet.Deserializer;
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +020025import org.onlab.packet.Ethernet;
26import org.onlab.packet.ICMP6;
27import org.onlab.packet.IPv6;
28import org.onlab.packet.Ip6Address;
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080029import org.onlab.packet.MacAddress;
Charles Chan3599d632015-09-05 14:47:51 +080030import org.onlab.packet.PacketTestUtils;
31
32import java.nio.ByteBuffer;
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +020033import java.util.Arrays;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080034
35import static org.hamcrest.Matchers.is;
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +020036import static org.hamcrest.core.IsCollectionContaining.hasItem;
Jian Li5fc14292015-12-04 11:30:46 -080037import static org.junit.Assert.*;
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080038
39/**
40 * Tests for class {@link NeighborAdvertisement}.
41 */
42public class NeighborAdvertisementTest {
43 private static final byte[] TARGET_ADDRESS = {
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080044 (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18,
45 (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15,
46 (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff,
47 (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080048 };
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080049 private static final MacAddress MAC_ADDRESS =
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +020050 MacAddress.valueOf("11:22:33:44:55:66");
51 private static final MacAddress MAC_ADDRESS2 =
52 MacAddress.valueOf("10:20:30:40:50:60");
53 private static final byte[] IPV6_SOURCE_ADDRESS = {
54 (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
55 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01
56 };
57 private static final byte[] IPV6_DESTINATION_ADDRESS = {
58 (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
59 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02
60 };
61 private static final Ip6Address IP_6_ADDRESS = Ip6Address.valueOf(IPV6_DESTINATION_ADDRESS);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080062
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080063 private static byte[] bytePacket;
64
Jonathan Hart2a655752015-04-07 16:46:33 -070065 private Deserializer<NeighborAdvertisement> deserializer
66 = NeighborAdvertisement.deserializer();
67
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080068 @BeforeClass
69 public static void setUpBeforeClass() throws Exception {
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080070 byte[] byteHeader = {
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080071 (byte) 0xe0, (byte) 0x00, (byte) 0x00, (byte) 0x00,
72 (byte) 0x20, (byte) 0x01, (byte) 0x0f, (byte) 0x18,
73 (byte) 0x01, (byte) 0x13, (byte) 0x02, (byte) 0x15,
74 (byte) 0xca, (byte) 0x2a, (byte) 0x14, (byte) 0xff,
75 (byte) 0xfe, (byte) 0x35, (byte) 0x26, (byte) 0xce,
76 (byte) 0x02, (byte) 0x01, (byte) 0x11, (byte) 0x22,
77 (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080078 };
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080079 bytePacket = new byte[byteHeader.length];
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080080 System.arraycopy(byteHeader, 0, bytePacket, 0, byteHeader.length);
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080081 }
82
83 /**
84 * Tests serialize and setters.
85 */
86 @Test
87 public void testSerialize() {
88 NeighborAdvertisement na = new NeighborAdvertisement();
89 na.setRouterFlag((byte) 1);
90 na.setSolicitedFlag((byte) 1);
91 na.setOverrideFlag((byte) 1);
92 na.setTargetAddress(TARGET_ADDRESS);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -080093 na.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
94 MAC_ADDRESS.toBytes());
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +080095
96 assertArrayEquals(na.serialize(), bytePacket);
97 }
98
Charles Chan3599d632015-09-05 14:47:51 +080099 @Test
100 public void testDeserializeBadInput() throws Exception {
101 PacketTestUtils.testDeserializeBadInput(NeighborAdvertisement.deserializer());
102 }
103
104 @Test
105 public void testDeserializeTruncated() throws Exception {
106 // Run the truncation test only on the NeighborAdvertisement header
107 byte[] naHeader = new byte[NeighborAdvertisement.HEADER_LENGTH];
108 ByteBuffer.wrap(bytePacket).get(naHeader);
109
110 PacketTestUtils.testDeserializeTruncated(NeighborAdvertisement.deserializer(), naHeader);
111 }
112
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800113 /**
114 * Tests deserialize and getters.
115 */
116 @Test
Jonathan Hart2a655752015-04-07 16:46:33 -0700117 public void testDeserialize() throws DeserializationException {
118 NeighborAdvertisement na = deserializer.deserialize(bytePacket, 0, bytePacket.length);
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800119
120 assertThat(na.getRouterFlag(), is((byte) 1));
121 assertThat(na.getSolicitedFlag(), is((byte) 1));
122 assertThat(na.getOverrideFlag(), is((byte) 1));
123 assertArrayEquals(na.getTargetAddress(), TARGET_ADDRESS);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800124
125 // Check the option(s)
126 assertThat(na.getOptions().size(), is(1));
127 NeighborDiscoveryOptions.Option option = na.getOptions().get(0);
128 assertThat(option.type(),
129 is(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS));
130 assertArrayEquals(option.data(), MAC_ADDRESS.toBytes());
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800131 }
132
133 /**
134 * Tests comparator.
135 */
136 @Test
137 public void testEqual() {
138 NeighborAdvertisement na1 = new NeighborAdvertisement();
139 na1.setRouterFlag((byte) 1);
140 na1.setSolicitedFlag((byte) 1);
141 na1.setOverrideFlag((byte) 1);
142 na1.setTargetAddress(TARGET_ADDRESS);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800143 na1.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
144 MAC_ADDRESS.toBytes());
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800145
146 NeighborAdvertisement na2 = new NeighborAdvertisement();
147 na2.setRouterFlag((byte) 1);
148 na2.setSolicitedFlag((byte) 1);
149 na2.setOverrideFlag((byte) 0);
150 na2.setTargetAddress(TARGET_ADDRESS);
Pavlin Radoslavova2626ef2015-02-18 18:33:25 -0800151 na2.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
152 MAC_ADDRESS.toBytes());
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800153
154 assertTrue(na1.equals(na1));
155 assertFalse(na1.equals(na2));
156 }
Jian Li5fc14292015-12-04 11:30:46 -0800157
158 /**
159 * Tests toString.
160 */
161 @Test
162 public void testToStringNA() throws Exception {
163 NeighborAdvertisement na = deserializer.deserialize(bytePacket, 0, bytePacket.length);
164 String str = na.toString();
165
166 assertTrue(StringUtils.contains(str, "routerFlag=" + (byte) 1));
167 assertTrue(StringUtils.contains(str, "solicitedFlag=" + (byte) 1));
168 assertTrue(StringUtils.contains(str, "overrideFlag=" + (byte) 1));
169 // TODO: need to handle TARGET_ADDRESS
170 }
Bartlomiej Goluszka08537a82017-06-12 15:18:32 +0200171
172 /**
173 * Test Neighbor Advertisement reply build.
174 */
175 @Test
176 public void testBuildNdpAdv() {
177 Ethernet eth = new Ethernet();
178 eth.setSourceMACAddress(MAC_ADDRESS);
179 eth.setDestinationMACAddress(MAC_ADDRESS2);
180
181 IPv6 ipv6 = new IPv6();
182 ipv6.setSourceAddress(IPV6_SOURCE_ADDRESS);
183 ipv6.setDestinationAddress(IPV6_DESTINATION_ADDRESS);
184 ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
185
186 eth.setEtherType(Ethernet.TYPE_IPV6);
187 eth.setPayload(ipv6);
188
189 ICMP6 icmp6 = new ICMP6();
190 icmp6.setIcmpType(ICMP6.NEIGHBOR_SOLICITATION);
191 icmp6.setIcmpCode(NeighborAdvertisement.RESERVED_CODE);
192 ipv6.setPayload(icmp6);
193
194 final Ethernet ethResponse = NeighborAdvertisement.buildNdpAdv(IP_6_ADDRESS, MAC_ADDRESS2, eth);
195
196 assertTrue(ethResponse.getDestinationMAC().equals(MAC_ADDRESS));
197 assertTrue(ethResponse.getSourceMAC().equals(MAC_ADDRESS2));
198 assertTrue(ethResponse.getEtherType() == Ethernet.TYPE_IPV6);
199
200 final IPv6 responseIpv6 = (IPv6) ethResponse.getPayload();
201
202 assertArrayEquals(responseIpv6.getSourceAddress(), ipv6.getDestinationAddress());
203 assertArrayEquals(responseIpv6.getDestinationAddress(), ipv6.getSourceAddress());
204 assertTrue(responseIpv6.getNextHeader() == IPv6.PROTOCOL_ICMP6);
205
206 final ICMP6 responseIcmp6 = (ICMP6) responseIpv6.getPayload();
207
208 assertTrue(responseIcmp6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT);
209 assertTrue(responseIcmp6.getIcmpCode() == NeighborAdvertisement.RESERVED_CODE);
210
211 final NeighborAdvertisement responseNadv = (NeighborAdvertisement) responseIcmp6.getPayload();
212
213 assertArrayEquals(responseNadv.getTargetAddress(), IPV6_DESTINATION_ADDRESS);
214 assertTrue(responseNadv.getSolicitedFlag() == NeighborAdvertisement.NDP_SOLICITED_FLAG);
215 assertTrue(responseNadv.getOverrideFlag() == NeighborAdvertisement.NDP_OVERRIDE_FLAG);
216 assertThat(responseNadv.getOptions(),
217 hasItem(hasOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS, MAC_ADDRESS2.toBytes())));
218 }
219
220 private NeighborDiscoveryOptionMatcher hasOption(byte type, byte[] data) {
221 return new NeighborDiscoveryOptionMatcher(type, data);
222 }
223
224 private static class NeighborDiscoveryOptionMatcher extends TypeSafeMatcher<NeighborDiscoveryOptions.Option> {
225
226 private final byte type;
227 private final byte[] data;
228 private String reason = "";
229
230 NeighborDiscoveryOptionMatcher(byte type, byte[] data) {
231 this.type = type;
232 this.data = data;
233 }
234
235 @Override
236 protected boolean matchesSafely(NeighborDiscoveryOptions.Option option) {
237 if (type != option.type()) {
238 reason = "Wrong Option type";
239 return false;
240 }
241 if (!Arrays.equals(data, option.data())) {
242 reason = "Wrong Option data";
243 return false;
244 }
245 return true;
246 }
247
248 @Override
249 public void describeTo(Description description) {
250 description.appendText(reason);
251 }
252 }
Charles M.C. Chan93b7fb02014-12-28 03:59:36 +0800253}