blob: 175a299b34f69942b6e4b8c3b3e85e020f9d59f6 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 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 */
tombe988312014-09-19 18:38:47 -070016package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070017
Thomas Vachuskae0f804a2014-10-27 23:40:48 -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;
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -080023
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070024import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070027import org.onlab.onos.core.ApplicationId;
28import org.onlab.onos.core.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070029import org.onlab.onos.event.impl.TestEventDispatcher;
30import org.onlab.onos.net.DefaultDevice;
31import org.onlab.onos.net.Device;
32import org.onlab.onos.net.Device.Type;
33import org.onlab.onos.net.DeviceId;
34import org.onlab.onos.net.MastershipRole;
35import org.onlab.onos.net.Port;
36import org.onlab.onos.net.PortNumber;
37import org.onlab.onos.net.device.DeviceListener;
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -080038import org.onlab.onos.net.device.DeviceServiceAdapter;
Jonathan Hart936c49d2014-10-23 16:38:59 -070039import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070040import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070041import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070042import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070043import org.onlab.onos.net.flow.FlowEntry;
44import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070045import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070046import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070047import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070048import org.onlab.onos.net.flow.FlowRuleEvent;
49import org.onlab.onos.net.flow.FlowRuleListener;
50import org.onlab.onos.net.flow.FlowRuleProvider;
51import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
52import org.onlab.onos.net.flow.FlowRuleProviderService;
53import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070054import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070055import org.onlab.onos.net.flow.TrafficSelector;
56import org.onlab.onos.net.flow.TrafficTreatment;
57import org.onlab.onos.net.flow.criteria.Criterion;
58import org.onlab.onos.net.flow.instructions.Instruction;
59import org.onlab.onos.net.provider.AbstractProvider;
60import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070061import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070062
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070063import java.util.ArrayList;
64import java.util.Arrays;
65import java.util.Collections;
66import java.util.HashMap;
67import java.util.List;
68import java.util.Map;
69import java.util.Set;
70import java.util.concurrent.ExecutionException;
71import java.util.concurrent.Executor;
72import java.util.concurrent.Future;
73import java.util.concurrent.TimeUnit;
74import java.util.concurrent.TimeoutException;
75
76import static org.junit.Assert.*;
77import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070078
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070079/**
80 * Test codifying the flow rule service & flow rule provider service contracts.
81 */
tom202175a2014-09-19 19:00:11 -070082public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070083
alshabib92c65ad2014-10-08 21:56:05 -070084
tomf6ab2152014-09-18 12:08:29 -070085 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070086 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070087 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070088 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070089 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070090
tom202175a2014-09-19 19:00:11 -070091 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070092
93 protected FlowRuleService service;
94 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070095 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070096 protected TestProvider provider;
97 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070098 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070099
100 @Before
101 public void setUp() {
tom202175a2014-09-19 19:00:11 -0700102 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -0700103 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700104 mgr.eventDispatcher = new TestEventDispatcher();
105 mgr.deviceService = new TestDeviceService();
106 service = mgr;
107 registry = mgr;
108
109 mgr.activate();
110 mgr.addListener(listener);
111 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700112 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700113 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700114 assertTrue("provider should be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700115 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700116 }
117
118 @After
119 public void tearDown() {
120 registry.unregister(provider);
121 assertFalse("provider should not be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700122 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700123 service.removeListener(listener);
124 mgr.deactivate();
125 mgr.eventDispatcher = null;
126 mgr.deviceService = null;
127 }
128
129 private FlowRule flowRule(int tsval, int trval) {
130 TestSelector ts = new TestSelector(tsval);
131 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700132 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700133 }
134
alshabibbb8b1282014-09-22 17:00:18 -0700135
136 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700137 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700138 service.applyFlowRules(rule);
139
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700140 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700141 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700142 }
143
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700144 private void validateEvents(FlowRuleEvent.Type... events) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700145 if (events == null) {
146 assertTrue("events generated", listener.events.isEmpty());
147 }
148
149 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700150 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700151 for (FlowRuleEvent e : listener.events) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800152 assertEquals("unexpected event", events[i], e.type());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700153 i++;
154 }
155
156 assertEquals("mispredicted number of events",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700157 events.length, listener.events.size());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700158
159 listener.events.clear();
160 }
161
162 private int flowCount() {
163 return Sets.newHashSet(service.getFlowEntries(DID)).size();
164 }
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700165
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700166 @Test
167 public void getFlowEntries() {
168 assertTrue("store should be empty",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700169 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700170 FlowRule f1 = addFlowRule(1);
171 FlowRule f2 = addFlowRule(2);
172
alshabib1c319ff2014-10-04 20:29:09 -0700173 FlowEntry fe1 = new DefaultFlowEntry(f1);
174 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700175 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700176
alshabib1c319ff2014-10-04 20:29:09 -0700177 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700178 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
179 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700180
181 addFlowRule(1);
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800182 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700183 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700184
alshabib1c319ff2014-10-04 20:29:09 -0700185 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700186 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700187 }
188
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700189 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
190 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700191 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700192 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700193 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
194 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
195 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700196 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700197 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700198 return true;
199 }
200
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700201 @Test
202 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700203
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700204 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700205 FlowRule r2 = flowRule(2, 2);
206 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700207
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700208 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700209 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700210 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700211 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700212 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700213 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700214 r1, FlowEntryState.PENDING_ADD,
215 r2, FlowEntryState.PENDING_ADD,
216 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700217 }
218
219 @Test
220 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700221 FlowRule f1 = addFlowRule(1);
222 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700223 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700224 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700225
alshabib1c319ff2014-10-04 20:29:09 -0700226 FlowEntry fe1 = new DefaultFlowEntry(f1);
227 FlowEntry fe2 = new DefaultFlowEntry(f2);
228 FlowEntry fe3 = new DefaultFlowEntry(f3);
229 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700230 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
231 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700232
alshabib1c319ff2014-10-04 20:29:09 -0700233 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700234 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700235 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700236 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700237 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700238 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700239 f1, FlowEntryState.PENDING_REMOVE,
240 f2, FlowEntryState.PENDING_REMOVE,
241 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700242
alshabib1c319ff2014-10-04 20:29:09 -0700243 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700244 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700245 }
246
247 @Test
248 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700249 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700250 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700251 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700252 FlowEntry fe2 = new DefaultFlowEntry(f2);
253 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700254 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700255 fe1.setState(FlowEntryState.REMOVED);
256 providerService.flowRemoved(fe1);
alshabib3d643ec2014-10-22 18:33:00 -0700257 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
258 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700259
alshabib1c319ff2014-10-04 20:29:09 -0700260 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700261 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700262
alshabibba5ac482014-10-02 17:15:20 -0700263 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700264 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700265 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700266 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700267 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700268
alshabib1c319ff2014-10-04 20:29:09 -0700269 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700270 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700271 }
272
alshabibbb8b1282014-09-22 17:00:18 -0700273 @Test
274 public void flowMetrics() {
275 FlowRule f1 = flowRule(1, 1);
276 FlowRule f2 = flowRule(2, 2);
277 FlowRule f3 = flowRule(3, 3);
278
alshabibba5ac482014-10-02 17:15:20 -0700279 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700280
alshabib1c319ff2014-10-04 20:29:09 -0700281 FlowEntry fe1 = new DefaultFlowEntry(f1);
282 FlowEntry fe2 = new DefaultFlowEntry(f2);
283
284
285 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
286 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
287
288 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700289
290 assertTrue("Entries should be added.",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700291 validateState(ImmutableMap.of(
292 f1, FlowEntryState.ADDED,
293 f2, FlowEntryState.ADDED,
294 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700295
alshabib3d643ec2014-10-22 18:33:00 -0700296 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
297 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700298 }
299
300 @Test
301 public void extraneousFlow() {
302 FlowRule f1 = flowRule(1, 1);
303 FlowRule f2 = flowRule(2, 2);
304 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700305 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700306
alshabib1c319ff2014-10-04 20:29:09 -0700307// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
308// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
309// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
310 FlowEntry fe1 = new DefaultFlowEntry(f1);
311 FlowEntry fe2 = new DefaultFlowEntry(f2);
312 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700313
alshabib1c319ff2014-10-04 20:29:09 -0700314
315 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700316
alshabib3d643ec2014-10-22 18:33:00 -0700317 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700318
319 }
320
321 /*
322 * Tests whether a rule that was marked for removal but no flowRemoved was received
323 * is indeed removed at the next stats update.
324 */
325 @Test
326 public void flowMissingRemove() {
327 FlowRule f1 = flowRule(1, 1);
328 FlowRule f2 = flowRule(2, 2);
329 FlowRule f3 = flowRule(3, 3);
330
alshabib1c319ff2014-10-04 20:29:09 -0700331// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
332// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
333
334 FlowEntry fe1 = new DefaultFlowEntry(f1);
335 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700336 mgr.applyFlowRules(f1, f2, f3);
337
338 mgr.removeFlowRules(f3);
339
alshabib1c319ff2014-10-04 20:29:09 -0700340 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700341
alshabib3d643ec2014-10-22 18:33:00 -0700342 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
343 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700344
345 }
346
347 @Test
348 public void getByAppId() {
349 FlowRule f1 = flowRule(1, 1);
350 FlowRule f2 = flowRule(2, 2);
351 mgr.applyFlowRules(f1, f2);
352
353 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700354 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700355 }
356
357 @Test
358 public void removeByAppId() {
359 FlowRule f1 = flowRule(1, 1);
360 FlowRule f2 = flowRule(2, 2);
361 mgr.applyFlowRules(f1, f2);
362
363
364 mgr.removeFlowRulesById(appId);
365
366 //only check that we are in pending remove. Events and actual remove state will
367 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700368 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700369 f1, FlowEntryState.PENDING_REMOVE,
370 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700371 }
372
alshabibcf369912014-10-13 14:16:42 -0700373 @Test
374 public void applyBatch() {
375 FlowRule f1 = flowRule(1, 1);
376 FlowRule f2 = flowRule(2, 2);
377
378
379 mgr.applyFlowRules(f1);
380
381 FlowEntry fe1 = new DefaultFlowEntry(f1);
382 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
383
384 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
385 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
386
387 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
388 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
389
390 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
391 Lists.newArrayList(fbe1, fbe2));
392 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
393 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700394 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700395 f1, FlowEntryState.PENDING_REMOVE,
396 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700397 CompletedBatchOperation completed = null;
398 try {
399 completed = future.get();
400 } catch (InterruptedException | ExecutionException e) {
401 fail("Unexpected exception: " + e);
402 }
403 if (!completed.isSuccess()) {
404 fail("Installation should be a success");
405 }
406
407 }
408
409 @Test
410 public void cancelBatch() {
411 FlowRule f1 = flowRule(1, 1);
412 FlowRule f2 = flowRule(2, 2);
413
414
415 mgr.applyFlowRules(f1);
416
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700417 assertTrue("Entries in wrong state",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700418 validateState(ImmutableMap.of(
419 f1, FlowEntryState.PENDING_ADD)));
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700420
alshabibcf369912014-10-13 14:16:42 -0700421 FlowEntry fe1 = new DefaultFlowEntry(f1);
422 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
423
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700424 assertTrue("Entries in wrong state",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700425 validateState(ImmutableMap.of(
426 f1, FlowEntryState.ADDED)));
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700427
428
alshabibcf369912014-10-13 14:16:42 -0700429 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
430 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
431
432 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
433 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
434
435 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
436 Lists.newArrayList(fbe1, fbe2));
437 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
438
439 future.cancel(true);
440
441 assertTrue(flowCount() == 2);
442
443 /*
444 * Rule f1 should be re-added to the list and therefore be in a pending add
445 * state.
446 */
447 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700448 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700449 f2, FlowEntryState.PENDING_REMOVE,
450 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700451
452
alshabibcf369912014-10-13 14:16:42 -0700453 }
454
455
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700456 private static class TestListener implements FlowRuleListener {
457 final List<FlowRuleEvent> events = new ArrayList<>();
458
459 @Override
460 public void event(FlowRuleEvent event) {
461 events.add(event);
462 }
463 }
464
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800465 private static class TestDeviceService extends DeviceServiceAdapter {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700466
467 @Override
468 public int getDeviceCount() {
Madan Jampani6a456162014-10-24 11:36:17 -0700469 return 1;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700470 }
471
472 @Override
473 public Iterable<Device> getDevices() {
Madan Jampani6a456162014-10-24 11:36:17 -0700474 return Arrays.asList(DEV);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700475 }
476
477 @Override
478 public Device getDevice(DeviceId deviceId) {
479 return DEV;
480 }
481
482 @Override
483 public MastershipRole getRole(DeviceId deviceId) {
484 return null;
485 }
486
487 @Override
488 public List<Port> getPorts(DeviceId deviceId) {
489 return null;
490 }
491
492 @Override
493 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
494 return null;
495 }
496
497 @Override
498 public boolean isAvailable(DeviceId deviceId) {
499 return false;
500 }
501
502 @Override
503 public void addListener(DeviceListener listener) {
504 }
505
506 @Override
507 public void removeListener(DeviceListener listener) {
508 }
509
510 }
511
512 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
513
514 protected TestProvider(ProviderId id) {
515 super(PID);
516 }
517
518 @Override
519 public void applyFlowRule(FlowRule... flowRules) {
520 }
521
522 @Override
523 public void removeFlowRule(FlowRule... flowRules) {
524 }
525
alshabiba68eb962014-09-24 20:34:13 -0700526 @Override
527 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
528 }
529
alshabib902d41b2014-10-07 16:52:05 -0700530 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700531 public ListenableFuture<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700532 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700533 return new TestInstallationFuture();
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 {
Yuta HIGUCHI4b524442014-10-28 22:23:57 -0700557 return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet());
alshabibcf369912014-10-13 14:16:42 -0700558 }
559
560 @Override
561 public CompletedBatchOperation get(long timeout, TimeUnit unit)
562 throws InterruptedException,
563 ExecutionException, TimeoutException {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800564 return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet());
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() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700588 return null;
589 }
590
591 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700592 public Criterion getCriterion(
593 org.onlab.onos.net.flow.criteria.Criterion.Type type) {
594 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
622 public List<Instruction> instructions() {
623 return null;
624 }
625
626 @Override
627 public int hashCode() {
628 return testval;
629 }
630
631 @Override
632 public boolean equals(Object o) {
633 if (o instanceof TestTreatment) {
634 return this.testval == ((TestTreatment) o).testval;
635 }
636 return false;
637 }
638
639 }
640
alshabib92c65ad2014-10-08 21:56:05 -0700641 public class TestApplicationId extends DefaultApplicationId {
642
643 public TestApplicationId(short id, String name) {
644 super(id, name);
645 }
646 }
647
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700648}