blob: 88a7e7aa36997c0dece6eaa9c74846a1d3dd977a [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070017
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableMap;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Sets;
22import com.google.common.util.concurrent.ListenableFuture;
23import com.google.common.util.concurrent.MoreExecutors;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070024import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080027import org.onlab.junit.TestTools;
Marc De Leenheerde47caa2015-04-24 11:27:44 -070028import org.onosproject.cfg.ComponentConfigAdapter;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080029import org.onosproject.common.event.impl.TestEventDispatcher;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.core.ApplicationId;
Ray Milkeycc53abd2015-02-19 12:31:33 -080031import org.onosproject.core.CoreServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.core.DefaultApplicationId;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080033import org.onosproject.core.IdGenerator;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080034import org.onosproject.mastership.MastershipServiceAdapter;
35import org.onosproject.net.AnnotationKeys;
36import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.DefaultDevice;
38import org.onosproject.net.Device;
39import org.onosproject.net.Device.Type;
40import org.onosproject.net.DeviceId;
41import org.onosproject.net.MastershipRole;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.device.DeviceServiceAdapter;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080043import org.onosproject.net.driver.AbstractHandlerBehaviour;
44import org.onosproject.net.driver.DefaultDriver;
45import org.onosproject.net.driver.impl.DriverManager;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.flow.CompletedBatchOperation;
47import org.onosproject.net.flow.DefaultFlowEntry;
48import org.onosproject.net.flow.DefaultFlowRule;
49import org.onosproject.net.flow.FlowEntry;
50import org.onosproject.net.flow.FlowEntry.FlowEntryState;
51import org.onosproject.net.flow.FlowRule;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.flow.FlowRuleBatchOperation;
53import org.onosproject.net.flow.FlowRuleEvent;
54import org.onosproject.net.flow.FlowRuleListener;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080055import org.onosproject.net.flow.FlowRuleProgrammable;
Brian O'Connorabafb502014-12-02 22:26:20 -080056import org.onosproject.net.flow.FlowRuleProvider;
57import org.onosproject.net.flow.FlowRuleProviderRegistry;
58import org.onosproject.net.flow.FlowRuleProviderService;
59import org.onosproject.net.flow.FlowRuleService;
60import org.onosproject.net.flow.StoredFlowEntry;
61import org.onosproject.net.flow.TrafficSelector;
62import org.onosproject.net.flow.TrafficTreatment;
63import org.onosproject.net.flow.criteria.Criterion;
64import org.onosproject.net.flow.instructions.Instruction;
alshabib346b5b32015-03-06 00:42:16 -080065import org.onosproject.net.flow.instructions.Instructions;
Saurav Das86af8f12015-05-25 23:55:33 -070066import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080067import org.onosproject.net.provider.AbstractProvider;
68import org.onosproject.net.provider.ProviderId;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070069import org.onosproject.store.trivial.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070070
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070071import java.util.ArrayList;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080072import java.util.Collection;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070073import java.util.Collections;
74import java.util.HashMap;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080075import java.util.HashSet;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070076import java.util.List;
77import java.util.Map;
78import java.util.Set;
79import java.util.concurrent.ExecutionException;
80import java.util.concurrent.Executor;
81import java.util.concurrent.TimeUnit;
82import java.util.concurrent.TimeoutException;
83import java.util.concurrent.atomic.AtomicLong;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070084
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080085import static org.junit.Assert.*;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070086import static org.onosproject.net.NetTestTools.injectEventDispatcher;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080087import static org.onosproject.net.flow.FlowRuleEvent.Type.*;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070088
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070089/**
90 * Test codifying the flow rule service & flow rule provider service contracts.
91 */
tom202175a2014-09-19 19:00:11 -070092public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070093
alshabib92c65ad2014-10-08 21:56:05 -070094
tomf6ab2152014-09-18 12:08:29 -070095 private static final ProviderId PID = new ProviderId("of", "foo");
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080096 private static final ProviderId FOO_PID = new ProviderId("foo", "foo");
97
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070098 private static final DeviceId DID = DeviceId.deviceId("of:001");
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080099 private static final DeviceId FOO_DID = DeviceId.deviceId("foo:002");
alshabibba5ac482014-10-02 17:15:20 -0700100 private static final int TIMEOUT = 10;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800101
102 private static final DefaultAnnotations ANNOTATIONS =
103 DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, "foo").build();
104
105 private static final Device DEV =
106 new DefaultDevice(PID, DID, Type.SWITCH, "", "", "", "", null);
107 private static final Device FOO_DEV =
108 new DefaultDevice(FOO_PID, FOO_DID, Type.SWITCH, "", "", "", "", null, ANNOTATIONS);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700109
tom202175a2014-09-19 19:00:11 -0700110 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700111
112 protected FlowRuleService service;
113 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -0700114 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700115 protected TestProvider provider;
116 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -0700117 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700118
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800119 private TestDriverManager driverService;
120
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800121
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700122 @Before
123 public void setUp() {
tom202175a2014-09-19 19:00:11 -0700124 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -0700125 mgr.store = new SimpleFlowRuleStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700126 injectEventDispatcher(mgr, new TestEventDispatcher());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700127 mgr.deviceService = new TestDeviceService();
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800128 mgr.mastershipService = new TestMastershipService();
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800129 mgr.coreService = new TestCoreService();
130 mgr.operationsService = MoreExecutors.newDirectExecutorService();
131 mgr.deviceInstallers = MoreExecutors.newDirectExecutorService();
Marc De Leenheerde47caa2015-04-24 11:27:44 -0700132 mgr.cfgService = new ComponentConfigAdapter();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700133 service = mgr;
134 registry = mgr;
135
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800136 driverService = new TestDriverManager();
137 driverService.addDriver(new DefaultDriver("foo", ImmutableList.of(), "", "", "",
138 ImmutableMap.of(FlowRuleProgrammable.class,
139 TestFlowRuleProgrammable.class),
140 ImmutableMap.of()));
141
Marc De Leenheerde47caa2015-04-24 11:27:44 -0700142 mgr.activate(null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700143 mgr.addListener(listener);
144 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700145 providerService = registry.register(provider);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800146 appId = new TestApplicationId(0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700147 assertTrue("provider should be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700148 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700149 }
150
151 @After
152 public void tearDown() {
153 registry.unregister(provider);
154 assertFalse("provider should not be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700155 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700156 service.removeListener(listener);
157 mgr.deactivate();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700158 injectEventDispatcher(mgr, null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700159 mgr.deviceService = null;
160 }
161
162 private FlowRule flowRule(int tsval, int trval) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800163 return flowRule(DID, tsval, trval);
164 }
165
166 private FlowRule flowRule(DeviceId did, int tsval, int trval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700167 TestSelector ts = new TestSelector(tsval);
168 TestTreatment tr = new TestTreatment(trval);
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700169 return DefaultFlowRule.builder()
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800170 .forDevice(did)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700171 .withSelector(ts)
172 .withTreatment(tr)
173 .withPriority(10)
174 .fromApp(appId)
175 .makeTemporary(TIMEOUT)
176 .build();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700177 }
178
alshabibbb8b1282014-09-22 17:00:18 -0700179 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700180 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700181 service.applyFlowRules(rule);
182
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700183 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700184 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700185 }
186
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700187 private void validateEvents(FlowRuleEvent.Type... events) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700188 if (events == null) {
189 assertTrue("events generated", listener.events.isEmpty());
190 }
191
192 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700193 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700194 for (FlowRuleEvent e : listener.events) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800195 assertEquals("unexpected event", events[i], e.type());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700196 i++;
197 }
198
199 assertEquals("mispredicted number of events",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700200 events.length, listener.events.size());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700201
202 listener.events.clear();
203 }
204
205 private int flowCount() {
206 return Sets.newHashSet(service.getFlowEntries(DID)).size();
207 }
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700208
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700209 @Test
210 public void getFlowEntries() {
211 assertTrue("store should be empty",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700212 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700213 FlowRule f1 = addFlowRule(1);
214 FlowRule f2 = addFlowRule(2);
215
alshabib1c319ff2014-10-04 20:29:09 -0700216 FlowEntry fe1 = new DefaultFlowEntry(f1);
217 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700218 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700219
alshabib1c319ff2014-10-04 20:29:09 -0700220 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700221 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
222 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700223
224 addFlowRule(1);
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800225 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700226 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700227
alshabib1c319ff2014-10-04 20:29:09 -0700228 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
Charles Chan93fa7272016-01-26 22:27:02 -0800229 validateEvents(RULE_UPDATED, RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700230 }
231
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700232 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
233 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700234 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700235 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700236 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
237 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
238 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700239 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700240 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700241 return true;
242 }
243
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700244 @Test
245 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700246
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700247 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700248 FlowRule r2 = flowRule(2, 2);
249 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700250
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700251 assertTrue("store should be empty",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800252 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700253 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700254 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700255 assertTrue("Entries should be pending add.",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800256 validateState(ImmutableMap.of(
257 r1, FlowEntryState.PENDING_ADD,
258 r2, FlowEntryState.PENDING_ADD,
259 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700260 }
261
262 @Test
Kavitha Alagesanc69c66a2016-06-15 14:26:04 +0530263 public void purgeFlowRules() {
264 FlowRule f1 = addFlowRule(1);
265 FlowRule f2 = addFlowRule(2);
266 FlowRule f3 = addFlowRule(3);
267 assertEquals("3 rules should exist", 3, flowCount());
268 FlowEntry fe1 = new DefaultFlowEntry(f1);
269 FlowEntry fe2 = new DefaultFlowEntry(f2);
270 FlowEntry fe3 = new DefaultFlowEntry(f3);
271 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
272 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
273 RULE_ADDED, RULE_ADDED, RULE_ADDED);
274 mgr.purgeFlowRules(DID);
275 assertEquals("0 rule should exist", 0, flowCount());
276 }
277
278 @Test
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700279 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700280 FlowRule f1 = addFlowRule(1);
281 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700282 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700283 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700284
alshabib1c319ff2014-10-04 20:29:09 -0700285 FlowEntry fe1 = new DefaultFlowEntry(f1);
286 FlowEntry fe2 = new DefaultFlowEntry(f2);
287 FlowEntry fe3 = new DefaultFlowEntry(f3);
288 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700289 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
290 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700291
alshabib1c319ff2014-10-04 20:29:09 -0700292 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700293 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700294 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700295 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700296 assertTrue("Entries should be pending remove.",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800297 validateState(ImmutableMap.of(
298 f1, FlowEntryState.PENDING_REMOVE,
299 f2, FlowEntryState.PENDING_REMOVE,
300 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700301
alshabib1c319ff2014-10-04 20:29:09 -0700302 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700303 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700304 }
305
306 @Test
307 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700308 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700309 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700310 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700311 FlowEntry fe2 = new DefaultFlowEntry(f2);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800312
alshabib1c319ff2014-10-04 20:29:09 -0700313 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700314 service.removeFlowRules(f1);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800315
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800316 //FIXME modification of "stored" flow entry outside of store
alshabib1c319ff2014-10-04 20:29:09 -0700317 fe1.setState(FlowEntryState.REMOVED);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800318
alshabib1c319ff2014-10-04 20:29:09 -0700319 providerService.flowRemoved(fe1);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800320
alshabib3d643ec2014-10-22 18:33:00 -0700321 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800322 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700323
alshabib1c319ff2014-10-04 20:29:09 -0700324 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700325 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700326
alshabibba5ac482014-10-02 17:15:20 -0700327 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700328 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700329 service.applyFlowRules(f3);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800330
alshabib1c319ff2014-10-04 20:29:09 -0700331 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
Charles Chan93fa7272016-01-26 22:27:02 -0800332 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED, RULE_UPDATED);
alshabibba5ac482014-10-02 17:15:20 -0700333
alshabib1c319ff2014-10-04 20:29:09 -0700334 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700335 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700336 }
337
alshabibbb8b1282014-09-22 17:00:18 -0700338 @Test
339 public void flowMetrics() {
340 FlowRule f1 = flowRule(1, 1);
341 FlowRule f2 = flowRule(2, 2);
342 FlowRule f3 = flowRule(3, 3);
343
alshabibba5ac482014-10-02 17:15:20 -0700344 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700345
alshabib1c319ff2014-10-04 20:29:09 -0700346 FlowEntry fe1 = new DefaultFlowEntry(f1);
347 FlowEntry fe2 = new DefaultFlowEntry(f2);
348
alshabib1c319ff2014-10-04 20:29:09 -0700349 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
350 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
351
352 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700353
354 assertTrue("Entries should be added.",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700355 validateState(ImmutableMap.of(
356 f1, FlowEntryState.ADDED,
357 f2, FlowEntryState.ADDED,
358 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700359
alshabib3d643ec2014-10-22 18:33:00 -0700360 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800361 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700362 }
363
364 @Test
365 public void extraneousFlow() {
366 FlowRule f1 = flowRule(1, 1);
367 FlowRule f2 = flowRule(2, 2);
368 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700369 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700370
alshabib1c319ff2014-10-04 20:29:09 -0700371// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
372// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
373// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
374 FlowEntry fe1 = new DefaultFlowEntry(f1);
375 FlowEntry fe2 = new DefaultFlowEntry(f2);
376 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700377
alshabib1c319ff2014-10-04 20:29:09 -0700378
379 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700380
alshabib3d643ec2014-10-22 18:33:00 -0700381 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700382
383 }
384
385 /*
386 * Tests whether a rule that was marked for removal but no flowRemoved was received
387 * is indeed removed at the next stats update.
388 */
389 @Test
390 public void flowMissingRemove() {
391 FlowRule f1 = flowRule(1, 1);
392 FlowRule f2 = flowRule(2, 2);
393 FlowRule f3 = flowRule(3, 3);
394
alshabib1c319ff2014-10-04 20:29:09 -0700395// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
396// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
397
398 FlowEntry fe1 = new DefaultFlowEntry(f1);
399 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700400 mgr.applyFlowRules(f1, f2, f3);
401
402 mgr.removeFlowRules(f3);
403
alshabib1c319ff2014-10-04 20:29:09 -0700404 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700405
alshabib3d643ec2014-10-22 18:33:00 -0700406 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
407 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700408
409 }
410
411 @Test
412 public void getByAppId() {
413 FlowRule f1 = flowRule(1, 1);
414 FlowRule f2 = flowRule(2, 2);
415 mgr.applyFlowRules(f1, f2);
416
417 assertTrue("should have two rules",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800418 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700419 }
420
421 @Test
422 public void removeByAppId() {
423 FlowRule f1 = flowRule(1, 1);
424 FlowRule f2 = flowRule(2, 2);
425 mgr.applyFlowRules(f1, f2);
426
427
428 mgr.removeFlowRulesById(appId);
429
430 //only check that we are in pending remove. Events and actual remove state will
431 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700432 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700433 f1, FlowEntryState.PENDING_REMOVE,
434 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700435 }
436
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800437 @Test
438 public void fallbackBasics() {
439 FlowRule f1 = flowRule(FOO_DID, 1, 1);
440 flowRules.clear();
441 mgr.applyFlowRules(f1);
442 assertTrue("flow rule not applied", flowRules.contains(f1));
443
444 flowRules.clear();
445 mgr.removeFlowRules(f1);
446 assertTrue("flow rule not removed", flowRules.contains(f1));
447 }
448
449 @Test
450 public void fallbackFlowRemoved() {
451 FlowRule f1 = flowRule(FOO_DID, 1, 1);
452 mgr.applyFlowRules(f1);
453 flowRules.clear();
454 providerService.flowRemoved(new DefaultFlowEntry(f1));
455 assertTrue("flow rule not reapplied", flowRules.contains(f1));
456 }
457
458 @Test
459 public void fallbackExtraFlow() {
460 FlowRule f1 = flowRule(FOO_DID, 1, 1);
461 flowRules.clear();
462 providerService.pushFlowMetrics(FOO_DID, ImmutableList.of(new DefaultFlowEntry(f1)));
463 assertTrue("flow rule not removed", flowRules.contains(f1));
464 }
465
466 @Test
467 public void fallbackPoll() {
468 FlowRuleDriverProvider fallback = (FlowRuleDriverProvider) mgr.defaultProvider();
469 FlowRule f1 = flowRule(FOO_DID, 1, 1);
470 mgr.applyFlowRules(f1);
471 FlowEntry fe = mgr.getFlowEntries(FOO_DID).iterator().next();
472 assertEquals("incorrect state", FlowEntryState.PENDING_ADD, fe.state());
473
474 fallback.init(fallback.providerService, mgr.deviceService, mgr.mastershipService, 1);
475 TestTools.assertAfter(2000, () -> {
476 FlowEntry e = mgr.getFlowEntries(FOO_DID).iterator().next();
477 assertEquals("incorrect state", FlowEntryState.ADDED, e.state());
478 });
479 }
480
481
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700482 private static class TestListener implements FlowRuleListener {
483 final List<FlowRuleEvent> events = new ArrayList<>();
484
485 @Override
486 public void event(FlowRuleEvent event) {
487 events.add(event);
488 }
489 }
490
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800491 private static class TestDeviceService extends DeviceServiceAdapter {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700492 @Override
493 public int getDeviceCount() {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800494 return 2;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700495 }
496
497 @Override
498 public Iterable<Device> getDevices() {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800499 return ImmutableList.of(DEV, FOO_DEV);
500 }
501
502 @Override
503 public Iterable<Device> getAvailableDevices() {
504 return getDevices();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700505 }
506
507 @Override
508 public Device getDevice(DeviceId deviceId) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800509 return deviceId.equals(FOO_DID) ? FOO_DEV : DEV;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700510 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700511 }
512
513 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
514
515 protected TestProvider(ProviderId id) {
516 super(PID);
517 }
518
519 @Override
520 public void applyFlowRule(FlowRule... flowRules) {
521 }
522
523 @Override
524 public void removeFlowRule(FlowRule... flowRules) {
525 }
526
alshabiba68eb962014-09-24 20:34:13 -0700527 @Override
528 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
529 }
530
alshabib902d41b2014-10-07 16:52:05 -0700531 @Override
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800532 public void executeBatch(FlowRuleBatchOperation batch) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800533 // TODO: need to call batchOperationComplete
alshabib902d41b2014-10-07 16:52:05 -0700534 }
535
alshabibcf369912014-10-13 14:16:42 -0700536 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700537 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700538
539 @Override
540 public boolean cancel(boolean mayInterruptIfRunning) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800541 return false;
alshabibcf369912014-10-13 14:16:42 -0700542 }
543
544 @Override
545 public boolean isCancelled() {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800546 return false;
alshabibcf369912014-10-13 14:16:42 -0700547 }
548
549 @Override
550 public boolean isDone() {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800551 return true;
alshabibcf369912014-10-13 14:16:42 -0700552 }
553
554 @Override
555 public CompletedBatchOperation get()
556 throws InterruptedException, ExecutionException {
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700557 return new CompletedBatchOperation(true, Collections.emptySet(), null);
alshabibcf369912014-10-13 14:16:42 -0700558 }
559
560 @Override
561 public CompletedBatchOperation get(long timeout, TimeUnit unit)
562 throws InterruptedException,
563 ExecutionException, TimeoutException {
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700564 return new CompletedBatchOperation(true, Collections.emptySet(), null);
alshabibcf369912014-10-13 14:16:42 -0700565 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700566
567 @Override
568 public void addListener(Runnable task, Executor executor) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800569 if (isDone()) {
570 executor.execute(task);
571 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700572 }
alshabibcf369912014-10-13 14:16:42 -0700573 }
alshabiba68eb962014-09-24 20:34:13 -0700574
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700575 }
576
577 private class TestSelector implements TrafficSelector {
578
579 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700580 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700581
582 public TestSelector(int val) {
583 testval = val;
584 }
585
586 @Override
alshabibba5ac482014-10-02 17:15:20 -0700587 public Set<Criterion> criteria() {
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700588 return Collections.emptySet();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700589 }
590
591 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700592 public Criterion getCriterion(
Brian O'Connorabafb502014-12-02 22:26:20 -0800593 org.onosproject.net.flow.criteria.Criterion.Type type) {
Jonathan Hart936c49d2014-10-23 16:38:59 -0700594 return null;
595 }
596
597 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700598 public int hashCode() {
599 return testval;
600 }
601
602 @Override
603 public boolean equals(Object o) {
604 if (o instanceof TestSelector) {
605 return this.testval == ((TestSelector) o).testval;
606 }
607 return false;
608 }
Jonathan Hart936c49d2014-10-23 16:38:59 -0700609
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700610 }
611
612 private class TestTreatment implements TrafficTreatment {
613
614 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700615 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700616
617 public TestTreatment(int val) {
618 testval = val;
619 }
620
621 @Override
alshabib346b5b32015-03-06 00:42:16 -0800622 public List<Instruction> deferred() {
623 return null;
624 }
625
626 @Override
627 public List<Instruction> immediate() {
628 return null;
629 }
630
631 @Override
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -0700632 public List<Instruction> allInstructions() {
633 return null;
634 }
635
636 @Override
alshabib346b5b32015-03-06 00:42:16 -0800637 public Instructions.TableTypeTransition tableTransition() {
638 return null;
639 }
640
641 @Override
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700642 public boolean clearedDeferred() {
643 return false;
alshabib346b5b32015-03-06 00:42:16 -0800644 }
645
646 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700647 public int hashCode() {
648 return testval;
649 }
650
651 @Override
652 public boolean equals(Object o) {
653 if (o instanceof TestTreatment) {
654 return this.testval == ((TestTreatment) o).testval;
655 }
656 return false;
657 }
658
Saurav Das86af8f12015-05-25 23:55:33 -0700659 @Override
660 public MetadataInstruction writeMetadata() {
661 return null;
662 }
663
alshabib10c810b2015-08-18 16:59:04 -0700664 @Override
665 public Instructions.MeterInstruction metered() {
666 return null;
667 }
668
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700669 }
670
alshabib92c65ad2014-10-08 21:56:05 -0700671 public class TestApplicationId extends DefaultApplicationId {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800672 public TestApplicationId(int id, String name) {
alshabib92c65ad2014-10-08 21:56:05 -0700673 super(id, name);
674 }
675 }
676
Ray Milkeycc53abd2015-02-19 12:31:33 -0800677 private class TestCoreService extends CoreServiceAdapter {
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800678
679 @Override
680 public IdGenerator getIdGenerator(String topic) {
681 return new IdGenerator() {
682 private AtomicLong counter = new AtomicLong(0);
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800683
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800684 @Override
685 public long getNewId() {
686 return counter.getAndIncrement();
687 }
688 };
689 }
690 }
691
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800692 private class TestMastershipService extends MastershipServiceAdapter {
693 @Override
694 public MastershipRole getLocalRole(DeviceId deviceId) {
695 return MastershipRole.MASTER;
696 }
697 }
698
699 private class TestDriverManager extends DriverManager {
700 TestDriverManager() {
701 this.deviceService = mgr.deviceService;
702 activate();
703 }
704 }
705
706 static Collection<FlowRule> flowRules = new HashSet<>();
707
708 public static class TestFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
709
710 @Override
711 public Collection<FlowEntry> getFlowEntries() {
712 ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
713 flowRules.stream().map(DefaultFlowEntry::new).forEach(builder::add);
714 return builder.build();
715 }
716
717 @Override
718 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
719 flowRules.addAll(rules);
720 return rules;
721 }
722
723 @Override
724 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
725 flowRules.addAll(rules);
726 return rules;
727 }
728 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700729}