blob: 1a49e22b5d107afa604214256a16075280cf31b8 [file] [log] [blame]
yoonseon322c9c32016-12-07 16:47:02 -08001/*
2 * Copyright 2017-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.virtual.impl;
18
Claudine Chiu93ce3e82017-02-18 14:28:22 -050019import com.google.common.collect.Sets;
yoonseon322c9c32016-12-07 16:47:02 -080020import org.junit.Before;
21import org.junit.Test;
22import org.onlab.junit.TestUtils;
23import org.onlab.osgi.TestServiceDirectory;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050024import org.onosproject.TestApplicationId;
yoonseon322c9c32016-12-07 16:47:02 -080025import org.onosproject.cluster.ClusterService;
26import org.onosproject.cluster.ClusterServiceAdapter;
27import org.onosproject.common.event.impl.TestEventDispatcher;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050028import org.onosproject.core.ApplicationId;
yoonseon322c9c32016-12-07 16:47:02 -080029import org.onosproject.core.CoreService;
30import org.onosproject.core.CoreServiceAdapter;
31import org.onosproject.core.IdGenerator;
32import org.onosproject.event.EventDeliveryService;
33import org.onosproject.incubator.net.virtual.NetworkId;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050034import org.onosproject.incubator.net.virtual.VirtualDevice;
yoonseon322c9c32016-12-07 16:47:02 -080035import org.onosproject.incubator.net.virtual.VirtualNetwork;
36import org.onosproject.incubator.net.virtual.VirtualNetworkPacketStore;
37import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
38import org.onosproject.incubator.net.virtual.impl.provider.VirtualProviderManager;
39import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
40import org.onosproject.incubator.net.virtual.provider.VirtualPacketProvider;
41import org.onosproject.incubator.net.virtual.provider.VirtualProviderRegistryService;
42import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
43import org.onosproject.incubator.store.virtual.impl.SimpleVirtualPacketStore;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050044import org.onosproject.net.DeviceId;
yoonseon322c9c32016-12-07 16:47:02 -080045import org.onosproject.net.NetTestTools;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050046import org.onosproject.net.flow.DefaultTrafficSelector;
yoonseon322c9c32016-12-07 16:47:02 -080047import org.onosproject.net.flow.DefaultTrafficTreatment;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050048import org.onosproject.net.flow.TrafficSelector;
49import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
50import org.onosproject.net.flowobjective.ForwardingObjective;
51import org.onosproject.net.flowobjective.Objective;
yoonseon322c9c32016-12-07 16:47:02 -080052import org.onosproject.net.intent.FakeIntentManager;
53import org.onosproject.net.intent.TestableIntentService;
54import org.onosproject.net.packet.DefaultOutboundPacket;
55import org.onosproject.net.packet.OutboundPacket;
56import org.onosproject.net.packet.PacketContext;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050057import org.onosproject.net.packet.PacketPriority;
yoonseon322c9c32016-12-07 16:47:02 -080058import org.onosproject.net.packet.PacketProcessor;
59import org.onosproject.net.provider.ProviderId;
60import org.onosproject.store.service.TestStorageService;
61
62import java.nio.ByteBuffer;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050063import java.util.HashMap;
64import java.util.Map;
65import java.util.Optional;
66import java.util.Set;
yoonseon322c9c32016-12-07 16:47:02 -080067import java.util.concurrent.atomic.AtomicLong;
68
69import static org.junit.Assert.*;
Claudine Chiu93ce3e82017-02-18 14:28:22 -050070import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
71import static org.onosproject.net.flowobjective.Objective.Operation.REMOVE;
72import static org.onosproject.net.packet.PacketPriority.CONTROL;
73import static org.onosproject.net.packet.PacketPriority.REACTIVE;
yoonseon322c9c32016-12-07 16:47:02 -080074
75public class VirtualNetworkPacketManagerTest extends VirtualNetworkTestUtil {
76
77 private static final int PROCESSOR_PRIORITY = 1;
78
79 private VirtualNetworkManager manager;
80 private DistributedVirtualNetworkStore virtualNetworkManagerStore;
81 private CoreService coreService = new TestCoreService();
82 private TestableIntentService intentService = new FakeIntentManager();
83 private TestServiceDirectory testDirectory;
84 private EventDeliveryService eventDeliveryService;
85 private VirtualProviderManager providerRegistryService;
86
87 private VirtualNetwork vnet1;
88 private VirtualNetwork vnet2;
89
90 private VirtualPacketProvider provider = new TestPacketProvider();
91 private VirtualNetworkPacketStore packetStore = new SimpleVirtualPacketStore();
92
93 private VirtualNetworkPacketManager packetManager1;
94 private VirtualNetworkPacketManager packetManager2;
95
Claudine Chiu93ce3e82017-02-18 14:28:22 -050096 private ApplicationId appId = new TestApplicationId("VirtualPacketManagerTest");
97
yoonseon322c9c32016-12-07 16:47:02 -080098 @Before
99 public void setUp() throws TestUtils.TestUtilsException {
100 virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
101
102 TestUtils.setField(virtualNetworkManagerStore, "coreService", coreService);
103 TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
104 virtualNetworkManagerStore.activate();
105
106 manager = new VirtualNetworkManager();
107 manager.store = virtualNetworkManagerStore;
108 manager.coreService = coreService;
109 manager.intentService = intentService;
110 NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
111
112 providerRegistryService = new VirtualProviderManager();
113 providerRegistryService.registerProvider(provider);
114
115 testDirectory = new TestServiceDirectory()
116 .add(VirtualNetworkStore.class, virtualNetworkManagerStore)
117 .add(CoreService.class, coreService)
118 .add(VirtualProviderRegistryService.class, providerRegistryService)
119 .add(EventDeliveryService.class, eventDeliveryService)
120 .add(ClusterService.class, new ClusterServiceAdapter())
121 .add(VirtualNetworkPacketStore.class, packetStore);
122 TestUtils.setField(manager, "serviceDirectory", testDirectory);
123
124 eventDeliveryService = new TestEventDispatcher();
125 NetTestTools.injectEventDispatcher(manager, eventDeliveryService);
126
127 manager.activate();
128
129 vnet1 = VirtualNetworkTestUtil.setupVirtualNetworkTopology(manager, TID1);
130 vnet2 = VirtualNetworkTestUtil.setupVirtualNetworkTopology(manager, TID2);
131
132 packetManager1 = new VirtualNetworkPacketManager(manager, vnet1.id());
133 packetManager2 = new VirtualNetworkPacketManager(manager, vnet2.id());
134 }
135
136 /**
137 * Tests the correct usage of addProcessor() for a outbound packet.
138 */
139 @Test
140 public void addProcessorTest() {
141 PacketProcessor testProcessor = new TestProcessor();
142 packetManager1.addProcessor(testProcessor, PROCESSOR_PRIORITY);
143
144 assertEquals("1 processor expected", 1,
145 packetManager1.getProcessors().size());
146 assertEquals("0 processor expected", 0,
147 packetManager2.getProcessors().size());
148
149 assertEquals("not equal packet processor", testProcessor,
150 packetManager1.getProcessors().get(0).processor());
151 assertEquals("not equal packet processor priority", PROCESSOR_PRIORITY,
152 packetManager1.getProcessors().get(0).priority());
153 }
154
155 /**
156 * Tests the correct usage of addProcessor() for a outbound packet.
157 */
158 @Test
159 public void removeProcessorTest() {
160 PacketProcessor testProcessor = new TestProcessor();
161 packetManager1.addProcessor(testProcessor, PROCESSOR_PRIORITY);
162
163 assertEquals("1 processor expected", 1,
164 packetManager1.getProcessors().size());
165 assertEquals("0 processor expected", 0,
166 packetManager2.getProcessors().size());
167
168 packetManager1.removeProcessor(testProcessor);
169
170 assertEquals("0 processor expected", 0,
171 packetManager1.getProcessors().size());
172 assertEquals("0 processor expected", 0,
173 packetManager2.getProcessors().size());
174 }
175
176 /**
177 * Tests the correct usage of emit() for a outbound packet.
178 */
179 @Test
180 public void emitTest() {
181 OutboundPacket packet =
182 new DefaultOutboundPacket(VDID1, DefaultTrafficTreatment.emptyTreatment(), ByteBuffer.allocate(5));
183 packetManager1.emit(packet);
184 assertEquals("Packet not emitted correctly", packet, emittedPacket);
185 }
186
Claudine Chiu93ce3e82017-02-18 14:28:22 -0500187 /**
188 * Tests the addition and removal of packet requests for a device.
189 *
190 * @throws TestUtils.TestUtilsException
191 */
192 @Test
193 public void requestAndCancelPacketsForDeviceTest() throws TestUtils.TestUtilsException {
194 TestFlowObjectiveService testFlowObjectiveService = new TestFlowObjectiveService();
195 TestUtils.setField(packetManager1, "objectiveService", testFlowObjectiveService);
196 TrafficSelector ts = DefaultTrafficSelector.emptySelector();
197 Optional<DeviceId> optionalDeviceId = Optional.of(VDID3);
198
199 // add first request
200 packetManager1.requestPackets(ts, CONTROL, appId, optionalDeviceId);
201 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
202 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, CONTROL, ADD);
203
204 // add same request as first
205 packetManager1.requestPackets(ts, CONTROL, appId, optionalDeviceId);
206 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
207 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, CONTROL, ADD);
208
209 // add second request
210 packetManager1.requestPackets(ts, REACTIVE, appId, optionalDeviceId);
211 assertEquals("2 packets expected", 2, packetManager1.getRequests().size());
212 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, REACTIVE, ADD);
213
214 // cancel second request
215 packetManager1.cancelPackets(ts, REACTIVE, appId, optionalDeviceId);
216 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
217 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, REACTIVE, REMOVE);
218
219 // cancel second request again
220 packetManager1.cancelPackets(ts, REACTIVE, appId, optionalDeviceId);
221 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
222 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, REACTIVE, REMOVE);
223
224 // cancel first request
225 packetManager1.cancelPackets(ts, CONTROL, appId, optionalDeviceId);
226 assertEquals("0 packet expected", 0, packetManager1.getRequests().size());
227 testFlowObjectiveService.validateObjectiveForDevice(VDID3, ts, CONTROL, REMOVE);
228 }
229
230 /**
231 * Tests the addition and removal of packet requests for all devices in a virtual
232 * network.
233 *
234 * @throws TestUtils.TestUtilsException
235 */
236 @Test
237 public void requestAndCancelPacketsForVnetTest() throws TestUtils.TestUtilsException {
238 TestFlowObjectiveService testFlowObjectiveService = new TestFlowObjectiveService();
239 TestUtils.setField(packetManager1, "objectiveService", testFlowObjectiveService);
240 TrafficSelector ts = DefaultTrafficSelector.emptySelector();
241 Set<VirtualDevice> vnet1Devices = manager.getVirtualDevices(vnet1.id());
242
243 // add first request
244 packetManager1.requestPackets(ts, CONTROL, appId);
245 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
246 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, CONTROL, ADD);
247
248 // add same request as first
249 packetManager1.requestPackets(ts, CONTROL, appId);
250 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
251 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, CONTROL, ADD);
252
253 // add second request
254 packetManager1.requestPackets(ts, REACTIVE, appId);
255 assertEquals("2 packets expected", 2, packetManager1.getRequests().size());
256 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, REACTIVE, ADD);
257
258 // cancel second request
259 packetManager1.cancelPackets(ts, REACTIVE, appId);
260 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
261 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, REACTIVE, REMOVE);
262
263 // cancel second request again
264 packetManager1.cancelPackets(ts, REACTIVE, appId);
265 assertEquals("1 packet expected", 1, packetManager1.getRequests().size());
266 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, REACTIVE, REMOVE);
267
268 // cancel first request
269 packetManager1.cancelPackets(ts, CONTROL, appId);
270 assertEquals("0 packet expected", 0, packetManager1.getRequests().size());
271 testFlowObjectiveService.validateObjectives(vnet1Devices, ts, CONTROL, REMOVE);
272 }
273
yoonseon322c9c32016-12-07 16:47:02 -0800274 private static OutboundPacket emittedPacket = null;
275
276 /**
277 * Core service test class.
278 */
279 private class TestCoreService extends CoreServiceAdapter {
280
281 @Override
282 public IdGenerator getIdGenerator(String topic) {
283 return new IdGenerator() {
284 private AtomicLong counter = new AtomicLong(0);
285
286 @Override
287 public long getNewId() {
288 return counter.getAndIncrement();
289 }
290 };
291 }
Claudine Chiu93ce3e82017-02-18 14:28:22 -0500292
293 @Override
294 public ApplicationId registerApplication(String name) {
295 return appId;
296 }
yoonseon322c9c32016-12-07 16:47:02 -0800297 }
298
299 private class TestPacketProvider extends AbstractVirtualProvider
300 implements VirtualPacketProvider {
301
302 /**
303 * Creates a provider with the supplied identifier.
304 */
305 protected TestPacketProvider() {
306 super(new ProviderId("test-packet",
307 "org.onosproject.virtual.test-packet"));
308 }
309
310 @Override
311 public void emit(NetworkId networkId, OutboundPacket packet) {
312 emittedPacket = packet;
313 }
yoonseonfb4a1db2017-01-31 11:38:30 -0800314
315 @Override
316 public void startPacketHandling() {
317
318 }
yoonseon322c9c32016-12-07 16:47:02 -0800319 }
320
321 private class TestProcessor implements PacketProcessor {
322
323 @Override
324 public void process(PacketContext context) {
325
326 }
327 }
Claudine Chiu93ce3e82017-02-18 14:28:22 -0500328
329 private class TestFlowObjectiveService extends FlowObjectiveServiceAdapter {
330 // track objectives received for each device
331 private final Map<DeviceId, Set<ForwardingObjective>> deviceFwdObjs = new HashMap<>();
332
333 @Override
334 public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
335 deviceFwdObjs.compute(deviceId, (deviceId1, forwardingObjectives) -> {
336 if (forwardingObjectives == null) {
337 return Sets.newHashSet(forwardingObjective);
338 }
339 forwardingObjectives.add(forwardingObjective);
340 return forwardingObjectives;
341 }
342 );
343 }
344
345 private void validateObjectives(Set<VirtualDevice> vdevs, TrafficSelector ts,
346 PacketPriority pp, Objective.Operation op) {
347 assertNotNull("set of devices must not be null", vdevs);
348 for (VirtualDevice vdev: vdevs) {
349 assertTrue("Forwarding objective must exist for device " + vdev.id(),
350 deviceHasObjective(vdev.id(), ts, pp, op));
351 }
352 }
353
354 private void validateObjectiveForDevice(DeviceId deviceId, TrafficSelector ts,
355 PacketPriority pp, Objective.Operation op) {
356 assertNotNull("deviceId must not be null", deviceId);
357 assertTrue("Forwarding objective must exist for device " + deviceId,
358 deviceHasObjective(deviceId, ts, pp, op));
359 }
360
361 private boolean deviceHasObjective(DeviceId deviceId, TrafficSelector ts,
362 PacketPriority pp, Objective.Operation op) {
363 Set<ForwardingObjective> fos = deviceFwdObjs.get(deviceId);
364 if (fos != null) {
365 for (ForwardingObjective fo: fos) {
366 if (fo.selector().equals(ts)
367 && fo.priority() == pp.priorityValue()
368 && fo.op().equals(op)) {
369 return true;
370 }
371 }
372 }
373 return false;
374 }
375 }
376}