blob: 6cdc88c42f329650e7176d9ba847c48bf0d1b1c3 [file] [log] [blame]
Jonathan Hart584ea2d2016-10-11 10:49:16 +02001/*
2 * Copyright 2016-present 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
17package org.onosproject.incubator.net.neighbour.impl;
18
19import org.junit.Before;
20import org.junit.Test;
21import org.onlab.osgi.ComponentContextAdapter;
22import org.onlab.packet.Ethernet;
23import org.onlab.packet.IpAddress;
24import org.onlab.packet.MacAddress;
25import org.onlab.packet.VlanId;
26import org.onosproject.TestApplicationId;
27import org.onosproject.cfg.ComponentConfigAdapter;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.incubator.net.intf.Interface;
31import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration;
32import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
33import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.host.HostService;
37import org.onosproject.net.packet.DefaultInboundPacket;
38import org.onosproject.net.packet.DefaultOutboundPacket;
39import org.onosproject.net.packet.InboundPacket;
40import org.onosproject.net.packet.PacketContextAdapter;
41import org.onosproject.net.packet.OutboundPacket;
42import org.onosproject.net.packet.PacketContext;
43import org.onosproject.net.packet.PacketPriority;
44import org.onosproject.net.packet.PacketProcessor;
45import org.onosproject.net.packet.PacketService;
46import org.onosproject.net.packet.PacketServiceAdapter;
47
48import java.util.Collection;
49
50import static org.easymock.EasyMock.anyInt;
51import static org.easymock.EasyMock.anyObject;
52import static org.easymock.EasyMock.createMock;
53import static org.easymock.EasyMock.createNiceMock;
54import static org.easymock.EasyMock.eq;
55import static org.easymock.EasyMock.expectLastCall;
56import static org.easymock.EasyMock.replay;
57import static org.easymock.EasyMock.reset;
58import static org.easymock.EasyMock.verify;
59import static org.junit.Assert.assertEquals;
60import static org.junit.Assert.assertTrue;
61import static org.onosproject.incubator.net.neighbour.impl.DefaultNeighbourMessageContext.createContext;
62import static org.onosproject.incubator.net.neighbour.impl.NeighbourTestUtils.createArpRequest;
63import static org.onosproject.incubator.net.neighbour.impl.NeighbourTestUtils.intf;
64
65/**
66 * Unit tests for the NeighbourResolutionManager.
67 */
68public class NeighbourResolutionManagerTest {
69
70 private NeighbourResolutionManager neighbourManager;
71
72 private PacketService packetService;
73 private PacketProcessor packetProcessor;
74
75 private static final NeighbourMessageHandler HANDLER = new TestNeighbourHandler();
76
77 private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
78 private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
79
80 private static final MacAddress MAC1 = MacAddress.valueOf(1);
81 private static final IpAddress IP1 = IpAddress.valueOf(1);
82 private static final IpAddress IP2 = IpAddress.valueOf(2);
83
84 private static final Interface INTF1 = intf(CP1, IP1, MAC1, VlanId.NONE);
85
86 private static final ApplicationId APP_ID = TestApplicationId.create("app");
87
88 @Before
89 public void setUp() throws Exception {
90 neighbourManager = new NeighbourResolutionManager();
91
92 packetService = createMock(PacketService.class);
93 packetService.requestPackets(anyObject(TrafficSelector.class),
94 anyObject(PacketPriority.class), anyObject(ApplicationId.class));
95 expectLastCall().anyTimes();
96 packetService.addProcessor(anyObject(PacketProcessor.class), anyInt());
97 expectLastCall().andDelegateTo(new TestPacketService()).once();
98 packetService.cancelPackets(anyObject(TrafficSelector.class),
99 anyObject(PacketPriority.class), anyObject(ApplicationId.class));
100 expectLastCall().anyTimes();
101 replay(packetService);
102
103 neighbourManager.packetService = packetService;
104
105 CoreService coreService = createNiceMock(CoreService.class);
106 replay(coreService);
107 neighbourManager.coreService = coreService;
108
109 neighbourManager.componentConfigService = new ComponentConfigAdapter();
110
111 neighbourManager.activate(new ComponentContextAdapter());
112 }
113
114 @Test
115 public void testRegistration() throws Exception {
116 neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);
117
118 assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));
119 }
120
121 @Test
122 public void testUnregister() {
123 // Register a handler and verify the registration is there
124 neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);
125 assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));
126
127 // Unregister the handler but supply a different connect point
128 neighbourManager.unregisterNeighbourHandler(CP2, HANDLER, APP_ID);
129
130 // Verify the original registration is still there on the original
131 // connect point
132 assertTrue(verifyRegistration(CP1, HANDLER, APP_ID));
133
134 assertTrue(verifyNoRegistration(CP2));
135
136 // Unregister the handler from the original connect point
137 neighbourManager.unregisterNeighbourHandler(CP1, HANDLER, APP_ID);
138
139 // Verify that it is gone
140 assertTrue(verifyNoRegistration(CP1));
141 }
142
143 @Test
144 public void testRegisterInterface() {
145 neighbourManager.registerNeighbourHandler(INTF1, HANDLER, APP_ID);
146
147 assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));
148 }
149
150 @Test
151 public void testUnregisterInterface() {
152 // Register a handler for an interface and verify it is there
153 neighbourManager.registerNeighbourHandler(INTF1, HANDLER, APP_ID);
154 assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));
155
156 // Unregister the handler but use the connect point rather than the interface
157 neighbourManager.unregisterNeighbourHandler(CP1, HANDLER, APP_ID);
158
159 // Verify the interface registration is still there
160 assertTrue(verifyRegistration(INTF1, HANDLER, APP_ID));
161
162 // Unregister the handler from the interface
163 neighbourManager.unregisterNeighbourHandler(INTF1, HANDLER, APP_ID);
164
165 // Verify the registration is gone
166 assertTrue(verifyNoRegistration(INTF1));
167 }
168
169 @Test
170 public void testUnregisterByAppId() {
171 // Register some handlers and verify they are there
172 neighbourManager.registerNeighbourHandler(CP1, HANDLER, APP_ID);
173 neighbourManager.registerNeighbourHandler(CP2, HANDLER, APP_ID);
174
175 assertEquals(2, neighbourManager.getHandlerRegistrations().size());
176
177 // Unregister all handlers for the given app ID
178 neighbourManager.unregisterNeighbourHandlers(APP_ID);
179
180 // Verify the handlers are gone
181 assertEquals(0, neighbourManager.getHandlerRegistrations().size());
182 }
183
184 @Test
185 public void testPacketDistribution() {
186 Ethernet arpRequest = createArpRequest(IP1);
187
188 NeighbourMessageHandler handler = createMock(NeighbourMessageHandler.class);
189 handler.handleMessage(eq(createContext(arpRequest, CP1, null)), anyObject(HostService.class));
190 expectLastCall().once();
191 replay(handler);
192 neighbourManager.registerNeighbourHandler(CP1, handler, APP_ID);
193
194 // Incoming packet on the connect point where the handler is registered
195 packetProcessor.process(context(arpRequest, CP1));
196
197 // Send a packet from a different connect point that should not be
198 // delivered to the handler
199 packetProcessor.process(context(arpRequest, CP2));
200
201 verify(handler);
202 }
203
204 @Test
205 public void testPacketDistributionToInterface() {
206 Ethernet arpRequest = createArpRequest(IP1);
207
208 NeighbourMessageHandler handler = createMock(NeighbourMessageHandler.class);
209 handler.handleMessage(eq(createContext(arpRequest, CP1, null)), anyObject(HostService.class));
210 expectLastCall().once();
211 replay(handler);
212 neighbourManager.registerNeighbourHandler(INTF1, handler, APP_ID);
213
214 // Incoming packet matching the interface where the handler is registered
215 packetProcessor.process(context(arpRequest, CP1));
216
217 verify(handler);
218
219 reset(handler);
220 replay(handler);
221
222 // Incoming packet on same connect point but not matching the interface
223 packetProcessor.process(context(createArpRequest(IP2), CP1));
224
225 verify(handler);
226 }
227
228 /**
229 * Verifies that there is one registration for the given connect point and
230 * that the registration matches the given handler and appId.
231 *
232 * @param cp connect point to verify registration for
233 * @param handler neighbour message handler
234 * @param appId application ID
235 * @return true if the registration is the only registration present for
236 * this connect point, otherwise false
237 */
238 private boolean verifyRegistration(ConnectPoint cp, NeighbourMessageHandler handler, ApplicationId appId) {
239 Collection<NeighbourHandlerRegistration> registrations =
240 neighbourManager.getHandlerRegistrations().get(cp);
241
242 if (registrations == null) {
243 return false;
244 }
245
246 if (registrations.size() != 1) {
247 return false;
248 }
249
250 NeighbourHandlerRegistration reg = registrations.stream().findFirst().get();
251
252 return reg.appId().equals(appId) &&
253 reg.handler().equals(handler);
254 }
255
256 /**
257 * Verifies that there is one registration for the given interface and
258 * that the registration matches the given handler and appId.
259 *
260 * @param intf interface to verify registration for
261 * @param handler neighbour message handler
262 * @param appId application ID
263 * @return true if the registration is the only registration present for
264 * this interface, otherwise false
265 */
266 private boolean verifyRegistration(Interface intf, NeighbourMessageHandler handler, ApplicationId appId) {
267 return verifyRegistration(intf.connectPoint(), handler, appId);
268 }
269
270 /**
271 * Verifies that there are no registrations for the given connect point.
272 *
273 * @param cp connect point
274 * @return true if there are no registrations for this connect point,
275 * otherwise false
276 */
277 private boolean verifyNoRegistration(ConnectPoint cp) {
278 return neighbourManager.getHandlerRegistrations().get(cp) == null;
279 }
280
281 /**
282 * Verifies that there are no registrations for the given interface.
283 *
284 * @param intf interface
285 * @return true if there are no registrations for this interface,
286 * otherwise false
287 */
288 private boolean verifyNoRegistration(Interface intf) {
289 return verifyNoRegistration(intf.connectPoint());
290 }
291
292 /**
293 * Creates a packet context for the given packet coming in the given port.
294 *
295 * @param packet packet to wrap in a packet context
296 * @param inPort input port of the packet
297 * @return packet context
298 */
299 private static PacketContext context(Ethernet packet, ConnectPoint inPort) {
300 InboundPacket inboundPacket = new DefaultInboundPacket(inPort, packet, null);
301 OutboundPacket outboundPacket = new DefaultOutboundPacket(null, null, null);
302 return new PacketContextAdapter(0, inboundPacket, outboundPacket, false);
303 }
304
305 private class TestPacketService extends PacketServiceAdapter {
306
307 @Override
308 public void addProcessor(PacketProcessor processor, int priority) {
309 NeighbourResolutionManagerTest.this.packetProcessor = processor;
310 }
311 }
312
313 private static class TestNeighbourHandler implements NeighbourMessageHandler {
314
315 @Override
316 public void handleMessage(NeighbourMessageContext context, HostService hostService) {
317
318 }
319 }
320
321}