blob: 048edf2f362e5c1bf09b52ebcc615021aa35ba3c [file] [log] [blame]
Ray Milkey2e78d902016-03-01 09:35:36 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Ray Milkey2e78d902016-03-01 09:35: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 */
16package org.onosproject.net.flowobjective.impl;
17
18import java.util.ArrayList;
19import java.util.List;
20
21import org.junit.After;
22import org.junit.Before;
23import org.junit.Test;
24import org.onlab.junit.TestUtils;
25import org.onlab.packet.ChassisId;
26import org.onosproject.mastership.MastershipEvent;
27import org.onosproject.mastership.MastershipListener;
28import org.onosproject.mastership.MastershipServiceAdapter;
29import org.onosproject.net.DefaultAnnotations;
30import org.onosproject.net.DefaultDevice;
31import org.onosproject.net.Device;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.NetTestTools;
34import org.onosproject.net.behaviour.DefaultNextGroup;
35import org.onosproject.net.behaviour.NextGroup;
36import org.onosproject.net.behaviour.PipelinerAdapter;
37import org.onosproject.net.behaviour.PipelinerContext;
38import org.onosproject.net.device.DeviceEvent;
39import org.onosproject.net.device.DeviceListener;
40import org.onosproject.net.device.DeviceServiceAdapter;
41import org.onosproject.net.driver.AbstractDriverLoader;
42import org.onosproject.net.driver.Behaviour;
43import org.onosproject.net.driver.DefaultDriverData;
44import org.onosproject.net.driver.DefaultDriverHandler;
45import org.onosproject.net.driver.DefaultDriverProviderService;
46import org.onosproject.net.driver.Driver;
Ray Milkeyd931a9b2016-03-02 17:01:30 -080047import org.onosproject.net.driver.DriverAdapter;
Ray Milkey2e78d902016-03-01 09:35:36 -080048import org.onosproject.net.driver.DriverData;
49import org.onosproject.net.driver.DriverHandler;
Ray Milkeyd931a9b2016-03-02 17:01:30 -080050import org.onosproject.net.driver.DriverServiceAdapter;
Ray Milkey2e78d902016-03-01 09:35:36 -080051import org.onosproject.net.flow.DefaultTrafficSelector;
52import org.onosproject.net.flow.DefaultTrafficTreatment;
53import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
55import org.onosproject.net.flow.criteria.Criteria;
56import org.onosproject.net.flowobjective.DefaultFilteringObjective;
57import org.onosproject.net.flowobjective.DefaultForwardingObjective;
58import org.onosproject.net.flowobjective.DefaultNextObjective;
59import org.onosproject.net.flowobjective.FilteringObjective;
60import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
61import org.onosproject.net.flowobjective.ForwardingObjective;
62import org.onosproject.net.flowobjective.NextObjective;
63import org.onosproject.net.flowobjective.ObjectiveEvent;
64import org.onosproject.net.intent.TestTools;
Ray Milkey2e78d902016-03-01 09:35:36 -080065
66import static org.hamcrest.CoreMatchers.hasItem;
67import static org.hamcrest.MatcherAssert.assertThat;
68import static org.hamcrest.Matchers.hasSize;
69import static org.hamcrest.Matchers.notNullValue;
70import static org.onlab.junit.TestUtils.TestUtilsException;
71
72/**
73 * Tests for the flow objective manager.
74 */
75public class FlowObjectiveManagerTest {
76
77 private static final int RETRY_MS = 250;
78 private FlowObjectiveManager manager;
79 DeviceId id1 = NetTestTools.did("d1");
80 DefaultDevice d1 = new DefaultDevice(NetTestTools.PID, id1, Device.Type.SWITCH,
81 "test", "1.0", "1.0",
82 "abacab", new ChassisId("c"),
83 DefaultAnnotations.EMPTY);
84
85 DeviceId id2 = NetTestTools.did("d2");
86 DefaultDevice d2 = new DefaultDevice(NetTestTools.PID, id2, Device.Type.SWITCH,
87 "test", "1.0", "1.0",
88 "abacab", new ChassisId("c"),
89 DefaultAnnotations.EMPTY);
90
91 List<String> filteringObjectives;
92 List<String> forwardingObjectives;
93 List<String> nextObjectives;
94
95 private class TestDeviceService extends DeviceServiceAdapter {
96
97 List<Device> deviceList;
98
99 TestDeviceService() {
100 deviceList = new ArrayList<>();
101
102 deviceList.add(d1);
103 }
104
105 @Override
106 public Iterable<Device> getDevices() {
107 return deviceList;
108 }
109
110 @Override
111 public boolean isAvailable(DeviceId deviceId) {
112 return true;
113 }
114 }
115
116 private class TestFlowObjectiveStore extends FlowObjectiveStoreAdapter {
117 @Override
118 public NextGroup getNextGroup(Integer nextId) {
119 if (nextId != 4) {
120 byte[] data = new byte[1];
121 data[0] = 5;
122 return new DefaultNextGroup(data);
123 } else {
124 return null;
125 }
126 }
127
128 }
129
130 private class TestDriversLoader extends AbstractDriverLoader implements DefaultDriverProviderService {
131 public TestDriversLoader() {
132 super("/onos-drivers.xml");
133 }
134 }
135
136 private class TestDriver extends DriverAdapter {
137
138 @Override
139 public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
140 return true;
141 }
142
143 @Override
144 @SuppressWarnings("unchecked")
145 public <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass) {
146 return (T) new TestPipeliner();
147 }
148
149 @Override
150 @SuppressWarnings("unchecked")
151 public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) {
152 return (T) new TestPipeliner();
153 }
154
155 }
156
157 private class TestPipeliner extends PipelinerAdapter {
158 DeviceId deviceId;
159
160 @Override
161 public void init(DeviceId deviceId, PipelinerContext context) {
162 this.deviceId = deviceId;
163 }
164
165 @Override
166 public void filter(FilteringObjective filterObjective) {
167 filteringObjectives.add(deviceId.toString());
168 }
169
170 @Override
171 public void forward(ForwardingObjective forwardObjective) {
172 forwardingObjectives.add(deviceId.toString());
173 }
174
175 @Override
176 public void next(NextObjective nextObjective) {
177 nextObjectives.add(deviceId.toString());
178 }
179 }
180
181 private class TestDriverService extends DriverServiceAdapter {
182 @Override
183 public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
184 Driver driver = new TestDriver();
185 return new DefaultDriverHandler(new DefaultDriverData(driver, id1));
186 }
187 }
188
189 @Before
190 public void initializeTest() {
191 manager = new FlowObjectiveManager();
192 manager.flowObjectiveStore = new TestFlowObjectiveStore();
193 manager.mastershipService = new MastershipServiceAdapter();
194 manager.deviceService = new TestDeviceService();
195 manager.defaultDriverService = new TestDriversLoader();
196 manager.driverService = new TestDriverService();
197
198 filteringObjectives = new ArrayList<>();
199 forwardingObjectives = new ArrayList<>();
200 nextObjectives = new ArrayList<>();
201 manager.activate();
202 }
203
204 @After
205 public void tearDownTest() {
206 manager.deactivate();
207 manager = null;
208 filteringObjectives.clear();
209 forwardingObjectives.clear();
210 nextObjectives.clear();
211 }
212
213 /**
214 * Tests adding a forwarding objective.
215 */
216 @Test
217 public void forwardingObjective() {
218 TrafficSelector selector = DefaultTrafficSelector.emptySelector();
219 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
220 ForwardingObjective forward =
221 DefaultForwardingObjective.builder()
222 .fromApp(NetTestTools.APP_ID)
223 .withFlag(ForwardingObjective.Flag.SPECIFIC)
224 .withSelector(selector)
225 .withTreatment(treatment)
226 .makePermanent()
227 .add();
228
229 manager.forward(id1, forward);
230
231 TestTools.assertAfter(RETRY_MS, () ->
232 assertThat(forwardingObjectives, hasSize(1)));
233
234 assertThat(forwardingObjectives, hasItem("of:d1"));
235 assertThat(filteringObjectives, hasSize(0));
236 assertThat(nextObjectives, hasSize(0));
237 }
238
239 /**
240 * Tests adding a filtering objective.
241 */
242 @Test
243 public void filteringObjective() {
244 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
245 FilteringObjective filter =
246 DefaultFilteringObjective.builder()
247 .fromApp(NetTestTools.APP_ID)
248 .withMeta(treatment)
249 .makePermanent()
250 .deny()
251 .addCondition(Criteria.matchEthType(12))
252 .add();
253
254 manager.activate();
255 manager.filter(id1, filter);
256
257 TestTools.assertAfter(RETRY_MS, () ->
258 assertThat(filteringObjectives, hasSize(1)));
259
260 assertThat(forwardingObjectives, hasSize(0));
261 assertThat(filteringObjectives, hasItem("of:d1"));
262 assertThat(nextObjectives, hasSize(0));
263 }
264
265 /**
266 * Tests adding a next objective.
267 */
268 @Test
269 public void nextObjective() {
270 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
271 NextObjective next =
272 DefaultNextObjective.builder()
273 .withId(manager.allocateNextId())
274 .addTreatment(treatment)
275 .withType(NextObjective.Type.BROADCAST)
276 .fromApp(NetTestTools.APP_ID)
277 .makePermanent()
278 .add();
279
280 manager.next(id1, next);
281
282 TestTools.assertAfter(RETRY_MS, () ->
283 assertThat(nextObjectives, hasSize(1)));
284
285 assertThat(forwardingObjectives, hasSize(0));
286 assertThat(filteringObjectives, hasSize(0));
287 assertThat(nextObjectives, hasItem("of:d1"));
288 }
289
290 /**
291 * Tests adding a pending forwarding objective.
292 *
293 * @throws TestUtilsException if lookup of a field fails
294 */
295 @Test
296 public void pendingForwardingObjective() throws TestUtilsException {
297 TrafficSelector selector = DefaultTrafficSelector.emptySelector();
298 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
299
300 ForwardingObjective forward4 =
301 DefaultForwardingObjective.builder()
302 .fromApp(NetTestTools.APP_ID)
303 .withFlag(ForwardingObjective.Flag.SPECIFIC)
304 .withSelector(selector)
305 .withTreatment(treatment)
306 .makePermanent()
307 .nextStep(4)
308 .add();
309 ForwardingObjective forward5 =
310 DefaultForwardingObjective.builder()
311 .fromApp(NetTestTools.APP_ID)
312 .withFlag(ForwardingObjective.Flag.SPECIFIC)
313 .withSelector(selector)
314 .withTreatment(treatment)
315 .makePermanent()
316 .nextStep(5)
317 .add();
318
319 // multiple pending forwards should be combined
320 manager.forward(id1, forward4);
321 manager.forward(id1, forward4);
322 manager.forward(id1, forward5);
323
324
325 // 1 should be complete, 1 pending
326 TestTools.assertAfter(RETRY_MS, () ->
327 assertThat(forwardingObjectives, hasSize(1)));
328
329 assertThat(forwardingObjectives, hasItem("of:d1"));
330 assertThat(filteringObjectives, hasSize(0));
331 assertThat(nextObjectives, hasSize(0));
332
333 // Now send events to trigger the objective still in the queue
334 ObjectiveEvent event1 = new ObjectiveEvent(ObjectiveEvent.Type.ADD, 4);
335 FlowObjectiveStoreDelegate delegate = TestUtils.getField(manager, "delegate");
336 delegate.notify(event1);
337
338 // all should be processed now
339 TestTools.assertAfter(RETRY_MS, () ->
340 assertThat(forwardingObjectives, hasSize(2)));
341 assertThat(forwardingObjectives, hasItem("of:d1"));
342 assertThat(filteringObjectives, hasSize(0));
343 assertThat(nextObjectives, hasSize(0));
344 }
345
346 /**
347 * Tests receipt of a device up event.
348 *
349 * @throws TestUtilsException if lookup of a field fails
350 */
351 @Test
352 public void deviceUpEvent() throws TestUtilsException {
353 TrafficSelector selector = DefaultTrafficSelector.emptySelector();
354 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
355
356 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, d2);
357 DeviceListener listener = TestUtils.getField(manager, "deviceListener");
358 assertThat(listener, notNullValue());
359
360 listener.event(event);
361
362 ForwardingObjective forward =
363 DefaultForwardingObjective.builder()
364 .fromApp(NetTestTools.APP_ID)
365 .withFlag(ForwardingObjective.Flag.SPECIFIC)
366 .withSelector(selector)
367 .withTreatment(treatment)
368 .makePermanent()
369 .add();
370 manager.forward(id2, forward);
371
372 // new device should have an objective now
373 TestTools.assertAfter(RETRY_MS, () ->
374 assertThat(forwardingObjectives, hasSize(1)));
375
376 assertThat(forwardingObjectives, hasItem("of:d2"));
377 assertThat(filteringObjectives, hasSize(0));
378 assertThat(nextObjectives, hasSize(0));
379 }
380
381 /**
382 * Tests recepit of a device mastership event.
383 *
384 * @throws TestUtilsException if lookup of a field fails
385 */
386 @Test
387 public void deviceMastershipEvent() throws TestUtilsException {
388 TrafficSelector selector = DefaultTrafficSelector.emptySelector();
389 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
390
391 MastershipEvent event =
392 new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, id2, null);
393 MastershipListener listener = TestUtils.getField(manager, "mastershipListener");
394 assertThat(listener, notNullValue());
395
396 listener.event(event);
397
398 ForwardingObjective forward =
399 DefaultForwardingObjective.builder()
400 .fromApp(NetTestTools.APP_ID)
401 .withFlag(ForwardingObjective.Flag.SPECIFIC)
402 .withSelector(selector)
403 .withTreatment(treatment)
404 .makePermanent()
405 .add();
406 manager.forward(id2, forward);
407
408 // new device should have an objective now
409 TestTools.assertAfter(RETRY_MS, () ->
410 assertThat(forwardingObjectives, hasSize(1)));
411
412 assertThat(forwardingObjectives, hasItem("of:d2"));
413 assertThat(filteringObjectives, hasSize(0));
414 assertThat(nextObjectives, hasSize(0));
415 }
416}