blob: 0608ee69146c8f4fbe06ade8bb0e2b64f74dff0b [file] [log] [blame]
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001/*
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03002 * Copyright 2016-present Open Networking Laboratory
Andreas Papazois6e1fca32016-02-09 11:27:10 +02003 *
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 */
16package org.onosproject.sdxl3;
17
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030018import com.google.common.collect.Lists;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020019import com.google.common.collect.Sets;
20import org.junit.Before;
21import org.junit.Test;
22import org.onlab.packet.ARP;
23import org.onlab.packet.Ethernet;
24import org.onlab.packet.ICMP6;
25import org.onlab.packet.IPacket;
26import org.onlab.packet.IPv6;
27import org.onlab.packet.Ip4Address;
28import org.onlab.packet.Ip4Prefix;
29import org.onlab.packet.Ip6Address;
30import org.onlab.packet.Ip6Prefix;
31import org.onlab.packet.IpAddress;
32import org.onlab.packet.IpPrefix;
33import org.onlab.packet.MacAddress;
34import org.onlab.packet.VlanId;
35import org.onlab.packet.ndp.NeighborAdvertisement;
36import org.onlab.packet.ndp.NeighborDiscoveryOptions;
37import org.onlab.packet.ndp.NeighborSolicitation;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030038import org.onosproject.TestApplicationId;
39import org.onosproject.core.ApplicationId;
40import org.onosproject.core.CoreService;
41import org.onosproject.core.CoreServiceAdapter;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020042import org.onosproject.incubator.net.intf.Interface;
43import org.onosproject.incubator.net.intf.InterfaceService;
44import org.onosproject.net.ConnectPoint;
45import org.onosproject.net.DefaultHost;
46import org.onosproject.net.Device;
47import org.onosproject.net.DeviceId;
48import org.onosproject.net.Host;
49import org.onosproject.net.HostId;
50import org.onosproject.net.HostLocation;
51import org.onosproject.net.Link;
52import org.onosproject.net.Port;
53import org.onosproject.net.PortNumber;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030054import org.onosproject.net.config.Config;
55import org.onosproject.net.config.NetworkConfigService;
56import org.onosproject.net.config.NetworkConfigServiceAdapter;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020057import org.onosproject.net.device.DeviceListener;
58import org.onosproject.net.device.DeviceService;
59import org.onosproject.net.edge.EdgePortService;
60import org.onosproject.net.flow.instructions.Instruction;
61import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
62import org.onosproject.net.host.HostService;
63import org.onosproject.net.host.InterfaceIpAddress;
64import org.onosproject.net.link.LinkListener;
65import org.onosproject.net.link.LinkService;
66import org.onosproject.net.packet.DefaultInboundPacket;
67import org.onosproject.net.packet.InboundPacket;
68import org.onosproject.net.packet.OutboundPacket;
69import org.onosproject.net.packet.PacketServiceAdapter;
70import org.onosproject.net.provider.ProviderId;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030071import org.onosproject.routing.RoutingService;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020072import org.onosproject.routing.config.BgpConfig;
73
74import java.nio.ByteBuffer;
75import java.util.ArrayList;
76import java.util.Arrays;
77import java.util.Collections;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030078import java.util.HashMap;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020079import java.util.HashSet;
80import java.util.List;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +030081import java.util.Map;
Andreas Papazois6e1fca32016-02-09 11:27:10 +020082import java.util.Optional;
83import java.util.Set;
84
85import static org.easymock.EasyMock.anyObject;
86import static org.easymock.EasyMock.createMock;
87import static org.easymock.EasyMock.expect;
88import static org.easymock.EasyMock.replay;
89import static org.easymock.EasyMock.reset;
90import static org.hamcrest.Matchers.anyOf;
91import static org.hamcrest.Matchers.is;
92import static org.junit.Assert.assertArrayEquals;
93import static org.junit.Assert.assertEquals;
94import static org.junit.Assert.assertNotNull;
95import static org.junit.Assert.assertThat;
96import static org.junit.Assert.assertTrue;
97
98/**
99 * Tests for the {@link SdxL3ArpHandler} class. It is based on tests for basic
100 * proxy ARP handling. Additional test cases for traffic between BGP peers are
101 * also included.
102 */
103public class SdxL3ArpHandlerTest {
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300104 private static final ApplicationId ROUTER_APPID =
105 TestApplicationId.create("foo");
106 private static final ApplicationId SDXL3_APPID =
107 TestApplicationId.create("bar");
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200108
109 private static final int NUM_DEVICES = 10;
110 private static final int NUM_PORTS_PER_DEVICE = 3;
111 private static final int LAST_CONF_DEVICE_INTF_VLAN_IP = 3;
112 private static final int LAST_CONF_DEVICE_INTF_VLAN = 6;
113
114 private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
115 private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
116 private static final Ip6Address IP3 = Ip6Address.valueOf("1000:ffff::1");
117 private static final Ip6Address IP4 = Ip6Address.valueOf("1000:ffff::2");
118
119 private static final ProviderId PID = new ProviderId("of", "foo");
120
121 private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
122 private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
123 private static final VlanId VLAN10 = VlanId.vlanId((short) 10);
124
125 private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
126 private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
127 private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
128 private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300129 private static final MacAddress MAC5 = MacAddress.valueOf("00:00:00:00:00:05");
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200130 private static final MacAddress MAC10 = MacAddress.valueOf("00:00:00:00:00:0A");
131
132 private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
133
134 private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
135 private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
136 private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
137 private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300138 private static final HostId HID5 = HostId.hostId(MAC5, VLAN1);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200139 private static final HostId HID10 = HostId.hostId(MAC10, VLAN10);
140
141 private static final DeviceId DID1 = getDeviceId(1);
142 private static final DeviceId DID2 = getDeviceId(2);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300143 private static final DeviceId DID3 = getDeviceId(100);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200144
145 private static final PortNumber P1 = PortNumber.portNumber(1);
146
147 private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
148 private static final ConnectPoint CP2 = new ConnectPoint(DID2, P1);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300149 private static final ConnectPoint CP3 = new ConnectPoint(DID3, P1);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200150
151 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300152 private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200153
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300154 private static final String SPEAKER_IP_STRING = "10.0.2.201";
155 private static final Ip4Address SPEAKER_IP = Ip4Address.valueOf(SPEAKER_IP_STRING);
156 private static final IpPrefix INTF1_IP_PREFIX = IpPrefix.valueOf(SPEAKER_IP_STRING + "/24");
157 private static final String PEER1_IP_STRING = "10.0.1.1";
158 private static final Ip4Address PEER1_IP = Ip4Address.valueOf(PEER1_IP_STRING);
159 private static final String PEER2_IP_STRING = "10.0.1.2";
160 private static final Ip4Address PEER2_IP = Ip4Address.valueOf(PEER2_IP_STRING);
161 private static final String PEER3_IP_STRING = "10.0.2.1";
162 private static final Ip4Address PEER3_IP = Ip4Address.valueOf(PEER3_IP_STRING);
163 private static final String SPEAKER_IP6_STRING = "1001::1";
164 private static final Ip6Address SPEAKER_IP6 = Ip6Address.valueOf(SPEAKER_IP6_STRING);
165 private static final IpPrefix INTF2_IP6_PREFIX = IpPrefix.valueOf(SPEAKER_IP6_STRING + "/64");
166 private static final String PEER1_IP6_STRING = "1001::100";
167 private static final Ip6Address PEER1_IP6 = Ip6Address.valueOf(PEER1_IP6_STRING);
168 private static final String PEER2_IP6_STRING = "1001::200";
169 private static final Ip6Address PEER2_IP6 = Ip6Address.valueOf(PEER2_IP6_STRING);
170 private static final String PEER3_IP6_STRING = "1001::1000";
171 private static final Ip6Address PEER3_IP6 = Ip6Address.valueOf(PEER3_IP6_STRING);
172 private static final String INTF1_NAME = "intf1";
173 private static final String INTF2_NAME = "intf2";
174 private static final String INTF_NAME_PREFIX = "intf";
175 private static final String NO_NAME = "";
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200176
177 private final byte[] zeroMacAddress = MacAddress.ZERO.toBytes();
178
179 // The first three devices in the topology have interfaces configured
180 // with VLANs and IPs
181 private final List<ConnectPoint> configIpCPoints = new ArrayList<>();
182
183 // Other three devices in the topology (from 4 to 6) have interfaces
184 // configured only with VLANs
185 private final List<ConnectPoint> configVlanCPoints = new ArrayList<>();
186
187 // Remaining devices in the network (id > 6) don't have any interface
188 // configured.
189 private final List<ConnectPoint> noConfigCPoints = new ArrayList<>();
190
191 private SdxL3ArpHandler proxyArp;
192
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300193 private CoreService coreService;
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200194 private InterfaceService interfaceService;
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300195 private EdgePortService edgePortService;
196 private HostService hostService;
197 private TestPacketService packetService;
198 private NetworkConfigService networkConfigService;
199 private SdxL3PeerService sdxL3PeerService;
200 private BgpConfig bgpConfig;
201
202 private DeviceService deviceService;
203 private LinkService linkService;
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200204
205 @Before
206 public void setUp() throws Exception {
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200207 interfaceService = createMock(InterfaceService.class);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300208 edgePortService = createMock(EdgePortService.class);
209 hostService = createMock(HostService.class);
210 sdxL3PeerService = createMock(SdxL3PeerService.class);
211 bgpConfig = createMock(BgpConfig.class);
212 coreService = new TestCoreService();
213 packetService = new TestPacketService();
214 networkConfigService = new TestNetworkConfigService();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200215
216 // Create the topology
217 createTopology();
218
219 setupNoConfigCPoints();
220 setupconfigIpCPoints();
221 setupconfigVlanCPoints();
222
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300223 proxyArp = new SdxL3ArpHandler();
224 proxyArp.coreService = coreService;
225 proxyArp.interfaceService = interfaceService;
226 proxyArp.edgeService = edgePortService;
227 proxyArp.hostService = hostService;
228 proxyArp.packetService = packetService;
229 proxyArp.networkConfigService = networkConfigService;
230 proxyArp.sdxL3PeerService = sdxL3PeerService;
231 proxyArp.activate();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200232 }
233
234 /**
235 * Creates a fake topology to feed into the ARP module.
236 * <p>
237 * The default topology is a unidirectional ring topology. Each switch has
238 * 3 ports. Ports 2 and 3 have the links to neighbor switches, and port 1
239 * is free (edge port).
240 * The first half of the switches have IP addresses configured on their
241 * free ports (port 1). The second half of the switches have no IP
242 * addresses configured.
243 */
244 private void createTopology() {
245 deviceService = createMock(DeviceService.class);
246 linkService = createMock(LinkService.class);
247
248 deviceService.addListener(anyObject(DeviceListener.class));
249 linkService.addListener(anyObject(LinkListener.class));
250
251 createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE);
252 createLinks(NUM_DEVICES);
253 addIntfConfig();
254 addEmptyBgpConfig();
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300255 populateEdgePortService();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200256 }
257
258 /**
259 * Creates the devices for the fake topology.
260 */
261 private void createDevices(int numDevices, int numPorts) {
262 List<Device> devices = new ArrayList<>();
263
264 for (int i = 1; i <= numDevices; i++) {
265 DeviceId devId = getDeviceId(i);
266 Device device = createMock(Device.class);
267 expect(device.id()).andReturn(devId).anyTimes();
268 replay(device);
269
270 devices.add(device);
271
272 List<Port> ports = new ArrayList<>();
273 for (int j = 1; j <= numPorts; j++) {
274 Port port = createMock(Port.class);
275 expect(port.number()).andReturn(PortNumber.portNumber(j)).anyTimes();
276 replay(port);
277 ports.add(port);
278 }
279
280 expect(deviceService.getPorts(devId)).andReturn(ports).anyTimes();
281 expect(deviceService.getDevice(devId)).andReturn(device).anyTimes();
282 }
283
284 expect(deviceService.getDevices()).andReturn(devices).anyTimes();
285 replay(deviceService);
286 }
287
288 /**
289 * Creates the links for the fake topology.
290 * NB: Only unidirectional links are created, as for this purpose all we
291 * need is to occupy the ports with some link.
292 */
293 private void createLinks(int numDevices) {
294 List<Link> links = new ArrayList<>();
295
296 for (int i = 1; i <= numDevices; i++) {
297 ConnectPoint src = new ConnectPoint(
298 getDeviceId(i),
299 PortNumber.portNumber(2));
300 ConnectPoint dst = new ConnectPoint(
301 getDeviceId((i + 1 > numDevices) ? 1 : i + 1),
302 PortNumber.portNumber(3));
303
304 Link link = createMock(Link.class);
305 expect(link.src()).andReturn(src).anyTimes();
306 expect(link.dst()).andReturn(dst).anyTimes();
307 replay(link);
308
309 links.add(link);
310 }
311
312 expect(linkService.getLinks()).andReturn(links).anyTimes();
313 replay(linkService);
314 }
315
316 /**
317 * On the first three devices two config interfaces are binded on port 1.
318 * The first one with VLAN1, the second one with VLAN equals to none.
319 * Both interfaces have an IP.
320 * On devices 4, 5 and 6 it's binded a config interface on port 1.
321 * The interface is configured with VLAN 1 and no IP.
322 */
323 private void addIntfConfig() {
324 Set<Interface> interfaces = Sets.newHashSet();
325
326 Set<Interface> vlanOneSet = new HashSet<>();
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300327 Set<Interface> vlanTwoSet = new HashSet<>();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200328
329 for (int i = 1; i <= LAST_CONF_DEVICE_INTF_VLAN_IP; i++) {
330 ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
331
332 // Interface addresses for IPv4
333 Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
334 Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
335 Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
336 Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
337 InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
338 InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
339
340 // Interface addresses for IPv6
341 Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
342 Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
343 Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
344 Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::2");
345 InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
346 InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
347
348 // Setting up interfaces
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300349 Interface intf1 = new Interface(INTF1_NAME, cp,
350 Lists.newArrayList(ia1, ia3),
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200351 MacAddress.valueOf(2 * i - 1),
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300352 VLAN1);
353 Interface intf2 = new Interface(INTF2_NAME, cp,
354 Lists.newArrayList(ia2, ia4),
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200355 MacAddress.valueOf(2 * i),
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300356 VLAN2);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200357
358 interfaces.add(intf1);
359 interfaces.add(intf2);
360
361 vlanOneSet.add(intf1);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300362 vlanTwoSet.add(intf2);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200363
364 expect(interfaceService.getInterfacesByPort(cp))
365 .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes();
366 }
367 for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
368 ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300369 Interface intf = new Interface(INTF_NAME_PREFIX + i, cp,
370 Collections.emptyList(),
371 MacAddress.NONE,
372 VlanId.vlanId((short) 1));
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200373
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300374 interfaces.add(intf);
375 vlanOneSet.add(intf);
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200376
377 expect(interfaceService.getInterfacesByPort(cp))
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300378 .andReturn(Sets.newHashSet(intf)).anyTimes();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200379 }
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300380 expect(interfaceService.getInterfacesByPort(CP3))
381 .andReturn(Collections.emptySet()).anyTimes();
382
383 expect(interfaceService.getInterfacesByVlan(VlanId.NONE))
384 .andReturn(vlanTwoSet).anyTimes();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200385 expect(interfaceService.getInterfacesByVlan(VLAN1))
386 .andReturn(vlanOneSet).anyTimes();
387 expect(interfaceService.getInterfacesByVlan(VLAN10))
388 .andReturn(Collections.emptySet()).anyTimes();
389 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
390
391 for (int i = LAST_CONF_DEVICE_INTF_VLAN + 1; i <= NUM_DEVICES; i++) {
392 ConnectPoint cp = new ConnectPoint(getDeviceId(i),
393 P1);
394 expect(interfaceService.getInterfacesByPort(cp))
395 .andReturn(Collections.emptySet()).anyTimes();
396 }
397 }
398
399 /**
400 * Adds an empty BGP configuration for the purposes of basic ARP handling.
401 */
402 private void addEmptyBgpConfig() {
403 Set<BgpConfig.BgpSpeakerConfig> speakers = Sets.newHashSet();
404
405 expect(bgpConfig.bgpSpeakers()).andReturn(speakers).anyTimes();
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300406 expect(bgpConfig.getSpeakerFromPeer(anyObject())).andReturn(null).anyTimes();
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200407 replay(bgpConfig);
408 }
409
410 /**
411 * Populates edge ports in the EdgePortService to return all port 1
412 * as edge ports.
413 */
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300414 private void populateEdgePortService() {
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200415 Set<ConnectPoint> edgeConnectPoints = new HashSet<>();
416
417 for (int i = 1; i <= NUM_DEVICES; i++) {
418 for (int j = 1; j <= NUM_PORTS_PER_DEVICE; j++) {
419 ConnectPoint edgeConnectPoint = new ConnectPoint(
420 getDeviceId(i),
421 PortNumber.portNumber(1));
422 ConnectPoint noEdgeConnectPointOne = new ConnectPoint(
423 getDeviceId(i),
424 PortNumber.portNumber(2));
425 ConnectPoint noEdgeConnectPointTwo = new ConnectPoint(
426 getDeviceId(i),
427 PortNumber.portNumber(3));
428
429 edgeConnectPoints.add(edgeConnectPoint);
430
431 expect(edgePortService.isEdgePoint(edgeConnectPoint))
432 .andReturn(true).anyTimes();
433 expect(edgePortService.isEdgePoint(noEdgeConnectPointOne))
434 .andReturn(false).anyTimes();
435 expect(edgePortService.isEdgePoint(noEdgeConnectPointTwo))
436 .andReturn(false).anyTimes();
437 }
438 }
439 expect(edgePortService.getEdgePoints())
440 .andReturn(edgeConnectPoints).anyTimes();
441
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300442 expect(edgePortService.isEdgePoint(CP3)).andReturn(true).anyTimes();
443
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200444 replay(edgePortService);
445 }
446
447 /**
448 * Creates a list of connect points used to verify floodling on ports
449 * with no interfaces configured (all ports without interface config).
450 */
451 private void setupNoConfigCPoints() {
452 for (int i = NUM_DEVICES / 2 + 2; i <= NUM_DEVICES; i++) {
453 ConnectPoint connectPoint = new ConnectPoint(
454 getDeviceId(i),
455 PortNumber.portNumber(1));
456 noConfigCPoints.add(connectPoint);
457 }
458 }
459
460 /**
461 * Creates a list of connect points used to verify floodling on ports
462 * with interfaces configured (both VLAN and IP).
463 */
464 private void setupconfigIpCPoints() {
465 for (int i = 1; i <= 3; i++) {
466 ConnectPoint connectPoint = new ConnectPoint(
467 getDeviceId(i),
468 PortNumber.portNumber(1));
469 configIpCPoints.add(connectPoint);
470 }
471 }
472
473 /**
474 * Creates a list of connect points used to verify floodling on ports
475 * with interfaces configured (both VLAN and IP).
476 */
477 private void setupconfigVlanCPoints() {
478 for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
479 ConnectPoint connectPoint = new ConnectPoint(
480 getDeviceId(i),
481 PortNumber.portNumber(1));
482 configVlanCPoints.add(connectPoint);
483 }
484 }
485
486 /**
487 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
488 * destination host is known.
489 * Two host using the same VLAN are registered on the host service on devices 5 and 6.
490 * Host on port 6 asks for the MAC of the device on port 5.
491 * Since the destination mac address is known, the request is not flooded to anywhere
492 * and ONOS directly builds an ARP reply, sended back to the requester on device 6.
493 * It's verified that a proper ARP reply is received on port 1 of device 6.
494 */
495 @Test
496 public void testReplyKnown() {
497 Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
498 Collections.singleton(IP1));
499
500 Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(NUM_DEVICES - 1),
501 Collections.singleton(IP2));
502
503 expect(hostService.getHostsByIp(IP2))
504 .andReturn(Collections.singleton(replyer));
505 expect(hostService.getHost(HID1)).andReturn(requestor);
506
507 replay(hostService);
508 replay(interfaceService);
509
510 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
511
512 InboundPacket pkt =
513 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
514 arpRequest,
515 ByteBuffer.wrap(arpRequest.serialize()));
516 proxyArp.processPacketIn(pkt);
517
518 assertEquals(1, packetService.packets.size());
519 Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1);
520 verifyPacketOut(arpReply, getLocation(NUM_DEVICES), packetService.packets.get(0));
521 }
522
523 /**
524 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
525 * destination host is known.
526 * Verifies the correct NDP reply is sent out the correct port.
527 */
528 @Test
529 public void testReplyKnownIpv6() {
530 Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
531 Collections.singleton(IP3));
532
533 Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
534 Collections.singleton(IP4));
535
536 expect(hostService.getHostsByIp(IP3))
537 .andReturn(Collections.singleton(replyer));
538 expect(hostService.getHost(HID4)).andReturn(requestor);
539
540 replay(hostService);
541 replay(interfaceService);
542
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300543 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200544 MAC4, SOLICITED_MAC3,
545 IP4, IP3);
546
547 InboundPacket pkt =
548 new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
549 ndpRequest,
550 ByteBuffer.wrap(ndpRequest.serialize()));
551 proxyArp.processPacketIn(pkt);
552
553 assertEquals(1, packetService.packets.size());
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300554 Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200555 MAC3, MAC4, IP3, IP4);
556 verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
557 }
558
559 /**
560 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
561 * destination host is not known.
562 * Only a requestor is present (on device 6, port 1). The device has a VLAN configured
563 * which is not configured anywhere in the system.
564 * Since the destination is not known, and since the ARP request can't be sent out of
565 * interfaces configured, the ARP request is flooded out of ports 4 and 5.
566 * Verifies the ARP request is flooded out the correct edge ports.
567 */
568 @Test
569 public void testReplyUnknown() {
570 Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
571 Collections.singleton(IP1));
572
573 expect(hostService.getHostsByIp(IP2))
574 .andReturn(Collections.emptySet());
575 expect(interfaceService.getInterfacesByIp(IP1))
576 .andReturn(Collections.emptySet());
577 expect(hostService.getHost(HID10)).andReturn(requestor);
578
579 replay(hostService);
580 replay(interfaceService);
581
582 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
583
584 InboundPacket pkt =
585 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
586 arpRequest,
587 ByteBuffer.wrap(arpRequest.serialize()));
588 proxyArp.processPacketIn(pkt);
589
590 verifyFlood(arpRequest, noConfigCPoints);
591 }
592
593 /**
594 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
595 * destination host is not known.
596 * Verifies the NDP request is flooded out the correct edge ports.
597 */
598 @Test
599 public void testReplyUnknownIpv6() {
600 Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
601 Collections.singleton(IP4));
602
603 expect(hostService.getHostsByIp(IP3))
604 .andReturn(Collections.emptySet());
605 expect(interfaceService.getInterfacesByIp(IP4))
606 .andReturn(Collections.emptySet());
607 expect(hostService.getHost(HID4)).andReturn(requestor);
608
609 replay(hostService);
610 replay(interfaceService);
611
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300612 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200613 MAC4, SOLICITED_MAC3,
614 IP4, IP3);
615
616 InboundPacket pkt =
617 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
618 ndpRequest,
619 ByteBuffer.wrap(ndpRequest.serialize()));
620 proxyArp.processPacketIn(pkt);
621
622 verifyFlood(ndpRequest, noConfigCPoints);
623 }
624
625 /**
626 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
627 * destination host is known for that IP address, but is not on the same
628 * VLAN as the source host.
629 * An host is connected on device 6, port 1 where no interfaces are defined. It sends
630 * ARP requests from VLAN10, not configured anywhere in the network. Another host with
631 * the IP address requested lives on device 5, port 1 in the network. Anyway, since the
632 * host uses another VLAN it's not found and the ARP packet is flooded out of port
633 * 4 and 5.
634 *
635 * Verifies the ARP request is flooded out the correct edge ports.
636 */
637 @Test
638 public void testReplyDifferentVlan() {
639 Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
640 Collections.singleton(IP1));
641
642 Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN2, getLocation(NUM_DEVICES - 1),
643 Collections.singleton(IP2));
644
645 expect(hostService.getHostsByIp(IP2))
646 .andReturn(Collections.singleton(replyer));
647 expect(interfaceService.getInterfacesByIp(IP1))
648 .andReturn(Collections.emptySet());
649 expect(hostService.getHost(HID10)).andReturn(requestor);
650
651 replay(hostService);
652 replay(interfaceService);
653
654 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
655
656 InboundPacket pkt =
657 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
658 arpRequest,
659 ByteBuffer.wrap(arpRequest.serialize()));
660 proxyArp.processPacketIn(pkt);
661
662 verifyFlood(arpRequest, noConfigCPoints);
663 }
664
665 /**
666 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
667 * a vlan packet comes in from a port without interfaces configured. The destination
668 * host is unknown for that IP address and there are some interfaces configured on
669 * the same vlan.
670 * It's expected to see the ARP request going out through ports with no interfaces
671 * configured, devices 4 and 5, port 1.
672 *
673 * Verifies the ARP request is flooded out the correct edge ports.
674 */
675 @Test
676 public void testConfiguredVlan() {
677 Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
678 Collections.singleton(IP1));
679
680 expect(hostService.getHostsByIp(IP2))
681 .andReturn(Collections.emptySet());
682 expect(interfaceService.getInterfacesByIp(IP1))
683 .andReturn(Collections.emptySet());
684 expect(hostService.getHost(HID1)).andReturn(requestor);
685
686 replay(hostService);
687 replay(interfaceService);
688
689 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
690
691 InboundPacket pkt =
692 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
693 arpRequest,
694 ByteBuffer.wrap(arpRequest.serialize()));
695 proxyArp.processPacketIn(pkt);
696
697 verifyFlood(arpRequest, noConfigCPoints);
698 }
699
700 /**
701 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
702 * a vlan packet comes in from a port without interfaces configured. The destination
703 * host is not known for that IP address and there are some interfaces configured on
704 * the same vlan.
705 * It's expected to see the ARP request going out through ports with no interfaces
706 * configured, devices 4 and 5, port 1.
707 *
708 * Verifies the ARP request is flooded out the correct edge ports.
709 */
710 @Test
711 public void testConfiguredVlanOnInterfaces() {
712 Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(6),
713 Collections.singleton(IP1));
714
715 expect(hostService.getHostsByIp(IP2))
716 .andReturn(Collections.emptySet());
717 expect(interfaceService.getInterfacesByIp(IP1))
718 .andReturn(Collections.emptySet());
719 expect(hostService.getHost(HID1)).andReturn(requestor);
720
721 replay(hostService);
722 replay(interfaceService);
723
724 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
725
726 InboundPacket pkt =
727 new DefaultInboundPacket(new ConnectPoint(getDeviceId(6), P1),
728 arpRequest,
729 ByteBuffer.wrap(arpRequest.serialize()));
730 proxyArp.processPacketIn(pkt);
731
732 verifyFlood(arpRequest, configVlanCPoints);
733 }
734
735 /**
736 * Tests {@link SdxL3ArpHandler#processPacketIn(InboundPacket)} in the case where the
737 * destination host is known for that IP address, but is not on the same
738 * VLAN as the source host.
739 * Verifies the NDP request is flooded out the correct edge ports.
740 */
741 @Test
742 public void testReplyDifferentVlanIpv6() {
743 Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
744 Collections.singleton(IP4));
745
746 Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(NUM_DEVICES - 1),
747 Collections.singleton(IP3));
748
749 expect(hostService.getHostsByIp(IP3))
750 .andReturn(Collections.singleton(replyer));
751 expect(interfaceService.getInterfacesByIp(IP4))
752 .andReturn(Collections.emptySet());
753 expect(hostService.getHost(HID4)).andReturn(requestor);
754
755 replay(hostService);
756 replay(interfaceService);
757
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300758 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200759 MAC4, SOLICITED_MAC3,
760 IP4, IP3);
761
762 InboundPacket pkt =
763 new DefaultInboundPacket(new ConnectPoint(getDeviceId(NUM_DEVICES), P1),
764 ndpRequest,
765 ByteBuffer.wrap(ndpRequest.serialize()));
766
767 proxyArp.processPacketIn(pkt);
768
769 verifyFlood(ndpRequest, noConfigCPoints);
770 }
771
772 /**
773 * Test ARP request from external network to an internal host.
774 */
775 @Test
776 public void testReplyToRequestForUs() {
777 Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
778 Ip4Address ourFirstIp = Ip4Address.valueOf("10.0.1.1");
779 Ip4Address ourSecondIp = Ip4Address.valueOf("10.0.2.1");
780 MacAddress firstMac = MacAddress.valueOf(1L);
781 MacAddress secondMac = MacAddress.valueOf(2L);
782
783 Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
784 Collections.singleton(theirIp));
785
786 expect(hostService.getHost(HID1)).andReturn(requestor);
787 replay(hostService);
788 replay(interfaceService);
789
790 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourFirstIp);
791
792 InboundPacket pkt =
793 new DefaultInboundPacket(CP1, arpRequest,
794 ByteBuffer.wrap(arpRequest.serialize()));
795
796 proxyArp.processPacketIn(pkt);
797
798 assertEquals(1, packetService.packets.size());
799 Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, firstMac, MAC1, ourFirstIp, theirIp);
800 verifyPacketOut(arpReply, CP1, packetService.packets.get(0));
801
802 // Test a request for the second address on that port
803 packetService.packets.clear();
804 arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourSecondIp);
805
806 pkt = new DefaultInboundPacket(CP1, arpRequest,
807 ByteBuffer.wrap(arpRequest.serialize()));
808 proxyArp.processPacketIn(pkt);
809
810 assertEquals(1, packetService.packets.size());
811 arpReply = buildArp(ARP.OP_REPLY, VLAN1, secondMac, MAC1, ourSecondIp, theirIp);
812 verifyPacketOut(arpReply, CP1, packetService.packets.get(0));
813 }
814
815 /**
816 * Test NDP request from external network to an internal host.
817 */
818 @Test
819 public void testReplyToRequestForUsIpv6() {
820 Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
821 Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
822 Ip6Address ourSecondIp = Ip6Address.valueOf("2000::2");
823 MacAddress firstMac = MacAddress.valueOf(1L);
824 MacAddress secondMac = MacAddress.valueOf(2L);
825
826 Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
827 Collections.singleton(theirIp));
828
829 expect(hostService.getHost(HID2)).andReturn(requestor);
830 expect(hostService.getHostsByIp(ourFirstIp))
831 .andReturn(Collections.singleton(requestor));
832 replay(hostService);
833 replay(interfaceService);
834
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300835 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200836 MAC2,
837 MacAddress.valueOf("33:33:ff:00:00:01"),
838 theirIp,
839 ourFirstIp);
840
841 InboundPacket pkt =
842 new DefaultInboundPacket(CP1, ndpRequest,
843 ByteBuffer.wrap(ndpRequest.serialize()));
844 proxyArp.processPacketIn(pkt);
845
846 assertEquals(1, packetService.packets.size());
847
848 Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300849 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200850 firstMac,
851 MAC2,
852 ourFirstIp,
853 theirIp);
854 verifyPacketOut(ndpReply, CP1, packetService.packets.get(0));
855
856 // Test a request for the second address on that port
857 packetService.packets.clear();
858 ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300859 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200860 MAC2,
861 MacAddress.valueOf("33:33:ff:00:00:01"),
862 theirIp,
863 ourSecondIp);
864
865 pkt = new DefaultInboundPacket(CP1, ndpRequest,
866 ByteBuffer.wrap(ndpReply.serialize()));
867
868 proxyArp.processPacketIn(pkt);
869
870 assertEquals(1, packetService.packets.size());
871
872 ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300873 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200874 secondMac,
875 MAC2,
876 ourSecondIp,
877 theirIp);
878 verifyPacketOut(ndpReply, CP1, packetService.packets.get(0));
879 }
880
881 /**
882 * Request for a valid external IPv4 address but coming in the wrong port.
883 */
884 @Test
885 public void testReplyExternalPortBadRequest() {
886 replay(hostService); // no further host service expectations
887 replay(interfaceService);
888
889 Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
890
891 // Request for a valid external IP address but coming in the wrong port
892 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp,
893 Ip4Address.valueOf("10.0.3.1"));
894 InboundPacket pkt =
895 new DefaultInboundPacket(CP1, arpRequest,
896 ByteBuffer.wrap(arpRequest.serialize()));
897 proxyArp.processPacketIn(pkt);
898
899 assertEquals(0, packetService.packets.size());
900
901 // Request for a valid internal IP address but coming in an external port
902 packetService.packets.clear();
903 arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, IP1);
904 pkt = new DefaultInboundPacket(CP1, arpRequest,
905 ByteBuffer.wrap(arpRequest.serialize()));
906 proxyArp.processPacketIn(pkt);
907 assertEquals(0, packetService.packets.size());
908 }
909
910 /**
911 * Request for a valid external IPv6 address but coming in the wrong port.
912 */
913 @Test
914 public void testReplyExternalPortBadRequestIpv6() {
915 replay(hostService); // no further host service expectations
916 replay(interfaceService);
917
918 Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
919
920 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300921 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200922 MAC1,
923 MacAddress.valueOf("33:33:ff:00:00:01"),
924 theirIp,
925 Ip6Address.valueOf("3000::1"));
926
927 InboundPacket pkt =
928 new DefaultInboundPacket(CP1, ndpRequest,
929 ByteBuffer.wrap(ndpRequest.serialize()));
930
931 proxyArp.processPacketIn(pkt);
932
933 assertEquals(0, packetService.packets.size());
934
935 // Request for a valid internal IP address but coming in an external port
936 packetService.packets.clear();
937 ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300938 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200939 MAC1,
940 MacAddress.valueOf("33:33:ff:00:00:01"),
941 theirIp,
942 IP3);
943
944 pkt = new DefaultInboundPacket(CP1, ndpRequest,
945 ByteBuffer.wrap(ndpRequest.serialize()));
946
947 proxyArp.processPacketIn(pkt);
948
949 assertEquals(0, packetService.packets.size());
950 }
951
952 /**
953 * Test ARP request from internal network to an external host.
954 */
955 @Test
956 public void testReplyToRequestFromUs() {
957 Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
958 MacAddress ourMac = MacAddress.valueOf(1L);
959 Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
960
961 expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
962 expect(interfaceService.getInterfacesByIp(ourIp)).andReturn(
Andreas Papazoise6aebaa2016-05-26 15:25:51 +0300963 Collections.singleton(new Interface(NO_NAME,
964 getLocation(1),
965 Collections.singletonList(
966 new InterfaceIpAddress(ourIp,
967 IpPrefix.valueOf("10.0.1.1/24"))),
968 ourMac, VLAN1)));
Andreas Papazois6e1fca32016-02-09 11:27:10 +0200969 expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
970 replay(hostService);
971 replay(interfaceService);
972
973 // This is a request from something inside our network (like a BGP
974 // daemon) to an external host.
975 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, ourMac, null, ourIp, theirIp);
976 //Ensure the packet is allowed through (it is not to an internal port)
977
978 InboundPacket pkt =
979 new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
980 arpRequest,
981 ByteBuffer.wrap(arpRequest.serialize()));
982 proxyArp.processPacketIn(pkt);
983
984 assertEquals(1, packetService.packets.size());
985
986 verifyPacketOut(arpRequest, getLocation(1), packetService.packets.get(0));
987
988 // The same request from a random external port should fail
989 packetService.packets.clear();
990 pkt = new DefaultInboundPacket(new ConnectPoint(getDeviceId(2), P1),
991 arpRequest,
992 ByteBuffer.wrap(arpRequest.serialize()));
993
994 proxyArp.processPacketIn(pkt);
995
996 assertEquals(0, packetService.packets.size());
997 }
998
999 /**
1000 * Test NDP request from internal network to an external host.
1001 */
1002 @Test
1003 public void testReplyToRequestFromUsIpv6() {
1004 Ip6Address ourIp = Ip6Address.valueOf("1000::1");
1005 MacAddress ourMac = MacAddress.valueOf(1L);
1006 Ip6Address theirIp = Ip6Address.valueOf("1000::100");
1007
1008 expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
1009 expect(interfaceService.getInterfacesByIp(ourIp))
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001010 .andReturn(Collections.singleton(new Interface(NO_NAME,
1011 getLocation(1),
1012 Collections.singletonList(new InterfaceIpAddress(
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001013 ourIp,
1014 IpPrefix.valueOf("1000::1/64"))),
1015 ourMac,
1016 VLAN1)));
1017 expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
1018 replay(hostService);
1019 replay(interfaceService);
1020
1021 // This is a request from something inside our network (like a BGP
1022 // daemon) to an external host.
1023 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001024 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001025 ourMac,
1026 MacAddress.valueOf("33:33:ff:00:00:01"),
1027 ourIp,
1028 theirIp);
1029
1030 InboundPacket pkt =
1031 new DefaultInboundPacket(new ConnectPoint(getDeviceId(5), P1),
1032 ndpRequest,
1033 ByteBuffer.wrap(ndpRequest.serialize()));
1034 proxyArp.processPacketIn(pkt);
1035
1036 assertEquals(1, packetService.packets.size());
1037
1038 verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
1039
1040 // The same request from a random external port should fail
1041 packetService.packets.clear();
1042
1043 pkt = new DefaultInboundPacket(new ConnectPoint(getDeviceId(2), P1),
1044 ndpRequest,
1045 ByteBuffer.wrap(ndpRequest.serialize()));
1046
1047 proxyArp.processPacketIn(pkt);
1048
1049 assertEquals(0, packetService.packets.size());
1050 }
1051
1052
1053 /**
1054 * Request for a valid IPv4 address for BGP peer and coming from a
1055 * BGP peer.
1056 */
1057 @Test
1058 public void testReplyExternalPortForPeer() {
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001059 setupSdx();
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001060
1061 // Request for a valid external IP address belonging to BGP peer
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001062 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, PEER1_IP, PEER2_IP);
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001063 InboundPacket pkt =
1064 new DefaultInboundPacket(CP1, arpRequest,
1065 ByteBuffer.wrap(arpRequest.serialize()));
1066 proxyArp.processPacketIn(pkt);
1067
1068 assertEquals(1, packetService.packets.size());
1069 }
1070
1071 /**
1072 * Request for a valid IPv6 address for BGP peer and coming from a
1073 * BGP peer.
1074 */
1075 @Test
1076 public void testReplyExternalPortForPeerIpv6() {
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001077 setupSdx();
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001078
1079 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001080 VLAN1,
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001081 MAC1,
1082 MacAddress.valueOf("33:33:ff:00:00:01"),
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001083 PEER1_IP6,
1084 PEER2_IP6);
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001085
1086 InboundPacket pkt =
1087 new DefaultInboundPacket(CP1, ndpRequest,
1088 ByteBuffer.wrap(ndpRequest.serialize()));
1089
1090 proxyArp.processPacketIn(pkt);
1091
1092 assertEquals(1, packetService.packets.size());
1093 }
1094
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001095 /**
1096 * Request for a valid IPv4 address for BGP peer, coming from a
1097 * BGP speaker and VLAN translation is necessary.
1098 */
1099 @Test
1100 public void testReplySpeakerForPeerWithVlan() {
1101 setupSdx();
1102
1103 // Request for a valid external IP address belonging to BGP peer
1104 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC1, null,
1105 SPEAKER_IP, PEER3_IP);
1106 InboundPacket pkt =
1107 new DefaultInboundPacket(CP3, arpRequest,
1108 ByteBuffer.wrap(arpRequest.serialize()));
1109 proxyArp.processPacketIn(pkt);
1110
1111 assertEquals(1, packetService.packets.size());
1112 }
1113
1114 /**
1115 * Request for a valid IPv6 address for BGP peer, coming from a
1116 * BGP speaker and VLAN translation is necessary.
1117 */
1118 @Test
1119 public void testReplySpeakerForPeerWithVlanIpv6() {
1120 setupSdx();
1121
1122 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
1123 VLAN10,
1124 MAC1,
1125 MacAddress.valueOf("33:33:ff:00:00:01"),
1126 SPEAKER_IP6,
1127 PEER3_IP6);
1128
1129 InboundPacket pkt =
1130 new DefaultInboundPacket(CP3, ndpRequest,
1131 ByteBuffer.wrap(ndpRequest.serialize()));
1132
1133 proxyArp.processPacketIn(pkt);
1134
1135 assertEquals(1, packetService.packets.size());
1136 }
1137
1138 /**
1139 * Request for a valid IPv4 address of BGP speaker, originating from a
1140 * BGP peer and VLAN translation is necessary.
1141 */
1142 @Test
1143 public void testReplyPeerForSpeakerWithVlan() {
1144 setupSdx();
1145
1146 // Request for a valid external IP address belonging to BGP peer
1147 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null,
1148 PEER3_IP, SPEAKER_IP);
1149 InboundPacket pkt =
1150 new DefaultInboundPacket(CP3, arpRequest,
1151 ByteBuffer.wrap(arpRequest.serialize()));
1152 proxyArp.processPacketIn(pkt);
1153
1154 assertEquals(1, packetService.packets.size());
1155 }
1156
1157 /**
1158 * Request for a valid IPv6 address for BGP speaker, originating from a
1159 * BGP peer and VLAN translation is necessary.
1160 */
1161 @Test
1162 public void testReplyPeerForSpeakerWithVlanIpv6() {
1163 setupSdx();
1164
1165 Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
1166 VLAN1,
1167 MAC1,
1168 MacAddress.valueOf("33:33:ff:00:00:01"),
1169 PEER3_IP6,
1170 SPEAKER_IP6);
1171
1172 InboundPacket pkt =
1173 new DefaultInboundPacket(CP3, ndpRequest,
1174 ByteBuffer.wrap(ndpRequest.serialize()));
1175 proxyArp.processPacketIn(pkt);
1176
1177 assertEquals(1, packetService.packets.size());
1178 }
1179
1180
1181 /**
1182 * Tests the VLAN translation for ARP reply originating from external peer
1183 * and addressing to internal speaker.
1184 */
1185 @Test
1186 public void testHandleArpReplyWithVlan() {
1187 setupSdx();
1188
1189 // Reply for a valid external IP address belonging to BGP peer
1190 Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1,
1191 PEER3_IP, SPEAKER_IP);
1192 InboundPacket pkt =
1193 new DefaultInboundPacket(CP3, arpReply,
1194 ByteBuffer.wrap(arpReply.serialize()));
1195 proxyArp.processPacketIn(pkt);
1196
1197 assertEquals(1, packetService.packets.size());
1198 }
1199
1200 /**
1201 * Tests the VLAN translation for NDP reply originating from external peer
1202 * and addressing to internal speaker.
1203 */
1204 @Test
1205 public void testHandleNdpReplyWithVlan() {
1206 setupSdx();
1207
1208 Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
1209 VLAN1,
1210 MAC2,
1211 MAC1,
1212 PEER3_IP6,
1213 SPEAKER_IP6);
1214
1215 InboundPacket pkt =
1216 new DefaultInboundPacket(CP3, ndpReply,
1217 ByteBuffer.wrap(ndpReply.serialize()));
1218 proxyArp.processPacketIn(pkt);
1219
1220 assertEquals(1, packetService.packets.size());
1221 }
1222
1223 private void setupSdx() {
1224 MacAddress dstMac = MacAddress.valueOf(1L);
1225
1226 Host peer1Host = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
1227 Collections.singleton(PEER1_IP));
1228
1229 expect(hostService.getHost(HID1)).andReturn(peer1Host);
1230 expect(hostService.getHostsByIp(PEER1_IP))
1231 .andReturn(Collections.singleton(peer1Host));
1232 Host peer2Host = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC2,
1233 Collections.singleton(PEER2_IP));
1234 expect(hostService.getHost(HID2)).andReturn(peer2Host);
1235 expect(hostService.getHostsByIp(PEER2_IP))
1236 .andReturn(Collections.singleton(peer2Host));
1237 Host peer1Ipv6Host = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
1238 Collections.singleton(PEER1_IP6));
1239 expect(hostService.getHost(HID3)).andReturn(peer1Ipv6Host);
1240 expect(hostService.getHostsByIp(PEER1_IP6))
1241 .andReturn(Collections.singleton(peer1Ipv6Host));
1242 Host peer2Ipv6Host = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
1243 Collections.singleton(PEER2_IP6));
1244 expect(hostService.getHost(HID4)).andReturn(peer2Ipv6Host);
1245 expect(hostService.getHostsByIp(PEER2_IP6))
1246 .andReturn(Collections.singleton(peer2Ipv6Host));
1247 expect(hostService.getHost(HostId.hostId(dstMac, VLAN1))).andReturn(null);
1248 expect(hostService.getHostsByIp(PEER3_IP)).andReturn(Collections.emptySet());
1249 expect(hostService.getHost(HostId.hostId(dstMac, VLAN10))).andReturn(null);
1250 Host peer3Ipv6Host = new DefaultHost(PID, HID5, MAC5, VLAN1, LOC2,
1251 Collections.singleton(PEER3_IP6));
1252 expect(hostService.getHost(HID5)).andReturn(peer3Ipv6Host);
1253 expect(hostService.getHostsByIp(PEER3_IP6))
1254 .andReturn(Collections.singleton(peer3Ipv6Host));
1255 expect(hostService.getHost(HostId.hostId(dstMac, VLAN10))).andReturn(null);
1256 expect(hostService.getHostsByIp(SPEAKER_IP)).andReturn(Collections.emptySet());
1257 expect(hostService.getHostsByIp(SPEAKER_IP6)).andReturn(Collections.emptySet());
1258
1259 replay(hostService);
1260
1261 expect(interfaceService.getInterfacesByIp(PEER1_IP))
1262 .andReturn(Collections.emptySet()).anyTimes();
1263 expect(interfaceService.getInterfacesByIp(PEER1_IP6))
1264 .andReturn(Collections.emptySet()).anyTimes();
1265
1266 Interface intf1 = new Interface(NO_NAME,
1267 getLocation(1),
1268 Collections.singletonList(
1269 new InterfaceIpAddress(
1270 SPEAKER_IP,
1271 INTF1_IP_PREFIX)),
1272 dstMac, VLAN1);
1273 expect(interfaceService.getInterfacesByIp(SPEAKER_IP)).andReturn(
1274 Collections.singleton(intf1)).anyTimes();
1275
1276 Interface intf2 = new Interface(NO_NAME,
1277 getLocation(1),
1278 Collections.singletonList(
1279 new InterfaceIpAddress(
1280 SPEAKER_IP6,
1281 INTF2_IP6_PREFIX)),
1282 dstMac, VLAN1);
1283 expect(interfaceService.getInterfacesByIp(SPEAKER_IP6)).andReturn(
1284 Collections.singleton(intf2)).anyTimes();
1285 expect(interfaceService.getInterfacesByIp(PEER3_IP)).andReturn(
1286 Collections.singleton(intf1));
1287 expect(interfaceService.getInterfacesByIp(PEER3_IP6)).andReturn(
1288 Collections.singleton(intf2));
1289
1290 replay(interfaceService);
1291
1292 expect(sdxL3PeerService.getInterfaceForPeer(PEER2_IP)).andReturn(intf1);
1293 expect(sdxL3PeerService.getInterfaceForPeer(PEER2_IP6)).andReturn(intf2);
1294 expect(sdxL3PeerService.getInterfaceForPeer(PEER3_IP)).andReturn(intf1);
1295 expect(sdxL3PeerService.getInterfaceForPeer(PEER3_IP6)).andReturn(intf2);
1296 replay(sdxL3PeerService);
1297
1298 addPeersToBgpConfig();
1299 }
1300
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001301 private void addPeersToBgpConfig() {
1302 reset(bgpConfig);
1303
1304 Set<BgpConfig.BgpSpeakerConfig> speakers = new HashSet<>();
1305
1306 Optional<String> speakerName = Optional.empty();
1307 ConnectPoint connectPoint = CP2;
1308 Set<IpAddress> connectedPeers =
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001309 new HashSet<>(Arrays.asList(PEER1_IP,
1310 PEER2_IP,
1311 PEER1_IP6,
1312 PEER2_IP6));
1313 BgpConfig.BgpSpeakerConfig speaker1 =
1314 new BgpConfig.BgpSpeakerConfig(speakerName,
1315 VlanId.NONE,
1316 connectPoint,
1317 connectedPeers);
1318 speakers.add(speaker1);
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001319
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001320 speakerName = Optional.empty();
1321 connectPoint = CP3;
1322 connectedPeers = new HashSet<>(Arrays.asList(PEER3_IP,
1323 PEER3_IP6));
1324 BgpConfig.BgpSpeakerConfig speaker2 =
1325 new BgpConfig.BgpSpeakerConfig(speakerName,
1326 VLAN10,
1327 connectPoint,
1328 connectedPeers);
1329 speakers.add(speaker2);
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001330
1331 expect(bgpConfig.bgpSpeakers()).andReturn(speakers).anyTimes();
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001332
1333 expect(bgpConfig.getSpeakerFromPeer(PEER1_IP)).andReturn(speaker1).anyTimes();
1334 expect(bgpConfig.getSpeakerFromPeer(PEER2_IP)).andReturn(speaker1).anyTimes();
1335 expect(bgpConfig.getSpeakerFromPeer(PEER3_IP)).andReturn(speaker2).anyTimes();
1336 expect(bgpConfig.getSpeakerFromPeer(PEER1_IP6)).andReturn(speaker1).anyTimes();
1337 expect(bgpConfig.getSpeakerFromPeer(PEER2_IP6)).andReturn(speaker1).anyTimes();
1338 expect(bgpConfig.getSpeakerFromPeer(PEER3_IP6)).andReturn(speaker2).anyTimes();
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001339 replay(bgpConfig);
1340 }
1341
1342 /**
1343 * Verifies that the given packet was flooded out all available edge ports,
1344 * except for the input port.
1345 *
1346 * @param packet the packet that was expected to be flooded
1347 * @param connectPoints the connectPoints where the outpacket should be
1348 * observed
1349 */
1350 private void verifyFlood(Ethernet packet, List<ConnectPoint> connectPoints) {
1351
1352 // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded.
1353 assertEquals(connectPoints.size() - 1, packetService.packets.size());
1354
1355 Collections.sort(packetService.packets,
1356 (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri()));
1357
1358 for (int i = 0; i < connectPoints.size() - 1; i++) {
1359 OutboundPacket outboundPacket = packetService.packets.get(i);
1360 verifyPacketOut(packet, connectPoints.get(i), outboundPacket);
1361 }
1362 }
1363
1364 /**
1365 * Verifies the given packet was sent out the given port.
1366 *
1367 * @param expected the packet that was expected to be sent
1368 * @param outPort the port the packet was expected to be sent out
1369 * @param actual the actual OutboundPacket to verify
1370 */
1371 private void verifyPacketOut(Ethernet expected, ConnectPoint outPort,
1372 OutboundPacket actual) {
1373 assertArrayEquals(expected.serialize(), actual.data().array());
1374 assertEquals(1, actual.treatment().immediate().size());
1375 assertEquals(outPort.deviceId(), actual.sendThrough());
1376 Instruction instruction = actual.treatment().immediate().get(0);
1377 assertTrue(instruction instanceof OutputInstruction);
1378 assertEquals(outPort.port(), ((OutputInstruction) instruction).port());
1379 }
1380
1381 /**
1382 * Returns the device ID of the ith device.
1383 *
1384 * @param i device to get the ID of
1385 * @return the device ID
1386 */
1387 private static DeviceId getDeviceId(int i) {
1388 return DeviceId.deviceId("" + i);
1389 }
1390
1391 private static HostLocation getLocation(int i) {
1392 return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
1393 }
1394
1395 /**
1396 * Builds an ARP packet with the given parameters.
1397 *
1398 * @param opcode opcode of the ARP packet
1399 * @param srcMac source MAC address
1400 * @param dstMac destination MAC address, or null if this is a request
1401 * @param srcIp source IP address
1402 * @param dstIp destination IP address
1403 * @return the ARP packet
1404 */
1405 private Ethernet buildArp(short opcode, VlanId vlanId, MacAddress srcMac,
1406 MacAddress dstMac, Ip4Address srcIp, Ip4Address dstIp) {
1407 Ethernet eth = new Ethernet();
1408
1409 if (dstMac == null) {
1410 eth.setDestinationMACAddress(MacAddress.BROADCAST);
1411 } else {
1412 eth.setDestinationMACAddress(dstMac);
1413 }
1414
1415 eth.setSourceMACAddress(srcMac);
1416 eth.setEtherType(Ethernet.TYPE_ARP);
1417 eth.setVlanID(vlanId.toShort());
1418
1419 ARP arp = new ARP();
1420 arp.setOpCode(opcode);
1421 arp.setProtocolType(ARP.PROTO_TYPE_IP);
1422 arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
1423
1424 arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
1425 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
1426 arp.setSenderHardwareAddress(srcMac.toBytes());
1427
1428 if (dstMac == null) {
1429 arp.setTargetHardwareAddress(zeroMacAddress);
1430 } else {
1431 arp.setTargetHardwareAddress(dstMac.toBytes());
1432 }
1433
1434 arp.setSenderProtocolAddress(srcIp.toOctets());
1435 arp.setTargetProtocolAddress(dstIp.toOctets());
1436
1437 eth.setPayload(arp);
1438 return eth;
1439 }
1440
1441 /**
1442 * Builds an NDP packet with the given parameters.
1443 *
1444 * @param type NeighborSolicitation or NeighborAdvertisement
1445 * @param srcMac source MAC address
1446 * @param dstMac destination MAC address, or null if this is a request
1447 * @param srcIp source IP address
1448 * @param dstIp destination IP address
1449 * @return the NDP packet
1450 */
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001451 private Ethernet buildNdp(byte type, VlanId vlanId, MacAddress srcMac, MacAddress dstMac,
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001452 Ip6Address srcIp, Ip6Address dstIp) {
1453 assertThat(type, anyOf(
1454 is(ICMP6.NEIGHBOR_SOLICITATION),
1455 is(ICMP6.NEIGHBOR_ADVERTISEMENT)
1456 ));
1457 assertNotNull(srcMac);
1458 assertNotNull(dstMac);
1459 assertNotNull(srcIp);
1460 assertNotNull(dstIp);
1461
1462 IPacket ndp;
1463 if (type == ICMP6.NEIGHBOR_SOLICITATION) {
1464 ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
1465 } else {
1466 ndp = new NeighborAdvertisement()
1467 .setSolicitedFlag((byte) 1)
1468 .setOverrideFlag((byte) 1)
1469 .setTargetAddress(srcIp.toOctets())
1470 .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
1471 srcMac.toBytes());
1472 }
1473
1474 ICMP6 icmp6 = new ICMP6();
1475 icmp6.setIcmpType(type);
1476 icmp6.setIcmpCode((byte) 0);
1477 icmp6.setPayload(ndp);
1478
1479 IPv6 ipv6 = new IPv6();
1480 ipv6.setDestinationAddress(dstIp.toOctets());
1481 ipv6.setSourceAddress(srcIp.toOctets());
1482 ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
1483 ipv6.setHopLimit((byte) 255);
1484 ipv6.setPayload(icmp6);
1485
1486 Ethernet eth = new Ethernet();
1487 eth.setDestinationMACAddress(dstMac);
1488 eth.setSourceMACAddress(srcMac);
1489 eth.setEtherType(Ethernet.TYPE_IPV6);
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001490 eth.setVlanID(vlanId.toShort());
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001491 eth.setPayload(ipv6);
1492
1493 return eth;
1494 }
1495
1496 /**
1497 * Test PacketService implementation that simply stores OutboundPackets
1498 * passed to {@link #emit(OutboundPacket)} for later verification.
1499 */
1500 class TestPacketService extends PacketServiceAdapter {
1501
1502 List<OutboundPacket> packets = new ArrayList<>();
1503
1504 @Override
1505 public void emit(OutboundPacket packet) {
1506 packets.add(packet);
1507 }
1508 }
Andreas Papazoise6aebaa2016-05-26 15:25:51 +03001509
1510 /**
1511 * Mocks the CoreService.
1512 */
1513 private class TestCoreService extends CoreServiceAdapter {
1514 private final Map<String, ApplicationId> registeredApps =
1515 new HashMap<>();
1516
1517 public TestCoreService() {
1518 registeredApps.put(RoutingService.ROUTER_APP_ID, ROUTER_APPID);
1519 registeredApps.put(SdxL3.SDX_L3_APP, SDXL3_APPID);
1520 }
1521
1522 @Override
1523 public ApplicationId getAppId(String name) {
1524 return registeredApps.get(name);
1525 }
1526 }
1527
1528 /**
1529 * Mocks the NetworkConfigService.
1530 */
1531 private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
1532 private final Map<ApplicationId, Config> registeredConfigs
1533 = new HashMap<>();
1534
1535 public TestNetworkConfigService() {
1536 registeredConfigs.put(ROUTER_APPID, bgpConfig);
1537 }
1538
1539 @Override
1540 public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
1541 return (C) registeredConfigs.get(subject);
1542 }
1543
1544 @Override
1545 public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
1546 return (C) registeredConfigs.get(subject);
1547 }
1548 }
Andreas Papazois6e1fca32016-02-09 11:27:10 +02001549}
1550